slapflow 1.0.2
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 +15 -0
- package/README.md +175 -0
- package/RUNTIME-FLOW.mmd +18 -0
- package/SPEC-RU.md +448 -0
- package/SPEC.md +448 -0
- package/dist/index.cjs +2560 -0
- package/dist/index.d.cts +379 -0
- package/dist/index.d.ts +379 -0
- package/dist/index.js +2524 -0
- package/package.json +65 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
type Input = Record<string, unknown>;
|
|
2
|
+
type Props = Record<string, unknown>;
|
|
3
|
+
type Config = {
|
|
4
|
+
version?: 1;
|
|
5
|
+
strategies: Record<string, Strategy>;
|
|
6
|
+
entrypoints?: Record<string, string>;
|
|
7
|
+
};
|
|
8
|
+
type Strategy = {
|
|
9
|
+
fn: string;
|
|
10
|
+
props?: Props;
|
|
11
|
+
when?: ConditionExpression;
|
|
12
|
+
then?: Next[];
|
|
13
|
+
catch?: Next[];
|
|
14
|
+
mode?: Mode;
|
|
15
|
+
terminal?: boolean;
|
|
16
|
+
tags?: string[];
|
|
17
|
+
description?: string;
|
|
18
|
+
};
|
|
19
|
+
type Mode = 'sequence' | 'selector' | 'parallel';
|
|
20
|
+
type Next = string | {
|
|
21
|
+
id?: string;
|
|
22
|
+
strategy: string;
|
|
23
|
+
props?: Props;
|
|
24
|
+
when?: ConditionExpression;
|
|
25
|
+
};
|
|
26
|
+
type ConditionExpression = boolean | [operator: string, ...args: unknown[]];
|
|
27
|
+
type Action<TContext, TPatch = unknown> = (args: ActionArgs<TContext>) => ActionResult<TContext, TPatch> | Promise<ActionResult<TContext, TPatch>>;
|
|
28
|
+
type ActionArgs<TContext> = {
|
|
29
|
+
context: TContext;
|
|
30
|
+
props: Props;
|
|
31
|
+
input: Input;
|
|
32
|
+
signal: AbortSignal;
|
|
33
|
+
runtime: Runtime;
|
|
34
|
+
};
|
|
35
|
+
type ActionResult<TContext, TPatch = unknown> = void | false | ActionSuccess<TContext, TPatch> | ActionSkip | ActionStop<TPatch> | ActionFail;
|
|
36
|
+
type ActionSuccess<TContext, TPatch> = {
|
|
37
|
+
type?: 'success';
|
|
38
|
+
context?: TContext;
|
|
39
|
+
data?: Record<string, unknown>;
|
|
40
|
+
patch?: TPatch | TPatch[];
|
|
41
|
+
events?: SlapEvent[];
|
|
42
|
+
continue?: boolean;
|
|
43
|
+
};
|
|
44
|
+
type RuntimeBranchResult = {
|
|
45
|
+
status: 'success';
|
|
46
|
+
} | {
|
|
47
|
+
status: 'skipped';
|
|
48
|
+
reason?: string;
|
|
49
|
+
} | {
|
|
50
|
+
status: 'stopped';
|
|
51
|
+
reason?: string;
|
|
52
|
+
} | {
|
|
53
|
+
status: 'failed';
|
|
54
|
+
error: SlapError;
|
|
55
|
+
};
|
|
56
|
+
type ActionSkip = {
|
|
57
|
+
type: 'skip';
|
|
58
|
+
reason?: string;
|
|
59
|
+
data?: Record<string, unknown>;
|
|
60
|
+
};
|
|
61
|
+
type ActionStop<TPatch> = {
|
|
62
|
+
type: 'stop';
|
|
63
|
+
reason?: string;
|
|
64
|
+
patch?: TPatch | TPatch[];
|
|
65
|
+
events?: SlapEvent[];
|
|
66
|
+
};
|
|
67
|
+
type ActionFail = {
|
|
68
|
+
type: 'fail';
|
|
69
|
+
reason?: string;
|
|
70
|
+
error?: unknown;
|
|
71
|
+
data?: Record<string, unknown>;
|
|
72
|
+
handled?: boolean;
|
|
73
|
+
};
|
|
74
|
+
type SlapEvent = {
|
|
75
|
+
type: string;
|
|
76
|
+
payload?: unknown;
|
|
77
|
+
};
|
|
78
|
+
type EventMap = Record<string, unknown>;
|
|
79
|
+
type EventName<TEvents extends object> = Extract<keyof TEvents, string>;
|
|
80
|
+
type BusEvent<TPayload = unknown> = {
|
|
81
|
+
id: string;
|
|
82
|
+
topic: string;
|
|
83
|
+
occurredAt: number;
|
|
84
|
+
origin?: string;
|
|
85
|
+
parsed: TPayload;
|
|
86
|
+
serialized: string;
|
|
87
|
+
};
|
|
88
|
+
type EventHandler<TEvents extends object, TEvent extends EventName<TEvents>> = (event: BusEvent<TEvents[TEvent]>) => void;
|
|
89
|
+
type BusErrorEvent<TEvents extends object> = {
|
|
90
|
+
type: 'serialization';
|
|
91
|
+
topic: EventName<TEvents>;
|
|
92
|
+
payload: TEvents[EventName<TEvents>];
|
|
93
|
+
origin?: string;
|
|
94
|
+
error: unknown;
|
|
95
|
+
} | {
|
|
96
|
+
type: 'subscriber';
|
|
97
|
+
event: BusEvent<TEvents[EventName<TEvents>]>;
|
|
98
|
+
error: unknown;
|
|
99
|
+
};
|
|
100
|
+
type BusEmitOptions = {
|
|
101
|
+
origin?: string;
|
|
102
|
+
};
|
|
103
|
+
type BusOptions<TEvents extends object> = {
|
|
104
|
+
onError?: (event: BusErrorEvent<TEvents>) => void;
|
|
105
|
+
};
|
|
106
|
+
type Bus<TEvents extends object = EventMap> = {
|
|
107
|
+
on<TEvent extends EventName<TEvents>>(event: TEvent, handler: EventHandler<TEvents, TEvent>): () => void;
|
|
108
|
+
off<TEvent extends EventName<TEvents>>(event: TEvent, handler?: EventHandler<TEvents, TEvent>): void;
|
|
109
|
+
emit<TEvent extends EventName<TEvents>>(topic: TEvent, payload: TEvents[TEvent], options?: BusEmitOptions): BusEvent<TEvents[TEvent]>;
|
|
110
|
+
dispatch(event: unknown): BusEvent | undefined;
|
|
111
|
+
};
|
|
112
|
+
type WSSocket = {
|
|
113
|
+
readyState: number;
|
|
114
|
+
send(data: string): void;
|
|
115
|
+
close(): void;
|
|
116
|
+
addEventListener(type: 'open' | 'close' | 'error' | 'message', listener: EventListener): void;
|
|
117
|
+
removeEventListener(type: 'open' | 'close' | 'error' | 'message', listener: EventListener): void;
|
|
118
|
+
};
|
|
119
|
+
type RetryOptions = {
|
|
120
|
+
initialDelay?: number;
|
|
121
|
+
maxDelay?: number;
|
|
122
|
+
multiplier?: number;
|
|
123
|
+
jitter?: boolean;
|
|
124
|
+
maxAttempts?: number;
|
|
125
|
+
};
|
|
126
|
+
type WSRetryOptions = RetryOptions;
|
|
127
|
+
type WSOptions<TEvents extends object = EventMap> = {
|
|
128
|
+
bus: Bus<TEvents>;
|
|
129
|
+
createSocket: () => WSSocket;
|
|
130
|
+
inboundTopics?: EventName<TEvents>[];
|
|
131
|
+
outboundTopics?: EventName<TEvents>[];
|
|
132
|
+
origin?: string;
|
|
133
|
+
retry?: WSRetryOptions;
|
|
134
|
+
};
|
|
135
|
+
type WSStatus = 'idle' | 'connecting' | 'connected' | 'retrying' | 'stopped';
|
|
136
|
+
type FetchResponseType = 'json' | 'text' | 'blob' | 'arrayBuffer' | 'none';
|
|
137
|
+
type WS = {
|
|
138
|
+
start(): void;
|
|
139
|
+
stop(): void;
|
|
140
|
+
reconnect(): void;
|
|
141
|
+
status(): WSStatus;
|
|
142
|
+
};
|
|
143
|
+
type BindingEventMap = Record<string, Input>;
|
|
144
|
+
type BusBindingKey<TEvents extends object> = {
|
|
145
|
+
[TEvent in EventName<TEvents>]: TEvents[TEvent] extends Input ? `[bus] ${TEvent}` : never;
|
|
146
|
+
}[EventName<TEvents>];
|
|
147
|
+
type ConcurrencyMode = 'parallel' | 'latest' | 'queue' | 'drop';
|
|
148
|
+
type QueueOverflow = 'drop-oldest' | 'drop-newest';
|
|
149
|
+
type ConcurrencyOptions<TPayload = Input> = {
|
|
150
|
+
mode?: ConcurrencyMode;
|
|
151
|
+
key?: (payload: TPayload) => string;
|
|
152
|
+
maxQueueSize?: number;
|
|
153
|
+
overflow?: QueueOverflow;
|
|
154
|
+
};
|
|
155
|
+
type BusBinding<TPayload = Input> = {
|
|
156
|
+
entrypoint: string;
|
|
157
|
+
options?: {
|
|
158
|
+
concurrency?: ConcurrencyOptions<TPayload>;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
161
|
+
type BusBindings<TEvents extends object> = {
|
|
162
|
+
[TBinding in BusBindingKey<TEvents>]?: BusBinding<TEvents[Extract<TBinding extends `[bus] ${infer TEvent}` ? TEvent : never, EventName<TEvents>>]>;
|
|
163
|
+
};
|
|
164
|
+
type DomBindingKey = `[dom] ${string}:${string}`;
|
|
165
|
+
type DomForm = Record<string, FormDataEntryValue | FormDataEntryValue[]>;
|
|
166
|
+
type DomInput = Input & {
|
|
167
|
+
type: string;
|
|
168
|
+
value?: string;
|
|
169
|
+
dataset: Record<string, string>;
|
|
170
|
+
form?: DomForm;
|
|
171
|
+
};
|
|
172
|
+
type DomBinding = {
|
|
173
|
+
entrypoint: string;
|
|
174
|
+
options?: {
|
|
175
|
+
preventDefault?: boolean;
|
|
176
|
+
stopPropagation?: boolean;
|
|
177
|
+
capture?: boolean;
|
|
178
|
+
once?: boolean;
|
|
179
|
+
input?: (scope: {
|
|
180
|
+
event: Event;
|
|
181
|
+
element: Element;
|
|
182
|
+
defaultInput: DomInput;
|
|
183
|
+
}) => Input;
|
|
184
|
+
concurrency?: ConcurrencyOptions<DomInput>;
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
type DomBindings = Partial<Record<DomBindingKey, DomBinding>>;
|
|
188
|
+
type FlowDefinition<TContext, TPatch = unknown, TEvents extends object = BindingEventMap> = {
|
|
189
|
+
config: Config;
|
|
190
|
+
actions?: Record<string, Action<TContext, TPatch>>;
|
|
191
|
+
conditions?: Record<string, ConditionFn<TContext>>;
|
|
192
|
+
events?: BusBindings<TEvents> & DomBindings;
|
|
193
|
+
};
|
|
194
|
+
type FlowOptions<TContext, TPatch = unknown, TEvents extends object = BindingEventMap> = RunnerOptions<TContext, TPatch> & {
|
|
195
|
+
context: TContext | (() => TContext);
|
|
196
|
+
bus?: Bus<TEvents>;
|
|
197
|
+
root?: Document | Element;
|
|
198
|
+
concurrency?: ConcurrencyOptions;
|
|
199
|
+
onRunnerError?: (event: RunnerErrorEvent<TContext, TPatch>) => void;
|
|
200
|
+
};
|
|
201
|
+
type RunnerErrorEvent<TContext, TPatch = unknown> = {
|
|
202
|
+
error: SlapError;
|
|
203
|
+
result: RunResult<TContext, TPatch>;
|
|
204
|
+
binding: string;
|
|
205
|
+
entrypoint: string;
|
|
206
|
+
runId: string;
|
|
207
|
+
key?: string;
|
|
208
|
+
};
|
|
209
|
+
type InactiveBinding = {
|
|
210
|
+
binding: string;
|
|
211
|
+
reason: 'unsupported-source' | 'dom-unavailable';
|
|
212
|
+
};
|
|
213
|
+
type StartResult = {
|
|
214
|
+
active: string[];
|
|
215
|
+
inactive: InactiveBinding[];
|
|
216
|
+
validation: ValidationResult;
|
|
217
|
+
};
|
|
218
|
+
type Flow<TContext, TPatch = unknown> = {
|
|
219
|
+
runner: Runner<TContext, TPatch>;
|
|
220
|
+
start(): StartResult;
|
|
221
|
+
stop(options?: {
|
|
222
|
+
force?: boolean;
|
|
223
|
+
}): void;
|
|
224
|
+
};
|
|
225
|
+
type RunResult<TContext, TPatch = unknown> = {
|
|
226
|
+
status: 'success' | 'stopped' | 'failed' | 'skipped';
|
|
227
|
+
context: TContext;
|
|
228
|
+
data: Record<string, unknown>;
|
|
229
|
+
patches: TPatch[];
|
|
230
|
+
events: SlapEvent[];
|
|
231
|
+
error?: SlapError;
|
|
232
|
+
trace?: TraceEntry[];
|
|
233
|
+
steps: number;
|
|
234
|
+
};
|
|
235
|
+
type Runtime = {
|
|
236
|
+
get(path: string): unknown;
|
|
237
|
+
set(path: string, value: unknown): void;
|
|
238
|
+
data: {
|
|
239
|
+
get(path: string): unknown;
|
|
240
|
+
set(path: string, value: unknown): void;
|
|
241
|
+
};
|
|
242
|
+
variables?: {
|
|
243
|
+
get(path: string): unknown;
|
|
244
|
+
};
|
|
245
|
+
/** @deprecated Use `runtime.data.get(path)` instead. */
|
|
246
|
+
getData(path: string): unknown;
|
|
247
|
+
/** @deprecated Use `runtime.data.set(path, value)` instead. */
|
|
248
|
+
setData(path: string, value: unknown): void;
|
|
249
|
+
resolve(value: unknown): unknown;
|
|
250
|
+
signal: AbortSignal;
|
|
251
|
+
executeThen(): Promise<RuntimeBranchResult>;
|
|
252
|
+
executeCatch(): Promise<RuntimeBranchResult | undefined>;
|
|
253
|
+
emit(event: SlapEvent): void;
|
|
254
|
+
patch(patch: unknown): void;
|
|
255
|
+
stop(reason?: string): ActionStop<unknown>;
|
|
256
|
+
fail(reason?: string, data?: Record<string, unknown>): ActionFail;
|
|
257
|
+
};
|
|
258
|
+
type VariableValue = string | number | boolean | bigint | null | readonly VariableValue[] | {
|
|
259
|
+
readonly [key: string]: VariableValue;
|
|
260
|
+
};
|
|
261
|
+
type Variables = Readonly<Record<string, VariableValue>>;
|
|
262
|
+
type RunnerOptions<TContext, TPatch> = {
|
|
263
|
+
maxStepCount?: number;
|
|
264
|
+
/** @deprecated Use `maxStepCount` instead. */
|
|
265
|
+
maxSteps?: number;
|
|
266
|
+
maxDepth?: number;
|
|
267
|
+
timeout?: number;
|
|
268
|
+
/** @deprecated Use `timeout`. It will be removed in a future major release. */
|
|
269
|
+
timeoutMs?: number;
|
|
270
|
+
trace?: boolean | TraceSink;
|
|
271
|
+
onError?: ErrorReporter<TContext, TPatch>;
|
|
272
|
+
mergeData?: (current: Record<string, unknown>, next: Record<string, unknown>) => Record<string, unknown>;
|
|
273
|
+
variables?: Variables;
|
|
274
|
+
expressions?: Record<string, ExpressionOperator>;
|
|
275
|
+
};
|
|
276
|
+
type ExpressionOperator = (args: unknown[]) => unknown;
|
|
277
|
+
type RunOptions = {
|
|
278
|
+
signal?: AbortSignal;
|
|
279
|
+
};
|
|
280
|
+
type TraceSink = {
|
|
281
|
+
push(entry: TraceEntry): void;
|
|
282
|
+
entries?(): TraceEntry[];
|
|
283
|
+
};
|
|
284
|
+
type TraceEntry = {
|
|
285
|
+
step: number;
|
|
286
|
+
depth: number;
|
|
287
|
+
strategy: string;
|
|
288
|
+
fn: string;
|
|
289
|
+
mode: Mode | undefined;
|
|
290
|
+
status: 'matched' | 'skipped' | 'success' | 'stopped' | 'failed';
|
|
291
|
+
input: Input;
|
|
292
|
+
props: Props;
|
|
293
|
+
dataBefore: Record<string, unknown>;
|
|
294
|
+
dataAfter: Record<string, unknown>;
|
|
295
|
+
durationMs: number;
|
|
296
|
+
reason?: string;
|
|
297
|
+
};
|
|
298
|
+
type SlapError = {
|
|
299
|
+
code: string;
|
|
300
|
+
message: string;
|
|
301
|
+
strategy?: string;
|
|
302
|
+
fn?: string;
|
|
303
|
+
stage?: ErrorStage;
|
|
304
|
+
cause?: unknown;
|
|
305
|
+
path?: string;
|
|
306
|
+
};
|
|
307
|
+
type ErrorStage = {
|
|
308
|
+
phase: 'entrypoint' | 'condition' | 'action' | 'catch' | 'limit';
|
|
309
|
+
entrypoint?: string | undefined;
|
|
310
|
+
strategy?: string | undefined;
|
|
311
|
+
fn?: string | undefined;
|
|
312
|
+
mode?: Mode | undefined;
|
|
313
|
+
step?: number | undefined;
|
|
314
|
+
depth?: number | undefined;
|
|
315
|
+
};
|
|
316
|
+
type SlapErrorEvent<TContext, TPatch = unknown> = {
|
|
317
|
+
error: SlapError;
|
|
318
|
+
context: TContext;
|
|
319
|
+
input: Input;
|
|
320
|
+
data: Record<string, unknown>;
|
|
321
|
+
patches: TPatch[];
|
|
322
|
+
events: SlapEvent[];
|
|
323
|
+
trace?: TraceEntry[];
|
|
324
|
+
};
|
|
325
|
+
type ErrorReporter<TContext, TPatch = unknown> = (event: SlapErrorEvent<TContext, TPatch>) => void;
|
|
326
|
+
type ErrorReporterHandlers<TContext, TPatch = unknown> = {
|
|
327
|
+
report: ErrorReporter<TContext, TPatch>;
|
|
328
|
+
};
|
|
329
|
+
type ValidationResult = {
|
|
330
|
+
ok: boolean;
|
|
331
|
+
errors: ValidationIssue[];
|
|
332
|
+
warnings: ValidationIssue[];
|
|
333
|
+
};
|
|
334
|
+
type ValidationIssue = {
|
|
335
|
+
code: string;
|
|
336
|
+
message: string;
|
|
337
|
+
path?: string;
|
|
338
|
+
strategy?: string;
|
|
339
|
+
};
|
|
340
|
+
type ConditionFn<TContext> = (context: {
|
|
341
|
+
context: TContext;
|
|
342
|
+
input: Input;
|
|
343
|
+
data: Record<string, unknown>;
|
|
344
|
+
runtime: Pick<Runtime, 'resolve' | 'get' | 'data' | 'variables' | 'getData'>;
|
|
345
|
+
}, ...conditionArgs: unknown[]) => boolean;
|
|
346
|
+
type Runner<TContext, TPatch = unknown> = {
|
|
347
|
+
registerAction(name: string, action: Action<TContext, TPatch>): void;
|
|
348
|
+
registerActions(actions: Record<string, Action<TContext, TPatch>>): void;
|
|
349
|
+
registerCondition(name: string, condition: ConditionFn<TContext>): void;
|
|
350
|
+
registerConditions(conditions: Record<string, ConditionFn<TContext>>): void;
|
|
351
|
+
loadConfig(config: Config): ValidationResult;
|
|
352
|
+
validateConfig(config?: Config): ValidationResult;
|
|
353
|
+
run(entrypoint: string, context: TContext, input?: Input, options?: RunOptions): Promise<RunResult<TContext, TPatch>>;
|
|
354
|
+
runSync(entrypoint: string, context: TContext, input?: Input, options?: RunOptions): RunResult<TContext, TPatch>;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
/** @deprecated Pass the configuration object directly to `createFlow` or `runner.loadConfig`. */
|
|
358
|
+
declare const defineConfig: <TConfig extends Config>(config: TConfig) => TConfig;
|
|
359
|
+
|
|
360
|
+
declare const createMemoryTraceSink: () => TraceSink;
|
|
361
|
+
|
|
362
|
+
declare const defineErrorReporter: <TContext, TPatch = unknown>(handlers: ErrorReporterHandlers<TContext, TPatch> | ErrorReporter<TContext, TPatch>) => ErrorReporter<TContext, TPatch>;
|
|
363
|
+
|
|
364
|
+
declare const createPubSub: <TEvents extends object = EventMap>(options?: BusOptions<TEvents>) => Bus<TEvents>;
|
|
365
|
+
declare const PubSub: Bus<EventMap>;
|
|
366
|
+
|
|
367
|
+
declare const createFlow: <TContext, TPatch = unknown, TEvents extends object = BindingEventMap>(definition: FlowDefinition<TContext, TPatch, TEvents>, options: FlowOptions<TContext, TPatch, TEvents>) => Flow<TContext, TPatch>;
|
|
368
|
+
|
|
369
|
+
declare const createWS: <TEvents extends object = EventMap>(options: WSOptions<TEvents>) => WS;
|
|
370
|
+
|
|
371
|
+
declare const catchError: <T>(callback: () => T | PromiseLike<T>) => Promise<T>;
|
|
372
|
+
|
|
373
|
+
type ActionsRegistry<TContext, TPatch> = Map<string, Action<TContext, TPatch>>;
|
|
374
|
+
declare const createActionsRegistry: <TContext, TPatch>() => ActionsRegistry<TContext, TPatch>;
|
|
375
|
+
|
|
376
|
+
type ConditionsRegistry<TContext> = Map<string, ConditionFn<TContext>>;
|
|
377
|
+
declare const createConditionsRegistry: <TContext>() => ConditionsRegistry<TContext>;
|
|
378
|
+
|
|
379
|
+
export { type Action, type ActionArgs, type ActionFail, type ActionResult, type ActionSkip, type ActionStop, type ActionSuccess, type ActionsRegistry, type BindingEventMap, type Bus, type BusBinding, type BusBindingKey, type BusBindings, type BusEmitOptions, type BusErrorEvent, type BusEvent, type BusOptions, type ConcurrencyMode, type ConcurrencyOptions, type ConditionExpression, type ConditionFn, type ConditionsRegistry, type Config, type DomBinding, type DomBindingKey, type DomBindings, type DomForm, type DomInput, type ErrorReporter, type ErrorReporterHandlers, type ErrorStage, type EventHandler, type EventMap, type EventName, type ExpressionOperator, type FetchResponseType, type Flow, type FlowDefinition, type FlowOptions, type InactiveBinding, type Input, type Mode, type Next, type Props, PubSub, type QueueOverflow, type RetryOptions, type RunOptions, type RunResult, type Runner, type RunnerErrorEvent, type RunnerOptions, type Runtime, type SlapError, type SlapErrorEvent, type SlapEvent, type StartResult, type Strategy, type TraceEntry, type TraceSink, type ValidationIssue, type ValidationResult, type VariableValue, type Variables, type WS, type WSOptions, type WSRetryOptions, type WSSocket, type WSStatus, catchError, createActionsRegistry, createConditionsRegistry, createFlow, createMemoryTraceSink, createPubSub, createWS, defineConfig, defineErrorReporter };
|