@unlaxer/tramli 3.3.0 → 3.4.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.
- package/dist/cjs/data-flow-graph.d.ts +1 -1
- package/dist/cjs/data-flow-graph.js +9 -4
- package/dist/cjs/flow-definition.d.ts +3 -0
- package/dist/cjs/flow-definition.js +13 -1
- package/dist/cjs/flow-engine.js +1 -1
- package/dist/cjs/types.d.ts +2 -0
- package/dist/esm/data-flow-graph.d.ts +1 -1
- package/dist/esm/data-flow-graph.js +9 -4
- package/dist/esm/flow-definition.d.ts +3 -0
- package/dist/esm/flow-definition.js +13 -1
- package/dist/esm/flow-engine.js +1 -1
- package/dist/esm/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -88,5 +88,5 @@ export declare class DataFlowGraph<S extends string> {
|
|
|
88
88
|
private static collectEdges;
|
|
89
89
|
/** Version compatibility: check if v1 instances can resume on v2 definition. */
|
|
90
90
|
static versionCompatibility<S extends string>(before: DataFlowGraph<S>, after: DataFlowGraph<S>): string[];
|
|
91
|
-
static build<S extends string>(def: FlowDefinition<S>, initiallyAvailable: string[]): DataFlowGraph<S>;
|
|
91
|
+
static build<S extends string>(def: FlowDefinition<S>, initiallyAvailable: string[], externallyProvided?: string[]): DataFlowGraph<S>;
|
|
92
92
|
}
|
|
@@ -370,14 +370,15 @@ class DataFlowGraph {
|
|
|
370
370
|
return issues;
|
|
371
371
|
}
|
|
372
372
|
// ─── Builder ─────────────────────────────────────────────
|
|
373
|
-
static build(def, initiallyAvailable) {
|
|
373
|
+
static build(def, initiallyAvailable, externallyProvided = []) {
|
|
374
374
|
const stateAvail = new Map();
|
|
375
375
|
const producers = new Map();
|
|
376
376
|
const consumers = new Map();
|
|
377
377
|
const allProduced = new Set(initiallyAvailable);
|
|
378
378
|
const allConsumed = new Set();
|
|
379
|
+
const extSet = new Set(externallyProvided);
|
|
379
380
|
if (def.initialState) {
|
|
380
|
-
traverse(def, def.initialState, new Set(initiallyAvailable), stateAvail, producers, consumers, allProduced, allConsumed);
|
|
381
|
+
traverse(def, def.initialState, new Set(initiallyAvailable), extSet, stateAvail, producers, consumers, allProduced, allConsumed);
|
|
381
382
|
// Mark initially available types as produced by "initial"
|
|
382
383
|
for (const key of initiallyAvailable) {
|
|
383
384
|
if (!producers.has(key))
|
|
@@ -391,7 +392,7 @@ class DataFlowGraph {
|
|
|
391
392
|
}
|
|
392
393
|
}
|
|
393
394
|
exports.DataFlowGraph = DataFlowGraph;
|
|
394
|
-
function traverse(def, state, available, stateAvail, producers, consumers, allProduced, allConsumed) {
|
|
395
|
+
function traverse(def, state, available, externallyProvided, stateAvail, producers, consumers, allProduced, allConsumed) {
|
|
395
396
|
if (stateAvail.has(state)) {
|
|
396
397
|
const existing = stateAvail.get(state);
|
|
397
398
|
let isSubset = true;
|
|
@@ -413,6 +414,10 @@ function traverse(def, state, available, stateAvail, producers, consumers, allPr
|
|
|
413
414
|
}
|
|
414
415
|
for (const t of def.transitionsFrom(state)) {
|
|
415
416
|
const newAvail = new Set(stateAvail.get(state));
|
|
417
|
+
if (t.type === 'external') {
|
|
418
|
+
for (const k of externallyProvided)
|
|
419
|
+
newAvail.add(k);
|
|
420
|
+
}
|
|
416
421
|
if (t.guard) {
|
|
417
422
|
for (const req of t.guard.requires) {
|
|
418
423
|
addTo(consumers, req, { name: t.guard.name, fromState: t.from, toState: t.to, kind: 'guard' });
|
|
@@ -441,7 +446,7 @@ function traverse(def, state, available, stateAvail, producers, consumers, allPr
|
|
|
441
446
|
newAvail.add(prod);
|
|
442
447
|
}
|
|
443
448
|
}
|
|
444
|
-
traverse(def, t.to, newAvail, stateAvail, producers, consumers, allProduced, allConsumed);
|
|
449
|
+
traverse(def, t.to, newAvail, externallyProvided, stateAvail, producers, consumers, allProduced, allConsumed);
|
|
445
450
|
}
|
|
446
451
|
}
|
|
447
452
|
function addTo(map, key, info) {
|
|
@@ -45,9 +45,12 @@ export declare class Builder<S extends string> {
|
|
|
45
45
|
private readonly _enterActions;
|
|
46
46
|
private readonly _exitActions;
|
|
47
47
|
private readonly initiallyAvailableKeys;
|
|
48
|
+
private readonly externallyProvidedKeys;
|
|
48
49
|
private _perpetual;
|
|
49
50
|
constructor(name: string, stateConfig: Record<S, StateConfig>);
|
|
50
51
|
initiallyAvailable(...keys: FlowKey<unknown>[]): this;
|
|
52
|
+
/** Declare data keys injected via resumeAndExecute(externalData), not available at start. */
|
|
53
|
+
externallyProvided(...keys: FlowKey<unknown>[]): this;
|
|
51
54
|
setTtl(ms: number): this;
|
|
52
55
|
setMaxGuardRetries(max: number): this;
|
|
53
56
|
from(state: S): FromBuilder<S>;
|
|
@@ -113,6 +113,7 @@ class Builder {
|
|
|
113
113
|
_enterActions = new Map();
|
|
114
114
|
_exitActions = new Map();
|
|
115
115
|
initiallyAvailableKeys = [];
|
|
116
|
+
externallyProvidedKeys = [];
|
|
116
117
|
_perpetual = false;
|
|
117
118
|
constructor(name, stateConfig) {
|
|
118
119
|
this.name = name;
|
|
@@ -123,6 +124,12 @@ class Builder {
|
|
|
123
124
|
this.initiallyAvailableKeys.push(k);
|
|
124
125
|
return this;
|
|
125
126
|
}
|
|
127
|
+
/** Declare data keys injected via resumeAndExecute(externalData), not available at start. */
|
|
128
|
+
externallyProvided(...keys) {
|
|
129
|
+
for (const k of keys)
|
|
130
|
+
this.externallyProvidedKeys.push(k);
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
126
133
|
setTtl(ms) { this.ttl = ms; return this; }
|
|
127
134
|
setMaxGuardRetries(max) { this.maxGuardRetries = max; return this; }
|
|
128
135
|
from(state) {
|
|
@@ -185,7 +192,7 @@ class Builder {
|
|
|
185
192
|
result.terminalStates = terminals;
|
|
186
193
|
result.dataFlowGraph = null;
|
|
187
194
|
this.validate(result);
|
|
188
|
-
result.dataFlowGraph = data_flow_graph_js_1.DataFlowGraph.build(result, this.initiallyAvailableKeys);
|
|
195
|
+
result.dataFlowGraph = data_flow_graph_js_1.DataFlowGraph.build(result, this.initiallyAvailableKeys, this.externallyProvidedKeys);
|
|
189
196
|
// Build warnings
|
|
190
197
|
const warnings = [];
|
|
191
198
|
const perpetual = terminals.size === 0;
|
|
@@ -354,6 +361,10 @@ class Builder {
|
|
|
354
361
|
}
|
|
355
362
|
for (const t of def.transitionsFrom(state)) {
|
|
356
363
|
const newAvailable = new Set(stateAvailable.get(state));
|
|
364
|
+
if (t.type === 'external') {
|
|
365
|
+
for (const k of this.externallyProvidedKeys)
|
|
366
|
+
newAvailable.add(k);
|
|
367
|
+
}
|
|
357
368
|
if (t.guard) {
|
|
358
369
|
for (const req of t.guard.requires) {
|
|
359
370
|
if (!newAvailable.has(req))
|
|
@@ -534,6 +545,7 @@ class BranchBuilder {
|
|
|
534
545
|
processor: this.processors.get(label),
|
|
535
546
|
guard: undefined, branch: this.branch,
|
|
536
547
|
branchTargets: new Map(this.targets),
|
|
548
|
+
branchLabel: label,
|
|
537
549
|
});
|
|
538
550
|
}
|
|
539
551
|
return this.builder;
|
package/dist/cjs/flow-engine.js
CHANGED
|
@@ -201,7 +201,7 @@ class FlowEngine {
|
|
|
201
201
|
if (!target) {
|
|
202
202
|
throw new flow_error_js_1.FlowError('UNKNOWN_BRANCH', `Branch '${branch.name}' returned unknown label: ${label}`);
|
|
203
203
|
}
|
|
204
|
-
const specific = transitions.find(t => t.type === 'branch' && t.to === target) ?? autoOrBranch;
|
|
204
|
+
const specific = transitions.find(t => t.type === 'branch' && t.branchLabel === label) ?? transitions.find(t => t.type === 'branch' && t.to === target) ?? autoOrBranch;
|
|
205
205
|
if (specific.processor)
|
|
206
206
|
await specific.processor.process(flow.context);
|
|
207
207
|
const from = flow.currentState;
|
package/dist/cjs/types.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface Transition<S extends string> {
|
|
|
26
26
|
guard?: TransitionGuard<S>;
|
|
27
27
|
branch?: BranchProcessor<S>;
|
|
28
28
|
branchTargets: Map<string, S>;
|
|
29
|
+
/** Label assigned by builder .to(target, label, processor). Used for branch label-specific processor matching. */
|
|
30
|
+
branchLabel?: string;
|
|
29
31
|
subFlowDefinition?: import('./flow-definition.js').FlowDefinition<any>;
|
|
30
32
|
exitMappings?: Map<string, S>;
|
|
31
33
|
/** Per-state timeout in milliseconds. If set, resumeAndExecute checks this before guard. */
|
|
@@ -88,5 +88,5 @@ export declare class DataFlowGraph<S extends string> {
|
|
|
88
88
|
private static collectEdges;
|
|
89
89
|
/** Version compatibility: check if v1 instances can resume on v2 definition. */
|
|
90
90
|
static versionCompatibility<S extends string>(before: DataFlowGraph<S>, after: DataFlowGraph<S>): string[];
|
|
91
|
-
static build<S extends string>(def: FlowDefinition<S>, initiallyAvailable: string[]): DataFlowGraph<S>;
|
|
91
|
+
static build<S extends string>(def: FlowDefinition<S>, initiallyAvailable: string[], externallyProvided?: string[]): DataFlowGraph<S>;
|
|
92
92
|
}
|
|
@@ -367,14 +367,15 @@ export class DataFlowGraph {
|
|
|
367
367
|
return issues;
|
|
368
368
|
}
|
|
369
369
|
// ─── Builder ─────────────────────────────────────────────
|
|
370
|
-
static build(def, initiallyAvailable) {
|
|
370
|
+
static build(def, initiallyAvailable, externallyProvided = []) {
|
|
371
371
|
const stateAvail = new Map();
|
|
372
372
|
const producers = new Map();
|
|
373
373
|
const consumers = new Map();
|
|
374
374
|
const allProduced = new Set(initiallyAvailable);
|
|
375
375
|
const allConsumed = new Set();
|
|
376
|
+
const extSet = new Set(externallyProvided);
|
|
376
377
|
if (def.initialState) {
|
|
377
|
-
traverse(def, def.initialState, new Set(initiallyAvailable), stateAvail, producers, consumers, allProduced, allConsumed);
|
|
378
|
+
traverse(def, def.initialState, new Set(initiallyAvailable), extSet, stateAvail, producers, consumers, allProduced, allConsumed);
|
|
378
379
|
// Mark initially available types as produced by "initial"
|
|
379
380
|
for (const key of initiallyAvailable) {
|
|
380
381
|
if (!producers.has(key))
|
|
@@ -387,7 +388,7 @@ export class DataFlowGraph {
|
|
|
387
388
|
return new DataFlowGraph(stateAvail, producers, consumers, allProduced, allConsumed);
|
|
388
389
|
}
|
|
389
390
|
}
|
|
390
|
-
function traverse(def, state, available, stateAvail, producers, consumers, allProduced, allConsumed) {
|
|
391
|
+
function traverse(def, state, available, externallyProvided, stateAvail, producers, consumers, allProduced, allConsumed) {
|
|
391
392
|
if (stateAvail.has(state)) {
|
|
392
393
|
const existing = stateAvail.get(state);
|
|
393
394
|
let isSubset = true;
|
|
@@ -409,6 +410,10 @@ function traverse(def, state, available, stateAvail, producers, consumers, allPr
|
|
|
409
410
|
}
|
|
410
411
|
for (const t of def.transitionsFrom(state)) {
|
|
411
412
|
const newAvail = new Set(stateAvail.get(state));
|
|
413
|
+
if (t.type === 'external') {
|
|
414
|
+
for (const k of externallyProvided)
|
|
415
|
+
newAvail.add(k);
|
|
416
|
+
}
|
|
412
417
|
if (t.guard) {
|
|
413
418
|
for (const req of t.guard.requires) {
|
|
414
419
|
addTo(consumers, req, { name: t.guard.name, fromState: t.from, toState: t.to, kind: 'guard' });
|
|
@@ -437,7 +442,7 @@ function traverse(def, state, available, stateAvail, producers, consumers, allPr
|
|
|
437
442
|
newAvail.add(prod);
|
|
438
443
|
}
|
|
439
444
|
}
|
|
440
|
-
traverse(def, t.to, newAvail, stateAvail, producers, consumers, allProduced, allConsumed);
|
|
445
|
+
traverse(def, t.to, newAvail, externallyProvided, stateAvail, producers, consumers, allProduced, allConsumed);
|
|
441
446
|
}
|
|
442
447
|
}
|
|
443
448
|
function addTo(map, key, info) {
|
|
@@ -45,9 +45,12 @@ export declare class Builder<S extends string> {
|
|
|
45
45
|
private readonly _enterActions;
|
|
46
46
|
private readonly _exitActions;
|
|
47
47
|
private readonly initiallyAvailableKeys;
|
|
48
|
+
private readonly externallyProvidedKeys;
|
|
48
49
|
private _perpetual;
|
|
49
50
|
constructor(name: string, stateConfig: Record<S, StateConfig>);
|
|
50
51
|
initiallyAvailable(...keys: FlowKey<unknown>[]): this;
|
|
52
|
+
/** Declare data keys injected via resumeAndExecute(externalData), not available at start. */
|
|
53
|
+
externallyProvided(...keys: FlowKey<unknown>[]): this;
|
|
51
54
|
setTtl(ms: number): this;
|
|
52
55
|
setMaxGuardRetries(max: number): this;
|
|
53
56
|
from(state: S): FromBuilder<S>;
|
|
@@ -109,6 +109,7 @@ export class Builder {
|
|
|
109
109
|
_enterActions = new Map();
|
|
110
110
|
_exitActions = new Map();
|
|
111
111
|
initiallyAvailableKeys = [];
|
|
112
|
+
externallyProvidedKeys = [];
|
|
112
113
|
_perpetual = false;
|
|
113
114
|
constructor(name, stateConfig) {
|
|
114
115
|
this.name = name;
|
|
@@ -119,6 +120,12 @@ export class Builder {
|
|
|
119
120
|
this.initiallyAvailableKeys.push(k);
|
|
120
121
|
return this;
|
|
121
122
|
}
|
|
123
|
+
/** Declare data keys injected via resumeAndExecute(externalData), not available at start. */
|
|
124
|
+
externallyProvided(...keys) {
|
|
125
|
+
for (const k of keys)
|
|
126
|
+
this.externallyProvidedKeys.push(k);
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
122
129
|
setTtl(ms) { this.ttl = ms; return this; }
|
|
123
130
|
setMaxGuardRetries(max) { this.maxGuardRetries = max; return this; }
|
|
124
131
|
from(state) {
|
|
@@ -181,7 +188,7 @@ export class Builder {
|
|
|
181
188
|
result.terminalStates = terminals;
|
|
182
189
|
result.dataFlowGraph = null;
|
|
183
190
|
this.validate(result);
|
|
184
|
-
result.dataFlowGraph = DataFlowGraph.build(result, this.initiallyAvailableKeys);
|
|
191
|
+
result.dataFlowGraph = DataFlowGraph.build(result, this.initiallyAvailableKeys, this.externallyProvidedKeys);
|
|
185
192
|
// Build warnings
|
|
186
193
|
const warnings = [];
|
|
187
194
|
const perpetual = terminals.size === 0;
|
|
@@ -350,6 +357,10 @@ export class Builder {
|
|
|
350
357
|
}
|
|
351
358
|
for (const t of def.transitionsFrom(state)) {
|
|
352
359
|
const newAvailable = new Set(stateAvailable.get(state));
|
|
360
|
+
if (t.type === 'external') {
|
|
361
|
+
for (const k of this.externallyProvidedKeys)
|
|
362
|
+
newAvailable.add(k);
|
|
363
|
+
}
|
|
353
364
|
if (t.guard) {
|
|
354
365
|
for (const req of t.guard.requires) {
|
|
355
366
|
if (!newAvailable.has(req))
|
|
@@ -527,6 +538,7 @@ export class BranchBuilder {
|
|
|
527
538
|
processor: this.processors.get(label),
|
|
528
539
|
guard: undefined, branch: this.branch,
|
|
529
540
|
branchTargets: new Map(this.targets),
|
|
541
|
+
branchLabel: label,
|
|
530
542
|
});
|
|
531
543
|
}
|
|
532
544
|
return this.builder;
|
package/dist/esm/flow-engine.js
CHANGED
|
@@ -198,7 +198,7 @@ export class FlowEngine {
|
|
|
198
198
|
if (!target) {
|
|
199
199
|
throw new FlowError('UNKNOWN_BRANCH', `Branch '${branch.name}' returned unknown label: ${label}`);
|
|
200
200
|
}
|
|
201
|
-
const specific = transitions.find(t => t.type === 'branch' && t.to === target) ?? autoOrBranch;
|
|
201
|
+
const specific = transitions.find(t => t.type === 'branch' && t.branchLabel === label) ?? transitions.find(t => t.type === 'branch' && t.to === target) ?? autoOrBranch;
|
|
202
202
|
if (specific.processor)
|
|
203
203
|
await specific.processor.process(flow.context);
|
|
204
204
|
const from = flow.currentState;
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface Transition<S extends string> {
|
|
|
26
26
|
guard?: TransitionGuard<S>;
|
|
27
27
|
branch?: BranchProcessor<S>;
|
|
28
28
|
branchTargets: Map<string, S>;
|
|
29
|
+
/** Label assigned by builder .to(target, label, processor). Used for branch label-specific processor matching. */
|
|
30
|
+
branchLabel?: string;
|
|
29
31
|
subFlowDefinition?: import('./flow-definition.js').FlowDefinition<any>;
|
|
30
32
|
exitMappings?: Map<string, S>;
|
|
31
33
|
/** Per-state timeout in milliseconds. If set, resumeAndExecute checks this before guard. */
|