@dsh-enhanced/event-triggers 0.1.3

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/lib/service.js ADDED
@@ -0,0 +1,334 @@
1
+ import { createHmac, timingSafeEqual } from 'node:crypto';
2
+ import { Context, Service } from '@deepseek-ai/cordis';
3
+ import { ConfigSchema, normalizeEventTriggersConfig, } from './config.js';
4
+ import { defaultLookup, pinFileRoots, readFileObservation, readHttpJsonObservation, } from './sensors.js';
5
+ import { EventTriggerStore } from './store.js';
6
+ export class EventTriggersError extends Error {
7
+ code;
8
+ constructor(code, message) {
9
+ super(message);
10
+ this.code = code;
11
+ this.name = 'EventTriggersError';
12
+ }
13
+ }
14
+ export class EventTriggersService extends Service {
15
+ static Config = ConfigSchema;
16
+ config;
17
+ store;
18
+ policy;
19
+ automations;
20
+ credentials;
21
+ triggers;
22
+ now;
23
+ fetcher;
24
+ lookup;
25
+ fileObserver;
26
+ pinnedFileRoots;
27
+ shutdown = new AbortController();
28
+ pollTimer;
29
+ flushTimer;
30
+ pollInFlight;
31
+ flushInFlight;
32
+ pollCursor = 0;
33
+ inFlight = new Set();
34
+ pendingObservations = new Map();
35
+ active = true;
36
+ constructor(ctx, input, options = {}) {
37
+ super(ctx, 'eventTriggers');
38
+ this.config = normalizeEventTriggersConfig(input);
39
+ const policy = ctx.get('assistantPolicy');
40
+ const automations = ctx.get('assistantAutomations');
41
+ if (policy === undefined || automations === undefined) {
42
+ throw new Error('event-triggers: assistantPolicy and assistantAutomations services are required');
43
+ }
44
+ this.policy = policy;
45
+ this.automations = automations;
46
+ this.credentials = ctx.get('credentialsKeychain');
47
+ if (this.config.triggers.some(trigger => trigger.kind === 'webhook') && this.credentials === undefined) {
48
+ throw new Error('event-triggers: credentialsKeychain is required when webhook triggers are configured');
49
+ }
50
+ this.triggers = new Map(this.config.triggers.map(trigger => [trigger.id, trigger]));
51
+ this.now = options.now ?? Date.now;
52
+ this.fetcher = options.fetcher;
53
+ this.lookup = options.lookup ?? defaultLookup;
54
+ this.fileObserver = options.fileObserver ?? readFileObservation;
55
+ this.pinnedFileRoots = this.config.triggers.some(trigger => trigger.kind === 'file')
56
+ ? pinFileRoots(this.config.allowedFileRoots)
57
+ : [];
58
+ this.store = new EventTriggerStore({ path: this.config.databasePath, now: this.now });
59
+ this.flushTimer = setInterval(() => void this.flushPending().catch(() => { }), this.config.pollIntervalMs);
60
+ this.flushTimer.unref?.();
61
+ void this.flushPending().catch(() => { });
62
+ if (this.config.pollerEnabled) {
63
+ this.pollTimer = setInterval(() => void this.pollOnce().catch(() => { }), this.config.pollIntervalMs);
64
+ this.pollTimer.unref?.();
65
+ void this.pollOnce().catch(() => { });
66
+ }
67
+ ctx.effect(() => async () => {
68
+ this.active = false;
69
+ if (this.pollTimer !== undefined)
70
+ clearInterval(this.pollTimer);
71
+ if (this.flushTimer !== undefined)
72
+ clearInterval(this.flushTimer);
73
+ this.shutdown.abort(new EventTriggersError('disposed', 'event-triggers service is disposed'));
74
+ await Promise.allSettled(this.inFlight);
75
+ this.store.close();
76
+ }, 'event-triggers.runtime');
77
+ }
78
+ async pollOnce() {
79
+ this.assertActive();
80
+ if (this.pollInFlight !== undefined)
81
+ return this.pollInFlight;
82
+ const operation = this.track(Promise.resolve().then(() => this.performPollOnce()));
83
+ this.pollInFlight = operation;
84
+ const clear = () => { if (this.pollInFlight === operation)
85
+ this.pollInFlight = undefined; };
86
+ void operation.then(clear, clear);
87
+ return operation;
88
+ }
89
+ async performPollOnce() {
90
+ const failures = [];
91
+ const enabled = this.config.triggers.filter((trigger) => trigger.enabled && trigger.kind !== 'webhook');
92
+ if (enabled.length > 0) {
93
+ const start = this.pollCursor % enabled.length;
94
+ const triggers = [...enabled.slice(start), ...enabled.slice(0, start)];
95
+ this.pollCursor = (start + 1) % enabled.length;
96
+ let next = 0;
97
+ const worker = async () => {
98
+ while (!this.shutdown.signal.aborted) {
99
+ const trigger = triggers[next];
100
+ next += 1;
101
+ if (trigger === undefined)
102
+ return;
103
+ try {
104
+ await this.observeTrigger(trigger);
105
+ }
106
+ catch (error) {
107
+ if (this.shutdown.signal.aborted)
108
+ return;
109
+ this.store.markTriggerFailure(trigger.id, error, this.now());
110
+ failures.push(error);
111
+ }
112
+ }
113
+ };
114
+ const workerCount = Math.min(this.config.pollConcurrency, triggers.length);
115
+ const workers = await Promise.allSettled(Array.from({ length: workerCount }, worker));
116
+ if (this.shutdown.signal.aborted)
117
+ throw this.shutdown.signal.reason;
118
+ for (const result of workers)
119
+ if (result.status === 'rejected')
120
+ failures.push(result.reason);
121
+ }
122
+ await this.startFlush();
123
+ if (failures.length === 1)
124
+ throw failures[0];
125
+ if (failures.length > 1 && failures.every(error => error instanceof EventTriggersError && error.code === 'policy-denied')) {
126
+ throw failures[0];
127
+ }
128
+ if (failures.length > 1)
129
+ throw new AggregateError(failures, 'event-triggers: one or more sensors failed');
130
+ }
131
+ async observeTrigger(trigger) {
132
+ const resource = trigger.kind === 'file'
133
+ ? { kind: 'filesystem', id: trigger.path }
134
+ : { kind: 'network', id: trigger.url };
135
+ const decision = this.policy.authorize({
136
+ subject: { kind: 'background', id: `event-triggers:${trigger.id}` },
137
+ action: 'observe', resource, context: { initiator: 'background' },
138
+ }, { idempotencyKey: `event-observe:${trigger.id}:${this.now()}` });
139
+ if (decision.effect !== 'allow') {
140
+ throw new EventTriggersError('policy-denied', `event-triggers policy denied observation: ${decision.reasonCode}`);
141
+ }
142
+ const observation = await this.startObservation(trigger);
143
+ if (observation === undefined)
144
+ return;
145
+ if (this.shutdown.signal.aborted)
146
+ throw this.shutdown.signal.reason;
147
+ const occurredAt = this.now();
148
+ this.store.observe({
149
+ triggerId: trigger.id, ...observation, occurredAt, fireWhen: trigger.fireWhen,
150
+ debounceMs: trigger.debounceMs, cooldownMs: trigger.cooldownMs,
151
+ maxFires: trigger.maxFires, ...(trigger.ttlMs === undefined ? {} : { ttlMs: trigger.ttlMs }),
152
+ });
153
+ this.store.markTriggerSuccess(trigger.id, occurredAt);
154
+ }
155
+ /**
156
+ * Starts at most one pure sensor read per trigger. A timed-out filesystem read
157
+ * may be uninterruptible, so its eventual result is discarded and no durable
158
+ * state is touched outside the bounded waiter below.
159
+ */
160
+ async startObservation(trigger) {
161
+ if (this.pendingObservations.has(trigger.id))
162
+ return undefined;
163
+ const controller = new AbortController();
164
+ const forwardShutdown = () => controller.abort(this.shutdown.signal.reason);
165
+ if (this.shutdown.signal.aborted)
166
+ forwardShutdown();
167
+ else
168
+ this.shutdown.signal.addEventListener('abort', forwardShutdown, { once: true });
169
+ let entry;
170
+ const removeIfIdle = () => {
171
+ if (entry.wrapperSettled && entry.operations.size === 0
172
+ && this.pendingObservations.get(trigger.id) === entry)
173
+ this.pendingObservations.delete(trigger.id);
174
+ };
175
+ const trackOperation = (operation) => {
176
+ entry.operations.add(operation);
177
+ const settled = () => { entry.operations.delete(operation); removeIfIdle(); };
178
+ void operation.then(settled, settled);
179
+ return operation;
180
+ };
181
+ const promise = Promise.resolve().then(() => trigger.kind === 'file'
182
+ ? this.fileObserver({ path: trigger.path, roots: this.config.allowedFileRoots,
183
+ mode: trigger.mode, maxBytes: this.config.maxBodyBytes, pinnedRoots: this.pinnedFileRoots })
184
+ : readHttpJsonObservation({ url: trigger.url, pointer: trigger.pointer,
185
+ maxBodyBytes: this.config.maxBodyBytes, timeoutMs: this.config.requestTimeoutMs,
186
+ allowedOrigins: new Set(this.config.allowedHttpOrigins), lookup: this.lookup, signal: controller.signal,
187
+ allowIpv6: this.config.ipv6Mode === 'native-only', trackOperation,
188
+ ...(this.fetcher === undefined ? {} : { fetcher: this.fetcher }) }));
189
+ entry = { controller, promise, operations: new Set(), wrapperSettled: false };
190
+ this.pendingObservations.set(trigger.id, entry);
191
+ const wrapperSettled = () => {
192
+ entry.wrapperSettled = true;
193
+ removeIfIdle();
194
+ };
195
+ void promise.then(wrapperSettled, wrapperSettled);
196
+ const timer = setTimeout(() => {
197
+ controller.abort(new Error(`event-triggers: observation timed out for trigger ${trigger.id}`));
198
+ }, this.config.requestTimeoutMs);
199
+ timer.unref?.();
200
+ try {
201
+ const observation = await this.raceObservation(promise, controller.signal);
202
+ if (controller.signal.aborted)
203
+ throw controller.signal.reason;
204
+ return observation;
205
+ }
206
+ finally {
207
+ clearTimeout(timer);
208
+ this.shutdown.signal.removeEventListener('abort', forwardShutdown);
209
+ }
210
+ }
211
+ async raceObservation(operation, signal) {
212
+ if (signal.aborted)
213
+ throw signal.reason;
214
+ return new Promise((resolvePromise, rejectPromise) => {
215
+ const aborted = () => { cleanup(); rejectPromise(signal.reason); };
216
+ const cleanup = () => signal.removeEventListener('abort', aborted);
217
+ signal.addEventListener('abort', aborted, { once: true });
218
+ void operation.then(value => { cleanup(); resolvePromise(value); }, error => { cleanup(); rejectPromise(error); });
219
+ });
220
+ }
221
+ async flushPending() {
222
+ this.assertActive();
223
+ return this.startFlush();
224
+ }
225
+ startFlush() {
226
+ if (this.flushInFlight !== undefined)
227
+ return this.flushInFlight;
228
+ const operation = this.track(Promise.resolve().then(() => this.performFlushPending()));
229
+ this.flushInFlight = operation;
230
+ const clear = () => { if (this.flushInFlight === operation)
231
+ this.flushInFlight = undefined; };
232
+ void operation.then(clear, clear);
233
+ return operation;
234
+ }
235
+ async performFlushPending() {
236
+ const maximum = 2_000;
237
+ let processed = 0;
238
+ while (processed < maximum) {
239
+ const items = this.store.pending(Math.min(100, maximum - processed));
240
+ if (items.length === 0)
241
+ return;
242
+ for (const item of items) {
243
+ processed += 1;
244
+ const trigger = this.triggers.get(item.triggerId);
245
+ if (trigger === undefined || !trigger.enabled) {
246
+ this.store.quarantine(item.id, 'trigger is no longer configured or enabled');
247
+ continue;
248
+ }
249
+ this.store.markAttempt(item.id);
250
+ try {
251
+ this.automations.ingestExternal({
252
+ sourceId: `event-triggers:${trigger.id}`,
253
+ automationId: trigger.automationId,
254
+ eventId: item.eventId,
255
+ occurredAt: item.occurredAt,
256
+ });
257
+ this.store.markDelivered(item.id);
258
+ }
259
+ catch (error) {
260
+ const exponent = Math.min(item.attempts, 10);
261
+ const delay = Math.min(3_600_000, this.config.pollIntervalMs * (2 ** exponent));
262
+ this.store.markRetry(item.id, error, this.now() + delay);
263
+ }
264
+ }
265
+ }
266
+ }
267
+ async ingestWebhook(triggerId, input) {
268
+ this.assertActive();
269
+ return this.track(Promise.resolve().then(() => this.performIngestWebhook(triggerId, input)));
270
+ }
271
+ async performIngestWebhook(triggerId, input) {
272
+ const trigger = this.triggers.get(triggerId);
273
+ if (trigger?.kind !== 'webhook' || !trigger.enabled)
274
+ throw new EventTriggersError('not-found', 'webhook trigger was not found');
275
+ if (input.body.byteLength > this.config.maxBodyBytes)
276
+ throw new Error('event-triggers: webhook body exceeds limit');
277
+ const receivedAt = this.now();
278
+ const timestamp = Number(input.timestamp);
279
+ if (!Number.isSafeInteger(timestamp) || Math.abs(receivedAt - timestamp) > trigger.maxSkewMs) {
280
+ throw new EventTriggersError('timestamp', 'event-triggers: webhook timestamp is outside the accepted window');
281
+ }
282
+ if (!/^[A-Za-z0-9._:-]{1,200}$/u.test(input.nonce))
283
+ throw new EventTriggersError('replay', 'invalid webhook nonce');
284
+ if (this.store.hasWebhookEvent(trigger.id, input.nonce))
285
+ throw new EventTriggersError('replay', 'webhook nonce was already accepted');
286
+ if (!/^sha256=[a-f0-9]{64}$/u.test(input.signature)) {
287
+ throw new EventTriggersError('invalid-signature', 'event-triggers: webhook signature is malformed');
288
+ }
289
+ await this.verifySignature(trigger, input);
290
+ const decision = this.policy.authorize({
291
+ subject: { kind: 'external', id: `webhook:${trigger.id}` }, action: 'accept',
292
+ resource: { kind: 'automation', id: trigger.automationId }, context: { initiator: 'external' },
293
+ }, { idempotencyKey: `event-webhook:${trigger.id}:${input.nonce}` });
294
+ if (decision.effect !== 'allow')
295
+ throw new EventTriggersError('policy-denied', 'event-triggers policy denied webhook');
296
+ const accepted = this.store.acceptWebhook({
297
+ triggerId: trigger.id, eventId: input.nonce, occurredAt: timestamp, acceptedAt: receivedAt,
298
+ cooldownMs: trigger.cooldownMs, maxFires: trigger.maxFires,
299
+ ...(trigger.ttlMs === undefined ? {} : { ttlMs: trigger.ttlMs }),
300
+ });
301
+ if (!accepted.accepted) {
302
+ throw new EventTriggersError(accepted.reason, `event-triggers: webhook event was rejected by ${accepted.reason}`);
303
+ }
304
+ await this.startFlush();
305
+ return { accepted: true, eventId: accepted.event.eventId };
306
+ }
307
+ health() { this.assertActive(); return this.store.health(); }
308
+ async verifySignature(trigger, input) {
309
+ await this.credentials.withSecret(this.ctx, {
310
+ handleId: trigger.credentialHandle,
311
+ purpose: 'verify-webhook',
312
+ ttlMs: 10_000,
313
+ idempotencyKey: `event-webhook-signature:${trigger.id}:${input.nonce}`,
314
+ }, async (secret) => {
315
+ const expected = createHmac('sha256', secret).update(`${input.timestamp}\n${input.nonce}\n`).update(input.body).digest();
316
+ const supplied = Buffer.from(input.signature.slice('sha256='.length), 'hex');
317
+ if (supplied.byteLength !== expected.byteLength || !timingSafeEqual(supplied, expected)) {
318
+ throw new EventTriggersError('invalid-signature', 'event-triggers: webhook signature is invalid');
319
+ }
320
+ });
321
+ }
322
+ assertActive() {
323
+ if (!this.active)
324
+ throw new EventTriggersError('disposed', 'event-triggers service is disposed');
325
+ }
326
+ track(operation) {
327
+ this.inFlight.add(operation);
328
+ const remove = () => { this.inFlight.delete(operation); };
329
+ void operation.then(remove, remove);
330
+ return operation;
331
+ }
332
+ }
333
+ export { ConfigSchema as Config };
334
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { DatabaseSync } from 'node:sqlite';
2
+ export declare class EventTriggerDatabaseError extends Error {
3
+ readonly code: 'invalid-path' | 'schema-too-new';
4
+ constructor(code: 'invalid-path' | 'schema-too-new', message: string);
5
+ }
6
+ export declare function openEventTriggerDatabase(path: string): DatabaseSync;
7
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,qBAAa,yBAA0B,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,gBAAgB;gBAAvC,IAAI,EAAE,cAAc,GAAG,gBAAgB,EAAE,OAAO,EAAE,MAAM;CAI9E;AAoFD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAuBnE"}
package/lib/sqlite.js ADDED
@@ -0,0 +1,128 @@
1
+ import { chmodSync, mkdirSync } from 'node:fs';
2
+ import { dirname, isAbsolute } from 'node:path';
3
+ import { DatabaseSync } from 'node:sqlite';
4
+ export class EventTriggerDatabaseError extends Error {
5
+ code;
6
+ constructor(code, message) {
7
+ super(message);
8
+ this.code = code;
9
+ this.name = 'EventTriggerDatabaseError';
10
+ }
11
+ }
12
+ function migrate(database) {
13
+ database.exec('BEGIN IMMEDIATE');
14
+ try {
15
+ const version = database.prepare('PRAGMA user_version').get().user_version;
16
+ if (version > 2)
17
+ throw new EventTriggerDatabaseError('schema-too-new', `event trigger schema ${version} is too new`);
18
+ if (version === 2) {
19
+ database.exec('COMMIT');
20
+ return;
21
+ }
22
+ if (version === 0)
23
+ database.exec(`
24
+ CREATE TABLE trigger_state (
25
+ trigger_id TEXT PRIMARY KEY,
26
+ first_observed_at INTEGER NOT NULL,
27
+ last_observed_at INTEGER NOT NULL,
28
+ last_fingerprint TEXT NOT NULL,
29
+ last_truthy INTEGER NOT NULL CHECK (last_truthy IN (0, 1)),
30
+ edge_revision INTEGER NOT NULL DEFAULT 0,
31
+ pending_fingerprint TEXT,
32
+ pending_since INTEGER,
33
+ pending_revision INTEGER,
34
+ last_fire_at INTEGER,
35
+ fire_count INTEGER NOT NULL DEFAULT 0
36
+ ) STRICT;
37
+ CREATE TABLE event_outbox (
38
+ id TEXT PRIMARY KEY,
39
+ trigger_id TEXT NOT NULL,
40
+ event_id TEXT NOT NULL UNIQUE,
41
+ occurred_at INTEGER NOT NULL,
42
+ status TEXT NOT NULL CHECK (status IN ('pending', 'delivered', 'quarantined')),
43
+ attempts INTEGER NOT NULL DEFAULT 0,
44
+ delivered_at INTEGER,
45
+ created_at INTEGER NOT NULL,
46
+ next_attempt_at INTEGER NOT NULL,
47
+ last_attempt_at INTEGER,
48
+ last_error TEXT
49
+ ) STRICT;
50
+ CREATE TABLE trigger_health (
51
+ trigger_id TEXT PRIMARY KEY,
52
+ consecutive_failures INTEGER NOT NULL DEFAULT 0,
53
+ last_error TEXT,
54
+ last_failed_at INTEGER,
55
+ last_success_at INTEGER
56
+ ) STRICT;
57
+ CREATE INDEX event_outbox_pending ON event_outbox(status, next_attempt_at, created_at, id);
58
+ `);
59
+ if (version === 1)
60
+ database.exec(`
61
+ DROP INDEX event_outbox_pending;
62
+ ALTER TABLE event_outbox RENAME TO event_outbox_v1;
63
+ CREATE TABLE event_outbox (
64
+ id TEXT PRIMARY KEY,
65
+ trigger_id TEXT NOT NULL,
66
+ event_id TEXT NOT NULL UNIQUE,
67
+ occurred_at INTEGER NOT NULL,
68
+ status TEXT NOT NULL CHECK (status IN ('pending', 'delivered', 'quarantined')),
69
+ attempts INTEGER NOT NULL DEFAULT 0,
70
+ delivered_at INTEGER,
71
+ created_at INTEGER NOT NULL,
72
+ next_attempt_at INTEGER NOT NULL,
73
+ last_attempt_at INTEGER,
74
+ last_error TEXT
75
+ ) STRICT;
76
+ INSERT INTO event_outbox(
77
+ id, trigger_id, event_id, occurred_at, status, attempts, delivered_at, created_at,
78
+ next_attempt_at, last_attempt_at, last_error
79
+ ) SELECT id, trigger_id, event_id, occurred_at, status, attempts, delivered_at, created_at,
80
+ created_at, CASE WHEN attempts > 0 THEN created_at ELSE NULL END, NULL
81
+ FROM event_outbox_v1;
82
+ DROP TABLE event_outbox_v1;
83
+ CREATE TABLE trigger_health (
84
+ trigger_id TEXT PRIMARY KEY,
85
+ consecutive_failures INTEGER NOT NULL DEFAULT 0,
86
+ last_error TEXT,
87
+ last_failed_at INTEGER,
88
+ last_success_at INTEGER
89
+ ) STRICT;
90
+ CREATE INDEX event_outbox_pending ON event_outbox(status, next_attempt_at, created_at, id);
91
+ `);
92
+ database.exec('PRAGMA user_version = 2');
93
+ database.exec('COMMIT');
94
+ }
95
+ catch (error) {
96
+ try {
97
+ database.exec('ROLLBACK');
98
+ }
99
+ catch { }
100
+ throw error;
101
+ }
102
+ }
103
+ export function openEventTriggerDatabase(path) {
104
+ if (path !== ':memory:' && !isAbsolute(path)) {
105
+ throw new EventTriggerDatabaseError('invalid-path', 'event trigger database path must be absolute');
106
+ }
107
+ if (path !== ':memory:') {
108
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
109
+ chmodSync(dirname(path), 0o700);
110
+ }
111
+ const database = new DatabaseSync(path);
112
+ try {
113
+ database.exec('PRAGMA foreign_keys = ON');
114
+ database.exec('PRAGMA busy_timeout = 5000');
115
+ database.exec('PRAGMA synchronous = FULL');
116
+ migrate(database);
117
+ if (path !== ':memory:') {
118
+ database.exec('PRAGMA journal_mode = WAL');
119
+ chmodSync(path, 0o600);
120
+ }
121
+ return database;
122
+ }
123
+ catch (error) {
124
+ database.close();
125
+ throw error;
126
+ }
127
+ }
128
+ //# sourceMappingURL=sqlite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.js","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC9C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAC7B;IAArB,YAAqB,IAAuC,EAAE,OAAe;QAC3E,KAAK,CAAC,OAAO,CAAC,CAAA;QADK,SAAI,GAAJ,IAAI,CAAmC;QAE1D,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;IACzC,CAAC;CACF;AAED,SAAS,OAAO,CAAC,QAAsB;IACrC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAChC,IAAI,CAAC;QACH,MAAM,OAAO,GAAI,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,GAAG,EAA+B,CAAC,YAAY,CAAA;QACxG,IAAI,OAAO,GAAG,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,gBAAgB,EAAE,wBAAwB,OAAO,aAAa,CAAC,CAAA;QACpH,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;YAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAAC,OAAM;QAAC,CAAC;QACtD,IAAI,OAAO,KAAK,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmChC,CAAC,CAAA;QACF,IAAI,OAAO,KAAK,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+BhC,CAAC,CAAA;QACF,QAAQ,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA;QACxC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACzB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;QAC1C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,IAAI,IAAI,KAAK,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,yBAAyB,CAAC,cAAc,EAAE,8CAA8C,CAAC,CAAA;IACrG,CAAC;IACD,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QACxB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QAC1D,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAA;IACjC,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAA;IACvC,IAAI,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;QACzC,QAAQ,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;QAC3C,QAAQ,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;QAC1C,OAAO,CAAC,QAAQ,CAAC,CAAA;QACjB,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;YAC1C,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QACxB,CAAC;QACD,OAAO,QAAQ,CAAA;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,QAAQ,CAAC,KAAK,EAAE,CAAA;QAChB,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC"}
package/lib/store.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ import type { FireWhen } from './config.js';
2
+ export type EventTriggerStoreErrorCode = 'invalid-input' | 'invalid-path' | 'schema-too-new';
3
+ export declare class EventTriggerStoreError extends Error {
4
+ readonly code: EventTriggerStoreErrorCode;
5
+ constructor(code: EventTriggerStoreErrorCode, message: string);
6
+ }
7
+ export interface TriggerOutboxEvent {
8
+ id: string;
9
+ triggerId: string;
10
+ eventId: string;
11
+ occurredAt: number;
12
+ status: 'delivered' | 'pending' | 'quarantined';
13
+ attempts: number;
14
+ deliveredAt?: number;
15
+ nextAttemptAt: number;
16
+ lastAttemptAt?: number;
17
+ lastError?: string;
18
+ createdAt: number;
19
+ }
20
+ export type WebhookAcceptance = {
21
+ accepted: true;
22
+ event: TriggerOutboxEvent;
23
+ } | {
24
+ accepted: false;
25
+ event?: TriggerOutboxEvent;
26
+ reason: 'cooldown' | 'limit' | 'replay' | 'ttl';
27
+ };
28
+ export declare class EventTriggerStore {
29
+ private readonly database;
30
+ private readonly now;
31
+ private closed;
32
+ constructor(options: {
33
+ path: string;
34
+ now?: () => number;
35
+ });
36
+ close(): void;
37
+ observe(input: {
38
+ triggerId: string;
39
+ fingerprint: string;
40
+ truthy: boolean;
41
+ occurredAt: number;
42
+ fireWhen: FireWhen;
43
+ debounceMs: number;
44
+ cooldownMs: number;
45
+ maxFires: number;
46
+ ttlMs?: number;
47
+ }): TriggerOutboxEvent[];
48
+ acceptWebhook(input: {
49
+ triggerId: string;
50
+ eventId: string;
51
+ occurredAt: number;
52
+ /** Trusted server receipt time. Defaults to occurredAt for API compatibility. */
53
+ acceptedAt?: number;
54
+ cooldownMs?: number;
55
+ maxFires: number;
56
+ ttlMs?: number;
57
+ }): WebhookAcceptance;
58
+ hasWebhookEvent(triggerId: string, externalEventId: string): boolean;
59
+ pending(limit?: number): TriggerOutboxEvent[];
60
+ markAttempt(id: string): void;
61
+ markRetry(id: string, error: unknown, nextAttemptAt: number): void;
62
+ quarantine(id: string, reason: unknown): void;
63
+ markDelivered(id: string): TriggerOutboxEvent;
64
+ markTriggerFailure(triggerId: string, error: unknown, failedAt?: number): void;
65
+ markTriggerSuccess(triggerId: string, succeededAt?: number): void;
66
+ health(): {
67
+ pendingEvents: number;
68
+ retryingEvents: number;
69
+ quarantinedEvents: number;
70
+ deliveredEvents: number;
71
+ triggersObserved: number;
72
+ failingTriggers: number;
73
+ lastOutboxError?: string;
74
+ lastTriggerError?: string;
75
+ };
76
+ private state;
77
+ private byEventId;
78
+ private insertOutbox;
79
+ private transaction;
80
+ }
81
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}