@incodetech/core 2.0.0-alpha.1 → 2.0.0-alpha.10
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/Manager-BGfxEmyv.d.ts +19 -0
- package/dist/OpenViduLogger-BdPfiZO6.esm.js +3 -0
- package/dist/OpenViduLogger-CQyDxBvM.esm.js +803 -0
- package/dist/StateMachine-DRE1oH2B.d.ts +2 -0
- package/dist/addEvent-W0ORK0jT.esm.js +16 -0
- package/dist/chunk-C_Yo44FK.esm.js +49 -0
- package/dist/email.d.ts +264 -0
- package/dist/email.esm.js +479 -0
- package/dist/endpoints-BSTFaHYo.esm.js +1706 -0
- package/dist/flow.d.ts +578 -0
- package/dist/flow.esm.js +628 -0
- package/dist/index.d.ts +226 -0
- package/dist/index.esm.js +155 -0
- package/dist/lib-Bu9XGMBW.esm.js +11700 -0
- package/dist/permissionServices-I6vX6DBy.esm.js +72 -0
- package/dist/phone.d.ts +292 -0
- package/dist/phone.esm.js +550 -0
- package/dist/selfie.d.ts +759 -0
- package/dist/selfie.esm.js +995 -0
- package/dist/types-iZi2rawo.d.ts +5 -0
- package/dist/warmup-CEJTfxQr.d.ts +55 -0
- package/dist/xstate.esm-B_rda9yU.esm.js +3261 -0
- package/package.json +14 -11
- package/src/camera/cameraActor.ts +0 -21
- package/src/camera/cameraService.test.ts +0 -437
- package/src/camera/cameraService.ts +0 -165
- package/src/camera/cameraServices.test.ts +0 -66
- package/src/camera/cameraServices.ts +0 -26
- package/src/camera/cameraStateMachine.test.ts +0 -602
- package/src/camera/cameraStateMachine.ts +0 -264
- package/src/camera/index.ts +0 -5
- package/src/camera/types.ts +0 -17
- package/src/device/getBrowser.ts +0 -31
- package/src/device/getDeviceClass.ts +0 -29
- package/src/device/index.ts +0 -2
- package/src/email/__mocks__/emailMocks.ts +0 -59
- package/src/email/emailActor.ts +0 -15
- package/src/email/emailManager.test.ts +0 -573
- package/src/email/emailManager.ts +0 -427
- package/src/email/emailServices.ts +0 -66
- package/src/email/emailStateMachine.test.ts +0 -741
- package/src/email/emailStateMachine.ts +0 -367
- package/src/email/index.ts +0 -39
- package/src/email/types.ts +0 -60
- package/src/events/addEvent.ts +0 -20
- package/src/events/types.ts +0 -7
- package/src/flow/__mocks__/flowMocks.ts +0 -84
- package/src/flow/flowActor.ts +0 -13
- package/src/flow/flowAnalyzer.test.ts +0 -266
- package/src/flow/flowAnalyzer.ts +0 -37
- package/src/flow/flowCompletionService.ts +0 -21
- package/src/flow/flowManager.test.ts +0 -560
- package/src/flow/flowManager.ts +0 -235
- package/src/flow/flowServices.test.ts +0 -109
- package/src/flow/flowServices.ts +0 -13
- package/src/flow/flowStateMachine.test.ts +0 -334
- package/src/flow/flowStateMachine.ts +0 -182
- package/src/flow/index.ts +0 -21
- package/src/flow/moduleLoader.test.ts +0 -136
- package/src/flow/moduleLoader.ts +0 -73
- package/src/flow/orchestratedFlowManager.test.ts +0 -240
- package/src/flow/orchestratedFlowManager.ts +0 -231
- package/src/flow/orchestratedFlowStateMachine.test.ts +0 -199
- package/src/flow/orchestratedFlowStateMachine.ts +0 -325
- package/src/flow/types.ts +0 -434
- package/src/http/__mocks__/api.ts +0 -88
- package/src/http/api.test.ts +0 -231
- package/src/http/api.ts +0 -90
- package/src/http/endpoints.ts +0 -17
- package/src/index.ts +0 -33
- package/src/permissions/index.ts +0 -2
- package/src/permissions/permissionServices.ts +0 -31
- package/src/permissions/types.ts +0 -3
- package/src/phone/__mocks__/phoneMocks.ts +0 -71
- package/src/phone/index.ts +0 -39
- package/src/phone/phoneActor.ts +0 -15
- package/src/phone/phoneManager.test.ts +0 -393
- package/src/phone/phoneManager.ts +0 -458
- package/src/phone/phoneServices.ts +0 -98
- package/src/phone/phoneStateMachine.test.ts +0 -918
- package/src/phone/phoneStateMachine.ts +0 -422
- package/src/phone/types.ts +0 -83
- package/src/recordings/recordingsRepository.test.ts +0 -87
- package/src/recordings/recordingsRepository.ts +0 -48
- package/src/recordings/streamingEvents.ts +0 -10
- package/src/selfie/__mocks__/selfieMocks.ts +0 -26
- package/src/selfie/index.ts +0 -14
- package/src/selfie/selfieActor.ts +0 -17
- package/src/selfie/selfieErrorUtils.test.ts +0 -116
- package/src/selfie/selfieErrorUtils.ts +0 -66
- package/src/selfie/selfieManager.test.ts +0 -297
- package/src/selfie/selfieManager.ts +0 -301
- package/src/selfie/selfieServices.ts +0 -362
- package/src/selfie/selfieStateMachine.test.ts +0 -283
- package/src/selfie/selfieStateMachine.ts +0 -804
- package/src/selfie/selfieUploadService.test.ts +0 -90
- package/src/selfie/selfieUploadService.ts +0 -81
- package/src/selfie/types.ts +0 -103
- package/src/session/index.ts +0 -5
- package/src/session/sessionService.ts +0 -78
- package/src/setup.test.ts +0 -61
- package/src/setup.ts +0 -171
- package/tsconfig.json +0 -13
- package/tsdown.config.ts +0 -22
- package/vitest.config.ts +0 -37
- package/vitest.setup.ts +0 -135
package/dist/flow.esm.js
ADDED
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
import { g as createManager, n as api, t as endpoints } from "./endpoints-BSTFaHYo.esm.js";
|
|
2
|
+
import { a as createActor, i as fromPromise, n as assign, r as fromCallback, t as setup } from "./xstate.esm-B_rda9yU.esm.js";
|
|
3
|
+
|
|
4
|
+
//#region src/modules/flow/flowAnalyzer.ts
|
|
5
|
+
const WASM_MODULE_PIPELINES = {
|
|
6
|
+
SELFIE: "selfie",
|
|
7
|
+
AUTHENTICATION: "selfie",
|
|
8
|
+
FACE_MATCH: "selfie",
|
|
9
|
+
VIDEO_ONBOARDING: "selfie",
|
|
10
|
+
ID: "idCapture",
|
|
11
|
+
TUTORIAL_ID: "idCapture",
|
|
12
|
+
SECOND_ID: "idCapture",
|
|
13
|
+
THIRD_ID: "idCapture"
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Analyzes a flow configuration and returns the WASM pipelines needed.
|
|
17
|
+
* Use this to conditionally warmup WASM only when required by the flow.
|
|
18
|
+
*
|
|
19
|
+
* @param flow - The flow configuration from /omni/onboarding/flow
|
|
20
|
+
* @returns Array of WASM pipelines needed (e.g., ['selfie', 'idCapture'])
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const pipelines = getRequiredWasmPipelines(flow);
|
|
25
|
+
* if (pipelines.length > 0) {
|
|
26
|
+
* warmupWasm({ ...wasmConfig, pipelines });
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
function getRequiredWasmPipelines(flow) {
|
|
31
|
+
const pipelines = /* @__PURE__ */ new Set();
|
|
32
|
+
for (const module of flow.flowModules) {
|
|
33
|
+
const pipeline = WASM_MODULE_PIPELINES[module.key];
|
|
34
|
+
if (pipeline) pipelines.add(pipeline);
|
|
35
|
+
}
|
|
36
|
+
return [...pipelines];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/modules/flow/flowServices.ts
|
|
41
|
+
const getFlow = async (signal) => {
|
|
42
|
+
const res = await api.get(endpoints.flow, { signal });
|
|
43
|
+
if (!res.ok) throw new Error(`GET /flow failed: ${res.status} ${res.statusText}`);
|
|
44
|
+
return res.data;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/modules/flow/flowStateMachine.ts
|
|
49
|
+
const flowMachine = setup({
|
|
50
|
+
types: {
|
|
51
|
+
context: {},
|
|
52
|
+
events: {},
|
|
53
|
+
input: {}
|
|
54
|
+
},
|
|
55
|
+
actors: { fetchFlow: fromPromise(async ({ input, signal }) => {
|
|
56
|
+
return input.getFlow(signal);
|
|
57
|
+
}) },
|
|
58
|
+
actions: {
|
|
59
|
+
resetContext: assign(({ context }) => ({
|
|
60
|
+
flow: void 0,
|
|
61
|
+
error: void 0,
|
|
62
|
+
steps: [],
|
|
63
|
+
currentStepIndex: -1,
|
|
64
|
+
currentStep: void 0,
|
|
65
|
+
config: void 0,
|
|
66
|
+
getFlow: context.getFlow
|
|
67
|
+
})),
|
|
68
|
+
setFlowData: assign(({ event }) => {
|
|
69
|
+
const flow = event.output;
|
|
70
|
+
return {
|
|
71
|
+
flow,
|
|
72
|
+
steps: (flow.flowModules ?? []).map((m) => m.key),
|
|
73
|
+
currentStepIndex: (flow.flowModules ?? []).length > 0 ? 0 : -1,
|
|
74
|
+
currentStep: flow.flowModules?.[0]?.key,
|
|
75
|
+
config: flow.flowModules?.[0]?.configuration
|
|
76
|
+
};
|
|
77
|
+
}),
|
|
78
|
+
setError: assign(({ event }) => ({ error: String(event.error) })),
|
|
79
|
+
incrementStep: assign(({ context }) => {
|
|
80
|
+
const nextIndex = context.currentStepIndex + 1;
|
|
81
|
+
const module = context.flow?.flowModules?.[nextIndex];
|
|
82
|
+
return {
|
|
83
|
+
currentStepIndex: nextIndex,
|
|
84
|
+
currentStep: module?.key,
|
|
85
|
+
config: module?.configuration
|
|
86
|
+
};
|
|
87
|
+
}),
|
|
88
|
+
decrementStep: assign(({ context }) => {
|
|
89
|
+
const prevIndex = context.currentStepIndex - 1;
|
|
90
|
+
const module = context.flow?.flowModules?.[prevIndex];
|
|
91
|
+
return {
|
|
92
|
+
currentStepIndex: prevIndex,
|
|
93
|
+
currentStep: module?.key,
|
|
94
|
+
config: module?.configuration
|
|
95
|
+
};
|
|
96
|
+
})
|
|
97
|
+
},
|
|
98
|
+
guards: {
|
|
99
|
+
isLastStep: ({ context }) => context.currentStepIndex >= 0 && context.currentStepIndex === context.steps.length - 1,
|
|
100
|
+
canGoNext: ({ context }) => context.currentStepIndex >= 0 && context.currentStepIndex < context.steps.length - 1,
|
|
101
|
+
canGoPrev: ({ context }) => context.currentStepIndex > 0
|
|
102
|
+
}
|
|
103
|
+
}).createMachine({
|
|
104
|
+
id: "flow",
|
|
105
|
+
initial: "idle",
|
|
106
|
+
context: ({ input }) => ({
|
|
107
|
+
flow: void 0,
|
|
108
|
+
error: void 0,
|
|
109
|
+
steps: [],
|
|
110
|
+
currentStepIndex: -1,
|
|
111
|
+
currentStep: void 0,
|
|
112
|
+
config: void 0,
|
|
113
|
+
getFlow: input.getFlow
|
|
114
|
+
}),
|
|
115
|
+
states: {
|
|
116
|
+
idle: { on: { LOAD: {
|
|
117
|
+
target: "loading",
|
|
118
|
+
actions: "resetContext"
|
|
119
|
+
} } },
|
|
120
|
+
loading: {
|
|
121
|
+
invoke: {
|
|
122
|
+
id: "fetchFlow",
|
|
123
|
+
src: "fetchFlow",
|
|
124
|
+
input: ({ context }) => ({ getFlow: context.getFlow }),
|
|
125
|
+
onDone: {
|
|
126
|
+
target: "ready",
|
|
127
|
+
actions: "setFlowData"
|
|
128
|
+
},
|
|
129
|
+
onError: {
|
|
130
|
+
target: "error",
|
|
131
|
+
actions: "setError"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
on: { CANCEL: {
|
|
135
|
+
target: "idle",
|
|
136
|
+
actions: "resetContext"
|
|
137
|
+
} }
|
|
138
|
+
},
|
|
139
|
+
ready: { on: {
|
|
140
|
+
NEXT_STEP: [{
|
|
141
|
+
target: "finished",
|
|
142
|
+
guard: "isLastStep"
|
|
143
|
+
}, {
|
|
144
|
+
target: "ready",
|
|
145
|
+
guard: "canGoNext",
|
|
146
|
+
actions: "incrementStep"
|
|
147
|
+
}],
|
|
148
|
+
PREV_STEP: {
|
|
149
|
+
target: "ready",
|
|
150
|
+
guard: "canGoPrev",
|
|
151
|
+
actions: "decrementStep"
|
|
152
|
+
},
|
|
153
|
+
RESET: {
|
|
154
|
+
target: "idle",
|
|
155
|
+
actions: "resetContext"
|
|
156
|
+
}
|
|
157
|
+
} },
|
|
158
|
+
finished: { on: { RESET: {
|
|
159
|
+
target: "idle",
|
|
160
|
+
actions: "resetContext"
|
|
161
|
+
} } },
|
|
162
|
+
error: { on: { RESET: {
|
|
163
|
+
target: "idle",
|
|
164
|
+
actions: "resetContext"
|
|
165
|
+
} } }
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
//#endregion
|
|
170
|
+
//#region src/modules/flow/flowActor.ts
|
|
171
|
+
function createFlowActor(options) {
|
|
172
|
+
return createActor(flowMachine, { input: { getFlow: options?.getFlow ?? getFlow } }).start();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
//#endregion
|
|
176
|
+
//#region src/modules/flow/flowManager.ts
|
|
177
|
+
function mapState$1(snapshot) {
|
|
178
|
+
const { value, context } = snapshot;
|
|
179
|
+
switch (value) {
|
|
180
|
+
case "idle": return { status: "idle" };
|
|
181
|
+
case "loading": return { status: "loading" };
|
|
182
|
+
case "ready": return {
|
|
183
|
+
status: "ready",
|
|
184
|
+
flow: context.flow ?? {},
|
|
185
|
+
steps: context.steps,
|
|
186
|
+
currentStepIndex: context.currentStepIndex,
|
|
187
|
+
currentStep: context.currentStep,
|
|
188
|
+
config: context.config
|
|
189
|
+
};
|
|
190
|
+
case "finished": return {
|
|
191
|
+
status: "finished",
|
|
192
|
+
flow: context.flow ?? {}
|
|
193
|
+
};
|
|
194
|
+
case "error": return {
|
|
195
|
+
status: "error",
|
|
196
|
+
error: context.error ?? "Unknown error"
|
|
197
|
+
};
|
|
198
|
+
default: return { status: "idle" };
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function createApi$1({ actor, getSnapshot }) {
|
|
202
|
+
function getCanNext() {
|
|
203
|
+
const snapshot = getSnapshot();
|
|
204
|
+
const { currentStepIndex, steps } = snapshot.context;
|
|
205
|
+
return snapshot.matches("ready") && currentStepIndex >= 0 && currentStepIndex < steps.length - 1;
|
|
206
|
+
}
|
|
207
|
+
function getCanPrev() {
|
|
208
|
+
const snapshot = getSnapshot();
|
|
209
|
+
return snapshot.matches("ready") && snapshot.context.currentStepIndex > 0;
|
|
210
|
+
}
|
|
211
|
+
function getModuleConfig(moduleKey) {
|
|
212
|
+
const snapshot = getSnapshot();
|
|
213
|
+
if (!snapshot.matches("ready")) return;
|
|
214
|
+
return (snapshot.context.flow?.flowModules.find((m) => m.key === moduleKey))?.configuration;
|
|
215
|
+
}
|
|
216
|
+
function isModuleEnabled(moduleKey) {
|
|
217
|
+
const snapshot = getSnapshot();
|
|
218
|
+
if (!snapshot.matches("ready")) return false;
|
|
219
|
+
return !!snapshot.context.flow?.flowModules.some((m) => m.key === moduleKey);
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
load() {
|
|
223
|
+
actor.send({ type: "LOAD" });
|
|
224
|
+
},
|
|
225
|
+
cancel() {
|
|
226
|
+
actor.send({ type: "CANCEL" });
|
|
227
|
+
},
|
|
228
|
+
reset() {
|
|
229
|
+
actor.send({ type: "RESET" });
|
|
230
|
+
},
|
|
231
|
+
nextStep() {
|
|
232
|
+
actor.send({ type: "NEXT_STEP" });
|
|
233
|
+
},
|
|
234
|
+
prevStep() {
|
|
235
|
+
actor.send({ type: "PREV_STEP" });
|
|
236
|
+
},
|
|
237
|
+
get canNext() {
|
|
238
|
+
return getCanNext();
|
|
239
|
+
},
|
|
240
|
+
get canPrev() {
|
|
241
|
+
return getCanPrev();
|
|
242
|
+
},
|
|
243
|
+
getModuleConfig,
|
|
244
|
+
isModuleEnabled
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Creates a flow manager instance for managing onboarding flow state and navigation.
|
|
249
|
+
*
|
|
250
|
+
* The flow manager provides:
|
|
251
|
+
* - State management with statuses: `idle`, `loading`, `ready`, `finished`, `error`
|
|
252
|
+
* - Step navigation with `nextStep()` and `prevStep()`
|
|
253
|
+
* - Current step info via `state.currentStep` and `state.config` when in `ready` state
|
|
254
|
+
* - Module configuration lookup via `getModuleConfig()`
|
|
255
|
+
*
|
|
256
|
+
* @param options - Optional configuration for the flow actor
|
|
257
|
+
* @param options.getFlow - Custom function to fetch flow data. Defaults to `getOnboardingFlow`
|
|
258
|
+
* @returns A manager instance with state subscription, API methods, and lifecycle controls
|
|
259
|
+
*
|
|
260
|
+
* @example
|
|
261
|
+
* ```ts
|
|
262
|
+
* const flowManager = createFlowManager();
|
|
263
|
+
*
|
|
264
|
+
* flowManager.subscribe((state) => {
|
|
265
|
+
* if (state.status === 'ready') {
|
|
266
|
+
* console.log(state.currentStep, state.config);
|
|
267
|
+
* }
|
|
268
|
+
* });
|
|
269
|
+
*
|
|
270
|
+
* flowManager.load({ token: 'session-token' });
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
function createFlowManager(options) {
|
|
274
|
+
return createManager({
|
|
275
|
+
actor: createFlowActor(options),
|
|
276
|
+
mapState: mapState$1,
|
|
277
|
+
createApi: createApi$1
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
//#endregion
|
|
282
|
+
//#region src/modules/flow/moduleLoader.ts
|
|
283
|
+
var ModuleLoaderImpl = class {
|
|
284
|
+
constructor(registry) {
|
|
285
|
+
this.registry = registry;
|
|
286
|
+
this.loadedModules = /* @__PURE__ */ new Map();
|
|
287
|
+
this.prefetchedModules = /* @__PURE__ */ new Set();
|
|
288
|
+
}
|
|
289
|
+
async load(moduleKey) {
|
|
290
|
+
if (!this.registry[moduleKey]) throw new Error(`Module ${moduleKey} not found in registry`);
|
|
291
|
+
const cached = this.loadedModules.get(moduleKey);
|
|
292
|
+
if (cached) return await cached;
|
|
293
|
+
const loadPromise = this.registry[moduleKey]().then((module) => {
|
|
294
|
+
if (module && typeof module === "object" && "default" in module) return module.default;
|
|
295
|
+
return module;
|
|
296
|
+
});
|
|
297
|
+
this.loadedModules.set(moduleKey, loadPromise);
|
|
298
|
+
try {
|
|
299
|
+
return await loadPromise;
|
|
300
|
+
} catch (error) {
|
|
301
|
+
this.loadedModules.delete(moduleKey);
|
|
302
|
+
throw error;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
prefetch(moduleKey) {
|
|
306
|
+
if (!this.registry[moduleKey]) return;
|
|
307
|
+
if (this.prefetchedModules.has(moduleKey) || this.loadedModules.has(moduleKey)) return;
|
|
308
|
+
this.prefetchedModules.add(moduleKey);
|
|
309
|
+
this.registry[moduleKey]().catch(() => {
|
|
310
|
+
this.prefetchedModules.delete(moduleKey);
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
isLoaded(moduleKey) {
|
|
314
|
+
return this.loadedModules.has(moduleKey);
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
function createModuleLoader(registry) {
|
|
318
|
+
return new ModuleLoaderImpl(registry);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
//#endregion
|
|
322
|
+
//#region src/modules/flow/flowCompletionService.ts
|
|
323
|
+
const getFinishStatus = async (flowId, signal) => {
|
|
324
|
+
const url = `/omni/finish-status${flowId ? `?flowId=${flowId}` : ""}`;
|
|
325
|
+
const res = await api.get(url, { signal });
|
|
326
|
+
if (!res.ok) throw new Error(`GET ${url} failed: ${res.status} ${res.statusText}`);
|
|
327
|
+
return res.data;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
//#endregion
|
|
331
|
+
//#region src/modules/flow/orchestratedFlowStateMachine.ts
|
|
332
|
+
const orchestratedFlowMachine = setup({
|
|
333
|
+
types: {
|
|
334
|
+
context: {},
|
|
335
|
+
events: {},
|
|
336
|
+
input: {}
|
|
337
|
+
},
|
|
338
|
+
actors: {
|
|
339
|
+
fetchFlow: fromPromise(async ({ input, signal }) => {
|
|
340
|
+
return input.getFlow(signal);
|
|
341
|
+
}),
|
|
342
|
+
notifyBackend: fromPromise(async ({ input, signal }) => {
|
|
343
|
+
return await input.getFinishStatus(input.flowId, signal);
|
|
344
|
+
}),
|
|
345
|
+
runChildModule: fromCallback(({ sendBack, input }) => {
|
|
346
|
+
const { machine, config } = input;
|
|
347
|
+
const actor = createActor(machine, { input: { config } });
|
|
348
|
+
const subscription = actor.subscribe({
|
|
349
|
+
complete: () => {
|
|
350
|
+
sendBack({ type: "MODULE_COMPLETE" });
|
|
351
|
+
},
|
|
352
|
+
error: (err) => {
|
|
353
|
+
sendBack({
|
|
354
|
+
type: "MODULE_ERROR",
|
|
355
|
+
error: err
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
actor.start();
|
|
360
|
+
return () => {
|
|
361
|
+
subscription.unsubscribe();
|
|
362
|
+
actor.stop();
|
|
363
|
+
};
|
|
364
|
+
})
|
|
365
|
+
},
|
|
366
|
+
actions: {
|
|
367
|
+
resetContext: assign(({ context }) => ({
|
|
368
|
+
flow: void 0,
|
|
369
|
+
error: void 0,
|
|
370
|
+
steps: [],
|
|
371
|
+
currentStepIndex: -1,
|
|
372
|
+
currentStep: void 0,
|
|
373
|
+
config: void 0,
|
|
374
|
+
getFlow: context.getFlow,
|
|
375
|
+
registeredModules: context.registeredModules,
|
|
376
|
+
getFinishStatus: context.getFinishStatus,
|
|
377
|
+
finishStatus: void 0
|
|
378
|
+
})),
|
|
379
|
+
setFlowData: assign(({ event }) => {
|
|
380
|
+
const flow = event.output;
|
|
381
|
+
return {
|
|
382
|
+
flow,
|
|
383
|
+
steps: (flow.flowModules ?? []).map((m) => m.key),
|
|
384
|
+
currentStepIndex: (flow.flowModules ?? []).length > 0 ? 0 : -1,
|
|
385
|
+
currentStep: flow.flowModules?.[0]?.key,
|
|
386
|
+
config: flow.flowModules?.[0]?.configuration
|
|
387
|
+
};
|
|
388
|
+
}),
|
|
389
|
+
setError: assign(({ event }) => ({ error: String(event.error) })),
|
|
390
|
+
incrementStep: assign(({ context }) => {
|
|
391
|
+
const nextIndex = context.currentStepIndex + 1;
|
|
392
|
+
const module = context.flow?.flowModules?.[nextIndex];
|
|
393
|
+
return {
|
|
394
|
+
currentStepIndex: nextIndex,
|
|
395
|
+
currentStep: module?.key,
|
|
396
|
+
config: module?.configuration
|
|
397
|
+
};
|
|
398
|
+
}),
|
|
399
|
+
setFinishStatus: assign(({ event }) => ({ finishStatus: event.output }))
|
|
400
|
+
},
|
|
401
|
+
guards: {
|
|
402
|
+
isLastStep: ({ context }) => context.currentStepIndex >= 0 && context.currentStepIndex === context.steps.length - 1,
|
|
403
|
+
canGoNext: ({ context }) => context.currentStepIndex >= 0 && context.currentStepIndex < context.steps.length - 1,
|
|
404
|
+
hasModule: ({ context, event }) => {
|
|
405
|
+
if (!("output" in event)) return false;
|
|
406
|
+
const firstModuleKey = event.output.flowModules?.[0]?.key;
|
|
407
|
+
if (!firstModuleKey) return false;
|
|
408
|
+
return context.registeredModules[firstModuleKey] != null;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}).createMachine({
|
|
412
|
+
id: "orchestratedFlow",
|
|
413
|
+
initial: "idle",
|
|
414
|
+
context: ({ input }) => ({
|
|
415
|
+
flow: void 0,
|
|
416
|
+
error: void 0,
|
|
417
|
+
steps: [],
|
|
418
|
+
currentStepIndex: -1,
|
|
419
|
+
currentStep: void 0,
|
|
420
|
+
config: void 0,
|
|
421
|
+
getFlow: input.getFlow,
|
|
422
|
+
registeredModules: input.modules,
|
|
423
|
+
getFinishStatus: input.getFinishStatus ?? getFinishStatus,
|
|
424
|
+
finishStatus: void 0
|
|
425
|
+
}),
|
|
426
|
+
states: {
|
|
427
|
+
idle: { on: { LOAD: {
|
|
428
|
+
target: "loading",
|
|
429
|
+
actions: "resetContext"
|
|
430
|
+
} } },
|
|
431
|
+
loading: {
|
|
432
|
+
invoke: {
|
|
433
|
+
id: "fetchFlow",
|
|
434
|
+
src: "fetchFlow",
|
|
435
|
+
input: ({ context }) => ({ getFlow: context.getFlow }),
|
|
436
|
+
onDone: [{
|
|
437
|
+
target: "runningModule",
|
|
438
|
+
guard: "hasModule",
|
|
439
|
+
actions: "setFlowData"
|
|
440
|
+
}, {
|
|
441
|
+
target: "error",
|
|
442
|
+
actions: assign({ error: () => "No registered module found for flow" })
|
|
443
|
+
}],
|
|
444
|
+
onError: {
|
|
445
|
+
target: "error",
|
|
446
|
+
actions: "setError"
|
|
447
|
+
}
|
|
448
|
+
},
|
|
449
|
+
on: { CANCEL: {
|
|
450
|
+
target: "idle",
|
|
451
|
+
actions: "resetContext"
|
|
452
|
+
} }
|
|
453
|
+
},
|
|
454
|
+
runningModule: {
|
|
455
|
+
invoke: {
|
|
456
|
+
id: "currentModule",
|
|
457
|
+
src: "runChildModule",
|
|
458
|
+
input: ({ context }) => {
|
|
459
|
+
if (!context.currentStep) throw new Error("No current step");
|
|
460
|
+
const machine = context.registeredModules[context.currentStep];
|
|
461
|
+
if (!machine) throw new Error(`Module ${context.currentStep} not registered`);
|
|
462
|
+
return {
|
|
463
|
+
machine,
|
|
464
|
+
config: context.config
|
|
465
|
+
};
|
|
466
|
+
},
|
|
467
|
+
onDone: [{
|
|
468
|
+
target: "completing",
|
|
469
|
+
guard: "isLastStep"
|
|
470
|
+
}, {
|
|
471
|
+
target: "runningModule",
|
|
472
|
+
actions: "incrementStep",
|
|
473
|
+
reenter: true
|
|
474
|
+
}],
|
|
475
|
+
onError: {
|
|
476
|
+
target: "error",
|
|
477
|
+
actions: "setError"
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
on: {
|
|
481
|
+
MODULE_COMPLETE: [{
|
|
482
|
+
target: "completing",
|
|
483
|
+
guard: "isLastStep"
|
|
484
|
+
}, {
|
|
485
|
+
target: "runningModule",
|
|
486
|
+
actions: "incrementStep",
|
|
487
|
+
reenter: true
|
|
488
|
+
}],
|
|
489
|
+
MODULE_ERROR: {
|
|
490
|
+
target: "error",
|
|
491
|
+
actions: assign(({ event }) => ({ error: String(event.error) }))
|
|
492
|
+
},
|
|
493
|
+
RESET: {
|
|
494
|
+
target: "idle",
|
|
495
|
+
actions: "resetContext"
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
completing: {
|
|
500
|
+
invoke: {
|
|
501
|
+
id: "notifyBackend",
|
|
502
|
+
src: "notifyBackend",
|
|
503
|
+
input: ({ context }) => ({
|
|
504
|
+
getFinishStatus: context.getFinishStatus,
|
|
505
|
+
flowId: context.flow?.flowId
|
|
506
|
+
}),
|
|
507
|
+
onDone: {
|
|
508
|
+
target: "finished",
|
|
509
|
+
actions: "setFinishStatus"
|
|
510
|
+
},
|
|
511
|
+
onError: {
|
|
512
|
+
target: "error",
|
|
513
|
+
actions: "setError"
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
on: { RESET: {
|
|
517
|
+
target: "idle",
|
|
518
|
+
actions: "resetContext"
|
|
519
|
+
} }
|
|
520
|
+
},
|
|
521
|
+
finished: { on: { RESET: {
|
|
522
|
+
target: "idle",
|
|
523
|
+
actions: "resetContext"
|
|
524
|
+
} } },
|
|
525
|
+
error: { on: { RESET: {
|
|
526
|
+
target: "idle",
|
|
527
|
+
actions: "resetContext"
|
|
528
|
+
} } }
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
//#endregion
|
|
533
|
+
//#region src/modules/flow/orchestratedFlowManager.ts
|
|
534
|
+
function mapState(snapshot) {
|
|
535
|
+
const { value, context } = snapshot;
|
|
536
|
+
switch (value) {
|
|
537
|
+
case "idle": return { status: "idle" };
|
|
538
|
+
case "loading": return { status: "loading" };
|
|
539
|
+
case "runningModule": {
|
|
540
|
+
const childSnapshot = snapshot.children.currentModule?.getSnapshot();
|
|
541
|
+
return {
|
|
542
|
+
status: "ready",
|
|
543
|
+
flow: context.flow ?? {},
|
|
544
|
+
steps: context.steps,
|
|
545
|
+
currentStepIndex: context.currentStepIndex,
|
|
546
|
+
currentStep: context.currentStep,
|
|
547
|
+
config: context.config,
|
|
548
|
+
moduleState: childSnapshot ?? null
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
case "finished": return {
|
|
552
|
+
status: "finished",
|
|
553
|
+
flow: context.flow ?? {},
|
|
554
|
+
finishStatus: context.finishStatus ?? {
|
|
555
|
+
redirectionUrl: "",
|
|
556
|
+
action: "none",
|
|
557
|
+
scoreStatus: "UNKNOWN"
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
case "error": return {
|
|
561
|
+
status: "error",
|
|
562
|
+
error: context.error ?? "Unknown error"
|
|
563
|
+
};
|
|
564
|
+
default: return { status: "idle" };
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
function createApi({ actor, getSnapshot }) {
|
|
568
|
+
function getCanNext() {
|
|
569
|
+
const snapshot = getSnapshot();
|
|
570
|
+
const { currentStepIndex, steps } = snapshot.context;
|
|
571
|
+
return snapshot.value === "runningModule" && currentStepIndex >= 0 && currentStepIndex < steps.length - 1;
|
|
572
|
+
}
|
|
573
|
+
function getModuleConfig(moduleKey) {
|
|
574
|
+
const snapshot = getSnapshot();
|
|
575
|
+
if (snapshot.value !== "runningModule") return;
|
|
576
|
+
return (snapshot.context.flow?.flowModules.find((m) => m.key === moduleKey))?.configuration;
|
|
577
|
+
}
|
|
578
|
+
function isModuleEnabled(moduleKey) {
|
|
579
|
+
const snapshot = getSnapshot();
|
|
580
|
+
if (snapshot.value !== "runningModule") return false;
|
|
581
|
+
return !!snapshot.context.flow?.flowModules.some((m) => m.key === moduleKey);
|
|
582
|
+
}
|
|
583
|
+
return {
|
|
584
|
+
load() {
|
|
585
|
+
actor.send({ type: "LOAD" });
|
|
586
|
+
},
|
|
587
|
+
cancel() {
|
|
588
|
+
actor.send({ type: "CANCEL" });
|
|
589
|
+
},
|
|
590
|
+
reset() {
|
|
591
|
+
actor.send({ type: "RESET" });
|
|
592
|
+
},
|
|
593
|
+
completeModule() {
|
|
594
|
+
actor.send({ type: "MODULE_COMPLETE" });
|
|
595
|
+
},
|
|
596
|
+
errorModule(error) {
|
|
597
|
+
actor.send({
|
|
598
|
+
type: "MODULE_ERROR",
|
|
599
|
+
error
|
|
600
|
+
});
|
|
601
|
+
},
|
|
602
|
+
send(event) {
|
|
603
|
+
actor.send(event);
|
|
604
|
+
},
|
|
605
|
+
get canNext() {
|
|
606
|
+
return getCanNext();
|
|
607
|
+
},
|
|
608
|
+
getModuleConfig,
|
|
609
|
+
isModuleEnabled
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
function createOrchestratedFlowActor(options) {
|
|
613
|
+
return createActor(orchestratedFlowMachine, { input: {
|
|
614
|
+
getFlow: options.getFlow ?? getFlow,
|
|
615
|
+
modules: options.modules,
|
|
616
|
+
getFinishStatus: options.getFinishStatus
|
|
617
|
+
} }).start();
|
|
618
|
+
}
|
|
619
|
+
function createOrchestratedFlowManager(options) {
|
|
620
|
+
return createManager({
|
|
621
|
+
actor: createOrchestratedFlowActor(options),
|
|
622
|
+
mapState,
|
|
623
|
+
createApi
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
//#endregion
|
|
628
|
+
export { createFlowManager, createModuleLoader, createOrchestratedFlowManager, getRequiredWasmPipelines };
|