@unlaxer/tramli 3.5.1 → 3.6.0

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.
@@ -11,6 +11,7 @@ export declare class FlowDefinition<S extends string> {
11
11
  readonly initialState: S | null;
12
12
  readonly terminalStates: Set<S>;
13
13
  readonly dataFlowGraph: DataFlowGraph<S> | null;
14
+ readonly strictMode: boolean;
14
15
  readonly warnings: string[];
15
16
  readonly exceptionRoutes: Map<S, Array<{
16
17
  errorClass: new (...args: any[]) => Error;
@@ -47,6 +48,7 @@ export declare class Builder<S extends string> {
47
48
  private readonly initiallyAvailableKeys;
48
49
  private readonly externallyProvidedKeys;
49
50
  private _perpetual;
51
+ private _strictMode;
50
52
  constructor(name: string, stateConfig: Record<S, StateConfig>);
51
53
  initiallyAvailable(...keys: FlowKey<unknown>[]): this;
52
54
  /** Declare data keys injected via resumeAndExecute(externalData), not available at start. */
@@ -64,6 +66,8 @@ export declare class Builder<S extends string> {
64
66
  onStateExit(state: S, action: (ctx: import('./flow-context.js').FlowContext) => void): this;
65
67
  /** Allow perpetual flows (no terminal states). Skips path-to-terminal validation. */
66
68
  allowPerpetual(): this;
69
+ /** Declare that this flow should run in strict mode (produces verification). */
70
+ strictMode(): this;
67
71
  /** @internal */
68
72
  addTransition(t: Transition<S>): void;
69
73
  build(): FlowDefinition<S>;
@@ -13,6 +13,7 @@ class FlowDefinition {
13
13
  initialState;
14
14
  terminalStates;
15
15
  dataFlowGraph;
16
+ strictMode;
16
17
  warnings;
17
18
  exceptionRoutes;
18
19
  enterActions;
@@ -115,6 +116,7 @@ class Builder {
115
116
  initiallyAvailableKeys = [];
116
117
  externallyProvidedKeys = [];
117
118
  _perpetual = false;
119
+ _strictMode = false;
118
120
  constructor(name, stateConfig) {
119
121
  this.name = name;
120
122
  this.stateConfig = stateConfig;
@@ -165,6 +167,8 @@ class Builder {
165
167
  }
166
168
  /** Allow perpetual flows (no terminal states). Skips path-to-terminal validation. */
167
169
  allowPerpetual() { this._perpetual = true; return this; }
170
+ /** Declare that this flow should run in strict mode (produces verification). */
171
+ strictMode() { this._strictMode = true; return this; }
168
172
  /** @internal */
169
173
  addTransition(t) { this.transitions.push(t); }
170
174
  build() {
@@ -201,6 +205,7 @@ class Builder {
201
205
  warnings.push(`Perpetual flow '${this.name}' has External transitions — ensure events are always delivered to avoid deadlock (liveness risk)`);
202
206
  }
203
207
  result.warnings = warnings;
208
+ result.strictMode = this._strictMode;
204
209
  result.exceptionRoutes = new Map(this._exceptionRoutes);
205
210
  result.enterActions = new Map(this._enterActions);
206
211
  result.exitActions = new Map(this._exitActions);
@@ -188,7 +188,7 @@ class FlowEngine {
188
188
  if (autoOrBranch.type === 'auto') {
189
189
  if (autoOrBranch.processor) {
190
190
  await autoOrBranch.processor.process(flow.context);
191
- this.verifyProduces(autoOrBranch.processor, flow.context);
191
+ this.verifyProduces(autoOrBranch.processor, flow.context, flow.definition.strictMode);
192
192
  }
193
193
  const from = flow.currentState;
194
194
  this.fireExit(flow, from);
@@ -318,8 +318,8 @@ class FlowEngine {
318
318
  this.store.save(parentFlow);
319
319
  return parentFlow;
320
320
  }
321
- verifyProduces(processor, ctx) {
322
- if (!this.strictMode)
321
+ verifyProduces(processor, ctx, defStrictMode) {
322
+ if (!this.strictMode && !defStrictMode)
323
323
  return;
324
324
  for (const prod of processor.produces) {
325
325
  if (!ctx.has(prod)) {
@@ -11,6 +11,7 @@ export declare class FlowDefinition<S extends string> {
11
11
  readonly initialState: S | null;
12
12
  readonly terminalStates: Set<S>;
13
13
  readonly dataFlowGraph: DataFlowGraph<S> | null;
14
+ readonly strictMode: boolean;
14
15
  readonly warnings: string[];
15
16
  readonly exceptionRoutes: Map<S, Array<{
16
17
  errorClass: new (...args: any[]) => Error;
@@ -47,6 +48,7 @@ export declare class Builder<S extends string> {
47
48
  private readonly initiallyAvailableKeys;
48
49
  private readonly externallyProvidedKeys;
49
50
  private _perpetual;
51
+ private _strictMode;
50
52
  constructor(name: string, stateConfig: Record<S, StateConfig>);
51
53
  initiallyAvailable(...keys: FlowKey<unknown>[]): this;
52
54
  /** Declare data keys injected via resumeAndExecute(externalData), not available at start. */
@@ -64,6 +66,8 @@ export declare class Builder<S extends string> {
64
66
  onStateExit(state: S, action: (ctx: import('./flow-context.js').FlowContext) => void): this;
65
67
  /** Allow perpetual flows (no terminal states). Skips path-to-terminal validation. */
66
68
  allowPerpetual(): this;
69
+ /** Declare that this flow should run in strict mode (produces verification). */
70
+ strictMode(): this;
67
71
  /** @internal */
68
72
  addTransition(t: Transition<S>): void;
69
73
  build(): FlowDefinition<S>;
@@ -10,6 +10,7 @@ export class FlowDefinition {
10
10
  initialState;
11
11
  terminalStates;
12
12
  dataFlowGraph;
13
+ strictMode;
13
14
  warnings;
14
15
  exceptionRoutes;
15
16
  enterActions;
@@ -111,6 +112,7 @@ export class Builder {
111
112
  initiallyAvailableKeys = [];
112
113
  externallyProvidedKeys = [];
113
114
  _perpetual = false;
115
+ _strictMode = false;
114
116
  constructor(name, stateConfig) {
115
117
  this.name = name;
116
118
  this.stateConfig = stateConfig;
@@ -161,6 +163,8 @@ export class Builder {
161
163
  }
162
164
  /** Allow perpetual flows (no terminal states). Skips path-to-terminal validation. */
163
165
  allowPerpetual() { this._perpetual = true; return this; }
166
+ /** Declare that this flow should run in strict mode (produces verification). */
167
+ strictMode() { this._strictMode = true; return this; }
164
168
  /** @internal */
165
169
  addTransition(t) { this.transitions.push(t); }
166
170
  build() {
@@ -197,6 +201,7 @@ export class Builder {
197
201
  warnings.push(`Perpetual flow '${this.name}' has External transitions — ensure events are always delivered to avoid deadlock (liveness risk)`);
198
202
  }
199
203
  result.warnings = warnings;
204
+ result.strictMode = this._strictMode;
200
205
  result.exceptionRoutes = new Map(this._exceptionRoutes);
201
206
  result.enterActions = new Map(this._enterActions);
202
207
  result.exitActions = new Map(this._exitActions);
@@ -185,7 +185,7 @@ export class FlowEngine {
185
185
  if (autoOrBranch.type === 'auto') {
186
186
  if (autoOrBranch.processor) {
187
187
  await autoOrBranch.processor.process(flow.context);
188
- this.verifyProduces(autoOrBranch.processor, flow.context);
188
+ this.verifyProduces(autoOrBranch.processor, flow.context, flow.definition.strictMode);
189
189
  }
190
190
  const from = flow.currentState;
191
191
  this.fireExit(flow, from);
@@ -315,8 +315,8 @@ export class FlowEngine {
315
315
  this.store.save(parentFlow);
316
316
  return parentFlow;
317
317
  }
318
- verifyProduces(processor, ctx) {
319
- if (!this.strictMode)
318
+ verifyProduces(processor, ctx, defStrictMode) {
319
+ if (!this.strictMode && !defStrictMode)
320
320
  return;
321
321
  for (const prod of processor.produces) {
322
322
  if (!ctx.has(prod)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unlaxer/tramli",
3
- "version": "3.5.1",
3
+ "version": "3.6.0",
4
4
  "description": "Constrained flow engine — state machines that prevent invalid transitions at build time",
5
5
  "type": "module",
6
6
  "exports": {