@flowcore/pathways 0.9.1 → 0.11.0
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/CHANGELOG.md +21 -0
- package/esm/pathways/builder.d.ts +10 -8
- package/esm/pathways/builder.d.ts.map +1 -1
- package/esm/pathways/builder.js +148 -37
- package/esm/pathways/postgres/postgres-pathway-state.d.ts.map +1 -1
- package/esm/pathways/postgres/postgres-pathway-state.js +27 -17
- package/esm/pathways/types.d.ts +7 -2
- package/esm/pathways/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/script/pathways/builder.d.ts +10 -8
- package/script/pathways/builder.d.ts.map +1 -1
- package/script/pathways/builder.js +148 -37
- package/script/pathways/postgres/postgres-pathway-state.d.ts.map +1 -1
- package/script/pathways/postgres/postgres-pathway-state.js +27 -17
- package/script/pathways/types.d.ts +7 -2
- package/script/pathways/types.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.11.0](https://github.com/flowcore-io/flowcore-pathways/compare/v0.10.0...v0.11.0) (2025-04-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* batch support ([32b641e](https://github.com/flowcore-io/flowcore-pathways/commit/32b641e4f181d9ff747a1f0b2bab85a9aea48504))
|
|
9
|
+
* batch support ([4ccf19b](https://github.com/flowcore-io/flowcore-pathways/commit/4ccf19b73419589ddea56dfa13533c4e73947287))
|
|
10
|
+
|
|
11
|
+
## [0.10.0](https://github.com/flowcore-io/flowcore-pathways/compare/v0.9.1...v0.10.0) (2025-04-09)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* allow to chain handle, subscribe, onError and onAnyError ([a560142](https://github.com/flowcore-io/flowcore-pathways/commit/a560142b940c61626a69d41b6c64dcad7947c957))
|
|
17
|
+
* allow to chain handle, subscribe, onError and onAnyError ([4ac4fdb](https://github.com/flowcore-io/flowcore-pathways/commit/4ac4fdb245ede9ef6c7bcf7e79918a9744bec611))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* only create table if it doesn't exist ([828d584](https://github.com/flowcore-io/flowcore-pathways/commit/828d58499067d6a46fa6e293b0c4eac67be840c7))
|
|
23
|
+
|
|
3
24
|
## [0.9.1](https://github.com/flowcore-io/flowcore-pathways/compare/v0.9.0...v0.9.1) (2025-04-08)
|
|
4
25
|
|
|
5
26
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Static, type TSchema } from "@sinclair/typebox";
|
|
2
2
|
import type { WebhookSendOptions } from "@flowcore/sdk-transformer-core";
|
|
3
3
|
import type { FlowcoreEvent } from "../contracts/event.js";
|
|
4
4
|
import type { KvAdapter } from "./kv/kv-adapter.js";
|
|
@@ -52,6 +52,7 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
|
|
|
52
52
|
private readonly errorObservers;
|
|
53
53
|
private readonly globalErrorSubject;
|
|
54
54
|
private readonly writers;
|
|
55
|
+
private readonly batchWriters;
|
|
55
56
|
private readonly schemas;
|
|
56
57
|
private readonly writable;
|
|
57
58
|
private readonly timeouts;
|
|
@@ -187,31 +188,31 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
|
|
|
187
188
|
* @param handler The function that will process events for this pathway
|
|
188
189
|
* @throws Error if the pathway doesn't exist or already has a handler
|
|
189
190
|
*/
|
|
190
|
-
handle<TPath extends keyof TPathway>(path: TPath, handler: (event: Omit<FlowcoreEvent,
|
|
191
|
+
handle<TPath extends keyof TPathway>(path: TPath, handler: (event: Omit<FlowcoreEvent, "payload"> & {
|
|
191
192
|
payload: TPathway[TPath];
|
|
192
|
-
}) =>
|
|
193
|
+
}) => Promise<void> | void): PathwaysBuilder<TPathway, TWritablePaths>;
|
|
193
194
|
/**
|
|
194
195
|
* Subscribe to pathway events (before or after processing)
|
|
195
196
|
* @param path The pathway to subscribe to
|
|
196
197
|
* @param handler The handler function for the events
|
|
197
198
|
* @param type The event type to subscribe to (before, after, or all)
|
|
198
199
|
*/
|
|
199
|
-
subscribe<TPath extends keyof TPathway>(path: TPath, handler: (event: Omit<FlowcoreEvent,
|
|
200
|
+
subscribe<TPath extends keyof TPathway>(path: TPath, handler: (event: Omit<FlowcoreEvent, "payload"> & {
|
|
200
201
|
payload: TPathway[TPath];
|
|
201
|
-
}) => void, type?: "before" | "after" | "all"):
|
|
202
|
+
}) => void, type?: "before" | "after" | "all"): PathwaysBuilder<TPathway, TWritablePaths>;
|
|
202
203
|
/**
|
|
203
204
|
* Subscribe to errors for a specific pathway
|
|
204
205
|
* @param path The pathway to subscribe to errors for
|
|
205
206
|
* @param handler The handler function that receives the error and event
|
|
206
207
|
*/
|
|
207
|
-
onError<TPath extends keyof TPathway>(path: TPath, handler: (error: Error, event: Omit<FlowcoreEvent,
|
|
208
|
+
onError<TPath extends keyof TPathway>(path: TPath, handler: (error: Error, event: Omit<FlowcoreEvent, "payload"> & {
|
|
208
209
|
payload: TPathway[TPath];
|
|
209
|
-
}) => void):
|
|
210
|
+
}) => void): PathwaysBuilder<TPathway, TWritablePaths>;
|
|
210
211
|
/**
|
|
211
212
|
* Subscribe to errors for all pathways
|
|
212
213
|
* @param handler The handler function that receives the error, event, and pathway name
|
|
213
214
|
*/
|
|
214
|
-
onAnyError(handler: (error: Error, event: FlowcoreEvent, pathway: string) => void):
|
|
215
|
+
onAnyError(handler: (error: Error, event: FlowcoreEvent, pathway: string) => void): PathwaysBuilder<TPathway, TWritablePaths>;
|
|
215
216
|
/**
|
|
216
217
|
* Writes data to a pathway with optional audit metadata
|
|
217
218
|
* @param path The pathway to write to
|
|
@@ -221,6 +222,7 @@ export declare class PathwaysBuilder<TPathway extends Record<string, unknown> =
|
|
|
221
222
|
* @returns A promise that resolves to the event ID(s)
|
|
222
223
|
*/
|
|
223
224
|
write<TPath extends TWritablePaths>(path: TPath, data: TPathway[TPath], metadata?: EventMetadata, options?: PathwayWriteOptions): Promise<string | string[]>;
|
|
225
|
+
writeBatch<TPath extends TWritablePaths>(path: TPath, data: TPathway[TPath][], metadata?: EventMetadata, options?: PathwayWriteOptions): Promise<string | string[]>;
|
|
224
226
|
/**
|
|
225
227
|
* Waits for a specific event to be processed
|
|
226
228
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/pathways/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/pathways/builder.ts"],"names":[],"mappings":"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"}
|
package/esm/pathways/builder.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
1
2
|
import { Value } from "@sinclair/typebox/value";
|
|
2
3
|
import { Subject } from "rxjs";
|
|
3
4
|
import { WebhookBuilder } from "../compatibility/flowcore-transformer-core.sdk.js";
|
|
@@ -88,6 +89,12 @@ export class PathwaysBuilder {
|
|
|
88
89
|
writable: true,
|
|
89
90
|
value: {}
|
|
90
91
|
});
|
|
92
|
+
Object.defineProperty(this, "batchWriters", {
|
|
93
|
+
enumerable: true,
|
|
94
|
+
configurable: true,
|
|
95
|
+
writable: true,
|
|
96
|
+
value: {}
|
|
97
|
+
});
|
|
91
98
|
Object.defineProperty(this, "schemas", {
|
|
92
99
|
enumerable: true,
|
|
93
100
|
configurable: true,
|
|
@@ -204,11 +211,11 @@ export class PathwaysBuilder {
|
|
|
204
211
|
if (sessionUserResolvers) {
|
|
205
212
|
this.sessionUserResolvers = sessionUserResolvers;
|
|
206
213
|
}
|
|
207
|
-
this.logger.debug(
|
|
214
|
+
this.logger.debug("Initializing PathwaysBuilder", {
|
|
208
215
|
baseUrl,
|
|
209
216
|
tenant,
|
|
210
217
|
dataCore,
|
|
211
|
-
pathwayTimeoutMs
|
|
218
|
+
pathwayTimeoutMs,
|
|
212
219
|
});
|
|
213
220
|
this.webhookBuilderFactory = new WebhookBuilder({
|
|
214
221
|
baseUrl,
|
|
@@ -231,7 +238,7 @@ export class PathwaysBuilder {
|
|
|
231
238
|
* @returns The PathwaysBuilder instance with custom state configured
|
|
232
239
|
*/
|
|
233
240
|
withPathwayState(state) {
|
|
234
|
-
this.logger.debug(
|
|
241
|
+
this.logger.debug("Setting custom pathway state");
|
|
235
242
|
this.pathwayState = state;
|
|
236
243
|
return this;
|
|
237
244
|
}
|
|
@@ -241,7 +248,7 @@ export class PathwaysBuilder {
|
|
|
241
248
|
* @returns The PathwaysBuilder instance with audit configured
|
|
242
249
|
*/
|
|
243
250
|
withAudit(handler) {
|
|
244
|
-
this.logger.debug(
|
|
251
|
+
this.logger.debug("Configuring audit functionality");
|
|
245
252
|
this.auditHandler = handler;
|
|
246
253
|
return this;
|
|
247
254
|
}
|
|
@@ -251,7 +258,7 @@ export class PathwaysBuilder {
|
|
|
251
258
|
* @returns The PathwaysBuilder instance with custom user ID resolver configured
|
|
252
259
|
*/
|
|
253
260
|
withUserResolver(resolver) {
|
|
254
|
-
this.logger.debug(
|
|
261
|
+
this.logger.debug("Configuring user resolver");
|
|
255
262
|
this.userIdResolver = resolver;
|
|
256
263
|
return this;
|
|
257
264
|
}
|
|
@@ -290,9 +297,9 @@ export class PathwaysBuilder {
|
|
|
290
297
|
*/
|
|
291
298
|
withSessionUserResolver(sessionId, resolver) {
|
|
292
299
|
if (!this.sessionUserResolvers) {
|
|
293
|
-
throw new Error(
|
|
300
|
+
throw new Error("Session user resolvers not configured");
|
|
294
301
|
}
|
|
295
|
-
this.logger.debug(
|
|
302
|
+
this.logger.debug("Configuring session-specific user resolver", { sessionId });
|
|
296
303
|
this.sessionUserResolvers.set(sessionId, resolver, DEFAULT_SESSION_USER_RESOLVER_TTL_MS);
|
|
297
304
|
return this;
|
|
298
305
|
}
|
|
@@ -318,7 +325,7 @@ export class PathwaysBuilder {
|
|
|
318
325
|
const pathwayStr = String(pathway);
|
|
319
326
|
this.logger.debug(`Processing pathway event`, {
|
|
320
327
|
pathway: pathwayStr,
|
|
321
|
-
eventId: data.eventId
|
|
328
|
+
eventId: data.eventId,
|
|
322
329
|
});
|
|
323
330
|
if (!this.pathways[pathway]) {
|
|
324
331
|
const error = `Pathway ${pathwayStr} not found`;
|
|
@@ -345,7 +352,7 @@ export class PathwaysBuilder {
|
|
|
345
352
|
if (this.auditHandler) {
|
|
346
353
|
this.logger.debug(`Calling audit handler for pathway`, {
|
|
347
354
|
pathway: pathwayStr,
|
|
348
|
-
eventId: data.eventId
|
|
355
|
+
eventId: data.eventId,
|
|
349
356
|
});
|
|
350
357
|
this.auditHandler(pathwayStr, data);
|
|
351
358
|
}
|
|
@@ -355,7 +362,7 @@ export class PathwaysBuilder {
|
|
|
355
362
|
const retryDelayMs = this.retryDelays[pathway] ?? DEFAULT_RETRY_DELAY_MS;
|
|
356
363
|
this.logger.debug(`Emitting 'before' event`, {
|
|
357
364
|
pathway: pathwayStr,
|
|
358
|
-
eventId: data.eventId
|
|
365
|
+
eventId: data.eventId,
|
|
359
366
|
});
|
|
360
367
|
this.beforeObservable[pathway].next(data);
|
|
361
368
|
while (true) {
|
|
@@ -363,7 +370,7 @@ export class PathwaysBuilder {
|
|
|
363
370
|
this.logger.debug(`Executing handler for pathway`, {
|
|
364
371
|
pathway: pathwayStr,
|
|
365
372
|
eventId: data.eventId,
|
|
366
|
-
attempt: retryCount + 1
|
|
373
|
+
attempt: retryCount + 1,
|
|
367
374
|
});
|
|
368
375
|
// Execute the handler
|
|
369
376
|
const handle = this.handlers[pathway](data);
|
|
@@ -371,13 +378,13 @@ export class PathwaysBuilder {
|
|
|
371
378
|
// If successful, emit success event and mark as processed
|
|
372
379
|
this.logger.debug(`Handler executed successfully, emitting 'after' event`, {
|
|
373
380
|
pathway: pathwayStr,
|
|
374
|
-
eventId: data.eventId
|
|
381
|
+
eventId: data.eventId,
|
|
375
382
|
});
|
|
376
383
|
this.afterObservers[pathway].next(data);
|
|
377
384
|
await this.pathwayState.setProcessed(data.eventId);
|
|
378
385
|
this.logger.info(`Successfully processed pathway event`, {
|
|
379
386
|
pathway: pathwayStr,
|
|
380
|
-
eventId: data.eventId
|
|
387
|
+
eventId: data.eventId,
|
|
381
388
|
});
|
|
382
389
|
return;
|
|
383
390
|
}
|
|
@@ -388,7 +395,7 @@ export class PathwaysBuilder {
|
|
|
388
395
|
pathway: pathwayStr,
|
|
389
396
|
eventId: data.eventId,
|
|
390
397
|
retryCount,
|
|
391
|
-
maxRetries
|
|
398
|
+
maxRetries,
|
|
392
399
|
});
|
|
393
400
|
// Emit error event with both error and event data
|
|
394
401
|
this.errorObservers[pathway].next({ event: data, error: errorObj });
|
|
@@ -396,7 +403,7 @@ export class PathwaysBuilder {
|
|
|
396
403
|
this.globalErrorSubject.next({
|
|
397
404
|
pathway: pathwayStr,
|
|
398
405
|
event: data,
|
|
399
|
-
error: errorObj
|
|
406
|
+
error: errorObj,
|
|
400
407
|
});
|
|
401
408
|
// Check if we should retry
|
|
402
409
|
if (retryCount < maxRetries) {
|
|
@@ -407,10 +414,10 @@ export class PathwaysBuilder {
|
|
|
407
414
|
eventId: data.eventId,
|
|
408
415
|
attempt: retryCount,
|
|
409
416
|
maxRetries,
|
|
410
|
-
nextDelay
|
|
417
|
+
nextDelay,
|
|
411
418
|
});
|
|
412
419
|
// Wait for delay before retrying
|
|
413
|
-
await new Promise(resolve => setTimeout(resolve, nextDelay));
|
|
420
|
+
await new Promise((resolve) => setTimeout(resolve, nextDelay));
|
|
414
421
|
continue;
|
|
415
422
|
}
|
|
416
423
|
// If we've exhausted retries, mark as processed to avoid hanging
|
|
@@ -418,7 +425,7 @@ export class PathwaysBuilder {
|
|
|
418
425
|
pathway: pathwayStr,
|
|
419
426
|
eventId: data.eventId,
|
|
420
427
|
retryCount,
|
|
421
|
-
maxRetries
|
|
428
|
+
maxRetries,
|
|
422
429
|
});
|
|
423
430
|
await this.pathwayState.setProcessed(data.eventId);
|
|
424
431
|
throw error;
|
|
@@ -429,7 +436,7 @@ export class PathwaysBuilder {
|
|
|
429
436
|
// No handler, just emit events and mark as processed
|
|
430
437
|
this.logger.debug(`No handler for pathway, emitting events and marking as processed`, {
|
|
431
438
|
pathway: pathwayStr,
|
|
432
|
-
eventId: data.eventId
|
|
439
|
+
eventId: data.eventId,
|
|
433
440
|
});
|
|
434
441
|
this.beforeObservable[pathway].next(data);
|
|
435
442
|
this.afterObservers[pathway].next(data);
|
|
@@ -456,9 +463,9 @@ export class PathwaysBuilder {
|
|
|
456
463
|
isFilePathway: contract.isFilePathway,
|
|
457
464
|
timeoutMs: contract.timeoutMs,
|
|
458
465
|
maxRetries: contract.maxRetries,
|
|
459
|
-
retryDelayMs: contract.retryDelayMs
|
|
460
|
-
})
|
|
461
|
-
|
|
466
|
+
retryDelayMs: contract.retryDelayMs,
|
|
467
|
+
}) // deno-lint-ignore no-explicit-any
|
|
468
|
+
;
|
|
462
469
|
this.pathways[path] = true;
|
|
463
470
|
this.beforeObservable[path] = new Subject();
|
|
464
471
|
this.afterObservers[path] = new Subject();
|
|
@@ -472,6 +479,8 @@ export class PathwaysBuilder {
|
|
|
472
479
|
else {
|
|
473
480
|
this.writers[path] = this.webhookBuilderFactory()
|
|
474
481
|
.buildWebhook(contract.flowType, contract.eventType).send;
|
|
482
|
+
this.batchWriters[path] = this.webhookBuilderFactory()
|
|
483
|
+
.buildWebhook(contract.flowType, contract.eventType).sendBatch;
|
|
475
484
|
}
|
|
476
485
|
}
|
|
477
486
|
if (contract.timeoutMs) {
|
|
@@ -489,7 +498,7 @@ export class PathwaysBuilder {
|
|
|
489
498
|
pathway: path,
|
|
490
499
|
flowType: contract.flowType,
|
|
491
500
|
eventType: contract.eventType,
|
|
492
|
-
writable
|
|
501
|
+
writable,
|
|
493
502
|
});
|
|
494
503
|
return this;
|
|
495
504
|
}
|
|
@@ -531,6 +540,7 @@ export class PathwaysBuilder {
|
|
|
531
540
|
}
|
|
532
541
|
this.handlers[path] = handler;
|
|
533
542
|
this.logger.info(`Handler set for pathway`, { pathway: pathStr });
|
|
543
|
+
return this;
|
|
534
544
|
}
|
|
535
545
|
/**
|
|
536
546
|
* Subscribe to pathway events (before or after processing)
|
|
@@ -557,8 +567,9 @@ export class PathwaysBuilder {
|
|
|
557
567
|
}
|
|
558
568
|
this.logger.info(`Subscription to pathway events set up`, {
|
|
559
569
|
pathway: pathStr,
|
|
560
|
-
type
|
|
570
|
+
type,
|
|
561
571
|
});
|
|
572
|
+
return this;
|
|
562
573
|
}
|
|
563
574
|
/**
|
|
564
575
|
* Subscribe to errors for a specific pathway
|
|
@@ -578,6 +589,7 @@ export class PathwaysBuilder {
|
|
|
578
589
|
const typedHandler = (payload) => handler(payload.error, payload.event);
|
|
579
590
|
this.errorObservers[path].subscribe(typedHandler);
|
|
580
591
|
this.logger.info(`Error handler set for pathway`, { pathway: pathStr });
|
|
592
|
+
return this;
|
|
581
593
|
}
|
|
582
594
|
/**
|
|
583
595
|
* Subscribe to errors for all pathways
|
|
@@ -587,6 +599,7 @@ export class PathwaysBuilder {
|
|
|
587
599
|
this.logger.debug(`Subscribing to all pathway errors`);
|
|
588
600
|
this.globalErrorSubject.subscribe(({ pathway, event, error }) => handler(error, event, pathway));
|
|
589
601
|
this.logger.debug(`Subscribed to all pathway errors`);
|
|
602
|
+
return this;
|
|
590
603
|
}
|
|
591
604
|
/**
|
|
592
605
|
* Writes data to a pathway with optional audit metadata
|
|
@@ -603,8 +616,8 @@ export class PathwaysBuilder {
|
|
|
603
616
|
metadata,
|
|
604
617
|
options: {
|
|
605
618
|
fireAndForget: options?.fireAndForget,
|
|
606
|
-
sessionId: options?.sessionId
|
|
607
|
-
}
|
|
619
|
+
sessionId: options?.sessionId,
|
|
620
|
+
},
|
|
608
621
|
});
|
|
609
622
|
if (!this.pathways[path]) {
|
|
610
623
|
const error = `Pathway ${pathStr} not found`;
|
|
@@ -621,7 +634,7 @@ export class PathwaysBuilder {
|
|
|
621
634
|
const errorMessage = `Invalid data for pathway ${pathStr}`;
|
|
622
635
|
this.logger.error(errorMessage, new Error(errorMessage), {
|
|
623
636
|
pathway: pathStr,
|
|
624
|
-
schema: schema.toString()
|
|
637
|
+
schema: schema.toString(),
|
|
625
638
|
});
|
|
626
639
|
throw new Error(errorMessage);
|
|
627
640
|
}
|
|
@@ -637,13 +650,13 @@ export class PathwaysBuilder {
|
|
|
637
650
|
this.logger.debug(`Using session-specific user resolver`, {
|
|
638
651
|
pathway: pathStr,
|
|
639
652
|
sessionId: options.sessionId,
|
|
640
|
-
userId
|
|
653
|
+
userId,
|
|
641
654
|
});
|
|
642
655
|
}
|
|
643
656
|
catch (error) {
|
|
644
657
|
this.logger.error(`Error resolving session user ID`, error instanceof Error ? error : new Error(String(error)), {
|
|
645
658
|
pathway: pathStr,
|
|
646
|
-
sessionId: options.sessionId
|
|
659
|
+
sessionId: options.sessionId,
|
|
647
660
|
});
|
|
648
661
|
}
|
|
649
662
|
}
|
|
@@ -661,7 +674,7 @@ export class PathwaysBuilder {
|
|
|
661
674
|
this.logger.debug(`Adding audit metadata`, {
|
|
662
675
|
pathway: pathStr,
|
|
663
676
|
auditMode,
|
|
664
|
-
userId
|
|
677
|
+
userId,
|
|
665
678
|
});
|
|
666
679
|
if (userId) {
|
|
667
680
|
// Add appropriate audit metadata based on mode
|
|
@@ -688,15 +701,113 @@ export class PathwaysBuilder {
|
|
|
688
701
|
this.logger.info(`Successfully wrote to pathway`, {
|
|
689
702
|
pathway: pathStr,
|
|
690
703
|
eventIds: Array.isArray(eventIds) ? eventIds : [eventIds],
|
|
691
|
-
fireAndForget: options?.fireAndForget
|
|
704
|
+
fireAndForget: options?.fireAndForget,
|
|
692
705
|
});
|
|
693
706
|
if (!options?.fireAndForget) {
|
|
694
707
|
this.logger.debug(`Waiting for pathway to be processed`, {
|
|
695
708
|
pathway: pathStr,
|
|
696
|
-
eventIds: Array.isArray(eventIds) ? eventIds : [eventIds]
|
|
709
|
+
eventIds: Array.isArray(eventIds) ? eventIds : [eventIds],
|
|
697
710
|
});
|
|
698
711
|
await Promise.all(Array.isArray(eventIds)
|
|
699
|
-
? eventIds.map(id => this.waitForPathwayToBeProcessed(id))
|
|
712
|
+
? eventIds.map((id) => this.waitForPathwayToBeProcessed(id))
|
|
713
|
+
: [this.waitForPathwayToBeProcessed(eventIds)]);
|
|
714
|
+
}
|
|
715
|
+
return eventIds;
|
|
716
|
+
}
|
|
717
|
+
async writeBatch(path, data, metadata, options) {
|
|
718
|
+
const pathStr = String(path);
|
|
719
|
+
this.logger.debug(`Writing batch to pathway`, {
|
|
720
|
+
pathway: pathStr,
|
|
721
|
+
metadata,
|
|
722
|
+
options: {
|
|
723
|
+
fireAndForget: options?.fireAndForget,
|
|
724
|
+
sessionId: options?.sessionId,
|
|
725
|
+
},
|
|
726
|
+
});
|
|
727
|
+
if (!this.pathways[path]) {
|
|
728
|
+
const error = `Pathway ${pathStr} not found`;
|
|
729
|
+
this.logger.error(error);
|
|
730
|
+
throw new Error(error);
|
|
731
|
+
}
|
|
732
|
+
if (!this.writable[path]) {
|
|
733
|
+
const error = `Pathway ${pathStr} is not writable`;
|
|
734
|
+
this.logger.error(error);
|
|
735
|
+
throw new Error(error);
|
|
736
|
+
}
|
|
737
|
+
const schema = this.schemas[path];
|
|
738
|
+
if (!Value.Check(Type.Array(schema), data)) {
|
|
739
|
+
const errorMessage = `Invalid batch data for pathway ${pathStr}`;
|
|
740
|
+
this.logger.error(errorMessage, new Error(errorMessage), {
|
|
741
|
+
pathway: pathStr,
|
|
742
|
+
schema: schema.toString(),
|
|
743
|
+
});
|
|
744
|
+
throw new Error(errorMessage);
|
|
745
|
+
}
|
|
746
|
+
// Create a copy of the metadata to avoid modifying the original
|
|
747
|
+
const finalMetadata = metadata ? { ...metadata } : {};
|
|
748
|
+
// Check for session-specific user resolver
|
|
749
|
+
let userId;
|
|
750
|
+
if (options?.sessionId) {
|
|
751
|
+
const sessionUserResolver = this.getSessionUserResolver(options.sessionId);
|
|
752
|
+
if (sessionUserResolver) {
|
|
753
|
+
try {
|
|
754
|
+
userId = await sessionUserResolver();
|
|
755
|
+
this.logger.debug(`Using session-specific user resolver`, {
|
|
756
|
+
pathway: pathStr,
|
|
757
|
+
sessionId: options.sessionId,
|
|
758
|
+
userId,
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
catch (error) {
|
|
762
|
+
this.logger.error(`Error resolving session user ID`, error instanceof Error ? error : new Error(String(error)), {
|
|
763
|
+
pathway: pathStr,
|
|
764
|
+
sessionId: options.sessionId,
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
// Process audit metadata if audit is configured
|
|
770
|
+
if (this.userIdResolver) {
|
|
771
|
+
// Only use global resolver if we don't already have a user ID from a session resolver
|
|
772
|
+
if (!userId) {
|
|
773
|
+
this.logger.debug(`Resolving user ID for audit metadata`, { pathway: pathStr });
|
|
774
|
+
userId = await this.userIdResolver();
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
// Determine the audit mode: default is "user" unless explicitly specified as "system"
|
|
778
|
+
const auditMode = options?.auditMode ?? "user";
|
|
779
|
+
this.logger.debug(`Adding audit metadata`, {
|
|
780
|
+
pathway: pathStr,
|
|
781
|
+
auditMode,
|
|
782
|
+
userId,
|
|
783
|
+
});
|
|
784
|
+
if (userId) {
|
|
785
|
+
// Add appropriate audit metadata based on mode
|
|
786
|
+
if (auditMode === "system") {
|
|
787
|
+
finalMetadata["audit/user-id"] = "system";
|
|
788
|
+
finalMetadata["audit/on-behalf-of"] = userId;
|
|
789
|
+
finalMetadata["audit/mode"] = "system";
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
finalMetadata["audit/user-id"] = userId;
|
|
793
|
+
finalMetadata["audit/mode"] = "user"; // Always set mode for user
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
let eventIds = [];
|
|
797
|
+
this.logger.debug(`Writing batch webhook data to pathway`, { pathway: pathStr });
|
|
798
|
+
eventIds = await this.batchWriters[path](data, finalMetadata, options);
|
|
799
|
+
this.logger.info(`Successfully wrote to pathway`, {
|
|
800
|
+
pathway: pathStr,
|
|
801
|
+
eventIds: Array.isArray(eventIds) ? eventIds : [eventIds],
|
|
802
|
+
fireAndForget: options?.fireAndForget,
|
|
803
|
+
});
|
|
804
|
+
if (!options?.fireAndForget) {
|
|
805
|
+
this.logger.debug(`Waiting for pathway to be processed`, {
|
|
806
|
+
pathway: pathStr,
|
|
807
|
+
eventIds: Array.isArray(eventIds) ? eventIds : [eventIds],
|
|
808
|
+
});
|
|
809
|
+
await Promise.all(Array.isArray(eventIds)
|
|
810
|
+
? eventIds.map((id) => this.waitForPathwayToBeProcessed(id))
|
|
700
811
|
: [this.waitForPathwayToBeProcessed(eventIds)]);
|
|
701
812
|
}
|
|
702
813
|
return eventIds;
|
|
@@ -717,7 +828,7 @@ export class PathwaysBuilder {
|
|
|
717
828
|
const timeoutMs = this.timeouts[eventId] ?? this.pathwayTimeoutMs;
|
|
718
829
|
this.logger.debug(`Waiting for event to be processed`, {
|
|
719
830
|
eventId,
|
|
720
|
-
timeoutMs
|
|
831
|
+
timeoutMs,
|
|
721
832
|
});
|
|
722
833
|
let attempts = 0;
|
|
723
834
|
while (!(await this.pathwayState.isProcessed(eventId))) {
|
|
@@ -729,7 +840,7 @@ export class PathwaysBuilder {
|
|
|
729
840
|
eventId,
|
|
730
841
|
timeoutMs,
|
|
731
842
|
elapsedTime,
|
|
732
|
-
attempts
|
|
843
|
+
attempts,
|
|
733
844
|
});
|
|
734
845
|
throw new Error(errorMessage);
|
|
735
846
|
}
|
|
@@ -738,7 +849,7 @@ export class PathwaysBuilder {
|
|
|
738
849
|
eventId,
|
|
739
850
|
elapsedTime,
|
|
740
851
|
attempts,
|
|
741
|
-
timeoutMs
|
|
852
|
+
timeoutMs,
|
|
742
853
|
});
|
|
743
854
|
}
|
|
744
855
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -746,7 +857,7 @@ export class PathwaysBuilder {
|
|
|
746
857
|
this.logger.debug(`Event has been processed`, {
|
|
747
858
|
eventId,
|
|
748
859
|
elapsedTime: Date.now() - startTime,
|
|
749
|
-
attempts
|
|
860
|
+
attempts,
|
|
750
861
|
});
|
|
751
862
|
}
|
|
752
863
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres-pathway-state.d.ts","sourceRoot":"","sources":["../../../src/pathways/postgres/postgres-pathway-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"postgres-pathway-state.d.ts","sourceRoot":"","sources":["../../../src/pathways/postgres/postgres-pathway-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI/C;;GAEG;AACH,MAAM,WAAW,0CAA0C;IACzD,gHAAgH;IAChH,gBAAgB,EAAE,MAAM,CAAA;IAExB,yEAAyE;IACzE,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,GAAG,CAAC,EAAE,KAAK,CAAA;IAEX,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;GAEG;AACH,MAAM,WAAW,oCAAoC;IACnD,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,KAAK,CAAA;IAExB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,OAAO,CAAA;IAEb,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,MAAM,MAAM,0BAA0B,GAClC,0CAA0C,GAC1C,oCAAoC,CAAA;AAExC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IA0C3C,OAAO,CAAC,MAAM;IAzC1B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAEtD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAkB;IAE5D;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAiB;IAEjC;;;OAGG;IACH,OAAO,CAAC,SAAS,CAAQ;IAEzB;;;OAGG;IACH,OAAO,CAAC,KAAK,CAAQ;IAErB;;;OAGG;IACH,OAAO,CAAC,WAAW,CAAQ;IAE3B;;;;OAIG;gBACiB,MAAM,EAAE,0BAA0B;IAMtD;;;;;OAKG;YACW,UAAU;IAuDxB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBlD;;;;;OAKG;YACW,cAAc;IAQ5B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,0BAA0B,GAAG,oBAAoB,CAGnG"}
|
|
@@ -114,10 +114,10 @@ export class PostgresPathwayState {
|
|
|
114
114
|
return;
|
|
115
115
|
}
|
|
116
116
|
// Create adapter using either connection string or individual parameters
|
|
117
|
-
if (
|
|
117
|
+
if ("connectionString" in this.config && this.config.connectionString) {
|
|
118
118
|
// Use connection string if provided
|
|
119
119
|
this.postgres = await createPostgresAdapter({
|
|
120
|
-
connectionString: this.config.connectionString
|
|
120
|
+
connectionString: this.config.connectionString,
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
else {
|
|
@@ -132,19 +132,29 @@ export class PostgresPathwayState {
|
|
|
132
132
|
ssl: this.config.ssl,
|
|
133
133
|
});
|
|
134
134
|
}
|
|
135
|
-
//
|
|
136
|
-
await this.postgres.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
expires_at TIMESTAMP WITH TIME ZONE NOT NULL
|
|
135
|
+
// Check if the table exists
|
|
136
|
+
const tableExists = await this.postgres.query(`
|
|
137
|
+
SELECT EXISTS (
|
|
138
|
+
SELECT 1
|
|
139
|
+
FROM information_schema.tables
|
|
140
|
+
WHERE table_name = $1
|
|
142
141
|
)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
`, [this.tableName]);
|
|
143
|
+
if (!tableExists[0]?.exists) {
|
|
144
|
+
// Create table if it doesn't exist
|
|
145
|
+
await this.postgres.execute(`
|
|
146
|
+
CREATE TABLE IF NOT EXISTS ${this.tableName} (
|
|
147
|
+
event_id TEXT PRIMARY KEY,
|
|
148
|
+
processed BOOLEAN NOT NULL,
|
|
149
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
150
|
+
expires_at TIMESTAMP WITH TIME ZONE NOT NULL
|
|
151
|
+
)
|
|
152
|
+
`);
|
|
153
|
+
// Create index on expires_at to help with cleanup
|
|
154
|
+
await this.postgres.execute(`
|
|
155
|
+
CREATE INDEX IF NOT EXISTS ${this.tableName}_expires_at_idx ON ${this.tableName} (expires_at)
|
|
156
|
+
`);
|
|
157
|
+
}
|
|
148
158
|
this.initialized = true;
|
|
149
159
|
}
|
|
150
160
|
/**
|
|
@@ -227,9 +237,9 @@ export class PostgresPathwayState {
|
|
|
227
237
|
await this.postgres.execute(`
|
|
228
238
|
INSERT INTO ${this.tableName} (event_id, processed, expires_at)
|
|
229
239
|
VALUES ($1, TRUE, NOW() + interval '${Math.floor(this.ttlMs / 1000)} seconds')
|
|
230
|
-
ON CONFLICT (event_id)
|
|
231
|
-
DO UPDATE SET
|
|
232
|
-
processed = TRUE,
|
|
240
|
+
ON CONFLICT (event_id)
|
|
241
|
+
DO UPDATE SET
|
|
242
|
+
processed = TRUE,
|
|
233
243
|
expires_at = NOW() + interval '${Math.floor(this.ttlMs / 1000)} seconds'
|
|
234
244
|
`, [eventId]);
|
|
235
245
|
}
|
package/esm/pathways/types.d.ts
CHANGED
|
@@ -89,6 +89,11 @@ export interface EventMetadata extends Record<string, unknown> {
|
|
|
89
89
|
* @template EventPayload The type of the event payload
|
|
90
90
|
*/
|
|
91
91
|
export type SendWebhook<EventPayload> = (payload: EventPayload, metadata?: EventMetadata, options?: WebhookSendOptions) => Promise<string>;
|
|
92
|
+
/**
|
|
93
|
+
* Function type for sending batch events to a webhook
|
|
94
|
+
* @template EventPayload The type of the event payload
|
|
95
|
+
*/
|
|
96
|
+
export type SendWebhookBatch<EventPayload> = (payload: EventPayload[], metadata?: EventMetadata, options?: WebhookSendOptions) => Promise<string[]>;
|
|
92
97
|
/**
|
|
93
98
|
* Function type for sending a file to a webhook
|
|
94
99
|
*/
|
|
@@ -108,12 +113,12 @@ export type PathwayState = {
|
|
|
108
113
|
* @param eventId The ID of the event to check
|
|
109
114
|
* @returns Boolean indicating if the event has been processed
|
|
110
115
|
*/
|
|
111
|
-
isProcessed: (eventId: string) =>
|
|
116
|
+
isProcessed: (eventId: string) => boolean | Promise<boolean>;
|
|
112
117
|
/**
|
|
113
118
|
* Marks an event as processed
|
|
114
119
|
* @param eventId The ID of the event to mark as processed
|
|
115
120
|
*/
|
|
116
|
-
setProcessed: (eventId: string) =>
|
|
121
|
+
setProcessed: (eventId: string) => void | Promise<void>;
|
|
117
122
|
};
|
|
118
123
|
/**
|
|
119
124
|
* Options for pathway writes, extending WebhookSendOptions
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pathways/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAEzF;;;GAGG;AACH,KAAK,uBAAuB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IACnD,QAAQ,CAAC,yBAAyB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/pathways/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAEzF;;;GAGG;AACH,KAAK,uBAAuB,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IACnD,QAAQ,CAAC,yBAAyB,EAChC,wGAAwG,CAAA;CAC3G,CAAA;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO;IACpF;;OAEG;IACH,QAAQ,EAAE,CAAC,CAAA;IAEX;;OAEG;IACH,SAAS,EAAE,CAAC,CAAA;IAEZ;;OAEG;IACH,MAAM,EAAE,CAAC,CAAA;IAET;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IAErB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAE3B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAED;;;;GAIG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,EAAE,CAAA;AAExE;;GAEG;AACH,MAAM,WAAW,aAAc,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAAG;AAEjE;;;GAGG;AACH,MAAM,MAAM,WAAW,CAAC,YAAY,IAAI,CACtC,OAAO,EAAE,YAAY,EACrB,QAAQ,CAAC,EAAE,aAAa,EACxB,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,MAAM,CAAC,CAAA;AAEpB;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,YAAY,IAAI,CAC3C,OAAO,EAAE,YAAY,EAAE,EACvB,QAAQ,CAAC,EAAE,aAAa,EACxB,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AAEtB;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CACzB,OAAO,EAAE,eAAe,EACxB,QAAQ,CAAC,EAAE,aAAa,EACxB,OAAO,CAAC,EAAE,kBAAkB,KACzB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;AAEtB;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,UAAU,SAAS,OAAO,IAAI,UAAU,SAAS,KAAK,GAChG,uBAAuB,CAAC,CAAC,CAAC,GAC1B,CAAC,CAAA;AAEL;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB;;;;OAIG;IACH,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAE5D;;;OAGG;IACH,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACxD,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAAG;IACrD;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAEhC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IAE7B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA"}
|