@clusterenvision/ui-framework 1.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/LICENSE +21 -0
- package/README.md +295 -0
- package/dist/ai-assistant-Db002XYC.d.ts +92 -0
- package/dist/ai-assistant-EobSUV70.d.cts +92 -0
- package/dist/browser-DnHpnWwE.d.cts +354 -0
- package/dist/browser-Dx4oKf5e.d.ts +354 -0
- package/dist/browser-signals-07qodpYT.d.cts +66 -0
- package/dist/browser-signals-07qodpYT.d.ts +66 -0
- package/dist/browser-signals.cjs +32 -0
- package/dist/browser-signals.cjs.map +1 -0
- package/dist/browser-signals.d.cts +1 -0
- package/dist/browser-signals.d.ts +1 -0
- package/dist/browser-signals.js +3 -0
- package/dist/browser-signals.js.map +1 -0
- package/dist/browser.cjs +197 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +13 -0
- package/dist/browser.d.ts +13 -0
- package/dist/browser.js +12 -0
- package/dist/browser.js.map +1 -0
- package/dist/chunk-22HQL2Y4.js +568 -0
- package/dist/chunk-22HQL2Y4.js.map +1 -0
- package/dist/chunk-3ZBRNFEE.js +1525 -0
- package/dist/chunk-3ZBRNFEE.js.map +1 -0
- package/dist/chunk-4HRORR2Q.js +1953 -0
- package/dist/chunk-4HRORR2Q.js.map +1 -0
- package/dist/chunk-4L3UXVL5.cjs +68 -0
- package/dist/chunk-4L3UXVL5.cjs.map +1 -0
- package/dist/chunk-6BYWFGQY.cjs +226 -0
- package/dist/chunk-6BYWFGQY.cjs.map +1 -0
- package/dist/chunk-7SCIB5HP.js +57 -0
- package/dist/chunk-7SCIB5HP.js.map +1 -0
- package/dist/chunk-BBAUALNU.js +888 -0
- package/dist/chunk-BBAUALNU.js.map +1 -0
- package/dist/chunk-CHLDE4JQ.js +715 -0
- package/dist/chunk-CHLDE4JQ.js.map +1 -0
- package/dist/chunk-CXTAUXLG.cjs +71 -0
- package/dist/chunk-CXTAUXLG.cjs.map +1 -0
- package/dist/chunk-D2USIT6V.js +121 -0
- package/dist/chunk-D2USIT6V.js.map +1 -0
- package/dist/chunk-D3H5CGVD.js +36 -0
- package/dist/chunk-D3H5CGVD.js.map +1 -0
- package/dist/chunk-DQBX75NJ.js +92 -0
- package/dist/chunk-DQBX75NJ.js.map +1 -0
- package/dist/chunk-DRPG2DFX.js +208 -0
- package/dist/chunk-DRPG2DFX.js.map +1 -0
- package/dist/chunk-EFOOXCY7.cjs +41 -0
- package/dist/chunk-EFOOXCY7.cjs.map +1 -0
- package/dist/chunk-FFCZSYC7.cjs +906 -0
- package/dist/chunk-FFCZSYC7.cjs.map +1 -0
- package/dist/chunk-FNXIYAET.cjs +1593 -0
- package/dist/chunk-FNXIYAET.cjs.map +1 -0
- package/dist/chunk-I6GNUM3P.cjs +63 -0
- package/dist/chunk-I6GNUM3P.cjs.map +1 -0
- package/dist/chunk-IHAMVLRY.js +129 -0
- package/dist/chunk-IHAMVLRY.js.map +1 -0
- package/dist/chunk-IRBUKIRF.cjs +133 -0
- package/dist/chunk-IRBUKIRF.cjs.map +1 -0
- package/dist/chunk-KPG5HAHK.cjs +97 -0
- package/dist/chunk-KPG5HAHK.cjs.map +1 -0
- package/dist/chunk-N7Q2ESLG.cjs +130 -0
- package/dist/chunk-N7Q2ESLG.cjs.map +1 -0
- package/dist/chunk-PFBEIFVS.js +180 -0
- package/dist/chunk-PFBEIFVS.js.map +1 -0
- package/dist/chunk-PVZVFICK.cjs +318 -0
- package/dist/chunk-PVZVFICK.cjs.map +1 -0
- package/dist/chunk-Q3KH6HMU.js +305 -0
- package/dist/chunk-Q3KH6HMU.js.map +1 -0
- package/dist/chunk-QPAAV32J.cjs +1985 -0
- package/dist/chunk-QPAAV32J.cjs.map +1 -0
- package/dist/chunk-R6XQUMWT.cjs +61 -0
- package/dist/chunk-R6XQUMWT.cjs.map +1 -0
- package/dist/chunk-SA5UD5B6.js +92 -0
- package/dist/chunk-SA5UD5B6.js.map +1 -0
- package/dist/chunk-SM35JOYD.cjs +211 -0
- package/dist/chunk-SM35JOYD.cjs.map +1 -0
- package/dist/chunk-SZQNIMYI.cjs +592 -0
- package/dist/chunk-SZQNIMYI.cjs.map +1 -0
- package/dist/chunk-T6T7QE4J.js +224 -0
- package/dist/chunk-T6T7QE4J.js.map +1 -0
- package/dist/chunk-TIF372DZ.js +65 -0
- package/dist/chunk-TIF372DZ.js.map +1 -0
- package/dist/chunk-V6JCOBGY.js +69 -0
- package/dist/chunk-V6JCOBGY.js.map +1 -0
- package/dist/chunk-VHUXNDW2.cjs +189 -0
- package/dist/chunk-VHUXNDW2.cjs.map +1 -0
- package/dist/chunk-W3LNNY3U.cjs +729 -0
- package/dist/chunk-W3LNNY3U.cjs.map +1 -0
- package/dist/chunk-ZUWSU4OA.js +61 -0
- package/dist/chunk-ZUWSU4OA.js.map +1 -0
- package/dist/chunk-ZWUA2LPB.cjs +103 -0
- package/dist/chunk-ZWUA2LPB.cjs.map +1 -0
- package/dist/cli/index.cjs +566 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +558 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/compiler/index.cjs +80 -0
- package/dist/compiler/index.cjs.map +1 -0
- package/dist/compiler/index.d.cts +130 -0
- package/dist/compiler/index.d.ts +130 -0
- package/dist/compiler/index.js +3 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/component-BVzvepw9.d.cts +90 -0
- package/dist/component-wTxZ2BPD.d.ts +90 -0
- package/dist/index-CpxDa60m.d.cts +644 -0
- package/dist/index-CpxDa60m.d.ts +644 -0
- package/dist/index.cjs +1356 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +165 -0
- package/dist/index.d.ts +165 -0
- package/dist/index.js +772 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/dom.cjs +102 -0
- package/dist/lib/dom.cjs.map +1 -0
- package/dist/lib/dom.d.cts +373 -0
- package/dist/lib/dom.d.ts +373 -0
- package/dist/lib/dom.js +3 -0
- package/dist/lib/dom.js.map +1 -0
- package/dist/lib/icons.cjs +20 -0
- package/dist/lib/icons.cjs.map +1 -0
- package/dist/lib/icons.d.cts +64 -0
- package/dist/lib/icons.d.ts +64 -0
- package/dist/lib/icons.js +3 -0
- package/dist/lib/icons.js.map +1 -0
- package/dist/lib/index.cjs +247 -0
- package/dist/lib/index.cjs.map +1 -0
- package/dist/lib/index.d.cts +30 -0
- package/dist/lib/index.d.ts +30 -0
- package/dist/lib/index.js +92 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/theme.cjs +56 -0
- package/dist/lib/theme.cjs.map +1 -0
- package/dist/lib/theme.d.cts +27 -0
- package/dist/lib/theme.d.ts +27 -0
- package/dist/lib/theme.js +3 -0
- package/dist/lib/theme.js.map +1 -0
- package/dist/router-B9kms5XQ.d.ts +124 -0
- package/dist/router-YnpW_sIK.d.cts +124 -0
- package/dist/runtime/adapters/angular.cjs +48 -0
- package/dist/runtime/adapters/angular.cjs.map +1 -0
- package/dist/runtime/adapters/angular.d.cts +38 -0
- package/dist/runtime/adapters/angular.d.ts +38 -0
- package/dist/runtime/adapters/angular.js +46 -0
- package/dist/runtime/adapters/angular.js.map +1 -0
- package/dist/runtime/adapters/react.cjs +41 -0
- package/dist/runtime/adapters/react.cjs.map +1 -0
- package/dist/runtime/adapters/react.d.cts +26 -0
- package/dist/runtime/adapters/react.d.ts +26 -0
- package/dist/runtime/adapters/react.js +39 -0
- package/dist/runtime/adapters/react.js.map +1 -0
- package/dist/runtime/adapters/vue.cjs +44 -0
- package/dist/runtime/adapters/vue.cjs.map +1 -0
- package/dist/runtime/adapters/vue.d.cts +37 -0
- package/dist/runtime/adapters/vue.d.ts +37 -0
- package/dist/runtime/adapters/vue.js +42 -0
- package/dist/runtime/adapters/vue.js.map +1 -0
- package/dist/runtime/components/ai-assistant.cjs +18 -0
- package/dist/runtime/components/ai-assistant.cjs.map +1 -0
- package/dist/runtime/components/ai-assistant.d.cts +8 -0
- package/dist/runtime/components/ai-assistant.d.ts +8 -0
- package/dist/runtime/components/ai-assistant.js +9 -0
- package/dist/runtime/components/ai-assistant.js.map +1 -0
- package/dist/runtime/components/ai-summary-card.cjs +18 -0
- package/dist/runtime/components/ai-summary-card.cjs.map +1 -0
- package/dist/runtime/components/ai-summary-card.d.cts +19 -0
- package/dist/runtime/components/ai-summary-card.d.ts +19 -0
- package/dist/runtime/components/ai-summary-card.js +9 -0
- package/dist/runtime/components/ai-summary-card.js.map +1 -0
- package/dist/runtime/router.cjs +429 -0
- package/dist/runtime/router.cjs.map +1 -0
- package/dist/runtime/router.d.cts +2 -0
- package/dist/runtime/router.d.ts +2 -0
- package/dist/runtime/router.js +421 -0
- package/dist/runtime/router.js.map +1 -0
- package/dist/runtime/server.cjs +125 -0
- package/dist/runtime/server.cjs.map +1 -0
- package/dist/runtime/server.d.cts +27 -0
- package/dist/runtime/server.d.ts +27 -0
- package/dist/runtime/server.js +117 -0
- package/dist/runtime/server.js.map +1 -0
- package/dist/runtime/workflow/index.cjs +282 -0
- package/dist/runtime/workflow/index.cjs.map +1 -0
- package/dist/runtime/workflow/index.d.cts +1 -0
- package/dist/runtime/workflow/index.d.ts +1 -0
- package/dist/runtime/workflow/index.js +5 -0
- package/dist/runtime/workflow/index.js.map +1 -0
- package/dist/tracing-DGdvMCEl.d.cts +109 -0
- package/dist/tracing-DGdvMCEl.d.ts +109 -0
- package/dist/types-C4RXXKfk.d.cts +76 -0
- package/dist/types-C4RXXKfk.d.ts +76 -0
- package/package.json +166 -0
|
@@ -0,0 +1,1593 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkSM35JOYD_cjs = require('./chunk-SM35JOYD.cjs');
|
|
4
|
+
var fs = require('fs');
|
|
5
|
+
|
|
6
|
+
// src/runtime/logger.js
|
|
7
|
+
var defaultConsoleWriter = {
|
|
8
|
+
debug: console.debug.bind(console),
|
|
9
|
+
info: console.info.bind(console),
|
|
10
|
+
warn: console.warn.bind(console),
|
|
11
|
+
error: console.error.bind(console)
|
|
12
|
+
};
|
|
13
|
+
var ConsoleLogger = class {
|
|
14
|
+
constructor(scope = "runtime", writer = defaultConsoleWriter) {
|
|
15
|
+
this.scope = scope;
|
|
16
|
+
this.writer = writer;
|
|
17
|
+
}
|
|
18
|
+
log(event) {
|
|
19
|
+
const { context: originalContext, error: explicitError, level, message } = event;
|
|
20
|
+
const { context, errorFromContext } = extractErrorFromContext(originalContext);
|
|
21
|
+
const payload = {
|
|
22
|
+
...context,
|
|
23
|
+
level,
|
|
24
|
+
timestamp: (event.timestamp ?? /* @__PURE__ */ new Date()).toISOString()
|
|
25
|
+
};
|
|
26
|
+
const normalizedScope = context?.scope ?? this.scope;
|
|
27
|
+
if (normalizedScope) {
|
|
28
|
+
payload.scope = normalizedScope;
|
|
29
|
+
}
|
|
30
|
+
const normalizedError = explicitError ?? normalizeError(errorFromContext);
|
|
31
|
+
if (normalizedError) {
|
|
32
|
+
payload.error = normalizedError;
|
|
33
|
+
}
|
|
34
|
+
this.writer[level](`[ceui${normalizedScope ? `:${normalizedScope}` : ""}] ${message}`, payload);
|
|
35
|
+
}
|
|
36
|
+
debug(message, context) {
|
|
37
|
+
this.log({ level: "debug", message, context });
|
|
38
|
+
}
|
|
39
|
+
info(message, context) {
|
|
40
|
+
this.log({ level: "info", message, context });
|
|
41
|
+
}
|
|
42
|
+
warn(message, context) {
|
|
43
|
+
this.log({ level: "warn", message, context });
|
|
44
|
+
}
|
|
45
|
+
error(message, context) {
|
|
46
|
+
this.log({ level: "error", message, context });
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function extractErrorFromContext(context) {
|
|
50
|
+
if (!context || typeof context !== "object") {
|
|
51
|
+
return { context: void 0, errorFromContext: void 0 };
|
|
52
|
+
}
|
|
53
|
+
const { error, ...rest } = context;
|
|
54
|
+
return { context: rest, errorFromContext: error };
|
|
55
|
+
}
|
|
56
|
+
function normalizeError(error) {
|
|
57
|
+
if (!error) {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
if (error instanceof Error) {
|
|
61
|
+
return {
|
|
62
|
+
name: error.name,
|
|
63
|
+
message: error.message,
|
|
64
|
+
stack: error.stack,
|
|
65
|
+
cause: error.cause
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (typeof error === "string") {
|
|
69
|
+
return { message: error };
|
|
70
|
+
}
|
|
71
|
+
if (typeof error === "object") {
|
|
72
|
+
const candidate = error;
|
|
73
|
+
const message = typeof candidate.message === "string" ? candidate.message : JSON.stringify(candidate);
|
|
74
|
+
const stack = typeof candidate.stack === "string" ? candidate.stack : void 0;
|
|
75
|
+
const name = typeof candidate.name === "string" ? candidate.name : void 0;
|
|
76
|
+
const cause = candidate.cause;
|
|
77
|
+
return { message, stack, name, cause };
|
|
78
|
+
}
|
|
79
|
+
if (typeof error === "number" || typeof error === "boolean" || typeof error === "bigint" || typeof error === "symbol") {
|
|
80
|
+
return { message: String(error) };
|
|
81
|
+
}
|
|
82
|
+
return { message: "Unknown error" };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/runtime/workflow/services.js
|
|
86
|
+
var SystemTimeService = class {
|
|
87
|
+
wait(ms) {
|
|
88
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
89
|
+
}
|
|
90
|
+
now() {
|
|
91
|
+
return /* @__PURE__ */ new Date();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
var DefaultBackgroundRunner = class {
|
|
95
|
+
constructor(logger = new ConsoleWorkflowLogger()) {
|
|
96
|
+
this.logger = logger;
|
|
97
|
+
}
|
|
98
|
+
dispatch(taskName, payload) {
|
|
99
|
+
this.logger.info("Dispatch background task", {
|
|
100
|
+
eventId: "workflow.background.dispatch",
|
|
101
|
+
taskName,
|
|
102
|
+
payload
|
|
103
|
+
});
|
|
104
|
+
return Promise.resolve();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
var InMemoryWorkflowStore = class {
|
|
108
|
+
constructor() {
|
|
109
|
+
this.instances = /* @__PURE__ */ new Map();
|
|
110
|
+
}
|
|
111
|
+
save(instance) {
|
|
112
|
+
this.instances.set(instance.id, {
|
|
113
|
+
...instance,
|
|
114
|
+
history: [...instance.history],
|
|
115
|
+
state: { ...instance.state }
|
|
116
|
+
});
|
|
117
|
+
return Promise.resolve();
|
|
118
|
+
}
|
|
119
|
+
load(id) {
|
|
120
|
+
const record = this.instances.get(id);
|
|
121
|
+
if (!record) {
|
|
122
|
+
return Promise.resolve(null);
|
|
123
|
+
}
|
|
124
|
+
return Promise.resolve({
|
|
125
|
+
...record,
|
|
126
|
+
history: [...record.history],
|
|
127
|
+
state: { ...record.state }
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
var InMemorySchedulerService = class {
|
|
132
|
+
constructor(background = new DefaultBackgroundRunner(), time = new SystemTimeService(), logger = new ConsoleWorkflowLogger(), trace) {
|
|
133
|
+
this.background = background;
|
|
134
|
+
this.time = time;
|
|
135
|
+
this.logger = logger;
|
|
136
|
+
this.trace = trace;
|
|
137
|
+
}
|
|
138
|
+
async schedule(request, context) {
|
|
139
|
+
const delay = computeDelay(request, this.time.now());
|
|
140
|
+
if (delay > 0) {
|
|
141
|
+
await this.time.wait(delay);
|
|
142
|
+
}
|
|
143
|
+
await this.background.dispatch(request.taskName, request.payload);
|
|
144
|
+
this.logger.info("Scheduled workflow task dispatched", {
|
|
145
|
+
eventId: "workflow.scheduler.dispatch",
|
|
146
|
+
taskName: request.taskName,
|
|
147
|
+
runAt: request.runAt?.toISOString(),
|
|
148
|
+
delayMs: delay,
|
|
149
|
+
workflowId: context.definition.name,
|
|
150
|
+
stepId: context.step.id,
|
|
151
|
+
runId: context.runId,
|
|
152
|
+
workflowVersion: context.definition.version
|
|
153
|
+
});
|
|
154
|
+
const sink = context.trace ?? this.trace;
|
|
155
|
+
if (sink) {
|
|
156
|
+
void sink.record({
|
|
157
|
+
type: "workflow.scheduler.dispatched",
|
|
158
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
159
|
+
workflowId: context.definition.name,
|
|
160
|
+
workflowVersion: context.definition.version,
|
|
161
|
+
instanceId: context.instanceId,
|
|
162
|
+
stepId: context.step.id,
|
|
163
|
+
runId: context.runId,
|
|
164
|
+
delayMs: delay,
|
|
165
|
+
attributes: { taskName: request.taskName }
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
var InMemoryDatabaseRegistry = class {
|
|
171
|
+
constructor() {
|
|
172
|
+
this.providers = /* @__PURE__ */ new Map();
|
|
173
|
+
}
|
|
174
|
+
register(provider) {
|
|
175
|
+
this.providers.set(provider.name, provider);
|
|
176
|
+
}
|
|
177
|
+
get(name) {
|
|
178
|
+
return this.providers.get(name);
|
|
179
|
+
}
|
|
180
|
+
list() {
|
|
181
|
+
return [...this.providers.keys()];
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
var DefaultApprovalResolver = class {
|
|
185
|
+
resolve(gate, context) {
|
|
186
|
+
if (!gate.requiredRoles && !gate.approvers) {
|
|
187
|
+
return Promise.resolve({ status: "approved", decidedAt: /* @__PURE__ */ new Date(), decidedBy: context.actor?.id });
|
|
188
|
+
}
|
|
189
|
+
const actor = context.actor;
|
|
190
|
+
if (!actor) {
|
|
191
|
+
return Promise.resolve({ status: "pending" });
|
|
192
|
+
}
|
|
193
|
+
const roleMatch = gate.requiredRoles?.every((role) => actor.roles?.includes(role)) ?? true;
|
|
194
|
+
const approverMatch = gate.approvers ? gate.approvers.includes(actor.id) : true;
|
|
195
|
+
if (roleMatch && approverMatch) {
|
|
196
|
+
return Promise.resolve({ status: "approved", decidedAt: /* @__PURE__ */ new Date(), decidedBy: actor.id });
|
|
197
|
+
}
|
|
198
|
+
return Promise.resolve({ status: "pending" });
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
var ConsoleWorkflowLogger = class extends ConsoleLogger {
|
|
202
|
+
constructor() {
|
|
203
|
+
super("workflow");
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
function computeDelay(request, now) {
|
|
207
|
+
if (request.runAt) {
|
|
208
|
+
return Math.max(0, request.runAt.getTime() - now.getTime());
|
|
209
|
+
}
|
|
210
|
+
if (typeof request.delayMs === "number") {
|
|
211
|
+
return Math.max(0, request.delayMs);
|
|
212
|
+
}
|
|
213
|
+
return 0;
|
|
214
|
+
}
|
|
215
|
+
var NoopWorkflowTraceSink = class {
|
|
216
|
+
record() {
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
var ConsoleWorkflowTraceSink = class {
|
|
220
|
+
constructor(logger = new ConsoleWorkflowLogger()) {
|
|
221
|
+
this.logger = logger;
|
|
222
|
+
}
|
|
223
|
+
record(event) {
|
|
224
|
+
const timestamp = event.timestamp instanceof Date ? event.timestamp : new Date(event.timestamp);
|
|
225
|
+
this.logger.info("Workflow trace event", {
|
|
226
|
+
eventId: event.type,
|
|
227
|
+
workflowId: event.workflowId,
|
|
228
|
+
workflowVersion: event.workflowVersion,
|
|
229
|
+
instanceId: event.instanceId,
|
|
230
|
+
stepId: event.stepId,
|
|
231
|
+
runId: event.runId,
|
|
232
|
+
attempt: event.attempt,
|
|
233
|
+
gateId: event.gateId,
|
|
234
|
+
approvalStatus: event.approvalStatus,
|
|
235
|
+
durationMs: event.durationMs,
|
|
236
|
+
delayMs: event.delayMs,
|
|
237
|
+
attributes: event.attributes,
|
|
238
|
+
timestamp: timestamp.toISOString()
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
var RecordingWorkflowTraceSink = class {
|
|
243
|
+
constructor() {
|
|
244
|
+
this.events = [];
|
|
245
|
+
}
|
|
246
|
+
record(event) {
|
|
247
|
+
this.events.push(event);
|
|
248
|
+
}
|
|
249
|
+
getEvents() {
|
|
250
|
+
return [...this.events];
|
|
251
|
+
}
|
|
252
|
+
toJSON() {
|
|
253
|
+
return this.getEvents();
|
|
254
|
+
}
|
|
255
|
+
clear() {
|
|
256
|
+
this.events.length = 0;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
var FileWorkflowTraceSink = class {
|
|
260
|
+
constructor(filePath, writer = fs.promises) {
|
|
261
|
+
this.exporter = new chunkSM35JOYD_cjs.JsonlTraceExporter({ filePath, writer });
|
|
262
|
+
}
|
|
263
|
+
record(event) {
|
|
264
|
+
return this.exporter.export(buildWorkflowTracePayload(event));
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
var WorkflowTraceExporterSink = class {
|
|
268
|
+
constructor(exporter) {
|
|
269
|
+
this.exporter = exporter;
|
|
270
|
+
}
|
|
271
|
+
record(event) {
|
|
272
|
+
return this.exporter.export(buildWorkflowTracePayload(event));
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
function buildWorkflowTracePayload(event) {
|
|
276
|
+
const timestamp = event.timestamp instanceof Date ? event.timestamp : new Date(event.timestamp);
|
|
277
|
+
return {
|
|
278
|
+
type: event.type,
|
|
279
|
+
timestamp,
|
|
280
|
+
attributes: compact({
|
|
281
|
+
workflowId: event.workflowId,
|
|
282
|
+
workflowVersion: event.workflowVersion,
|
|
283
|
+
instanceId: event.instanceId,
|
|
284
|
+
stepId: event.stepId,
|
|
285
|
+
runId: event.runId,
|
|
286
|
+
attempt: event.attempt,
|
|
287
|
+
gateId: event.gateId,
|
|
288
|
+
approvalStatus: event.approvalStatus,
|
|
289
|
+
durationMs: event.durationMs,
|
|
290
|
+
delayMs: event.delayMs,
|
|
291
|
+
actorId: event.actorId,
|
|
292
|
+
...event.attributes
|
|
293
|
+
})
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
function compact(record) {
|
|
297
|
+
if (!record) {
|
|
298
|
+
return void 0;
|
|
299
|
+
}
|
|
300
|
+
const entries = Object.entries(record).filter(([, value]) => typeof value !== "undefined");
|
|
301
|
+
if (entries.length === 0) {
|
|
302
|
+
return void 0;
|
|
303
|
+
}
|
|
304
|
+
return Object.fromEntries(entries);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/runtime/workflow/runtime.js
|
|
308
|
+
var WorkflowRuntime = class {
|
|
309
|
+
constructor(options) {
|
|
310
|
+
this.options = options;
|
|
311
|
+
this.tasks = /* @__PURE__ */ new Map();
|
|
312
|
+
this.logger = options.logger ?? new ConsoleWorkflowLogger();
|
|
313
|
+
this.trace = options.traceSink ?? new NoopWorkflowTraceSink();
|
|
314
|
+
const time = options.services?.time ?? new SystemTimeService();
|
|
315
|
+
const background = options.services?.background ?? new DefaultBackgroundRunner(this.logger);
|
|
316
|
+
const scheduler = options.services?.scheduler ?? new InMemorySchedulerService(background, time, this.logger, this.trace);
|
|
317
|
+
this.services = {
|
|
318
|
+
background,
|
|
319
|
+
http: options.services?.http,
|
|
320
|
+
databases: options.services?.databases,
|
|
321
|
+
time,
|
|
322
|
+
scheduler,
|
|
323
|
+
trace: this.trace
|
|
324
|
+
};
|
|
325
|
+
this.idGenerator = options.idGenerator ?? (() => {
|
|
326
|
+
const globalCrypto = globalThis.crypto;
|
|
327
|
+
if (globalCrypto?.randomUUID) {
|
|
328
|
+
return globalCrypto.randomUUID();
|
|
329
|
+
}
|
|
330
|
+
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;
|
|
331
|
+
});
|
|
332
|
+
this.approvalResolver = options.approvalResolver ?? new DefaultApprovalResolver();
|
|
333
|
+
if (options.tasks) {
|
|
334
|
+
for (const [name, handler] of Object.entries(options.tasks)) {
|
|
335
|
+
this.registerTask(name, handler);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
registerTask(name, handler) {
|
|
340
|
+
this.tasks.set(name, handler);
|
|
341
|
+
}
|
|
342
|
+
hasTask(name) {
|
|
343
|
+
return this.tasks.has(name);
|
|
344
|
+
}
|
|
345
|
+
listTasks() {
|
|
346
|
+
return [...this.tasks.keys()];
|
|
347
|
+
}
|
|
348
|
+
async run(definition, request = {}) {
|
|
349
|
+
const state = { ...request.state ?? {} };
|
|
350
|
+
const instance = {
|
|
351
|
+
id: request.instanceId ?? this.idGenerator(),
|
|
352
|
+
workflowId: definition.name,
|
|
353
|
+
version: definition.version,
|
|
354
|
+
status: "running",
|
|
355
|
+
currentStep: definition.entry,
|
|
356
|
+
state,
|
|
357
|
+
actor: request.actor,
|
|
358
|
+
metadata: request.metadata ?? definition.metadata,
|
|
359
|
+
history: [],
|
|
360
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
361
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
362
|
+
};
|
|
363
|
+
await this.options.store.save(instance);
|
|
364
|
+
this.emitTrace({
|
|
365
|
+
type: "workflow.run.started",
|
|
366
|
+
workflowId: definition.name,
|
|
367
|
+
workflowVersion: definition.version,
|
|
368
|
+
instanceId: instance.id,
|
|
369
|
+
actorId: instance.actor?.id
|
|
370
|
+
});
|
|
371
|
+
let currentStepId = definition.entry;
|
|
372
|
+
while (currentStepId) {
|
|
373
|
+
const step = currentStepId ? definition.steps[currentStepId] : void 0;
|
|
374
|
+
if (!step) {
|
|
375
|
+
throw new Error(`Unknown step '${currentStepId}' in workflow '${definition.name}'`);
|
|
376
|
+
}
|
|
377
|
+
instance.currentStep = step.id;
|
|
378
|
+
const approval = await this.ensureApprovals(step, instance);
|
|
379
|
+
const approvalDecision = approval?.decision;
|
|
380
|
+
if (approvalDecision?.status === "pending") {
|
|
381
|
+
instance.status = "waiting";
|
|
382
|
+
await this.persist(instance);
|
|
383
|
+
this.emitTrace({
|
|
384
|
+
type: "workflow.run.waiting",
|
|
385
|
+
workflowId: definition.name,
|
|
386
|
+
workflowVersion: definition.version,
|
|
387
|
+
instanceId: instance.id,
|
|
388
|
+
stepId: step.id,
|
|
389
|
+
attributes: { reason: "approval-pending", gateId: approval?.gateId }
|
|
390
|
+
});
|
|
391
|
+
return { instance, status: "waiting" };
|
|
392
|
+
}
|
|
393
|
+
if (approvalDecision?.status === "rejected") {
|
|
394
|
+
instance.status = "failed";
|
|
395
|
+
instance.history.push(this.buildHistoryEntry(step, "failure", 0, approvalDecision.reason ?? "Approval rejected"));
|
|
396
|
+
await this.persist(instance);
|
|
397
|
+
this.emitTrace({
|
|
398
|
+
type: "workflow.run.failed",
|
|
399
|
+
workflowId: definition.name,
|
|
400
|
+
workflowVersion: definition.version,
|
|
401
|
+
instanceId: instance.id,
|
|
402
|
+
stepId: step.id,
|
|
403
|
+
attributes: { reason: "approval-rejected", gateId: approval?.gateId }
|
|
404
|
+
});
|
|
405
|
+
return { instance, status: "failed" };
|
|
406
|
+
}
|
|
407
|
+
const { result, attempts } = await this.executeStep(definition, step, state, instance);
|
|
408
|
+
instance.history.push(this.buildHistoryEntry(step, result.status, attempts, typeof result.error === "string" ? result.error : void 0));
|
|
409
|
+
instance.state = state;
|
|
410
|
+
instance.updatedAt = /* @__PURE__ */ new Date();
|
|
411
|
+
if (result.status === "success") {
|
|
412
|
+
const transition = result.transition ?? step.transitions?.success;
|
|
413
|
+
if (!transition) {
|
|
414
|
+
instance.status = "completed";
|
|
415
|
+
await this.persist(instance);
|
|
416
|
+
this.emitTrace({
|
|
417
|
+
type: "workflow.run.completed",
|
|
418
|
+
workflowId: definition.name,
|
|
419
|
+
workflowVersion: definition.version,
|
|
420
|
+
instanceId: instance.id
|
|
421
|
+
});
|
|
422
|
+
return { instance, status: "completed", output: state };
|
|
423
|
+
}
|
|
424
|
+
currentStepId = transition;
|
|
425
|
+
} else {
|
|
426
|
+
const transition = step.transitions?.failure;
|
|
427
|
+
if (transition) {
|
|
428
|
+
currentStepId = transition;
|
|
429
|
+
} else {
|
|
430
|
+
instance.status = "failed";
|
|
431
|
+
await this.persist(instance);
|
|
432
|
+
this.emitTrace({
|
|
433
|
+
type: "workflow.run.failed",
|
|
434
|
+
workflowId: definition.name,
|
|
435
|
+
workflowVersion: definition.version,
|
|
436
|
+
instanceId: instance.id,
|
|
437
|
+
stepId: step.id
|
|
438
|
+
});
|
|
439
|
+
return { instance, status: "failed" };
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
instance.status = "completed";
|
|
444
|
+
await this.persist(instance);
|
|
445
|
+
this.emitTrace({
|
|
446
|
+
type: "workflow.run.completed",
|
|
447
|
+
workflowId: definition.name,
|
|
448
|
+
workflowVersion: definition.version,
|
|
449
|
+
instanceId: instance.id
|
|
450
|
+
});
|
|
451
|
+
return { instance, status: "completed", output: state };
|
|
452
|
+
}
|
|
453
|
+
async executeStep(definition, step, state, instance) {
|
|
454
|
+
const handler = this.resolveTask(step.task);
|
|
455
|
+
const retryPolicy = this.normalizeRetry(step.retry);
|
|
456
|
+
const services = this.services;
|
|
457
|
+
const logger = this.logger;
|
|
458
|
+
let attempt = 0;
|
|
459
|
+
while (attempt < retryPolicy.maxAttempts) {
|
|
460
|
+
attempt += 1;
|
|
461
|
+
const context = {
|
|
462
|
+
runId: this.idGenerator(),
|
|
463
|
+
instanceId: instance.id,
|
|
464
|
+
definition,
|
|
465
|
+
step,
|
|
466
|
+
input: step.task.input,
|
|
467
|
+
state,
|
|
468
|
+
actor: instance.actor,
|
|
469
|
+
services,
|
|
470
|
+
logger,
|
|
471
|
+
trace: this.trace
|
|
472
|
+
};
|
|
473
|
+
const stepStart = /* @__PURE__ */ new Date();
|
|
474
|
+
this.emitTrace({
|
|
475
|
+
type: "workflow.step.started",
|
|
476
|
+
workflowId: definition.name,
|
|
477
|
+
workflowVersion: definition.version,
|
|
478
|
+
instanceId: instance.id,
|
|
479
|
+
stepId: step.id,
|
|
480
|
+
runId: context.runId,
|
|
481
|
+
attempt
|
|
482
|
+
});
|
|
483
|
+
try {
|
|
484
|
+
const result = await handler(context);
|
|
485
|
+
if (result.data) {
|
|
486
|
+
Object.assign(state, result.data);
|
|
487
|
+
}
|
|
488
|
+
if (result.status === "success") {
|
|
489
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
490
|
+
this.emitTrace({
|
|
491
|
+
type: "workflow.step.completed",
|
|
492
|
+
workflowId: definition.name,
|
|
493
|
+
workflowVersion: definition.version,
|
|
494
|
+
instanceId: instance.id,
|
|
495
|
+
stepId: step.id,
|
|
496
|
+
runId: context.runId,
|
|
497
|
+
attempt,
|
|
498
|
+
durationMs: finishedAt.getTime() - stepStart.getTime(),
|
|
499
|
+
attributes: result.data
|
|
500
|
+
});
|
|
501
|
+
return { result, attempts: attempt };
|
|
502
|
+
}
|
|
503
|
+
this.emitTrace({
|
|
504
|
+
type: "workflow.step.failed",
|
|
505
|
+
workflowId: definition.name,
|
|
506
|
+
workflowVersion: definition.version,
|
|
507
|
+
instanceId: instance.id,
|
|
508
|
+
stepId: step.id,
|
|
509
|
+
runId: context.runId,
|
|
510
|
+
attempt,
|
|
511
|
+
attributes: { reason: "handler-result", transition: result.transition }
|
|
512
|
+
});
|
|
513
|
+
if (attempt < retryPolicy.maxAttempts) {
|
|
514
|
+
const waitTime = await this.waitForRetry(attempt, retryPolicy.delayMs, retryPolicy.backoff);
|
|
515
|
+
this.emitTrace({
|
|
516
|
+
type: "workflow.step.retry",
|
|
517
|
+
workflowId: definition.name,
|
|
518
|
+
workflowVersion: definition.version,
|
|
519
|
+
instanceId: instance.id,
|
|
520
|
+
stepId: step.id,
|
|
521
|
+
runId: context.runId,
|
|
522
|
+
attempt,
|
|
523
|
+
delayMs: waitTime
|
|
524
|
+
});
|
|
525
|
+
continue;
|
|
526
|
+
}
|
|
527
|
+
return { result, attempts: attempt };
|
|
528
|
+
} catch (error) {
|
|
529
|
+
logger.error("Workflow step execution failed", {
|
|
530
|
+
eventId: "workflow.step.failed",
|
|
531
|
+
workflowId: definition.name,
|
|
532
|
+
workflowVersion: definition.version,
|
|
533
|
+
stepId: step.id,
|
|
534
|
+
runId: context.runId,
|
|
535
|
+
attempt,
|
|
536
|
+
error
|
|
537
|
+
});
|
|
538
|
+
this.emitTrace({
|
|
539
|
+
type: "workflow.step.failed",
|
|
540
|
+
workflowId: definition.name,
|
|
541
|
+
workflowVersion: definition.version,
|
|
542
|
+
instanceId: instance.id,
|
|
543
|
+
stepId: step.id,
|
|
544
|
+
runId: context.runId,
|
|
545
|
+
attempt,
|
|
546
|
+
attributes: {
|
|
547
|
+
reason: "exception",
|
|
548
|
+
message: error instanceof Error ? error.message : String(error)
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
if (attempt >= retryPolicy.maxAttempts) {
|
|
552
|
+
return {
|
|
553
|
+
result: { status: "failure", error },
|
|
554
|
+
attempts: attempt
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
const waitTime = await this.waitForRetry(attempt, retryPolicy.delayMs, retryPolicy.backoff);
|
|
558
|
+
this.emitTrace({
|
|
559
|
+
type: "workflow.step.retry",
|
|
560
|
+
workflowId: definition.name,
|
|
561
|
+
workflowVersion: definition.version,
|
|
562
|
+
instanceId: instance.id,
|
|
563
|
+
stepId: step.id,
|
|
564
|
+
runId: context.runId,
|
|
565
|
+
attempt,
|
|
566
|
+
delayMs: waitTime
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return { result: { status: "failure", error: "Unknown failure" }, attempts: attempt };
|
|
571
|
+
}
|
|
572
|
+
normalizeRetry(retry) {
|
|
573
|
+
return {
|
|
574
|
+
maxAttempts: Math.max(1, retry?.maxAttempts ?? 1),
|
|
575
|
+
delayMs: retry?.delayMs ?? 0,
|
|
576
|
+
backoff: retry?.backoff ?? "fixed"
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
resolveTask(task2) {
|
|
580
|
+
const handler = this.tasks.get(task2.handler);
|
|
581
|
+
if (!handler) {
|
|
582
|
+
throw new Error(`Task handler '${task2.handler}' has not been registered`);
|
|
583
|
+
}
|
|
584
|
+
return handler;
|
|
585
|
+
}
|
|
586
|
+
buildHistoryEntry(step, status, attempt, notes) {
|
|
587
|
+
return {
|
|
588
|
+
stepId: step.id,
|
|
589
|
+
status,
|
|
590
|
+
attempt,
|
|
591
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
592
|
+
notes
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
async ensureApprovals(step, instance) {
|
|
596
|
+
if (!step.approvals || step.approvals.length === 0) {
|
|
597
|
+
return void 0;
|
|
598
|
+
}
|
|
599
|
+
for (const gate of step.approvals) {
|
|
600
|
+
this.emitTrace({
|
|
601
|
+
type: "workflow.approval.requested",
|
|
602
|
+
workflowId: instance.workflowId,
|
|
603
|
+
workflowVersion: instance.version,
|
|
604
|
+
instanceId: instance.id,
|
|
605
|
+
stepId: step.id,
|
|
606
|
+
gateId: gate.id,
|
|
607
|
+
actorId: instance.actor?.id
|
|
608
|
+
});
|
|
609
|
+
const decision = await this.approvalResolver.resolve(gate, {
|
|
610
|
+
actor: instance.actor,
|
|
611
|
+
instance,
|
|
612
|
+
step
|
|
613
|
+
});
|
|
614
|
+
this.emitTrace({
|
|
615
|
+
type: "workflow.approval.resolved",
|
|
616
|
+
workflowId: instance.workflowId,
|
|
617
|
+
workflowVersion: instance.version,
|
|
618
|
+
instanceId: instance.id,
|
|
619
|
+
stepId: step.id,
|
|
620
|
+
gateId: gate.id,
|
|
621
|
+
approvalStatus: decision.status,
|
|
622
|
+
actorId: decision.decidedBy ?? instance.actor?.id
|
|
623
|
+
});
|
|
624
|
+
if (decision.status !== "approved") {
|
|
625
|
+
return { decision, gateId: gate.id };
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return void 0;
|
|
629
|
+
}
|
|
630
|
+
async waitForRetry(attempt, delayMs, backoff) {
|
|
631
|
+
if (delayMs <= 0 || !this.services.time) {
|
|
632
|
+
return 0;
|
|
633
|
+
}
|
|
634
|
+
let waitTime = delayMs;
|
|
635
|
+
if (backoff === "exponential") {
|
|
636
|
+
waitTime = delayMs * 2 ** (attempt - 1);
|
|
637
|
+
} else if (backoff === "jitter") {
|
|
638
|
+
const base = delayMs * 2 ** (attempt - 1);
|
|
639
|
+
waitTime = Math.floor(Math.random() * base);
|
|
640
|
+
}
|
|
641
|
+
await this.services.time.wait(waitTime);
|
|
642
|
+
return waitTime;
|
|
643
|
+
}
|
|
644
|
+
async persist(instance) {
|
|
645
|
+
await this.options.store.save(instance);
|
|
646
|
+
}
|
|
647
|
+
emitTrace(event) {
|
|
648
|
+
void this.trace.record({
|
|
649
|
+
...event,
|
|
650
|
+
timestamp: event.timestamp ?? /* @__PURE__ */ new Date()
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
// src/runtime/workflow/dsl.js
|
|
656
|
+
function createWorkflow(name, configure, options = {}) {
|
|
657
|
+
const builder = new WorkflowBuilder(name, options.version ?? "1.0.0");
|
|
658
|
+
if (options.entry) {
|
|
659
|
+
builder.entry(options.entry);
|
|
660
|
+
}
|
|
661
|
+
if (options.metadata) {
|
|
662
|
+
builder.metadata(options.metadata);
|
|
663
|
+
}
|
|
664
|
+
configure(builder);
|
|
665
|
+
return builder.build();
|
|
666
|
+
}
|
|
667
|
+
var WorkflowBuilder = class {
|
|
668
|
+
constructor(workflowName, versionValue) {
|
|
669
|
+
this.workflowName = workflowName;
|
|
670
|
+
this.versionValue = versionValue;
|
|
671
|
+
this.steps = /* @__PURE__ */ new Map();
|
|
672
|
+
}
|
|
673
|
+
version(value) {
|
|
674
|
+
this.versionValue = value;
|
|
675
|
+
return this;
|
|
676
|
+
}
|
|
677
|
+
entry(stepId) {
|
|
678
|
+
this.entryStep = stepId;
|
|
679
|
+
return this;
|
|
680
|
+
}
|
|
681
|
+
metadata(data) {
|
|
682
|
+
this.metadataValue = { ...this.metadataValue ?? {}, ...data };
|
|
683
|
+
return this;
|
|
684
|
+
}
|
|
685
|
+
step(id, task2, configure) {
|
|
686
|
+
const definition = {
|
|
687
|
+
id,
|
|
688
|
+
task: task2
|
|
689
|
+
};
|
|
690
|
+
const builder = new WorkflowStepBuilder(this, definition);
|
|
691
|
+
configure?.(builder);
|
|
692
|
+
this.steps.set(id, definition);
|
|
693
|
+
if (!this.entryStep) {
|
|
694
|
+
this.entryStep = id;
|
|
695
|
+
}
|
|
696
|
+
return this;
|
|
697
|
+
}
|
|
698
|
+
build() {
|
|
699
|
+
if (!this.entryStep) {
|
|
700
|
+
throw new Error(`Workflow '${this.workflowName}' must declare at least one step`);
|
|
701
|
+
}
|
|
702
|
+
return {
|
|
703
|
+
name: this.workflowName,
|
|
704
|
+
version: this.versionValue,
|
|
705
|
+
entry: this.entryStep,
|
|
706
|
+
steps: Object.fromEntries(this.steps),
|
|
707
|
+
metadata: this.metadataValue
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
var WorkflowStepBuilder = class {
|
|
712
|
+
constructor(parent, definition) {
|
|
713
|
+
this.parent = parent;
|
|
714
|
+
this.definition = definition;
|
|
715
|
+
}
|
|
716
|
+
onSuccess(stepId) {
|
|
717
|
+
this.definition.transitions = { ...this.definition.transitions ?? {}, success: stepId };
|
|
718
|
+
return this;
|
|
719
|
+
}
|
|
720
|
+
onFailure(stepId) {
|
|
721
|
+
this.definition.transitions = { ...this.definition.transitions ?? {}, failure: stepId };
|
|
722
|
+
return this;
|
|
723
|
+
}
|
|
724
|
+
withRetry(policy) {
|
|
725
|
+
this.definition.retry = { ...policy };
|
|
726
|
+
return this;
|
|
727
|
+
}
|
|
728
|
+
withApproval(gate) {
|
|
729
|
+
this.definition.approvals = [...this.definition.approvals ?? [], gate];
|
|
730
|
+
return this;
|
|
731
|
+
}
|
|
732
|
+
metadata(data) {
|
|
733
|
+
this.definition.metadata = { ...this.definition.metadata ?? {}, ...data };
|
|
734
|
+
return this;
|
|
735
|
+
}
|
|
736
|
+
end() {
|
|
737
|
+
return this.parent;
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
function task(handler, input) {
|
|
741
|
+
return { handler, input };
|
|
742
|
+
}
|
|
743
|
+
function workflowFromJson(json) {
|
|
744
|
+
if (!json.name || !json.entry || !json.version) {
|
|
745
|
+
throw new Error("Invalid workflow definition JSON payload");
|
|
746
|
+
}
|
|
747
|
+
return {
|
|
748
|
+
name: json.name,
|
|
749
|
+
version: json.version,
|
|
750
|
+
entry: json.entry,
|
|
751
|
+
steps: json.steps,
|
|
752
|
+
metadata: json.metadata
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// src/runtime/workflow/tasks.js
|
|
757
|
+
var HTTP_TASK = "workflow.http.request";
|
|
758
|
+
var DATABASE_TASK = "workflow.database.execute";
|
|
759
|
+
var DELAY_TASK = "workflow.time.delay";
|
|
760
|
+
var SCHEDULE_TASK = "workflow.background.schedule";
|
|
761
|
+
function httpTask(options) {
|
|
762
|
+
return { handler: HTTP_TASK, input: options };
|
|
763
|
+
}
|
|
764
|
+
function databaseTask(options) {
|
|
765
|
+
return { handler: DATABASE_TASK, input: options };
|
|
766
|
+
}
|
|
767
|
+
function delayTask(options) {
|
|
768
|
+
return { handler: DELAY_TASK, input: options };
|
|
769
|
+
}
|
|
770
|
+
function scheduleTask(options) {
|
|
771
|
+
return { handler: SCHEDULE_TASK, input: options };
|
|
772
|
+
}
|
|
773
|
+
function createDefaultTaskMap(executor) {
|
|
774
|
+
return {
|
|
775
|
+
[HTTP_TASK]: createHttpTaskHandler(executor),
|
|
776
|
+
[DATABASE_TASK]: createDatabaseTaskHandler(),
|
|
777
|
+
[DELAY_TASK]: createDelayTaskHandler(),
|
|
778
|
+
[SCHEDULE_TASK]: createScheduleTaskHandler()
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
function createHttpTaskHandler(fallback) {
|
|
782
|
+
return async (context) => {
|
|
783
|
+
if (!context.input) {
|
|
784
|
+
throw new Error("HTTP task requires an input payload");
|
|
785
|
+
}
|
|
786
|
+
const optionsCandidate = context.input;
|
|
787
|
+
if (!optionsCandidate.url || typeof optionsCandidate.url !== "string") {
|
|
788
|
+
throw new Error("HTTP task requires a `url` property");
|
|
789
|
+
}
|
|
790
|
+
const options = optionsCandidate;
|
|
791
|
+
const executor = context.services.http ?? fallback ?? createFetchHttpExecutor();
|
|
792
|
+
const response = await executor(options, context);
|
|
793
|
+
const isSuccess = response.status >= 200 && response.status < 300;
|
|
794
|
+
const payloadKey = options.assignResponseTo;
|
|
795
|
+
const data = payloadKey ? { [payloadKey]: response.body ?? response } : void 0;
|
|
796
|
+
return {
|
|
797
|
+
status: isSuccess ? "success" : "failure",
|
|
798
|
+
data,
|
|
799
|
+
error: isSuccess ? void 0 : { status: response.status, body: response.body }
|
|
800
|
+
};
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
function createDatabaseTaskHandler() {
|
|
804
|
+
return async (context) => {
|
|
805
|
+
if (!context.input) {
|
|
806
|
+
throw new Error("Database task requires input payload");
|
|
807
|
+
}
|
|
808
|
+
const partialInput = context.input;
|
|
809
|
+
if (!partialInput.provider) {
|
|
810
|
+
throw new Error("Database task input missing `provider`");
|
|
811
|
+
}
|
|
812
|
+
if (!partialInput.operation) {
|
|
813
|
+
throw new Error("Database task input missing `operation` details");
|
|
814
|
+
}
|
|
815
|
+
const options = partialInput;
|
|
816
|
+
const registry = context.services.databases;
|
|
817
|
+
if (!registry) {
|
|
818
|
+
throw new Error("No database registry injected into workflow services");
|
|
819
|
+
}
|
|
820
|
+
const provider = registry.get(options.provider);
|
|
821
|
+
if (!provider) {
|
|
822
|
+
throw new Error(`Database provider '${options.provider}' was not registered`);
|
|
823
|
+
}
|
|
824
|
+
const result = await provider.execute(options.operation, { actor: context.actor });
|
|
825
|
+
const data = options.assignResultTo ? { [options.assignResultTo]: result } : void 0;
|
|
826
|
+
return { status: "success", data };
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
function createDelayTaskHandler() {
|
|
830
|
+
return async (context) => {
|
|
831
|
+
const options = context.input ? context.input : {};
|
|
832
|
+
const delayMs = normalizeDelay(options);
|
|
833
|
+
if (delayMs <= 0) {
|
|
834
|
+
return { status: "success" };
|
|
835
|
+
}
|
|
836
|
+
if (context.services.time) {
|
|
837
|
+
await context.services.time.wait(delayMs);
|
|
838
|
+
} else {
|
|
839
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
840
|
+
}
|
|
841
|
+
return { status: "success" };
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
function createScheduleTaskHandler() {
|
|
845
|
+
return async (context) => {
|
|
846
|
+
if (!context.input) {
|
|
847
|
+
throw new Error("Schedule task requires an input payload");
|
|
848
|
+
}
|
|
849
|
+
const options = context.input;
|
|
850
|
+
if (!options.taskName) {
|
|
851
|
+
throw new Error("Schedule task requires a taskName");
|
|
852
|
+
}
|
|
853
|
+
const scheduleRequest = {
|
|
854
|
+
taskName: options.taskName,
|
|
855
|
+
payload: options.payload,
|
|
856
|
+
description: options.description,
|
|
857
|
+
runAt: options.runAt ? new Date(options.runAt) : void 0,
|
|
858
|
+
delayMs: options.delayMs
|
|
859
|
+
};
|
|
860
|
+
if (context.services.scheduler) {
|
|
861
|
+
await context.services.scheduler.schedule(scheduleRequest, context);
|
|
862
|
+
return { status: "success" };
|
|
863
|
+
}
|
|
864
|
+
const delayMs = scheduleRequest.runAt ? Math.max(0, scheduleRequest.runAt.getTime() - Date.now()) : Math.max(0, scheduleRequest.delayMs ?? 0);
|
|
865
|
+
if (delayMs > 0) {
|
|
866
|
+
if (context.services.time) {
|
|
867
|
+
await context.services.time.wait(delayMs);
|
|
868
|
+
} else {
|
|
869
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
if (!context.services.background) {
|
|
873
|
+
throw new Error("No background runner available to dispatch scheduled task");
|
|
874
|
+
}
|
|
875
|
+
await context.services.background.dispatch(scheduleRequest.taskName, scheduleRequest.payload);
|
|
876
|
+
return { status: "success" };
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function createFetchHttpExecutor(fetchImpl) {
|
|
880
|
+
const resolvedFetch = fetchImpl ?? globalThis.fetch;
|
|
881
|
+
if (!resolvedFetch) {
|
|
882
|
+
throw new Error("Fetch API is not available in this runtime. Provide a custom http service.");
|
|
883
|
+
}
|
|
884
|
+
return async (request, context) => {
|
|
885
|
+
const url = withQueryString(request.url, request.query);
|
|
886
|
+
const body = typeof request.body === "object" && request.body !== null ? JSON.stringify(request.body) : request.body;
|
|
887
|
+
const response = await resolvedFetch(url, {
|
|
888
|
+
method: request.method ?? "GET",
|
|
889
|
+
headers: request.headers,
|
|
890
|
+
body
|
|
891
|
+
});
|
|
892
|
+
const headers = extractHeaders(response.headers);
|
|
893
|
+
const parseMode = determineParseMode(request);
|
|
894
|
+
const payload = parseMode === "text" ? await response.text() : await safeJson(response);
|
|
895
|
+
context.logger?.debug("HTTP task executed", { url, status: response.status });
|
|
896
|
+
return {
|
|
897
|
+
status: response.status,
|
|
898
|
+
headers,
|
|
899
|
+
body: payload
|
|
900
|
+
};
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
function determineParseMode(request) {
|
|
904
|
+
return request.parse ?? "auto";
|
|
905
|
+
}
|
|
906
|
+
async function safeJson(response) {
|
|
907
|
+
try {
|
|
908
|
+
return await response.json();
|
|
909
|
+
} catch {
|
|
910
|
+
return await response.text();
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function extractHeaders(source) {
|
|
914
|
+
const result = {};
|
|
915
|
+
if (!source) {
|
|
916
|
+
return result;
|
|
917
|
+
}
|
|
918
|
+
source.forEach((value, key) => {
|
|
919
|
+
result[key] = value;
|
|
920
|
+
});
|
|
921
|
+
return result;
|
|
922
|
+
}
|
|
923
|
+
function withQueryString(url, query) {
|
|
924
|
+
if (!query || Object.keys(query).length === 0) {
|
|
925
|
+
return url;
|
|
926
|
+
}
|
|
927
|
+
const usp = new URLSearchParams();
|
|
928
|
+
for (const [key, value] of Object.entries(query)) {
|
|
929
|
+
usp.append(key, String(value));
|
|
930
|
+
}
|
|
931
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
932
|
+
return `${url}${separator}${usp.toString()}`;
|
|
933
|
+
}
|
|
934
|
+
var FunctionalDatabaseProvider = class {
|
|
935
|
+
constructor(name, executor) {
|
|
936
|
+
this.name = name;
|
|
937
|
+
this.executor = executor;
|
|
938
|
+
}
|
|
939
|
+
execute(operation, context) {
|
|
940
|
+
return this.executor(operation, context);
|
|
941
|
+
}
|
|
942
|
+
};
|
|
943
|
+
function createSqlDatabaseProvider(options) {
|
|
944
|
+
return new FunctionalDatabaseProvider(options.name, (operation) => {
|
|
945
|
+
if (!operation.text) {
|
|
946
|
+
throw new Error("SQL operations require the `text` property");
|
|
947
|
+
}
|
|
948
|
+
return options.query(operation.text, operation.parameters);
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
function createMySqlProvider(client, name = "mysql") {
|
|
952
|
+
return createSqlDatabaseProvider({
|
|
953
|
+
name,
|
|
954
|
+
query: (sql, params) => client.query(sql, params)
|
|
955
|
+
});
|
|
956
|
+
}
|
|
957
|
+
function createPostgresProvider(client, name = "postgres") {
|
|
958
|
+
return createSqlDatabaseProvider({
|
|
959
|
+
name,
|
|
960
|
+
query: (sql, params) => client.query(sql, params)
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
function createSqliteProvider(client, name = "sqlite") {
|
|
964
|
+
return createSqlDatabaseProvider({
|
|
965
|
+
name,
|
|
966
|
+
query: (sql, params) => client.run(sql, params)
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
function createMongoProvider(options) {
|
|
970
|
+
return new FunctionalDatabaseProvider(options.name ?? "mongodb", (op) => {
|
|
971
|
+
if (!op.collection) {
|
|
972
|
+
throw new Error("Mongo operations require a collection name");
|
|
973
|
+
}
|
|
974
|
+
return options.run(op);
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
function registerDefaultDatabaseProviders(registry, providers) {
|
|
978
|
+
for (const provider of providers) {
|
|
979
|
+
registry.register(provider);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
function normalizeDelay(options) {
|
|
983
|
+
if (typeof options.milliseconds === "number") {
|
|
984
|
+
return Math.max(0, options.milliseconds);
|
|
985
|
+
}
|
|
986
|
+
if (typeof options.seconds === "number") {
|
|
987
|
+
return Math.max(0, options.seconds * 1e3);
|
|
988
|
+
}
|
|
989
|
+
return 0;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// src/runtime/workflow/stores/databaseStore.js
|
|
993
|
+
var DatabaseWorkflowStore = class {
|
|
994
|
+
constructor(options) {
|
|
995
|
+
this.options = options;
|
|
996
|
+
this.table = options.table ?? "workflow_instances";
|
|
997
|
+
this.dialect = options.dialect ?? "postgres";
|
|
998
|
+
}
|
|
999
|
+
async save(instance) {
|
|
1000
|
+
const nowIso = instance.updatedAt.toISOString();
|
|
1001
|
+
const params = [
|
|
1002
|
+
instance.id,
|
|
1003
|
+
instance.workflowId,
|
|
1004
|
+
instance.version,
|
|
1005
|
+
instance.status,
|
|
1006
|
+
instance.currentStep ?? null,
|
|
1007
|
+
JSON.stringify(instance.state),
|
|
1008
|
+
instance.actor ? JSON.stringify(instance.actor) : null,
|
|
1009
|
+
instance.metadata ? JSON.stringify(instance.metadata) : null,
|
|
1010
|
+
JSON.stringify(instance.history),
|
|
1011
|
+
instance.createdAt.toISOString(),
|
|
1012
|
+
nowIso
|
|
1013
|
+
];
|
|
1014
|
+
const sql = buildUpsertStatement(this.table, this.dialect);
|
|
1015
|
+
await this.options.provider.execute({ type: "command", text: sql, parameters: params });
|
|
1016
|
+
}
|
|
1017
|
+
async load(id) {
|
|
1018
|
+
const sql = `SELECT id, workflow_id, version, status, current_step, state_json, actor_json, metadata_json, history_json, created_at, updated_at FROM ${this.table} WHERE id = ${buildPlaceholder(1, this.dialect)}`;
|
|
1019
|
+
const result = await this.options.provider.execute({
|
|
1020
|
+
type: "query",
|
|
1021
|
+
text: sql,
|
|
1022
|
+
parameters: [id]
|
|
1023
|
+
});
|
|
1024
|
+
if (!result || result.length === 0) {
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
1027
|
+
return mapRowToInstance(result[0]);
|
|
1028
|
+
}
|
|
1029
|
+
};
|
|
1030
|
+
function buildUpsertStatement(table, dialect) {
|
|
1031
|
+
const columns = "(id, workflow_id, version, status, current_step, state_json, actor_json, metadata_json, history_json, created_at, updated_at)";
|
|
1032
|
+
const values = buildInsertValues(11, dialect);
|
|
1033
|
+
const base = `INSERT INTO ${table} ${columns} VALUES ${values}`;
|
|
1034
|
+
if (dialect === "postgres") {
|
|
1035
|
+
return `${base} ON CONFLICT (id) DO UPDATE SET workflow_id = EXCLUDED.workflow_id, version = EXCLUDED.version, status = EXCLUDED.status, current_step = EXCLUDED.current_step, state_json = EXCLUDED.state_json, actor_json = EXCLUDED.actor_json, metadata_json = EXCLUDED.metadata_json, history_json = EXCLUDED.history_json, updated_at = EXCLUDED.updated_at`;
|
|
1036
|
+
}
|
|
1037
|
+
if (dialect === "sqlite") {
|
|
1038
|
+
return `${base} ON CONFLICT(id) DO UPDATE SET workflow_id = excluded.workflow_id, version = excluded.version, status = excluded.status, current_step = excluded.current_step, state_json = excluded.state_json, actor_json = excluded.actor_json, metadata_json = excluded.metadata_json, history_json = excluded.history_json, updated_at = excluded.updated_at`;
|
|
1039
|
+
}
|
|
1040
|
+
return `${base} ON DUPLICATE KEY UPDATE workflow_id = VALUES(workflow_id), version = VALUES(version), status = VALUES(status), current_step = VALUES(current_step), state_json = VALUES(state_json), actor_json = VALUES(actor_json), metadata_json = VALUES(metadata_json), history_json = VALUES(history_json), updated_at = VALUES(updated_at)`;
|
|
1041
|
+
}
|
|
1042
|
+
function buildInsertValues(count, dialect) {
|
|
1043
|
+
if (dialect === "postgres") {
|
|
1044
|
+
const placeholders2 = Array.from({ length: count }, (_, index) => `$${String(index + 1)}`).join(", ");
|
|
1045
|
+
return `(${placeholders2})`;
|
|
1046
|
+
}
|
|
1047
|
+
const placeholders = Array.from({ length: count }, () => "?").join(", ");
|
|
1048
|
+
return `(${placeholders})`;
|
|
1049
|
+
}
|
|
1050
|
+
function buildPlaceholder(position, dialect) {
|
|
1051
|
+
return dialect === "postgres" ? `$${String(position)}` : "?";
|
|
1052
|
+
}
|
|
1053
|
+
function mapRowToInstance(row) {
|
|
1054
|
+
return {
|
|
1055
|
+
id: row.id,
|
|
1056
|
+
workflowId: row.workflow_id,
|
|
1057
|
+
version: row.version,
|
|
1058
|
+
status: row.status,
|
|
1059
|
+
currentStep: row.current_step ?? void 0,
|
|
1060
|
+
state: parseJson(row.state_json, {}),
|
|
1061
|
+
actor: parseJson(row.actor_json, void 0),
|
|
1062
|
+
metadata: parseJson(row.metadata_json, void 0),
|
|
1063
|
+
history: parseJson(row.history_json, []),
|
|
1064
|
+
createdAt: new Date(row.created_at),
|
|
1065
|
+
updatedAt: new Date(row.updated_at)
|
|
1066
|
+
};
|
|
1067
|
+
}
|
|
1068
|
+
function parseJson(value, fallback) {
|
|
1069
|
+
if (!value) {
|
|
1070
|
+
return fallback;
|
|
1071
|
+
}
|
|
1072
|
+
try {
|
|
1073
|
+
return JSON.parse(value);
|
|
1074
|
+
} catch {
|
|
1075
|
+
return fallback;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// src/runtime/workflow/stores/mongoStore.js
|
|
1080
|
+
var MongoWorkflowStore = class {
|
|
1081
|
+
constructor(options) {
|
|
1082
|
+
this.options = options;
|
|
1083
|
+
if (this.options.createIndexes) {
|
|
1084
|
+
void this.ensureIndexes();
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
async save(instance) {
|
|
1088
|
+
const document = serializeInstance(instance);
|
|
1089
|
+
await this.options.collection.updateOne({ _id: document._id }, {
|
|
1090
|
+
$set: {
|
|
1091
|
+
workflowId: document.workflowId,
|
|
1092
|
+
version: document.version,
|
|
1093
|
+
status: document.status,
|
|
1094
|
+
currentStep: document.currentStep,
|
|
1095
|
+
state: document.state,
|
|
1096
|
+
actor: document.actor,
|
|
1097
|
+
metadata: document.metadata,
|
|
1098
|
+
history: document.history,
|
|
1099
|
+
createdAt: document.createdAt,
|
|
1100
|
+
updatedAt: document.updatedAt
|
|
1101
|
+
}
|
|
1102
|
+
}, { upsert: true });
|
|
1103
|
+
}
|
|
1104
|
+
async load(id) {
|
|
1105
|
+
const doc = await this.options.collection.findOne({ _id: id });
|
|
1106
|
+
if (!doc) {
|
|
1107
|
+
return null;
|
|
1108
|
+
}
|
|
1109
|
+
return deserializeDocument(doc);
|
|
1110
|
+
}
|
|
1111
|
+
async ensureIndexes() {
|
|
1112
|
+
if (!this.options.collection.createIndex) {
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
await Promise.all([
|
|
1116
|
+
this.options.collection.createIndex({ workflowId: 1, updatedAt: -1 }),
|
|
1117
|
+
this.options.collection.createIndex({ status: 1, updatedAt: -1 })
|
|
1118
|
+
]);
|
|
1119
|
+
}
|
|
1120
|
+
};
|
|
1121
|
+
function serializeInstance(instance) {
|
|
1122
|
+
return {
|
|
1123
|
+
_id: instance.id,
|
|
1124
|
+
workflowId: instance.workflowId,
|
|
1125
|
+
version: instance.version,
|
|
1126
|
+
status: instance.status,
|
|
1127
|
+
currentStep: instance.currentStep,
|
|
1128
|
+
state: instance.state,
|
|
1129
|
+
actor: instance.actor,
|
|
1130
|
+
metadata: instance.metadata,
|
|
1131
|
+
history: instance.history.map((entry) => ({
|
|
1132
|
+
stepId: entry.stepId,
|
|
1133
|
+
status: entry.status,
|
|
1134
|
+
attempt: entry.attempt,
|
|
1135
|
+
timestamp: entry.timestamp.toISOString(),
|
|
1136
|
+
notes: entry.notes
|
|
1137
|
+
})),
|
|
1138
|
+
createdAt: instance.createdAt.toISOString(),
|
|
1139
|
+
updatedAt: instance.updatedAt.toISOString()
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
function deserializeDocument(document) {
|
|
1143
|
+
return {
|
|
1144
|
+
id: document._id,
|
|
1145
|
+
workflowId: document.workflowId,
|
|
1146
|
+
version: document.version,
|
|
1147
|
+
status: document.status,
|
|
1148
|
+
currentStep: document.currentStep,
|
|
1149
|
+
state: clone(document.state),
|
|
1150
|
+
actor: document.actor ? clone(document.actor) : void 0,
|
|
1151
|
+
metadata: document.metadata ? clone(document.metadata) : void 0,
|
|
1152
|
+
history: Array.isArray(document.history) ? document.history.map((entry) => ({ ...entry, timestamp: new Date(entry.timestamp) })) : [],
|
|
1153
|
+
createdAt: new Date(document.createdAt),
|
|
1154
|
+
updatedAt: new Date(document.updatedAt)
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
function clone(value) {
|
|
1158
|
+
return JSON.parse(JSON.stringify(value));
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// src/runtime/workflow/schema.js
|
|
1162
|
+
function workflowToVisualSchema(definition) {
|
|
1163
|
+
const nodes = Object.values(definition.steps).map((step) => ({
|
|
1164
|
+
id: step.id,
|
|
1165
|
+
label: String(step.metadata?.label ?? step.id),
|
|
1166
|
+
task: step.task,
|
|
1167
|
+
approvals: step.approvals,
|
|
1168
|
+
retry: step.retry,
|
|
1169
|
+
metadata: step.metadata
|
|
1170
|
+
}));
|
|
1171
|
+
const edges = [];
|
|
1172
|
+
for (const step of Object.values(definition.steps)) {
|
|
1173
|
+
if (step.transitions?.success) {
|
|
1174
|
+
edges.push({ id: `${step.id}->${step.transitions.success}#success`, source: step.id, target: step.transitions.success, when: "success" });
|
|
1175
|
+
}
|
|
1176
|
+
if (step.transitions?.failure) {
|
|
1177
|
+
edges.push({ id: `${step.id}->${step.transitions.failure}#failure`, source: step.id, target: step.transitions.failure, when: "failure" });
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
return {
|
|
1181
|
+
id: `${definition.name}@${definition.version}`,
|
|
1182
|
+
name: definition.name,
|
|
1183
|
+
version: definition.version,
|
|
1184
|
+
entry: definition.entry,
|
|
1185
|
+
metadata: definition.metadata,
|
|
1186
|
+
nodes,
|
|
1187
|
+
edges
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
function visualSchemaToWorkflow(schema) {
|
|
1191
|
+
const steps = {};
|
|
1192
|
+
for (const node of schema.nodes) {
|
|
1193
|
+
steps[node.id] = {
|
|
1194
|
+
id: node.id,
|
|
1195
|
+
task: node.task,
|
|
1196
|
+
approvals: node.approvals,
|
|
1197
|
+
retry: node.retry,
|
|
1198
|
+
metadata: { ...node.metadata, position: node.position, size: node.size, data: node.data }
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
for (const edge of schema.edges) {
|
|
1202
|
+
if (!Object.prototype.hasOwnProperty.call(steps, edge.source)) {
|
|
1203
|
+
continue;
|
|
1204
|
+
}
|
|
1205
|
+
const step = steps[edge.source];
|
|
1206
|
+
if (!step.transitions) {
|
|
1207
|
+
step.transitions = {};
|
|
1208
|
+
}
|
|
1209
|
+
if (edge.when === "failure") {
|
|
1210
|
+
step.transitions.failure = edge.target;
|
|
1211
|
+
} else {
|
|
1212
|
+
step.transitions.success = edge.target;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
return {
|
|
1216
|
+
name: schema.name,
|
|
1217
|
+
version: schema.version,
|
|
1218
|
+
entry: schema.entry,
|
|
1219
|
+
steps,
|
|
1220
|
+
metadata: schema.metadata
|
|
1221
|
+
};
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// src/runtime/workflow/adapters/databaseAdapters.js
|
|
1225
|
+
function createPrismaProvider(options) {
|
|
1226
|
+
const query = (text, params = []) => options.client.$queryRawUnsafe(text, ...params);
|
|
1227
|
+
const execute = (text, params = []) => {
|
|
1228
|
+
if (options.client.$executeRawUnsafe) {
|
|
1229
|
+
return options.client.$executeRawUnsafe(text, ...params);
|
|
1230
|
+
}
|
|
1231
|
+
return query(text, params);
|
|
1232
|
+
};
|
|
1233
|
+
return new FunctionalDatabaseProvider(options.name ?? "prisma", (operation) => {
|
|
1234
|
+
if (!operation.text) {
|
|
1235
|
+
throw new Error("Prisma provider requires `text` SQL input");
|
|
1236
|
+
}
|
|
1237
|
+
if (operation.type === "query") {
|
|
1238
|
+
return query(operation.text, operation.parameters ?? []);
|
|
1239
|
+
}
|
|
1240
|
+
return execute(operation.text, operation.parameters ?? []);
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
function createDrizzleProvider(options) {
|
|
1244
|
+
return new FunctionalDatabaseProvider(options.name ?? "drizzle", (operation) => {
|
|
1245
|
+
if (!operation.text) {
|
|
1246
|
+
throw new Error("Drizzle provider requires `text` SQL input");
|
|
1247
|
+
}
|
|
1248
|
+
return options.client.execute(operation.text, operation.parameters);
|
|
1249
|
+
});
|
|
1250
|
+
}
|
|
1251
|
+
function createSupabaseProvider(options) {
|
|
1252
|
+
return new FunctionalDatabaseProvider(options.name ?? "supabase", async (operation) => {
|
|
1253
|
+
if (operation.collection) {
|
|
1254
|
+
const table = options.client.from(operation.collection);
|
|
1255
|
+
if (operation.type === "query") {
|
|
1256
|
+
if (typeof table.select !== "function") {
|
|
1257
|
+
throw new Error("Supabase client is missing select support");
|
|
1258
|
+
}
|
|
1259
|
+
return table.select("*");
|
|
1260
|
+
}
|
|
1261
|
+
if (operation.type === "command") {
|
|
1262
|
+
if (operation.payload && operation.payload.action === "insert") {
|
|
1263
|
+
return table.insert(operation.payload.data);
|
|
1264
|
+
}
|
|
1265
|
+
if (operation.payload && operation.payload.action === "update") {
|
|
1266
|
+
return table.update(operation.payload.data);
|
|
1267
|
+
}
|
|
1268
|
+
if (operation.payload && operation.payload.action === "delete") {
|
|
1269
|
+
return table.delete();
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
if (options.client.rpc && operation.text) {
|
|
1274
|
+
return options.client.rpc(operation.text, operation.payload);
|
|
1275
|
+
}
|
|
1276
|
+
throw new Error("Supabase provider requires `collection` or `text` with rpc support");
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
function createRestDatabaseProvider(options) {
|
|
1280
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
1281
|
+
if (!fetchImpl) {
|
|
1282
|
+
throw new Error("Fetch API is not available. Provide a custom fetch implementation.");
|
|
1283
|
+
}
|
|
1284
|
+
return new FunctionalDatabaseProvider(options.name ?? "rest-db", async (operation) => {
|
|
1285
|
+
const url = new URL(options.endpoint);
|
|
1286
|
+
if (operation.collection) {
|
|
1287
|
+
url.pathname = `${url.pathname.replace(/\/$/, "")}/${operation.collection}`;
|
|
1288
|
+
}
|
|
1289
|
+
const body = JSON.stringify(operation.payload ?? { text: operation.text, parameters: operation.parameters });
|
|
1290
|
+
const response = await fetchImpl(url, {
|
|
1291
|
+
method: "POST",
|
|
1292
|
+
headers: { "content-type": "application/json", ...options.headers ?? {} },
|
|
1293
|
+
body
|
|
1294
|
+
});
|
|
1295
|
+
if (!response.ok) {
|
|
1296
|
+
throw new Error(`REST database adapter failed with status ${String(response.status)}`);
|
|
1297
|
+
}
|
|
1298
|
+
return response.json();
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// src/runtime/workflow/background.js
|
|
1303
|
+
var QueueBackgroundRunner = class {
|
|
1304
|
+
constructor(options) {
|
|
1305
|
+
this.options = options;
|
|
1306
|
+
}
|
|
1307
|
+
async dispatch(taskName, payload) {
|
|
1308
|
+
const message = { name: taskName, payload };
|
|
1309
|
+
await this.options.driver.enqueue(message);
|
|
1310
|
+
this.options.metrics?.record("enqueued", { taskName });
|
|
1311
|
+
}
|
|
1312
|
+
async schedule(request, context) {
|
|
1313
|
+
const message = {
|
|
1314
|
+
name: request.taskName,
|
|
1315
|
+
payload: { ...request.payload, workflowId: context.definition.name, stepId: context.step.id },
|
|
1316
|
+
runAt: request.runAt
|
|
1317
|
+
};
|
|
1318
|
+
if (request.runAt && this.options.driver.schedule) {
|
|
1319
|
+
await this.options.driver.schedule(message);
|
|
1320
|
+
this.options.metrics?.record("enqueued", { taskName: request.taskName, scheduled: true });
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
if (request.delayMs && this.options.driver.schedule) {
|
|
1324
|
+
await this.options.driver.schedule({ ...message, runAt: new Date(Date.now() + request.delayMs) });
|
|
1325
|
+
this.options.metrics?.record("enqueued", { taskName: request.taskName, scheduled: true });
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
await this.dispatch(request.taskName, message.payload);
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1331
|
+
function createBullMqDriver(queue) {
|
|
1332
|
+
return {
|
|
1333
|
+
enqueue: (message) => queue.add(message.name, message.payload).then(() => void 0),
|
|
1334
|
+
schedule: (message) => queue.add(message.name, message.payload, {
|
|
1335
|
+
delay: message.runAt ? Math.max(0, message.runAt.getTime() - Date.now()) : 0
|
|
1336
|
+
}).then(() => void 0)
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
function createSqsDriver(client, queueUrl) {
|
|
1340
|
+
return {
|
|
1341
|
+
enqueue: (message) => client.sendMessage({
|
|
1342
|
+
QueueUrl: queueUrl,
|
|
1343
|
+
MessageBody: JSON.stringify(message.payload ?? {}),
|
|
1344
|
+
MessageAttributes: {
|
|
1345
|
+
name: { DataType: "String", StringValue: message.name }
|
|
1346
|
+
}
|
|
1347
|
+
}).then(() => void 0),
|
|
1348
|
+
schedule: (message) => client.sendMessage({
|
|
1349
|
+
QueueUrl: queueUrl,
|
|
1350
|
+
MessageBody: JSON.stringify(message.payload ?? {}),
|
|
1351
|
+
DelaySeconds: message.runAt ? Math.min(900, Math.max(0, Math.floor((message.runAt.getTime() - Date.now()) / 1e3))) : void 0,
|
|
1352
|
+
MessageAttributes: {
|
|
1353
|
+
name: { DataType: "String", StringValue: message.name }
|
|
1354
|
+
}
|
|
1355
|
+
}).then(() => void 0)
|
|
1356
|
+
};
|
|
1357
|
+
}
|
|
1358
|
+
function createAzureQueueDriver(client) {
|
|
1359
|
+
return {
|
|
1360
|
+
enqueue: (message) => client.sendMessage(JSON.stringify({ name: message.name, payload: message.payload })).then(() => void 0),
|
|
1361
|
+
schedule: (message) => client.sendMessage(JSON.stringify({ name: message.name, payload: message.payload }), {
|
|
1362
|
+
visibilityTimeout: message.runAt ? Math.max(0, Math.floor((message.runAt.getTime() - Date.now()) / 1e3)) : 0
|
|
1363
|
+
}).then(() => void 0)
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
1366
|
+
var MetricsConsoleEmitter = class {
|
|
1367
|
+
record(event, metadata) {
|
|
1368
|
+
console.info(`[workflow.queue] ${event}`, metadata);
|
|
1369
|
+
}
|
|
1370
|
+
};
|
|
1371
|
+
|
|
1372
|
+
// src/runtime/workflow/auth.js
|
|
1373
|
+
var PolicyApprovalResolver = class {
|
|
1374
|
+
constructor(engine, fallback) {
|
|
1375
|
+
this.engine = engine;
|
|
1376
|
+
this.fallback = fallback;
|
|
1377
|
+
}
|
|
1378
|
+
async resolve(gate, context) {
|
|
1379
|
+
const decision = await this.engine.evaluate({
|
|
1380
|
+
actor: context.actor,
|
|
1381
|
+
instance: context.instance,
|
|
1382
|
+
step: context.step,
|
|
1383
|
+
action: "approve",
|
|
1384
|
+
metadata: { gateId: gate.id }
|
|
1385
|
+
});
|
|
1386
|
+
if (decision.allow) {
|
|
1387
|
+
return { status: "approved", decidedAt: /* @__PURE__ */ new Date(), decidedBy: context.actor?.id };
|
|
1388
|
+
}
|
|
1389
|
+
if (this.fallback) {
|
|
1390
|
+
return this.fallback.resolve(gate, context);
|
|
1391
|
+
}
|
|
1392
|
+
return { status: "pending", reason: decision.reason };
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
var RuleBasedPolicyEngine = class {
|
|
1396
|
+
constructor(rules, defaultDecision = { allow: true }) {
|
|
1397
|
+
this.rules = rules;
|
|
1398
|
+
this.defaultDecision = defaultDecision;
|
|
1399
|
+
}
|
|
1400
|
+
evaluate(request) {
|
|
1401
|
+
for (const rule of this.rules) {
|
|
1402
|
+
if (rule.match(request)) {
|
|
1403
|
+
return rule.decision(request);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
return this.defaultDecision;
|
|
1407
|
+
}
|
|
1408
|
+
};
|
|
1409
|
+
function actorFromOidcClaims(claims, mapping = {}) {
|
|
1410
|
+
const typedClaims = claims;
|
|
1411
|
+
return {
|
|
1412
|
+
id: String(claims[mapping.idClaim ?? "sub"] ?? typedClaims.user_id ?? "anonymous"),
|
|
1413
|
+
roles: toStringArray(claims[mapping.rolesClaim ?? "roles"] ?? claims["https://ce/roles"]),
|
|
1414
|
+
scopes: toStringArray(claims[mapping.scopesClaim ?? "scope"]),
|
|
1415
|
+
attributes: mapping.attributeClaims?.reduce((acc, key) => {
|
|
1416
|
+
acc[key] = claims[key];
|
|
1417
|
+
return acc;
|
|
1418
|
+
}, {}),
|
|
1419
|
+
metadata: { provider: mapping.provider ?? "oidc", raw: mapping.includeRaw ? claims : void 0 }
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
function actorFromCognitoClaims(claims) {
|
|
1423
|
+
return actorFromOidcClaims(claims, {
|
|
1424
|
+
provider: "cognito",
|
|
1425
|
+
idClaim: "sub",
|
|
1426
|
+
rolesClaim: "cognito:groups",
|
|
1427
|
+
scopesClaim: "scope"
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
function actorFromAzureAdClaims(claims) {
|
|
1431
|
+
return actorFromOidcClaims(claims, {
|
|
1432
|
+
provider: "azure-ad",
|
|
1433
|
+
idClaim: "oid",
|
|
1434
|
+
rolesClaim: "roles",
|
|
1435
|
+
scopesClaim: "scp"
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
function actorFromAuth0Claims(claims) {
|
|
1439
|
+
return actorFromOidcClaims(claims, {
|
|
1440
|
+
provider: "auth0",
|
|
1441
|
+
idClaim: "sub",
|
|
1442
|
+
rolesClaim: "https://auth0/roles",
|
|
1443
|
+
scopesClaim: "scope"
|
|
1444
|
+
});
|
|
1445
|
+
}
|
|
1446
|
+
function requireActorRoles(roles) {
|
|
1447
|
+
return (request) => {
|
|
1448
|
+
const actorRoles = request.actor?.roles ?? [];
|
|
1449
|
+
const hasRoles = roles.every((role) => actorRoles.includes(role));
|
|
1450
|
+
if (!hasRoles) {
|
|
1451
|
+
throw new Error(`Actor ${request.actor?.id ?? "unknown"} missing required roles: ${roles.join(", ")}`);
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
}
|
|
1455
|
+
function requireActorScopes(scopes) {
|
|
1456
|
+
return (request) => {
|
|
1457
|
+
const actorScopes = request.actor?.scopes ?? [];
|
|
1458
|
+
const hasScopes = scopes.every((scope) => actorScopes.includes(scope));
|
|
1459
|
+
if (!hasScopes) {
|
|
1460
|
+
throw new Error(`Actor ${request.actor?.id ?? "unknown"} missing required scopes: ${scopes.join(", ")}`);
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
async function runAuthMiddleware(middleware, request) {
|
|
1465
|
+
for (const fn of middleware) {
|
|
1466
|
+
await fn(request);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
function createStartWorkflowMiddleware(sequence) {
|
|
1470
|
+
return (request) => {
|
|
1471
|
+
if (request.action !== "start") {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
return runAuthMiddleware(sequence, request);
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
function createStepMiddleware(sequence) {
|
|
1478
|
+
return (request) => {
|
|
1479
|
+
if (request.action !== "step") {
|
|
1480
|
+
return;
|
|
1481
|
+
}
|
|
1482
|
+
return runAuthMiddleware(sequence, request);
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
function multiStepApprovalResolver(resolvers) {
|
|
1486
|
+
return {
|
|
1487
|
+
async resolve(gate, context) {
|
|
1488
|
+
for (const resolver of resolvers) {
|
|
1489
|
+
const result = await resolver.resolve(gate, context);
|
|
1490
|
+
if (result.status !== "pending") {
|
|
1491
|
+
return result;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
return { status: "pending" };
|
|
1495
|
+
}
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
var ManualOverrideApprovalResolver = class {
|
|
1499
|
+
constructor(overrides) {
|
|
1500
|
+
this.overrides = overrides;
|
|
1501
|
+
}
|
|
1502
|
+
resolve(gate, context) {
|
|
1503
|
+
const key = `${context.instance.id}:${gate.id}`;
|
|
1504
|
+
return this.overrides.get(key) ?? { status: "pending" };
|
|
1505
|
+
}
|
|
1506
|
+
};
|
|
1507
|
+
function buildPolicyRequest(instance, step, actor) {
|
|
1508
|
+
return {
|
|
1509
|
+
actor,
|
|
1510
|
+
instance,
|
|
1511
|
+
step,
|
|
1512
|
+
action: "step"
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
function toStringArray(value) {
|
|
1516
|
+
if (Array.isArray(value)) {
|
|
1517
|
+
return value.map((item) => String(item));
|
|
1518
|
+
}
|
|
1519
|
+
if (typeof value === "string") {
|
|
1520
|
+
return value.split(/[\s,]+/).filter(Boolean);
|
|
1521
|
+
}
|
|
1522
|
+
return [];
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
exports.ConsoleLogger = ConsoleLogger;
|
|
1526
|
+
exports.ConsoleWorkflowLogger = ConsoleWorkflowLogger;
|
|
1527
|
+
exports.ConsoleWorkflowTraceSink = ConsoleWorkflowTraceSink;
|
|
1528
|
+
exports.DATABASE_TASK = DATABASE_TASK;
|
|
1529
|
+
exports.DELAY_TASK = DELAY_TASK;
|
|
1530
|
+
exports.DatabaseWorkflowStore = DatabaseWorkflowStore;
|
|
1531
|
+
exports.DefaultApprovalResolver = DefaultApprovalResolver;
|
|
1532
|
+
exports.DefaultBackgroundRunner = DefaultBackgroundRunner;
|
|
1533
|
+
exports.FileWorkflowTraceSink = FileWorkflowTraceSink;
|
|
1534
|
+
exports.FunctionalDatabaseProvider = FunctionalDatabaseProvider;
|
|
1535
|
+
exports.HTTP_TASK = HTTP_TASK;
|
|
1536
|
+
exports.InMemoryDatabaseRegistry = InMemoryDatabaseRegistry;
|
|
1537
|
+
exports.InMemorySchedulerService = InMemorySchedulerService;
|
|
1538
|
+
exports.InMemoryWorkflowStore = InMemoryWorkflowStore;
|
|
1539
|
+
exports.ManualOverrideApprovalResolver = ManualOverrideApprovalResolver;
|
|
1540
|
+
exports.MetricsConsoleEmitter = MetricsConsoleEmitter;
|
|
1541
|
+
exports.MongoWorkflowStore = MongoWorkflowStore;
|
|
1542
|
+
exports.NoopWorkflowTraceSink = NoopWorkflowTraceSink;
|
|
1543
|
+
exports.PolicyApprovalResolver = PolicyApprovalResolver;
|
|
1544
|
+
exports.QueueBackgroundRunner = QueueBackgroundRunner;
|
|
1545
|
+
exports.RecordingWorkflowTraceSink = RecordingWorkflowTraceSink;
|
|
1546
|
+
exports.RuleBasedPolicyEngine = RuleBasedPolicyEngine;
|
|
1547
|
+
exports.SCHEDULE_TASK = SCHEDULE_TASK;
|
|
1548
|
+
exports.SystemTimeService = SystemTimeService;
|
|
1549
|
+
exports.WorkflowBuilder = WorkflowBuilder;
|
|
1550
|
+
exports.WorkflowRuntime = WorkflowRuntime;
|
|
1551
|
+
exports.WorkflowStepBuilder = WorkflowStepBuilder;
|
|
1552
|
+
exports.WorkflowTraceExporterSink = WorkflowTraceExporterSink;
|
|
1553
|
+
exports.actorFromAuth0Claims = actorFromAuth0Claims;
|
|
1554
|
+
exports.actorFromAzureAdClaims = actorFromAzureAdClaims;
|
|
1555
|
+
exports.actorFromCognitoClaims = actorFromCognitoClaims;
|
|
1556
|
+
exports.actorFromOidcClaims = actorFromOidcClaims;
|
|
1557
|
+
exports.buildPolicyRequest = buildPolicyRequest;
|
|
1558
|
+
exports.createAzureQueueDriver = createAzureQueueDriver;
|
|
1559
|
+
exports.createBullMqDriver = createBullMqDriver;
|
|
1560
|
+
exports.createDatabaseTaskHandler = createDatabaseTaskHandler;
|
|
1561
|
+
exports.createDefaultTaskMap = createDefaultTaskMap;
|
|
1562
|
+
exports.createDelayTaskHandler = createDelayTaskHandler;
|
|
1563
|
+
exports.createDrizzleProvider = createDrizzleProvider;
|
|
1564
|
+
exports.createFetchHttpExecutor = createFetchHttpExecutor;
|
|
1565
|
+
exports.createHttpTaskHandler = createHttpTaskHandler;
|
|
1566
|
+
exports.createMongoProvider = createMongoProvider;
|
|
1567
|
+
exports.createMySqlProvider = createMySqlProvider;
|
|
1568
|
+
exports.createPostgresProvider = createPostgresProvider;
|
|
1569
|
+
exports.createPrismaProvider = createPrismaProvider;
|
|
1570
|
+
exports.createRestDatabaseProvider = createRestDatabaseProvider;
|
|
1571
|
+
exports.createScheduleTaskHandler = createScheduleTaskHandler;
|
|
1572
|
+
exports.createSqlDatabaseProvider = createSqlDatabaseProvider;
|
|
1573
|
+
exports.createSqliteProvider = createSqliteProvider;
|
|
1574
|
+
exports.createSqsDriver = createSqsDriver;
|
|
1575
|
+
exports.createStartWorkflowMiddleware = createStartWorkflowMiddleware;
|
|
1576
|
+
exports.createStepMiddleware = createStepMiddleware;
|
|
1577
|
+
exports.createSupabaseProvider = createSupabaseProvider;
|
|
1578
|
+
exports.createWorkflow = createWorkflow;
|
|
1579
|
+
exports.databaseTask = databaseTask;
|
|
1580
|
+
exports.delayTask = delayTask;
|
|
1581
|
+
exports.httpTask = httpTask;
|
|
1582
|
+
exports.multiStepApprovalResolver = multiStepApprovalResolver;
|
|
1583
|
+
exports.registerDefaultDatabaseProviders = registerDefaultDatabaseProviders;
|
|
1584
|
+
exports.requireActorRoles = requireActorRoles;
|
|
1585
|
+
exports.requireActorScopes = requireActorScopes;
|
|
1586
|
+
exports.runAuthMiddleware = runAuthMiddleware;
|
|
1587
|
+
exports.scheduleTask = scheduleTask;
|
|
1588
|
+
exports.task = task;
|
|
1589
|
+
exports.visualSchemaToWorkflow = visualSchemaToWorkflow;
|
|
1590
|
+
exports.workflowFromJson = workflowFromJson;
|
|
1591
|
+
exports.workflowToVisualSchema = workflowToVisualSchema;
|
|
1592
|
+
//# sourceMappingURL=chunk-FNXIYAET.cjs.map
|
|
1593
|
+
//# sourceMappingURL=chunk-FNXIYAET.cjs.map
|