@critical-path/core 0.36.1 → 0.38.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.
Files changed (46) hide show
  1. package/README.md +2 -2
  2. package/dist/domain/authorization.d.ts.map +1 -1
  3. package/dist/domain/authorization.js +10 -7
  4. package/dist/domain/authorization.js.map +1 -1
  5. package/dist/engine/index.d.ts +6 -0
  6. package/dist/engine/index.d.ts.map +1 -1
  7. package/dist/engine/index.js +28 -2
  8. package/dist/engine/index.js.map +1 -1
  9. package/dist/schemas/index.d.ts +46 -16
  10. package/dist/schemas/index.d.ts.map +1 -1
  11. package/dist/schemas/index.js +4 -1
  12. package/dist/schemas/index.js.map +1 -1
  13. package/dist/store/firebase.d.ts +7 -3
  14. package/dist/store/firebase.d.ts.map +1 -1
  15. package/dist/store/firebase.js +28 -2
  16. package/dist/store/firebase.js.map +1 -1
  17. package/dist/store/index.d.ts +13 -3
  18. package/dist/store/index.d.ts.map +1 -1
  19. package/dist/store/index.js +20 -2
  20. package/dist/store/index.js.map +1 -1
  21. package/dist/store/sqlite.d.ts +7 -3
  22. package/dist/store/sqlite.d.ts.map +1 -1
  23. package/dist/store/sqlite.js +41 -3
  24. package/dist/store/sqlite.js.map +1 -1
  25. package/dist/testing/conformance.d.ts.map +1 -1
  26. package/dist/testing/conformance.js +26 -0
  27. package/dist/testing/conformance.js.map +1 -1
  28. package/dist/types/index.d.ts +13 -2
  29. package/dist/types/index.d.ts.map +1 -1
  30. package/dist/webhooks/address.d.ts +16 -0
  31. package/dist/webhooks/address.d.ts.map +1 -0
  32. package/dist/webhooks/address.js +114 -0
  33. package/dist/webhooks/address.js.map +1 -0
  34. package/dist/webhooks/dispatcher.d.ts +15 -3
  35. package/dist/webhooks/dispatcher.d.ts.map +1 -1
  36. package/dist/webhooks/dispatcher.js +23 -3
  37. package/dist/webhooks/dispatcher.js.map +1 -1
  38. package/dist/webhooks/index.d.ts +2 -0
  39. package/dist/webhooks/index.d.ts.map +1 -1
  40. package/dist/webhooks/index.js +2 -0
  41. package/dist/webhooks/index.js.map +1 -1
  42. package/dist/webhooks/outbox.d.ts +61 -0
  43. package/dist/webhooks/outbox.d.ts.map +1 -0
  44. package/dist/webhooks/outbox.js +74 -0
  45. package/dist/webhooks/outbox.js.map +1 -0
  46. package/package.json +1 -1
@@ -0,0 +1,74 @@
1
+ /**
2
+ * A durable `WebhookDeliveryQueue`: jobs are written to a store and survive restarts. Delivery is
3
+ * at-least-once, so receivers should de-duplicate on `X-CriticalPath-Delivery`.
4
+ *
5
+ * ```ts
6
+ * const store = new SQLiteStore({ filename: 'app.db' });
7
+ * const outbox = new OutboxWebhookQueue(store);
8
+ * const engine = new CriticalPathEngine({ store, webhookDelivery: { queue: outbox } });
9
+ * outbox.start(); // or call outbox.processDue() from a cron job
10
+ * ```
11
+ */
12
+ export class OutboxWebhookQueue {
13
+ store;
14
+ options;
15
+ deliver;
16
+ timer;
17
+ running;
18
+ constructor(store, options = {}) {
19
+ this.store = store;
20
+ this.options = options;
21
+ }
22
+ attach(deliver) {
23
+ this.deliver = deliver;
24
+ }
25
+ async enqueue(job, delayMs) {
26
+ await this.store.putWebhookJob({ key: `${job.id}:${job.attempt}`, job, runAt: Date.now() + delayMs });
27
+ }
28
+ /** Delivers every job that is due now, in batches. Returns how many jobs were attempted. */
29
+ async processDue() {
30
+ if (!this.deliver)
31
+ throw new Error('OutboxWebhookQueue is not attached; pass it as webhookDelivery.queue.');
32
+ const deliver = this.deliver;
33
+ const batchSize = this.options.batchSize ?? 20;
34
+ let attempted = 0;
35
+ for (;;) {
36
+ const entries = await this.store.claimWebhookJobs(Date.now(), batchSize, this.options.leaseMs ?? 60_000);
37
+ await Promise.all(entries.map(async (entry) => {
38
+ try {
39
+ // `deliver` schedules any retry as a new entry before this one is removed.
40
+ await deliver(entry.job);
41
+ await this.store.deleteWebhookJob(entry.key);
42
+ }
43
+ catch (error) {
44
+ // Leave the entry; it is claimed again when its lease expires.
45
+ console.warn(`[CriticalPath Webhooks] Outbox delivery ${entry.key} failed:`, error);
46
+ }
47
+ }));
48
+ attempted += entries.length;
49
+ if (entries.length < batchSize)
50
+ return attempted;
51
+ }
52
+ }
53
+ /** Polls for due jobs until `stop()`. The timer does not keep the process alive. */
54
+ start() {
55
+ if (this.timer)
56
+ return;
57
+ this.timer = setInterval(() => {
58
+ this.running ??= this.processDue()
59
+ .catch((error) => {
60
+ console.warn('[CriticalPath Webhooks] Outbox poll failed:', error);
61
+ return 0;
62
+ })
63
+ .finally(() => (this.running = undefined));
64
+ }, this.options.pollIntervalMs ?? 1_000);
65
+ this.timer.unref?.();
66
+ }
67
+ /** Stops polling and waits for the current batch to finish. */
68
+ async stop() {
69
+ clearInterval(this.timer);
70
+ this.timer = undefined;
71
+ await this.running;
72
+ }
73
+ }
74
+ //# sourceMappingURL=outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../../src/webhooks/outbox.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@critical-path/core",
3
- "version": "0.36.1",
3
+ "version": "0.38.0",
4
4
  "description": "Core headless domain engine, plugin architecture, and data stores for Critical Path",
5
5
  "author": "Jack James",
6
6
  "license": "MIT",