@growth-labs/push 0.2.0 → 0.4.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.
Files changed (41) hide show
  1. package/README.md +6 -2
  2. package/dist/db/schema.d.ts +24 -10
  3. package/dist/db/schema.d.ts.map +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +8 -3
  6. package/dist/index.js.map +1 -1
  7. package/dist/types.d.ts +28 -0
  8. package/dist/types.d.ts.map +1 -1
  9. package/dist/utils/index.d.ts +1 -1
  10. package/dist/utils/index.d.ts.map +1 -1
  11. package/dist/utils/index.js +1 -1
  12. package/dist/utils/index.js.map +1 -1
  13. package/dist/utils/queue.d.ts +18 -2
  14. package/dist/utils/queue.d.ts.map +1 -1
  15. package/dist/utils/queue.js +43 -9
  16. package/dist/utils/queue.js.map +1 -1
  17. package/dist/utils/scheduled.d.ts +1 -0
  18. package/dist/utils/scheduled.d.ts.map +1 -1
  19. package/dist/utils/scheduled.js +1 -1
  20. package/dist/utils/scheduled.js.map +1 -1
  21. package/package.json +13 -7
  22. package/src/db/schema.ts +14 -0
  23. package/src/index.ts +69 -0
  24. package/src/middleware/push.ts +10 -0
  25. package/src/options.ts +45 -0
  26. package/src/routes/subscribe.ts +82 -0
  27. package/src/routes/unsubscribe.ts +29 -0
  28. package/src/types.ts +129 -0
  29. package/src/utils/analytics.ts +96 -0
  30. package/src/utils/cleanup.ts +28 -0
  31. package/src/utils/composer.ts +141 -0
  32. package/src/utils/index.ts +38 -0
  33. package/src/utils/queue.ts +173 -0
  34. package/src/utils/scheduled.ts +152 -0
  35. package/src/utils/send.ts +140 -0
  36. package/src/utils/subscriptions.ts +124 -0
  37. package/src/utils/turnstile.ts +25 -0
  38. package/src/utils/vapid.ts +28 -0
  39. package/src/client/push-sw.d.ts.map +0 -1
  40. package/src/client/push-sw.js +0 -25
  41. package/src/client/push-sw.js.map +0 -1
package/README.md CHANGED
@@ -46,7 +46,11 @@ import { sendPushNotification, enqueuePushBatchAll } from '@growth-labs/push/uti
46
46
  await sendPushNotification(subscription, { title: 'Breaking', body: '...' }, sendContext)
47
47
 
48
48
  // Batch send to all subscribers (via Queue)
49
- await enqueuePushBatchAll(env.SITE_DB, payload, { queue: env.PUSH_QUEUE, batchSize: 100 })
49
+ await enqueuePushBatchAll(env.SITE_DB, payload, {
50
+ queue: env.PUSH_QUEUE,
51
+ siteId: 'fronts', // required since 0.4.0
52
+ batchSize: 100,
53
+ })
50
54
  ```
51
55
 
52
56
  ## Queue Consumer
@@ -54,7 +58,7 @@ await enqueuePushBatchAll(env.SITE_DB, payload, { queue: env.PUSH_QUEUE, batchSi
54
58
  Package provides handler, consumer wires it up:
55
59
 
56
60
  ```typescript
57
- import { handlePushQueue } from '@growth-labs/push/utils'
61
+ import { handlePushQueue } from '@growth-labs/push/consumer'
58
62
 
59
63
  export default {
60
64
  async queue(batch, env) {
@@ -18,7 +18,9 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
18
18
  baseColumn: never;
19
19
  identity: undefined;
20
20
  generated: undefined;
21
- }, object>;
21
+ }, {}, {
22
+ length: number | undefined;
23
+ }>;
22
24
  endpoint: import("drizzle-orm/sqlite-core").SQLiteColumn<{
23
25
  name: "endpoint";
24
26
  tableName: "gl_push_subscriptions";
@@ -35,7 +37,9 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
35
37
  baseColumn: never;
36
38
  identity: undefined;
37
39
  generated: undefined;
38
- }, object>;
40
+ }, {}, {
41
+ length: number | undefined;
42
+ }>;
39
43
  keyP256dh: import("drizzle-orm/sqlite-core").SQLiteColumn<{
40
44
  name: "key_p256dh";
41
45
  tableName: "gl_push_subscriptions";
@@ -52,7 +56,9 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
52
56
  baseColumn: never;
53
57
  identity: undefined;
54
58
  generated: undefined;
55
- }, object>;
59
+ }, {}, {
60
+ length: number | undefined;
61
+ }>;
56
62
  keyAuth: import("drizzle-orm/sqlite-core").SQLiteColumn<{
57
63
  name: "key_auth";
58
64
  tableName: "gl_push_subscriptions";
@@ -69,7 +75,9 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
69
75
  baseColumn: never;
70
76
  identity: undefined;
71
77
  generated: undefined;
72
- }, object>;
78
+ }, {}, {
79
+ length: number | undefined;
80
+ }>;
73
81
  topics: import("drizzle-orm/sqlite-core").SQLiteColumn<{
74
82
  name: "topics";
75
83
  tableName: "gl_push_subscriptions";
@@ -86,7 +94,9 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
86
94
  baseColumn: never;
87
95
  identity: undefined;
88
96
  generated: undefined;
89
- }, object>;
97
+ }, {}, {
98
+ length: number | undefined;
99
+ }>;
90
100
  createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
91
101
  name: "created_at";
92
102
  tableName: "gl_push_subscriptions";
@@ -103,7 +113,7 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
103
113
  baseColumn: never;
104
114
  identity: undefined;
105
115
  generated: undefined;
106
- }, object>;
116
+ }, {}, {}>;
107
117
  lastDeliveryAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
108
118
  name: "last_delivery_at";
109
119
  tableName: "gl_push_subscriptions";
@@ -120,7 +130,7 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
120
130
  baseColumn: never;
121
131
  identity: undefined;
122
132
  generated: undefined;
123
- }, object>;
133
+ }, {}, {}>;
124
134
  failureCount: import("drizzle-orm/sqlite-core").SQLiteColumn<{
125
135
  name: "failure_count";
126
136
  tableName: "gl_push_subscriptions";
@@ -137,7 +147,7 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
137
147
  baseColumn: never;
138
148
  identity: undefined;
139
149
  generated: undefined;
140
- }, object>;
150
+ }, {}, {}>;
141
151
  userAgent: import("drizzle-orm/sqlite-core").SQLiteColumn<{
142
152
  name: "user_agent";
143
153
  tableName: "gl_push_subscriptions";
@@ -154,7 +164,9 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
154
164
  baseColumn: never;
155
165
  identity: undefined;
156
166
  generated: undefined;
157
- }, object>;
167
+ }, {}, {
168
+ length: number | undefined;
169
+ }>;
158
170
  country: import("drizzle-orm/sqlite-core").SQLiteColumn<{
159
171
  name: "country";
160
172
  tableName: "gl_push_subscriptions";
@@ -171,7 +183,9 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
171
183
  baseColumn: never;
172
184
  identity: undefined;
173
185
  generated: undefined;
174
- }, object>;
186
+ }, {}, {
187
+ length: number | undefined;
188
+ }>;
175
189
  };
176
190
  dialect: "sqlite";
177
191
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW5B,CAAA"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW5B,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,cAAc,CAAA;AAElE,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,gBAAgB,CA0DnE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,EAAE,KAAK,WAAW,EAAqB,MAAM,cAAc,CAAA;AAQlE,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,gBAAgB,CA0DnE"}
package/dist/index.js CHANGED
@@ -1,4 +1,9 @@
1
+ import { fileURLToPath } from 'node:url';
1
2
  import { pushOptionsSchema } from './options.js';
3
+ const ENTRYPOINT_EXTENSION = import.meta.url.endsWith('.ts') ? '.ts' : '.js';
4
+ function resolveEntrypoint(path) {
5
+ return fileURLToPath(new URL(`${path}${ENTRYPOINT_EXTENSION}`, import.meta.url));
6
+ }
2
7
  export default function push(options) {
3
8
  const resolved = pushOptionsSchema.parse(options);
4
9
  const virtualConfig = {
@@ -36,17 +41,17 @@ export default function push(options) {
36
41
  },
37
42
  });
38
43
  addMiddleware({
39
- entrypoint: '@growth-labs/push/middleware',
44
+ entrypoint: resolveEntrypoint('./middleware/push'),
40
45
  order: 'pre',
41
46
  });
42
47
  injectRoute({
43
48
  pattern: resolved.routes.subscribe,
44
- entrypoint: '@growth-labs/push/routes/subscribe',
49
+ entrypoint: resolveEntrypoint('./routes/subscribe'),
45
50
  prerender: false,
46
51
  });
47
52
  injectRoute({
48
53
  pattern: resolved.routes.unsubscribe,
49
- entrypoint: '@growth-labs/push/routes/unsubscribe',
54
+ entrypoint: resolveEntrypoint('./routes/unsubscribe'),
50
55
  prerender: false,
51
56
  });
52
57
  },
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAElE,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,OAAoB;IAChD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAEjD,MAAM,aAAa,GAAG;QACrB,cAAc,EAAE,QAAQ,CAAC,cAAc;QACvC,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;KACzB,CAAA;IAED,MAAM,eAAe,GAAG,iCAAiC,CAAA;IACzD,MAAM,uBAAuB,GAAG,KAAK,eAAe,EAAE,CAAA;IAEtD,OAAO;QACN,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE;YACN,oBAAoB,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,EAAE;gBACtE,YAAY,CAAC;oBACZ,IAAI,EAAE;wBACL,OAAO,EAAE;4BACR;gCACC,IAAI,EAAE,yBAAyB;gCAC/B,SAAS,CAAC,EAAE;oCACX,IAAI,EAAE,KAAK,eAAe;wCAAE,OAAO,uBAAuB,CAAA;gCAC3D,CAAC;gCACD,IAAI,CAAC,EAAE;oCACN,IAAI,EAAE,KAAK,uBAAuB,EAAE,CAAC;wCACpC,OAAO,kBAAkB,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAA;oCACzD,CAAC;gCACF,CAAC;6BACD;yBACD;qBACD;iBACD,CAAC,CAAA;gBAEF,aAAa,CAAC;oBACb,UAAU,EAAE,8BAA8B;oBAC1C,KAAK,EAAE,KAAK;iBACZ,CAAC,CAAA;gBAEF,WAAW,CAAC;oBACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;oBAClC,UAAU,EAAE,oCAAoC;oBAChD,SAAS,EAAE,KAAK;iBAChB,CAAC,CAAA;gBAEF,WAAW,CAAC;oBACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW;oBACpC,UAAU,EAAE,sCAAsC;oBAClD,SAAS,EAAE,KAAK;iBAChB,CAAC,CAAA;YACH,CAAC;SACD;KACD,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAoB,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAElE,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;AAE5E,SAAS,iBAAiB,CAAC,IAAY;IACtC,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,oBAAoB,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACjF,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,OAAoB;IAChD,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAEjD,MAAM,aAAa,GAAG;QACrB,cAAc,EAAE,QAAQ,CAAC,cAAc;QACvC,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,YAAY,EAAE,QAAQ,CAAC,YAAY;QACnC,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,OAAO,EAAE,QAAQ,CAAC,OAAO;KACzB,CAAA;IAED,MAAM,eAAe,GAAG,iCAAiC,CAAA;IACzD,MAAM,uBAAuB,GAAG,KAAK,eAAe,EAAE,CAAA;IAEtD,OAAO;QACN,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE;YACN,oBAAoB,EAAE,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,EAAE,EAAE;gBACtE,YAAY,CAAC;oBACZ,IAAI,EAAE;wBACL,OAAO,EAAE;4BACR;gCACC,IAAI,EAAE,yBAAyB;gCAC/B,SAAS,CAAC,EAAE;oCACX,IAAI,EAAE,KAAK,eAAe;wCAAE,OAAO,uBAAuB,CAAA;gCAC3D,CAAC;gCACD,IAAI,CAAC,EAAE;oCACN,IAAI,EAAE,KAAK,uBAAuB,EAAE,CAAC;wCACpC,OAAO,kBAAkB,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAA;oCACzD,CAAC;gCACF,CAAC;6BACD;yBACD;qBACD;iBACD,CAAC,CAAA;gBAEF,aAAa,CAAC;oBACb,UAAU,EAAE,iBAAiB,CAAC,mBAAmB,CAAC;oBAClD,KAAK,EAAE,KAAK;iBACZ,CAAC,CAAA;gBAEF,WAAW,CAAC;oBACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS;oBAClC,UAAU,EAAE,iBAAiB,CAAC,oBAAoB,CAAC;oBACnD,SAAS,EAAE,KAAK;iBAChB,CAAC,CAAA;gBAEF,WAAW,CAAC;oBACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW;oBACpC,UAAU,EAAE,iBAAiB,CAAC,sBAAsB,CAAC;oBACrD,SAAS,EAAE,KAAK;iBAChB,CAAC,CAAA;YACH,CAAC;SACD;KACD,CAAA;AACF,CAAC"}
package/dist/types.d.ts CHANGED
@@ -35,12 +35,40 @@ export interface PushSubscriptionRecord {
35
35
  * VAPID credentials are NOT included. The Queue consumer Worker reads them
36
36
  * from its own env bindings (Cloudflare Secrets). This keeps the private key
37
37
  * in exactly one place and avoids serializing it into every Queue message.
38
+ *
39
+ * `siteId` identifies which site enqueued the message. The realm consumer
40
+ * uses it with `siteConfigLookup` to apply per-site overrides (icon URL,
41
+ * VAPID identity, etc.). Sites in single-tenant mode can pass any string.
38
42
  */
39
43
  export interface PushQueueMessage {
44
+ siteId: string;
40
45
  subscriptions: PushSubscriptionRecord[];
41
46
  payload: PushPayload;
42
47
  options: PushSendOptions;
43
48
  }
49
+ /**
50
+ * Per-site config override applied at consumer time. Returned from
51
+ * SitePushConfigLookup. All fields are optional — only the ones present
52
+ * will override the consumer context for that message.
53
+ */
54
+ export interface SitePushConfig {
55
+ defaults?: {
56
+ icon?: string;
57
+ ttl?: number;
58
+ urgency?: 'very-low' | 'low' | 'normal' | 'high';
59
+ };
60
+ vapid?: {
61
+ subject?: string;
62
+ publicKey?: string;
63
+ privateKey?: string;
64
+ };
65
+ }
66
+ /**
67
+ * Per-message lookup. The realm consumer calls it with the message's
68
+ * `siteId`. Returns the per-site config to apply, or `null` to skip the
69
+ * override and use the consumer's context as-is.
70
+ */
71
+ export type SitePushConfigLookup = (siteId: string, env: Record<string, unknown>) => Promise<SitePushConfig | null>;
44
72
  /** Result of a single push send attempt */
45
73
  export interface PushSendResult {
46
74
  subscriptionId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE;QACR,KAAK,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;KACX,CAAA;IACD,GAAG,CAAC,EAAE,MAAM,CAAA;CACZ;AAED,wCAAwC;AACxC,MAAM,WAAW,eAAe;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;CAChD;AAED,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACtC,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAChC,aAAa,EAAE,sBAAsB,EAAE,CAAA;IACvC,OAAO,EAAE,WAAW,CAAA;IACpB,OAAO,EAAE,eAAe,CAAA;CACxB;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC9B,cAAc,EAAE,MAAM,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,wBAAwB;AACxB,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,cAAc,EAAE,CAAA;CACzB;AAED,iDAAiD;AACjD,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE;QACL,cAAc,EAAE,MAAM,CAAA;KACtB,CAAA;CACD;AAED,yDAAyD;AACzD,MAAM,WAAW,UAAU;IAC1B,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;QACX,OAAO,EAAE,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;KAC/C,CAAA;IACD,KAAK,EAAE;QACN,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,SAAS,EAAE;QACV,SAAS,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,MAAM,EAAE;QACP,SAAS,EAAE,MAAM,CAAA;QACjB,WAAW,EAAE,MAAM,CAAA;KACnB,CAAA;IACD,OAAO,EAAE;QACR,cAAc,EAAE,MAAM,CAAA;KACtB,CAAA;CACD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  export { emitPushAnalyticsEvent, trackPushCleanup, trackPushEvent, trackPushSend, trackPushSubscription, } from './analytics.js';
2
2
  export { cleanupStaleSubscriptions } from './cleanup.js';
3
3
  export { composePushPayload, type PushTemplate, type TemplateVariables, templates, } from './composer.js';
4
- export { enqueuePushBatch, enqueuePushBatchAll, handlePushQueue, } from './queue.js';
4
+ export { enqueuePushBatch, enqueuePushBatchAll } from './queue.js';
5
5
  export { handleScheduledPush, type ScheduledContentProvider, type ScheduledPushContext, type ScheduledPushResult, } from './scheduled.js';
6
6
  export { type SendContext, sendPushBatch, sendPushNotification, } from './send.js';
7
7
  export { countSubscriptions, deleteSubscriptionByEndpoint, deleteSubscriptionById, findSubscriptionByEndpoint, getAllSubscriptions, incrementFailureCount, markDelivered, saveSubscription, } from './subscriptions.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,qBAAqB,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EACN,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,SAAS,GACT,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,GACf,MAAM,YAAY,CAAA;AACnB,OAAO,EACN,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACN,KAAK,WAAW,EAChB,aAAa,EACb,oBAAoB,GACpB,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,gBAAgB,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,qBAAqB,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EACN,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,SAAS,GACT,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EACN,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACN,KAAK,WAAW,EAChB,aAAa,EACb,oBAAoB,GACpB,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,gBAAgB,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA"}
@@ -1,7 +1,7 @@
1
1
  export { emitPushAnalyticsEvent, trackPushCleanup, trackPushEvent, trackPushSend, trackPushSubscription, } from './analytics.js';
2
2
  export { cleanupStaleSubscriptions } from './cleanup.js';
3
3
  export { composePushPayload, templates, } from './composer.js';
4
- export { enqueuePushBatch, enqueuePushBatchAll, handlePushQueue, } from './queue.js';
4
+ export { enqueuePushBatch, enqueuePushBatchAll } from './queue.js';
5
5
  export { handleScheduledPush, } from './scheduled.js';
6
6
  export { sendPushBatch, sendPushNotification, } from './send.js';
7
7
  export { countSubscriptions, deleteSubscriptionByEndpoint, deleteSubscriptionById, findSubscriptionByEndpoint, getAllSubscriptions, incrementFailureCount, markDelivered, saveSubscription, } from './subscriptions.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,qBAAqB,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EACN,kBAAkB,EAGlB,SAAS,GACT,MAAM,eAAe,CAAA;AACtB,OAAO,EACN,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,GACf,MAAM,YAAY,CAAA;AACnB,OAAO,EACN,mBAAmB,GAInB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAEN,aAAa,EACb,oBAAoB,GACpB,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,gBAAgB,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,sBAAsB,EACtB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,qBAAqB,GACrB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EACN,kBAAkB,EAGlB,SAAS,GACT,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EACN,mBAAmB,GAInB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAEN,aAAa,EACb,oBAAoB,GACpB,MAAM,WAAW,CAAA;AAClB,OAAO,EACN,kBAAkB,EAClB,4BAA4B,EAC5B,sBAAsB,EACtB,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,aAAa,EACb,gBAAgB,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA"}
@@ -1,10 +1,13 @@
1
- import type { PushPayload, PushQueueMessage, PushSendOptions, PushSubscriptionRecord } from '../types.js';
1
+ import type { PushPayload, PushQueueMessage, PushSendOptions, PushSubscriptionRecord, SitePushConfigLookup } from '../types.js';
2
2
  interface EnqueueContext {
3
3
  queue: Queue;
4
+ siteId: string;
4
5
  batchSize?: number;
5
6
  }
6
7
  /**
7
8
  * Split a known set of subscriptions into batches and enqueue each batch.
9
+ * Each emitted message carries the caller's `siteId` so the realm consumer
10
+ * can apply per-site overrides via `siteConfigLookup`.
8
11
  */
9
12
  export declare function enqueuePushBatch(subscriptions: PushSubscriptionRecord[], payload: PushPayload, context: EnqueueContext, options?: PushSendOptions): Promise<{
10
13
  batches: number;
@@ -30,10 +33,23 @@ interface QueueConsumerContext {
30
33
  ttl: number;
31
34
  urgency: 'very-low' | 'low' | 'normal' | 'high';
32
35
  };
36
+ /**
37
+ * Optional realm-level multi-tenant lookup. When provided, the consumer
38
+ * calls it per message using `message.body.siteId` and merges the result
39
+ * over the base context for that batch.
40
+ */
41
+ siteConfigLookup?: SitePushConfigLookup;
42
+ /**
43
+ * Worker env, forwarded to `siteConfigLookup` so the lookup can read
44
+ * KV / D1 / etc. Required when `siteConfigLookup` is set.
45
+ */
46
+ env?: Record<string, unknown>;
33
47
  }
34
48
  /**
35
49
  * Queue consumer handler. Process a batch of push notification sends.
36
- * VAPID credentials come from env — they are NOT in the Queue message.
50
+ * VAPID credentials come from context — they are NOT in the Queue message.
51
+ * When `context.siteConfigLookup` is configured, per-message overrides are
52
+ * applied for VAPID identity and notification defaults.
37
53
  */
38
54
  export declare function handlePushQueue(batch: MessageBatch<PushQueueMessage>, context: QueueConsumerContext): Promise<void>;
39
55
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/utils/queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EACtB,MAAM,aAAa,CAAA;AASpB,UAAU,cAAc;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACrC,aAAa,EAAE,sBAAsB,EAAE,EACvC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAe1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAmB1D;AAED,UAAU,oBAAoB;IAC7B,EAAE,EAAE,UAAU,CAAA;IACd,KAAK,EAAE;QACN,OAAO,EAAE,MAAM,CAAA;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,QAAQ,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;QACX,OAAO,EAAE,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;KAC/C,CAAA;CACD;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACpC,KAAK,EAAE,YAAY,CAAC,gBAAgB,CAAC,EACrC,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAyBf"}
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/utils/queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,sBAAsB,EAEtB,oBAAoB,EACpB,MAAM,aAAa,CAAA;AASpB,UAAU,cAAc;IACvB,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACrC,aAAa,EAAE,sBAAsB,EAAE,EACvC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAoB1D;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,eAAoB,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB1D;AAED,UAAU,oBAAoB;IAC7B,EAAE,EAAE,UAAU,CAAA;IACd,KAAK,EAAE;QACN,OAAO,EAAE,MAAM,CAAA;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;KAClB,CAAA;IACD,QAAQ,EAAE;QACT,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,GAAG,EAAE,MAAM,CAAA;QACX,OAAO,EAAE,UAAU,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAA;KAC/C,CAAA;IACD;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,CAAA;IACvC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC7B;AAqBD;;;;;GAKG;AACH,wBAAsB,eAAe,CACpC,KAAK,EAAE,YAAY,CAAC,gBAAgB,CAAC,EACrC,OAAO,EAAE,oBAAoB,GAC3B,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
@@ -2,13 +2,20 @@ import { sendPushBatch } from './send.js';
2
2
  import { deleteSubscriptionById, getAllSubscriptions, incrementFailureCount, markDelivered, } from './subscriptions.js';
3
3
  /**
4
4
  * Split a known set of subscriptions into batches and enqueue each batch.
5
+ * Each emitted message carries the caller's `siteId` so the realm consumer
6
+ * can apply per-site overrides via `siteConfigLookup`.
5
7
  */
6
8
  export async function enqueuePushBatch(subscriptions, payload, context, options = {}) {
7
9
  const batchSize = context.batchSize ?? 100;
8
10
  let batches = 0;
9
11
  for (let i = 0; i < subscriptions.length; i += batchSize) {
10
12
  const batch = subscriptions.slice(i, i + batchSize);
11
- const message = { subscriptions: batch, payload, options };
13
+ const message = {
14
+ siteId: context.siteId,
15
+ subscriptions: batch,
16
+ payload,
17
+ options,
18
+ };
12
19
  await context.queue.send(message);
13
20
  batches++;
14
21
  }
@@ -30,7 +37,12 @@ export async function enqueuePushBatchAll(db, payload, context, options = {}) {
30
37
  const subs = await getAllSubscriptions(db, { limit: batchSize, offset });
31
38
  if (subs.length === 0)
32
39
  break;
33
- const message = { subscriptions: subs, payload, options };
40
+ const message = {
41
+ siteId: context.siteId,
42
+ subscriptions: subs,
43
+ payload,
44
+ options,
45
+ };
34
46
  await context.queue.send(message);
35
47
  batches++;
36
48
  total += subs.length;
@@ -38,18 +50,40 @@ export async function enqueuePushBatchAll(db, payload, context, options = {}) {
38
50
  }
39
51
  return { batches, totalSubscriptions: total };
40
52
  }
53
+ function applyOverride(context, override) {
54
+ if (!override)
55
+ return { vapid: context.vapid, defaults: context.defaults };
56
+ return {
57
+ vapid: {
58
+ subject: override.vapid?.subject ?? context.vapid.subject,
59
+ publicKey: override.vapid?.publicKey ?? context.vapid.publicKey,
60
+ privateKey: override.vapid?.privateKey ?? context.vapid.privateKey,
61
+ },
62
+ defaults: {
63
+ icon: override.defaults?.icon ?? context.defaults.icon,
64
+ ttl: override.defaults?.ttl ?? context.defaults.ttl,
65
+ urgency: override.defaults?.urgency ?? context.defaults.urgency,
66
+ },
67
+ };
68
+ }
41
69
  /**
42
70
  * Queue consumer handler. Process a batch of push notification sends.
43
- * VAPID credentials come from env — they are NOT in the Queue message.
71
+ * VAPID credentials come from context — they are NOT in the Queue message.
72
+ * When `context.siteConfigLookup` is configured, per-message overrides are
73
+ * applied for VAPID identity and notification defaults.
44
74
  */
45
75
  export async function handlePushQueue(batch, context) {
46
- const sendContext = {
47
- vapidSubject: context.vapid.subject,
48
- vapidPublicKey: context.vapid.publicKey,
49
- vapidPrivateKey: context.vapid.privateKey,
50
- defaults: context.defaults,
51
- };
52
76
  for (const message of batch.messages) {
77
+ const override = context.siteConfigLookup
78
+ ? await context.siteConfigLookup(message.body.siteId, context.env ?? {})
79
+ : null;
80
+ const effective = applyOverride(context, override);
81
+ const sendContext = {
82
+ vapidSubject: effective.vapid.subject,
83
+ vapidPublicKey: effective.vapid.publicKey,
84
+ vapidPrivateKey: effective.vapid.privateKey,
85
+ defaults: effective.defaults,
86
+ };
53
87
  const { subscriptions, payload, options } = message.body;
54
88
  const result = await sendPushBatch(subscriptions, payload, sendContext, options);
55
89
  for (const sendResult of result.results) {
@@ -1 +1 @@
1
- {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/utils/queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/utils/queue.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import type { PushPayload, PushSendOptions } from '../types.js';
6
6
  export interface ScheduledPushContext {
7
7
  db: D1Database;
8
8
  queue: Queue;
9
+ siteId: string;
9
10
  batchSize?: number;
10
11
  cleanup: {
11
12
  staleAfterDays: number;
@@ -1 +1 @@
1
- {"version":3,"file":"scheduled.d.ts","sourceRoot":"","sources":["../../src/utils/scheduled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAK/D;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,EAAE,EAAE,UAAU,CAAA;IACd,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE;QACR,cAAc,EAAE,MAAM,CAAA;KACtB,CAAA;CACD;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,YAAY,EAAE;QACb,OAAO,EAAE,MAAM,CAAA;QACf,kBAAkB,EAAE,MAAM,CAAA;KAC1B,GAAG,IAAI,CAAA;IACR,OAAO,EAAE;QACR,OAAO,EAAE,MAAM,CAAA;KACf,CAAA;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE;IAChD,EAAE,EAAE,UAAU,CAAA;CACd,KAAK,OAAO,CAAC;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,GAAG,IAAI,CAAC,CAAA;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,mBAAmB,CACxC,OAAO,EAAE,oBAAoB,EAC7B,eAAe,EAAE,wBAAwB,GACvC,OAAO,CAAC,mBAAmB,CAAC,CAwC9B"}
1
+ {"version":3,"file":"scheduled.d.ts","sourceRoot":"","sources":["../../src/utils/scheduled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAK/D;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACpC,EAAE,EAAE,UAAU,CAAA;IACd,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE;QACR,cAAc,EAAE,MAAM,CAAA;KACtB,CAAA;CACD;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IACnC,YAAY,EAAE;QACb,OAAO,EAAE,MAAM,CAAA;QACf,kBAAkB,EAAE,MAAM,CAAA;KAC1B,GAAG,IAAI,CAAA;IACR,OAAO,EAAE;QACR,OAAO,EAAE,MAAM,CAAA;KACf,CAAA;CACD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,EAAE;IAChD,EAAE,EAAE,UAAU,CAAA;CACd,KAAK,OAAO,CAAC;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAE,GAAG,IAAI,CAAC,CAAA;AAEzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAsB,mBAAmB,CACxC,OAAO,EAAE,oBAAoB,EAC7B,eAAe,EAAE,wBAAwB,GACvC,OAAO,CAAC,mBAAmB,CAAC,CAwC9B"}
@@ -48,7 +48,7 @@ export async function handleScheduledPush(context, contentProvider) {
48
48
  const content = await contentProvider({ db: context.db });
49
49
  // Step 2: Enqueue notifications if content is available
50
50
  if (content) {
51
- const enqueueResult = await enqueuePushBatchAll(context.db, content.payload, { queue: context.queue, batchSize: context.batchSize }, content.options ?? {});
51
+ const enqueueResult = await enqueuePushBatchAll(context.db, content.payload, { queue: context.queue, siteId: context.siteId, batchSize: context.batchSize }, content.options ?? {});
52
52
  notification = {
53
53
  batches: enqueueResult.batches,
54
54
  totalSubscriptions: enqueueResult.totalSubscriptions,
@@ -1 +1 @@
1
- {"version":3,"file":"scheduled.js","sourceRoot":"","sources":["../../src/utils/scheduled.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AA+DhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,OAA6B,EAC7B,eAAyC;IAEzC,IAAI,YAAY,GAAwC,IAAI,CAAA;IAE5D,2CAA2C;IAC3C,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;IAEzD,wDAAwD;IACxD,IAAI,OAAO,EAAE,CAAC;QACb,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAC9C,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,OAAO,EACf,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,EACtD,OAAO,CAAC,OAAO,IAAI,EAAE,CACrB,CAAA;QAED,YAAY,GAAG;YACd,OAAO,EAAE,aAAa,CAAC,OAAO;YAC9B,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;SACpD,CAAA;QAED,0EAA0E;QAC1E,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE;YACpC,IAAI,EAAE,aAAa,CAAC,kBAAkB;YACtC,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,EAAE;SACX,CAAC,CAAA;IACH,CAAC;IAED,8CAA8C;IAC9C,MAAM,aAAa,GAAG,MAAM,yBAAyB,CAAC,OAAO,CAAC,EAAE,EAAE;QACjE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc;KAC9C,CAAC,CAAA;IAEF,OAAO;QACN,YAAY;QACZ,OAAO,EAAE;YACR,OAAO,EAAE,aAAa,CAAC,OAAO;SAC9B;KACD,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"scheduled.js","sourceRoot":"","sources":["../../src/utils/scheduled.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAgEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,OAA6B,EAC7B,eAAyC;IAEzC,IAAI,YAAY,GAAwC,IAAI,CAAA;IAE5D,2CAA2C;IAC3C,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAA;IAEzD,wDAAwD;IACxD,IAAI,OAAO,EAAE,CAAC;QACb,MAAM,aAAa,GAAG,MAAM,mBAAmB,CAC9C,OAAO,CAAC,EAAE,EACV,OAAO,CAAC,OAAO,EACf,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,EAC9E,OAAO,CAAC,OAAO,IAAI,EAAE,CACrB,CAAA;QAED,YAAY,GAAG;YACd,OAAO,EAAE,aAAa,CAAC,OAAO;YAC9B,kBAAkB,EAAE,aAAa,CAAC,kBAAkB;SACpD,CAAA;QAED,0EAA0E;QAC1E,MAAM,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE;YACpC,IAAI,EAAE,aAAa,CAAC,kBAAkB;YACtC,MAAM,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,EAAE;SACX,CAAC,CAAA;IACH,CAAC;IAED,8CAA8C;IAC9C,MAAM,aAAa,GAAG,MAAM,yBAAyB,CAAC,OAAO,CAAC,EAAE,EAAE;QACjE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc;KAC9C,CAAC,CAAA;IAEF,OAAO;QACN,YAAY;QACZ,OAAO,EAAE;YACR,OAAO,EAAE,aAAa,CAAC,OAAO;SAC9B;KACD,CAAA;AACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-labs/push",
3
- "version": "0.2.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -32,6 +32,10 @@
32
32
  "types": "./dist/db/schema.d.ts",
33
33
  "import": "./dist/db/schema.js"
34
34
  },
35
+ "./consumer": {
36
+ "types": "./dist/utils/queue.d.ts",
37
+ "import": "./dist/utils/queue.js"
38
+ },
35
39
  "./middleware": {
36
40
  "types": "./dist/middleware/push.d.ts",
37
41
  "import": "./dist/middleware/push.js",
@@ -48,9 +52,11 @@
48
52
  },
49
53
  "files": [
50
54
  "dist",
51
- "src/components",
52
- "src/client",
53
- "src/virtual.d.ts",
55
+ "src/**/*.ts",
56
+ "src/**/*.astro",
57
+ "src/**/*.css",
58
+ "src/**/*.md",
59
+ "src/**/*.sql",
54
60
  "README.md"
55
61
  ],
56
62
  "publishConfig": {
@@ -58,16 +64,16 @@
58
64
  "registry": "https://registry.npmjs.org/"
59
65
  },
60
66
  "peerDependencies": {
61
- "astro": "^6.0.0"
67
+ "astro": "^6.1.10"
62
68
  },
63
69
  "dependencies": {
64
70
  "@block65/webcrypto-web-push": "^1.0.0",
65
- "drizzle-orm": "^0.36.0",
71
+ "drizzle-orm": "^0.45.2",
66
72
  "zod": "^3.23.0"
67
73
  },
68
74
  "devDependencies": {
69
75
  "@cloudflare/workers-types": "^4.0.0",
70
- "astro": "^6.0.0",
76
+ "astro": "^6.1.10",
71
77
  "typescript": "^5.7.0",
72
78
  "vitest": "^3.0.0"
73
79
  },
@@ -0,0 +1,14 @@
1
+ import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
2
+
3
+ export const pushSubscriptions = sqliteTable('gl_push_subscriptions', {
4
+ id: text('id').primaryKey(),
5
+ endpoint: text('endpoint').notNull().unique(),
6
+ keyP256dh: text('key_p256dh').notNull(),
7
+ keyAuth: text('key_auth').notNull(),
8
+ topics: text('topics'),
9
+ createdAt: integer('created_at', { mode: 'timestamp' }).notNull(),
10
+ lastDeliveryAt: integer('last_delivery_at', { mode: 'timestamp' }),
11
+ failureCount: integer('failure_count').notNull().default(0),
12
+ userAgent: text('user_agent'),
13
+ country: text('country'),
14
+ })
package/src/index.ts ADDED
@@ -0,0 +1,69 @@
1
+ import { fileURLToPath } from 'node:url'
2
+ import type { AstroIntegration } from 'astro'
3
+ import { type PushOptions, pushOptionsSchema } from './options.js'
4
+
5
+ const ENTRYPOINT_EXTENSION = import.meta.url.endsWith('.ts') ? '.ts' : '.js'
6
+
7
+ function resolveEntrypoint(path: string): string {
8
+ return fileURLToPath(new URL(`${path}${ENTRYPOINT_EXTENSION}`, import.meta.url))
9
+ }
10
+
11
+ export default function push(options: PushOptions): AstroIntegration {
12
+ const resolved = pushOptionsSchema.parse(options)
13
+
14
+ const virtualConfig = {
15
+ vapidPublicKey: resolved.vapidPublicKey,
16
+ d1Binding: resolved.d1Binding,
17
+ queueBinding: resolved.queueBinding,
18
+ defaults: resolved.defaults,
19
+ queue: resolved.queue,
20
+ turnstile: resolved.turnstile,
21
+ routes: resolved.routes,
22
+ cleanup: resolved.cleanup,
23
+ }
24
+
25
+ const virtualModuleId = 'virtual:growth-labs/push/config'
26
+ const resolvedVirtualModuleId = `\0${virtualModuleId}`
27
+
28
+ return {
29
+ name: '@growth-labs/push',
30
+ hooks: {
31
+ 'astro:config:setup': ({ addMiddleware, injectRoute, updateConfig }) => {
32
+ updateConfig({
33
+ vite: {
34
+ plugins: [
35
+ {
36
+ name: 'growth-labs-push-config',
37
+ resolveId(id) {
38
+ if (id === virtualModuleId) return resolvedVirtualModuleId
39
+ },
40
+ load(id) {
41
+ if (id === resolvedVirtualModuleId) {
42
+ return `export default ${JSON.stringify(virtualConfig)}`
43
+ }
44
+ },
45
+ },
46
+ ],
47
+ },
48
+ })
49
+
50
+ addMiddleware({
51
+ entrypoint: resolveEntrypoint('./middleware/push'),
52
+ order: 'pre',
53
+ })
54
+
55
+ injectRoute({
56
+ pattern: resolved.routes.subscribe,
57
+ entrypoint: resolveEntrypoint('./routes/subscribe'),
58
+ prerender: false,
59
+ })
60
+
61
+ injectRoute({
62
+ pattern: resolved.routes.unsubscribe,
63
+ entrypoint: resolveEntrypoint('./routes/unsubscribe'),
64
+ prerender: false,
65
+ })
66
+ },
67
+ },
68
+ }
69
+ }
@@ -0,0 +1,10 @@
1
+ import config from 'virtual:growth-labs/push/config'
2
+ import { defineMiddleware } from 'astro/middleware'
3
+
4
+ export const onRequest = defineMiddleware(async (context, next) => {
5
+ ;(context.locals as Record<string, unknown>).push = {
6
+ vapidPublicKey: config.vapidPublicKey,
7
+ }
8
+
9
+ return next()
10
+ })