@onereach/state-machine-runtime 1.0.0-framework.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @onereach/state-machine-runtime
2
+
3
+ This package defines runtime logic for running state machine.
@@ -0,0 +1,68 @@
1
+ import { CompiledFunctionValidators, CompiledStateTemplateValidators, SchemaValidator, StateMachineFunctionDefinition, StateTemplateDefinition } from "@onereach/state-machine-core";
2
+ //#region src/runtime/types.d.ts
3
+ interface RuntimeOptions<TContext> {
4
+ /**
5
+ * Turns declarative capabilities into an actual restricted
6
+ * context.
7
+ */
8
+ scopeContext?: (context: TContext, capabilities: readonly string[], definition: StateMachineFunctionDefinition) => TContext | Promise<TContext>;
9
+ }
10
+ interface PreparedTemplateInput {
11
+ definition: StateTemplateDefinition;
12
+ validators: CompiledStateTemplateValidators;
13
+ }
14
+ //#endregion
15
+ //#region src/types/results.d.ts
16
+ interface QueryExecutionResult<TOutput = unknown> {
17
+ kind: 'query';
18
+ output: TOutput;
19
+ }
20
+ interface MutationExecutionResult<TState extends object = Record<string, unknown>, TOutput = unknown> {
21
+ kind: 'mutation';
22
+ output: TOutput;
23
+ /**
24
+ * Candidate next state.
25
+ */
26
+ state: TState;
27
+ }
28
+ type ExecutionResult<TState extends object = Record<string, unknown>, TOutput = unknown> = QueryExecutionResult<TOutput> | MutationExecutionResult<TState, TOutput>;
29
+ //#endregion
30
+ //#region src/prepared-runtime/types.d.ts
31
+ type RuntimeImplementation<TContext> = (input: Record<string, unknown>, state: Record<string, unknown>, context: TContext) => Promise<unknown>;
32
+ interface PreparedFunction<TContext> {
33
+ definition: StateMachineFunctionDefinition;
34
+ implementation: RuntimeImplementation<TContext>;
35
+ validators: CompiledFunctionValidators;
36
+ }
37
+ //#endregion
38
+ //#region src/prepared-runtime/prepared-runtime.d.ts
39
+ declare class PreparedStateTemplate<TContext> {
40
+ private readonly functions;
41
+ private readonly stateValidator;
42
+ private readonly scopeContext?;
43
+ readonly definition: StateTemplateDefinition;
44
+ constructor(definition: StateTemplateDefinition, functions: ReadonlyMap<string, PreparedFunction<TContext>>, stateValidator: SchemaValidator<Record<string, unknown>>, scopeContext?: RuntimeOptions<TContext>['scopeContext']);
45
+ getFunction(name: string): StateMachineFunctionDefinition | undefined;
46
+ execute<TState extends object>(name: string, input: unknown, currentState: TState, context: TContext): Promise<ExecutionResult<TState>>;
47
+ }
48
+ //#endregion
49
+ //#region src/runtime/runtime.d.ts
50
+ declare class StateMachineRuntime<TContext> {
51
+ private readonly options;
52
+ constructor(options?: RuntimeOptions<TContext>);
53
+ prepare(template: PreparedTemplateInput): PreparedStateTemplate<TContext>;
54
+ }
55
+ //#endregion
56
+ //#region src/errors.d.ts
57
+ declare class UnknownFunctionError extends Error {
58
+ readonly functionName: string;
59
+ constructor(functionName: string);
60
+ }
61
+ declare class FunctionTimeoutError extends Error {
62
+ readonly functionName: string;
63
+ readonly timeoutMs: number;
64
+ constructor(functionName: string, timeoutMs: number);
65
+ }
66
+ //#endregion
67
+ export { type ExecutionResult, FunctionTimeoutError, type MutationExecutionResult, type PreparedFunction, PreparedStateTemplate, type QueryExecutionResult, type RuntimeImplementation, StateMachineRuntime, UnknownFunctionError };
68
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/runtime/types.ts","../src/types/results.ts","../src/prepared-runtime/types.ts","../src/prepared-runtime/prepared-runtime.ts","../src/runtime/runtime.ts","../src/errors.ts"],"mappings":";;UAMiB,eAAe;;;;;EAK9B,gBACE,SAAS,UAET,iCAEA,YAAY,mCACT,WAAW,QAAQ;;UAGT;EACf,YAAY;EACZ,YAAY;;;;UCtBG,qBAAqB;EACpC;EACA,QAAQ;;UAGO,wBAAwB,wBAAwB,yBAAyB;EACxF;EACA,QAAQ;;;;EAKR,OAAO;;KAGG,gBAAgB,wBAAwB,yBAAyB,qBAC3E,qBAAqB,WAAW,wBAAwB,QAAQ;;;KCdtD,sBAAsB,aAChC,OAAO,yBACP,OAAO,yBACP,SAAS,aACN;UAEY,iBAAiB;EAChC,YAAY;EAEZ,gBAAgB,sBAAsB;EAEtC,YAAY;;;;cCCD,sBAAsB;mBAChB;mBACA;mBACA;WAED,YAAY;EAG1B,YAAA,YAAY,yBACZ,WAAW,oBAAoB,iBAAiB,YAChD,gBAAgB,gBAAgB,0BAChC,eAAe,eAAe;EAQzB,YAAY,eAAe;EAIrB,QAAQ,uBACnB,cACA,gBACA,cAAc,QACd,SAAS,WACR,QAAQ,gBAAgB;;;;cCpChB,oBAAoB;mBACd;EAEL,YAAA,UAAS,eAAe;EAI7B,QAAQ,UAAU,wBAAwB,sBAAsB;;;;cCb5D,6BAA6B;WACxB;EAEJ,YAAA;;cAQD,6BAA6B;WACxB;WACA;EAEJ,YAAA,sBAAsB"}
package/dist/index.mjs ADDED
@@ -0,0 +1,12 @@
1
+ import{assertSchema as e}from"@onereach/state-machine-core";var t=class extends Error{functionName;constructor(e){super(`Unknown state-machine function: ${e}`),this.name=`UnknownFunctionError`,this.functionName=e}},n=class extends Error{functionName;timeoutMs;constructor(e,t){super(`Function "${e}" exceeded ${t}ms`),this.name=`FunctionTimeoutError`,this.functionName=e,this.timeoutMs=t}};function r(e,t=new WeakSet){if(typeof e!=`object`||!e)return e;let n=e;if(t.has(n))return e;t.add(n);for(let n of Object.values(e))r(n,t);return Object.freeze(e)}async function i(e,t,r){let i;try{return await Promise.race([e,new Promise((e,a)=>{i=setTimeout(()=>a(new n(t,r)),r)})])}finally{i&&clearTimeout(i)}}var a=class{functions;stateValidator;scopeContext;definition;constructor(e,t,n,r){this.definition=e,this.functions=t,this.stateValidator=n,this.scopeContext=r}getFunction(e){return this.functions.get(e)?.definition}async execute(n,a,o,s){let c=this.functions.get(n);if(!c)throw new t(n);e(c.validators.input,a,`input`),e(this.stateValidator,o,`state-before`);let l=structuredClone(o),u=c.definition.kind===`query`?r(l):l,d=structuredClone(a),f=c.definition.implementation.capabilities,p=this.scopeContext?await this.scopeContext(s,f,c.definition):s,m=c.implementation(d,u,p),h=c.definition.implementation.timeoutMs,g=h===void 0?await m:await i(m,c.definition.name,h);return c.validators.output&&e(c.validators.output,g,`output`),c.definition.kind===`query`?{kind:`query`,output:g}:(e(this.stateValidator,u,`state-after`),{kind:`mutation`,output:g,state:u})}};function o(e,t){let n=t.implementation;if(n.runtime!==`javascript`||n.abi!==`state-machine-function-v1`||n.format!==`async-function-body`)throw Error(`Unsupported implementation: ${t.name}`);let r=`state-machine://${encodeURIComponent(e)}/${encodeURIComponent(t.name)}`;try{return Function(`
2
+ "use strict";
3
+
4
+ return async function(input, state, ctx) {
5
+ "use strict";
6
+
7
+ ${n.code}
8
+ };
9
+
10
+ //# sourceURL=${r}
11
+ `)()}catch(e){throw Error(`Failed to compile function "${t.name}"`,{cause:e})}}var s=class{options;constructor(e={}){this.options=e}prepare(e){let t=new Map;for(let n of e.definition.functions){let r=e.validators.functions.get(n.name);if(!r)throw Error(`Missing compiled validators for function "${n.name}"`);t.set(n.name,{definition:n,validators:r,implementation:o(e.definition.id,n)})}return new a(e.definition,t,e.validators.state,this.options.scopeContext)}};export{n as FunctionTimeoutError,a as PreparedStateTemplate,s as StateMachineRuntime,t as UnknownFunctionError};
12
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/errors.ts","../src/helpers.ts","../src/prepared-runtime/prepared-runtime.ts","../src/runtime/compilation.ts","../src/runtime/runtime.ts"],"sourcesContent":["export class UnknownFunctionError extends Error {\n public readonly functionName: string;\n\n constructor(functionName: string) {\n super(`Unknown state-machine function: ${functionName}`);\n\n this.name = 'UnknownFunctionError';\n this.functionName = functionName;\n }\n}\n\nexport class FunctionTimeoutError extends Error {\n public readonly functionName: string;\n public readonly timeoutMs: number;\n\n constructor(functionName: string, timeoutMs: number) {\n super(`Function \"${functionName}\" exceeded ${timeoutMs}ms`);\n\n this.name = 'FunctionTimeoutError';\n this.functionName = functionName;\n this.timeoutMs = timeoutMs;\n }\n}\n","import { FunctionTimeoutError } from './errors.ts';\n\nexport function deepFreeze<T>(value: T, seen = new WeakSet<object>()): T {\n if (value === null || typeof value !== 'object') {\n return value;\n }\n\n const object = value as object;\n\n if (seen.has(object)) {\n return value;\n }\n\n seen.add(object);\n\n for (const child of Object.values(value as Record<string, unknown>)) {\n deepFreeze(child, seen);\n }\n\n return Object.freeze(value);\n}\n\nexport async function withTimeout<T>(promise: Promise<T>, name: string, timeoutMs: number): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n\n try {\n return await Promise.race([\n promise,\n\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new FunctionTimeoutError(name, timeoutMs)), timeoutMs);\n }),\n ]);\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n","import { assertSchema } from '@onereach/state-machine-core';\nimport type {\n SchemaValidator,\n StateMachineFunctionDefinition,\n StateTemplateDefinition,\n} from '@onereach/state-machine-core';\n\nimport { UnknownFunctionError } from '../errors.ts';\nimport { deepFreeze, withTimeout } from '../helpers.ts';\nimport type { RuntimeOptions } from '../runtime/types.ts';\nimport type { ExecutionResult } from '../types/results.ts';\n\nimport type { PreparedFunction } from './types.ts';\n\nexport class PreparedStateTemplate<TContext> {\n private readonly functions: ReadonlyMap<string, PreparedFunction<TContext>>;\n private readonly stateValidator: SchemaValidator<Record<string, unknown>>;\n private readonly scopeContext?: RuntimeOptions<TContext>['scopeContext'];\n\n public readonly definition: StateTemplateDefinition;\n\n constructor(\n definition: StateTemplateDefinition,\n functions: ReadonlyMap<string, PreparedFunction<TContext>>,\n stateValidator: SchemaValidator<Record<string, unknown>>,\n scopeContext?: RuntimeOptions<TContext>['scopeContext'],\n ) {\n this.definition = definition;\n this.functions = functions;\n this.stateValidator = stateValidator;\n this.scopeContext = scopeContext;\n }\n\n public getFunction(name: string): StateMachineFunctionDefinition | undefined {\n return this.functions.get(name)?.definition;\n }\n\n public async execute<TState extends object>(\n name: string,\n input: unknown,\n currentState: TState,\n context: TContext,\n ): Promise<ExecutionResult<TState>> {\n const function_ = this.functions.get(name);\n\n if (!function_) throw new UnknownFunctionError(name);\n\n assertSchema(function_.validators.input, input, 'input');\n assertSchema(this.stateValidator, currentState, 'state-before');\n\n /**\n * Implementation never receives the real state.\n */\n const clonedState = structuredClone(currentState);\n\n /**\n * query:\n *\n * cloned + deeply frozen\n *\n * mutation:\n *\n * cloned + mutable\n */\n const executionState = function_.definition.kind === 'query' ? deepFreeze(clonedState) : clonedState;\n const executionInput = structuredClone(input);\n const capabilities = function_.definition.implementation.capabilities;\n const functionContext = this.scopeContext\n ? await this.scopeContext(context, capabilities, function_.definition)\n : context;\n const execution = function_.implementation(executionInput, executionState, functionContext);\n\n const timeoutMs = function_.definition.implementation.timeoutMs;\n\n const output =\n timeoutMs === undefined ? await execution : await withTimeout(execution, function_.definition.name, timeoutMs);\n\n if (function_.validators.output) assertSchema(function_.validators.output, output, 'output');\n if (function_.definition.kind === 'query') {\n /**\n * No state property at all.\n */\n return {\n kind: 'query',\n output,\n };\n }\n\n assertSchema(this.stateValidator, executionState, 'state-after');\n\n return {\n kind: 'mutation',\n output,\n state: executionState,\n };\n }\n}\n","import type { StateMachineFunctionDefinition } from '@onereach/state-machine-core';\n\nimport type { RuntimeImplementation } from '../prepared-runtime/types.ts';\n\nexport function compileImplementation<TContext>(\n templateId: string,\n function_: StateMachineFunctionDefinition,\n): RuntimeImplementation<TContext> {\n const implementation = function_.implementation;\n\n if (\n implementation.runtime !== 'javascript' ||\n implementation.abi !== 'state-machine-function-v1' ||\n implementation.format !== 'async-function-body'\n ) {\n throw new Error(`Unsupported implementation: ${function_.name}`);\n }\n\n const sourceUrl = `state-machine://${encodeURIComponent(templateId)}/${encodeURIComponent(function_.name)}`;\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const factory = new Function(`\n \"use strict\";\n\n return async function(input, state, ctx) {\n \"use strict\";\n\n ${implementation.code}\n };\n\n //# sourceURL=${sourceUrl}\n `);\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n return factory() as RuntimeImplementation<TContext>;\n } catch (error) {\n throw new Error(`Failed to compile function \"${function_.name}\"`, { cause: error });\n }\n}\n","import { PreparedStateTemplate } from '../prepared-runtime/prepared-runtime.ts';\nimport type { PreparedFunction } from '../prepared-runtime/types.ts';\n\nimport { compileImplementation } from './compilation.ts';\nimport type { PreparedTemplateInput, RuntimeOptions } from './types.ts';\n\nexport class StateMachineRuntime<TContext> {\n private readonly options: RuntimeOptions<TContext>;\n\n constructor(options: RuntimeOptions<TContext> = {}) {\n this.options = options;\n }\n\n public prepare(template: PreparedTemplateInput): PreparedStateTemplate<TContext> {\n const functions = new Map<string, PreparedFunction<TContext>>();\n\n for (const function_ of template.definition.functions) {\n const validators = template.validators.functions.get(function_.name);\n\n if (!validators) throw new Error(`Missing compiled validators for function \"${function_.name}\"`);\n\n functions.set(function_.name, {\n definition: function_,\n validators,\n implementation: compileImplementation<TContext>(template.definition.id, function_),\n });\n }\n\n return new PreparedStateTemplate(\n template.definition,\n functions,\n template.validators.state,\n this.options.scopeContext,\n );\n }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@onereach/state-machine-runtime",
3
+ "version": "1.0.0-framework.2",
4
+ "description": "State Machine runtime implementation",
5
+ "keywords": [
6
+ "onereach",
7
+ "toolkit",
8
+ "state-machine"
9
+ ],
10
+ "author": "OneReach Development Team <dev.team@onereach.ai>",
11
+ "license": "Apache-2.0",
12
+ "type": "module",
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "!dist/metafile*.json"
19
+ ],
20
+ "devDependencies": {
21
+ "@arethetypeswrong/core": "^0.18.5",
22
+ "@types/source-map-support": "^0.5.10",
23
+ "publint": "^0.3.24",
24
+ "rollup-plugin-visualizer": "^7.1.1",
25
+ "tsdown": "^0.22.14",
26
+ "typescript": "^6.0.3"
27
+ },
28
+ "dependencies": {
29
+ "@onereach/state-machine-core": "1.0.0-framework.2"
30
+ },
31
+ "exports": {
32
+ ".": "./dist/index.mjs",
33
+ "./package.json": "./package.json"
34
+ },
35
+ "scripts": {
36
+ "build": "tsdown --config tsdown.config.mts",
37
+ "build:visualize": "VISUALIZE=1 pnpm build",
38
+ "preversion_": "pnpm build && pnpm test",
39
+ "publish:rc": "pnpm version prerelease --preid rc && pnpm publish --tag rc",
40
+ "test": "pnpm run unit",
41
+ "unit": "vitest run",
42
+ "preversion": "pnpm build"
43
+ }
44
+ }