@pgflow/dsl 0.0.0-test-snapshot-releases2-8d5d9bc1-20250922101158 → 0.0.0-testsnap-9294d743-20251207205914

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/README.md ADDED
@@ -0,0 +1,346 @@
1
+ # @pgflow/dsl
2
+
3
+ The TypeScript Domain Specific Language (DSL) for defining type-safe workflow definitions in pgflow.
4
+
5
+ > [!NOTE]
6
+ > This project and all its components are licensed under [Apache 2.0](./LICENSE) license.
7
+
8
+ ## Overview
9
+
10
+ `@pgflow/dsl` provides a type-safe, fluent interface for defining data-driven workflows with explicit dependencies. The DSL ensures that data flows correctly between steps and maintains type safety throughout the entire workflow definition.
11
+
12
+ Key features:
13
+
14
+ - **Type Safety** - Complete TypeScript type checking from flow inputs to outputs
15
+ - **Fluent Interface** - Chainable method calls for defining steps and dependencies
16
+ - **Functional Approach** - Clean separation between task implementation and flow orchestration
17
+ - **JSON-Compatible** - All inputs and outputs are JSON-serializable for database storage
18
+ - **Immutable Flow Definitions** - Each step operation returns a new Flow instance
19
+
20
+ ## Usage
21
+
22
+ ### Basic Example
23
+
24
+ ```typescript
25
+ import { Flow } from '@pgflow/dsl';
26
+
27
+ // Define input type for the flow
28
+ type Input = {
29
+ url: string;
30
+ };
31
+
32
+ // Define a flow with steps and dependencies
33
+ export const AnalyzeWebsite = new Flow<Input>({
34
+ slug: 'analyzeWebsite',
35
+ maxAttempts: 3,
36
+ baseDelay: 5,
37
+ timeout: 10,
38
+ })
39
+ .step(
40
+ { slug: 'website' },
41
+ async (input) => await scrapeWebsite(input.run.url)
42
+ )
43
+ .step(
44
+ { slug: 'sentiment', dependsOn: ['website'] },
45
+ async (input) => await analyzeSentiment(input.website.content)
46
+ )
47
+ .step(
48
+ { slug: 'summary', dependsOn: ['website'] },
49
+ async (input) => await summarizeWithAI(input.website.content)
50
+ )
51
+ .step(
52
+ { slug: 'saveToDb', dependsOn: ['sentiment', 'summary'] },
53
+ async (input) => {
54
+ return await saveToDb({
55
+ websiteUrl: input.run.url,
56
+ sentiment: input.sentiment.score,
57
+ summary: input.summary.aiSummary,
58
+ });
59
+ }
60
+ );
61
+ ```
62
+
63
+ ### Understanding Data Flow
64
+
65
+ In pgflow, each step receives an `input` object that contains:
66
+
67
+ 1. **`input.run`** - The original flow input (available to all steps)
68
+ 2. **`input.{stepName}`** - Outputs from dependency steps
69
+
70
+ This design ensures:
71
+
72
+ - Original flow parameters are accessible throughout the entire flow
73
+ - Data doesn't need to be manually forwarded through intermediate steps
74
+ - Steps can combine original input with processed data from previous steps
75
+
76
+ ### Step Methods
77
+
78
+ The Flow DSL provides three methods for defining steps in your workflow:
79
+
80
+ #### `.step()` - Regular Steps
81
+
82
+ The standard method for adding steps to a flow. Each step processes input and returns output.
83
+
84
+ ```typescript
85
+ .step(
86
+ { slug: 'process', dependsOn: ['previous'] },
87
+ async (input) => {
88
+ // Access input.run and input.previous
89
+ return { result: 'processed' };
90
+ }
91
+ )
92
+ ```
93
+
94
+ #### `.array()` - Array-Returning Steps
95
+
96
+ A semantic wrapper around `.step()` that provides type enforcement for steps that return arrays. Useful for data fetching or collection steps that will be processed by map steps.
97
+
98
+ ```typescript
99
+ // Fetch an array of items to be processed
100
+ .array(
101
+ { slug: 'fetchItems' },
102
+ async () => [1, 2, 3, 4, 5]
103
+ )
104
+
105
+ // With dependencies - combining data from multiple sources
106
+ .array(
107
+ { slug: 'combineResults', dependsOn: ['source1', 'source2'] },
108
+ async (input) => [...input.source1, ...input.source2]
109
+ )
110
+ ```
111
+
112
+ **Key Points:**
113
+ - Return type is enforced to be an array at compile time
114
+ - Commonly used as input for subsequent map steps
115
+ - Can depend on other steps just like regular steps
116
+
117
+ #### `.map()` - Array Processing Steps
118
+
119
+ Processes arrays element-by-element, similar to JavaScript's `Array.map()`. The handler receives individual items instead of the full input object.
120
+
121
+ **Two Modes of Operation:**
122
+
123
+ 1. **Root Map** (no `array:` property): Processes the flow's input array directly
124
+ - The flow input MUST be an array when using root maps
125
+ - Omitting the `array:` property tells pgflow to use the flow input
126
+
127
+ 2. **Dependent Map** (with `array:` property): Processes another step's array output
128
+ - The `array:` property specifies which step's output to process
129
+ - That step must return an array
130
+
131
+ ```typescript
132
+ // ROOT MAP - No array: property means use flow input
133
+ // Flow input MUST be an array (e.g., ["hello", "world"])
134
+ new Flow<string[]>({ slug: 'processStrings' })
135
+ .map(
136
+ { slug: 'uppercase' }, // No array: property!
137
+ (item) => item.toUpperCase()
138
+ );
139
+ // Each string in the input array gets uppercased in parallel
140
+
141
+ // DEPENDENT MAP - array: property specifies the source step
142
+ new Flow<{}>({ slug: 'dataPipeline' })
143
+ .array({ slug: 'numbers' }, () => [1, 2, 3])
144
+ .map(
145
+ { slug: 'double', array: 'numbers' }, // Processes 'numbers' output
146
+ (n) => n * 2
147
+ )
148
+ .map(
149
+ { slug: 'square', array: 'double' }, // Chains from 'double'
150
+ (n) => n * n
151
+ );
152
+ // Results: numbers: [1,2,3] → double: [2,4,6] → square: [4,16,36]
153
+ ```
154
+
155
+ **Key differences from regular steps:**
156
+ - Uses `array:` to specify dependency (not `dependsOn:`)
157
+ - When `array:` is omitted, uses flow input array (root map)
158
+ - Handler signature is `(item, context) => result` instead of `(input, context) => result`
159
+ - Return type is always an array
160
+ - Map steps can have at most one dependency (the array source)
161
+ - Generates SQL with `step_type => 'map'` parameter for pgflow's map processing
162
+
163
+ **Type Safety:**
164
+ The `.map()` method provides full TypeScript type inference for array elements:
165
+
166
+ ```typescript
167
+ type User = { id: number; name: string };
168
+
169
+ new Flow<{}>({ slug: 'userFlow' })
170
+ .array({ slug: 'users' }, (): User[] => [
171
+ { id: 1, name: 'Alice' },
172
+ { id: 2, name: 'Bob' }
173
+ ])
174
+ .map({ slug: 'greet', array: 'users' }, (user) => {
175
+ // TypeScript knows user is of type User
176
+ return `Hello, ${user.name} (ID: ${user.id})`;
177
+ });
178
+ ```
179
+
180
+ **Common Patterns:**
181
+
182
+ ```typescript
183
+ // Batch processing - process multiple items in parallel
184
+ new Flow<number[]>({ slug: 'batchProcessor' })
185
+ .map({ slug: 'validate' }, (item) => {
186
+ if (item < 0) throw new Error('Invalid item');
187
+ return item;
188
+ })
189
+ .map({ slug: 'process', array: 'validate' }, async (item) => {
190
+ // Each item processed in its own task
191
+ return await expensiveOperation(item);
192
+ });
193
+
194
+ // Data transformation pipeline
195
+ new Flow<{}>({ slug: 'etlPipeline' })
196
+ .step({ slug: 'fetchUrls' }, () => ['url1', 'url2', 'url3'])
197
+ .map({ slug: 'scrape', array: 'fetchUrls' }, async (url) => {
198
+ return await fetchContent(url);
199
+ })
200
+ .map({ slug: 'extract', array: 'scrape' }, (html) => {
201
+ return extractData(html);
202
+ })
203
+ .step({ slug: 'aggregate', dependsOn: ['extract'] }, (input) => {
204
+ // input.extract is the aggregated array from all map tasks
205
+ return consolidateResults(input.extract);
206
+ });
207
+ ```
208
+
209
+ **Limitations:**
210
+ - Can only depend on a single array-returning step
211
+ - TypeScript may not track type transformations between chained maps (use type assertions if needed)
212
+ - Root maps require the entire flow input to be an array
213
+
214
+ ### Context Object
215
+
216
+ Step handlers can optionally receive a second parameter - the **context object** - which provides access to platform resources and runtime information.
217
+
218
+ ```typescript
219
+ .step(
220
+ { slug: 'saveToDb' },
221
+ async (input, context) => {
222
+ // Access platform resources through context
223
+ const result = await context.sql`SELECT * FROM users WHERE id = ${input.userId}`;
224
+ return result[0];
225
+ }
226
+ )
227
+ ```
228
+
229
+ #### Core Context Resources
230
+
231
+ All platforms provide these core resources:
232
+
233
+ - **`context.env`** - Environment variables (`Record<string, string | undefined>`)
234
+ - **`context.shutdownSignal`** - AbortSignal for graceful shutdown handling
235
+ - **`context.rawMessage`** - Original pgmq message with metadata
236
+ ```typescript
237
+ interface PgmqMessageRecord<T> {
238
+ msg_id: number;
239
+ read_ct: number;
240
+ enqueued_at: Date;
241
+ vt: Date;
242
+ message: T; // <-- this is your 'input'
243
+ }
244
+ ```
245
+ - **`context.stepTask`** - Current step task details (flow handlers only)
246
+ ```typescript
247
+ interface StepTaskRecord<TFlow> {
248
+ flow_slug: string;
249
+ run_id: string;
250
+ step_slug: string;
251
+ input: StepInput<TFlow, StepSlug>; // <-- this is handler 'input'
252
+ msg_id: number;
253
+ }
254
+ ```
255
+ - **`context.workerConfig`** - Resolved worker configuration with all defaults applied
256
+ ```typescript
257
+ // Provides access to worker settings like retry limits
258
+ const isLastAttempt = context.rawMessage.read_ct >= context.workerConfig.retry.limit;
259
+ ```
260
+
261
+ #### Supabase Platform Resources
262
+
263
+ When using the Supabase platform with EdgeWorker, additional resources are available:
264
+
265
+ - **`context.sql`** - PostgreSQL client (postgres.js)
266
+ - **`context.supabase`** - Supabase client with service role key for full database access
267
+
268
+ To use Supabase resources, import the `Flow` class from the Supabase preset:
269
+
270
+ ```typescript
271
+ import { Flow } from '@pgflow/dsl/supabase';
272
+
273
+ const MyFlow = new Flow<{ userId: string }>({
274
+ slug: 'myFlow',
275
+ }).step({ slug: 'process' }, async (input, context) => {
276
+ // TypeScript knows context includes Supabase resources
277
+ const { data } = await context.supabase
278
+ .from('users')
279
+ .select('*')
280
+ .eq('id', input.userId);
281
+
282
+ // Use SQL directly
283
+ const stats = await context.sql`
284
+ SELECT COUNT(*) as total FROM events
285
+ WHERE user_id = ${input.userId}
286
+ `;
287
+
288
+ return { user: data[0], eventCount: stats[0].total };
289
+ });
290
+ ```
291
+
292
+ > [!NOTE]
293
+ > Context is optional - handlers that don't need platform resources can omit the second parameter for backward compatibility.
294
+
295
+ For more details on available resources and platform configuration, see the [@pgflow/edge-worker documentation](https://github.com/pgflow-org/pgflow/tree/main/pkgs/edge-worker#context-resources).
296
+
297
+ ### Flow Configuration
298
+
299
+ Configure flows and steps with runtime options:
300
+
301
+ ```typescript
302
+ new Flow<Input>({
303
+ slug: 'myFlow', // Required: Unique flow identifier
304
+ maxAttempts: 3, // Optional: Maximum retry attempts (default: 1)
305
+ baseDelay: 5, // Optional: Base delay in seconds for retries (default: 1)
306
+ timeout: 10, // Optional: Task timeout in seconds (default: 30)
307
+ });
308
+ ```
309
+
310
+ ## Compiling Flows
311
+
312
+ Use the `compileFlow` utility to convert a flow definition into SQL statements:
313
+
314
+ ```typescript
315
+ import { compileFlow } from '@pgflow/dsl';
316
+
317
+ const sqlStatements = compileFlow(MyFlow);
318
+ console.log(sqlStatements.join('\n'));
319
+ ```
320
+
321
+ Alternatively, use the pgflow CLI to compile flows directly to migration files:
322
+
323
+ ```bash
324
+ npx pgflow compile path/to/flow.ts
325
+ ```
326
+
327
+ ## Requirements
328
+
329
+ - All step inputs and outputs MUST be JSON-serializable
330
+ - Use only: primitive types, plain objects, and arrays
331
+ - Convert dates to ISO strings (`new Date().toISOString()`)
332
+ - Avoid: class instances, functions, symbols, undefined values, and circular references
333
+
334
+ ## Building
335
+
336
+ Run `nx build dsl` to build the library.
337
+
338
+ ## Running unit tests
339
+
340
+ Run `nx test dsl` to execute the unit tests via [Vitest](https://vitest.dev/).
341
+
342
+ ## Documentation
343
+
344
+ For detailed documentation on the Flow DSL, visit:
345
+
346
+ - [Understanding the Flow DSL](https://pgflow.dev/explanations/flow-dsl/)
@@ -0,0 +1,10 @@
1
+ import { AnyFlow } from './dsl.js';
2
+ /**
3
+ * Compiles a Flow object into an array of SQL statements
4
+ * that can be executed to create the flow and its steps in PostgreSQL
5
+ *
6
+ * @param flow The Flow object to compile
7
+ * @returns Array of SQL statements
8
+ */
9
+ export declare function compileFlow(flow: AnyFlow): string[];
10
+ //# sourceMappingURL=compile-flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compile-flow.d.ts","sourceRoot":"","sources":["../src/compile-flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAsC,MAAM,UAAU,CAAC;AAEvE;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CA+BnD"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Compiles a Flow object into an array of SQL statements
3
+ * that can be executed to create the flow and its steps in PostgreSQL
4
+ *
5
+ * @param flow The Flow object to compile
6
+ * @returns Array of SQL statements
7
+ */
8
+ export function compileFlow(flow) {
9
+ const statements = [];
10
+ // Create the flow
11
+ const flowOptions = formatRuntimeOptions(flow.options);
12
+ statements.push(`SELECT pgflow.create_flow('${flow.slug}'${flowOptions});`);
13
+ // Add steps in the order they were defined
14
+ for (const stepSlug of flow.stepOrder) {
15
+ const step = flow.getStepDefinition(stepSlug);
16
+ const stepOptions = formatRuntimeOptions(step.options);
17
+ // Format dependencies array if it exists
18
+ let depsClause = '';
19
+ if (step.dependencies.length > 0) {
20
+ const depsArray = step.dependencies.map((dep) => `'${dep}'`).join(', ');
21
+ depsClause = `, ARRAY[${depsArray}]`;
22
+ }
23
+ // Add step_type parameter for map steps
24
+ let stepTypeClause = '';
25
+ if (step.stepType === 'map') {
26
+ stepTypeClause = `, step_type => 'map'`;
27
+ }
28
+ statements.push(`SELECT pgflow.add_step('${flow.slug}', '${step.slug}'${depsClause}${stepOptions}${stepTypeClause});`);
29
+ }
30
+ return statements;
31
+ }
32
+ /**
33
+ * Formats runtime options into SQL parameter string
34
+ */
35
+ function formatRuntimeOptions(options) {
36
+ const parts = [];
37
+ if (options.maxAttempts !== undefined) {
38
+ parts.push(`max_attempts => ${options.maxAttempts}`);
39
+ }
40
+ if (options.baseDelay !== undefined) {
41
+ parts.push(`base_delay => ${options.baseDelay}`);
42
+ }
43
+ if (options.timeout !== undefined) {
44
+ parts.push(`timeout => ${options.timeout}`);
45
+ }
46
+ if ('startDelay' in options && options.startDelay !== undefined) {
47
+ parts.push(`start_delay => ${options.startDelay}`);
48
+ }
49
+ return parts.length > 0 ? `, ${parts.join(', ')}` : '';
50
+ }
package/dist/dsl.d.ts ADDED
@@ -0,0 +1,256 @@
1
+ export type Json = string | number | boolean | null | Json[] | {
2
+ [key: string]: Json;
3
+ };
4
+ export type Simplify<T> = {
5
+ [KeyType in keyof T]: T[KeyType];
6
+ } & {};
7
+ type AwaitedReturn<T> = T extends (...args: any[]) => Promise<infer R> ? R : T extends (...args: any[]) => infer R ? R : never;
8
+ export interface Env {
9
+ [key: string]: string | undefined;
10
+ }
11
+ export type ValidEnv<T> = T extends Env ? T : never;
12
+ export interface UserEnv extends Env {
13
+ }
14
+ export type AnyInput = Json;
15
+ export type AnyOutput = Json;
16
+ export type EmptySteps = Record<never, never>;
17
+ export type AnySteps = Record<string, AnyOutput>;
18
+ export type EmptyDeps = Record<never, never[]>;
19
+ export type DefaultDeps = Record<string, string[]>;
20
+ export type AnyDeps = Record<string, string[]>;
21
+ /**
22
+ * Represents a Flow that has not steps nor deps defined yet
23
+ */
24
+ export type EmptyFlow = Flow<AnyInput, {}, EmptySteps, EmptyDeps>;
25
+ /**
26
+ * Represents any Flow with flexible input, context, steps, and dependencies.
27
+ * This type is intentionally more permissive to allow for better type inference
28
+ * in utility types like StepOutput.
29
+ */
30
+ export type AnyFlow = Flow<any, any, any, any, any>;
31
+ /**
32
+ * Extracts the input type from a Flow
33
+ * @template TFlow - The Flow type to extract from
34
+ */
35
+ export type ExtractFlowInput<TFlow extends AnyFlow> = TFlow extends Flow<infer TI, infer _TC, infer _TS, infer _TD, infer _TEnv> ? TI : never;
36
+ /**
37
+ * Utility type to extract all possible step inputs from a flow
38
+ * This creates a union of all step input types
39
+ */
40
+ export type AllStepInputs<TFlow extends AnyFlow> = {
41
+ [K in keyof ExtractFlowSteps<TFlow> & string]: StepInput<TFlow, K>;
42
+ }[keyof ExtractFlowSteps<TFlow> & string];
43
+ /**
44
+ * Extracts the output type from a Flow
45
+ * @template TFlow - The Flow type to extract from
46
+ */
47
+ export type ExtractFlowOutput<TFlow extends AnyFlow> = TFlow extends Flow<infer _TI, infer _TC, infer _TS, infer _TD, infer _TEnv> ? {
48
+ [K in keyof ExtractFlowLeafSteps<TFlow> as K extends string ? K : never]: StepOutput<TFlow, K & string>;
49
+ } : never;
50
+ /**
51
+ * Extracts the steps type from a Flow
52
+ * @template TFlow - The Flow type to extract from
53
+ */
54
+ export type ExtractFlowSteps<TFlow extends AnyFlow> = TFlow extends Flow<infer _TI, infer _TC, infer TS, infer _TD, infer _TEnv> ? TS : never;
55
+ /**
56
+ * Extracts the dependencies type from a Flow
57
+ * @template TFlow - The Flow type to extract from
58
+ */
59
+ export type ExtractFlowDeps<TFlow extends AnyFlow> = TFlow extends Flow<infer _TI, infer _TC, infer _TS, infer TD, infer _TEnv> ? TD : never;
60
+ /**
61
+ * Extracts the environment type from a Flow
62
+ * @template TFlow - The Flow type to extract from
63
+ * Returns the TEnv type parameter
64
+ */
65
+ export type ExtractFlowEnv<TFlow extends AnyFlow> = TFlow extends Flow<infer _TI, infer _TC, infer _TS, infer _TD, infer TEnv> ? TEnv : never;
66
+ /**
67
+ * Extracts the full handler context type from a Flow
68
+ * @template TFlow - The Flow type to extract from
69
+ * Returns FlowContext<TEnv> & TContext (the complete context handlers receive)
70
+ */
71
+ export type ExtractFlowContext<TFlow extends AnyFlow> = TFlow extends Flow<infer _TI, infer TC, infer _TS, infer _TD, infer TEnv> ? FlowContext<TEnv> & TC : never;
72
+ /**
73
+ * Type guard that ensures a flow's context requirements can be satisfied
74
+ * by the resources provided by the platform and optional user resources.
75
+ *
76
+ * A flow is compatible if the provided platform and user resources can satisfy
77
+ * all the context requirements declared by the flow.
78
+ *
79
+ * @template F - The Flow type to check for compatibility
80
+ * @template PlatformResources - Resources provided by the execution platform (e.g., Supabase resources)
81
+ * @template UserResources - Additional user-provided resources (default: empty)
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * // In a platform worker:
86
+ * type SupabaseCompatibleFlow<F extends AnyFlow> = CompatibleFlow<F, SupabaseResources>;
87
+ *
88
+ * // Usage:
89
+ * function startWorker<F extends AnyFlow>(flow: SupabaseCompatibleFlow<F>) {
90
+ * // flow is guaranteed to be compatible with Supabase platform
91
+ * }
92
+ * ```
93
+ */
94
+ export type CompatibleFlow<F extends AnyFlow, PlatformResources extends Record<string, unknown>, UserResources extends Record<string, unknown> = Record<string, never>> = (FlowContext<ExtractFlowEnv<F>> & PlatformResources & UserResources) extends ExtractFlowContext<F> ? F : never;
95
+ /**
96
+ * Extracts the dependencies type from a Flow
97
+ * @template TFlow - The Flow type to extract from
98
+ */
99
+ type StepDepsOf<TFlow extends AnyFlow, TStepSlug extends string> = TStepSlug extends keyof ExtractFlowDeps<TFlow> ? ExtractFlowDeps<TFlow>[TStepSlug][number] : never;
100
+ /**
101
+ * Extracts only the leaf steps from a Flow (steps that are not dependencies of any other steps)
102
+ * @template TFlow - The Flow type to extract from
103
+ */
104
+ export type ExtractFlowLeafSteps<TFlow extends AnyFlow> = {
105
+ [K in keyof ExtractFlowSteps<TFlow> as K extends string ? K extends ExtractFlowDeps<TFlow>[keyof ExtractFlowDeps<TFlow>][number] ? never : K : never]: ExtractFlowSteps<TFlow>[K];
106
+ };
107
+ export type StepOutput<TFlow extends AnyFlow, TStepSlug extends string> = TStepSlug extends keyof ExtractFlowSteps<TFlow> ? ExtractFlowSteps<TFlow>[TStepSlug] : never;
108
+ /**
109
+ * This ensures that:
110
+ * 1. The run input is always included
111
+ * 2. Only declared dependencies are included
112
+ * 3. No extra properties are allowed
113
+ * Utility type to extract the input type for a specific step in a flow
114
+ */
115
+ export type StepInput<TFlow extends AnyFlow, TStepSlug extends string> = {
116
+ run: ExtractFlowInput<TFlow>;
117
+ } & {
118
+ [K in Extract<keyof ExtractFlowSteps<TFlow>, StepDepsOf<TFlow, TStepSlug>>]: ExtractFlowSteps<TFlow>[K];
119
+ };
120
+ export interface RuntimeOptions {
121
+ maxAttempts?: number;
122
+ baseDelay?: number;
123
+ timeout?: number;
124
+ }
125
+ export interface WorkerConfig {
126
+ maxConcurrent: number;
127
+ maxPollSeconds: number;
128
+ pollIntervalMs: number;
129
+ batchSize: number;
130
+ visibilityTimeout: number;
131
+ }
132
+ export interface MessageRecord {
133
+ msg_id: number;
134
+ read_ct: number;
135
+ enqueued_at: string;
136
+ vt: string;
137
+ message: Json;
138
+ }
139
+ export interface StepTaskRecord<TFlow extends AnyFlow> {
140
+ flow_slug: string;
141
+ run_id: string;
142
+ step_slug: string;
143
+ input: Json;
144
+ msg_id: number;
145
+ }
146
+ export interface BaseContext<TEnv extends Env = Env> {
147
+ env: TEnv & ValidEnv<UserEnv>;
148
+ shutdownSignal: AbortSignal;
149
+ rawMessage: MessageRecord;
150
+ workerConfig: Readonly<WorkerConfig>;
151
+ }
152
+ export interface FlowContext<TEnv extends Env = Env> extends BaseContext<TEnv> {
153
+ stepTask: StepTaskRecord<AnyFlow>;
154
+ }
155
+ export type Context<T extends Record<string, unknown> = Record<string, never>, TEnv extends Env = Env> = FlowContext<TEnv> & T;
156
+ export interface StepRuntimeOptions extends RuntimeOptions {
157
+ startDelay?: number;
158
+ }
159
+ export interface StepDefinition<TInput extends AnyInput, TOutput extends AnyOutput, TContext = FlowContext> {
160
+ slug: string;
161
+ handler: (input: TInput, context: TContext) => TOutput | Promise<TOutput>;
162
+ dependencies: string[];
163
+ options: StepRuntimeOptions;
164
+ stepType?: 'single' | 'map';
165
+ }
166
+ export declare class Flow<TFlowInput extends AnyInput = AnyInput, TContext extends Record<string, unknown> = {}, // Accumulated custom context (FlowContext is always provided)
167
+ Steps extends AnySteps = EmptySteps, StepDependencies extends AnyDeps = EmptyDeps, TEnv extends Env = Env> {
168
+ /**
169
+ * Store step definitions with their proper types
170
+ *
171
+ * This is typed as a generic record because TypeScript cannot track the exact relationship
172
+ * between step slugs and their corresponding input/output types at the container level.
173
+ * Type safety is enforced at the method level when adding or retrieving steps.
174
+ */
175
+ private stepDefinitions;
176
+ readonly stepOrder: string[];
177
+ readonly slug: string;
178
+ readonly options: RuntimeOptions;
179
+ constructor(config: Simplify<{
180
+ slug: string;
181
+ } & RuntimeOptions>, stepDefinitions?: Record<string, StepDefinition<AnyInput, AnyOutput>>, stepOrder?: string[]);
182
+ /**
183
+ * Get a specific step definition by slug with proper typing
184
+ * @throws Error if the step with the given slug doesn't exist
185
+ */
186
+ getStepDefinition<SlugType extends keyof Steps & keyof StepDependencies>(slug: SlugType): StepDefinition<Simplify<{
187
+ run: TFlowInput;
188
+ } & {
189
+ [K in StepDependencies[SlugType][number]]: K extends keyof Steps ? Steps[K] : never;
190
+ }>, Steps[SlugType]>;
191
+ step<Slug extends string, THandler extends (input: Simplify<{
192
+ run: TFlowInput;
193
+ } & {
194
+ [K in Deps]: K extends keyof Steps ? Steps[K] : never;
195
+ }>, context: FlowContext<TEnv> & TContext) => any, Deps extends Extract<keyof Steps, string> = never>(opts: Simplify<{
196
+ slug: Slug extends keyof Steps ? never : Slug;
197
+ dependsOn?: Deps[];
198
+ } & StepRuntimeOptions>, handler: THandler): Flow<TFlowInput, TContext, Steps & {
199
+ [K in Slug]: AwaitedReturn<THandler>;
200
+ }, StepDependencies & {
201
+ [K in Slug]: Deps[];
202
+ }, TEnv>;
203
+ /**
204
+ * Add an array-returning step to the flow with compile-time type safety
205
+ *
206
+ * This method provides semantic clarity and type enforcement for steps that return arrays,
207
+ * while maintaining full compatibility with the existing step system by delegating to `.step()`.
208
+ *
209
+ * @template Slug - The unique identifier for this step
210
+ * @template THandler - The handler function that must return an array or Promise<array>
211
+ * @template Deps - The step dependencies (must be existing step slugs)
212
+ * @param opts - Step configuration including slug, dependencies, and runtime options
213
+ * @param handler - Function that processes input and returns an array (null/undefined rejected)
214
+ * @returns A new Flow instance with the array step added
215
+ */
216
+ array<Slug extends string, THandler extends (input: Simplify<{
217
+ run: TFlowInput;
218
+ } & {
219
+ [K in Deps]: K extends keyof Steps ? Steps[K] : never;
220
+ }>, context: BaseContext & TContext) => readonly any[] | Promise<readonly any[]>, Deps extends Extract<keyof Steps, string> = never>(opts: Simplify<{
221
+ slug: Slug extends keyof Steps ? never : Slug;
222
+ dependsOn?: Deps[];
223
+ } & StepRuntimeOptions>, handler: THandler): Flow<TFlowInput, TContext, Steps & {
224
+ [K in Slug]: AwaitedReturn<THandler>;
225
+ }, StepDependencies & {
226
+ [K in Slug]: Deps[];
227
+ }, TEnv>;
228
+ /**
229
+ * Add a map step to the flow that processes arrays element by element
230
+ *
231
+ * Map steps apply a handler function to each element of an array, producing
232
+ * a new array with the transformed elements. The handler receives individual
233
+ * array elements, not the full input object.
234
+ *
235
+ * @param opts - Step configuration including slug and optional array dependency
236
+ * @param handler - Function that processes individual array elements
237
+ * @returns A new Flow instance with the map step added
238
+ */
239
+ map<Slug extends string, THandler extends TFlowInput extends readonly (infer Item)[] ? (item: Item, context: BaseContext & TContext) => Json | Promise<Json> : never>(opts: Simplify<{
240
+ slug: Slug extends keyof Steps ? never : Slug;
241
+ } & StepRuntimeOptions>, handler: THandler): Flow<TFlowInput, TContext & BaseContext, Steps & {
242
+ [K in Slug]: AwaitedReturn<THandler>[];
243
+ }, StepDependencies & {
244
+ [K in Slug]: [];
245
+ }>;
246
+ map<Slug extends string, TArrayDep extends Extract<keyof Steps, string>, THandler extends Steps[TArrayDep] extends readonly (infer Item)[] ? (item: Item, context: BaseContext & TContext) => Json | Promise<Json> : never>(opts: Simplify<{
247
+ slug: Slug extends keyof Steps ? never : Slug;
248
+ array: TArrayDep;
249
+ } & StepRuntimeOptions>, handler: THandler): Flow<TFlowInput, TContext & BaseContext, Steps & {
250
+ [K in Slug]: AwaitedReturn<THandler>[];
251
+ }, StepDependencies & {
252
+ [K in Slug]: [TArrayDep];
253
+ }>;
254
+ }
255
+ export {};
256
+ //# sourceMappingURL=dsl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsl.d.ts","sourceRoot":"","sources":["../src/dsl.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,IAAI,GACZ,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,IAAI,EAAE,GACN;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAG5B,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI;KAAG,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;CAAE,GAAG,EAAE,CAAC;AAKpE,KAAK,aAAa,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,GAClE,CAAC,GACD,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,CAAC,GACnC,CAAC,GACD,KAAK,CAAC;AAOZ,MAAM,WAAW,GAAG;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AAGD,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;AAKpD,MAAM,WAAW,OAAQ,SAAQ,GAAG;CAAG;AAOvC,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC;AAC5B,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC;AAG7B,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC9C,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAGjD,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/C,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAM/C;;GAEG;AAEH,MAAM,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAElE;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAMpD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,IAAI,CACtE,MAAM,EAAE,EACR,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,KAAK,CACZ,GACG,EAAE,GACF,KAAK,CAAC;AAEV;;;GAGG;AACH,MAAM,MAAM,aAAa,CAAC,KAAK,SAAS,OAAO,IAAI;KAChD,CAAC,IAAI,MAAM,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;CACnE,CAAC,MAAM,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC;AAE1C;;;GAGG;AACH,MAAM,MAAM,iBAAiB,CAAC,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,IAAI,CACvE,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,KAAK,CACZ,GACG;KACG,CAAC,IAAI,MAAM,oBAAoB,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,GACvD,CAAC,GACD,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC;CAC1C,GACD,KAAK,CAAC;AAEV;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,IAAI,CACtE,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,EAAE,EACR,MAAM,GAAG,EACT,MAAM,KAAK,CACZ,GACG,EAAE,GACF,KAAK,CAAC;AAEV;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,IAAI,CACrE,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,EAAE,EACR,MAAM,KAAK,CACZ,GACG,EAAE,GACF,KAAK,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,cAAc,CAAC,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,IAAI,CACpE,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,IAAI,CACX,GACG,IAAI,GACJ,KAAK,CAAC;AAEV;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,CAAC,KAAK,SAAS,OAAO,IAAI,KAAK,SAAS,IAAI,CACxE,MAAM,GAAG,EACT,MAAM,EAAE,EACR,MAAM,GAAG,EACT,MAAM,GAAG,EACT,MAAM,IAAI,CACX,GACG,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,GACtB,KAAK,CAAC;AAEV;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,MAAM,cAAc,CACxB,CAAC,SAAS,OAAO,EACjB,iBAAiB,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjD,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAErE,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,iBAAiB,GAAG,aAAa,CAAC,SAAS,kBAAkB,CAAC,CAAC,CAAC,GAC9F,CAAC,GACD,KAAK,CAAC;AAEZ;;;GAGG;AACH,KAAK,UAAU,CACb,KAAK,SAAS,OAAO,EACrB,SAAS,SAAS,MAAM,IACtB,SAAS,SAAS,MAAM,eAAe,CAAC,KAAK,CAAC,GAC9C,eAAe,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,GACzC,KAAK,CAAC;AAEV;;;GAGG;AACH,MAAM,MAAM,oBAAoB,CAAC,KAAK,SAAS,OAAO,IAAI;KACvD,CAAC,IAAI,MAAM,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,MAAM,GACnD,CAAC,SAAS,eAAe,CAAC,KAAK,CAAC,CAAC,MAAM,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GACpE,KAAK,GACL,CAAC,GACH,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CACvC,CAAC;AAKF,MAAM,MAAM,UAAU,CACpB,KAAK,SAAS,OAAO,EACrB,SAAS,SAAS,MAAM,IACtB,SAAS,SAAS,MAAM,gBAAgB,CAAC,KAAK,CAAC,GAC/C,gBAAgB,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,GAClC,KAAK,CAAC;AAEV;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,CAAC,KAAK,SAAS,OAAO,EAAE,SAAS,SAAS,MAAM,IAAI;IACvE,GAAG,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC;CAC9B,GAAG;KACD,CAAC,IAAI,OAAO,CACX,MAAM,gBAAgB,CAAC,KAAK,CAAC,EAC7B,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAC7B,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;CAC/B,CAAC;AAGF,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAGD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,IAAI,CAAC;CACf;AAGD,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,OAAO;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,WAAW,WAAW,CAAC,IAAI,SAAS,GAAG,GAAG,GAAG;IACjD,GAAG,EAAE,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC9B,cAAc,EAAE,WAAW,CAAC;IAC5B,UAAU,EAAE,aAAa,CAAC;IAC1B,YAAY,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;CACtC;AAGD,MAAM,WAAW,WAAW,CAAC,IAAI,SAAS,GAAG,GAAG,GAAG,CAAE,SAAQ,WAAW,CAAC,IAAI,CAAC;IAC5E,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;CACnC;AAGD,MAAM,MAAM,OAAO,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,SAAS,GAAG,GAAG,GAAG,IAAI,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAG/H,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAGD,MAAM,WAAW,cAAc,CAC7B,MAAM,SAAS,QAAQ,EACvB,OAAO,SAAS,SAAS,EACzB,QAAQ,GAAG,WAAW;IAEtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1E,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,CAAC;CAC7B;AAMD,qBAAa,IAAI,CACf,UAAU,SAAS,QAAQ,GAAG,QAAQ,EAEtC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,8DAA8D;AAC7G,KAAK,SAAS,QAAQ,GAAG,UAAU,EACnC,gBAAgB,SAAS,OAAO,GAAG,SAAS,EAC5C,IAAI,SAAS,GAAG,GAAG,GAAG;IAEtB;;;;;;OAMG;IACH,OAAO,CAAC,eAAe,CAAsD;IAC7E,SAAgB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpC,SAAgB,IAAI,EAAE,MAAM,CAAC;IAC7B,SAAgB,OAAO,EAAE,cAAc,CAAC;gBAGtC,MAAM,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,cAAc,CAAC,EACnD,eAAe,GAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAM,EACzE,SAAS,GAAE,MAAM,EAAO;IAkB1B;;;OAGG;IACH,iBAAiB,CAAC,QAAQ,SAAS,MAAM,KAAK,GAAG,MAAM,gBAAgB,EACrE,IAAI,EAAE,QAAQ,GACb,cAAc,CACf,QAAQ,CACN;QACE,GAAG,EAAE,UAAU,CAAC;KACjB,GAAG;SACD,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,MAAM,KAAK,GAC5D,KAAK,CAAC,CAAC,CAAC,GACR,KAAK;KACV,CACF,EACD,KAAK,CAAC,QAAQ,CAAC,CAChB;IAeD,IAAI,CACF,IAAI,SAAS,MAAM,EACnB,QAAQ,SAAS,CACf,KAAK,EAAE,QAAQ,CACb;QACE,GAAG,EAAE,UAAU,CAAC;KACjB,GAAG;SACD,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK;KACtD,CACF,EACD,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,GAAG,QAAQ,KAClC,GAAG,EACR,IAAI,SAAS,OAAO,CAAC,MAAM,KAAK,EAAE,MAAM,CAAC,GAAG,KAAK,EAEjD,IAAI,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,IAAI,SAAS,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAA;KAAE,GAAG,kBAAkB,CAAC,EAC1G,OAAO,EAAE,QAAQ,GAChB,IAAI,CACL,UAAU,EACV,QAAQ,EACR,KAAK,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC;KAAE,EAChD,gBAAgB,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,IAAI,EAAE;KAAE,EAC1C,IAAI,CACL;IA0ED;;;;;;;;;;;;OAYG;IACH,KAAK,CACH,IAAI,SAAS,MAAM,EACnB,QAAQ,SAAS,CACf,KAAK,EAAE,QAAQ,CACb;QACE,GAAG,EAAE,UAAU,CAAC;KACjB,GAAG;SACD,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK;KACtD,CACF,EACD,OAAO,EAAE,WAAW,GAAG,QAAQ,KAC5B,SAAS,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC,EAC7C,IAAI,SAAS,OAAO,CAAC,MAAM,KAAK,EAAE,MAAM,CAAC,GAAG,KAAK,EAEjD,IAAI,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,IAAI,SAAS,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;QAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAA;KAAE,GAAG,kBAAkB,CAAC,EAC1G,OAAO,EAAE,QAAQ,GAChB,IAAI,CACL,UAAU,EACV,QAAQ,EACR,KAAK,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC;KAAE,EAChD,gBAAgB,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,IAAI,EAAE;KAAE,EAC1C,IAAI,CACL;IAKD;;;;;;;;;;OAUG;IAEH,GAAG,CACD,IAAI,SAAS,MAAM,EACnB,QAAQ,SAAS,UAAU,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GACvD,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACrE,KAAK,EAET,IAAI,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,IAAI,SAAS,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAA;KAAE,GAAG,kBAAkB,CAAC,EACtF,OAAO,EAAE,QAAQ,GAChB,IAAI,CACL,UAAU,EACV,QAAQ,GAAG,WAAW,EACtB,KAAK,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,EAAE;KAAE,EAClD,gBAAgB,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,EAAE;KAAE,CACvC;IAGD,GAAG,CACD,IAAI,SAAS,MAAM,EACnB,SAAS,SAAS,OAAO,CAAC,MAAM,KAAK,EAAE,MAAM,CAAC,EAC9C,QAAQ,SAAS,KAAK,CAAC,SAAS,CAAC,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GAC7D,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,GAAG,QAAQ,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACrE,KAAK,EAET,IAAI,EAAE,QAAQ,CAAC;QAAE,IAAI,EAAE,IAAI,SAAS,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,kBAAkB,CAAC,EACxG,OAAO,EAAE,QAAQ,GAChB,IAAI,CACL,UAAU,EACV,QAAQ,GAAG,WAAW,EACtB,KAAK,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,EAAE;KAAE,EAClD,gBAAgB,GAAG;SAAG,CAAC,IAAI,IAAI,GAAG,CAAC,SAAS,CAAC;KAAE,CAChD;CA8DF"}