@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/README.md CHANGED
@@ -31,7 +31,7 @@ type Input = {
31
31
 
32
32
  // Define a flow with steps and dependencies
33
33
  export const AnalyzeWebsite = new Flow<Input>({
34
- slug: 'analyze_website',
34
+ slug: 'analyzeWebsite',
35
35
  maxAttempts: 3,
36
36
  baseDelay: 5,
37
37
  timeout: 10,
@@ -73,6 +73,144 @@ This design ensures:
73
73
  - Data doesn't need to be manually forwarded through intermediate steps
74
74
  - Steps can combine original input with processed data from previous steps
75
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
+
76
214
  ### Context Object
77
215
 
78
216
  Step handlers can optionally receive a second parameter - the **context object** - which provides access to platform resources and runtime information.
@@ -114,6 +252,11 @@ All platforms provide these core resources:
114
252
  msg_id: number;
115
253
  }
116
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
+ ```
117
260
 
118
261
  #### Supabase Platform Resources
119
262
 
@@ -128,7 +271,7 @@ To use Supabase resources, import the `Flow` class from the Supabase preset:
128
271
  import { Flow } from '@pgflow/dsl/supabase';
129
272
 
130
273
  const MyFlow = new Flow<{ userId: string }>({
131
- slug: 'my_flow',
274
+ slug: 'myFlow',
132
275
  }).step({ slug: 'process' }, async (input, context) => {
133
276
  // TypeScript knows context includes Supabase resources
134
277
  const { data } = await context.supabase
@@ -157,7 +300,7 @@ Configure flows and steps with runtime options:
157
300
 
158
301
  ```typescript
159
302
  new Flow<Input>({
160
- slug: 'my_flow', // Required: Unique flow identifier
303
+ slug: 'myFlow', // Required: Unique flow identifier
161
304
  maxAttempts: 3, // Optional: Maximum retry attempts (default: 1)
162
305
  baseDelay: 5, // Optional: Base delay in seconds for retries (default: 1)
163
306
  timeout: 10, // Optional: Task timeout in seconds (default: 30)
@@ -0,0 +1,481 @@
1
+ # @pgflow/dsl
2
+
3
+ ## 0.0.0-testsnap-9294d743-20251207205914
4
+
5
+ ### Patch Changes
6
+
7
+ - 0b84bb0: Add automatic flow compilation at worker startup. Workers now call ensure_flow_compiled to verify flows are up-to-date. In development, mismatched flows are recompiled automatically. In production, mismatches cause errors. Use ensureCompiledOnStartup: false to opt-out.
8
+
9
+ ## 0.9.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 992a86b: Unify connection configuration with improved local detection. The `connectionString` config option now works correctly, and you can pass a raw postgres.js `sql` instance via `config.sql` for full control over connection options (SSL, pooling, etc.).
14
+
15
+ Fixes [#469](https://github.com/pgflow-dev/pgflow/issues/469), [#424](https://github.com/pgflow-dev/pgflow/issues/424). Thanks to [@Nciso](https://github.com/Nciso), [@mikz](https://github.com/mikz), [@ddlaws0n](https://github.com/ddlaws0n), and **PixelEcho** for feedback and bug reports.
16
+
17
+ ## 0.9.0
18
+
19
+ ## 0.8.1
20
+
21
+ ## 0.8.0
22
+
23
+ ## 0.7.3
24
+
25
+ ## 0.7.2
26
+
27
+ ## 0.7.1
28
+
29
+ ## 0.7.0
30
+
31
+ ### Minor Changes
32
+
33
+ - 524db03: Add `.array()` method for type-safe array step creation
34
+
35
+ Introduces a new `.array()` method that provides compile-time type safety for array-returning handlers with zero runtime overhead.
36
+
37
+ - Enforces array return types at compile time
38
+ - Pure delegation to existing `.step()` method
39
+ - Full support for dependencies and runtime options
40
+ - Backward compatible
41
+
42
+ ```typescript
43
+ flow.array({ slug: 'items' }, () => [1, 2, 3]); // ✅ Valid
44
+ flow.array({ slug: 'invalid' }, () => 42); // ❌ Compile error
45
+ ```
46
+
47
+ - 524db03: Add `.map()` method to Flow DSL for defining map-type steps
48
+
49
+ The new `.map()` method enables defining steps that process arrays element-by-element, complementing the existing SQL Core map infrastructure. Key features:
50
+
51
+ - **Root maps**: Process flow input arrays directly by omitting the `array` property
52
+ - **Dependent maps**: Process another step's array output using `array: 'stepSlug'`
53
+ - **Type-safe**: Enforces Json-compatible types with full TypeScript inference
54
+ - **Compile-time duplicate slug detection**: TypeScript now prevents duplicate step slugs at compile-time
55
+ - **Different handler signature**: Receives individual items `(item, context)` instead of full input object
56
+ - **Always returns arrays**: Return type is `HandlerReturnType[]`
57
+ - **SQL generation**: Correctly adds `step_type => 'map'` parameter to `pgflow.add_step()`
58
+
59
+ Example usage:
60
+
61
+ ```typescript
62
+ // Root map - processes array input
63
+ new Flow<string[]>({ slug: 'process' }).map({ slug: 'uppercase' }, (item) =>
64
+ item.toUpperCase()
65
+ );
66
+
67
+ // Dependent map - processes another step's output
68
+ new Flow<{}>({ slug: 'workflow' })
69
+ .array({ slug: 'items' }, () => [1, 2, 3])
70
+ .map({ slug: 'double', array: 'items' }, (n) => n * 2);
71
+ ```
72
+
73
+ ## 0.6.1
74
+
75
+ ## 0.6.0
76
+
77
+ ### Minor Changes
78
+
79
+ - a67bf27: 🚨 **BREAKING**: Remove `anonSupabase` and `serviceSupabase` from context, replaced with single `supabase` client (initialized with service role key)
80
+
81
+ The dual-client approach was unnecessary complexity. Edge Functions run in a trusted environment with service role access, so a single client is sufficient.
82
+
83
+ **Migration guide**:
84
+
85
+ ```typescript
86
+ // Before
87
+ const { data } = await context.serviceSupabase.from('users').select();
88
+ const { data: publicData } = await context.anonSupabase
89
+ .from('posts')
90
+ .select();
91
+
92
+ // After
93
+ const { data } = await context.supabase.from('users').select();
94
+ // For RLS-respecting queries, implement proper policies in your database
95
+ ```
96
+
97
+ ⚠️ **Breaking changes**:
98
+
99
+ - Removed `anonSupabase` from context interface
100
+ - Removed `serviceSupabase` from context interface
101
+ - Added `supabase` field (initialized with service role key)
102
+ - Removed `createAnonSupabaseClient` function
103
+
104
+ ## 0.5.4
105
+
106
+ ### Patch Changes
107
+
108
+ - 9f219a4: Add context object as second parameter to handlers
109
+
110
+ Queue and flow handlers now receive an optional context parameter that provides platform resources like database connections, environment variables, and Supabase clients - eliminating boilerplate and connection management.
111
+
112
+ ```typescript
113
+ // Queue handler
114
+ EdgeWorker.start(async (payload, context) => {
115
+ await context.sql`INSERT INTO tasks (data) VALUES (${payload})`;
116
+ });
117
+
118
+ // Flow step handler
119
+ .step({ slug: 'process' }, async (input, context) => {
120
+ const result = await context.serviceSupabase.from('users').select();
121
+ })
122
+ ```
123
+
124
+ **Core resources** (always available):
125
+
126
+ - `context.env` - Environment variables
127
+ - `context.shutdownSignal` - AbortSignal for graceful shutdown
128
+ - `context.rawMessage` - Original pgmq message with metadata
129
+ - `context.stepTask` - Current step task details (flow handlers only)
130
+
131
+ **Supabase platform resources**:
132
+
133
+ - `context.sql` - PostgreSQL client (postgres.js)
134
+ - `context.anonSupabase` - Supabase client with anonymous key
135
+ - `context.serviceSupabase` - Supabase client with service role key
136
+
137
+ To use Supabase resources in flows, import from the Supabase preset:
138
+
139
+ ```typescript
140
+ import { Flow } from '@pgflow/dsl/supabase';
141
+ ```
142
+
143
+ The context parameter is optional for backward compatibility - existing single-parameter handlers continue to work unchanged.
144
+
145
+ ## 0.5.3
146
+
147
+ ### Patch Changes
148
+
149
+ - af787ff: Add `startDelay` option for workflow steps
150
+
151
+ Introduces the ability to delay a step's **initial execution** by a specified number of seconds, enabling multi-day workflows and scheduled tasks within pgflow.
152
+
153
+ **Important**: `startDelay` only applies to the first execution attempt. Retries use the standard exponential backoff mechanism based on `baseDelay`, not `startDelay`.
154
+
155
+ ### Core Changes (@pgflow/core)
156
+
157
+ - Added `opt_start_delay` column (integer, nullable, CHECK >= 0) to `pgflow.steps` table
158
+ - Updated `add_step` function to accept and validate the new `start_delay` parameter
159
+ - Modified `start_ready_steps` to schedule initial task execution with delay via `pgmq.send(queue, message, delay)`
160
+ - Requires pgmq >= 0.40 for delay support
161
+ - Migration: `20250707210212_pgflow_add_opt_start_delay.sql`
162
+ - Added comprehensive PgTAP tests for validation and scheduling behavior
163
+
164
+ ### DSL Changes (@pgflow/dsl)
165
+
166
+ - Extended `StepOptions` and `StepRuntimeOptions` interfaces with optional `startDelay` (in seconds)
167
+ - Updated `compileFlow()` to emit `start_delay => value` in generated SQL
168
+ - Added validation: `startDelay` is only allowed at step level, not flow level (prevents cascading delays)
169
+ - Valid range: 0 to 2,147,483,647 seconds (~68 years)
170
+ - Added unit tests for compilation and validation
171
+
172
+ ### Documentation Updates (@pgflow/website)
173
+
174
+ - Added `startDelay` section in configuration guide with detailed explanation
175
+ - Created multi-day workflow example (onboarding email sequence)
176
+ - Updated "Update Flow Options" to include `opt_start_delay`
177
+ - Enhanced VS comparison pages to mention "Native step delays" capability
178
+ - Documented why `startDelay` is step-level only
179
+
180
+ ### Example Usage
181
+
182
+ ```typescript
183
+ new Flow({
184
+ slug: 'user_onboarding',
185
+ maxAttempts: 3,
186
+ baseDelay: 5, // Retry delay (not initial delay)
187
+ timeout: 60,
188
+ })
189
+ .step(
190
+ {
191
+ slug: 'send_welcome_email',
192
+ // Executes immediately when step becomes ready
193
+ },
194
+ sendWelcomeHandler
195
+ )
196
+ .step(
197
+ {
198
+ slug: 'send_day_3_tips',
199
+ startDelay: 259200, // Wait 3 days before first execution
200
+ timeout: 120,
201
+ },
202
+ sendTipsHandler
203
+ )
204
+ .step(
205
+ {
206
+ slug: 'send_week_review',
207
+ startDelay: 604800, // Wait 7 days after dependencies complete
208
+ timeout: 120,
209
+ },
210
+ sendReviewHandler
211
+ );
212
+ ```
213
+
214
+ ### Use Cases
215
+
216
+ - **Multi-day workflows**: Onboarding sequences, follow-up reminders
217
+ - **Scheduled notifications**: Send reports or alerts at specific intervals
218
+ - **Rate limiting**: Enforce minimum time between API calls
219
+ - **Compliance delays**: Cooling-off periods before actions
220
+
221
+ ### Technical Notes
222
+
223
+ - Non-breaking, additive change (hence minor version bump)
224
+ - No changes required in `@pgflow/edge-worker` - delays handled by pgmq
225
+ - `startDelay` does not affect retry timing - only the initial execution
226
+ - Delays are reliable even across worker restarts (persisted in queue)
227
+
228
+ ## 0.5.2
229
+
230
+ ## 0.5.1
231
+
232
+ ## 0.5.0
233
+
234
+ ## 0.4.3
235
+
236
+ ## 0.4.2
237
+
238
+ ## 0.4.1
239
+
240
+ ## 0.4.0
241
+
242
+ ### Patch Changes
243
+
244
+ - 98556d3: Add TypeScript client library for pgflow workflow management
245
+
246
+ ## @pgflow/client
247
+
248
+ Introduces a new TypeScript client library that provides both event-based and promise-based APIs for interacting with pgflow workflows:
249
+
250
+ ### Features
251
+
252
+ - **Type-safe workflow management** with full TypeScript support and automatic type inference from flow definitions
253
+ - **Dual API approach**: Choose between event-based subscriptions or promise-based async/await patterns
254
+ - **Real-time monitoring** via Supabase broadcasts with granular event subscriptions
255
+ - **Resource management** with automatic cleanup and disposal
256
+ - **Comprehensive error handling** and recovery mechanisms
257
+
258
+ ### Core Components
259
+
260
+ - `PgflowClient` - Main client for starting and managing workflow runs
261
+ - `FlowRun` - Monitor and interact with workflow executions
262
+ - `FlowStep` - Track individual step progress and outputs
263
+
264
+ ### Example Usage
265
+
266
+ ```typescript
267
+ // Start a workflow
268
+ const pgflow = new PgflowClient(supabase);
269
+ const run = await pgflow.startFlow('analyze_website', {
270
+ url: 'https://example.com',
271
+ });
272
+
273
+ // Event-based monitoring
274
+ run.on('completed', (event) => {
275
+ console.log('Workflow completed:', event.output);
276
+ });
277
+
278
+ // Promise-based monitoring
279
+ const completed = await run.waitForStatus(FlowRunStatus.Completed, {
280
+ timeoutMs: 30000,
281
+ });
282
+ ```
283
+
284
+ ## @pgflow/core
285
+
286
+ ### Database Enhancements
287
+
288
+ - Add `start_flow_with_states()` function to start flows and return complete initial state
289
+ - Add `get_run_with_states()` function to retrieve runs with all step states efficiently
290
+ - Implement `SECURITY DEFINER` functions for secure API access
291
+ - Add real-time broadcast support for workflow state changes
292
+
293
+ ## @pgflow/edge-worker
294
+
295
+ ### Test Infrastructure Updates
296
+
297
+ - Update test database configuration to use standard PostgreSQL credentials
298
+ - Improve test helper functions for database transactions
299
+ - Update Docker Compose configuration for test environment
300
+
301
+ ## @pgflow/dsl
302
+
303
+ ### Build Configuration
304
+
305
+ - Add TypeScript references to tsconfig.spec.json for improved type checking in tests
306
+
307
+ ## 0.3.1
308
+
309
+ ## 0.3.0
310
+
311
+ ## 0.2.6
312
+
313
+ ## 0.2.5
314
+
315
+ ## 0.2.4
316
+
317
+ ## 0.2.3
318
+
319
+ ## 0.2.2
320
+
321
+ ## 0.2.1
322
+
323
+ ### Patch Changes
324
+
325
+ - 3f3174e: Update the README's
326
+
327
+ ## 0.2.0
328
+
329
+ ## 0.1.23
330
+
331
+ ## 0.1.22
332
+
333
+ ### Patch Changes
334
+
335
+ - 8f6eb3d: Added ExtractFlowLeafSteps and ExtractFlowOutput utility types
336
+
337
+ ## 0.1.21
338
+
339
+ ## 0.1.20
340
+
341
+ ## 0.1.19
342
+
343
+ ## 0.1.18
344
+
345
+ ### Patch Changes
346
+
347
+ - 3a7e132: Do not build edge-worker for npm
348
+
349
+ ## 0.1.17
350
+
351
+ ### Patch Changes
352
+
353
+ - d215ed2: Trigger version change
354
+
355
+ ## 0.1.16
356
+
357
+ ### Patch Changes
358
+
359
+ - cc7c431: Test release to verify combined publishing of both npm and jsr packages
360
+
361
+ ## 0.1.15
362
+
363
+ ### Patch Changes
364
+
365
+ - ce34a2c: Update release pipeline to publish to jsr
366
+
367
+ ## 0.1.14
368
+
369
+ ## 0.1.13
370
+
371
+ ## 0.1.12
372
+
373
+ ### Patch Changes
374
+
375
+ - 7b1328e: Include invalid slug in validateSlug error message
376
+
377
+ ## 0.1.11
378
+
379
+ ## 0.1.10
380
+
381
+ ### Patch Changes
382
+
383
+ - bafe767: Fix deno/ folder for cli being missing
384
+
385
+ ## 0.1.9
386
+
387
+ ### Patch Changes
388
+
389
+ - 1a30c6c: Make sure to tag and push tags
390
+
391
+ ## 0.1.8
392
+
393
+ ### Patch Changes
394
+
395
+ - 05f5bd8: Update release script
396
+
397
+ ## 0.1.7
398
+
399
+ ## 0.1.6
400
+
401
+ ### Patch Changes
402
+
403
+ - Test release to verify problem with bumping edge-worker
404
+
405
+ ## 0.1.5
406
+
407
+ ### Patch Changes
408
+
409
+ - 5820e7a: Bump version for tests
410
+
411
+ ## 0.1.4
412
+
413
+ ## 0.1.3
414
+
415
+ ## 0.1.2
416
+
417
+ ## 0.1.1
418
+
419
+ ### Patch Changes
420
+
421
+ - b362364: Add compileFlow function
422
+
423
+ ## 0.1.0
424
+
425
+ ## 0.0.23
426
+
427
+ ## 0.0.22
428
+
429
+ ## 0.0.21
430
+
431
+ ## 0.0.20
432
+
433
+ ## 0.0.19
434
+
435
+ ## 0.0.18
436
+
437
+ ### Patch Changes
438
+
439
+ - 53abf4a: Fix pnpm issues with linking to dist/
440
+
441
+ ## 0.0.17
442
+
443
+ ## 0.0.16
444
+
445
+ ## 0.0.15
446
+
447
+ ## 0.0.14
448
+
449
+ ## 0.0.13
450
+
451
+ ## 0.0.12
452
+
453
+ ## 0.0.11
454
+
455
+ ### Patch Changes
456
+
457
+ - 17937e3: Update changesets action and comment out custom publish
458
+
459
+ ## 0.0.10
460
+
461
+ ## 0.0.9
462
+
463
+ ### Patch Changes
464
+
465
+ - 70d3f2d: Tweak extension setting in tsconfig.base.json
466
+
467
+ ## 0.0.8
468
+
469
+ ## 0.0.7
470
+
471
+ ### Patch Changes
472
+
473
+ - 7c83db9: Add release-related options to package.json files
474
+
475
+ ## 0.0.6
476
+
477
+ ## 0.0.5
478
+
479
+ ### Patch Changes
480
+
481
+ - b4b0809: test changesets