@growth-labs/push 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/db/schema.d.ts +19 -0
  2. package/dist/db/schema.d.ts.map +1 -1
  3. package/dist/db/schema.js +1 -0
  4. package/dist/db/schema.js.map +1 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/options.d.ts +6 -0
  9. package/dist/options.d.ts.map +1 -1
  10. package/dist/options.js +6 -0
  11. package/dist/options.js.map +1 -1
  12. package/dist/routes/subscribe.d.ts.map +1 -1
  13. package/dist/routes/subscribe.js +3 -1
  14. package/dist/routes/subscribe.js.map +1 -1
  15. package/dist/routes/unsubscribe.d.ts.map +1 -1
  16. package/dist/routes/unsubscribe.js +2 -1
  17. package/dist/routes/unsubscribe.js.map +1 -1
  18. package/dist/types.d.ts +6 -0
  19. package/dist/types.d.ts.map +1 -1
  20. package/dist/utils/cleanup.d.ts +5 -0
  21. package/dist/utils/cleanup.d.ts.map +1 -1
  22. package/dist/utils/cleanup.js +15 -0
  23. package/dist/utils/cleanup.js.map +1 -1
  24. package/dist/utils/queue.d.ts +10 -1
  25. package/dist/utils/queue.d.ts.map +1 -1
  26. package/dist/utils/queue.js +15 -2
  27. package/dist/utils/queue.js.map +1 -1
  28. package/dist/utils/scheduled.d.ts +9 -0
  29. package/dist/utils/scheduled.d.ts.map +1 -1
  30. package/dist/utils/scheduled.js +7 -2
  31. package/dist/utils/scheduled.js.map +1 -1
  32. package/dist/utils/subscriptions.d.ts +7 -1
  33. package/dist/utils/subscriptions.d.ts.map +1 -1
  34. package/dist/utils/subscriptions.js +17 -4
  35. package/dist/utils/subscriptions.js.map +1 -1
  36. package/package.json +2 -2
  37. package/src/db/schema.ts +1 -0
  38. package/src/index.ts +2 -0
  39. package/src/options.ts +7 -0
  40. package/src/routes/subscribe.ts +3 -1
  41. package/src/routes/unsubscribe.ts +2 -1
  42. package/src/types.ts +6 -0
  43. package/src/utils/cleanup.ts +19 -1
  44. package/src/utils/queue.ts +15 -1
  45. package/src/utils/scheduled.ts +16 -1
  46. package/src/utils/subscriptions.ts +21 -4
@@ -186,6 +186,25 @@ export declare const pushSubscriptions: import("drizzle-orm/sqlite-core").SQLite
186
186
  }, {}, {
187
187
  length: number | undefined;
188
188
  }>;
189
+ siteId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
190
+ name: "site_id";
191
+ tableName: "gl_push_subscriptions";
192
+ dataType: "string";
193
+ columnType: "SQLiteText";
194
+ data: string;
195
+ driverParam: string;
196
+ notNull: false;
197
+ hasDefault: false;
198
+ isPrimaryKey: false;
199
+ isAutoincrement: false;
200
+ hasRuntimeDefault: false;
201
+ enumValues: [string, ...string[]];
202
+ baseColumn: never;
203
+ identity: undefined;
204
+ generated: undefined;
205
+ }, {}, {
206
+ length: number | undefined;
207
+ }>;
189
208
  };
190
209
  dialect: "sqlite";
191
210
  }>;
@@ -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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAY5B,CAAA"}
package/dist/db/schema.js CHANGED
@@ -10,5 +10,6 @@ export const pushSubscriptions = sqliteTable('gl_push_subscriptions', {
10
10
  failureCount: integer('failure_count').notNull().default(0),
11
11
  userAgent: text('user_agent'),
12
12
  country: text('country'),
13
+ siteId: text('site_id'),
13
14
  });
14
15
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC,uBAAuB,EAAE;IACrE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE;IAC7C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE;IACjE,cAAc,EAAE,OAAO,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAClE,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3D,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;IAC7B,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;CACxB,CAAC,CAAA"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC,uBAAuB,EAAE;IACrE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE;IAC7C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE;IACjE,cAAc,EAAE,OAAO,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IAClE,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3D,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;IAC7B,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC;IACxB,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;CACvB,CAAC,CAAA"}
@@ -1 +1 @@
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;AAYlE,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;AAYlE,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,gBAAgB,CA4DnE"}
package/dist/index.js CHANGED
@@ -11,7 +11,9 @@ export default function push(options) {
11
11
  const resolved = pushOptionsSchema.parse(options);
12
12
  const virtualConfig = {
13
13
  vapidPublicKey: resolved.vapidPublicKey,
14
+ siteId: resolved.siteId,
14
15
  d1Binding: resolved.d1Binding,
16
+ subscriptionsD1Binding: resolved.subscriptionsD1Binding,
15
17
  queueBinding: resolved.queueBinding,
16
18
  defaults: resolved.defaults,
17
19
  queue: resolved.queue,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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,SAAS,kBAAkB;IAC1B,OAAO,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC9E,CAAC;AAED,MAAM,oBAAoB,GAAG,kBAAkB,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;AAEjE,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"}
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,SAAS,kBAAkB;IAC1B,OAAO,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC9E,CAAC;AAED,MAAM,oBAAoB,GAAG,kBAAkB,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;AAEjE,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,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,sBAAsB,EAAE,QAAQ,CAAC,sBAAsB;QACvD,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/options.d.ts CHANGED
@@ -3,7 +3,9 @@ export declare const pushOptionsSchema: z.ZodObject<{
3
3
  vapidPublicKey: z.ZodString;
4
4
  vapidPrivateKey: z.ZodString;
5
5
  vapidSubject: z.ZodString;
6
+ siteId: z.ZodString;
6
7
  d1Binding: z.ZodDefault<z.ZodString>;
8
+ subscriptionsD1Binding: z.ZodOptional<z.ZodString>;
7
9
  queueBinding: z.ZodDefault<z.ZodString>;
8
10
  defaults: z.ZodDefault<z.ZodObject<{
9
11
  icon: z.ZodOptional<z.ZodString>;
@@ -56,6 +58,7 @@ export declare const pushOptionsSchema: z.ZodObject<{
56
58
  vapidPublicKey: string;
57
59
  vapidPrivateKey: string;
58
60
  vapidSubject: string;
61
+ siteId: string;
59
62
  d1Binding: string;
60
63
  queueBinding: string;
61
64
  defaults: {
@@ -77,14 +80,17 @@ export declare const pushOptionsSchema: z.ZodObject<{
77
80
  cleanup: {
78
81
  staleAfterDays: number;
79
82
  };
83
+ subscriptionsD1Binding?: string | undefined;
80
84
  }, {
81
85
  vapidPublicKey: string;
82
86
  vapidPrivateKey: string;
83
87
  vapidSubject: string;
88
+ siteId: string;
84
89
  turnstile: {
85
90
  secretKey: string;
86
91
  };
87
92
  d1Binding?: string | undefined;
93
+ subscriptionsD1Binding?: string | undefined;
88
94
  queueBinding?: string | undefined;
89
95
  defaults?: {
90
96
  icon?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuC5B,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAC3D,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8C5B,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAC3D,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
package/dist/options.js CHANGED
@@ -3,7 +3,13 @@ export const pushOptionsSchema = z.object({
3
3
  vapidPublicKey: z.string().min(1),
4
4
  vapidPrivateKey: z.string().min(1),
5
5
  vapidSubject: z.string().min(1),
6
+ siteId: z.string().min(1),
6
7
  d1Binding: z.string().default('SITE_DB'),
8
+ // D1 binding holding gl_push_subscriptions (subscribe/unsubscribe + producer
9
+ // reads). Defaults to d1Binding. Set to the realm push DB (e.g. 'MAILER_DB')
10
+ // on sites whose queue is drained by the central push-platform Worker, so the
11
+ // consumer's status writeback and the site's subscribe/produce share one DB.
12
+ subscriptionsD1Binding: z.string().optional(),
7
13
  queueBinding: z.string().default('PUSH_QUEUE'),
8
14
  defaults: z
9
15
  .object({
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACxC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IAE9C,QAAQ,EAAE,CAAC;SACT,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC/C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;KACxE,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IAEb,KAAK,EAAE,CAAC;SACN,MAAM,CAAC;QACP,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;QACnD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;KACrD,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IAEb,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,CAAC;SACP,MAAM,CAAC;QACP,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC;QACpD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;KACxD,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IAEb,OAAO,EAAE,CAAC;SACR,MAAM,CAAC;QACP,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KACvD,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;CACb,CAAC,CAAA"}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAE/B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEzB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACxC,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,6EAA6E;IAC7E,sBAAsB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7C,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IAE9C,QAAQ,EAAE,CAAC;SACT,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC3B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;QAC/C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;KACxE,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IAEb,KAAK,EAAE,CAAC;SACN,MAAM,CAAC;QACP,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;QACnD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;KACrD,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IAEb,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC;QACnB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAC5B,CAAC;IAEF,MAAM,EAAE,CAAC;SACP,MAAM,CAAC;QACP,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,qBAAqB,CAAC;QACpD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,uBAAuB,CAAC;KACxD,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;IAEb,OAAO,EAAE,CAAC;SACR,MAAM,CAAC;QACP,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;KACvD,CAAC;SACD,OAAO,CAAC,EAAE,CAAC;CACb,CAAC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/routes/subscribe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAKrC,eAAO,MAAM,IAAI,EAAE,QA0ElB,CAAA"}
1
+ {"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/routes/subscribe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAKrC,eAAO,MAAM,IAAI,EAAE,QA4ElB,CAAA"}
@@ -30,7 +30,8 @@ export const POST = async ({ request }) => {
30
30
  headers: { 'Content-Type': 'application/json' },
31
31
  });
32
32
  }
33
- const db = envMap[config.d1Binding];
33
+ const subsBinding = config.subscriptionsD1Binding ?? config.d1Binding;
34
+ const db = envMap[subsBinding];
34
35
  const existing = await findSubscriptionByEndpoint(db, endpoint);
35
36
  if (existing) {
36
37
  await saveSubscription(db, {
@@ -56,6 +57,7 @@ export const POST = async ({ request }) => {
56
57
  failureCount: 0,
57
58
  userAgent: request.headers.get('User-Agent'),
58
59
  country: request.headers.get('CF-IPCountry') ?? null,
60
+ siteId: config.siteId,
59
61
  });
60
62
  trackPushSubscription('subscribed', {
61
63
  country: request.headers.get('CF-IPCountry') ?? undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/routes/subscribe.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/routes/subscribe.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"unsubscribe.d.ts","sourceRoot":"","sources":["../../src/routes/unsubscribe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAIrC,eAAO,MAAM,IAAI,EAAE,QAsBlB,CAAA"}
1
+ {"version":3,"file":"unsubscribe.d.ts","sourceRoot":"","sources":["../../src/routes/unsubscribe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAIrC,eAAO,MAAM,IAAI,EAAE,QAuBlB,CAAA"}
@@ -11,7 +11,8 @@ export const POST = async ({ request }) => {
11
11
  headers: { 'Content-Type': 'application/json' },
12
12
  });
13
13
  }
14
- const db = env[config.d1Binding];
14
+ const subsBinding = config.subscriptionsD1Binding ?? config.d1Binding;
15
+ const db = env[subsBinding];
15
16
  const deleted = await deleteSubscriptionByEndpoint(db, endpoint);
16
17
  if (deleted) {
17
18
  trackPushSubscription('unsubscribed').catch(() => { });
@@ -1 +1 @@
1
- {"version":3,"file":"unsubscribe.js","sourceRoot":"","sources":["../../src/routes/unsubscribe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AACxC,OAAO,MAAM,MAAM,iCAAiC,CAAA;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAA;AAExE,MAAM,CAAC,MAAM,IAAI,GAAa,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;IACnD,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAA4B,CAAA;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAA8B,CAAA;IAEpD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,EAAE;YAClE,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAC/C,CAAC,CAAA;IACH,CAAC;IAED,MAAM,EAAE,GAAI,GAA+B,CAAC,MAAM,CAAC,SAAS,CAAe,CAAA;IAC3E,MAAM,OAAO,GAAG,MAAM,4BAA4B,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IAEhE,IAAI,OAAO,EAAE,CAAC;QACb,qBAAqB,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACtD,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1D,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAC/C,CAAC,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"unsubscribe.js","sourceRoot":"","sources":["../../src/routes/unsubscribe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AACxC,OAAO,MAAM,MAAM,iCAAiC,CAAA;AAEpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAA;AAExE,MAAM,CAAC,MAAM,IAAI,GAAa,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;IACnD,MAAM,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,CAA4B,CAAA;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,QAA8B,CAAA;IAEpD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC,EAAE;YAClE,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;SAC/C,CAAC,CAAA;IACH,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,sBAAsB,IAAI,MAAM,CAAC,SAAS,CAAA;IACrE,MAAM,EAAE,GAAI,GAA+B,CAAC,WAAW,CAAe,CAAA;IACtE,MAAM,OAAO,GAAG,MAAM,4BAA4B,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAA;IAEhE,IAAI,OAAO,EAAE,CAAC;QACb,qBAAqB,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IACtD,CAAC;IAED,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE;QAC1D,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;KAC/C,CAAC,CAAA;AACH,CAAC,CAAA"}
package/dist/types.d.ts CHANGED
@@ -28,6 +28,9 @@ export interface PushSubscriptionRecord {
28
28
  failureCount: number;
29
29
  userAgent: string | null;
30
30
  country: string | null;
31
+ /** Site identifier. Null in single-tenant mode; set to options.siteId in
32
+ * central-consumer mode so a shared subscriptions table can be scoped per site. */
33
+ siteId?: string | null;
31
34
  }
32
35
  /**
33
36
  * Queue message shape for batch sends.
@@ -93,7 +96,10 @@ export interface PushLocals {
93
96
  /** Serializable config exported by the virtual module */
94
97
  export interface PushConfig {
95
98
  vapidPublicKey: string;
99
+ siteId: string;
96
100
  d1Binding: string;
101
+ /** Optional separate DB holding gl_push_subscriptions. Defaults to d1Binding. */
102
+ subscriptionsD1Binding?: string;
97
103
  queueBinding: string;
98
104
  defaults: {
99
105
  icon?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -4,9 +4,14 @@ interface CleanupResult {
4
4
  /**
5
5
  * Remove stale or high-failure subscriptions.
6
6
  * Call from a cron trigger or maintenance script.
7
+ *
8
+ * When `siteId` is provided the delete is scoped to that site's rows only —
9
+ * required in central-consumer mode where the table is shared across sites.
10
+ * Omit `siteId` for the back-compat single-tenant path (no filter applied).
7
11
  */
8
12
  export declare function cleanupStaleSubscriptions(db: D1Database, options: {
9
13
  staleAfterDays: number;
14
+ siteId?: string;
10
15
  }): Promise<CleanupResult>;
11
16
  export {};
12
17
  //# sourceMappingURL=cleanup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/utils/cleanup.ts"],"names":[],"mappings":"AAAA,UAAU,aAAa;IACtB,OAAO,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,wBAAsB,yBAAyB,CAC9C,EAAE,EAAE,UAAU,EACd,OAAO,EAAE;IAAE,cAAc,EAAE,MAAM,CAAA;CAAE,GACjC,OAAO,CAAC,aAAa,CAAC,CAgBxB"}
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/utils/cleanup.ts"],"names":[],"mappings":"AAAA,UAAU,aAAa;IACtB,OAAO,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC9C,EAAE,EAAE,UAAU,EACd,OAAO,EAAE;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD,OAAO,CAAC,aAAa,CAAC,CA8BxB"}
@@ -1,9 +1,24 @@
1
1
  /**
2
2
  * Remove stale or high-failure subscriptions.
3
3
  * Call from a cron trigger or maintenance script.
4
+ *
5
+ * When `siteId` is provided the delete is scoped to that site's rows only —
6
+ * required in central-consumer mode where the table is shared across sites.
7
+ * Omit `siteId` for the back-compat single-tenant path (no filter applied).
4
8
  */
5
9
  export async function cleanupStaleSubscriptions(db, options) {
6
10
  const cutoff = Math.floor(Date.now() / 1000) - options.staleAfterDays * 86400;
11
+ if (options.siteId !== undefined) {
12
+ const result = await db
13
+ .prepare(`DELETE FROM gl_push_subscriptions
14
+ WHERE site_id = ?
15
+ AND ((last_delivery_at IS NOT NULL AND last_delivery_at < ?)
16
+ OR (last_delivery_at IS NULL AND created_at < ?)
17
+ OR failure_count >= 10)`)
18
+ .bind(options.siteId, cutoff, cutoff)
19
+ .run();
20
+ return { removed: result.meta?.changes ?? 0 };
21
+ }
7
22
  const result = await db
8
23
  .prepare(`DELETE FROM gl_push_subscriptions
9
24
  WHERE (last_delivery_at IS NOT NULL AND last_delivery_at < ?)
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/utils/cleanup.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,EAAc,EACd,OAAmC;IAEnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,cAAc,GAAG,KAAK,CAAA;IAE7E,MAAM,MAAM,GAAG,MAAM,EAAE;SACrB,OAAO,CACP;;;4BAGyB,CACzB;SACA,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;SACpB,GAAG,EAAE,CAAA;IAEP,OAAO;QACN,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC;KAClC,CAAA;AACF,CAAC"}
1
+ {"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/utils/cleanup.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,EAAc,EACd,OAAoD;IAEpD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,cAAc,GAAG,KAAK,CAAA;IAE7E,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,EAAE;aACrB,OAAO,CACP;;;;iCAI6B,CAC7B;aACA,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aACpC,GAAG,EAAE,CAAA;QACP,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,EAAE,CAAA;IAC9C,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,EAAE;SACrB,OAAO,CACP;;;4BAGyB,CACzB;SACA,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;SACpB,GAAG,EAAE,CAAA;IAEP,OAAO;QACN,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC;KAClC,CAAA;AACF,CAAC"}
@@ -16,8 +16,17 @@ export declare function enqueuePushBatch(subscriptions: PushSubscriptionRecord[]
16
16
  /**
17
17
  * Page through all subscriptions in D1 and enqueue batches as it goes.
18
18
  * Never holds more than one page of subscriptions in memory.
19
+ *
20
+ * Central-consumer mode: pass `centralOptions.subscriptionsDb` to read from a
21
+ * shared realm D1 instead of `db`. A `site_id` filter is automatically applied
22
+ * using `context.siteId` so the site only fans out its own subscriptions.
23
+ *
24
+ * Back-compat (single-tenant): omit `centralOptions` — reads from `db` with no
25
+ * site_id filter, preserving existing behavior.
19
26
  */
20
- export declare function enqueuePushBatchAll(db: D1Database, payload: PushPayload, context: EnqueueContext, options?: PushSendOptions): Promise<{
27
+ export declare function enqueuePushBatchAll(db: D1Database, payload: PushPayload, context: EnqueueContext, options?: PushSendOptions, centralOptions?: {
28
+ subscriptionsDb: D1Database;
29
+ }): Promise<{
21
30
  batches: number;
22
31
  totalSubscriptions: number;
23
32
  }>;
@@ -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,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"}
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;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,eAAoB,EAC7B,cAAc,CAAC,EAAE;IAAE,eAAe,EAAE,UAAU,CAAA;CAAE,GAC9C,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CA8B1D;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"}
@@ -27,14 +27,27 @@ export async function enqueuePushBatch(subscriptions, payload, context, options
27
27
  /**
28
28
  * Page through all subscriptions in D1 and enqueue batches as it goes.
29
29
  * Never holds more than one page of subscriptions in memory.
30
+ *
31
+ * Central-consumer mode: pass `centralOptions.subscriptionsDb` to read from a
32
+ * shared realm D1 instead of `db`. A `site_id` filter is automatically applied
33
+ * using `context.siteId` so the site only fans out its own subscriptions.
34
+ *
35
+ * Back-compat (single-tenant): omit `centralOptions` — reads from `db` with no
36
+ * site_id filter, preserving existing behavior.
30
37
  */
31
- export async function enqueuePushBatchAll(db, payload, context, options = {}) {
38
+ export async function enqueuePushBatchAll(db, payload, context, options = {}, centralOptions) {
32
39
  const batchSize = context.batchSize ?? 100;
40
+ const subsDb = centralOptions?.subscriptionsDb ?? db;
41
+ const siteIdFilter = centralOptions?.subscriptionsDb !== undefined ? context.siteId : undefined;
33
42
  let offset = 0;
34
43
  let batches = 0;
35
44
  let total = 0;
36
45
  while (true) {
37
- const subs = await getAllSubscriptions(db, { limit: batchSize, offset });
46
+ const subs = await getAllSubscriptions(subsDb, {
47
+ limit: batchSize,
48
+ offset,
49
+ siteId: siteIdFilter,
50
+ });
38
51
  if (subs.length === 0)
39
52
  break;
40
53
  const message = {
@@ -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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"}
@@ -2,11 +2,20 @@ import type { PushPayload, PushSendOptions } from '../types.js';
2
2
  /**
3
3
  * Context required by the scheduled push handler.
4
4
  * The consumer provides this from their cron trigger's env bindings.
5
+ *
6
+ * Central-consumer mode: set `subscriptionsDb` to the shared realm D1 holding
7
+ * gl_push_subscriptions. The producer will read from that DB and filter by
8
+ * `siteId`, and cleanup will scope deletes to this site's rows only.
9
+ *
10
+ * Back-compat (single-tenant): omit `subscriptionsDb` — `db` is used for all
11
+ * operations and no site_id filter is applied.
5
12
  */
6
13
  export interface ScheduledPushContext {
7
14
  db: D1Database;
8
15
  queue: Queue;
9
16
  siteId: string;
17
+ /** Optional separate DB holding gl_push_subscriptions (central mode). */
18
+ subscriptionsDb?: D1Database;
10
19
  batchSize?: number;
11
20
  cleanup: {
12
21
  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,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"}
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;;;;;;;;;;GAUG;AACH,MAAM,WAAW,oBAAoB;IACpC,EAAE,EAAE,UAAU,CAAA;IACd,KAAK,EAAE,KAAK,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,eAAe,CAAC,EAAE,UAAU,CAAA;IAC5B,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,CA8C9B"}
@@ -48,7 +48,10 @@ 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, siteId: context.siteId, batchSize: context.batchSize }, content.options ?? {});
51
+ const centralOptions = context.subscriptionsDb
52
+ ? { subscriptionsDb: context.subscriptionsDb }
53
+ : undefined;
54
+ const enqueueResult = await enqueuePushBatchAll(context.db, content.payload, { queue: context.queue, siteId: context.siteId, batchSize: context.batchSize }, content.options ?? {}, centralOptions);
52
55
  notification = {
53
56
  batches: enqueueResult.batches,
54
57
  totalSubscriptions: enqueueResult.totalSubscriptions,
@@ -62,8 +65,10 @@ export async function handleScheduledPush(context, contentProvider) {
62
65
  });
63
66
  }
64
67
  // Step 3: Always clean up stale subscriptions
65
- const cleanupResult = await cleanupStaleSubscriptions(context.db, {
68
+ const cleanupDb = context.subscriptionsDb ?? context.db;
69
+ const cleanupResult = await cleanupStaleSubscriptions(cleanupDb, {
66
70
  staleAfterDays: context.cleanup.staleAfterDays,
71
+ siteId: context.subscriptionsDb !== undefined ? context.siteId : undefined,
67
72
  });
68
73
  return {
69
74
  notification,
@@ -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;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"}
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;AAyEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,cAAc,GAAG,OAAO,CAAC,eAAe;YAC7C,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE;YAC9C,CAAC,CAAC,SAAS,CAAA;QACZ,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,EACrB,cAAc,CACd,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,SAAS,GAAG,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,EAAE,CAAA;IACvD,MAAM,aAAa,GAAG,MAAM,yBAAyB,CAAC,SAAS,EAAE;QAChE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,cAAc;QAC9C,MAAM,EAAE,OAAO,CAAC,eAAe,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;KAC1E,CAAC,CAAA;IAEF,OAAO;QACN,YAAY;QACZ,OAAO,EAAE;YACR,OAAO,EAAE,aAAa,CAAC,OAAO;SAC9B;KACD,CAAA;AACF,CAAC"}
@@ -7,10 +7,16 @@ export declare function findSubscriptionByEndpoint(db: D1Database, endpoint: str
7
7
  export declare function deleteSubscriptionByEndpoint(db: D1Database, endpoint: string): Promise<boolean>;
8
8
  /** Delete a subscription by ID */
9
9
  export declare function deleteSubscriptionById(db: D1Database, id: string): Promise<void>;
10
- /** Get subscriptions with offset-based pagination. Used by enqueuePushBatchAll. */
10
+ /** Get subscriptions with offset-based pagination. Used by enqueuePushBatchAll.
11
+ *
12
+ * When `siteId` is provided the query adds `WHERE site_id = ?` so a site only
13
+ * reads its own rows from a shared (central) subscriptions table. Omit siteId
14
+ * for the back-compat single-tenant path (no filter applied).
15
+ */
11
16
  export declare function getAllSubscriptions(db: D1Database, options?: {
12
17
  limit?: number;
13
18
  offset?: number;
19
+ siteId?: string;
14
20
  }): Promise<PushSubscriptionRecord[]>;
15
21
  /** Count total subscriptions */
16
22
  export declare function countSubscriptions(db: D1Database): Promise<number>;
@@ -1 +1 @@
1
- {"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../../src/utils/subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzD,sCAAsC;AACtC,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBjG;AAED,8CAA8C;AAC9C,wBAAsB,0BAA0B,CAC/C,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAOxC;AAED,4EAA4E;AAC5E,wBAAsB,4BAA4B,CACjD,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,kCAAkC;AAClC,wBAAsB,sBAAsB,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtF;AAED,mFAAmF;AACnF,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,UAAU,EACd,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/C,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAUnC;AAED,gCAAgC;AAChC,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAMxE;AAED,oDAAoD;AACpD,wBAAsB,aAAa,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS7E;AAED,iDAAiD;AACjD,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASrF"}
1
+ {"version":3,"file":"subscriptions.d.ts","sourceRoot":"","sources":["../../src/utils/subscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEzD,sCAAsC;AACtC,wBAAsB,gBAAgB,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0BjG;AAED,8CAA8C;AAC9C,wBAAsB,0BAA0B,CAC/C,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAOxC;AAED,4EAA4E;AAC5E,wBAAsB,4BAA4B,CACjD,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,MAAM,GACd,OAAO,CAAC,OAAO,CAAC,CAOlB;AAED,kCAAkC;AAClC,wBAAsB,sBAAsB,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtF;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,UAAU,EACd,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAChE,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAoBnC;AAED,gCAAgC;AAChC,wBAAsB,kBAAkB,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAMxE;AAED,oDAAoD;AACpD,wBAAsB,aAAa,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS7E;AAED,iDAAiD;AACjD,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASrF"}
@@ -2,14 +2,14 @@
2
2
  export async function saveSubscription(db, sub) {
3
3
  await db
4
4
  .prepare(`INSERT INTO gl_push_subscriptions
5
- (id, endpoint, key_p256dh, key_auth, topics, created_at, last_delivery_at, failure_count, user_agent, country)
6
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
5
+ (id, endpoint, key_p256dh, key_auth, topics, created_at, last_delivery_at, failure_count, user_agent, country, site_id)
6
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
7
7
  ON CONFLICT (endpoint) DO UPDATE SET
8
8
  key_p256dh = excluded.key_p256dh,
9
9
  key_auth = excluded.key_auth,
10
10
  failure_count = excluded.failure_count,
11
11
  last_delivery_at = excluded.last_delivery_at`)
12
- .bind(sub.id, sub.endpoint, sub.keyP256dh, sub.keyAuth, sub.topics, sub.createdAt, sub.lastDeliveryAt, sub.failureCount, sub.userAgent, sub.country)
12
+ .bind(sub.id, sub.endpoint, sub.keyP256dh, sub.keyAuth, sub.topics, sub.createdAt, sub.lastDeliveryAt, sub.failureCount, sub.userAgent, sub.country, sub.siteId ?? null)
13
13
  .run();
14
14
  }
15
15
  /** Find a subscription by its endpoint URL */
@@ -32,10 +32,22 @@ export async function deleteSubscriptionByEndpoint(db, endpoint) {
32
32
  export async function deleteSubscriptionById(db, id) {
33
33
  await db.prepare('DELETE FROM gl_push_subscriptions WHERE id = ?').bind(id).run();
34
34
  }
35
- /** Get subscriptions with offset-based pagination. Used by enqueuePushBatchAll. */
35
+ /** Get subscriptions with offset-based pagination. Used by enqueuePushBatchAll.
36
+ *
37
+ * When `siteId` is provided the query adds `WHERE site_id = ?` so a site only
38
+ * reads its own rows from a shared (central) subscriptions table. Omit siteId
39
+ * for the back-compat single-tenant path (no filter applied).
40
+ */
36
41
  export async function getAllSubscriptions(db, options = {}) {
37
42
  const limit = options.limit ?? 1000;
38
43
  const offset = options.offset ?? 0;
44
+ if (options.siteId !== undefined) {
45
+ const result = await db
46
+ .prepare('SELECT * FROM gl_push_subscriptions WHERE site_id = ? ORDER BY created_at ASC LIMIT ? OFFSET ?')
47
+ .bind(options.siteId, limit, offset)
48
+ .all();
49
+ return (result.results ?? []).map(mapRow);
50
+ }
39
51
  const result = await db
40
52
  .prepare('SELECT * FROM gl_push_subscriptions ORDER BY created_at ASC LIMIT ? OFFSET ?')
41
53
  .bind(limit, offset)
@@ -79,6 +91,7 @@ function mapRow(row) {
79
91
  failureCount: row.failure_count,
80
92
  userAgent: row.user_agent,
81
93
  country: row.country,
94
+ siteId: row.site_id ?? null,
82
95
  };
83
96
  }
84
97
  //# sourceMappingURL=subscriptions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"subscriptions.js","sourceRoot":"","sources":["../../src/utils/subscriptions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subscriptions.js","sourceRoot":"","sources":["../../src/utils/subscriptions.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-labs/push",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
@@ -75,7 +75,7 @@
75
75
  "@cloudflare/workers-types": "^4.0.0",
76
76
  "astro": "^6.1.10",
77
77
  "typescript": "^5.7.0",
78
- "vitest": "^3.0.0"
78
+ "vitest": "^4.1.8"
79
79
  },
80
80
  "scripts": {
81
81
  "build": "tsc",
package/src/db/schema.ts CHANGED
@@ -11,4 +11,5 @@ export const pushSubscriptions = sqliteTable('gl_push_subscriptions', {
11
11
  failureCount: integer('failure_count').notNull().default(0),
12
12
  userAgent: text('user_agent'),
13
13
  country: text('country'),
14
+ siteId: text('site_id'),
14
15
  })
package/src/index.ts CHANGED
@@ -17,7 +17,9 @@ export default function push(options: PushOptions): AstroIntegration {
17
17
 
18
18
  const virtualConfig = {
19
19
  vapidPublicKey: resolved.vapidPublicKey,
20
+ siteId: resolved.siteId,
20
21
  d1Binding: resolved.d1Binding,
22
+ subscriptionsD1Binding: resolved.subscriptionsD1Binding,
21
23
  queueBinding: resolved.queueBinding,
22
24
  defaults: resolved.defaults,
23
25
  queue: resolved.queue,
package/src/options.ts CHANGED
@@ -5,7 +5,14 @@ export const pushOptionsSchema = z.object({
5
5
  vapidPrivateKey: z.string().min(1),
6
6
  vapidSubject: z.string().min(1),
7
7
 
8
+ siteId: z.string().min(1),
9
+
8
10
  d1Binding: z.string().default('SITE_DB'),
11
+ // D1 binding holding gl_push_subscriptions (subscribe/unsubscribe + producer
12
+ // reads). Defaults to d1Binding. Set to the realm push DB (e.g. 'MAILER_DB')
13
+ // on sites whose queue is drained by the central push-platform Worker, so the
14
+ // consumer's status writeback and the site's subscribe/produce share one DB.
15
+ subscriptionsD1Binding: z.string().optional(),
9
16
  queueBinding: z.string().default('PUSH_QUEUE'),
10
17
 
11
18
  defaults: z
@@ -41,7 +41,8 @@ export const POST: APIRoute = async ({ request }) => {
41
41
  })
42
42
  }
43
43
 
44
- const db = envMap[config.d1Binding] as D1Database
44
+ const subsBinding = config.subscriptionsD1Binding ?? config.d1Binding
45
+ const db = envMap[subsBinding] as D1Database
45
46
  const existing = await findSubscriptionByEndpoint(db, endpoint)
46
47
  if (existing) {
47
48
  await saveSubscription(db, {
@@ -68,6 +69,7 @@ export const POST: APIRoute = async ({ request }) => {
68
69
  failureCount: 0,
69
70
  userAgent: request.headers.get('User-Agent'),
70
71
  country: request.headers.get('CF-IPCountry') ?? null,
72
+ siteId: config.siteId,
71
73
  })
72
74
 
73
75
  trackPushSubscription('subscribed', {
@@ -15,7 +15,8 @@ export const POST: APIRoute = async ({ request }) => {
15
15
  })
16
16
  }
17
17
 
18
- const db = (env as Record<string, unknown>)[config.d1Binding] as D1Database
18
+ const subsBinding = config.subscriptionsD1Binding ?? config.d1Binding
19
+ const db = (env as Record<string, unknown>)[subsBinding] as D1Database
19
20
  const deleted = await deleteSubscriptionByEndpoint(db, endpoint)
20
21
 
21
22
  if (deleted) {
package/src/types.ts CHANGED
@@ -30,6 +30,9 @@ export interface PushSubscriptionRecord {
30
30
  failureCount: number
31
31
  userAgent: string | null
32
32
  country: string | null
33
+ /** Site identifier. Null in single-tenant mode; set to options.siteId in
34
+ * central-consumer mode so a shared subscriptions table can be scoped per site. */
35
+ siteId?: string | null
33
36
  }
34
37
 
35
38
  /**
@@ -105,7 +108,10 @@ export interface PushLocals {
105
108
  /** Serializable config exported by the virtual module */
106
109
  export interface PushConfig {
107
110
  vapidPublicKey: string
111
+ siteId: string
108
112
  d1Binding: string
113
+ /** Optional separate DB holding gl_push_subscriptions. Defaults to d1Binding. */
114
+ subscriptionsD1Binding?: string
109
115
  queueBinding: string
110
116
  defaults: {
111
117
  icon?: string
@@ -5,13 +5,31 @@ interface CleanupResult {
5
5
  /**
6
6
  * Remove stale or high-failure subscriptions.
7
7
  * Call from a cron trigger or maintenance script.
8
+ *
9
+ * When `siteId` is provided the delete is scoped to that site's rows only —
10
+ * required in central-consumer mode where the table is shared across sites.
11
+ * Omit `siteId` for the back-compat single-tenant path (no filter applied).
8
12
  */
9
13
  export async function cleanupStaleSubscriptions(
10
14
  db: D1Database,
11
- options: { staleAfterDays: number },
15
+ options: { staleAfterDays: number; siteId?: string },
12
16
  ): Promise<CleanupResult> {
13
17
  const cutoff = Math.floor(Date.now() / 1000) - options.staleAfterDays * 86400
14
18
 
19
+ if (options.siteId !== undefined) {
20
+ const result = await db
21
+ .prepare(
22
+ `DELETE FROM gl_push_subscriptions
23
+ WHERE site_id = ?
24
+ AND ((last_delivery_at IS NOT NULL AND last_delivery_at < ?)
25
+ OR (last_delivery_at IS NULL AND created_at < ?)
26
+ OR failure_count >= 10)`,
27
+ )
28
+ .bind(options.siteId, cutoff, cutoff)
29
+ .run()
30
+ return { removed: result.meta?.changes ?? 0 }
31
+ }
32
+
15
33
  const result = await db
16
34
  .prepare(
17
35
  `DELETE FROM gl_push_subscriptions
@@ -55,20 +55,34 @@ export async function enqueuePushBatch(
55
55
  /**
56
56
  * Page through all subscriptions in D1 and enqueue batches as it goes.
57
57
  * Never holds more than one page of subscriptions in memory.
58
+ *
59
+ * Central-consumer mode: pass `centralOptions.subscriptionsDb` to read from a
60
+ * shared realm D1 instead of `db`. A `site_id` filter is automatically applied
61
+ * using `context.siteId` so the site only fans out its own subscriptions.
62
+ *
63
+ * Back-compat (single-tenant): omit `centralOptions` — reads from `db` with no
64
+ * site_id filter, preserving existing behavior.
58
65
  */
59
66
  export async function enqueuePushBatchAll(
60
67
  db: D1Database,
61
68
  payload: PushPayload,
62
69
  context: EnqueueContext,
63
70
  options: PushSendOptions = {},
71
+ centralOptions?: { subscriptionsDb: D1Database },
64
72
  ): Promise<{ batches: number; totalSubscriptions: number }> {
65
73
  const batchSize = context.batchSize ?? 100
74
+ const subsDb = centralOptions?.subscriptionsDb ?? db
75
+ const siteIdFilter = centralOptions?.subscriptionsDb !== undefined ? context.siteId : undefined
66
76
  let offset = 0
67
77
  let batches = 0
68
78
  let total = 0
69
79
 
70
80
  while (true) {
71
- const subs = await getAllSubscriptions(db, { limit: batchSize, offset })
81
+ const subs = await getAllSubscriptions(subsDb, {
82
+ limit: batchSize,
83
+ offset,
84
+ siteId: siteIdFilter,
85
+ })
72
86
  if (subs.length === 0) break
73
87
 
74
88
  const message: PushQueueMessage = {
@@ -6,11 +6,20 @@ import { enqueuePushBatchAll } from './queue.js'
6
6
  /**
7
7
  * Context required by the scheduled push handler.
8
8
  * The consumer provides this from their cron trigger's env bindings.
9
+ *
10
+ * Central-consumer mode: set `subscriptionsDb` to the shared realm D1 holding
11
+ * gl_push_subscriptions. The producer will read from that DB and filter by
12
+ * `siteId`, and cleanup will scope deletes to this site's rows only.
13
+ *
14
+ * Back-compat (single-tenant): omit `subscriptionsDb` — `db` is used for all
15
+ * operations and no site_id filter is applied.
9
16
  */
10
17
  export interface ScheduledPushContext {
11
18
  db: D1Database
12
19
  queue: Queue
13
20
  siteId: string
21
+ /** Optional separate DB holding gl_push_subscriptions (central mode). */
22
+ subscriptionsDb?: D1Database
14
23
  batchSize?: number
15
24
  cleanup: {
16
25
  staleAfterDays: number
@@ -117,11 +126,15 @@ export async function handleScheduledPush(
117
126
 
118
127
  // Step 2: Enqueue notifications if content is available
119
128
  if (content) {
129
+ const centralOptions = context.subscriptionsDb
130
+ ? { subscriptionsDb: context.subscriptionsDb }
131
+ : undefined
120
132
  const enqueueResult = await enqueuePushBatchAll(
121
133
  context.db,
122
134
  content.payload,
123
135
  { queue: context.queue, siteId: context.siteId, batchSize: context.batchSize },
124
136
  content.options ?? {},
137
+ centralOptions,
125
138
  )
126
139
 
127
140
  notification = {
@@ -139,8 +152,10 @@ export async function handleScheduledPush(
139
152
  }
140
153
 
141
154
  // Step 3: Always clean up stale subscriptions
142
- const cleanupResult = await cleanupStaleSubscriptions(context.db, {
155
+ const cleanupDb = context.subscriptionsDb ?? context.db
156
+ const cleanupResult = await cleanupStaleSubscriptions(cleanupDb, {
143
157
  staleAfterDays: context.cleanup.staleAfterDays,
158
+ siteId: context.subscriptionsDb !== undefined ? context.siteId : undefined,
144
159
  })
145
160
 
146
161
  return {
@@ -5,8 +5,8 @@ export async function saveSubscription(db: D1Database, sub: PushSubscriptionReco
5
5
  await db
6
6
  .prepare(
7
7
  `INSERT INTO gl_push_subscriptions
8
- (id, endpoint, key_p256dh, key_auth, topics, created_at, last_delivery_at, failure_count, user_agent, country)
9
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
8
+ (id, endpoint, key_p256dh, key_auth, topics, created_at, last_delivery_at, failure_count, user_agent, country, site_id)
9
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
10
10
  ON CONFLICT (endpoint) DO UPDATE SET
11
11
  key_p256dh = excluded.key_p256dh,
12
12
  key_auth = excluded.key_auth,
@@ -24,6 +24,7 @@ export async function saveSubscription(db: D1Database, sub: PushSubscriptionReco
24
24
  sub.failureCount,
25
25
  sub.userAgent,
26
26
  sub.country,
27
+ sub.siteId ?? null,
27
28
  )
28
29
  .run()
29
30
  }
@@ -59,14 +60,29 @@ export async function deleteSubscriptionById(db: D1Database, id: string): Promis
59
60
  await db.prepare('DELETE FROM gl_push_subscriptions WHERE id = ?').bind(id).run()
60
61
  }
61
62
 
62
- /** Get subscriptions with offset-based pagination. Used by enqueuePushBatchAll. */
63
+ /** Get subscriptions with offset-based pagination. Used by enqueuePushBatchAll.
64
+ *
65
+ * When `siteId` is provided the query adds `WHERE site_id = ?` so a site only
66
+ * reads its own rows from a shared (central) subscriptions table. Omit siteId
67
+ * for the back-compat single-tenant path (no filter applied).
68
+ */
63
69
  export async function getAllSubscriptions(
64
70
  db: D1Database,
65
- options: { limit?: number; offset?: number } = {},
71
+ options: { limit?: number; offset?: number; siteId?: string } = {},
66
72
  ): Promise<PushSubscriptionRecord[]> {
67
73
  const limit = options.limit ?? 1000
68
74
  const offset = options.offset ?? 0
69
75
 
76
+ if (options.siteId !== undefined) {
77
+ const result = await db
78
+ .prepare(
79
+ 'SELECT * FROM gl_push_subscriptions WHERE site_id = ? ORDER BY created_at ASC LIMIT ? OFFSET ?',
80
+ )
81
+ .bind(options.siteId, limit, offset)
82
+ .all()
83
+ return (result.results ?? []).map(mapRow)
84
+ }
85
+
70
86
  const result = await db
71
87
  .prepare('SELECT * FROM gl_push_subscriptions ORDER BY created_at ASC LIMIT ? OFFSET ?')
72
88
  .bind(limit, offset)
@@ -120,5 +136,6 @@ function mapRow(row: Record<string, unknown>): PushSubscriptionRecord {
120
136
  failureCount: row.failure_count as number,
121
137
  userAgent: row.user_agent as string | null,
122
138
  country: row.country as string | null,
139
+ siteId: (row.site_id as string | null | undefined) ?? null,
123
140
  }
124
141
  }