hazo_notify 5.0.0 → 5.2.1
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 +5 -5
- package/dist/components/notification_bell/index.d.ts +11 -1
- package/dist/components/notification_bell/index.d.ts.map +1 -1
- package/dist/components/notification_bell/index.js +33 -1
- package/dist/components/notification_bell/index.js.map +1 -1
- package/dist/lib/adapters/email/adapter.d.ts +2 -0
- package/dist/lib/adapters/email/adapter.d.ts.map +1 -1
- package/dist/lib/adapters/email/adapter.js +53 -22
- package/dist/lib/adapters/email/adapter.js.map +1 -1
- package/dist/lib/adapters/webhook/adapter.d.ts +10 -0
- package/dist/lib/adapters/webhook/adapter.d.ts.map +1 -0
- package/dist/lib/adapters/webhook/adapter.js +90 -0
- package/dist/lib/adapters/webhook/adapter.js.map +1 -0
- package/dist/lib/adapters/webhook/index.d.ts +8 -0
- package/dist/lib/adapters/webhook/index.d.ts.map +1 -0
- package/dist/lib/adapters/webhook/index.js +3 -0
- package/dist/lib/adapters/webhook/index.js.map +1 -0
- package/dist/lib/adapters/webhook/types.d.ts +45 -0
- package/dist/lib/adapters/webhook/types.d.ts.map +1 -0
- package/dist/lib/adapters/webhook/types.js +12 -0
- package/dist/lib/adapters/webhook/types.js.map +1 -0
- package/dist/lib/api/inbox.d.ts +32 -0
- package/dist/lib/api/inbox.d.ts.map +1 -1
- package/dist/lib/api/inbox.js +68 -0
- package/dist/lib/api/inbox.js.map +1 -1
- package/dist/lib/dispatcher/index.d.ts +2 -2
- package/dist/lib/dispatcher/index.d.ts.map +1 -1
- package/dist/lib/dispatcher/index.js +28 -8
- package/dist/lib/dispatcher/index.js.map +1 -1
- package/dist/lib/inbox/broadcaster.d.ts +44 -0
- package/dist/lib/inbox/broadcaster.d.ts.map +1 -0
- package/dist/lib/inbox/broadcaster.js +62 -0
- package/dist/lib/inbox/broadcaster.js.map +1 -0
- package/dist/lib/inbox/index.d.ts +2 -0
- package/dist/lib/inbox/index.d.ts.map +1 -1
- package/dist/lib/inbox/index.js +1 -0
- package/dist/lib/inbox/index.js.map +1 -1
- package/dist/lib/inbox/storage.d.ts +11 -32
- package/dist/lib/inbox/storage.d.ts.map +1 -1
- package/dist/lib/inbox/storage.js +22 -38
- package/dist/lib/inbox/storage.js.map +1 -1
- package/dist/lib/inbox/types.d.ts +7 -0
- package/dist/lib/inbox/types.d.ts.map +1 -1
- package/dist/lib/jobs/submit.d.ts.map +1 -1
- package/dist/lib/jobs/submit.js +1 -0
- package/dist/lib/jobs/submit.js.map +1 -1
- package/dist/lib/jobs/types.d.ts +1 -0
- package/dist/lib/jobs/types.d.ts.map +1 -1
- package/dist/lib/lifecycle/default_templates.d.ts +9 -0
- package/dist/lib/lifecycle/default_templates.d.ts.map +1 -0
- package/dist/lib/lifecycle/default_templates.js +160 -0
- package/dist/lib/lifecycle/default_templates.js.map +1 -0
- package/dist/lib/lifecycle/dispatch.d.ts +37 -0
- package/dist/lib/lifecycle/dispatch.d.ts.map +1 -0
- package/dist/lib/lifecycle/dispatch.js +32 -0
- package/dist/lib/lifecycle/dispatch.js.map +1 -0
- package/dist/lib/lifecycle/events.d.ts +34 -0
- package/dist/lib/lifecycle/events.d.ts.map +1 -0
- package/dist/lib/lifecycle/events.js +118 -0
- package/dist/lib/lifecycle/events.js.map +1 -0
- package/dist/lib/lifecycle/handler.d.ts +29 -0
- package/dist/lib/lifecycle/handler.d.ts.map +1 -0
- package/dist/lib/lifecycle/handler.js +145 -0
- package/dist/lib/lifecycle/handler.js.map +1 -0
- package/dist/lib/lifecycle/index.d.ts +23 -0
- package/dist/lib/lifecycle/index.d.ts.map +1 -0
- package/dist/lib/lifecycle/index.js +21 -0
- package/dist/lib/lifecycle/index.js.map +1 -0
- package/dist/lib/lifecycle/register.d.ts +29 -0
- package/dist/lib/lifecycle/register.d.ts.map +1 -0
- package/dist/lib/lifecycle/register.js +29 -0
- package/dist/lib/lifecycle/register.js.map +1 -0
- package/dist/lib/lifecycle/resolver.d.ts +22 -0
- package/dist/lib/lifecycle/resolver.d.ts.map +1 -0
- package/dist/lib/lifecycle/resolver.js +105 -0
- package/dist/lib/lifecycle/resolver.js.map +1 -0
- package/dist/lib/lifecycle/scheduler.d.ts +27 -0
- package/dist/lib/lifecycle/scheduler.d.ts.map +1 -0
- package/dist/lib/lifecycle/scheduler.js +108 -0
- package/dist/lib/lifecycle/scheduler.js.map +1 -0
- package/dist/lib/lifecycle/status.d.ts +39 -0
- package/dist/lib/lifecycle/status.d.ts.map +1 -0
- package/dist/lib/lifecycle/status.js +67 -0
- package/dist/lib/lifecycle/status.js.map +1 -0
- package/dist/lib/lifecycle/types.d.ts +165 -0
- package/dist/lib/lifecycle/types.d.ts.map +1 -0
- package/dist/lib/lifecycle/types.js +11 -0
- package/dist/lib/lifecycle/types.js.map +1 -0
- package/dist/lib/preferences/index.d.ts +3 -0
- package/dist/lib/preferences/index.d.ts.map +1 -0
- package/dist/lib/preferences/index.js +3 -0
- package/dist/lib/preferences/index.js.map +1 -0
- package/dist/lib/preferences/storage.d.ts +33 -0
- package/dist/lib/preferences/storage.d.ts.map +1 -0
- package/dist/lib/preferences/storage.js +125 -0
- package/dist/lib/preferences/storage.js.map +1 -0
- package/dist/lib/preferences/types.d.ts +59 -0
- package/dist/lib/preferences/types.d.ts.map +1 -0
- package/dist/lib/preferences/types.js +20 -0
- package/dist/lib/preferences/types.js.map +1 -0
- package/dist/lib/template_manager/db/template_repository.d.ts +4 -1
- package/dist/lib/template_manager/db/template_repository.d.ts.map +1 -1
- package/dist/lib/template_manager/db/template_repository.js +17 -1
- package/dist/lib/template_manager/db/template_repository.js.map +1 -1
- package/dist/lib/template_manager/types.d.ts +1 -0
- package/dist/lib/template_manager/types.d.ts.map +1 -1
- package/migrations/008_lifecycle_status.pg.sql +27 -0
- package/migrations/008_lifecycle_status.sqlite.sql +24 -0
- package/migrations/009_templates_locale.pg.sql +6 -0
- package/migrations/009_templates_locale.sqlite.sql +4 -0
- package/migrations/010_preferences.pg.sql +26 -0
- package/migrations/010_preferences.sqlite.sql +32 -0
- package/package.json +17 -5
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { getChannel } from
|
|
2
|
-
import { upsertInboxRow, upsertDelivery } from
|
|
3
|
-
import { buildBatchKey } from
|
|
1
|
+
import { getChannel } from '../channels/registry.js';
|
|
2
|
+
import { upsertInboxRow, upsertDelivery } from '../inbox/storage.js';
|
|
3
|
+
import { buildBatchKey } from './batch-key.js';
|
|
4
|
+
import { batchGetPreferences } from '../preferences/storage.js';
|
|
5
|
+
import { getInboxBroadcaster } from '../inbox/broadcaster.js';
|
|
4
6
|
const DEFAULT_BATCH_WINDOW_MS = 5 * 60000;
|
|
5
7
|
export async function dispatch(input) {
|
|
6
8
|
const enabled = Object.entries(input.channels)
|
|
@@ -16,20 +18,29 @@ export async function dispatch(input) {
|
|
|
16
18
|
throw new Error(`dispatch: channel_payloads.${id} required`);
|
|
17
19
|
const v = adapter.validate(payload);
|
|
18
20
|
if (!v.ok)
|
|
19
|
-
throw new Error(`dispatch: validation failed for ${id}: ${(v.errors ?? []).join(
|
|
21
|
+
throw new Error(`dispatch: validation failed for ${id}: ${(v.errors ?? []).join('; ')}`);
|
|
20
22
|
}
|
|
21
23
|
if (input.recipient_user_ids.length === 0 || enabled.length === 0) {
|
|
22
24
|
return {
|
|
23
25
|
inbox_rows_upserted: 0, inbox_rows_inserted: 0, inbox_rows_aggregated: 0,
|
|
24
|
-
deliveries_created: 0, deliveries_refreshed: 0,
|
|
26
|
+
deliveries_created: 0, deliveries_refreshed: 0, deliveries_skipped_by_preference: 0,
|
|
25
27
|
channels_dispatched: enabled,
|
|
26
28
|
};
|
|
27
29
|
}
|
|
30
|
+
// Batch-fetch preferences for all recipients × channels before the loop.
|
|
31
|
+
const pref_map = await batchGetPreferences({
|
|
32
|
+
user_ids: input.recipient_user_ids,
|
|
33
|
+
scope_id: input.scope_id,
|
|
34
|
+
event_type: input.event_type,
|
|
35
|
+
channel_ids: enabled,
|
|
36
|
+
default_mode: input.preference_default ?? 'on',
|
|
37
|
+
});
|
|
38
|
+
const broadcaster = getInboxBroadcaster();
|
|
28
39
|
const window_ms = input.batch_window_ms ?? DEFAULT_BATCH_WINDOW_MS;
|
|
29
40
|
const now = Date.now();
|
|
30
41
|
const batch_closed_at = window_ms === 0 ? new Date(now).toISOString() : null;
|
|
31
42
|
const flush_after = new Date(now + window_ms).toISOString();
|
|
32
|
-
let inserted = 0, aggregated = 0, deliveries_created = 0, deliveries_refreshed = 0;
|
|
43
|
+
let inserted = 0, aggregated = 0, deliveries_created = 0, deliveries_refreshed = 0, deliveries_skipped = 0;
|
|
33
44
|
for (const user_id of input.recipient_user_ids) {
|
|
34
45
|
const batch_key = buildBatchKey(input.event_type, input.subject_id, user_id, window_ms);
|
|
35
46
|
const inbox = await upsertInboxRow({
|
|
@@ -44,11 +55,19 @@ export async function dispatch(input) {
|
|
|
44
55
|
surfaces: input.surfaces,
|
|
45
56
|
batch_closed_at,
|
|
46
57
|
});
|
|
47
|
-
if (inbox.inserted)
|
|
58
|
+
if (inbox.inserted) {
|
|
48
59
|
inserted++;
|
|
49
|
-
|
|
60
|
+
broadcaster?.notify(user_id, { user_id, inbox_id: inbox.id });
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
50
63
|
aggregated++;
|
|
64
|
+
}
|
|
51
65
|
for (const channel_id of enabled) {
|
|
66
|
+
const mode = pref_map.get(user_id)?.get(channel_id) ?? (input.preference_default ?? 'on');
|
|
67
|
+
if (mode === 'off') {
|
|
68
|
+
deliveries_skipped++;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
52
71
|
const d = await upsertDelivery({
|
|
53
72
|
inbox_id: inbox.id,
|
|
54
73
|
channel_id,
|
|
@@ -67,6 +86,7 @@ export async function dispatch(input) {
|
|
|
67
86
|
inbox_rows_aggregated: aggregated,
|
|
68
87
|
deliveries_created,
|
|
69
88
|
deliveries_refreshed,
|
|
89
|
+
deliveries_skipped_by_preference: deliveries_skipped,
|
|
70
90
|
channels_dispatched: enabled,
|
|
71
91
|
};
|
|
72
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/dispatcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/dispatcher/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-process broadcaster for inbox push events.
|
|
3
|
+
*
|
|
4
|
+
* Single-instance: use createInboxBroadcaster() — returns a matched
|
|
5
|
+
* { broadcaster, subscribe } pair backed by an in-process Map.
|
|
6
|
+
*
|
|
7
|
+
* Multi-instance: provide your own InboxBroadcaster implementation (e.g.
|
|
8
|
+
* backed by Redis pub/sub) and register it with setInboxBroadcaster().
|
|
9
|
+
* The subscribe function used by createInboxStreamRoute must be wired to
|
|
10
|
+
* the same channel.
|
|
11
|
+
*
|
|
12
|
+
* Both setInboxBroadcaster and the subscribe Map are stored on globalThis
|
|
13
|
+
* so they survive Next.js dev-mode bundle isolation.
|
|
14
|
+
*
|
|
15
|
+
* @packageDocumentation
|
|
16
|
+
*/
|
|
17
|
+
/** Payload pushed to SSE clients when a new inbox row is inserted. */
|
|
18
|
+
export interface InboxBroadcastEvent {
|
|
19
|
+
user_id: string;
|
|
20
|
+
inbox_id: string;
|
|
21
|
+
}
|
|
22
|
+
/** Minimal broadcaster interface. Implement this for multi-instance fan-out. */
|
|
23
|
+
export interface InboxBroadcaster {
|
|
24
|
+
notify(user_id: string, event: InboxBroadcastEvent): void;
|
|
25
|
+
}
|
|
26
|
+
/** Register a broadcaster. Call once at app boot. */
|
|
27
|
+
export declare function setInboxBroadcaster(broadcaster: InboxBroadcaster): void;
|
|
28
|
+
/** Returns the registered broadcaster, or null if not configured. */
|
|
29
|
+
export declare function getInboxBroadcaster(): InboxBroadcaster | null;
|
|
30
|
+
/**
|
|
31
|
+
* Create an in-process broadcaster + matching subscribe function.
|
|
32
|
+
*
|
|
33
|
+
* Consumer wiring:
|
|
34
|
+
* ```ts
|
|
35
|
+
* const { broadcaster, subscribe } = createInboxBroadcaster();
|
|
36
|
+
* setInboxBroadcaster(broadcaster);
|
|
37
|
+
* export const GET = createInboxStreamRoute({ getAuth, subscribe });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function createInboxBroadcaster(): {
|
|
41
|
+
broadcaster: InboxBroadcaster;
|
|
42
|
+
subscribe: (user_id: string, fn: (event: InboxBroadcastEvent) => void) => () => void;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=broadcaster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcaster.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/broadcaster.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;GAeG;AAEH,sEAAsE;AACtE,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;CAC3D;AAOD,qDAAqD;AACrD,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,gBAAgB,GAAG,IAAI,CAEvE;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,IAAI,gBAAgB,GAAG,IAAI,CAE7D;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,IAAI;IACxC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,KAAK,MAAM,IAAI,CAAC;CACtF,CAwBA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/lib/inbox/broadcaster.ts
|
|
2
|
+
/**
|
|
3
|
+
* In-process broadcaster for inbox push events.
|
|
4
|
+
*
|
|
5
|
+
* Single-instance: use createInboxBroadcaster() — returns a matched
|
|
6
|
+
* { broadcaster, subscribe } pair backed by an in-process Map.
|
|
7
|
+
*
|
|
8
|
+
* Multi-instance: provide your own InboxBroadcaster implementation (e.g.
|
|
9
|
+
* backed by Redis pub/sub) and register it with setInboxBroadcaster().
|
|
10
|
+
* The subscribe function used by createInboxStreamRoute must be wired to
|
|
11
|
+
* the same channel.
|
|
12
|
+
*
|
|
13
|
+
* Both setInboxBroadcaster and the subscribe Map are stored on globalThis
|
|
14
|
+
* so they survive Next.js dev-mode bundle isolation.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
const BROADCASTER_KEY = '__hazo_notify_broadcaster__';
|
|
19
|
+
const g = globalThis;
|
|
20
|
+
/** Register a broadcaster. Call once at app boot. */
|
|
21
|
+
export function setInboxBroadcaster(broadcaster) {
|
|
22
|
+
g[BROADCASTER_KEY] = broadcaster;
|
|
23
|
+
}
|
|
24
|
+
/** Returns the registered broadcaster, or null if not configured. */
|
|
25
|
+
export function getInboxBroadcaster() {
|
|
26
|
+
return g[BROADCASTER_KEY] ?? null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create an in-process broadcaster + matching subscribe function.
|
|
30
|
+
*
|
|
31
|
+
* Consumer wiring:
|
|
32
|
+
* ```ts
|
|
33
|
+
* const { broadcaster, subscribe } = createInboxBroadcaster();
|
|
34
|
+
* setInboxBroadcaster(broadcaster);
|
|
35
|
+
* export const GET = createInboxStreamRoute({ getAuth, subscribe });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function createInboxBroadcaster() {
|
|
39
|
+
const subs = new Map();
|
|
40
|
+
const broadcaster = {
|
|
41
|
+
notify(user_id, event) {
|
|
42
|
+
subs.get(user_id)?.forEach((fn) => {
|
|
43
|
+
try {
|
|
44
|
+
fn(event);
|
|
45
|
+
}
|
|
46
|
+
catch { /* swallow subscriber errors */ }
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
function subscribe(user_id, fn) {
|
|
51
|
+
if (!subs.has(user_id))
|
|
52
|
+
subs.set(user_id, new Set());
|
|
53
|
+
subs.get(user_id).add(fn);
|
|
54
|
+
return () => {
|
|
55
|
+
subs.get(user_id)?.delete(fn);
|
|
56
|
+
if (subs.get(user_id)?.size === 0)
|
|
57
|
+
subs.delete(user_id);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
return { broadcaster, subscribe };
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=broadcaster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broadcaster.js","sourceRoot":"","sources":["../../../src/lib/inbox/broadcaster.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B;;;;;;;;;;;;;;;GAeG;AAaH,MAAM,eAAe,GAAG,6BAA6B,CAAC;AACtD,MAAM,CAAC,GAAG,UAET,CAAC;AAEF,qDAAqD;AACrD,MAAM,UAAU,mBAAmB,CAAC,WAA6B;IAC/D,CAAC,CAAC,eAAe,CAAC,GAAG,WAAW,CAAC;AACnC,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,mBAAmB;IACjC,OAAO,CAAC,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC;AACpC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB;IAIpC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqD,CAAC;IAE1E,MAAM,WAAW,GAAqB;QACpC,MAAM,CAAC,OAAe,EAAE,KAA0B;YAChD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;gBAChC,IAAI,CAAC;oBAAC,EAAE,CAAC,KAAK,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,+BAA+B,CAAC,CAAC;YAC9D,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;IAEF,SAAS,SAAS,CAChB,OAAe,EACf,EAAwC;QAExC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;YAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC3B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;YAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,KAAK,CAAC;gBAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1D,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -6,4 +6,6 @@ export { startInboxWorker } from "./worker/start.js";
|
|
|
6
6
|
export type { StartInboxWorkerOptions, WorkerHandle } from "./worker/start.js";
|
|
7
7
|
export { flushChannelOnce } from "./worker/flush.js";
|
|
8
8
|
export type { FlushOptions, FlushResult } from "./worker/flush.js";
|
|
9
|
+
export { setInboxBroadcaster, createInboxBroadcaster } from "./broadcaster.js";
|
|
10
|
+
export type { InboxBroadcaster, InboxBroadcastEvent } from "./broadcaster.js";
|
|
9
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EACV,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAC3C,aAAa,EAAE,cAAc,GAC9B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,GACtD,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EACV,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAC3C,aAAa,EAAE,cAAc,GAC9B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,iBAAiB,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,GACtD,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC/E,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/lib/inbox/index.js
CHANGED
|
@@ -3,4 +3,5 @@ export { initInbox } from "./connection.js";
|
|
|
3
3
|
export { listUnreadForUser, unreadCount, markRead, markAllRead, } from "./storage.js";
|
|
4
4
|
export { startInboxWorker } from "./worker/start.js";
|
|
5
5
|
export { flushChannelOnce } from "./worker/flush.js";
|
|
6
|
+
export { setInboxBroadcaster, createInboxBroadcaster } from "./broadcaster.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/inbox/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C,OAAO,EACL,iBAAiB,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,GACtD,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/inbox/index.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAM5C,OAAO,EACL,iBAAiB,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,GACtD,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -3,9 +3,9 @@ import type { UpsertInboxRowInput, UpsertInboxRowResult, UpsertDeliveryInput, Up
|
|
|
3
3
|
* Upsert an inbox row using a claim-first strategy:
|
|
4
4
|
*
|
|
5
5
|
* 1. Try to increment an existing open batch that matches `batch_key` and
|
|
6
|
-
* `batch_closed_at`. This preserves the increment-on-conflict
|
|
7
|
-
* the original Postgres
|
|
8
|
-
* partial-index upsert.
|
|
6
|
+
* `batch_closed_at IS NULL`. This preserves the increment-on-conflict
|
|
7
|
+
* semantics of the original Postgres
|
|
8
|
+
* `ON CONFLICT (batch_key) WHERE batch_closed_at IS NULL` partial-index upsert.
|
|
9
9
|
* 2. If no open batch found, insert a fresh row.
|
|
10
10
|
*
|
|
11
11
|
* Race-condition trade-off: if two workers concurrently find no open batch and
|
|
@@ -13,12 +13,6 @@ import type { UpsertInboxRowInput, UpsertInboxRowResult, UpsertDeliveryInput, Up
|
|
|
13
13
|
* The original Postgres SQL used a partial unique index for true atomicity.
|
|
14
14
|
* For Hazodocs (single-worker), this race window is acceptable; adding retry
|
|
15
15
|
* logic would require error-code parsing not available in hazo_connect.
|
|
16
|
-
*
|
|
17
|
-
* SQLite NULL caveat: the clause-builder emits `col = ?` which SQLite's `=`
|
|
18
|
-
* operator does not use to match NULL (needs IS NULL). In production (Postgres),
|
|
19
|
-
* the behaviour is correct because Postgres's `=` also doesn't match NULL — the
|
|
20
|
-
* partial index `WHERE batch_closed_at IS NULL` handles the constraint there.
|
|
21
|
-
* In SQLite-backed tests use empty string instead of null for batch_closed_at.
|
|
22
16
|
*/
|
|
23
17
|
export declare function upsertInboxRow(i: UpsertInboxRowInput): Promise<UpsertInboxRowResult>;
|
|
24
18
|
/**
|
|
@@ -59,15 +53,9 @@ export declare function rescheduleDelivery(id: string, flush_after: string, erro
|
|
|
59
53
|
/**
|
|
60
54
|
* Task 2.10 — closeStaleBatches via adapter.claimRows
|
|
61
55
|
*
|
|
62
|
-
* Closes inbox rows whose batch_closed_at is
|
|
56
|
+
* Closes inbox rows whose batch_closed_at is NULL (open) and whose
|
|
63
57
|
* created_at is older than (now - window_ms).
|
|
64
58
|
*
|
|
65
|
-
* NULL caveat: SQLite's claimRows WHERE emits `col = ?` which does not match
|
|
66
|
-
* SQL NULL. Empty string '' is used as the sentinel for "open batch" in both
|
|
67
|
-
* SQLite tests and production (see upsertInboxRow). In production (Postgres),
|
|
68
|
-
* rows inserted via this adapter path use '' not NULL, so the '' sentinel is
|
|
69
|
-
* consistent end-to-end.
|
|
70
|
-
*
|
|
71
59
|
* Returns the number of batches closed.
|
|
72
60
|
*/
|
|
73
61
|
export declare function closeStaleBatches(window_ms: number): Promise<number>;
|
|
@@ -115,28 +103,19 @@ export declare function listUnreadForUser(user_id: string, scope_id: string, opt
|
|
|
115
103
|
*/
|
|
116
104
|
export declare function unreadCount(user_id: string, scope_id: string): Promise<number>;
|
|
117
105
|
/**
|
|
118
|
-
* Task 2.13a — markRead via claimRows
|
|
106
|
+
* Task 2.13a — markRead via claimRows
|
|
119
107
|
*
|
|
120
108
|
* Sets read_at = now() for the given inbox row, scoped by user_id to prevent
|
|
121
|
-
* cross-user reads.
|
|
122
|
-
*
|
|
123
|
-
* Idempotency trade-off: the `read_at: null` condition is omitted from the
|
|
124
|
-
* claimRows WHERE because the clause-builder emits `col = ?` which SQLite's
|
|
125
|
-
* `=` operator does not use to match NULL. Dropping the condition makes the
|
|
126
|
-
* operation idempotent — re-marking an already-read row re-sets read_at = now(),
|
|
127
|
-
* which is harmless for UI-driven calls.
|
|
109
|
+
* cross-user reads. Only updates unread rows. Returns true iff a row was
|
|
110
|
+
* actually marked read by this call.
|
|
128
111
|
*/
|
|
129
112
|
export declare function markRead(id: string, user_id: string): Promise<boolean>;
|
|
130
113
|
/**
|
|
131
|
-
* Task 2.13b — markAllRead via claimRows
|
|
132
|
-
*
|
|
133
|
-
* Sets read_at = now() for every inbox row belonging to the given user/scope.
|
|
134
|
-
*
|
|
135
|
-
* Idempotency trade-off: same as markRead — the `read_at: null` condition is
|
|
136
|
-
* omitted to avoid the SQLite NULL-matching issue. Already-read rows will have
|
|
137
|
-
* their read_at re-stamped, which is acceptable for bulk UI acknowledgment.
|
|
114
|
+
* Task 2.13b — markAllRead via claimRows
|
|
138
115
|
*
|
|
139
|
-
*
|
|
116
|
+
* Sets read_at = now() for every unread inbox row belonging to the given
|
|
117
|
+
* user/scope. Only updates unread rows. Returns the number of rows actually
|
|
118
|
+
* marked read by this call (already-read rows are not touched).
|
|
140
119
|
*/
|
|
141
120
|
export declare function markAllRead(user_id: string, scope_id: string): Promise<number>;
|
|
142
121
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/storage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/storage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,eAAe,EACf,QAAQ,EACT,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4C1F;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA6C1F;AAED,wBAAsB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAwD3G;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASpF;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASjF;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQtG;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW1E;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQxE;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlF;AAID,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;CAC/B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,QAAQ,EAAE,CAAC,CAarB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CASpF;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAU5E;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUpF"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { QueryBuilder, createCrudService } from "hazo_connect/server";
|
|
2
3
|
import { getInboxConnection } from "./connection.js";
|
|
3
4
|
/**
|
|
4
5
|
* Upsert an inbox row using a claim-first strategy:
|
|
5
6
|
*
|
|
6
7
|
* 1. Try to increment an existing open batch that matches `batch_key` and
|
|
7
|
-
* `batch_closed_at`. This preserves the increment-on-conflict
|
|
8
|
-
* the original Postgres
|
|
9
|
-
* partial-index upsert.
|
|
8
|
+
* `batch_closed_at IS NULL`. This preserves the increment-on-conflict
|
|
9
|
+
* semantics of the original Postgres
|
|
10
|
+
* `ON CONFLICT (batch_key) WHERE batch_closed_at IS NULL` partial-index upsert.
|
|
10
11
|
* 2. If no open batch found, insert a fresh row.
|
|
11
12
|
*
|
|
12
13
|
* Race-condition trade-off: if two workers concurrently find no open batch and
|
|
@@ -14,19 +15,13 @@ import { getInboxConnection } from "./connection.js";
|
|
|
14
15
|
* The original Postgres SQL used a partial unique index for true atomicity.
|
|
15
16
|
* For Hazodocs (single-worker), this race window is acceptable; adding retry
|
|
16
17
|
* logic would require error-code parsing not available in hazo_connect.
|
|
17
|
-
*
|
|
18
|
-
* SQLite NULL caveat: the clause-builder emits `col = ?` which SQLite's `=`
|
|
19
|
-
* operator does not use to match NULL (needs IS NULL). In production (Postgres),
|
|
20
|
-
* the behaviour is correct because Postgres's `=` also doesn't match NULL — the
|
|
21
|
-
* partial index `WHERE batch_closed_at IS NULL` handles the constraint there.
|
|
22
|
-
* In SQLite-backed tests use empty string instead of null for batch_closed_at.
|
|
23
18
|
*/
|
|
24
19
|
export async function upsertInboxRow(i) {
|
|
25
20
|
const adapter = getInboxConnection();
|
|
26
21
|
// Try to increment an existing open batch first.
|
|
27
22
|
const claimed = await adapter.claimRows({
|
|
28
23
|
table: "hazo_notify_inbox",
|
|
29
|
-
where: { batch_key: i.batch_key, batch_closed_at:
|
|
24
|
+
where: { batch_key: i.batch_key, batch_closed_at: null },
|
|
30
25
|
set: {
|
|
31
26
|
aggregate_count: { increment: 1 },
|
|
32
27
|
in_app_text: i.in_app_text,
|
|
@@ -40,9 +35,11 @@ export async function upsertInboxRow(i) {
|
|
|
40
35
|
return { id: claimed[0].id, inserted: false };
|
|
41
36
|
}
|
|
42
37
|
// No open batch — insert a new row.
|
|
38
|
+
const new_inbox_id = randomUUID();
|
|
43
39
|
const rows = await adapter.query(new QueryBuilder()
|
|
44
40
|
.from("hazo_notify_inbox")
|
|
45
41
|
.returning("id"), "POST", {
|
|
42
|
+
id: new_inbox_id,
|
|
46
43
|
scope_id: i.scope_id,
|
|
47
44
|
user_id: i.user_id,
|
|
48
45
|
event_type: i.event_type,
|
|
@@ -54,7 +51,7 @@ export async function upsertInboxRow(i) {
|
|
|
54
51
|
surfaces: JSON.stringify(i.surfaces),
|
|
55
52
|
batch_closed_at: i.batch_closed_at,
|
|
56
53
|
});
|
|
57
|
-
return { id: rows[0]
|
|
54
|
+
return { id: rows[0]?.id ?? new_inbox_id, inserted: true };
|
|
58
55
|
}
|
|
59
56
|
/**
|
|
60
57
|
* Upsert a channel delivery row using a two-claim strategy that preserves the
|
|
@@ -94,15 +91,17 @@ export async function upsertDelivery(i) {
|
|
|
94
91
|
return { id: claimedInFlight[0].id, inserted: false, attempt_in_flight: true };
|
|
95
92
|
}
|
|
96
93
|
// Step 3: no existing row — insert a new delivery.
|
|
94
|
+
const new_delivery_id = randomUUID();
|
|
97
95
|
const rows = await adapter.query(new QueryBuilder()
|
|
98
96
|
.from("hazo_notify_channel_deliveries")
|
|
99
97
|
.returning("id"), "POST", {
|
|
98
|
+
id: new_delivery_id,
|
|
100
99
|
inbox_id: i.inbox_id,
|
|
101
100
|
channel_id: i.channel_id,
|
|
102
101
|
payload: JSON.stringify(i.payload),
|
|
103
102
|
flush_after: i.flush_after,
|
|
104
103
|
});
|
|
105
|
-
return { id: rows[0]
|
|
104
|
+
return { id: rows[0]?.id ?? new_delivery_id, inserted: true, attempt_in_flight: false };
|
|
106
105
|
}
|
|
107
106
|
export async function claimDueDeliveries(channel_id, batch_size) {
|
|
108
107
|
const adapter = getInboxConnection();
|
|
@@ -198,15 +197,9 @@ export async function rescheduleDelivery(id, flush_after, error) {
|
|
|
198
197
|
/**
|
|
199
198
|
* Task 2.10 — closeStaleBatches via adapter.claimRows
|
|
200
199
|
*
|
|
201
|
-
* Closes inbox rows whose batch_closed_at is
|
|
200
|
+
* Closes inbox rows whose batch_closed_at is NULL (open) and whose
|
|
202
201
|
* created_at is older than (now - window_ms).
|
|
203
202
|
*
|
|
204
|
-
* NULL caveat: SQLite's claimRows WHERE emits `col = ?` which does not match
|
|
205
|
-
* SQL NULL. Empty string '' is used as the sentinel for "open batch" in both
|
|
206
|
-
* SQLite tests and production (see upsertInboxRow). In production (Postgres),
|
|
207
|
-
* rows inserted via this adapter path use '' not NULL, so the '' sentinel is
|
|
208
|
-
* consistent end-to-end.
|
|
209
|
-
*
|
|
210
203
|
* Returns the number of batches closed.
|
|
211
204
|
*/
|
|
212
205
|
export async function closeStaleBatches(window_ms) {
|
|
@@ -214,7 +207,7 @@ export async function closeStaleBatches(window_ms) {
|
|
|
214
207
|
const cutoff = new Date(Date.now() - window_ms).toISOString();
|
|
215
208
|
const rows = await adapter.claimRows({
|
|
216
209
|
table: "hazo_notify_inbox",
|
|
217
|
-
where: { batch_closed_at:
|
|
210
|
+
where: { batch_closed_at: null, created_at: { lte: cutoff } },
|
|
218
211
|
set: { batch_closed_at: { $now: true } },
|
|
219
212
|
returning: ["id"],
|
|
220
213
|
limit: 10000,
|
|
@@ -298,22 +291,17 @@ export async function unreadCount(user_id, scope_id) {
|
|
|
298
291
|
return rows.length;
|
|
299
292
|
}
|
|
300
293
|
/**
|
|
301
|
-
* Task 2.13a — markRead via claimRows
|
|
294
|
+
* Task 2.13a — markRead via claimRows
|
|
302
295
|
*
|
|
303
296
|
* Sets read_at = now() for the given inbox row, scoped by user_id to prevent
|
|
304
|
-
* cross-user reads.
|
|
305
|
-
*
|
|
306
|
-
* Idempotency trade-off: the `read_at: null` condition is omitted from the
|
|
307
|
-
* claimRows WHERE because the clause-builder emits `col = ?` which SQLite's
|
|
308
|
-
* `=` operator does not use to match NULL. Dropping the condition makes the
|
|
309
|
-
* operation idempotent — re-marking an already-read row re-sets read_at = now(),
|
|
310
|
-
* which is harmless for UI-driven calls.
|
|
297
|
+
* cross-user reads. Only updates unread rows. Returns true iff a row was
|
|
298
|
+
* actually marked read by this call.
|
|
311
299
|
*/
|
|
312
300
|
export async function markRead(id, user_id) {
|
|
313
301
|
const adapter = getInboxConnection();
|
|
314
302
|
const rows = await adapter.claimRows({
|
|
315
303
|
table: "hazo_notify_inbox",
|
|
316
|
-
where: { id, user_id },
|
|
304
|
+
where: { id, user_id, read_at: null },
|
|
317
305
|
set: { read_at: { $now: true } },
|
|
318
306
|
returning: ["id"],
|
|
319
307
|
limit: 1,
|
|
@@ -321,21 +309,17 @@ export async function markRead(id, user_id) {
|
|
|
321
309
|
return rows.length > 0;
|
|
322
310
|
}
|
|
323
311
|
/**
|
|
324
|
-
* Task 2.13b — markAllRead via claimRows
|
|
325
|
-
*
|
|
326
|
-
* Sets read_at = now() for every inbox row belonging to the given user/scope.
|
|
327
|
-
*
|
|
328
|
-
* Idempotency trade-off: same as markRead — the `read_at: null` condition is
|
|
329
|
-
* omitted to avoid the SQLite NULL-matching issue. Already-read rows will have
|
|
330
|
-
* their read_at re-stamped, which is acceptable for bulk UI acknowledgment.
|
|
312
|
+
* Task 2.13b — markAllRead via claimRows
|
|
331
313
|
*
|
|
332
|
-
*
|
|
314
|
+
* Sets read_at = now() for every unread inbox row belonging to the given
|
|
315
|
+
* user/scope. Only updates unread rows. Returns the number of rows actually
|
|
316
|
+
* marked read by this call (already-read rows are not touched).
|
|
333
317
|
*/
|
|
334
318
|
export async function markAllRead(user_id, scope_id) {
|
|
335
319
|
const adapter = getInboxConnection();
|
|
336
320
|
const rows = await adapter.claimRows({
|
|
337
321
|
table: "hazo_notify_inbox",
|
|
338
|
-
where: { user_id, scope_id },
|
|
322
|
+
where: { user_id, scope_id, read_at: null },
|
|
339
323
|
set: { read_at: { $now: true } },
|
|
340
324
|
returning: ["id"],
|
|
341
325
|
limit: 10000,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/lib/inbox/storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAUrD
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/lib/inbox/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -45,6 +45,11 @@ export interface DispatchInput {
|
|
|
45
45
|
channel_payloads?: Record<string, Record<string, unknown>>;
|
|
46
46
|
payload?: Record<string, unknown>;
|
|
47
47
|
batch_window_ms?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Default preference mode applied when no preference row exists for a
|
|
50
|
+
* (user × channel) pair. Defaults to 'on' (backward-compatible).
|
|
51
|
+
*/
|
|
52
|
+
preference_default?: 'on' | 'off';
|
|
48
53
|
}
|
|
49
54
|
export interface DispatchResult {
|
|
50
55
|
inbox_rows_upserted: number;
|
|
@@ -53,6 +58,8 @@ export interface DispatchResult {
|
|
|
53
58
|
deliveries_created: number;
|
|
54
59
|
deliveries_refreshed: number;
|
|
55
60
|
channels_dispatched: string[];
|
|
61
|
+
/** Delivery rows skipped because the user's preference mode was 'off'. */
|
|
62
|
+
deliveries_skipped_by_preference: number;
|
|
56
63
|
}
|
|
57
64
|
export interface UpsertInboxRowInput {
|
|
58
65
|
scope_id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/inbox/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../../src/lib/jobs/submit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA0B;IACzC,yDAAyD;IACzD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"submit.d.ts","sourceRoot":"","sources":["../../../src/lib/jobs/submit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA0B;IACzC,yDAAyD;IACzD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,0BAA0B,GACjC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAe/B"}
|
package/dist/lib/jobs/submit.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit.js","sourceRoot":"","sources":["../../../src/lib/jobs/submit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAalD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAuB,EACvB,MAAkC;IAElC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACzC,MAAM,OAAO,GACX,MAAM,CAAC,UAAU,IAAI,IAAI;YACvB,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;YAC/C,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;QACrB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;YAClC,IAAI,EAAE,oBAAoB;YAC1B,OAAO;SACR,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
|
1
|
+
{"version":3,"file":"submit.js","sourceRoot":"","sources":["../../../src/lib/jobs/submit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAalD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAuB,EACvB,MAAkC;IAElC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,UAAU,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACzC,MAAM,OAAO,GACX,MAAM,CAAC,UAAU,IAAI,IAAI;YACvB,CAAC,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE;YAC/C,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;QACrB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;YAClC,IAAI,EAAE,oBAAoB;YAC1B,WAAW,EAAE,eAAe,UAAU,EAAE;YACxC,OAAO;SACR,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,CAAC;AACpB,CAAC"}
|
package/dist/lib/jobs/types.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/jobs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iDAAiD;AACjD,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAE9D,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,0DAA0D;AAC1D,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACtC;AAED,yDAAyD;AACzD,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CACrD,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EACf,GAAG,CAAC,EAAE,aAAa,KAChB,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhB,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,IAAI,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/jobs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iDAAiD;AACjD,eAAO,MAAM,oBAAoB,4BAA4B,CAAC;AAE9D,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,0DAA0D;AAC1D,MAAM,WAAW,OAAO,CAAC,CAAC,GAAG,OAAO;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACpC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACtC;AAED,yDAAyD;AACzD,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,CACrD,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,EACf,GAAG,CAAC,EAAE,aAAa,KAChB,OAAO,CAAC,CAAC,CAAC,CAAC;AAEhB,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,IAAI,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default system template manifests for the lifecycle module.
|
|
3
|
+
*
|
|
4
|
+
* Consumers call `sync_system_templates(hazo_connect, lifecycleDefaultTemplates)`
|
|
5
|
+
* at boot to upsert these templates into the database.
|
|
6
|
+
*/
|
|
7
|
+
import type { SystemTemplateManifest } from '../template_manager/types.js';
|
|
8
|
+
export declare const lifecycleDefaultTemplates: SystemTemplateManifest[];
|
|
9
|
+
//# sourceMappingURL=default_templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default_templates.d.ts","sourceRoot":"","sources":["../../../src/lib/lifecycle/default_templates.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAA8B,MAAM,8BAA8B,CAAC;AA8DvG,eAAO,MAAM,yBAAyB,EAAE,sBAAsB,EAyG7D,CAAC"}
|