Form conversion and workflow
Schema value conversion
Section titled “Schema value conversion”import { castValuesBySchema } from '@alneas/data-engine/schema/cast';const values = castValuesBySchema({ quantity: '12', optional: '' }, { type: 'object', properties: { quantity: { type: 'integer' }, optional: { type: ['number', 'null'] }, },}, { numericMode: 'strict' }); // { quantity: 12, optional: null }Conversion is separate from JSON Schema validation. Validate the result with AJV
before storing it. Neither mode enforces required, minimum/maximum, enum, formats,
additionalProperties or other schema constraints. It does not resolve $ref, choose
anyOf/oneOf/allOf branches, insert defaults, convert boolean strings, or parse dates.
Only own declared object properties, array prefixItems and remaining items are walked.
Unknown properties and mismatched object/array inputs survive for validation. Inputs
are not mutated. Existing null/undefined values remain unchanged.
The default numericMode: 'legacy' preserves existing form behavior: parseInt for
integer (including integer/number unions), parseFloat for number. Thus 12suffix
becomes 12, integer 1.9 becomes 1, integer 1e3 becomes 1, and number Infinity
becomes Infinity. This mode is input convenience, not a numeric safety boundary.
Prefer explicit strict mode for new consumers: it accepts an entire finite JSON
number, supports exponents, rejects hexadecimal/leading zeros/trailing characters,
and retains values failing Number.isInteger for integer inputs as strings. Results
use JavaScript Number (IEEE 754); large integers and decimals can lose precision,
including before the integer check. Keep exact financial/large-integer values as
strings and use a separate decimal representation. In either mode whitespace-only
numeric strings become null when the numeric type includes null, otherwise undefined.
Unconvertible strings remain unchanged. Object/array/string unions follow the same
object/array-first traversal, not branch validation. Depth over 64 or more than
10,000 visited values throws, including cyclic input/schema combinations.
Workflow metadata
Section titled “Workflow metadata”import { WorkflowEngine, WorkflowPolicyEngine } from '@alneas/data-engine/workflow';const flow = new WorkflowEngine({ id: 'review', label: 'Review', statusOrder: ['draft', 'done'], transitions: [{ from: 'draft', to: 'done' }], statusInfo: {}, defaultStatusInfo: { title: 'Unknown' } });flow.getTransitions('draft');flow.getProgress('draft'); // 50: position-based, first known status is 1/Nconst policy = new WorkflowPolicyEngine<{ authorized: boolean }>({ validateTransition: context => ({ allowed: context.authorized }), requiresApproval: context => !context.authorized, getRequiredFields: () => [],});WorkflowEngine filters configured transitions/actions and reads labels/status info. Unknown status progress is 0; absent or falsy status information uses defaultStatusInfo, including prototype-named keys. Configuration and returned entries retain their references. It does not write state, persist transitions, enforce approvals/required fields, or authenticate/authorize users. Applications enforce these on the server. Generic transition/action types contain no ReactNode, icons, colours or components; consumers can add presentation metadata through the generic types.
WorkflowPolicyEngine requires all three callbacks explicitly. No purchase document, 10,000 threshold or PAID/RECEIVED/INVOICED convention is built in. Before first public release, react-tools changes its former static policy API to this configured instance API. Private UI retains the former static purchase policy in private app-core. Public and private WorkflowEngine use the same constructor specialized with UI types.
Other optional utilities
Section titled “Other optional utilities”@alneas/data-engine/async provides withTimeout(promise, milliseconds = 30000,
errorFactory?). Timers are cleared on success, failure and timeout. Milliseconds
must be finite and between 0 and 2147483647. A deadline does not cancel underlying
work; supply AbortSignal handling to that work separately. Private error/display
handling remains in the React consumer.
@alneas/data-engine/google-calendar/watch provides setupWatchChannel. It POSTs
calendarId/webhookUrl to the application’s functionUrl with the supplied bearer
token and returns channelId/resourceId/expiration. The application owns endpoint
validation, authorization, watch renewal, webhook verification and deployment.
Neither helper needs React or another ALNEAS peer.
Granular compatibility subpaths now expose existing canonical schema, Excel,
Calendar, notification and graph integration modules. Graph DB/HTTP and agent
entries still require their documented optional peers. /server/contained-path
is Node-only (its declarations are self-contained); use it only with a trusted,
application-owned filesystem root. It does not make arbitrary file access safe.