@pgflow/client 0.0.0-array-map-steps-cd94242a-20251008042921 → 0.0.0-compatible-flow-86a8ccf0-20260319203539

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +171 -3
  2. package/README.md +6 -2
  3. package/dist/client/src/browser.d.ts +7 -0
  4. package/dist/client/src/browser.d.ts.map +1 -0
  5. package/dist/client/src/index.d.ts +6 -0
  6. package/dist/client/src/index.d.ts.map +1 -0
  7. package/dist/client/src/lib/FlowRun.d.ts +125 -0
  8. package/dist/client/src/lib/FlowRun.d.ts.map +1 -0
  9. package/dist/client/src/lib/FlowStep.d.ts +98 -0
  10. package/dist/client/src/lib/FlowStep.d.ts.map +1 -0
  11. package/dist/client/src/lib/PgflowClient.d.ts +76 -0
  12. package/dist/client/src/lib/PgflowClient.d.ts.map +1 -0
  13. package/dist/client/src/lib/SupabaseBroadcastAdapter.d.ts +66 -0
  14. package/dist/client/src/lib/SupabaseBroadcastAdapter.d.ts.map +1 -0
  15. package/dist/client/src/lib/eventAdapters.d.ts +21 -0
  16. package/dist/client/src/lib/eventAdapters.d.ts.map +1 -0
  17. package/dist/client/src/lib/types.d.ts +337 -0
  18. package/dist/client/src/lib/types.d.ts.map +1 -0
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.js +455 -454
  21. package/dist/index.js.map +1 -1
  22. package/dist/package.json +8 -3
  23. package/dist/pgflow-client.browser.js +1 -1
  24. package/dist/pgflow-client.browser.js.map +1 -1
  25. package/dist/src/browser.d.ts +3 -3
  26. package/dist/src/browser.d.ts.map +1 -1
  27. package/dist/src/browser.js +10 -0
  28. package/dist/src/index.js +7 -0
  29. package/dist/src/lib/FlowRun.d.ts +11 -3
  30. package/dist/src/lib/FlowRun.d.ts.map +1 -1
  31. package/dist/src/lib/FlowRun.js +372 -0
  32. package/dist/src/lib/FlowStep.d.ts +20 -4
  33. package/dist/src/lib/FlowStep.d.ts.map +1 -1
  34. package/dist/src/lib/FlowStep.js +284 -0
  35. package/dist/src/lib/PgflowClient.d.ts +12 -10
  36. package/dist/src/lib/PgflowClient.d.ts.map +1 -1
  37. package/dist/src/lib/PgflowClient.js +227 -0
  38. package/dist/src/lib/SupabaseBroadcastAdapter.d.ts +4 -4
  39. package/dist/src/lib/SupabaseBroadcastAdapter.d.ts.map +1 -1
  40. package/dist/src/lib/SupabaseBroadcastAdapter.js +332 -0
  41. package/dist/src/lib/eventAdapters.d.ts +3 -4
  42. package/dist/src/lib/eventAdapters.d.ts.map +1 -1
  43. package/dist/src/lib/eventAdapters.js +160 -0
  44. package/dist/src/lib/types.d.ts +34 -6
  45. package/dist/src/lib/types.d.ts.map +1 -1
  46. package/dist/src/lib/types.js +102 -0
  47. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  48. package/package.json +10 -5
@@ -0,0 +1,372 @@
1
+ import { createNanoEvents } from 'nanoevents';
2
+ import { FlowRunStatus, FlowStepStatus } from './types.js';
3
+ import { FlowStep } from './FlowStep.js';
4
+ /**
5
+ * Represents a single execution of a flow
6
+ */
7
+ export class FlowRun {
8
+ #state;
9
+ #events = createNanoEvents();
10
+ #steps = new Map();
11
+ #statusPrecedence = {
12
+ [FlowRunStatus.Started]: 0,
13
+ [FlowRunStatus.Completed]: 1,
14
+ [FlowRunStatus.Failed]: 2,
15
+ };
16
+ #disposed = false;
17
+ /**
18
+ * Creates a new FlowRun instance
19
+ *
20
+ * @param initialState - Initial state for the run
21
+ */
22
+ constructor(initialState) {
23
+ this.#state = initialState;
24
+ }
25
+ /**
26
+ * Get the run ID
27
+ */
28
+ get run_id() {
29
+ return this.#state.run_id;
30
+ }
31
+ /**
32
+ * Get the flow slug
33
+ */
34
+ get flow_slug() {
35
+ return this.#state.flow_slug;
36
+ }
37
+ /**
38
+ * Get the current status
39
+ */
40
+ get status() {
41
+ return this.#state.status;
42
+ }
43
+ /**
44
+ * Get the started_at timestamp
45
+ */
46
+ get started_at() {
47
+ return this.#state.started_at;
48
+ }
49
+ /**
50
+ * Get the completed_at timestamp
51
+ */
52
+ get completed_at() {
53
+ return this.#state.completed_at;
54
+ }
55
+ /**
56
+ * Get the failed_at timestamp
57
+ */
58
+ get failed_at() {
59
+ return this.#state.failed_at;
60
+ }
61
+ /**
62
+ * Get the flow input
63
+ */
64
+ get input() {
65
+ return this.#state.input;
66
+ }
67
+ /**
68
+ * Get the flow output
69
+ */
70
+ get output() {
71
+ return this.#state.output;
72
+ }
73
+ /**
74
+ * Get the error object
75
+ */
76
+ get error() {
77
+ return this.#state.error;
78
+ }
79
+ /**
80
+ * Get the error message
81
+ */
82
+ get error_message() {
83
+ return this.#state.error_message;
84
+ }
85
+ /**
86
+ * Get the number of remaining steps
87
+ */
88
+ get remaining_steps() {
89
+ return this.#state.remaining_steps;
90
+ }
91
+ /**
92
+ * Register an event handler for a run event
93
+ *
94
+ * @param event - Event type to listen for
95
+ * @param callback - Callback function to execute when event is emitted
96
+ * @returns Function to unsubscribe from the event
97
+ */
98
+ on(event, callback) {
99
+ this.#listenerCount++;
100
+ // Wrap the unsubscribe function to track listener count
101
+ const unsubscribe = this.#events.on(event, callback);
102
+ return () => {
103
+ unsubscribe();
104
+ this.#listenerCount--;
105
+ this.#checkAutoDispose();
106
+ };
107
+ }
108
+ /**
109
+ * Get a FlowStep instance for a specific step
110
+ *
111
+ * @param stepSlug - Step slug to get
112
+ * @returns FlowStep instance for the specified step
113
+ */
114
+ step(stepSlug) {
115
+ // Look up if we already have this step cached
116
+ const existingStep = this.#steps.get(stepSlug);
117
+ if (existingStep) {
118
+ // Safe to cast since we only store steps with matching slugs
119
+ return existingStep;
120
+ }
121
+ // Create a new step instance with default state
122
+ const step = new FlowStep({
123
+ run_id: this.run_id,
124
+ step_slug: stepSlug,
125
+ status: FlowStepStatus.Created,
126
+ output: null,
127
+ error: null,
128
+ error_message: null,
129
+ started_at: null,
130
+ completed_at: null,
131
+ failed_at: null,
132
+ skipped_at: null,
133
+ skip_reason: null,
134
+ });
135
+ // Cache the step
136
+ this.#steps.set(stepSlug, step);
137
+ return step;
138
+ }
139
+ /**
140
+ * Check if this run has a specific step
141
+ *
142
+ * @param stepSlug - Step slug to check
143
+ * @returns true if the step exists, false otherwise
144
+ */
145
+ hasStep(stepSlug) {
146
+ // Check if we have this step cached
147
+ return this.#steps.has(stepSlug);
148
+ }
149
+ /**
150
+ * Wait for the run to reach a specific status
151
+ *
152
+ * @param targetStatus - The status to wait for
153
+ * @param options - Optional timeout and abort signal
154
+ * @returns Promise that resolves with the run instance when the status is reached
155
+ */
156
+ waitForStatus(targetStatus, options) {
157
+ const timeoutMs = options?.timeoutMs ?? 5 * 60 * 1000; // Default 5 minutes
158
+ const { signal } = options || {};
159
+ // If we already have the target status, resolve immediately
160
+ if (this.status === targetStatus) {
161
+ return Promise.resolve(this);
162
+ }
163
+ // Otherwise, wait for the status to change
164
+ return new Promise((resolve, reject) => {
165
+ let timeoutId;
166
+ let cleanedUp = false;
167
+ // Set up timeout if provided
168
+ if (timeoutMs > 0) {
169
+ timeoutId = setTimeout(() => {
170
+ if (cleanedUp)
171
+ return; // Prevent firing if already cleaned up
172
+ cleanedUp = true;
173
+ unbind();
174
+ reject(new Error(`Timeout waiting for run ${this.run_id} to reach status '${targetStatus}'`));
175
+ }, timeoutMs);
176
+ }
177
+ // Set up abort signal if provided
178
+ let abortCleanup;
179
+ if (signal) {
180
+ const abortHandler = () => {
181
+ if (cleanedUp)
182
+ return; // Prevent double cleanup
183
+ cleanedUp = true;
184
+ if (timeoutId)
185
+ clearTimeout(timeoutId);
186
+ unbind();
187
+ reject(new Error(`Aborted waiting for run ${this.run_id} to reach status '${targetStatus}'`));
188
+ };
189
+ signal.addEventListener('abort', abortHandler);
190
+ abortCleanup = () => {
191
+ signal.removeEventListener('abort', abortHandler);
192
+ };
193
+ }
194
+ // Subscribe to all events
195
+ const unbind = this.on('*', (event) => {
196
+ if (event.status === targetStatus) {
197
+ if (cleanedUp)
198
+ return; // Prevent double cleanup
199
+ cleanedUp = true;
200
+ if (timeoutId)
201
+ clearTimeout(timeoutId);
202
+ if (abortCleanup)
203
+ abortCleanup();
204
+ unbind();
205
+ resolve(this);
206
+ }
207
+ });
208
+ });
209
+ }
210
+ /**
211
+ * Apply state from database snapshot (no events emitted)
212
+ * Used when initializing state from start_flow_with_states() or get_run_with_states()
213
+ *
214
+ * @internal This method is only intended for use by PgflowClient.
215
+ * Applications should not call this directly.
216
+ */
217
+ applySnapshot(row) {
218
+ // Direct state assignment from database row (no event conversion)
219
+ this.#state.status = row.status;
220
+ this.#state.input = row.input;
221
+ this.#state.output = row.output;
222
+ this.#state.started_at = row.started_at ? new Date(row.started_at) : null;
223
+ this.#state.completed_at = row.completed_at
224
+ ? new Date(row.completed_at)
225
+ : null;
226
+ this.#state.failed_at = row.failed_at ? new Date(row.failed_at) : null;
227
+ this.#state.remaining_steps = row.remaining_steps;
228
+ this.#state.error_message = null; // Database doesn't have error_message for runs
229
+ this.#state.error = null;
230
+ }
231
+ /**
232
+ * Updates the run state based on an event
233
+ *
234
+ * @internal This method is only intended for use by PgflowClient and tests.
235
+ * Applications should not call this directly - state updates should come from
236
+ * database events through the PgflowClient.
237
+ *
238
+ * TODO: After v1.0, make this method private and refactor tests to use PgflowClient
239
+ * with event emission instead of direct state manipulation.
240
+ */
241
+ updateState(event) {
242
+ // Validate the event is for this run
243
+ if (event.run_id !== this.#state.run_id) {
244
+ return false;
245
+ }
246
+ // Check if the event status has higher precedence than current status
247
+ if (!this.#shouldUpdateStatus(this.#state.status, event.status)) {
248
+ return false;
249
+ }
250
+ // Update state based on event type using narrowing type guards
251
+ switch (event.status) {
252
+ case FlowRunStatus.Started:
253
+ this.#state = {
254
+ ...this.#state,
255
+ status: FlowRunStatus.Started,
256
+ started_at: typeof event.started_at === 'string'
257
+ ? new Date(event.started_at)
258
+ : new Date(),
259
+ remaining_steps: 'remaining_steps' in event
260
+ ? Number(event.remaining_steps)
261
+ : this.#state.remaining_steps,
262
+ };
263
+ this.#events.emit('started', event);
264
+ break;
265
+ case FlowRunStatus.Completed:
266
+ this.#state = {
267
+ ...this.#state,
268
+ status: FlowRunStatus.Completed,
269
+ completed_at: typeof event.completed_at === 'string'
270
+ ? new Date(event.completed_at)
271
+ : new Date(),
272
+ output: event.output,
273
+ remaining_steps: 0,
274
+ };
275
+ this.#events.emit('completed', event);
276
+ // Check for auto-dispose
277
+ this.#checkAutoDispose();
278
+ break;
279
+ case FlowRunStatus.Failed:
280
+ this.#state = {
281
+ ...this.#state,
282
+ status: FlowRunStatus.Failed,
283
+ failed_at: typeof event.failed_at === 'string'
284
+ ? new Date(event.failed_at)
285
+ : new Date(),
286
+ error_message: typeof event.error_message === 'string'
287
+ ? event.error_message
288
+ : 'Unknown error',
289
+ error: new Error(typeof event.error_message === 'string'
290
+ ? event.error_message
291
+ : 'Unknown error'),
292
+ };
293
+ this.#events.emit('failed', event);
294
+ // Check for auto-dispose
295
+ this.#checkAutoDispose();
296
+ break;
297
+ default: {
298
+ // Exhaustiveness check - ensures all event statuses are handled
299
+ event;
300
+ return false;
301
+ }
302
+ }
303
+ // Also emit to the catch-all listener
304
+ this.#events.emit('*', event);
305
+ return true;
306
+ }
307
+ /**
308
+ * Updates a step state based on an event
309
+ *
310
+ * @param stepSlug - Step slug to update
311
+ * @param event - Event data to update the step with
312
+ * @returns true if the state was updated, false otherwise
313
+ */
314
+ updateStepState(stepSlug, event) {
315
+ const step = this.step(stepSlug);
316
+ return step.updateState(event);
317
+ }
318
+ // Track number of listeners
319
+ #listenerCount = 0;
320
+ /**
321
+ * Checks if auto-dispose should be triggered (when in terminal state with no listeners)
322
+ */
323
+ #checkAutoDispose() {
324
+ // Don't auto-dispose multiple times
325
+ if (this.#disposed) {
326
+ return;
327
+ }
328
+ // Only auto-dispose in terminal states
329
+ if (this.status !== FlowRunStatus.Completed &&
330
+ this.status !== FlowRunStatus.Failed) {
331
+ return;
332
+ }
333
+ // If there are no listeners, auto-dispose
334
+ if (this.#listenerCount === 0) {
335
+ this.dispose();
336
+ }
337
+ }
338
+ /**
339
+ * Determines if a status should be updated based on precedence
340
+ *
341
+ * @param currentStatus - Current status
342
+ * @param newStatus - New status
343
+ * @returns true if the status should be updated, false otherwise
344
+ */
345
+ #shouldUpdateStatus(currentStatus, newStatus) {
346
+ // Don't allow changes to terminal states
347
+ if (currentStatus === FlowRunStatus.Completed ||
348
+ currentStatus === FlowRunStatus.Failed) {
349
+ return false; // Terminal states should never change
350
+ }
351
+ const currentPrecedence = this.#statusPrecedence[currentStatus];
352
+ const newPrecedence = this.#statusPrecedence[newStatus];
353
+ // Only allow transitions to higher precedence non-terminal status
354
+ return newPrecedence > currentPrecedence;
355
+ }
356
+ /**
357
+ * Clean up all resources held by this run
358
+ */
359
+ dispose() {
360
+ if (this.#disposed) {
361
+ return;
362
+ }
363
+ // Clear the map to allow garbage collection of steps
364
+ this.#steps.clear();
365
+ // Create a new events object - this effectively clears all listeners
366
+ // without accessing the private internals of nanoevents
367
+ this.#events = createNanoEvents();
368
+ this.#listenerCount = 0;
369
+ // Mark as disposed
370
+ this.#disposed = true;
371
+ }
372
+ }
@@ -1,6 +1,6 @@
1
- import { FlowStepStatus, FlowStepState, StepEvents, Unsubscribe, FlowStepBase, StepEvent } from './types.js';
2
- import { AnyFlow, ExtractFlowSteps, StepOutput } from '../../../dsl/src/index.ts';
3
-
1
+ import type { AnyFlow, ExtractFlowSteps, StepOutput } from '@pgflow/dsl';
2
+ import { FlowStepStatus } from './types.js';
3
+ import type { FlowStepState, StepEvents, Unsubscribe, FlowStepBase, StepEvent, SkipReason } from './types.js';
4
4
  /**
5
5
  * Represents a single step in a flow run
6
6
  */
@@ -36,6 +36,14 @@ export declare class FlowStep<TFlow extends AnyFlow, TStepSlug extends keyof Ext
36
36
  * Get the failed_at timestamp
37
37
  */
38
38
  get failed_at(): Date | null;
39
+ /**
40
+ * Get the skipped_at timestamp
41
+ */
42
+ get skipped_at(): Date | null;
43
+ /**
44
+ * Get the skip reason
45
+ */
46
+ get skip_reason(): SkipReason | null;
39
47
  /**
40
48
  * Get the step output
41
49
  */
@@ -63,10 +71,18 @@ export declare class FlowStep<TFlow extends AnyFlow, TStepSlug extends keyof Ext
63
71
  * @param options - Optional timeout and abort signal
64
72
  * @returns Promise that resolves with the step instance when the status is reached
65
73
  */
66
- waitForStatus(targetStatus: FlowStepStatus.Started | FlowStepStatus.Completed | FlowStepStatus.Failed, options?: {
74
+ waitForStatus(targetStatus: FlowStepStatus.Started | FlowStepStatus.Completed | FlowStepStatus.Failed | FlowStepStatus.Skipped, options?: {
67
75
  timeoutMs?: number;
68
76
  signal?: AbortSignal;
69
77
  }): Promise<this>;
78
+ /**
79
+ * Apply state from database snapshot (no events emitted)
80
+ * Used when initializing state from start_flow_with_states() or get_run_with_states()
81
+ *
82
+ * @internal This method is only intended for use by PgflowClient.
83
+ * Applications should not call this directly.
84
+ */
85
+ applySnapshot(row: import('@pgflow/core').StepStateRow): void;
70
86
  /**
71
87
  * Updates the step state based on an event
72
88
  *
@@ -1 +1 @@
1
- {"version":3,"file":"FlowStep.d.ts","sourceRoot":"","sources":["../../../src/lib/FlowStep.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,EACZ,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,qBAAa,QAAQ,CACnB,KAAK,SAAS,OAAO,EACrB,SAAS,SAAS,MAAM,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CACxD,YAAW,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;;IAUpD;;;;OAIG;gBACS,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC;IAIzD;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,SAAS,CAEzB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,cAAc,CAE3B;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,IAAI,GAAG,IAAI,CAE5B;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,IAAI,GAAG,IAAI,CAE9B;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,IAAI,GAAG,IAAI,CAE3B;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAAI,CAEhD;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,CAExB;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAEjC;IAED;;;;;;OAMG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,EAC7C,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,GACxC,WAAW;IAId;;;;;;OAMG;IACH,aAAa,CACX,YAAY,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,SAAS,GAAG,cAAc,CAAC,MAAM,EACvF,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACrD,OAAO,CAAC,IAAI,CAAC;IAuDhB;;;;;;;;;OASG;IACH,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,OAAO;CAkFzD"}
1
+ {"version":3,"file":"FlowStep.d.ts","sourceRoot":"","sources":["../../../src/lib/FlowStep.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAU,EACX,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,qBAAa,QAAQ,CACnB,KAAK,SAAS,OAAO,EACrB,SAAS,SAAS,MAAM,gBAAgB,CAAC,KAAK,CAAC,GAAG,MAAM,CACxD,YAAW,YAAY,CAAC,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;;IAYpD;;;;OAIG;gBACS,YAAY,EAAE,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC;IAIzD;;OAEG;IACH,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,SAAS,CAEzB;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,cAAc,CAE3B;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,IAAI,GAAG,IAAI,CAE5B;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,IAAI,GAAG,IAAI,CAE9B;IAED;;OAEG;IACH,IAAI,SAAS,IAAI,IAAI,GAAG,IAAI,CAE3B;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,IAAI,GAAG,IAAI,CAE5B;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,UAAU,GAAG,IAAI,CAEnC;IAED;;OAEG;IACH,IAAI,MAAM,IAAI,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,IAAI,CAEhD;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,KAAK,GAAG,IAAI,CAExB;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAEjC;IAED;;;;;;OAMG;IACH,EAAE,CAAC,CAAC,SAAS,MAAM,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,EAC7C,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,GACxC,WAAW;IAId;;;;;;OAMG;IACH,aAAa,CACX,YAAY,EACR,cAAc,CAAC,OAAO,GACtB,cAAc,CAAC,SAAS,GACxB,cAAc,CAAC,MAAM,GACrB,cAAc,CAAC,OAAO,EAC1B,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACrD,OAAO,CAAC,IAAI,CAAC;IA+DhB;;;;;;OAMG;IACH,aAAa,CAAC,GAAG,EAAE,OAAO,cAAc,EAAE,YAAY,GAAG,IAAI;IAe7D;;;;;;;;;OASG;IACH,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,OAAO;CAoHzD"}