@critical-path/core 0.37.0 → 0.39.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/README.md +2 -2
- package/dist/engine/index.d.ts +14 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +62 -0
- package/dist/engine/index.js.map +1 -1
- package/dist/schemas/index.d.ts +4 -4
- package/dist/store/firebase.d.ts +5 -1
- package/dist/store/firebase.d.ts.map +1 -1
- package/dist/store/firebase.js +24 -0
- package/dist/store/firebase.js.map +1 -1
- package/dist/store/index.d.ts +12 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +17 -0
- package/dist/store/index.js.map +1 -1
- package/dist/store/sqlite.d.ts +11 -1
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +105 -0
- package/dist/store/sqlite.js.map +1 -1
- package/dist/testing/conformance.d.ts.map +1 -1
- package/dist/testing/conformance.js +17 -0
- package/dist/testing/conformance.js.map +1 -1
- package/dist/webhooks/address.d.ts +16 -0
- package/dist/webhooks/address.d.ts.map +1 -0
- package/dist/webhooks/address.js +114 -0
- package/dist/webhooks/address.js.map +1 -0
- package/dist/webhooks/dispatcher.d.ts +15 -3
- package/dist/webhooks/dispatcher.d.ts.map +1 -1
- package/dist/webhooks/dispatcher.js +23 -3
- package/dist/webhooks/dispatcher.js.map +1 -1
- package/dist/webhooks/index.d.ts +2 -0
- package/dist/webhooks/index.d.ts.map +1 -1
- package/dist/webhooks/index.js +2 -0
- package/dist/webhooks/index.js.map +1 -1
- package/dist/webhooks/outbox.d.ts +61 -0
- package/dist/webhooks/outbox.d.ts.map +1 -0
- package/dist/webhooks/outbox.js +74 -0
- package/dist/webhooks/outbox.js.map +1 -0
- package/package.json +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/webhooks/dispatcher.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../src/webhooks/dispatcher.ts"],"names":[],"mappings":"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"}
|
package/dist/webhooks/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webhooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webhooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
package/dist/webhooks/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/webhooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { WebhookDeliveryJob, WebhookDeliveryQueue } from './dispatcher.js';
|
|
2
|
+
/** A stored delivery attempt. `key` is `<job.id>:<job.attempt>`, so each retry is its own entry. */
|
|
3
|
+
export interface WebhookOutboxEntry {
|
|
4
|
+
key: string;
|
|
5
|
+
job: WebhookDeliveryJob;
|
|
6
|
+
/** Epoch milliseconds when the attempt becomes due. */
|
|
7
|
+
runAt: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Persistence for `OutboxWebhookQueue`. `SQLiteStore`, `InMemoryStore` and `FirebaseStore`
|
|
11
|
+
* implement it; custom storage adapters can too.
|
|
12
|
+
*/
|
|
13
|
+
export interface WebhookOutboxStore {
|
|
14
|
+
/** Inserts or replaces the entry with this key. */
|
|
15
|
+
putWebhookJob(entry: WebhookOutboxEntry): Promise<void>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns up to `limit` entries due at `now` that are not leased, leasing them until
|
|
18
|
+
* `now + leaseMs` so other workers skip them. An entry whose lease expires becomes claimable again.
|
|
19
|
+
*/
|
|
20
|
+
claimWebhookJobs(now: number, limit: number, leaseMs: number): Promise<WebhookOutboxEntry[]>;
|
|
21
|
+
deleteWebhookJob(key: string): Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export interface OutboxWebhookQueueOptions {
|
|
24
|
+
/** How often `start()` polls for due jobs. Default 1 000 ms. */
|
|
25
|
+
pollIntervalMs?: number;
|
|
26
|
+
/** Jobs claimed per poll. Default 20. */
|
|
27
|
+
batchSize?: number;
|
|
28
|
+
/**
|
|
29
|
+
* How long a claimed job is hidden from other workers. If a worker dies mid-delivery, the job
|
|
30
|
+
* is retried after this. Must exceed the delivery timeout. Default 60 000 ms.
|
|
31
|
+
*/
|
|
32
|
+
leaseMs?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A durable `WebhookDeliveryQueue`: jobs are written to a store and survive restarts. Delivery is
|
|
36
|
+
* at-least-once, so receivers should de-duplicate on `X-CriticalPath-Delivery`.
|
|
37
|
+
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* const store = new SQLiteStore({ filename: 'app.db' });
|
|
40
|
+
* const outbox = new OutboxWebhookQueue(store);
|
|
41
|
+
* const engine = new CriticalPathEngine({ store, webhookDelivery: { queue: outbox } });
|
|
42
|
+
* outbox.start(); // or call outbox.processDue() from a cron job
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare class OutboxWebhookQueue implements WebhookDeliveryQueue {
|
|
46
|
+
private readonly store;
|
|
47
|
+
private readonly options;
|
|
48
|
+
private deliver?;
|
|
49
|
+
private timer?;
|
|
50
|
+
private running?;
|
|
51
|
+
constructor(store: WebhookOutboxStore, options?: OutboxWebhookQueueOptions);
|
|
52
|
+
attach(deliver: (job: WebhookDeliveryJob) => Promise<void>): void;
|
|
53
|
+
enqueue(job: WebhookDeliveryJob, delayMs: number): Promise<void>;
|
|
54
|
+
/** Delivers every job that is due now, in batches. Returns how many jobs were attempted. */
|
|
55
|
+
processDue(): Promise<number>;
|
|
56
|
+
/** Polls for due jobs until `stop()`. The timer does not keep the process alive. */
|
|
57
|
+
start(): void;
|
|
58
|
+
/** Stops polling and waits for the current batch to finish. */
|
|
59
|
+
stop(): Promise<void>;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=outbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../../src/webhooks/outbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,oGAAoG;AACpG,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,kBAAkB,CAAC;IACxB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD;;;OAGG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAC7F,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,yBAAyB;IACxC,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,kBAAmB,YAAW,oBAAoB;IAM3D,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,OAAO,CAAC,CAA6C;IAC7D,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,OAAO,CAAC,CAAkB;gBAGf,KAAK,EAAE,kBAAkB,EACzB,OAAO,GAAE,yBAA8B;IAG1D,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAI3D,OAAO,CAAC,GAAG,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,4FAA4F;IACtF,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAwBnC,oFAAoF;IACpF,KAAK,IAAI,IAAI;IAab,+DAA+D;IACzD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAK5B"}
|
|
@@ -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.
|
|
3
|
+
"version": "0.39.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",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
+
"@google-cloud/firestore": "^9.3.1",
|
|
29
30
|
"@types/node": "^24.0.0",
|
|
30
31
|
"typescript": "^5.7.0",
|
|
31
32
|
"vitest": "^3.0.0"
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
"scripts": {
|
|
44
45
|
"build": "tsc --build",
|
|
45
46
|
"test": "vitest run",
|
|
46
|
-
"clean": "rm -rf dist *.tsbuildinfo"
|
|
47
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
48
|
+
"test:firestore": "firebase emulators:exec --only firestore --project demo-critical-path --config ../../firebase.json 'vitest run src/store/firestore-emulator.test.ts'"
|
|
47
49
|
}
|
|
48
50
|
}
|