@pgflow/client 0.4.1

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/index.js ADDED
@@ -0,0 +1,971 @@
1
+ var N = (e) => {
2
+ throw TypeError(e);
3
+ };
4
+ var O = (e, t, s) => t.has(e) || N("Cannot " + s);
5
+ var r = (e, t, s) => (O(e, t, "read from private field"), s ? s.call(e) : t.get(e)), c = (e, t, s) => t.has(e) ? N("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, s), g = (e, t, s, n) => (O(e, t, "write to private field"), n ? n.call(e, s) : t.set(e, s), s), w = (e, t, s) => (O(e, t, "access private method"), s);
6
+ var H = (e, t, s, n) => ({
7
+ set _(i) {
8
+ g(e, t, i, s);
9
+ },
10
+ get _() {
11
+ return r(e, t, n);
12
+ }
13
+ });
14
+ import { v4 as st } from "uuid";
15
+ import { createNanoEvents as L } from "nanoevents";
16
+ var u = /* @__PURE__ */ ((e) => (e.Started = "started", e.Completed = "completed", e.Failed = "failed", e))(u || {});
17
+ function ct(e) {
18
+ return !!e && typeof e == "object" && "run_id" in e && "flow_slug" in e && !("step_slug" in e) && "status" in e && (e.status === "started" || e.status === "completed" || e.status === "failed");
19
+ }
20
+ function pt(e) {
21
+ return e.status === "started";
22
+ }
23
+ function ht(e) {
24
+ return e.status === "completed";
25
+ }
26
+ function _t(e) {
27
+ return e.status === "failed";
28
+ }
29
+ var l = /* @__PURE__ */ ((e) => (e.Created = "created", e.Started = "started", e.Completed = "completed", e.Failed = "failed", e))(l || {});
30
+ function K(e) {
31
+ return !!e && typeof e == "object" && "run_id" in e && "step_slug" in e && "status" in e && (e.status === "started" || e.status === "completed" || e.status === "failed");
32
+ }
33
+ function ft(e) {
34
+ return K(e) && e.status === "started" && "event_type" in e && e.event_type === "step:started";
35
+ }
36
+ function mt(e) {
37
+ return K(e) && e.status === "completed" && "event_type" in e && e.event_type === "step:completed";
38
+ }
39
+ function gt(e) {
40
+ return K(e) && e.status === "failed" && "event_type" in e && e.event_type === "step:failed";
41
+ }
42
+ var S, C, F, M, I, f, j, X, z, Y, Z, v, k, G;
43
+ class rt {
44
+ /**
45
+ * Creates a new instance of SupabaseBroadcastAdapter
46
+ *
47
+ * @param supabase - Supabase client instance
48
+ */
49
+ constructor(t, s = {}) {
50
+ c(this, f);
51
+ c(this, S);
52
+ c(this, C, /* @__PURE__ */ new Map());
53
+ c(this, F, L());
54
+ c(this, M);
55
+ c(this, I);
56
+ // Store unsubscribe functions per run ID for reference equality
57
+ c(this, k, /* @__PURE__ */ new Map());
58
+ g(this, S, t), g(this, M, s.reconnectDelayMs ?? 2e3), g(this, I, s.schedule ?? setTimeout);
59
+ }
60
+ /**
61
+ * Fetches flow definition metadata from the database
62
+ *
63
+ * @param flow_slug - Flow slug to fetch
64
+ */
65
+ async fetchFlowDefinition(t) {
66
+ const [s, n] = await Promise.all([
67
+ r(this, S).schema("pgflow").from("flows").select("*").eq("flow_slug", t).single(),
68
+ r(this, S).schema("pgflow").from("steps").select("*").eq("flow_slug", t).order("step_index", { ascending: !0 })
69
+ ]);
70
+ if (s.error) throw s.error;
71
+ if (!s.data) throw new Error(`Flow "${t}" not found`);
72
+ if (n.error) throw n.error;
73
+ const i = Array.isArray(n.data) ? n.data : [];
74
+ return {
75
+ flow: s.data,
76
+ steps: i
77
+ };
78
+ }
79
+ /**
80
+ * Registers a callback for run events
81
+ *
82
+ * @param callback - Function to call when run events are received
83
+ * @returns Function to unsubscribe from the event
84
+ */
85
+ onRunEvent(t) {
86
+ const s = r(this, F).on("runEvent", t);
87
+ return () => {
88
+ try {
89
+ s();
90
+ } catch (n) {
91
+ console.warn("Could not unsubscribe from run event - emitter may have been disposed", n);
92
+ }
93
+ };
94
+ }
95
+ /**
96
+ * Registers a callback for step events
97
+ *
98
+ * @param callback - Function to call when step events are received
99
+ * @returns Function to unsubscribe from the event
100
+ */
101
+ onStepEvent(t) {
102
+ const s = r(this, F).on("stepEvent", t);
103
+ return () => {
104
+ try {
105
+ s();
106
+ } catch (n) {
107
+ console.warn("Could not unsubscribe from step event - emitter may have been disposed", n);
108
+ }
109
+ };
110
+ }
111
+ /**
112
+ * Subscribes to a flow run's events
113
+ *
114
+ * @param run_id - Run ID to subscribe to
115
+ * @returns Function to unsubscribe
116
+ */
117
+ async subscribeToRun(t) {
118
+ const s = `pgflow:run:${t}`;
119
+ if (r(this, C).has(t)) {
120
+ const _ = r(this, k).get(t);
121
+ if (_)
122
+ return _;
123
+ w(this, f, G).call(this, t);
124
+ }
125
+ const n = r(this, S).channel(s);
126
+ n.on("broadcast", { event: "*" }, w(this, f, j).bind(this)), n.on("system", { event: "closed" }, () => {
127
+ console.log(`Channel ${s} closed`);
128
+ }), n.on("system", { event: "error" }, (_) => {
129
+ console.log(`Channel ${s} error:`, _), w(this, f, z).call(this, t, s, n, _.error);
130
+ }), console.log(`Subscribing to channel ${s}...`), await new Promise((_, h) => {
131
+ const d = setTimeout(() => {
132
+ h(new Error(`Subscription timeout for channel ${s}`));
133
+ }, 2e4);
134
+ n.subscribe((m) => {
135
+ console.log(`Channel ${s} subscription status:`, m), m === "SUBSCRIBED" && (clearTimeout(d), _());
136
+ });
137
+ }), r(this, C).set(t, n);
138
+ const a = () => this.unsubscribe(t);
139
+ return r(this, k).set(t, a), a;
140
+ }
141
+ /**
142
+ * Unsubscribes from a run's events
143
+ *
144
+ * @param run_id - Run ID to unsubscribe from
145
+ */
146
+ unsubscribe(t) {
147
+ w(this, f, G).call(this, t);
148
+ }
149
+ /**
150
+ * Fetches current state of a run and its steps
151
+ *
152
+ * @param run_id - Run ID to fetch
153
+ */
154
+ async getRunWithStates(t) {
155
+ const { data: s, error: n } = await r(this, S).schema("pgflow").rpc("get_run_with_states", { run_id: t });
156
+ if (n) throw n;
157
+ if (!s) throw new Error(`No data returned for run ${t}`);
158
+ return s;
159
+ }
160
+ }
161
+ S = new WeakMap(), C = new WeakMap(), F = new WeakMap(), M = new WeakMap(), I = new WeakMap(), f = new WeakSet(), /**
162
+ * Handle broadcast messages from Supabase
163
+ * @param payload - The message payload
164
+ */
165
+ j = function(t) {
166
+ const { event: s, payload: n } = t, i = n;
167
+ w(this, f, X).call(this, i), s.startsWith("run:") ? r(this, F).emit("runEvent", i) : s.startsWith("step:") && r(this, F).emit("stepEvent", i);
168
+ }, /**
169
+ * Parse JSON string fields in broadcast event data
170
+ * @param eventData - The event data object to parse
171
+ */
172
+ X = function(t) {
173
+ if ("output" in t && typeof t.output == "string")
174
+ try {
175
+ t.output = JSON.parse(t.output);
176
+ } catch {
177
+ }
178
+ if ("input" in t && typeof t.input == "string")
179
+ try {
180
+ t.input = JSON.parse(t.input);
181
+ } catch {
182
+ }
183
+ }, z = async function(t, s, n, i) {
184
+ console.error(`Channel ${s} error:`, i), r(this, I).call(this, async () => {
185
+ r(this, C).has(t) && await w(this, f, Z).call(this, t, s);
186
+ }, r(this, M));
187
+ }, /**
188
+ * Creates and configures a channel for a run
189
+ * @param run_id - The run ID
190
+ * @param channelName - The channel name
191
+ * @returns The configured RealtimeChannel
192
+ */
193
+ Y = function(t, s) {
194
+ const n = r(this, S).channel(s);
195
+ return n.on("broadcast", { event: "*" }, w(this, f, j).bind(this)), n;
196
+ }, Z = async function(t, s) {
197
+ console.log(`Attempting to reconnect to ${s}`);
198
+ try {
199
+ const n = await this.getRunWithStates(t);
200
+ w(this, f, v).call(this, t, n);
201
+ const i = w(this, f, Y).call(this, t, s);
202
+ i.on("system", { event: "subscribed" }, () => {
203
+ console.log(`Reconnected and subscribed to channel ${s}`);
204
+ }), i.on("system", { event: "closed" }, () => {
205
+ console.log(`Reconnected channel ${s} closed`);
206
+ }), i.on(
207
+ "system",
208
+ { event: "error" },
209
+ (a) => w(this, f, z).call(this, t, s, i, a.error)
210
+ ), i.subscribe(), r(this, C).set(t, i);
211
+ } catch (n) {
212
+ console.error(`Failed to reconnect to ${s}:`, n);
213
+ }
214
+ }, /**
215
+ * Refresh client state from a state snapshot
216
+ * @param run_id - The run ID
217
+ * @param state - The state snapshot
218
+ */
219
+ v = function(t, s) {
220
+ if (!s || !s.run) return;
221
+ const n = {
222
+ event_type: `run:${s.run.status}`,
223
+ ...s.run
224
+ };
225
+ if (r(this, F).emit("runEvent", n), s.steps && Array.isArray(s.steps))
226
+ for (const i of s.steps) {
227
+ const a = {
228
+ event_type: `step:${i.status}`,
229
+ ...i
230
+ };
231
+ r(this, F).emit("stepEvent", a);
232
+ }
233
+ }, k = new WeakMap(), /**
234
+ * Unsubscribes from a run's events
235
+ *
236
+ * @param run_id - Run ID to unsubscribe from
237
+ */
238
+ G = function(t) {
239
+ const s = r(this, C).get(t);
240
+ s && (s.unsubscribe(), r(this, C).delete(t), r(this, k).delete(t));
241
+ };
242
+ var p, $, W, J, tt;
243
+ class nt {
244
+ /**
245
+ * Creates a new FlowStep instance
246
+ *
247
+ * @param initialState - Initial state for the step
248
+ */
249
+ constructor(t) {
250
+ c(this, J);
251
+ c(this, p);
252
+ c(this, $, L());
253
+ c(this, W, {
254
+ [l.Created]: 0,
255
+ [l.Started]: 1,
256
+ [l.Completed]: 2,
257
+ [l.Failed]: 3
258
+ });
259
+ g(this, p, t);
260
+ }
261
+ /**
262
+ * Get the run ID this step belongs to
263
+ */
264
+ get run_id() {
265
+ return r(this, p).run_id;
266
+ }
267
+ /**
268
+ * Get the step slug
269
+ */
270
+ get step_slug() {
271
+ return r(this, p).step_slug;
272
+ }
273
+ /**
274
+ * Get the current status
275
+ */
276
+ get status() {
277
+ return r(this, p).status;
278
+ }
279
+ /**
280
+ * Get the started_at timestamp
281
+ */
282
+ get started_at() {
283
+ return r(this, p).started_at;
284
+ }
285
+ /**
286
+ * Get the completed_at timestamp
287
+ */
288
+ get completed_at() {
289
+ return r(this, p).completed_at;
290
+ }
291
+ /**
292
+ * Get the failed_at timestamp
293
+ */
294
+ get failed_at() {
295
+ return r(this, p).failed_at;
296
+ }
297
+ /**
298
+ * Get the step output
299
+ */
300
+ get output() {
301
+ return r(this, p).output;
302
+ }
303
+ /**
304
+ * Get the error object
305
+ */
306
+ get error() {
307
+ return r(this, p).error;
308
+ }
309
+ /**
310
+ * Get the error message
311
+ */
312
+ get error_message() {
313
+ return r(this, p).error_message;
314
+ }
315
+ /**
316
+ * Register an event handler for a step event
317
+ *
318
+ * @param event - Event type to listen for
319
+ * @param callback - Callback function to execute when event is emitted
320
+ * @returns Function to unsubscribe from the event
321
+ */
322
+ on(t, s) {
323
+ return r(this, $).on(t, s);
324
+ }
325
+ /**
326
+ * Wait for the step to reach a specific status
327
+ *
328
+ * @param targetStatus - The status to wait for
329
+ * @param options - Optional timeout and abort signal
330
+ * @returns Promise that resolves with the step instance when the status is reached
331
+ */
332
+ waitForStatus(t, s) {
333
+ const n = (s == null ? void 0 : s.timeoutMs) ?? 3e5, { signal: i } = s || {};
334
+ return this.status === t ? Promise.resolve(this) : new Promise((a, _) => {
335
+ let h, d = !1;
336
+ n > 0 && (h = setTimeout(() => {
337
+ d || (d = !0, A(), _(new Error(`Timeout waiting for step ${this.step_slug} to reach status '${t}'`)));
338
+ }, n));
339
+ let m;
340
+ if (i) {
341
+ const E = () => {
342
+ d || (d = !0, h && clearTimeout(h), A(), _(new Error(`Aborted waiting for step ${this.step_slug} to reach status '${t}'`)));
343
+ };
344
+ i.addEventListener("abort", E), m = () => {
345
+ i.removeEventListener("abort", E);
346
+ };
347
+ }
348
+ const A = this.on("*", (E) => {
349
+ if (E.status === t) {
350
+ if (d) return;
351
+ d = !0, h && clearTimeout(h), m && m(), A(), a(this);
352
+ }
353
+ });
354
+ });
355
+ }
356
+ /**
357
+ * Updates the step state based on an event
358
+ *
359
+ * @internal This method is only intended for use by FlowRun and tests.
360
+ * Applications should not call this directly - state updates should come from
361
+ * database events through the PgflowClient.
362
+ *
363
+ * TODO: After v1.0, make this method private and refactor tests to use PgflowClient
364
+ * with event emission instead of direct state manipulation.
365
+ */
366
+ updateState(t) {
367
+ if (t.step_slug !== r(this, p).step_slug || t.run_id !== r(this, p).run_id || !w(this, J, tt).call(this, r(this, p).status, t.status))
368
+ return !1;
369
+ switch (t.status) {
370
+ case l.Started:
371
+ g(this, p, {
372
+ ...r(this, p),
373
+ status: l.Started,
374
+ started_at: typeof t.started_at == "string" ? new Date(t.started_at) : /* @__PURE__ */ new Date()
375
+ }), r(this, $).emit("started", t);
376
+ break;
377
+ case l.Completed:
378
+ g(this, p, {
379
+ ...r(this, p),
380
+ status: l.Completed,
381
+ completed_at: typeof t.completed_at == "string" ? new Date(t.completed_at) : /* @__PURE__ */ new Date(),
382
+ output: t.output
383
+ }), r(this, $).emit("completed", t);
384
+ break;
385
+ case l.Failed:
386
+ g(this, p, {
387
+ ...r(this, p),
388
+ status: l.Failed,
389
+ failed_at: typeof t.failed_at == "string" ? new Date(t.failed_at) : /* @__PURE__ */ new Date(),
390
+ error_message: typeof t.error_message == "string" ? t.error_message : "Unknown error",
391
+ error: new Error(typeof t.error_message == "string" ? t.error_message : "Unknown error")
392
+ }), r(this, $).emit("failed", t);
393
+ break;
394
+ default:
395
+ return !1;
396
+ }
397
+ return r(this, $).emit("*", t), !0;
398
+ }
399
+ }
400
+ p = new WeakMap(), $ = new WeakMap(), W = new WeakMap(), J = new WeakSet(), /**
401
+ * Determines if a status should be updated based on precedence
402
+ *
403
+ * @param currentStatus - Current status
404
+ * @param newStatus - New status
405
+ * @returns true if the status should be updated, false otherwise
406
+ */
407
+ tt = function(t, s) {
408
+ if (t === l.Completed || t === l.Failed)
409
+ return !1;
410
+ const n = r(this, W)[t];
411
+ return r(this, W)[s] > n;
412
+ };
413
+ var o, R, D, x, U, P, T, B, et;
414
+ class Q {
415
+ /**
416
+ * Creates a new FlowRun instance
417
+ *
418
+ * @param initialState - Initial state for the run
419
+ */
420
+ constructor(t) {
421
+ c(this, T);
422
+ c(this, o);
423
+ c(this, R, L());
424
+ c(this, D, /* @__PURE__ */ new Map());
425
+ c(this, x, {
426
+ [u.Started]: 0,
427
+ [u.Completed]: 1,
428
+ [u.Failed]: 2
429
+ });
430
+ c(this, U, !1);
431
+ // Track number of listeners
432
+ c(this, P, 0);
433
+ g(this, o, t);
434
+ }
435
+ /**
436
+ * Get the run ID
437
+ */
438
+ get run_id() {
439
+ return r(this, o).run_id;
440
+ }
441
+ /**
442
+ * Get the flow slug
443
+ */
444
+ get flow_slug() {
445
+ return r(this, o).flow_slug;
446
+ }
447
+ /**
448
+ * Get the current status
449
+ */
450
+ get status() {
451
+ return r(this, o).status;
452
+ }
453
+ /**
454
+ * Get the started_at timestamp
455
+ */
456
+ get started_at() {
457
+ return r(this, o).started_at;
458
+ }
459
+ /**
460
+ * Get the completed_at timestamp
461
+ */
462
+ get completed_at() {
463
+ return r(this, o).completed_at;
464
+ }
465
+ /**
466
+ * Get the failed_at timestamp
467
+ */
468
+ get failed_at() {
469
+ return r(this, o).failed_at;
470
+ }
471
+ /**
472
+ * Get the flow input
473
+ */
474
+ get input() {
475
+ return r(this, o).input;
476
+ }
477
+ /**
478
+ * Get the flow output
479
+ */
480
+ get output() {
481
+ return r(this, o).output;
482
+ }
483
+ /**
484
+ * Get the error object
485
+ */
486
+ get error() {
487
+ return r(this, o).error;
488
+ }
489
+ /**
490
+ * Get the error message
491
+ */
492
+ get error_message() {
493
+ return r(this, o).error_message;
494
+ }
495
+ /**
496
+ * Get the number of remaining steps
497
+ */
498
+ get remaining_steps() {
499
+ return r(this, o).remaining_steps;
500
+ }
501
+ /**
502
+ * Register an event handler for a run event
503
+ *
504
+ * @param event - Event type to listen for
505
+ * @param callback - Callback function to execute when event is emitted
506
+ * @returns Function to unsubscribe from the event
507
+ */
508
+ on(t, s) {
509
+ H(this, P)._++;
510
+ const n = r(this, R).on(t, s);
511
+ return () => {
512
+ n(), H(this, P)._--, w(this, T, B).call(this);
513
+ };
514
+ }
515
+ /**
516
+ * Get a FlowStep instance for a specific step
517
+ *
518
+ * @param stepSlug - Step slug to get
519
+ * @returns FlowStep instance for the specified step
520
+ */
521
+ step(t) {
522
+ const s = r(this, D).get(t);
523
+ if (s)
524
+ return s;
525
+ const n = new nt({
526
+ run_id: this.run_id,
527
+ step_slug: t,
528
+ status: l.Created,
529
+ output: null,
530
+ error: null,
531
+ error_message: null,
532
+ started_at: null,
533
+ completed_at: null,
534
+ failed_at: null
535
+ });
536
+ return r(this, D).set(
537
+ t,
538
+ n
539
+ ), n;
540
+ }
541
+ /**
542
+ * Check if this run has a specific step
543
+ *
544
+ * @param stepSlug - Step slug to check
545
+ * @returns true if the step exists, false otherwise
546
+ */
547
+ hasStep(t) {
548
+ return r(this, D).has(t);
549
+ }
550
+ /**
551
+ * Wait for the run to reach a specific status
552
+ *
553
+ * @param targetStatus - The status to wait for
554
+ * @param options - Optional timeout and abort signal
555
+ * @returns Promise that resolves with the run instance when the status is reached
556
+ */
557
+ waitForStatus(t, s) {
558
+ const n = (s == null ? void 0 : s.timeoutMs) ?? 3e5, { signal: i } = s || {};
559
+ return this.status === t ? Promise.resolve(this) : new Promise((a, _) => {
560
+ let h, d = !1;
561
+ n > 0 && (h = setTimeout(() => {
562
+ d || (d = !0, A(), _(
563
+ new Error(
564
+ `Timeout waiting for run ${this.run_id} to reach status '${t}'`
565
+ )
566
+ ));
567
+ }, n));
568
+ let m;
569
+ if (i) {
570
+ const E = () => {
571
+ d || (d = !0, h && clearTimeout(h), A(), _(
572
+ new Error(
573
+ `Aborted waiting for run ${this.run_id} to reach status '${t}'`
574
+ )
575
+ ));
576
+ };
577
+ i.addEventListener("abort", E), m = () => {
578
+ i.removeEventListener("abort", E);
579
+ };
580
+ }
581
+ const A = this.on("*", (E) => {
582
+ if (E.status === t) {
583
+ if (d) return;
584
+ d = !0, h && clearTimeout(h), m && m(), A(), a(this);
585
+ }
586
+ });
587
+ });
588
+ }
589
+ /**
590
+ * Updates the run state based on an event
591
+ *
592
+ * @internal This method is only intended for use by PgflowClient and tests.
593
+ * Applications should not call this directly - state updates should come from
594
+ * database events through the PgflowClient.
595
+ *
596
+ * TODO: After v1.0, make this method private and refactor tests to use PgflowClient
597
+ * with event emission instead of direct state manipulation.
598
+ */
599
+ updateState(t) {
600
+ if (t.run_id !== r(this, o).run_id || !w(this, T, et).call(this, r(this, o).status, t.status))
601
+ return !1;
602
+ switch (t.status) {
603
+ case u.Started:
604
+ g(this, o, {
605
+ ...r(this, o),
606
+ status: u.Started,
607
+ started_at: typeof t.started_at == "string" ? new Date(t.started_at) : /* @__PURE__ */ new Date(),
608
+ remaining_steps: "remaining_steps" in t ? Number(t.remaining_steps) : r(this, o).remaining_steps
609
+ }), r(this, R).emit("started", t);
610
+ break;
611
+ case u.Completed:
612
+ g(this, o, {
613
+ ...r(this, o),
614
+ status: u.Completed,
615
+ completed_at: typeof t.completed_at == "string" ? new Date(t.completed_at) : /* @__PURE__ */ new Date(),
616
+ output: t.output,
617
+ remaining_steps: 0
618
+ }), r(this, R).emit("completed", t), w(this, T, B).call(this);
619
+ break;
620
+ case u.Failed:
621
+ g(this, o, {
622
+ ...r(this, o),
623
+ status: u.Failed,
624
+ failed_at: typeof t.failed_at == "string" ? new Date(t.failed_at) : /* @__PURE__ */ new Date(),
625
+ error_message: typeof t.error_message == "string" ? t.error_message : "Unknown error",
626
+ error: new Error(
627
+ typeof t.error_message == "string" ? t.error_message : "Unknown error"
628
+ )
629
+ }), r(this, R).emit("failed", t), w(this, T, B).call(this);
630
+ break;
631
+ default:
632
+ return !1;
633
+ }
634
+ return r(this, R).emit("*", t), !0;
635
+ }
636
+ /**
637
+ * Updates a step state based on an event
638
+ *
639
+ * @param stepSlug - Step slug to update
640
+ * @param event - Event data to update the step with
641
+ * @returns true if the state was updated, false otherwise
642
+ */
643
+ updateStepState(t, s) {
644
+ return this.step(t).updateState(s);
645
+ }
646
+ /**
647
+ * Clean up all resources held by this run
648
+ */
649
+ dispose() {
650
+ r(this, U) || (r(this, D).clear(), g(this, R, L()), g(this, P, 0), g(this, U, !0));
651
+ }
652
+ }
653
+ o = new WeakMap(), R = new WeakMap(), D = new WeakMap(), x = new WeakMap(), U = new WeakMap(), P = new WeakMap(), T = new WeakSet(), /**
654
+ * Checks if auto-dispose should be triggered (when in terminal state with no listeners)
655
+ */
656
+ B = function() {
657
+ r(this, U) || this.status !== u.Completed && this.status !== u.Failed || r(this, P) === 0 && this.dispose();
658
+ }, /**
659
+ * Determines if a status should be updated based on precedence
660
+ *
661
+ * @param currentStatus - Current status
662
+ * @param newStatus - New status
663
+ * @returns true if the status should be updated, false otherwise
664
+ */
665
+ et = function(t, s) {
666
+ if (t === u.Completed || t === u.Failed)
667
+ return !1;
668
+ const n = r(this, x)[t];
669
+ return r(this, x)[s] > n;
670
+ };
671
+ function it(e) {
672
+ switch (e.status) {
673
+ case u.Started:
674
+ return {
675
+ event_type: "run:started",
676
+ run_id: e.run_id,
677
+ flow_slug: e.flow_slug,
678
+ status: u.Started,
679
+ started_at: e.started_at,
680
+ remaining_steps: e.remaining_steps,
681
+ input: e.input
682
+ };
683
+ case u.Completed:
684
+ return {
685
+ event_type: "run:completed",
686
+ run_id: e.run_id,
687
+ flow_slug: e.flow_slug,
688
+ status: u.Completed,
689
+ completed_at: e.completed_at,
690
+ output: e.output
691
+ };
692
+ case u.Failed:
693
+ return {
694
+ event_type: "run:failed",
695
+ run_id: e.run_id,
696
+ flow_slug: e.flow_slug,
697
+ status: u.Failed,
698
+ failed_at: e.failed_at,
699
+ error_message: e.error_message
700
+ };
701
+ }
702
+ }
703
+ function at(e) {
704
+ switch (e.status) {
705
+ case l.Started:
706
+ return {
707
+ event_type: "step:started",
708
+ run_id: e.run_id,
709
+ step_slug: e.step_slug,
710
+ status: l.Started,
711
+ started_at: e.started_at
712
+ };
713
+ case l.Completed:
714
+ return {
715
+ event_type: "step:completed",
716
+ run_id: e.run_id,
717
+ step_slug: e.step_slug,
718
+ status: l.Completed,
719
+ completed_at: e.completed_at,
720
+ output: e.output
721
+ };
722
+ case l.Failed:
723
+ return {
724
+ event_type: "step:failed",
725
+ run_id: e.run_id,
726
+ step_slug: e.step_slug,
727
+ status: l.Failed,
728
+ failed_at: e.failed_at,
729
+ error_message: e.error_message
730
+ };
731
+ }
732
+ }
733
+ function ut(e) {
734
+ switch (e.status) {
735
+ case "started":
736
+ return {
737
+ event_type: "run:started",
738
+ run_id: e.run_id,
739
+ flow_slug: e.flow_slug,
740
+ status: u.Started,
741
+ started_at: e.started_at,
742
+ remaining_steps: e.remaining_steps,
743
+ input: e.input
744
+ };
745
+ case "completed":
746
+ return {
747
+ event_type: "run:completed",
748
+ run_id: e.run_id,
749
+ flow_slug: e.flow_slug,
750
+ status: u.Completed,
751
+ completed_at: e.completed_at,
752
+ output: e.output
753
+ };
754
+ case "failed":
755
+ return {
756
+ event_type: "run:failed",
757
+ run_id: e.run_id,
758
+ flow_slug: e.flow_slug,
759
+ status: u.Failed,
760
+ failed_at: e.failed_at,
761
+ error_message: "Flow failed"
762
+ // Database doesn't have error_message for runs
763
+ };
764
+ default:
765
+ throw new Error(`Unknown run status: ${e.status}`);
766
+ }
767
+ }
768
+ function V(e) {
769
+ switch (e.status) {
770
+ case "created":
771
+ case "started":
772
+ return {
773
+ event_type: "step:started",
774
+ run_id: e.run_id,
775
+ step_slug: e.step_slug,
776
+ status: l.Started,
777
+ started_at: e.started_at
778
+ };
779
+ case "completed":
780
+ return {
781
+ event_type: "step:completed",
782
+ run_id: e.run_id,
783
+ step_slug: e.step_slug,
784
+ status: l.Completed,
785
+ completed_at: e.completed_at,
786
+ output: {}
787
+ // Database doesn't have output in step_states
788
+ };
789
+ case "failed":
790
+ return {
791
+ event_type: "step:failed",
792
+ run_id: e.run_id,
793
+ step_slug: e.step_slug,
794
+ status: l.Failed,
795
+ failed_at: e.failed_at,
796
+ error_message: e.error_message || "Step failed"
797
+ };
798
+ default:
799
+ throw new Error(`Unknown step status: ${e.status}`);
800
+ }
801
+ }
802
+ var q, b, y;
803
+ class wt {
804
+ /**
805
+ * Creates a new PgflowClient instance
806
+ *
807
+ * @param supabaseClient - Supabase client instance
808
+ */
809
+ constructor(t) {
810
+ c(this, q);
811
+ c(this, b);
812
+ // Use the widest event type - keeps the compiler happy but
813
+ // still provides the structural API we need (updateState/step/...)
814
+ c(this, y, /* @__PURE__ */ new Map());
815
+ g(this, q, t), g(this, b, new rt(t)), r(this, b).onRunEvent((s) => {
816
+ const n = r(this, y).get(s.run_id);
817
+ n && n.updateState(it(s));
818
+ }), r(this, b).onStepEvent((s) => {
819
+ const n = r(this, y).get(s.run_id);
820
+ if (n) {
821
+ const i = s.step_slug;
822
+ n.step(i).updateState(at(s));
823
+ }
824
+ });
825
+ }
826
+ /**
827
+ * Start a flow with optional run_id
828
+ *
829
+ * @param flow_slug - Flow slug to start
830
+ * @param input - Input data for the flow
831
+ * @param run_id - Optional run ID (will be generated if not provided)
832
+ * @returns Promise that resolves with the FlowRun instance
833
+ */
834
+ async startFlow(t, s, n) {
835
+ const i = n || st(), a = {
836
+ run_id: i,
837
+ flow_slug: t,
838
+ status: u.Started,
839
+ input: s,
840
+ output: null,
841
+ error: null,
842
+ error_message: null,
843
+ started_at: null,
844
+ completed_at: null,
845
+ failed_at: null,
846
+ remaining_steps: -1
847
+ // Use -1 to indicate unknown until first snapshot arrives
848
+ }, _ = new Q(a);
849
+ r(this, y).set(i, _), await r(this, b).subscribeToRun(i);
850
+ const { data: h, error: d } = await r(this, q).schema("pgflow").rpc("start_flow_with_states", {
851
+ flow_slug: t,
852
+ input: s,
853
+ run_id: i
854
+ });
855
+ if (d)
856
+ throw this.dispose(i), d;
857
+ if (h.run && _.updateState(ut(h.run)), h.steps && Array.isArray(h.steps))
858
+ for (const m of h.steps)
859
+ _.step(m.step_slug).updateState(V(m));
860
+ return _;
861
+ }
862
+ /**
863
+ * Dispose a specific flow run
864
+ *
865
+ * @param runId - Run ID to dispose
866
+ */
867
+ dispose(t) {
868
+ const s = r(this, y).get(t);
869
+ s && (r(this, b).unsubscribe(t), s.dispose(), r(this, y).delete(t));
870
+ }
871
+ /**
872
+ * Dispose all flow runs
873
+ */
874
+ disposeAll() {
875
+ for (const t of r(this, y).keys())
876
+ this.dispose(t);
877
+ }
878
+ // Delegate IFlowRealtime methods to the adapter
879
+ /**
880
+ * Fetch flow definition metadata
881
+ */
882
+ async fetchFlowDefinition(t) {
883
+ return r(this, b).fetchFlowDefinition(t);
884
+ }
885
+ /**
886
+ * Register a callback for run events
887
+ * @returns Function to unsubscribe from the event
888
+ */
889
+ onRunEvent(t) {
890
+ return r(this, b).onRunEvent(t);
891
+ }
892
+ /**
893
+ * Register a callback for step events
894
+ * @returns Function to unsubscribe from the event
895
+ */
896
+ onStepEvent(t) {
897
+ return r(this, b).onStepEvent(t);
898
+ }
899
+ /**
900
+ * Subscribe to a flow run's events
901
+ */
902
+ async subscribeToRun(t) {
903
+ return await r(this, b).subscribeToRun(t);
904
+ }
905
+ /**
906
+ * Fetch current state of a run and its steps
907
+ */
908
+ async getRunWithStates(t) {
909
+ return r(this, b).getRunWithStates(t);
910
+ }
911
+ /**
912
+ * Get a flow run by ID
913
+ *
914
+ * @param run_id - ID of the run to get
915
+ * @returns Promise that resolves with the FlowRun instance or null if not found
916
+ */
917
+ async getRun(t) {
918
+ const s = r(this, y).get(t);
919
+ if (s)
920
+ return s;
921
+ try {
922
+ const { run: n, steps: i } = await this.getRunWithStates(t);
923
+ if (!n)
924
+ return null;
925
+ const a = n;
926
+ if (!a.run_id || !a.flow_slug || !a.status)
927
+ throw new Error("Invalid run data: missing required fields");
928
+ if (!Object.values(u).includes(a.status))
929
+ throw new Error(`Invalid run data: invalid status '${a.status}'`);
930
+ const h = {
931
+ run_id: a.run_id,
932
+ flow_slug: a.flow_slug,
933
+ status: a.status,
934
+ input: a.input,
935
+ output: a.output,
936
+ error: a.error_message ? new Error(a.error_message) : null,
937
+ error_message: a.error_message || null,
938
+ started_at: a.started_at ? new Date(a.started_at) : null,
939
+ completed_at: a.completed_at ? new Date(a.completed_at) : null,
940
+ failed_at: a.failed_at ? new Date(a.failed_at) : null,
941
+ remaining_steps: a.remaining_steps || 0
942
+ }, d = new Q(h);
943
+ if (r(this, y).set(t, d), await r(this, b).subscribeToRun(t), i && Array.isArray(i))
944
+ for (const m of i) {
945
+ if (!m.step_slug || !m.status)
946
+ throw new Error("Invalid step data: missing required fields");
947
+ d.step(m.step_slug).updateState(V(m));
948
+ }
949
+ return d;
950
+ } catch (n) {
951
+ if (console.error("Error getting run:", n), n instanceof Error && (n.message.includes("Invalid run data") || n.message.includes("Invalid step data")))
952
+ throw n;
953
+ return null;
954
+ }
955
+ }
956
+ }
957
+ q = new WeakMap(), b = new WeakMap(), y = new WeakMap();
958
+ export {
959
+ u as FlowRunStatus,
960
+ l as FlowStepStatus,
961
+ wt as PgflowClient,
962
+ ht as isFlowRunCompletedEvent,
963
+ ct as isFlowRunEvent,
964
+ _t as isFlowRunFailedEvent,
965
+ pt as isFlowRunStartedEvent,
966
+ mt as isStepCompletedEvent,
967
+ K as isStepEvent,
968
+ gt as isStepFailedEvent,
969
+ ft as isStepStartedEvent
970
+ };
971
+ //# sourceMappingURL=index.js.map