@unlaxer/tramli-plugins 3.0.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/api/plugin-registry.d.ts +19 -0
- package/dist/cjs/api/plugin-registry.js +55 -0
- package/dist/cjs/api/types.d.ts +51 -0
- package/dist/cjs/api/types.js +23 -0
- package/dist/cjs/audit/audit-store-plugin.d.ts +7 -0
- package/dist/cjs/audit/audit-store-plugin.js +14 -0
- package/dist/cjs/audit/auditing-flow-store.d.ts +24 -0
- package/dist/cjs/audit/auditing-flow-store.js +33 -0
- package/dist/cjs/diagram/diagram-generation-plugin.d.ts +9 -0
- package/dist/cjs/diagram/diagram-generation-plugin.js +19 -0
- package/dist/cjs/diagram/diagram-plugin.d.ts +5 -0
- package/dist/cjs/diagram/diagram-plugin.js +16 -0
- package/dist/cjs/diagram/types.d.ts +5 -0
- package/dist/cjs/diagram/types.js +2 -0
- package/dist/cjs/docs/documentation-plugin.d.ts +7 -0
- package/dist/cjs/docs/documentation-plugin.js +33 -0
- package/dist/cjs/docs/flow-documentation-plugin.d.ts +8 -0
- package/dist/cjs/docs/flow-documentation-plugin.js +19 -0
- package/dist/cjs/eventstore/compensation-service.d.ts +11 -0
- package/dist/cjs/eventstore/compensation-service.js +22 -0
- package/dist/cjs/eventstore/event-log-store-decorator.d.ts +24 -0
- package/dist/cjs/eventstore/event-log-store-decorator.js +50 -0
- package/dist/cjs/eventstore/event-log-store-plugin.d.ts +7 -0
- package/dist/cjs/eventstore/event-log-store-plugin.js +14 -0
- package/dist/cjs/eventstore/replay-service.d.ts +14 -0
- package/dist/cjs/eventstore/replay-service.js +33 -0
- package/dist/cjs/eventstore/types.d.ts +19 -0
- package/dist/cjs/eventstore/types.js +2 -0
- package/dist/cjs/hierarchy/entry-exit-compiler.d.ts +8 -0
- package/dist/cjs/hierarchy/entry-exit-compiler.js +39 -0
- package/dist/cjs/hierarchy/hierarchy-code-generator.d.ts +10 -0
- package/dist/cjs/hierarchy/hierarchy-code-generator.js +48 -0
- package/dist/cjs/hierarchy/hierarchy-generation-plugin.d.ts +8 -0
- package/dist/cjs/hierarchy/hierarchy-generation-plugin.js +22 -0
- package/dist/cjs/hierarchy/types.d.ts +27 -0
- package/dist/cjs/hierarchy/types.js +21 -0
- package/dist/cjs/idempotency/idempotency-runtime-plugin.d.ts +11 -0
- package/dist/cjs/idempotency/idempotency-runtime-plugin.js +22 -0
- package/dist/cjs/idempotency/idempotent-rich-resume-executor.d.ts +9 -0
- package/dist/cjs/idempotency/idempotent-rich-resume-executor.js +22 -0
- package/dist/cjs/idempotency/in-memory-idempotency-registry.d.ts +5 -0
- package/dist/cjs/idempotency/in-memory-idempotency-registry.js +14 -0
- package/dist/cjs/idempotency/types.d.ts +13 -0
- package/dist/cjs/idempotency/types.js +2 -0
- package/dist/cjs/index.d.ts +36 -0
- package/dist/cjs/index.js +72 -0
- package/dist/cjs/lint/default-flow-policies.d.ts +2 -0
- package/dist/cjs/lint/default-flow-policies.js +41 -0
- package/dist/cjs/lint/policy-lint-plugin.d.ts +11 -0
- package/dist/cjs/lint/policy-lint-plugin.js +27 -0
- package/dist/cjs/lint/types.d.ts +5 -0
- package/dist/cjs/lint/types.js +2 -0
- package/dist/cjs/observability/observability-plugin.d.ts +25 -0
- package/dist/cjs/observability/observability-plugin.js +36 -0
- package/dist/cjs/resume/rich-resume.d.ts +21 -0
- package/dist/cjs/resume/rich-resume.js +47 -0
- package/dist/cjs/subflow/guaranteed-subflow-validator.d.ts +8 -0
- package/dist/cjs/subflow/guaranteed-subflow-validator.js +31 -0
- package/dist/cjs/testing/scenario-generation-plugin.d.ts +9 -0
- package/dist/cjs/testing/scenario-generation-plugin.js +19 -0
- package/dist/cjs/testing/scenario-test-plugin.d.ts +8 -0
- package/dist/cjs/testing/scenario-test-plugin.js +28 -0
- package/dist/cjs/testing/types.d.ts +7 -0
- package/dist/cjs/testing/types.js +2 -0
- package/dist/esm/api/plugin-registry.d.ts +19 -0
- package/dist/esm/api/plugin-registry.js +51 -0
- package/dist/esm/api/types.d.ts +51 -0
- package/dist/esm/api/types.js +19 -0
- package/dist/esm/audit/audit-store-plugin.d.ts +7 -0
- package/dist/esm/audit/audit-store-plugin.js +10 -0
- package/dist/esm/audit/auditing-flow-store.d.ts +24 -0
- package/dist/esm/audit/auditing-flow-store.js +29 -0
- package/dist/esm/diagram/diagram-generation-plugin.d.ts +9 -0
- package/dist/esm/diagram/diagram-generation-plugin.js +15 -0
- package/dist/esm/diagram/diagram-plugin.d.ts +5 -0
- package/dist/esm/diagram/diagram-plugin.js +12 -0
- package/dist/esm/diagram/types.d.ts +5 -0
- package/dist/esm/diagram/types.js +1 -0
- package/dist/esm/docs/documentation-plugin.d.ts +7 -0
- package/dist/esm/docs/documentation-plugin.js +29 -0
- package/dist/esm/docs/flow-documentation-plugin.d.ts +8 -0
- package/dist/esm/docs/flow-documentation-plugin.js +15 -0
- package/dist/esm/eventstore/compensation-service.d.ts +11 -0
- package/dist/esm/eventstore/compensation-service.js +18 -0
- package/dist/esm/eventstore/event-log-store-decorator.d.ts +24 -0
- package/dist/esm/eventstore/event-log-store-decorator.js +46 -0
- package/dist/esm/eventstore/event-log-store-plugin.d.ts +7 -0
- package/dist/esm/eventstore/event-log-store-plugin.js +10 -0
- package/dist/esm/eventstore/replay-service.d.ts +14 -0
- package/dist/esm/eventstore/replay-service.js +28 -0
- package/dist/esm/eventstore/types.d.ts +19 -0
- package/dist/esm/eventstore/types.js +1 -0
- package/dist/esm/hierarchy/entry-exit-compiler.d.ts +8 -0
- package/dist/esm/hierarchy/entry-exit-compiler.js +35 -0
- package/dist/esm/hierarchy/hierarchy-code-generator.d.ts +10 -0
- package/dist/esm/hierarchy/hierarchy-code-generator.js +44 -0
- package/dist/esm/hierarchy/hierarchy-generation-plugin.d.ts +8 -0
- package/dist/esm/hierarchy/hierarchy-generation-plugin.js +18 -0
- package/dist/esm/hierarchy/types.d.ts +27 -0
- package/dist/esm/hierarchy/types.js +16 -0
- package/dist/esm/idempotency/idempotency-runtime-plugin.d.ts +11 -0
- package/dist/esm/idempotency/idempotency-runtime-plugin.js +18 -0
- package/dist/esm/idempotency/idempotent-rich-resume-executor.d.ts +9 -0
- package/dist/esm/idempotency/idempotent-rich-resume-executor.js +18 -0
- package/dist/esm/idempotency/in-memory-idempotency-registry.d.ts +5 -0
- package/dist/esm/idempotency/in-memory-idempotency-registry.js +10 -0
- package/dist/esm/idempotency/types.d.ts +13 -0
- package/dist/esm/idempotency/types.js +1 -0
- package/dist/esm/index.d.ts +36 -0
- package/dist/esm/index.js +38 -0
- package/dist/esm/lint/default-flow-policies.d.ts +2 -0
- package/dist/esm/lint/default-flow-policies.js +38 -0
- package/dist/esm/lint/policy-lint-plugin.d.ts +11 -0
- package/dist/esm/lint/policy-lint-plugin.js +23 -0
- package/dist/esm/lint/types.d.ts +5 -0
- package/dist/esm/lint/types.js +1 -0
- package/dist/esm/observability/observability-plugin.d.ts +25 -0
- package/dist/esm/observability/observability-plugin.js +31 -0
- package/dist/esm/resume/rich-resume.d.ts +21 -0
- package/dist/esm/resume/rich-resume.js +42 -0
- package/dist/esm/subflow/guaranteed-subflow-validator.d.ts +8 -0
- package/dist/esm/subflow/guaranteed-subflow-validator.js +27 -0
- package/dist/esm/testing/scenario-generation-plugin.d.ts +9 -0
- package/dist/esm/testing/scenario-generation-plugin.js +15 -0
- package/dist/esm/testing/scenario-test-plugin.d.ts +8 -0
- package/dist/esm/testing/scenario-test-plugin.js +24 -0
- package/dist/esm/testing/types.d.ts +7 -0
- package/dist/esm/testing/types.js +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FlowDefinition, FlowEngine } from '@unlaxer/tramli';
|
|
2
|
+
import type { FlowPlugin } from './types.js';
|
|
3
|
+
import { PluginReport } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Central registry for tramli plugins.
|
|
6
|
+
* Manages plugin lifecycle: analyze → wrap store → install engine → bind adapters.
|
|
7
|
+
*/
|
|
8
|
+
export declare class PluginRegistry<S extends string> {
|
|
9
|
+
private plugins;
|
|
10
|
+
register(plugin: FlowPlugin): this;
|
|
11
|
+
/** Run all analysis plugins against a FlowDefinition. */
|
|
12
|
+
analyzeAll(definition: FlowDefinition<S>): PluginReport;
|
|
13
|
+
/** Apply all store plugins (wrapping in registration order). */
|
|
14
|
+
applyStorePlugins(store: any): any;
|
|
15
|
+
/** Install all engine plugins. */
|
|
16
|
+
installEnginePlugins(engine: FlowEngine): void;
|
|
17
|
+
/** Bind all runtime adapter plugins. Returns map of plugin id → bound adapter. */
|
|
18
|
+
bindRuntimeAdapters(engine: FlowEngine): Map<string, unknown>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PluginRegistry = void 0;
|
|
4
|
+
const types_js_1 = require("./types.js");
|
|
5
|
+
/**
|
|
6
|
+
* Central registry for tramli plugins.
|
|
7
|
+
* Manages plugin lifecycle: analyze → wrap store → install engine → bind adapters.
|
|
8
|
+
*/
|
|
9
|
+
class PluginRegistry {
|
|
10
|
+
plugins = [];
|
|
11
|
+
register(plugin) {
|
|
12
|
+
this.plugins.push(plugin);
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
/** Run all analysis plugins against a FlowDefinition. */
|
|
16
|
+
analyzeAll(definition) {
|
|
17
|
+
const report = new types_js_1.PluginReport();
|
|
18
|
+
for (const p of this.plugins) {
|
|
19
|
+
if (p.kind() === 'ANALYSIS') {
|
|
20
|
+
p.analyze(definition, report);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return report;
|
|
24
|
+
}
|
|
25
|
+
/** Apply all store plugins (wrapping in registration order). */
|
|
26
|
+
applyStorePlugins(store) {
|
|
27
|
+
let wrapped = store;
|
|
28
|
+
for (const p of this.plugins) {
|
|
29
|
+
if (p.kind() === 'STORE') {
|
|
30
|
+
wrapped = p.wrapStore(wrapped);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return wrapped;
|
|
34
|
+
}
|
|
35
|
+
/** Install all engine plugins. */
|
|
36
|
+
installEnginePlugins(engine) {
|
|
37
|
+
for (const p of this.plugins) {
|
|
38
|
+
if (p.kind() === 'ENGINE') {
|
|
39
|
+
p.install(engine);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Bind all runtime adapter plugins. Returns map of plugin id → bound adapter. */
|
|
44
|
+
bindRuntimeAdapters(engine) {
|
|
45
|
+
const adapters = new Map();
|
|
46
|
+
for (const p of this.plugins) {
|
|
47
|
+
if (p.kind() === 'RUNTIME_ADAPTER') {
|
|
48
|
+
const adapter = p.bind(engine);
|
|
49
|
+
adapters.set(p.descriptor().id, adapter);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return adapters;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.PluginRegistry = PluginRegistry;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { FlowDefinition, FlowEngine } from '@unlaxer/tramli';
|
|
2
|
+
/** Plugin kind classification. */
|
|
3
|
+
export type PluginKind = 'ANALYSIS' | 'STORE' | 'ENGINE' | 'RUNTIME_ADAPTER' | 'GENERATION' | 'DOCUMENTATION';
|
|
4
|
+
/** Plugin descriptor. */
|
|
5
|
+
export interface PluginDescriptor {
|
|
6
|
+
id: string;
|
|
7
|
+
displayName: string;
|
|
8
|
+
description: string;
|
|
9
|
+
}
|
|
10
|
+
/** Base plugin interface. */
|
|
11
|
+
export interface FlowPlugin {
|
|
12
|
+
descriptor(): PluginDescriptor;
|
|
13
|
+
kind(): PluginKind;
|
|
14
|
+
id?(): string;
|
|
15
|
+
}
|
|
16
|
+
/** Analysis plugin — static analysis of FlowDefinition. */
|
|
17
|
+
export interface AnalysisPlugin<S extends string> extends FlowPlugin {
|
|
18
|
+
analyze(definition: FlowDefinition<S>, report: PluginReport): void;
|
|
19
|
+
}
|
|
20
|
+
/** Store plugin — wraps FlowStore with additional behavior. */
|
|
21
|
+
export interface StorePlugin extends FlowPlugin {
|
|
22
|
+
wrapStore(store: any): any;
|
|
23
|
+
}
|
|
24
|
+
/** Engine plugin — installs hooks on FlowEngine. */
|
|
25
|
+
export interface EnginePlugin extends FlowPlugin {
|
|
26
|
+
install(engine: FlowEngine): void;
|
|
27
|
+
}
|
|
28
|
+
/** Runtime adapter plugin — binds FlowEngine to return richer API. */
|
|
29
|
+
export interface RuntimeAdapterPlugin<R> extends FlowPlugin {
|
|
30
|
+
bind(engine: FlowEngine): R;
|
|
31
|
+
}
|
|
32
|
+
/** Generation plugin — generates output from input. */
|
|
33
|
+
export interface GenerationPlugin<I, O> extends FlowPlugin {
|
|
34
|
+
generate(input: I): O;
|
|
35
|
+
}
|
|
36
|
+
/** Documentation plugin — generates string documentation. */
|
|
37
|
+
export interface DocumentationPlugin<I> extends GenerationPlugin<I, string> {
|
|
38
|
+
}
|
|
39
|
+
/** Plugin report — collects analysis findings. */
|
|
40
|
+
export declare class PluginReport {
|
|
41
|
+
private entries;
|
|
42
|
+
add(pluginId: string, severity: string, message: string): void;
|
|
43
|
+
warn(pluginId: string, message: string): void;
|
|
44
|
+
error(pluginId: string, message: string): void;
|
|
45
|
+
asText(): string;
|
|
46
|
+
findings(): {
|
|
47
|
+
pluginId: string;
|
|
48
|
+
severity: string;
|
|
49
|
+
message: string;
|
|
50
|
+
}[];
|
|
51
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PluginReport = void 0;
|
|
4
|
+
/** Plugin report — collects analysis findings. */
|
|
5
|
+
class PluginReport {
|
|
6
|
+
entries = [];
|
|
7
|
+
add(pluginId, severity, message) {
|
|
8
|
+
this.entries.push({ pluginId, severity, message });
|
|
9
|
+
}
|
|
10
|
+
warn(pluginId, message) {
|
|
11
|
+
this.add(pluginId, 'WARN', message);
|
|
12
|
+
}
|
|
13
|
+
error(pluginId, message) {
|
|
14
|
+
this.add(pluginId, 'ERROR', message);
|
|
15
|
+
}
|
|
16
|
+
asText() {
|
|
17
|
+
if (this.entries.length === 0)
|
|
18
|
+
return 'No findings.';
|
|
19
|
+
return this.entries.map(e => `[${e.severity}] ${e.pluginId}: ${e.message}`).join('\n');
|
|
20
|
+
}
|
|
21
|
+
findings() { return [...this.entries]; }
|
|
22
|
+
}
|
|
23
|
+
exports.PluginReport = PluginReport;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { StorePlugin, PluginDescriptor } from '../api/types.js';
|
|
2
|
+
import { AuditingFlowStore } from './auditing-flow-store.js';
|
|
3
|
+
export declare class AuditStorePlugin implements StorePlugin {
|
|
4
|
+
descriptor(): PluginDescriptor;
|
|
5
|
+
kind(): "STORE";
|
|
6
|
+
wrapStore(store: any): AuditingFlowStore;
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuditStorePlugin = void 0;
|
|
4
|
+
const auditing_flow_store_js_1 = require("./auditing-flow-store.js");
|
|
5
|
+
class AuditStorePlugin {
|
|
6
|
+
descriptor() {
|
|
7
|
+
return { id: 'audit', displayName: 'Audit Store', description: 'Captures transition + produced-data diffs' };
|
|
8
|
+
}
|
|
9
|
+
kind() { return 'STORE'; }
|
|
10
|
+
wrapStore(store) {
|
|
11
|
+
return new auditing_flow_store_js_1.AuditingFlowStore(store);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.AuditStorePlugin = AuditStorePlugin;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { FlowContext } from '@unlaxer/tramli';
|
|
2
|
+
export interface AuditedTransitionRecord {
|
|
3
|
+
flowId: string;
|
|
4
|
+
from: string | null;
|
|
5
|
+
to: string;
|
|
6
|
+
trigger: string;
|
|
7
|
+
timestamp: Date;
|
|
8
|
+
producedDataSnapshot: Map<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* FlowStore decorator that captures produced-data snapshots on each transition.
|
|
12
|
+
*/
|
|
13
|
+
export declare class AuditingFlowStore {
|
|
14
|
+
private readonly delegate;
|
|
15
|
+
private auditLog;
|
|
16
|
+
constructor(delegate: any);
|
|
17
|
+
create(flow: any): void;
|
|
18
|
+
loadForUpdate<S extends string>(flowId: string, definition?: any): any;
|
|
19
|
+
save(flow: any): void;
|
|
20
|
+
recordTransition(flowId: string, from: any, to: string, trigger: string, ctx: FlowContext): void;
|
|
21
|
+
get auditedTransitions(): readonly AuditedTransitionRecord[];
|
|
22
|
+
get transitionLog(): any;
|
|
23
|
+
clear(): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuditingFlowStore = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* FlowStore decorator that captures produced-data snapshots on each transition.
|
|
6
|
+
*/
|
|
7
|
+
class AuditingFlowStore {
|
|
8
|
+
delegate;
|
|
9
|
+
auditLog = [];
|
|
10
|
+
constructor(delegate) {
|
|
11
|
+
this.delegate = delegate;
|
|
12
|
+
}
|
|
13
|
+
create(flow) { this.delegate.create(flow); }
|
|
14
|
+
loadForUpdate(flowId, definition) {
|
|
15
|
+
return this.delegate.loadForUpdate(flowId, definition);
|
|
16
|
+
}
|
|
17
|
+
save(flow) { this.delegate.save(flow); }
|
|
18
|
+
recordTransition(flowId, from, to, trigger, ctx) {
|
|
19
|
+
this.delegate.recordTransition(flowId, from, to, trigger, ctx);
|
|
20
|
+
const snapshot = new Map();
|
|
21
|
+
for (const [k, v] of ctx.snapshot()) {
|
|
22
|
+
snapshot.set(k, v);
|
|
23
|
+
}
|
|
24
|
+
this.auditLog.push({
|
|
25
|
+
flowId, from: from?.toString() ?? null, to, trigger,
|
|
26
|
+
timestamp: new Date(), producedDataSnapshot: snapshot,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
get auditedTransitions() { return this.auditLog; }
|
|
30
|
+
get transitionLog() { return this.delegate.transitionLog; }
|
|
31
|
+
clear() { this.delegate.clear?.(); this.auditLog = []; }
|
|
32
|
+
}
|
|
33
|
+
exports.AuditingFlowStore = AuditingFlowStore;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FlowDefinition } from '@unlaxer/tramli';
|
|
2
|
+
import type { GenerationPlugin, PluginDescriptor } from '../api/types.js';
|
|
3
|
+
import type { DiagramBundle } from './types.js';
|
|
4
|
+
export declare class DiagramGenerationPlugin<S extends string> implements GenerationPlugin<FlowDefinition<S>, DiagramBundle> {
|
|
5
|
+
private readonly delegate;
|
|
6
|
+
descriptor(): PluginDescriptor;
|
|
7
|
+
kind(): "GENERATION";
|
|
8
|
+
generate(input: FlowDefinition<S>): DiagramBundle;
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DiagramGenerationPlugin = void 0;
|
|
4
|
+
const diagram_plugin_js_1 = require("./diagram-plugin.js");
|
|
5
|
+
class DiagramGenerationPlugin {
|
|
6
|
+
delegate = new diagram_plugin_js_1.DiagramPlugin();
|
|
7
|
+
descriptor() {
|
|
8
|
+
return {
|
|
9
|
+
id: 'diagram',
|
|
10
|
+
displayName: 'Diagram Generator',
|
|
11
|
+
description: 'Generates Mermaid and data-flow bundles from a flow definition.',
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
kind() { return 'GENERATION'; }
|
|
15
|
+
generate(input) {
|
|
16
|
+
return this.delegate.generate(input);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.DiagramGenerationPlugin = DiagramGenerationPlugin;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DiagramPlugin = void 0;
|
|
4
|
+
const tramli_1 = require("@unlaxer/tramli");
|
|
5
|
+
class DiagramPlugin {
|
|
6
|
+
generate(definition) {
|
|
7
|
+
const mermaid = tramli_1.MermaidGenerator.generate(definition);
|
|
8
|
+
const json = definition.dataFlowGraph?.toJson() ?? '{}';
|
|
9
|
+
const md = `# ${definition.name}\n\n` +
|
|
10
|
+
`- initial: \`${definition.initialState}\`\n` +
|
|
11
|
+
`- states: \`${definition.allStates().length}\`\n` +
|
|
12
|
+
`- transitions: \`${definition.transitions.length}\`\n`;
|
|
13
|
+
return { mermaid, dataFlowJson: json, markdownSummary: md };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.DiagramPlugin = DiagramPlugin;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DocumentationPlugin = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Generates a markdown flow catalog from a flow definition.
|
|
6
|
+
*/
|
|
7
|
+
class DocumentationPlugin {
|
|
8
|
+
toMarkdown(definition) {
|
|
9
|
+
const lines = [];
|
|
10
|
+
lines.push(`# Flow Catalog: ${definition.name}`);
|
|
11
|
+
lines.push('');
|
|
12
|
+
lines.push('## States');
|
|
13
|
+
lines.push('');
|
|
14
|
+
for (const state of definition.allStates()) {
|
|
15
|
+
const config = definition.stateConfig[state];
|
|
16
|
+
let suffix = '';
|
|
17
|
+
if (config?.initial)
|
|
18
|
+
suffix += ' (initial)';
|
|
19
|
+
if (config?.terminal)
|
|
20
|
+
suffix += ' (terminal)';
|
|
21
|
+
lines.push(`- \`${state}\`${suffix}`);
|
|
22
|
+
}
|
|
23
|
+
lines.push('');
|
|
24
|
+
lines.push('## Transitions');
|
|
25
|
+
lines.push('');
|
|
26
|
+
for (const t of definition.transitions) {
|
|
27
|
+
const via = t.processor?.name ?? t.guard?.name ?? t.branch?.name ?? t.type;
|
|
28
|
+
lines.push(`- \`${t.from} -> ${t.to}\` via \`${via}\``);
|
|
29
|
+
}
|
|
30
|
+
return lines.join('\n');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.DocumentationPlugin = DocumentationPlugin;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FlowDefinition } from '@unlaxer/tramli';
|
|
2
|
+
import type { DocumentationPlugin as DocPluginSPI, PluginDescriptor } from '../api/types.js';
|
|
3
|
+
export declare class FlowDocumentationPlugin<S extends string> implements DocPluginSPI<FlowDefinition<S>> {
|
|
4
|
+
private readonly delegate;
|
|
5
|
+
descriptor(): PluginDescriptor;
|
|
6
|
+
kind(): "DOCUMENTATION";
|
|
7
|
+
generate(input: FlowDefinition<S>): string;
|
|
8
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FlowDocumentationPlugin = void 0;
|
|
4
|
+
const documentation_plugin_js_1 = require("./documentation-plugin.js");
|
|
5
|
+
class FlowDocumentationPlugin {
|
|
6
|
+
delegate = new documentation_plugin_js_1.DocumentationPlugin();
|
|
7
|
+
descriptor() {
|
|
8
|
+
return {
|
|
9
|
+
id: 'docs',
|
|
10
|
+
displayName: 'Documentation Generator',
|
|
11
|
+
description: 'Renders a markdown flow catalog from a flow definition.',
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
kind() { return 'DOCUMENTATION'; }
|
|
15
|
+
generate(input) {
|
|
16
|
+
return this.delegate.toMarkdown(input);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.FlowDocumentationPlugin = FlowDocumentationPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { VersionedTransitionEvent, CompensationResolver } from './types.js';
|
|
2
|
+
import type { EventLogStoreDecorator } from './event-log-store-decorator.js';
|
|
3
|
+
/**
|
|
4
|
+
* Compensation service — records compensation events for failed transitions.
|
|
5
|
+
*/
|
|
6
|
+
export declare class CompensationService {
|
|
7
|
+
private readonly resolver;
|
|
8
|
+
private readonly eventLog;
|
|
9
|
+
constructor(resolver: CompensationResolver, eventLog: EventLogStoreDecorator);
|
|
10
|
+
compensate(event: VersionedTransitionEvent, cause: Error): boolean;
|
|
11
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CompensationService = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Compensation service — records compensation events for failed transitions.
|
|
6
|
+
*/
|
|
7
|
+
class CompensationService {
|
|
8
|
+
resolver;
|
|
9
|
+
eventLog;
|
|
10
|
+
constructor(resolver, eventLog) {
|
|
11
|
+
this.resolver = resolver;
|
|
12
|
+
this.eventLog = eventLog;
|
|
13
|
+
}
|
|
14
|
+
compensate(event, cause) {
|
|
15
|
+
const plan = this.resolver(event, cause);
|
|
16
|
+
if (!plan)
|
|
17
|
+
return false;
|
|
18
|
+
this.eventLog.appendCompensation(event.flowId, plan.action, JSON.stringify(plan.metadata));
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.CompensationService = CompensationService;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { FlowContext } from '@unlaxer/tramli';
|
|
2
|
+
import type { VersionedTransitionEvent } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* FlowStore decorator that maintains an append-only event log.
|
|
5
|
+
* Tenure-lite: not full event sourcing, intentionally lighter.
|
|
6
|
+
*/
|
|
7
|
+
export declare class EventLogStoreDecorator {
|
|
8
|
+
private readonly delegate;
|
|
9
|
+
private eventLog;
|
|
10
|
+
private versionCounters;
|
|
11
|
+
constructor(delegate: any);
|
|
12
|
+
create(flow: any): void;
|
|
13
|
+
loadForUpdate<S extends string>(flowId: string, definition?: any): any;
|
|
14
|
+
save(flow: any): void;
|
|
15
|
+
recordTransition(flowId: string, from: any, to: string, trigger: string, ctx: FlowContext): void;
|
|
16
|
+
/** All events across all flows. */
|
|
17
|
+
events(): readonly VersionedTransitionEvent[];
|
|
18
|
+
/** Events for a specific flow. */
|
|
19
|
+
eventsForFlow(flowId: string): VersionedTransitionEvent[];
|
|
20
|
+
/** Append a compensation event. */
|
|
21
|
+
appendCompensation(flowId: string, trigger: string, metadata: string): void;
|
|
22
|
+
get transitionLog(): any;
|
|
23
|
+
clear(): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventLogStoreDecorator = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* FlowStore decorator that maintains an append-only event log.
|
|
6
|
+
* Tenure-lite: not full event sourcing, intentionally lighter.
|
|
7
|
+
*/
|
|
8
|
+
class EventLogStoreDecorator {
|
|
9
|
+
delegate;
|
|
10
|
+
eventLog = [];
|
|
11
|
+
versionCounters = new Map();
|
|
12
|
+
constructor(delegate) {
|
|
13
|
+
this.delegate = delegate;
|
|
14
|
+
}
|
|
15
|
+
create(flow) { this.delegate.create(flow); }
|
|
16
|
+
loadForUpdate(flowId, definition) {
|
|
17
|
+
return this.delegate.loadForUpdate(flowId, definition);
|
|
18
|
+
}
|
|
19
|
+
save(flow) { this.delegate.save(flow); }
|
|
20
|
+
recordTransition(flowId, from, to, trigger, ctx) {
|
|
21
|
+
this.delegate.recordTransition(flowId, from, to, trigger, ctx);
|
|
22
|
+
const version = (this.versionCounters.get(flowId) ?? 0) + 1;
|
|
23
|
+
this.versionCounters.set(flowId, version);
|
|
24
|
+
this.eventLog.push({
|
|
25
|
+
flowId, version, type: 'TRANSITION',
|
|
26
|
+
from: from?.toString() ?? null, to, trigger,
|
|
27
|
+
timestamp: new Date(),
|
|
28
|
+
stateSnapshot: JSON.stringify(Object.fromEntries(ctx.snapshot())),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** All events across all flows. */
|
|
32
|
+
events() { return this.eventLog; }
|
|
33
|
+
/** Events for a specific flow. */
|
|
34
|
+
eventsForFlow(flowId) {
|
|
35
|
+
return this.eventLog.filter(e => e.flowId === flowId);
|
|
36
|
+
}
|
|
37
|
+
/** Append a compensation event. */
|
|
38
|
+
appendCompensation(flowId, trigger, metadata) {
|
|
39
|
+
const version = (this.versionCounters.get(flowId) ?? 0) + 1;
|
|
40
|
+
this.versionCounters.set(flowId, version);
|
|
41
|
+
this.eventLog.push({
|
|
42
|
+
flowId, version, type: 'COMPENSATION',
|
|
43
|
+
from: null, to: 'COMPENSATED', trigger,
|
|
44
|
+
timestamp: new Date(), stateSnapshot: metadata,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
get transitionLog() { return this.delegate.transitionLog; }
|
|
48
|
+
clear() { this.delegate.clear?.(); this.eventLog = []; this.versionCounters.clear(); }
|
|
49
|
+
}
|
|
50
|
+
exports.EventLogStoreDecorator = EventLogStoreDecorator;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { StorePlugin, PluginDescriptor } from '../api/types.js';
|
|
2
|
+
import { EventLogStoreDecorator } from './event-log-store-decorator.js';
|
|
3
|
+
export declare class EventLogStorePlugin implements StorePlugin {
|
|
4
|
+
descriptor(): PluginDescriptor;
|
|
5
|
+
kind(): "STORE";
|
|
6
|
+
wrapStore(store: any): EventLogStoreDecorator;
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EventLogStorePlugin = void 0;
|
|
4
|
+
const event_log_store_decorator_js_1 = require("./event-log-store-decorator.js");
|
|
5
|
+
class EventLogStorePlugin {
|
|
6
|
+
descriptor() {
|
|
7
|
+
return { id: 'eventstore', displayName: 'Event Log Store', description: 'Tenure-lite: append-only transition log with replay' };
|
|
8
|
+
}
|
|
9
|
+
kind() { return 'STORE'; }
|
|
10
|
+
wrapStore(store) {
|
|
11
|
+
return new event_log_store_decorator_js_1.EventLogStoreDecorator(store);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.EventLogStorePlugin = EventLogStorePlugin;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { VersionedTransitionEvent, ProjectionReducer } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Replay service — stateAtVersion using full-snapshot assumption.
|
|
4
|
+
* If moving to diff-only persistence, this must become a fold/reducer.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ReplayService {
|
|
7
|
+
stateAtVersion(events: readonly VersionedTransitionEvent[], flowId: string, targetVersion: number): string | null;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Projection replay service — custom reducers for materialized views.
|
|
11
|
+
*/
|
|
12
|
+
export declare class ProjectionReplayService {
|
|
13
|
+
stateAtVersion<T>(events: readonly VersionedTransitionEvent[], flowId: string, targetVersion: number, reducer: ProjectionReducer<T>): T;
|
|
14
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ProjectionReplayService = exports.ReplayService = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Replay service — stateAtVersion using full-snapshot assumption.
|
|
6
|
+
* If moving to diff-only persistence, this must become a fold/reducer.
|
|
7
|
+
*/
|
|
8
|
+
class ReplayService {
|
|
9
|
+
stateAtVersion(events, flowId, targetVersion) {
|
|
10
|
+
const flowEvents = events
|
|
11
|
+
.filter(e => e.flowId === flowId && e.type === 'TRANSITION' && e.version <= targetVersion)
|
|
12
|
+
.sort((a, b) => a.version - b.version);
|
|
13
|
+
if (flowEvents.length === 0)
|
|
14
|
+
return null;
|
|
15
|
+
return flowEvents[flowEvents.length - 1].to;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.ReplayService = ReplayService;
|
|
19
|
+
/**
|
|
20
|
+
* Projection replay service — custom reducers for materialized views.
|
|
21
|
+
*/
|
|
22
|
+
class ProjectionReplayService {
|
|
23
|
+
stateAtVersion(events, flowId, targetVersion, reducer) {
|
|
24
|
+
let state = reducer.initialState();
|
|
25
|
+
for (const event of events) {
|
|
26
|
+
if (event.flowId === flowId && event.version <= targetVersion) {
|
|
27
|
+
state = reducer.apply(state, event);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return state;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.ProjectionReplayService = ProjectionReplayService;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface VersionedTransitionEvent {
|
|
2
|
+
flowId: string;
|
|
3
|
+
version: number;
|
|
4
|
+
type: 'TRANSITION' | 'COMPENSATION';
|
|
5
|
+
from: string | null;
|
|
6
|
+
to: string;
|
|
7
|
+
trigger: string;
|
|
8
|
+
timestamp: Date;
|
|
9
|
+
stateSnapshot: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CompensationPlan {
|
|
12
|
+
action: string;
|
|
13
|
+
metadata: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
export type CompensationResolver = (event: VersionedTransitionEvent, cause: Error) => CompensationPlan | null;
|
|
16
|
+
export interface ProjectionReducer<T> {
|
|
17
|
+
initialState(): T;
|
|
18
|
+
apply(current: T, event: VersionedTransitionEvent): T;
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HierarchicalFlowSpec, HierarchicalTransitionSpec } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Synthesizes entry/exit transitions from hierarchical state specs.
|
|
4
|
+
*/
|
|
5
|
+
export declare class EntryExitCompiler {
|
|
6
|
+
synthesize(spec: HierarchicalFlowSpec): HierarchicalTransitionSpec[];
|
|
7
|
+
private walk;
|
|
8
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EntryExitCompiler = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Synthesizes entry/exit transitions from hierarchical state specs.
|
|
6
|
+
*/
|
|
7
|
+
class EntryExitCompiler {
|
|
8
|
+
synthesize(spec) {
|
|
9
|
+
const generated = [];
|
|
10
|
+
for (const state of spec.rootStates) {
|
|
11
|
+
this.walk(state, generated, null);
|
|
12
|
+
}
|
|
13
|
+
return generated;
|
|
14
|
+
}
|
|
15
|
+
walk(state, out, parentName) {
|
|
16
|
+
if (state.entryProduces.length > 0) {
|
|
17
|
+
out.push({
|
|
18
|
+
from: parentName ?? `${state.name}__ENTRY_START`,
|
|
19
|
+
to: state.name,
|
|
20
|
+
trigger: `__entry__${state.name}`,
|
|
21
|
+
requires: [],
|
|
22
|
+
produces: [...state.entryProduces],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (state.exitProduces.length > 0) {
|
|
26
|
+
out.push({
|
|
27
|
+
from: state.name,
|
|
28
|
+
to: `${state.name}__EXIT_END`,
|
|
29
|
+
trigger: `__exit__${state.name}`,
|
|
30
|
+
requires: [],
|
|
31
|
+
produces: [...state.exitProduces],
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
for (const child of state.children) {
|
|
35
|
+
this.walk(child, out, state.name);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.EntryExitCompiler = EntryExitCompiler;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HierarchicalFlowSpec } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Generates TypeScript source from a hierarchical flow spec.
|
|
4
|
+
* Flattens the hierarchy into a flat state config + builder skeleton.
|
|
5
|
+
*/
|
|
6
|
+
export declare class HierarchyCodeGenerator {
|
|
7
|
+
generateStateConfig(spec: HierarchicalFlowSpec): string;
|
|
8
|
+
generateBuilderSkeleton(spec: HierarchicalFlowSpec): string;
|
|
9
|
+
private flatten;
|
|
10
|
+
}
|