@edge-base/server 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/admin-build/_app/immutable/chunks/{DjOEv9M9.js → A_3UuvCe.js} +1 -1
  2. package/admin-build/_app/immutable/chunks/{Dqk2TGNU.js → B-_-hJ9o.js} +1 -1
  3. package/admin-build/_app/immutable/chunks/{BFs_qStz.js → B5Nwfelm.js} +1 -1
  4. package/admin-build/_app/immutable/chunks/{B0QyxC2M.js → BxoNtYHK.js} +3 -3
  5. package/admin-build/_app/immutable/chunks/{BsFiK_FJ.js → CZ0TVkCa.js} +1 -1
  6. package/admin-build/_app/immutable/chunks/{k0CIJkw4.js → CzSAxmuj.js} +1 -1
  7. package/admin-build/_app/immutable/chunks/{D-x55wdW.js → DCKcAiQH.js} +1 -1
  8. package/admin-build/_app/immutable/chunks/{CSGrwS7E.js → DCvwWZrm.js} +1 -1
  9. package/admin-build/_app/immutable/chunks/{BTJcQFEp.js → DRqPU3wD.js} +1 -1
  10. package/admin-build/_app/immutable/chunks/{CqUxCvs_.js → Dc1-6Po6.js} +1 -1
  11. package/admin-build/_app/immutable/chunks/{D755Tqat.js → DiyBpamp.js} +1 -1
  12. package/admin-build/_app/immutable/chunks/{BcIUK2sk.js → Dlty5069.js} +1 -1
  13. package/admin-build/_app/immutable/chunks/{BY07qVPA.js → DpVAayDG.js} +1 -1
  14. package/admin-build/_app/immutable/chunks/{BCKr7yKd.js → Du5vWVa2.js} +1 -1
  15. package/admin-build/_app/immutable/chunks/{m9QZTyVV.js → byv2rTy8.js} +1 -1
  16. package/admin-build/_app/immutable/chunks/{DnLqc9L1.js → nZvorU8i.js} +1 -1
  17. package/admin-build/_app/immutable/entry/{app.BTsq3_xq.js → app.CfrmEXPD.js} +2 -2
  18. package/admin-build/_app/immutable/entry/start.l1WvHznQ.js +1 -0
  19. package/admin-build/_app/immutable/nodes/{0.BZ00WDYH.js → 0.Cn2BZ4da.js} +1 -1
  20. package/admin-build/_app/immutable/nodes/{1.RzSJ3yyr.js → 1.Dv4LX_Co.js} +1 -1
  21. package/admin-build/_app/immutable/nodes/{10.D-rsiquF.js → 10.DPVv3kat.js} +1 -1
  22. package/admin-build/_app/immutable/nodes/{11.l7-bgtFD.js → 11.CiCb6Ayu.js} +1 -1
  23. package/admin-build/_app/immutable/nodes/{12.Dkq0H7B5.js → 12.CIPyeekF.js} +1 -1
  24. package/admin-build/_app/immutable/nodes/{13.DtK_4oRz.js → 13.Z15Lt36e.js} +1 -1
  25. package/admin-build/_app/immutable/nodes/{14.BKo7-AMx.js → 14.s0l5bAq3.js} +1 -1
  26. package/admin-build/_app/immutable/nodes/{15.CQAj_6lq.js → 15.UwSSNO76.js} +1 -1
  27. package/admin-build/_app/immutable/nodes/{16.XVIG-Ffr.js → 16.qiD8i883.js} +1 -1
  28. package/admin-build/_app/immutable/nodes/{17.g6raZLCM.js → 17.Dy3dcSvu.js} +1 -1
  29. package/admin-build/_app/immutable/nodes/{18.IQz6a3T6.js → 18.DeXyPYsO.js} +1 -1
  30. package/admin-build/_app/immutable/nodes/{19.CAAZ8i8h.js → 19.CAbuyS6w.js} +1 -1
  31. package/admin-build/_app/immutable/nodes/{20.BPcX3KPj.js → 20.Bec0T7un.js} +1 -1
  32. package/admin-build/_app/immutable/nodes/21.DuDYelMY.js +1 -0
  33. package/admin-build/_app/immutable/nodes/{22.Br5AG_5Z.js → 22.CdVprrv2.js} +1 -1
  34. package/admin-build/_app/immutable/nodes/{23.KjbrdXoE.js → 23.Y8RzVLoF.js} +1 -1
  35. package/admin-build/_app/immutable/nodes/{24.C3n2-hgw.js → 24.CWhHYFBx.js} +1 -1
  36. package/admin-build/_app/immutable/nodes/{25.SFDSBzHd.js → 25.wCBplOVt.js} +1 -1
  37. package/admin-build/_app/immutable/nodes/{26.D95vui6E.js → 26.Cod_JRFK.js} +1 -1
  38. package/admin-build/_app/immutable/nodes/{27.FgLgdjwB.js → 27.BO2HVMu9.js} +1 -1
  39. package/admin-build/_app/immutable/nodes/{28.B9sYYm1F.js → 28.DxG-FBVQ.js} +1 -1
  40. package/admin-build/_app/immutable/nodes/{29.DyqZ_wbN.js → 29.CjGqWGvE.js} +1 -1
  41. package/admin-build/_app/immutable/nodes/{3.Bzo2yVIO.js → 3.By3_OmdZ.js} +1 -1
  42. package/admin-build/_app/immutable/nodes/{30.c1CiNwiS.js → 30.M_H7Htpq.js} +1 -1
  43. package/admin-build/_app/immutable/nodes/{31.CXty66Vh.js → 31.DEU18izM.js} +1 -1
  44. package/admin-build/_app/immutable/nodes/{4.BgQaXZ27.js → 4.DeYhKtzJ.js} +1 -1
  45. package/admin-build/_app/immutable/nodes/{5.BuJrHvxH.js → 5.9WLgxhrD.js} +1 -1
  46. package/admin-build/_app/immutable/nodes/{6.CkBBC94k.js → 6.BdT2i_dd.js} +1 -1
  47. package/admin-build/_app/immutable/nodes/{7.D2YBvNFM.js → 7.CHq0s4K6.js} +1 -1
  48. package/admin-build/_app/immutable/nodes/{8.D8qQWo_z.js → 8.DuvRw-XZ.js} +1 -1
  49. package/admin-build/_app/immutable/nodes/{9.BLDLX5hV.js → 9.C2Ub82wn.js} +1 -1
  50. package/admin-build/_app/version.json +1 -1
  51. package/admin-build/index.html +7 -7
  52. package/package.json +3 -2
  53. package/src/__tests__/d1-live-broadcast-verification.test.ts +271 -0
  54. package/src/__tests__/database-live-do.test.ts +50 -0
  55. package/src/__tests__/database-live-emitter.test.ts +116 -1
  56. package/src/__tests__/error-format.test.ts +63 -0
  57. package/src/__tests__/functions-context.test.ts +592 -35
  58. package/src/__tests__/meta-export-coverage.test.ts +1 -0
  59. package/src/__tests__/postgres-field-ops-compat.test.ts +110 -0
  60. package/src/__tests__/provider-aware-sql.test.ts +157 -0
  61. package/src/__tests__/room-auth-state-loss.test.ts +124 -0
  62. package/src/__tests__/runtime-surface-accounting.test.ts +0 -4
  63. package/src/__tests__/sql-route.test.ts +187 -76
  64. package/src/durable-objects/database-live-do.ts +46 -1
  65. package/src/durable-objects/room-runtime-base.ts +26 -2
  66. package/src/durable-objects/rooms-do.ts +1 -1
  67. package/src/lib/admin-db-target.ts +30 -74
  68. package/src/lib/d1-handler.ts +45 -14
  69. package/src/lib/database-live-emitter.ts +57 -16
  70. package/src/lib/functions.ts +332 -454
  71. package/src/lib/internal-transport.ts +316 -0
  72. package/src/lib/plugin-migrations.ts +39 -39
  73. package/src/lib/postgres-handler.ts +39 -11
  74. package/src/lib/provider-aware-sql.ts +827 -0
  75. package/src/routes/admin.ts +7 -1
  76. package/src/routes/auth.ts +11 -12
  77. package/src/routes/sql.ts +51 -76
  78. package/src/routes/storage.ts +11 -12
  79. package/src/types.ts +2 -0
  80. package/admin-build/_app/immutable/entry/start.zXCirpgY.js +0 -1
  81. package/admin-build/_app/immutable/nodes/21.DoPabrY_.js +0 -1
@@ -288,6 +288,18 @@ function buildHookCtx(
288
288
  };
289
289
  }
290
290
 
291
+ function scheduleDbLive(
292
+ executionCtx: ExecutionContext,
293
+ promise: Promise<void>,
294
+ context: string,
295
+ ): void {
296
+ executionCtx.waitUntil(
297
+ promise.catch((error) => {
298
+ console.warn(`[db-live] ${context} failed`, error);
299
+ }),
300
+ );
301
+ }
302
+
291
303
  // ─── Utility ───
292
304
 
293
305
  function esc(name: string): string {
@@ -748,10 +760,12 @@ async function handleInsert(
748
760
  hookCtx.waitUntil(Promise.resolve(hook(inserted, hookCtx)).catch(() => {}));
749
761
  }
750
762
 
751
- // Emit database-live event (fire-and-forget)
763
+ // Emit database-live event in the background so writes stay fast.
752
764
  const eventType = isUpsert && isUpdate ? 'modified' : 'added';
753
- c.executionCtx.waitUntil(
765
+ scheduleDbLive(
766
+ c.executionCtx,
754
767
  emitDbLiveEvent(c.env, resolved.namespace, tableName, eventType, String(inserted.id ?? ''), inserted),
768
+ `emit ${eventType} ${resolved.namespace}.${tableName}`,
755
769
  );
756
770
  c.executionCtx.waitUntil(
757
771
  executeDbTriggers(
@@ -891,9 +905,10 @@ async function handleUpdate(
891
905
  );
892
906
  }
893
907
 
894
- // Emit database-live event (fire-and-forget)
895
- c.executionCtx.waitUntil(
908
+ scheduleDbLive(
909
+ c.executionCtx,
896
910
  emitDbLiveEvent(c.env, resolved.namespace, tableName, 'modified', id, updated),
911
+ `emit modified ${resolved.namespace}.${tableName}:${id}`,
897
912
  );
898
913
  c.executionCtx.waitUntil(
899
914
  executeDbTriggers(
@@ -969,9 +984,10 @@ async function handleDelete(
969
984
  );
970
985
  }
971
986
 
972
- // Emit database-live event (fire-and-forget)
973
- c.executionCtx.waitUntil(
987
+ scheduleDbLive(
988
+ c.executionCtx,
974
989
  emitDbLiveEvent(c.env, resolved.namespace, tableName, 'removed', id, stripInternalFields(existingRow)),
990
+ `emit removed ${resolved.namespace}.${tableName}:${id}`,
975
991
  );
976
992
  c.executionCtx.waitUntil(
977
993
  executeDbTriggers(
@@ -1203,15 +1219,21 @@ async function handleBatch(
1203
1219
  // Emit database-live events
1204
1220
  if (allChanges.length > 0) {
1205
1221
  if (allChanges.length >= 10) {
1206
- c.executionCtx.waitUntil(
1222
+ scheduleDbLive(
1223
+ c.executionCtx,
1207
1224
  emitDbLiveBatchEvent(c.env, resolved.namespace, tableName, allChanges),
1225
+ `emit batch ${resolved.namespace}.${tableName} (${allChanges.length} changes)`,
1208
1226
  );
1209
1227
  } else {
1210
- for (const ch of allChanges) {
1211
- c.executionCtx.waitUntil(
1212
- emitDbLiveEvent(c.env, resolved.namespace, tableName, ch.type, ch.docId, ch.data),
1213
- );
1214
- }
1228
+ scheduleDbLive(
1229
+ c.executionCtx,
1230
+ Promise.all(
1231
+ allChanges.map((ch) =>
1232
+ emitDbLiveEvent(c.env, resolved.namespace, tableName, ch.type, ch.docId, ch.data),
1233
+ ),
1234
+ ).then(() => undefined),
1235
+ `emit fan-out ${resolved.namespace}.${tableName} (${allChanges.length} changes)`,
1236
+ );
1215
1237
  }
1216
1238
  }
1217
1239
 
@@ -1306,8 +1328,17 @@ async function handleBatchByFilter(
1306
1328
  // Emit database-live events
1307
1329
  if (succeeded > 0) {
1308
1330
  const eventType = body.action === 'delete' ? 'removed' : 'modified';
1309
- c.executionCtx.waitUntil(
1310
- emitDbLiveEvent(c.env, resolved.namespace, tableName, eventType as 'modified' | 'removed', '_bulk', { action: body.action, count: succeeded }),
1331
+ scheduleDbLive(
1332
+ c.executionCtx,
1333
+ emitDbLiveEvent(
1334
+ c.env,
1335
+ resolved.namespace,
1336
+ tableName,
1337
+ eventType as 'modified' | 'removed',
1338
+ '_bulk',
1339
+ { action: body.action, count: succeeded },
1340
+ ),
1341
+ `emit bulk ${resolved.namespace}.${tableName} (${body.action})`,
1311
1342
  );
1312
1343
  }
1313
1344
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Shared database live event emission helpers.
3
3
  *
4
- * Used by d1-handler.ts and postgres-handler.ts for fire-and-forget
4
+ * Used by d1-handler.ts and postgres-handler.ts for background
5
5
  * event delivery to DatabaseLiveDO after successful CUD operations.
6
6
  *
7
7
  * database-do.ts keeps its own internal version (uses DO env).
@@ -10,6 +10,16 @@ import type { Env } from '../types.js';
10
10
 
11
11
  export const DATABASE_LIVE_HUB_DO_NAME = 'database-live:hub';
12
12
 
13
+ function withDeliveryId(event: Record<string, unknown>): Record<string, unknown> {
14
+ if (typeof event.deliveryId === 'string' && event.deliveryId.length > 0) {
15
+ return event;
16
+ }
17
+ return {
18
+ ...event,
19
+ deliveryId: crypto.randomUUID(),
20
+ };
21
+ }
22
+
13
23
  export function buildDbLiveChannel(
14
24
  namespace: string,
15
25
  table: string,
@@ -34,7 +44,7 @@ export function isDbLiveChannel(channel: string): boolean {
34
44
 
35
45
  /**
36
46
  * Emit a single CUD event to DatabaseLiveDO.
37
- * Mirrors database-do.ts emitDbLiveEvent() — fire-and-forget.
47
+ * Mirrors database-do.ts emitDbLiveEvent().
38
48
  */
39
49
  export function emitDbLiveEvent(
40
50
  env: Env,
@@ -87,25 +97,56 @@ export function emitDbLiveBatchEvent(
87
97
  return sendToDatabaseLiveDO(env, event, '/internal/batch-event');
88
98
  }
89
99
 
100
+ async function postToDatabaseLiveDO(
101
+ env: Env,
102
+ event: Record<string, unknown>,
103
+ path = '/internal/event',
104
+ ): Promise<void> {
105
+ const liveNamespace = env.DATABASE_LIVE;
106
+ if (!liveNamespace) {
107
+ return;
108
+ }
109
+
110
+ const doId = liveNamespace.idFromName(DATABASE_LIVE_HUB_DO_NAME);
111
+ const stub = liveNamespace.get(doId);
112
+ const response = await stub.fetch(`http://internal${path}`, {
113
+ method: 'POST',
114
+ headers: { 'Content-Type': 'application/json' },
115
+ body: JSON.stringify(event),
116
+ });
117
+
118
+ if (!response.ok) {
119
+ const detail = await response.text().catch(() => '');
120
+ const suffix = detail ? `: ${detail.slice(0, 200)}` : '';
121
+ throw new Error(`DatabaseLiveDO ${path} failed with ${response.status}${suffix}`);
122
+ }
123
+ }
124
+
90
125
  /**
91
- * Fire-and-forget: send event to DatabaseLiveDO via stub.fetch().
92
- * Never blocks CRUD response errors are silently ignored.
126
+ * Send an event to DatabaseLiveDO via stub.fetch().
127
+ * Callers should schedule this with waitUntil() when they want
128
+ * fire-and-forget request semantics without hiding delivery failures.
93
129
  */
94
- export function sendToDatabaseLiveDO(
130
+ export async function sendToDatabaseLiveDO(
95
131
  env: Env,
96
132
  event: Record<string, unknown>,
97
133
  path = '/internal/event',
98
134
  ): Promise<void> {
99
- try {
100
- const doId = env.DATABASE_LIVE.idFromName(DATABASE_LIVE_HUB_DO_NAME);
101
- const stub = env.DATABASE_LIVE.get(doId);
102
- return stub.fetch(`http://internal${path}`, {
103
- method: 'POST',
104
- headers: { 'Content-Type': 'application/json' },
105
- body: JSON.stringify(event),
106
- }).then(() => undefined).catch(() => undefined);
107
- } catch {
108
- // Ignore — database live delivery should not block database operations
109
- return Promise.resolve();
135
+ const eventWithDeliveryId = withDeliveryId(event);
136
+ let lastError: unknown;
137
+
138
+ for (let attempt = 0; attempt < 2; attempt++) {
139
+ try {
140
+ await postToDatabaseLiveDO(env, eventWithDeliveryId, path);
141
+ return;
142
+ } catch (error) {
143
+ lastError = error;
144
+ }
145
+ }
146
+
147
+ if (lastError instanceof Error) {
148
+ throw lastError;
110
149
  }
150
+
151
+ throw new Error('DatabaseLiveDO delivery failed.');
111
152
  }