@pgflow/dsl 0.0.0-fix-supa-version-d565b97a-20251124083521 → 0.0.0-logger-improvements-0aa6c926-20251209134018
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 +12 -12
- package/dist/CHANGELOG.md +17 -1
- package/dist/README.md +12 -12
- package/dist/flow-shape.d.ts +81 -0
- package/dist/flow-shape.d.ts.map +1 -0
- package/dist/flow-shape.js +119 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/package.json +1 -1
- package/dist/platforms/supabase.d.ts +2 -1
- package/dist/platforms/supabase.d.ts.map +1 -1
- package/package.json +1 -1
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: '
|
|
34
|
+
slug: 'analyzeWebsite',
|
|
35
35
|
maxAttempts: 3,
|
|
36
36
|
baseDelay: 5,
|
|
37
37
|
timeout: 10,
|
|
@@ -98,13 +98,13 @@ A semantic wrapper around `.step()` that provides type enforcement for steps tha
|
|
|
98
98
|
```typescript
|
|
99
99
|
// Fetch an array of items to be processed
|
|
100
100
|
.array(
|
|
101
|
-
{ slug: '
|
|
101
|
+
{ slug: 'fetchItems' },
|
|
102
102
|
async () => [1, 2, 3, 4, 5]
|
|
103
103
|
)
|
|
104
104
|
|
|
105
105
|
// With dependencies - combining data from multiple sources
|
|
106
106
|
.array(
|
|
107
|
-
{ slug: '
|
|
107
|
+
{ slug: 'combineResults', dependsOn: ['source1', 'source2'] },
|
|
108
108
|
async (input) => [...input.source1, ...input.source2]
|
|
109
109
|
)
|
|
110
110
|
```
|
|
@@ -131,7 +131,7 @@ Processes arrays element-by-element, similar to JavaScript's `Array.map()`. The
|
|
|
131
131
|
```typescript
|
|
132
132
|
// ROOT MAP - No array: property means use flow input
|
|
133
133
|
// Flow input MUST be an array (e.g., ["hello", "world"])
|
|
134
|
-
new Flow<string[]>({ slug: '
|
|
134
|
+
new Flow<string[]>({ slug: 'processStrings' })
|
|
135
135
|
.map(
|
|
136
136
|
{ slug: 'uppercase' }, // No array: property!
|
|
137
137
|
(item) => item.toUpperCase()
|
|
@@ -139,7 +139,7 @@ new Flow<string[]>({ slug: 'process_strings' })
|
|
|
139
139
|
// Each string in the input array gets uppercased in parallel
|
|
140
140
|
|
|
141
141
|
// DEPENDENT MAP - array: property specifies the source step
|
|
142
|
-
new Flow<{}>({ slug: '
|
|
142
|
+
new Flow<{}>({ slug: 'dataPipeline' })
|
|
143
143
|
.array({ slug: 'numbers' }, () => [1, 2, 3])
|
|
144
144
|
.map(
|
|
145
145
|
{ slug: 'double', array: 'numbers' }, // Processes 'numbers' output
|
|
@@ -166,7 +166,7 @@ The `.map()` method provides full TypeScript type inference for array elements:
|
|
|
166
166
|
```typescript
|
|
167
167
|
type User = { id: number; name: string };
|
|
168
168
|
|
|
169
|
-
new Flow<{}>({ slug: '
|
|
169
|
+
new Flow<{}>({ slug: 'userFlow' })
|
|
170
170
|
.array({ slug: 'users' }, (): User[] => [
|
|
171
171
|
{ id: 1, name: 'Alice' },
|
|
172
172
|
{ id: 2, name: 'Bob' }
|
|
@@ -181,7 +181,7 @@ new Flow<{}>({ slug: 'user_flow' })
|
|
|
181
181
|
|
|
182
182
|
```typescript
|
|
183
183
|
// Batch processing - process multiple items in parallel
|
|
184
|
-
new Flow<number[]>({ slug: '
|
|
184
|
+
new Flow<number[]>({ slug: 'batchProcessor' })
|
|
185
185
|
.map({ slug: 'validate' }, (item) => {
|
|
186
186
|
if (item < 0) throw new Error('Invalid item');
|
|
187
187
|
return item;
|
|
@@ -192,9 +192,9 @@ new Flow<number[]>({ slug: 'batch_processor' })
|
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
// Data transformation pipeline
|
|
195
|
-
new Flow<{}>({ slug: '
|
|
196
|
-
.step({ slug: '
|
|
197
|
-
.map({ slug: 'scrape', array: '
|
|
195
|
+
new Flow<{}>({ slug: 'etlPipeline' })
|
|
196
|
+
.step({ slug: 'fetchUrls' }, () => ['url1', 'url2', 'url3'])
|
|
197
|
+
.map({ slug: 'scrape', array: 'fetchUrls' }, async (url) => {
|
|
198
198
|
return await fetchContent(url);
|
|
199
199
|
})
|
|
200
200
|
.map({ slug: 'extract', array: 'scrape' }, (html) => {
|
|
@@ -271,7 +271,7 @@ To use Supabase resources, import the `Flow` class from the Supabase preset:
|
|
|
271
271
|
import { Flow } from '@pgflow/dsl/supabase';
|
|
272
272
|
|
|
273
273
|
const MyFlow = new Flow<{ userId: string }>({
|
|
274
|
-
slug: '
|
|
274
|
+
slug: 'myFlow',
|
|
275
275
|
}).step({ slug: 'process' }, async (input, context) => {
|
|
276
276
|
// TypeScript knows context includes Supabase resources
|
|
277
277
|
const { data } = await context.supabase
|
|
@@ -300,7 +300,7 @@ Configure flows and steps with runtime options:
|
|
|
300
300
|
|
|
301
301
|
```typescript
|
|
302
302
|
new Flow<Input>({
|
|
303
|
-
slug: '
|
|
303
|
+
slug: 'myFlow', // Required: Unique flow identifier
|
|
304
304
|
maxAttempts: 3, // Optional: Maximum retry attempts (default: 1)
|
|
305
305
|
baseDelay: 5, // Optional: Base delay in seconds for retries (default: 1)
|
|
306
306
|
timeout: 10, // Optional: Task timeout in seconds (default: 30)
|
package/dist/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
# @pgflow/dsl
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-logger-improvements-0aa6c926-20251209134018
|
|
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
|
|
4
20
|
|
|
5
21
|
## 0.8.0
|
|
6
22
|
|
package/dist/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: '
|
|
34
|
+
slug: 'analyzeWebsite',
|
|
35
35
|
maxAttempts: 3,
|
|
36
36
|
baseDelay: 5,
|
|
37
37
|
timeout: 10,
|
|
@@ -98,13 +98,13 @@ A semantic wrapper around `.step()` that provides type enforcement for steps tha
|
|
|
98
98
|
```typescript
|
|
99
99
|
// Fetch an array of items to be processed
|
|
100
100
|
.array(
|
|
101
|
-
{ slug: '
|
|
101
|
+
{ slug: 'fetchItems' },
|
|
102
102
|
async () => [1, 2, 3, 4, 5]
|
|
103
103
|
)
|
|
104
104
|
|
|
105
105
|
// With dependencies - combining data from multiple sources
|
|
106
106
|
.array(
|
|
107
|
-
{ slug: '
|
|
107
|
+
{ slug: 'combineResults', dependsOn: ['source1', 'source2'] },
|
|
108
108
|
async (input) => [...input.source1, ...input.source2]
|
|
109
109
|
)
|
|
110
110
|
```
|
|
@@ -131,7 +131,7 @@ Processes arrays element-by-element, similar to JavaScript's `Array.map()`. The
|
|
|
131
131
|
```typescript
|
|
132
132
|
// ROOT MAP - No array: property means use flow input
|
|
133
133
|
// Flow input MUST be an array (e.g., ["hello", "world"])
|
|
134
|
-
new Flow<string[]>({ slug: '
|
|
134
|
+
new Flow<string[]>({ slug: 'processStrings' })
|
|
135
135
|
.map(
|
|
136
136
|
{ slug: 'uppercase' }, // No array: property!
|
|
137
137
|
(item) => item.toUpperCase()
|
|
@@ -139,7 +139,7 @@ new Flow<string[]>({ slug: 'process_strings' })
|
|
|
139
139
|
// Each string in the input array gets uppercased in parallel
|
|
140
140
|
|
|
141
141
|
// DEPENDENT MAP - array: property specifies the source step
|
|
142
|
-
new Flow<{}>({ slug: '
|
|
142
|
+
new Flow<{}>({ slug: 'dataPipeline' })
|
|
143
143
|
.array({ slug: 'numbers' }, () => [1, 2, 3])
|
|
144
144
|
.map(
|
|
145
145
|
{ slug: 'double', array: 'numbers' }, // Processes 'numbers' output
|
|
@@ -166,7 +166,7 @@ The `.map()` method provides full TypeScript type inference for array elements:
|
|
|
166
166
|
```typescript
|
|
167
167
|
type User = { id: number; name: string };
|
|
168
168
|
|
|
169
|
-
new Flow<{}>({ slug: '
|
|
169
|
+
new Flow<{}>({ slug: 'userFlow' })
|
|
170
170
|
.array({ slug: 'users' }, (): User[] => [
|
|
171
171
|
{ id: 1, name: 'Alice' },
|
|
172
172
|
{ id: 2, name: 'Bob' }
|
|
@@ -181,7 +181,7 @@ new Flow<{}>({ slug: 'user_flow' })
|
|
|
181
181
|
|
|
182
182
|
```typescript
|
|
183
183
|
// Batch processing - process multiple items in parallel
|
|
184
|
-
new Flow<number[]>({ slug: '
|
|
184
|
+
new Flow<number[]>({ slug: 'batchProcessor' })
|
|
185
185
|
.map({ slug: 'validate' }, (item) => {
|
|
186
186
|
if (item < 0) throw new Error('Invalid item');
|
|
187
187
|
return item;
|
|
@@ -192,9 +192,9 @@ new Flow<number[]>({ slug: 'batch_processor' })
|
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
// Data transformation pipeline
|
|
195
|
-
new Flow<{}>({ slug: '
|
|
196
|
-
.step({ slug: '
|
|
197
|
-
.map({ slug: 'scrape', array: '
|
|
195
|
+
new Flow<{}>({ slug: 'etlPipeline' })
|
|
196
|
+
.step({ slug: 'fetchUrls' }, () => ['url1', 'url2', 'url3'])
|
|
197
|
+
.map({ slug: 'scrape', array: 'fetchUrls' }, async (url) => {
|
|
198
198
|
return await fetchContent(url);
|
|
199
199
|
})
|
|
200
200
|
.map({ slug: 'extract', array: 'scrape' }, (html) => {
|
|
@@ -271,7 +271,7 @@ To use Supabase resources, import the `Flow` class from the Supabase preset:
|
|
|
271
271
|
import { Flow } from '@pgflow/dsl/supabase';
|
|
272
272
|
|
|
273
273
|
const MyFlow = new Flow<{ userId: string }>({
|
|
274
|
-
slug: '
|
|
274
|
+
slug: 'myFlow',
|
|
275
275
|
}).step({ slug: 'process' }, async (input, context) => {
|
|
276
276
|
// TypeScript knows context includes Supabase resources
|
|
277
277
|
const { data } = await context.supabase
|
|
@@ -300,7 +300,7 @@ Configure flows and steps with runtime options:
|
|
|
300
300
|
|
|
301
301
|
```typescript
|
|
302
302
|
new Flow<Input>({
|
|
303
|
-
slug: '
|
|
303
|
+
slug: 'myFlow', // Required: Unique flow identifier
|
|
304
304
|
maxAttempts: 3, // Optional: Maximum retry attempts (default: 1)
|
|
305
305
|
baseDelay: 5, // Optional: Base delay in seconds for retries (default: 1)
|
|
306
306
|
timeout: 10, // Optional: Task timeout in seconds (default: 30)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { AnyFlow } from './dsl.js';
|
|
2
|
+
/**
|
|
3
|
+
* Step-level options that can be included in the shape for creation,
|
|
4
|
+
* but are NOT compared during shape comparison (runtime tunable).
|
|
5
|
+
*/
|
|
6
|
+
export interface StepShapeOptions {
|
|
7
|
+
maxAttempts?: number;
|
|
8
|
+
baseDelay?: number;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
startDelay?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Flow-level options that can be included in the shape for creation,
|
|
14
|
+
* but are NOT compared during shape comparison (runtime tunable).
|
|
15
|
+
*/
|
|
16
|
+
export interface FlowShapeOptions {
|
|
17
|
+
maxAttempts?: number;
|
|
18
|
+
baseDelay?: number;
|
|
19
|
+
timeout?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* StepShape captures the structural definition of a step for drift detection.
|
|
23
|
+
*
|
|
24
|
+
* The `options` field is included for flow creation but NOT compared during
|
|
25
|
+
* shape comparison. Options can be tuned at runtime via SQL without
|
|
26
|
+
* requiring recompilation. See: /deploy/tune-flow-config/
|
|
27
|
+
*/
|
|
28
|
+
export interface StepShape {
|
|
29
|
+
slug: string;
|
|
30
|
+
stepType: 'single' | 'map';
|
|
31
|
+
dependencies: string[];
|
|
32
|
+
options?: StepShapeOptions;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* FlowShape captures the structural definition of a flow for drift detection.
|
|
36
|
+
*
|
|
37
|
+
* This represents the DAG topology - which steps exist, their types, and how
|
|
38
|
+
* they connect via dependencies.
|
|
39
|
+
*
|
|
40
|
+
* The `options` field is included for flow creation but NOT compared during
|
|
41
|
+
* shape comparison. Options can be tuned at runtime via SQL without recompilation.
|
|
42
|
+
*
|
|
43
|
+
* Note: flowSlug is intentionally excluded - it's an identifier, not structural
|
|
44
|
+
* data. The slug comes from context (URL, registry lookup, function parameter).
|
|
45
|
+
*/
|
|
46
|
+
export interface FlowShape {
|
|
47
|
+
steps: StepShape[];
|
|
48
|
+
options?: FlowShapeOptions;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Result of comparing two FlowShapes.
|
|
52
|
+
*/
|
|
53
|
+
export interface ShapeComparisonResult {
|
|
54
|
+
match: boolean;
|
|
55
|
+
differences: string[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Extracts a FlowShape from a Flow object.
|
|
59
|
+
* The shape captures structural information needed for drift detection,
|
|
60
|
+
* plus options for flow creation.
|
|
61
|
+
*
|
|
62
|
+
* Options are included in the shape for proper flow/step creation, but
|
|
63
|
+
* are NOT compared during shape comparison (they're runtime tunable).
|
|
64
|
+
*
|
|
65
|
+
* @param flow - The Flow object to extract shape from
|
|
66
|
+
* @returns A FlowShape representing the flow's structure and options
|
|
67
|
+
*/
|
|
68
|
+
export declare function extractFlowShape(flow: AnyFlow): FlowShape;
|
|
69
|
+
/**
|
|
70
|
+
* Compares two FlowShapes and returns detailed differences.
|
|
71
|
+
* Used by ControlPlane for Layer 1 comparison (Worker vs ControlPlane).
|
|
72
|
+
*
|
|
73
|
+
* Only compares structural aspects (steps, types, dependencies).
|
|
74
|
+
* Runtime options are not compared as they can be tuned independently.
|
|
75
|
+
*
|
|
76
|
+
* @param a - First FlowShape (typically from worker)
|
|
77
|
+
* @param b - Second FlowShape (typically from ControlPlane or database)
|
|
78
|
+
* @returns ShapeComparisonResult with match status and list of differences
|
|
79
|
+
*/
|
|
80
|
+
export declare function compareFlowShapes(a: FlowShape, b: FlowShape): ShapeComparisonResult;
|
|
81
|
+
//# sourceMappingURL=flow-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-shape.d.ts","sourceRoot":"","sources":["../src/flow-shape.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAMnC;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAyBD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,CAwCzD;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,SAAS,EACZ,CAAC,EAAE,SAAS,GACX,qBAAqB,CA6BvB"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// ========================
|
|
2
|
+
// SHAPE EXTRACTION
|
|
3
|
+
// ========================
|
|
4
|
+
/**
|
|
5
|
+
* Checks if an options object has any defined (non-undefined) values.
|
|
6
|
+
*/
|
|
7
|
+
function hasDefinedOptions(options) {
|
|
8
|
+
return Object.values(options).some((v) => v !== undefined);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Filters out undefined values from an options object.
|
|
12
|
+
* Returns only the keys with defined values.
|
|
13
|
+
*/
|
|
14
|
+
function filterDefinedOptions(options) {
|
|
15
|
+
return Object.fromEntries(Object.entries(options).filter(([_, v]) => v !== undefined));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Extracts a FlowShape from a Flow object.
|
|
19
|
+
* The shape captures structural information needed for drift detection,
|
|
20
|
+
* plus options for flow creation.
|
|
21
|
+
*
|
|
22
|
+
* Options are included in the shape for proper flow/step creation, but
|
|
23
|
+
* are NOT compared during shape comparison (they're runtime tunable).
|
|
24
|
+
*
|
|
25
|
+
* @param flow - The Flow object to extract shape from
|
|
26
|
+
* @returns A FlowShape representing the flow's structure and options
|
|
27
|
+
*/
|
|
28
|
+
export function extractFlowShape(flow) {
|
|
29
|
+
const steps = flow.stepOrder.map((stepSlug) => {
|
|
30
|
+
const stepDef = flow.getStepDefinition(stepSlug);
|
|
31
|
+
const stepShape = {
|
|
32
|
+
slug: stepSlug,
|
|
33
|
+
stepType: stepDef.stepType ?? 'single',
|
|
34
|
+
// Sort dependencies alphabetically for deterministic comparison
|
|
35
|
+
dependencies: [...stepDef.dependencies].sort(),
|
|
36
|
+
};
|
|
37
|
+
// Only include options if at least one is defined
|
|
38
|
+
const stepOptions = {
|
|
39
|
+
maxAttempts: stepDef.options.maxAttempts,
|
|
40
|
+
baseDelay: stepDef.options.baseDelay,
|
|
41
|
+
timeout: stepDef.options.timeout,
|
|
42
|
+
startDelay: stepDef.options.startDelay,
|
|
43
|
+
};
|
|
44
|
+
if (hasDefinedOptions(stepOptions)) {
|
|
45
|
+
stepShape.options = filterDefinedOptions(stepOptions);
|
|
46
|
+
}
|
|
47
|
+
return stepShape;
|
|
48
|
+
});
|
|
49
|
+
const shape = { steps };
|
|
50
|
+
// Only include flow options if at least one is defined
|
|
51
|
+
const flowOptions = {
|
|
52
|
+
maxAttempts: flow.options.maxAttempts,
|
|
53
|
+
baseDelay: flow.options.baseDelay,
|
|
54
|
+
timeout: flow.options.timeout,
|
|
55
|
+
};
|
|
56
|
+
if (hasDefinedOptions(flowOptions)) {
|
|
57
|
+
shape.options = filterDefinedOptions(flowOptions);
|
|
58
|
+
}
|
|
59
|
+
return shape;
|
|
60
|
+
}
|
|
61
|
+
// ========================
|
|
62
|
+
// SHAPE COMPARISON
|
|
63
|
+
// ========================
|
|
64
|
+
/**
|
|
65
|
+
* Compares two FlowShapes and returns detailed differences.
|
|
66
|
+
* Used by ControlPlane for Layer 1 comparison (Worker vs ControlPlane).
|
|
67
|
+
*
|
|
68
|
+
* Only compares structural aspects (steps, types, dependencies).
|
|
69
|
+
* Runtime options are not compared as they can be tuned independently.
|
|
70
|
+
*
|
|
71
|
+
* @param a - First FlowShape (typically from worker)
|
|
72
|
+
* @param b - Second FlowShape (typically from ControlPlane or database)
|
|
73
|
+
* @returns ShapeComparisonResult with match status and list of differences
|
|
74
|
+
*/
|
|
75
|
+
export function compareFlowShapes(a, b) {
|
|
76
|
+
const differences = [];
|
|
77
|
+
// Compare step counts
|
|
78
|
+
if (a.steps.length !== b.steps.length) {
|
|
79
|
+
differences.push(`Step count differs: ${a.steps.length} vs ${b.steps.length}`);
|
|
80
|
+
}
|
|
81
|
+
// Compare steps by index (order matters)
|
|
82
|
+
const maxLen = Math.max(a.steps.length, b.steps.length);
|
|
83
|
+
for (let i = 0; i < maxLen; i++) {
|
|
84
|
+
const aStep = a.steps[i];
|
|
85
|
+
const bStep = b.steps[i];
|
|
86
|
+
if (!aStep) {
|
|
87
|
+
differences.push(`Step at index ${i}: missing in first shape (second has '${bStep.slug}')`);
|
|
88
|
+
}
|
|
89
|
+
else if (!bStep) {
|
|
90
|
+
differences.push(`Step at index ${i}: missing in second shape (first has '${aStep.slug}')`);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
compareSteps(aStep, bStep, i, differences);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
match: differences.length === 0,
|
|
98
|
+
differences,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Compares two steps at the same index and adds differences to the list.
|
|
103
|
+
*/
|
|
104
|
+
function compareSteps(a, b, index, differences) {
|
|
105
|
+
// Compare slug (order matters, so slugs must match at same index)
|
|
106
|
+
if (a.slug !== b.slug) {
|
|
107
|
+
differences.push(`Step at index ${index}: slug differs '${a.slug}' vs '${b.slug}'`);
|
|
108
|
+
}
|
|
109
|
+
// Compare step type
|
|
110
|
+
if (a.stepType !== b.stepType) {
|
|
111
|
+
differences.push(`Step at index ${index}: type differs '${a.stepType}' vs '${b.stepType}'`);
|
|
112
|
+
}
|
|
113
|
+
// Compare dependencies (already sorted)
|
|
114
|
+
const aDeps = a.dependencies.join(',');
|
|
115
|
+
const bDeps = b.dependencies.join(',');
|
|
116
|
+
if (aDeps !== bDeps) {
|
|
117
|
+
differences.push(`Step at index ${index}: dependencies differ [${a.dependencies.join(', ')}] vs [${b.dependencies.join(', ')}]`);
|
|
118
|
+
}
|
|
119
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/package.json
CHANGED
|
@@ -9,11 +9,12 @@ export interface SupabaseResources extends Record<string, unknown> {
|
|
|
9
9
|
supabase: SupabaseClient;
|
|
10
10
|
}
|
|
11
11
|
export interface SupabaseEnv extends Env {
|
|
12
|
-
|
|
12
|
+
SUPABASE_DB_URL: string;
|
|
13
13
|
SUPABASE_URL: string;
|
|
14
14
|
SUPABASE_ANON_KEY: string;
|
|
15
15
|
SUPABASE_SERVICE_ROLE_KEY: string;
|
|
16
16
|
SB_EXECUTION_ID: string;
|
|
17
|
+
EDGE_WORKER_DB_URL?: string;
|
|
17
18
|
EDGE_WORKER_LOG_LEVEL?: string;
|
|
18
19
|
}
|
|
19
20
|
export type SupabasePlatformContext = SupabaseResources;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/platforms/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACL,IAAI,IAAI,QAAQ,EAChB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAC1C,UAAU,EAAE,SAAS,EAAE,KAAK,GAAG,EAChC,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,iBAAkB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAChE,GAAG,EAAc,GAAG,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAS,cAAc,CAAC;CACjC;AAGD,MAAM,WAAW,WAAY,SAAQ,GAAG;IACtC,
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/platforms/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACL,IAAI,IAAI,QAAQ,EAChB,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAC1C,UAAU,EAAE,SAAS,EAAE,KAAK,GAAG,EAChC,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,iBAAkB,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAChE,GAAG,EAAc,GAAG,CAAC;IACrB;;OAEG;IACH,QAAQ,EAAS,cAAc,CAAC;CACjC;AAGD,MAAM,WAAW,WAAY,SAAQ,GAAG;IACtC,eAAe,EAAY,MAAM,CAAC;IAClC,YAAY,EAAe,MAAM,CAAC;IAClC,iBAAiB,EAAU,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;IAClC,eAAe,EAAY,MAAM,CAAC;IAClC,kBAAkB,CAAC,EAAQ,MAAM,CAAC;IAClC,qBAAqB,CAAC,EAAK,MAAM,CAAC;CACnC;AAMD,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAGxD,qBAAa,IAAI,CACf,CAAC,SAAS,QAAQ,GAAG,QAAQ,EAE7B,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,EAC9C,CAAC,SAAS,QAAQ,GAAG,UAAU,EAC/B,CAAC,SAAS,OAAO,GAAK,SAAS,EAC/B,IAAI,SAAS,GAAG,GAAG,WAAW,CAC9B,SAAQ,QAAQ,CAChB,CAAC,EACD,uBAAuB,GAAG,SAAS,EACnC,CAAC,EAAE,CAAC,EACJ,IAAI,CACL;CAAG"}
|