@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.
- package/admin-build/_app/immutable/chunks/{BWyDPAjM.js → A_3UuvCe.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BKXmgPq4.js → B-_-hJ9o.js} +1 -1
- package/admin-build/_app/immutable/chunks/{B8DT4fss.js → B5Nwfelm.js} +1 -1
- package/admin-build/_app/immutable/chunks/{C-DsDCNG.js → BxoNtYHK.js} +3 -3
- package/admin-build/_app/immutable/chunks/{CPdXvRUb.js → CZ0TVkCa.js} +1 -1
- package/admin-build/_app/immutable/chunks/{C85dMlzL.js → CzSAxmuj.js} +1 -1
- package/admin-build/_app/immutable/chunks/{DzXaj-Ja.js → DCKcAiQH.js} +1 -1
- package/admin-build/_app/immutable/chunks/{kiJ6KthZ.js → DCvwWZrm.js} +1 -1
- package/admin-build/_app/immutable/chunks/{c5iKSdWY.js → DRqPU3wD.js} +1 -1
- package/admin-build/_app/immutable/chunks/{g3ZZdY-r.js → Dc1-6Po6.js} +1 -1
- package/admin-build/_app/immutable/chunks/{5PDcRlfX.js → DiyBpamp.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BaCHY17I.js → Dlty5069.js} +1 -1
- package/admin-build/_app/immutable/chunks/{4vlsb8ej.js → DpVAayDG.js} +1 -1
- package/admin-build/_app/immutable/chunks/{CTngeX8H.js → Du5vWVa2.js} +1 -1
- package/admin-build/_app/immutable/chunks/{qiZXAKh-.js → byv2rTy8.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BEYYl662.js → nZvorU8i.js} +1 -1
- package/admin-build/_app/immutable/entry/{app.BZxfavhF.js → app.CfrmEXPD.js} +2 -2
- package/admin-build/_app/immutable/entry/start.l1WvHznQ.js +1 -0
- package/admin-build/_app/immutable/nodes/{0.DlsaydXO.js → 0.Cn2BZ4da.js} +1 -1
- package/admin-build/_app/immutable/nodes/{1.D2NWN5eG.js → 1.Dv4LX_Co.js} +1 -1
- package/admin-build/_app/immutable/nodes/{10.EMDaN3nw.js → 10.DPVv3kat.js} +1 -1
- package/admin-build/_app/immutable/nodes/{11.BasqQ_o9.js → 11.CiCb6Ayu.js} +1 -1
- package/admin-build/_app/immutable/nodes/{12.DO31Ljs7.js → 12.CIPyeekF.js} +1 -1
- package/admin-build/_app/immutable/nodes/{13.DhyAy-GZ.js → 13.Z15Lt36e.js} +1 -1
- package/admin-build/_app/immutable/nodes/{14.CLecGWc4.js → 14.s0l5bAq3.js} +1 -1
- package/admin-build/_app/immutable/nodes/{15.B9kp3W4e.js → 15.UwSSNO76.js} +1 -1
- package/admin-build/_app/immutable/nodes/{16.Pu_8T3RI.js → 16.qiD8i883.js} +1 -1
- package/admin-build/_app/immutable/nodes/{17.DX4z43t6.js → 17.Dy3dcSvu.js} +1 -1
- package/admin-build/_app/immutable/nodes/{18.BKsSaxrr.js → 18.DeXyPYsO.js} +1 -1
- package/admin-build/_app/immutable/nodes/{19.DXNF1htN.js → 19.CAbuyS6w.js} +1 -1
- package/admin-build/_app/immutable/nodes/{20.VRVb0wee.js → 20.Bec0T7un.js} +1 -1
- package/admin-build/_app/immutable/nodes/21.DuDYelMY.js +1 -0
- package/admin-build/_app/immutable/nodes/{22.DqZf4CtH.js → 22.CdVprrv2.js} +1 -1
- package/admin-build/_app/immutable/nodes/{23.DtyxMiQG.js → 23.Y8RzVLoF.js} +1 -1
- package/admin-build/_app/immutable/nodes/{24.CloWNmTd.js → 24.CWhHYFBx.js} +1 -1
- package/admin-build/_app/immutable/nodes/{25.CnZWMq7_.js → 25.wCBplOVt.js} +1 -1
- package/admin-build/_app/immutable/nodes/{26.DrV7XOmf.js → 26.Cod_JRFK.js} +1 -1
- package/admin-build/_app/immutable/nodes/{27.DV8L32OF.js → 27.BO2HVMu9.js} +1 -1
- package/admin-build/_app/immutable/nodes/{28.Stil2D4u.js → 28.DxG-FBVQ.js} +1 -1
- package/admin-build/_app/immutable/nodes/{29.Zsm1e5Dc.js → 29.CjGqWGvE.js} +1 -1
- package/admin-build/_app/immutable/nodes/{3.CKoj2vNz.js → 3.By3_OmdZ.js} +1 -1
- package/admin-build/_app/immutable/nodes/{30.Ni0k5bER.js → 30.M_H7Htpq.js} +1 -1
- package/admin-build/_app/immutable/nodes/{31.mnqj9EbV.js → 31.DEU18izM.js} +1 -1
- package/admin-build/_app/immutable/nodes/{4.B_-z9AzT.js → 4.DeYhKtzJ.js} +1 -1
- package/admin-build/_app/immutable/nodes/{5.yiZ72j4k.js → 5.9WLgxhrD.js} +1 -1
- package/admin-build/_app/immutable/nodes/{6.BqykybBG.js → 6.BdT2i_dd.js} +1 -1
- package/admin-build/_app/immutable/nodes/{7.BDAHlhsF.js → 7.CHq0s4K6.js} +1 -1
- package/admin-build/_app/immutable/nodes/{8.D8Xvy0lH.js → 8.DuvRw-XZ.js} +1 -1
- package/admin-build/_app/immutable/nodes/{9.Dddmd7_F.js → 9.C2Ub82wn.js} +1 -1
- package/admin-build/_app/version.json +1 -1
- package/admin-build/index.html +7 -7
- package/package.json +3 -3
- package/src/__tests__/d1-live-broadcast-verification.test.ts +271 -0
- package/src/__tests__/database-live-do.test.ts +50 -0
- package/src/__tests__/database-live-emitter.test.ts +116 -1
- package/src/__tests__/error-format.test.ts +63 -0
- package/src/__tests__/functions-context.test.ts +590 -33
- package/src/__tests__/postgres-field-ops-compat.test.ts +110 -0
- package/src/__tests__/provider-aware-sql.test.ts +157 -0
- package/src/__tests__/room-auth-state-loss.test.ts +124 -0
- package/src/__tests__/runtime-surface-accounting.test.ts +0 -4
- package/src/__tests__/sql-route.test.ts +187 -76
- package/src/durable-objects/database-live-do.ts +46 -1
- package/src/durable-objects/room-runtime-base.ts +26 -2
- package/src/durable-objects/rooms-do.ts +1 -1
- package/src/lib/admin-db-target.ts +30 -74
- package/src/lib/d1-handler.ts +45 -14
- package/src/lib/database-live-emitter.ts +57 -16
- package/src/lib/functions.ts +212 -141
- package/src/lib/plugin-migrations.ts +38 -38
- package/src/lib/postgres-handler.ts +39 -11
- package/src/lib/provider-aware-sql.ts +827 -0
- package/src/routes/auth.ts +7 -2
- package/src/routes/sql.ts +51 -76
- package/src/routes/storage.ts +7 -2
- package/admin-build/_app/immutable/entry/start.Mr9mmopc.js +0 -1
- 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 {
|
|
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(
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
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 =
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
952
|
-
c.executionCtx
|
|
953
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|