@edge-base/server 0.2.2 → 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 (77) hide show
  1. package/admin-build/_app/immutable/chunks/{BWyDPAjM.js → A_3UuvCe.js} +1 -1
  2. package/admin-build/_app/immutable/chunks/{BKXmgPq4.js → B-_-hJ9o.js} +1 -1
  3. package/admin-build/_app/immutable/chunks/{B8DT4fss.js → B5Nwfelm.js} +1 -1
  4. package/admin-build/_app/immutable/chunks/{C-DsDCNG.js → BxoNtYHK.js} +3 -3
  5. package/admin-build/_app/immutable/chunks/{CPdXvRUb.js → CZ0TVkCa.js} +1 -1
  6. package/admin-build/_app/immutable/chunks/{C85dMlzL.js → CzSAxmuj.js} +1 -1
  7. package/admin-build/_app/immutable/chunks/{DzXaj-Ja.js → DCKcAiQH.js} +1 -1
  8. package/admin-build/_app/immutable/chunks/{kiJ6KthZ.js → DCvwWZrm.js} +1 -1
  9. package/admin-build/_app/immutable/chunks/{c5iKSdWY.js → DRqPU3wD.js} +1 -1
  10. package/admin-build/_app/immutable/chunks/{g3ZZdY-r.js → Dc1-6Po6.js} +1 -1
  11. package/admin-build/_app/immutable/chunks/{5PDcRlfX.js → DiyBpamp.js} +1 -1
  12. package/admin-build/_app/immutable/chunks/{BaCHY17I.js → Dlty5069.js} +1 -1
  13. package/admin-build/_app/immutable/chunks/{4vlsb8ej.js → DpVAayDG.js} +1 -1
  14. package/admin-build/_app/immutable/chunks/{CTngeX8H.js → Du5vWVa2.js} +1 -1
  15. package/admin-build/_app/immutable/chunks/{qiZXAKh-.js → byv2rTy8.js} +1 -1
  16. package/admin-build/_app/immutable/chunks/{BEYYl662.js → nZvorU8i.js} +1 -1
  17. package/admin-build/_app/immutable/entry/{app.BZxfavhF.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.DlsaydXO.js → 0.Cn2BZ4da.js} +1 -1
  20. package/admin-build/_app/immutable/nodes/{1.D2NWN5eG.js → 1.Dv4LX_Co.js} +1 -1
  21. package/admin-build/_app/immutable/nodes/{10.EMDaN3nw.js → 10.DPVv3kat.js} +1 -1
  22. package/admin-build/_app/immutable/nodes/{11.BasqQ_o9.js → 11.CiCb6Ayu.js} +1 -1
  23. package/admin-build/_app/immutable/nodes/{12.DO31Ljs7.js → 12.CIPyeekF.js} +1 -1
  24. package/admin-build/_app/immutable/nodes/{13.DhyAy-GZ.js → 13.Z15Lt36e.js} +1 -1
  25. package/admin-build/_app/immutable/nodes/{14.CLecGWc4.js → 14.s0l5bAq3.js} +1 -1
  26. package/admin-build/_app/immutable/nodes/{15.B9kp3W4e.js → 15.UwSSNO76.js} +1 -1
  27. package/admin-build/_app/immutable/nodes/{16.Pu_8T3RI.js → 16.qiD8i883.js} +1 -1
  28. package/admin-build/_app/immutable/nodes/{17.DX4z43t6.js → 17.Dy3dcSvu.js} +1 -1
  29. package/admin-build/_app/immutable/nodes/{18.BKsSaxrr.js → 18.DeXyPYsO.js} +1 -1
  30. package/admin-build/_app/immutable/nodes/{19.DXNF1htN.js → 19.CAbuyS6w.js} +1 -1
  31. package/admin-build/_app/immutable/nodes/{20.VRVb0wee.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.DqZf4CtH.js → 22.CdVprrv2.js} +1 -1
  34. package/admin-build/_app/immutable/nodes/{23.DtyxMiQG.js → 23.Y8RzVLoF.js} +1 -1
  35. package/admin-build/_app/immutable/nodes/{24.CloWNmTd.js → 24.CWhHYFBx.js} +1 -1
  36. package/admin-build/_app/immutable/nodes/{25.CnZWMq7_.js → 25.wCBplOVt.js} +1 -1
  37. package/admin-build/_app/immutable/nodes/{26.DrV7XOmf.js → 26.Cod_JRFK.js} +1 -1
  38. package/admin-build/_app/immutable/nodes/{27.DV8L32OF.js → 27.BO2HVMu9.js} +1 -1
  39. package/admin-build/_app/immutable/nodes/{28.Stil2D4u.js → 28.DxG-FBVQ.js} +1 -1
  40. package/admin-build/_app/immutable/nodes/{29.Zsm1e5Dc.js → 29.CjGqWGvE.js} +1 -1
  41. package/admin-build/_app/immutable/nodes/{3.CKoj2vNz.js → 3.By3_OmdZ.js} +1 -1
  42. package/admin-build/_app/immutable/nodes/{30.Ni0k5bER.js → 30.M_H7Htpq.js} +1 -1
  43. package/admin-build/_app/immutable/nodes/{31.mnqj9EbV.js → 31.DEU18izM.js} +1 -1
  44. package/admin-build/_app/immutable/nodes/{4.B_-z9AzT.js → 4.DeYhKtzJ.js} +1 -1
  45. package/admin-build/_app/immutable/nodes/{5.yiZ72j4k.js → 5.9WLgxhrD.js} +1 -1
  46. package/admin-build/_app/immutable/nodes/{6.BqykybBG.js → 6.BdT2i_dd.js} +1 -1
  47. package/admin-build/_app/immutable/nodes/{7.BDAHlhsF.js → 7.CHq0s4K6.js} +1 -1
  48. package/admin-build/_app/immutable/nodes/{8.D8Xvy0lH.js → 8.DuvRw-XZ.js} +1 -1
  49. package/admin-build/_app/immutable/nodes/{9.Dddmd7_F.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 -3
  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 +590 -33
  58. package/src/__tests__/postgres-field-ops-compat.test.ts +110 -0
  59. package/src/__tests__/provider-aware-sql.test.ts +157 -0
  60. package/src/__tests__/room-auth-state-loss.test.ts +124 -0
  61. package/src/__tests__/runtime-surface-accounting.test.ts +0 -4
  62. package/src/__tests__/sql-route.test.ts +187 -76
  63. package/src/durable-objects/database-live-do.ts +46 -1
  64. package/src/durable-objects/room-runtime-base.ts +26 -2
  65. package/src/durable-objects/rooms-do.ts +1 -1
  66. package/src/lib/admin-db-target.ts +30 -74
  67. package/src/lib/d1-handler.ts +45 -14
  68. package/src/lib/database-live-emitter.ts +57 -16
  69. package/src/lib/functions.ts +212 -141
  70. package/src/lib/plugin-migrations.ts +38 -38
  71. package/src/lib/postgres-handler.ts +39 -11
  72. package/src/lib/provider-aware-sql.ts +827 -0
  73. package/src/routes/auth.ts +7 -2
  74. package/src/routes/sql.ts +51 -76
  75. package/src/routes/storage.ts +7 -2
  76. package/admin-build/_app/immutable/entry/start.Mr9mmopc.js +0 -1
  77. package/admin-build/_app/immutable/nodes/21.Ck3_0D2f.js +0 -1
@@ -33,7 +33,7 @@ import {
33
33
  buildFunctionPushProxy,
34
34
  buildAdminAuthContext,
35
35
  } from './functions.js';
36
- import { executeDoSql } from './do-sql.js';
36
+ import { executeProviderAwareSql } from './provider-aware-sql.js';
37
37
  import { resolveRootServiceKey } from './service-key.js';
38
38
 
39
39
  /**
@@ -118,9 +118,9 @@ function arePluginMigrationsCurrentInMemory(plugins: PluginInstance[]): boolean
118
118
  return false;
119
119
  }
120
120
 
121
- return versionedPlugins.every((plugin) => (
122
- currentVersionedPlugins.get(plugin.name) === plugin.version
123
- ));
121
+ return versionedPlugins.every(
122
+ (plugin) => currentVersionedPlugins.get(plugin.name) === plugin.version,
123
+ );
124
124
  }
125
125
 
126
126
  function markPluginsCurrent(plugins: PluginInstance[]): void {
@@ -217,7 +217,8 @@ async function runMigrationsWithTimeout(
217
217
  }
218
218
 
219
219
  function resolvePluginMigrationTimeoutMs(): number {
220
- const raw = typeof process !== 'undefined' ? process.env.EDGEBASE_PLUGIN_MIGRATIONS_TIMEOUT_MS : undefined;
220
+ const raw =
221
+ typeof process !== 'undefined' ? process.env.EDGEBASE_PLUGIN_MIGRATIONS_TIMEOUT_MS : undefined;
221
222
  const parsed = Number(raw);
222
223
  if (Number.isFinite(parsed) && parsed > 0) {
223
224
  return parsed;
@@ -250,9 +251,9 @@ async function arePluginMigrationsCurrent(
250
251
  );
251
252
  const versions = new Map(rows.map((row) => [row.key, row.value]));
252
253
 
253
- return versionedPlugins.every((plugin) => (
254
- versions.get(`plugin_version:${plugin.name}`) === plugin.version
255
- ));
254
+ return versionedPlugins.every(
255
+ (plugin) => versions.get(`plugin_version:${plugin.name}`) === plugin.version,
256
+ );
256
257
  }
257
258
 
258
259
  // ─── Helpers ───
@@ -334,6 +335,28 @@ function buildMigrationAdminContext(
334
335
  return directUrl ?? null;
335
336
  }
336
337
 
338
+ const sqlProviderAware = async (
339
+ namespace: string,
340
+ id: string | undefined,
341
+ query: string,
342
+ params?: unknown[],
343
+ ): Promise<unknown[]> => {
344
+ const result = await executeProviderAwareSql(
345
+ {
346
+ env,
347
+ config,
348
+ databaseNamespace: dbNamespace,
349
+ workerUrl,
350
+ serviceKey,
351
+ },
352
+ namespace,
353
+ id,
354
+ query,
355
+ params ?? [],
356
+ );
357
+ return result.rows as unknown[];
358
+ };
359
+
337
360
  return {
338
361
  db(namespace: string, id?: string) {
339
362
  const pgConnStr = resolvePgConnString(namespace);
@@ -350,40 +373,14 @@ function buildMigrationAdminContext(
350
373
  return doAdminDb(namespace, id);
351
374
  },
352
375
 
376
+ sqlProviderAware,
353
377
  async sqlWithDirectD1Access(
354
378
  namespace: string,
355
379
  id: string | undefined,
356
380
  query: string,
357
381
  params?: unknown[],
358
382
  ): Promise<unknown[]> {
359
- const dbBlock = config.databases?.[namespace];
360
- const isDynamicNamespace = !!(dbBlock?.instance || dbBlock?.access?.canCreate || dbBlock?.access?.access);
361
- if (isDynamicNamespace && !id) {
362
- throw new Error(`admin.sqlWithDirectD1Access() requires an id for dynamic namespace '${namespace}'.`);
363
- }
364
-
365
- const pgConnStr = resolvePgConnString(namespace);
366
-
367
- // ─── PostgreSQL path ───
368
- if (pgConnStr) {
369
- // Ensure schema is initialized before raw SQL
370
- const dbBlock = config.databases?.[namespace];
371
- if (dbBlock?.tables) {
372
- await ensurePgSchema(pgConnStr, namespace, dbBlock.tables);
373
- }
374
- const result = await executePostgresQuery(pgConnStr, query, params ?? []);
375
- return result.rows as unknown[];
376
- }
377
-
378
- // ─── DO path (existing) ───
379
- return executeDoSql({
380
- databaseNamespace: dbNamespace,
381
- namespace,
382
- id,
383
- query,
384
- params: params ?? [],
385
- internal: true,
386
- });
383
+ return sqlProviderAware(namespace, id, query, params);
387
384
  },
388
385
 
389
386
  // ─── Convenience shortcut: table(name) → db('shared').table(name) ───
@@ -523,7 +520,8 @@ function buildPgTableOps(
523
520
  const setClauses = (updatableCols.length > 0 ? updatableCols : [conflictTarget]).map(
524
521
  (col) => `${escapePgIdentifier(col)} = EXCLUDED.${escapePgIdentifier(col)}`,
525
522
  );
526
- const sql = `INSERT INTO ${escapePgIdentifier(tableName)} (${cols.map(escapePgIdentifier).join(', ')}) VALUES (${placeholders.join(', ')})` +
523
+ const sql =
524
+ `INSERT INTO ${escapePgIdentifier(tableName)} (${cols.map(escapePgIdentifier).join(', ')}) VALUES (${placeholders.join(', ')})` +
527
525
  ` ON CONFLICT (${escapePgIdentifier(conflictTarget)}) DO UPDATE SET ${setClauses.join(', ')} RETURNING *`;
528
526
  const result = await executePostgresQuery(connectionString, sql, vals);
529
527
  return result.rows[0]
@@ -596,7 +594,9 @@ function buildPgTableOps(
596
594
  }
597
595
 
598
596
  const result = await executePostgresQuery(connectionString, sql, params);
599
- return { items: result.rows.map((row) => stripInternalPgFields(row as Record<string, unknown>)) };
597
+ return {
598
+ items: result.rows.map((row) => stripInternalPgFields(row as Record<string, unknown>)),
599
+ };
600
600
  },
601
601
  };
602
602
  }
@@ -298,6 +298,18 @@ function buildHookCtx(
298
298
  };
299
299
  }
300
300
 
301
+ function scheduleDbLive(
302
+ executionCtx: ExecutionContext,
303
+ promise: Promise<void>,
304
+ context: string,
305
+ ): void {
306
+ executionCtx.waitUntil(
307
+ promise.catch((error) => {
308
+ console.warn(`[db-live] ${context} failed`, error);
309
+ }),
310
+ );
311
+ }
312
+
301
313
  function toFieldErrorData(
302
314
  errors: Record<string, string>,
303
315
  ): Record<string, { code: string; message: string }> {
@@ -605,7 +617,8 @@ async function handleInsert(
605
617
  }
606
618
 
607
619
  // Emit database-live event (fire-and-forget)
608
- c.executionCtx.waitUntil(
620
+ scheduleDbLive(
621
+ c.executionCtx,
609
622
  emitDbLiveEvent(
610
623
  c.env,
611
624
  resolved.namespace,
@@ -614,6 +627,7 @@ async function handleInsert(
614
627
  String(inserted.id ?? ''),
615
628
  inserted,
616
629
  ),
630
+ `emit ${isUpsert && isUpdate ? 'modified' : 'added'} ${resolved.namespace}.${tableName}`,
617
631
  );
618
632
  c.executionCtx.waitUntil(
619
633
  executeDbTriggers(
@@ -733,8 +747,10 @@ async function handleUpdate(
733
747
  }
734
748
 
735
749
  // Emit database-live event (fire-and-forget)
736
- c.executionCtx.waitUntil(
750
+ scheduleDbLive(
751
+ c.executionCtx,
737
752
  emitDbLiveEvent(c.env, resolved.namespace, tableName, 'modified', id, updated),
753
+ `emit modified ${resolved.namespace}.${tableName}:${id}`,
738
754
  );
739
755
  c.executionCtx.waitUntil(
740
756
  executeDbTriggers(
@@ -817,8 +833,10 @@ async function handleDelete(
817
833
  }
818
834
 
819
835
  // Emit database-live event (fire-and-forget)
820
- c.executionCtx.waitUntil(
836
+ scheduleDbLive(
837
+ c.executionCtx,
821
838
  emitDbLiveEvent(c.env, resolved.namespace, tableName, 'removed', id, stripInternalPgFields(existingRow)),
839
+ `emit removed ${resolved.namespace}.${tableName}:${id}`,
822
840
  );
823
841
  c.executionCtx.waitUntil(
824
842
  executeDbTriggers(
@@ -944,15 +962,21 @@ async function handleBatch(
944
962
  data: r as Record<string, unknown>,
945
963
  }));
946
964
  if (changes.length >= 10) {
947
- c.executionCtx.waitUntil(
965
+ scheduleDbLive(
966
+ c.executionCtx,
948
967
  emitDbLiveBatchEvent(c.env, resolved.namespace, tableName, changes),
968
+ `emit batch ${resolved.namespace}.${tableName} (${changes.length} changes)`,
949
969
  );
950
970
  } else {
951
- for (const ch of changes) {
952
- c.executionCtx.waitUntil(
953
- emitDbLiveEvent(c.env, resolved.namespace, tableName, ch.type, ch.docId, ch.data),
954
- );
955
- }
971
+ scheduleDbLive(
972
+ c.executionCtx,
973
+ Promise.all(
974
+ changes.map((ch) =>
975
+ emitDbLiveEvent(c.env, resolved.namespace, tableName, ch.type, ch.docId, ch.data),
976
+ ),
977
+ ).then(() => undefined),
978
+ `emit fan-out ${resolved.namespace}.${tableName} (${changes.length} changes)`,
979
+ );
956
980
  }
957
981
  }
958
982
 
@@ -1031,8 +1055,10 @@ async function handleBatchByFilter(
1031
1055
  succeeded = result.rowCount;
1032
1056
 
1033
1057
  if (succeeded > 0) {
1034
- c.executionCtx.waitUntil(
1058
+ scheduleDbLive(
1059
+ c.executionCtx,
1035
1060
  emitDbLiveEvent(c.env, resolved.namespace, tableName, 'removed', '_bulk', { action: 'delete', count: succeeded }),
1061
+ `emit bulk ${resolved.namespace}.${tableName} (delete)`,
1036
1062
  );
1037
1063
  }
1038
1064
 
@@ -1074,8 +1100,10 @@ async function handleBatchByFilter(
1074
1100
  succeeded = result.rowCount;
1075
1101
 
1076
1102
  if (succeeded > 0) {
1077
- c.executionCtx.waitUntil(
1103
+ scheduleDbLive(
1104
+ c.executionCtx,
1078
1105
  emitDbLiveEvent(c.env, resolved.namespace, tableName, 'modified', '_bulk', { action: 'update', count: succeeded }),
1106
+ `emit bulk ${resolved.namespace}.${tableName} (update)`,
1079
1107
  );
1080
1108
  }
1081
1109