@edge-base/server 0.2.2 → 0.2.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.
- package/admin-build/_app/immutable/chunks/{C85dMlzL.js → 5RQRbp5q.js} +1 -1
- package/admin-build/_app/immutable/chunks/{B8DT4fss.js → BME_U9TJ.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BaCHY17I.js → BYI6CUvd.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BWyDPAjM.js → BgDzp0i0.js} +1 -1
- package/admin-build/_app/immutable/chunks/{c5iKSdWY.js → BjWZuf8W.js} +1 -1
- package/admin-build/_app/immutable/chunks/{g3ZZdY-r.js → C6lpZLE2.js} +1 -1
- package/admin-build/_app/immutable/chunks/{C-DsDCNG.js → D5GswVnI.js} +3 -3
- package/admin-build/_app/immutable/chunks/DBsVqhuh.js +1 -0
- package/admin-build/_app/immutable/chunks/{BEYYl662.js → DYaCRWMA.js} +1 -1
- package/admin-build/_app/immutable/chunks/D__dwMuW.js +1 -0
- package/admin-build/_app/immutable/chunks/{4vlsb8ej.js → Dj-E9-FO.js} +1 -1
- package/admin-build/_app/immutable/chunks/{kiJ6KthZ.js → Dj0QUuOf.js} +1 -1
- package/admin-build/_app/immutable/chunks/{BKXmgPq4.js → XQM1k9PM.js} +1 -1
- package/admin-build/_app/immutable/chunks/{CTngeX8H.js → fYEKMQ-Z.js} +1 -1
- package/admin-build/_app/immutable/chunks/{CPdXvRUb.js → g_-Kpxu3.js} +1 -1
- package/admin-build/_app/immutable/chunks/{DzXaj-Ja.js → wCNueVYy.js} +1 -1
- package/admin-build/_app/immutable/entry/{app.BZxfavhF.js → app.C8ylfBe6.js} +2 -2
- package/admin-build/_app/immutable/entry/start.CtsqDyfj.js +1 -0
- package/admin-build/_app/immutable/nodes/{0.DlsaydXO.js → 0.CJJ6HZbp.js} +1 -1
- package/admin-build/_app/immutable/nodes/{1.D2NWN5eG.js → 1.B4sI5cB4.js} +1 -1
- package/admin-build/_app/immutable/nodes/{10.EMDaN3nw.js → 10.D6hvCer6.js} +1 -1
- package/admin-build/_app/immutable/nodes/{11.BasqQ_o9.js → 11.Dx7b8aQ5.js} +1 -1
- package/admin-build/_app/immutable/nodes/{12.DO31Ljs7.js → 12.Bqmy5KIF.js} +1 -1
- package/admin-build/_app/immutable/nodes/{13.DhyAy-GZ.js → 13.CC6KpXgS.js} +1 -1
- package/admin-build/_app/immutable/nodes/{14.CLecGWc4.js → 14.yCo1Ix8E.js} +1 -1
- package/admin-build/_app/immutable/nodes/{15.B9kp3W4e.js → 15.co0UfPlh.js} +1 -1
- package/admin-build/_app/immutable/nodes/{16.Pu_8T3RI.js → 16.D0xkPUBW.js} +1 -1
- package/admin-build/_app/immutable/nodes/{17.DX4z43t6.js → 17.CebNqPeh.js} +1 -1
- package/admin-build/_app/immutable/nodes/{18.BKsSaxrr.js → 18.JUoLOZxh.js} +1 -1
- package/admin-build/_app/immutable/nodes/{19.DXNF1htN.js → 19.ND8kmQJe.js} +1 -1
- package/admin-build/_app/immutable/nodes/{20.VRVb0wee.js → 20.DYb-q3W8.js} +1 -1
- package/admin-build/_app/immutable/nodes/21.cz3IN9Cc.js +1 -0
- package/admin-build/_app/immutable/nodes/{22.DqZf4CtH.js → 22.UOzm8WYV.js} +1 -1
- package/admin-build/_app/immutable/nodes/{23.DtyxMiQG.js → 23.BLgq21om.js} +1 -1
- package/admin-build/_app/immutable/nodes/{24.CloWNmTd.js → 24.DN9usmUs.js} +1 -1
- package/admin-build/_app/immutable/nodes/{25.CnZWMq7_.js → 25.BddRfAyE.js} +1 -1
- package/admin-build/_app/immutable/nodes/{26.DrV7XOmf.js → 26.Dl6XHIeT.js} +1 -1
- package/admin-build/_app/immutable/nodes/{27.DV8L32OF.js → 27.D0iNwALG.js} +1 -1
- package/admin-build/_app/immutable/nodes/{28.Stil2D4u.js → 28.9dKQmdGi.js} +1 -1
- package/admin-build/_app/immutable/nodes/{29.Zsm1e5Dc.js → 29.wXzfJUXp.js} +1 -1
- package/admin-build/_app/immutable/nodes/{3.CKoj2vNz.js → 3.z8ut3jS-.js} +1 -1
- package/admin-build/_app/immutable/nodes/{30.Ni0k5bER.js → 30.BtZETNsL.js} +1 -1
- package/admin-build/_app/immutable/nodes/{31.mnqj9EbV.js → 31.CYonj2Jh.js} +1 -1
- package/admin-build/_app/immutable/nodes/{4.B_-z9AzT.js → 4.COtDPQ9b.js} +1 -1
- package/admin-build/_app/immutable/nodes/{5.yiZ72j4k.js → 5.CTRCeIhp.js} +1 -1
- package/admin-build/_app/immutable/nodes/{6.BqykybBG.js → 6.ChHi3QkR.js} +1 -1
- package/admin-build/_app/immutable/nodes/{7.BDAHlhsF.js → 7.CCMtr6Ac.js} +1 -1
- package/admin-build/_app/immutable/nodes/{8.D8Xvy0lH.js → 8.DpWJ-X_-.js} +1 -1
- package/admin-build/_app/immutable/nodes/{9.Dddmd7_F.js → 9.DOkvfmir.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__/admin-data-routes.test.ts +29 -0
- package/src/__tests__/d1-live-broadcast-verification.test.ts +271 -0
- package/src/__tests__/database-do-route-validation.test.ts +105 -0
- package/src/__tests__/database-live-do.test.ts +50 -0
- package/src/__tests__/database-live-emitter.test.ts +116 -1
- package/src/__tests__/database-live-route.test.ts +82 -0
- package/src/__tests__/do-router.test.ts +116 -0
- package/src/__tests__/error-format.test.ts +63 -0
- package/src/__tests__/functions-context.test.ts +674 -33
- package/src/__tests__/functions-d1-proxy.test.ts +54 -0
- package/src/__tests__/plugin-migration-routing.test.ts +32 -0
- package/src/__tests__/postgres-field-ops-compat.test.ts +110 -0
- package/src/__tests__/provider-aware-sql.test.ts +163 -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__/scheduled.test.ts +55 -0
- package/src/__tests__/service-key-db-proxy.test.ts +122 -1
- package/src/__tests__/sql-route.test.ts +252 -75
- package/src/__tests__/table-hook-runtime.test.ts +137 -0
- package/src/durable-objects/database-do.ts +36 -45
- 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/index.ts +12 -6
- package/src/lib/admin-db-target.ts +30 -74
- package/src/lib/d1-handler.ts +55 -35
- package/src/lib/database-live-emitter.ts +57 -16
- package/src/lib/do-router.ts +135 -3
- package/src/lib/functions.ts +215 -143
- package/src/lib/internal-transport.ts +28 -12
- package/src/lib/plugin-migration-routing.ts +28 -0
- package/src/lib/plugin-migrations.ts +38 -38
- package/src/lib/postgres-handler.ts +51 -31
- package/src/lib/provider-aware-sql.ts +831 -0
- package/src/lib/table-hook-runtime.ts +62 -0
- package/src/routes/admin.ts +41 -41
- package/src/routes/auth.ts +7 -2
- package/src/routes/database-live.ts +110 -12
- package/src/routes/sql.ts +64 -84
- package/src/routes/storage.ts +7 -2
- package/src/routes/tables.ts +42 -29
- package/admin-build/_app/immutable/chunks/5PDcRlfX.js +0 -1
- package/admin-build/_app/immutable/chunks/qiZXAKh-.js +0 -1
- package/admin-build/_app/immutable/entry/start.Mr9mmopc.js +0 -1
- package/admin-build/_app/immutable/nodes/21.Ck3_0D2f.js +0 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const PLUGIN_MIGRATION_PATH_PREFIXES = [
|
|
2
|
+
'/api/auth',
|
|
3
|
+
'/api/db',
|
|
4
|
+
'/api/functions',
|
|
5
|
+
'/api/sql',
|
|
6
|
+
'/api/storage',
|
|
7
|
+
'/admin/api',
|
|
8
|
+
] as const;
|
|
9
|
+
|
|
10
|
+
export function shouldRunPluginMigrationsForRequestPath(path: string): boolean {
|
|
11
|
+
if (!path.startsWith('/')) {
|
|
12
|
+
path = `/${path}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (
|
|
16
|
+
path === '/admin/api/backup'
|
|
17
|
+
|| path.startsWith('/admin/api/backup/')
|
|
18
|
+
|| path.startsWith('/admin/api/data/backup/')
|
|
19
|
+
|| path === '/internal/backup'
|
|
20
|
+
|| path.startsWith('/internal/backup/')
|
|
21
|
+
) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return PLUGIN_MIGRATION_PATH_PREFIXES.some(
|
|
26
|
+
(prefix) => path === prefix || path.startsWith(`${prefix}/`),
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -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
|
}
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
import { isTrustedInternalContext } from './internal-request.js';
|
|
52
52
|
import { executeDbTriggers } from './functions.js';
|
|
53
53
|
import { parseUpdateBody } from './op-parser.js';
|
|
54
|
+
import { buildTableHookRuntimeServices } from './table-hook-runtime.js';
|
|
54
55
|
|
|
55
56
|
// ─── Types ───
|
|
56
57
|
|
|
@@ -232,13 +233,14 @@ async function evalInsertRule(
|
|
|
232
233
|
|
|
233
234
|
function buildHookCtx(
|
|
234
235
|
connectionString: string,
|
|
235
|
-
|
|
236
|
+
env: Env,
|
|
236
237
|
executionCtx?: ExecutionContext,
|
|
237
238
|
queryExecutor?: PostgresExecutor,
|
|
238
239
|
): HookCtx {
|
|
239
240
|
const query =
|
|
240
241
|
queryExecutor ??
|
|
241
242
|
((sql: string, params: unknown[] = []) => executePostgresQuery(connectionString, sql, params));
|
|
243
|
+
const runtimeServices = buildTableHookRuntimeServices(parseConfig(env), env);
|
|
242
244
|
|
|
243
245
|
return {
|
|
244
246
|
db: {
|
|
@@ -279,17 +281,7 @@ function buildHookCtx(
|
|
|
279
281
|
return result.rows.length > 0;
|
|
280
282
|
},
|
|
281
283
|
},
|
|
282
|
-
|
|
283
|
-
async broadcast(_channel: string, _event: string, _data: unknown): Promise<void> {
|
|
284
|
-
// HookCtx broadcast — not implemented for PostgreSQL provider (no direct env access)
|
|
285
|
-
// Use database-live subscription from client SDK instead
|
|
286
|
-
},
|
|
287
|
-
},
|
|
288
|
-
push: {
|
|
289
|
-
async send(_userId: string, _payload: { title?: string; body: string }): Promise<void> {
|
|
290
|
-
// Push notifications — same mechanism as DO (via Worker env)
|
|
291
|
-
},
|
|
292
|
-
},
|
|
284
|
+
...runtimeServices,
|
|
293
285
|
waitUntil(promise: Promise<unknown>): void {
|
|
294
286
|
if (executionCtx) {
|
|
295
287
|
executionCtx.waitUntil(promise);
|
|
@@ -298,6 +290,18 @@ function buildHookCtx(
|
|
|
298
290
|
};
|
|
299
291
|
}
|
|
300
292
|
|
|
293
|
+
function scheduleDbLive(
|
|
294
|
+
executionCtx: ExecutionContext,
|
|
295
|
+
promise: Promise<void>,
|
|
296
|
+
context: string,
|
|
297
|
+
): void {
|
|
298
|
+
executionCtx.waitUntil(
|
|
299
|
+
promise.catch((error) => {
|
|
300
|
+
console.warn(`[db-live] ${context} failed`, error);
|
|
301
|
+
}),
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
301
305
|
function toFieldErrorData(
|
|
302
306
|
errors: Record<string, string>,
|
|
303
307
|
): Record<string, { code: string; message: string }> {
|
|
@@ -346,7 +350,7 @@ async function handleList(
|
|
|
346
350
|
|
|
347
351
|
// Apply onEnrich hook
|
|
348
352
|
if (tableHooks?.onEnrich) {
|
|
349
|
-
const hookCtx = buildHookCtx(resolved.connectionString,
|
|
353
|
+
const hookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx, query);
|
|
350
354
|
for (let i = 0; i < items.length; i++) {
|
|
351
355
|
try {
|
|
352
356
|
const enriched = await tableHooks.onEnrich(auth, items[i], hookCtx);
|
|
@@ -495,7 +499,7 @@ async function handleGet(
|
|
|
495
499
|
|
|
496
500
|
// Apply onEnrich hook
|
|
497
501
|
if (tableHooks?.onEnrich) {
|
|
498
|
-
const hookCtx = buildHookCtx(resolved.connectionString,
|
|
502
|
+
const hookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx, query);
|
|
499
503
|
try {
|
|
500
504
|
const enriched = await tableHooks.onEnrich(auth, row, hookCtx);
|
|
501
505
|
if (enriched && typeof enriched === 'object') return c.json({ ...row, ...enriched });
|
|
@@ -546,7 +550,7 @@ async function handleInsert(
|
|
|
546
550
|
}
|
|
547
551
|
|
|
548
552
|
// Run beforeInsert hook
|
|
549
|
-
const requestHookCtx = buildHookCtx(resolved.connectionString,
|
|
553
|
+
const requestHookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx, query);
|
|
550
554
|
if (tableHooks?.beforeInsert) {
|
|
551
555
|
try {
|
|
552
556
|
const transformed = await tableHooks.beforeInsert(auth, body, requestHookCtx);
|
|
@@ -600,12 +604,13 @@ async function handleInsert(
|
|
|
600
604
|
// Run afterInsert hook (fire-and-forget)
|
|
601
605
|
if (tableHooks?.afterInsert) {
|
|
602
606
|
const hook = tableHooks.afterInsert;
|
|
603
|
-
const backgroundHookCtx = buildHookCtx(resolved.connectionString,
|
|
607
|
+
const backgroundHookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx);
|
|
604
608
|
backgroundHookCtx.waitUntil(Promise.resolve(hook(inserted, backgroundHookCtx)).catch(() => {}));
|
|
605
609
|
}
|
|
606
610
|
|
|
607
611
|
// Emit database-live event (fire-and-forget)
|
|
608
|
-
|
|
612
|
+
scheduleDbLive(
|
|
613
|
+
c.executionCtx,
|
|
609
614
|
emitDbLiveEvent(
|
|
610
615
|
c.env,
|
|
611
616
|
resolved.namespace,
|
|
@@ -614,6 +619,7 @@ async function handleInsert(
|
|
|
614
619
|
String(inserted.id ?? ''),
|
|
615
620
|
inserted,
|
|
616
621
|
),
|
|
622
|
+
`emit ${isUpsert && isUpdate ? 'modified' : 'added'} ${resolved.namespace}.${tableName}`,
|
|
617
623
|
);
|
|
618
624
|
c.executionCtx.waitUntil(
|
|
619
625
|
executeDbTriggers(
|
|
@@ -689,7 +695,7 @@ async function handleUpdate(
|
|
|
689
695
|
}
|
|
690
696
|
|
|
691
697
|
// Run beforeUpdate hook
|
|
692
|
-
const requestHookCtx = buildHookCtx(resolved.connectionString,
|
|
698
|
+
const requestHookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx, query);
|
|
693
699
|
if (tableHooks?.beforeUpdate) {
|
|
694
700
|
try {
|
|
695
701
|
const transformed = await tableHooks.beforeUpdate(auth, existingRow, body, requestHookCtx);
|
|
@@ -726,15 +732,17 @@ async function handleUpdate(
|
|
|
726
732
|
// Run afterUpdate hook (fire-and-forget)
|
|
727
733
|
if (tableHooks?.afterUpdate) {
|
|
728
734
|
const hook = tableHooks.afterUpdate;
|
|
729
|
-
const backgroundHookCtx = buildHookCtx(resolved.connectionString,
|
|
735
|
+
const backgroundHookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx);
|
|
730
736
|
backgroundHookCtx.waitUntil(
|
|
731
737
|
Promise.resolve(hook(existingRow, updated, backgroundHookCtx)).catch(() => {}),
|
|
732
738
|
);
|
|
733
739
|
}
|
|
734
740
|
|
|
735
741
|
// Emit database-live event (fire-and-forget)
|
|
736
|
-
|
|
742
|
+
scheduleDbLive(
|
|
743
|
+
c.executionCtx,
|
|
737
744
|
emitDbLiveEvent(c.env, resolved.namespace, tableName, 'modified', id, updated),
|
|
745
|
+
`emit modified ${resolved.namespace}.${tableName}:${id}`,
|
|
738
746
|
);
|
|
739
747
|
c.executionCtx.waitUntil(
|
|
740
748
|
executeDbTriggers(
|
|
@@ -789,7 +797,7 @@ async function handleDelete(
|
|
|
789
797
|
}
|
|
790
798
|
|
|
791
799
|
// Run beforeDelete hook
|
|
792
|
-
const requestHookCtx = buildHookCtx(resolved.connectionString,
|
|
800
|
+
const requestHookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx, query);
|
|
793
801
|
if (tableHooks?.beforeDelete) {
|
|
794
802
|
try {
|
|
795
803
|
await tableHooks.beforeDelete(auth, existingRow, requestHookCtx);
|
|
@@ -810,15 +818,17 @@ async function handleDelete(
|
|
|
810
818
|
// Run afterDelete hook (fire-and-forget)
|
|
811
819
|
if (tableHooks?.afterDelete) {
|
|
812
820
|
const hook = tableHooks.afterDelete;
|
|
813
|
-
const backgroundHookCtx = buildHookCtx(resolved.connectionString,
|
|
821
|
+
const backgroundHookCtx = buildHookCtx(resolved.connectionString, c.env, c.executionCtx);
|
|
814
822
|
backgroundHookCtx.waitUntil(
|
|
815
823
|
Promise.resolve(hook(existingRow, backgroundHookCtx)).catch(() => {}),
|
|
816
824
|
);
|
|
817
825
|
}
|
|
818
826
|
|
|
819
827
|
// Emit database-live event (fire-and-forget)
|
|
820
|
-
|
|
828
|
+
scheduleDbLive(
|
|
829
|
+
c.executionCtx,
|
|
821
830
|
emitDbLiveEvent(c.env, resolved.namespace, tableName, 'removed', id, stripInternalPgFields(existingRow)),
|
|
831
|
+
`emit removed ${resolved.namespace}.${tableName}:${id}`,
|
|
822
832
|
);
|
|
823
833
|
c.executionCtx.waitUntil(
|
|
824
834
|
executeDbTriggers(
|
|
@@ -944,15 +954,21 @@ async function handleBatch(
|
|
|
944
954
|
data: r as Record<string, unknown>,
|
|
945
955
|
}));
|
|
946
956
|
if (changes.length >= 10) {
|
|
947
|
-
|
|
957
|
+
scheduleDbLive(
|
|
958
|
+
c.executionCtx,
|
|
948
959
|
emitDbLiveBatchEvent(c.env, resolved.namespace, tableName, changes),
|
|
960
|
+
`emit batch ${resolved.namespace}.${tableName} (${changes.length} changes)`,
|
|
949
961
|
);
|
|
950
962
|
} else {
|
|
951
|
-
|
|
952
|
-
c.executionCtx
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
963
|
+
scheduleDbLive(
|
|
964
|
+
c.executionCtx,
|
|
965
|
+
Promise.all(
|
|
966
|
+
changes.map((ch) =>
|
|
967
|
+
emitDbLiveEvent(c.env, resolved.namespace, tableName, ch.type, ch.docId, ch.data),
|
|
968
|
+
),
|
|
969
|
+
).then(() => undefined),
|
|
970
|
+
`emit fan-out ${resolved.namespace}.${tableName} (${changes.length} changes)`,
|
|
971
|
+
);
|
|
956
972
|
}
|
|
957
973
|
}
|
|
958
974
|
|
|
@@ -1031,8 +1047,10 @@ async function handleBatchByFilter(
|
|
|
1031
1047
|
succeeded = result.rowCount;
|
|
1032
1048
|
|
|
1033
1049
|
if (succeeded > 0) {
|
|
1034
|
-
|
|
1050
|
+
scheduleDbLive(
|
|
1051
|
+
c.executionCtx,
|
|
1035
1052
|
emitDbLiveEvent(c.env, resolved.namespace, tableName, 'removed', '_bulk', { action: 'delete', count: succeeded }),
|
|
1053
|
+
`emit bulk ${resolved.namespace}.${tableName} (delete)`,
|
|
1036
1054
|
);
|
|
1037
1055
|
}
|
|
1038
1056
|
|
|
@@ -1074,8 +1092,10 @@ async function handleBatchByFilter(
|
|
|
1074
1092
|
succeeded = result.rowCount;
|
|
1075
1093
|
|
|
1076
1094
|
if (succeeded > 0) {
|
|
1077
|
-
|
|
1095
|
+
scheduleDbLive(
|
|
1096
|
+
c.executionCtx,
|
|
1078
1097
|
emitDbLiveEvent(c.env, resolved.namespace, tableName, 'modified', '_bulk', { action: 'update', count: succeeded }),
|
|
1098
|
+
`emit bulk ${resolved.namespace}.${tableName} (update)`,
|
|
1079
1099
|
);
|
|
1080
1100
|
}
|
|
1081
1101
|
|