@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
package/src/routes/auth.ts
CHANGED
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
buildFunctionPushProxy,
|
|
55
55
|
buildAdminAuthContext,
|
|
56
56
|
buildAdminDbProxy,
|
|
57
|
-
|
|
57
|
+
executeSqlProviderAware,
|
|
58
58
|
getWorkerUrl,
|
|
59
59
|
} from '../lib/functions.js';
|
|
60
60
|
import * as authService from '../lib/auth-d1-service.js';
|
|
@@ -660,8 +660,13 @@ export async function executeAuthHook(
|
|
|
660
660
|
db: adminDb,
|
|
661
661
|
table: (name: string) => adminDb('shared').table(name),
|
|
662
662
|
auth: authAdmin,
|
|
663
|
+
sqlProviderAware: (namespace: string, id: string | undefined, query: string, params?: unknown[]) =>
|
|
664
|
+
executeSqlProviderAware(
|
|
665
|
+
{ env, config, databaseNamespace: env.DATABASE, workerUrl: options.workerUrl, serviceKey },
|
|
666
|
+
namespace, id, query, params,
|
|
667
|
+
),
|
|
663
668
|
sqlWithDirectD1Access: (namespace: string, id: string | undefined, query: string, params?: unknown[]) =>
|
|
664
|
-
|
|
669
|
+
executeSqlProviderAware(
|
|
665
670
|
{ env, config, databaseNamespace: env.DATABASE, workerUrl: options.workerUrl, serviceKey },
|
|
666
671
|
namespace, id, query, params,
|
|
667
672
|
),
|
package/src/routes/sql.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SQL endpoint — POST /api/sql
|
|
3
3
|
*
|
|
4
|
-
* Allows server SDK (with Service Key) to execute raw SQL
|
|
4
|
+
* Allows server SDK (with Service Key) to execute provider-aware raw SQL.
|
|
5
5
|
* NOT available to client SDK (no sql() method on ClientEdgeBase).
|
|
6
6
|
*
|
|
7
7
|
* §11: URL stays /api/sql, but request body now uses
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* - id, if provided, must not contain ':' (§2)
|
|
14
14
|
* - Parameterized queries enforced (sql + params separate)
|
|
15
15
|
*
|
|
16
|
-
* Flow: Server SDK → POST /api/sql → Worker →
|
|
16
|
+
* Flow: Server SDK → POST /api/sql → Worker → provider-aware executor → JSON
|
|
17
17
|
*
|
|
18
18
|
* Request body:
|
|
19
19
|
* { namespace: string, id?: string, sql: string, params?: unknown[] }
|
|
@@ -23,19 +23,15 @@
|
|
|
23
23
|
* { namespace: 'workspace', id: 'ws-456', sql: 'SELECT * FROM documents', params: [] }
|
|
24
24
|
*/
|
|
25
25
|
import { OpenAPIHono, createRoute, type HonoEnv } from '../lib/hono.js';
|
|
26
|
-
import { parseConfig
|
|
27
|
-
import { executeD1Sql } from '../lib/d1-sql.js';
|
|
26
|
+
import { parseConfig } from '../lib/do-router.js';
|
|
28
27
|
import { validateKey, buildConstraintCtx } from '../lib/service-key.js';
|
|
29
|
-
import { zodDefaultHook, sqlBodySchema, jsonResponseSchema, errorResponseSchema } from '../lib/schemas.js';
|
|
30
28
|
import {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} from '../lib/
|
|
36
|
-
import {
|
|
37
|
-
import { executeDoSql } from '../lib/do-sql.js';
|
|
38
|
-
|
|
29
|
+
zodDefaultHook,
|
|
30
|
+
sqlBodySchema,
|
|
31
|
+
jsonResponseSchema,
|
|
32
|
+
errorResponseSchema,
|
|
33
|
+
} from '../lib/schemas.js';
|
|
34
|
+
import { executeProviderAwareSql } from '../lib/provider-aware-sql.js';
|
|
39
35
|
|
|
40
36
|
export const sqlRoute = new OpenAPIHono<HonoEnv>({ defaultHook: zodDefaultHook });
|
|
41
37
|
|
|
@@ -48,15 +44,27 @@ const executeSql = createRoute({
|
|
|
48
44
|
method: 'post',
|
|
49
45
|
path: '/',
|
|
50
46
|
tags: ['admin'],
|
|
51
|
-
summary: 'Execute
|
|
47
|
+
summary: 'Execute provider-aware raw SQL',
|
|
52
48
|
request: {
|
|
53
49
|
body: { content: { 'application/json': { schema: sqlBodySchema } }, required: true },
|
|
54
50
|
},
|
|
55
51
|
responses: {
|
|
56
|
-
200: {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
200: {
|
|
53
|
+
description: 'Query results',
|
|
54
|
+
content: { 'application/json': { schema: jsonResponseSchema } },
|
|
55
|
+
},
|
|
56
|
+
400: {
|
|
57
|
+
description: 'Bad request',
|
|
58
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
59
|
+
},
|
|
60
|
+
401: {
|
|
61
|
+
description: 'Unauthorized',
|
|
62
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
63
|
+
},
|
|
64
|
+
403: {
|
|
65
|
+
description: 'Forbidden',
|
|
66
|
+
content: { 'application/json': { schema: errorResponseSchema } },
|
|
67
|
+
},
|
|
60
68
|
},
|
|
61
69
|
});
|
|
62
70
|
|
|
@@ -77,7 +85,7 @@ sqlRoute.openapi(executeSql, async (c) => {
|
|
|
77
85
|
return c.json({ code: 400, message: 'id must be a string' }, 400);
|
|
78
86
|
}
|
|
79
87
|
if (id && id.includes(':')) {
|
|
80
|
-
return c.json({ code: 400, message:
|
|
88
|
+
return c.json({ code: 400, message: "id must not contain ':' (§2)" }, 400);
|
|
81
89
|
}
|
|
82
90
|
if (!sql || typeof sql !== 'string') {
|
|
83
91
|
return c.json({ code: 400, message: 'sql is required' }, 400);
|
|
@@ -89,9 +97,16 @@ sqlRoute.openapi(executeSql, async (c) => {
|
|
|
89
97
|
if (!dbBlock) {
|
|
90
98
|
return c.json({ code: 404, message: `Namespace '${namespace}' not found in config` }, 404);
|
|
91
99
|
}
|
|
92
|
-
const isDynamicNamespace = !!(
|
|
100
|
+
const isDynamicNamespace = !!(
|
|
101
|
+
dbBlock.instance ||
|
|
102
|
+
dbBlock.access?.canCreate ||
|
|
103
|
+
dbBlock.access?.access
|
|
104
|
+
);
|
|
93
105
|
if (isDynamicNamespace && !id) {
|
|
94
|
-
return c.json(
|
|
106
|
+
return c.json(
|
|
107
|
+
{ code: 400, message: `id is required for dynamic namespace '${namespace}'` },
|
|
108
|
+
400,
|
|
109
|
+
);
|
|
95
110
|
}
|
|
96
111
|
|
|
97
112
|
// Service Key required AND validated
|
|
@@ -110,65 +125,25 @@ sqlRoute.openapi(executeSql, async (c) => {
|
|
|
110
125
|
return c.json({ code: 401, message: 'Unauthorized. Invalid Service Key.' }, 401);
|
|
111
126
|
}
|
|
112
127
|
|
|
113
|
-
if (!id && (dbBlock?.provider === 'neon' || dbBlock?.provider === 'postgres')) {
|
|
114
|
-
const bindingName = getProviderBindingName(namespace);
|
|
115
|
-
const envRecord = c.env as unknown as Record<string, unknown>;
|
|
116
|
-
const hyperdrive = envRecord[bindingName] as { connectionString?: string } | undefined;
|
|
117
|
-
const envKey = dbBlock.connectionString ?? `${bindingName}_URL`;
|
|
118
|
-
const connStr = hyperdrive?.connectionString ?? (envRecord[envKey] as string | undefined);
|
|
119
|
-
if (!connStr) {
|
|
120
|
-
return c.json({ code: 500, message: `PostgreSQL connection '${envKey}' not found.` }, 500);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
const localDevOptions = getLocalDevPostgresExecOptions(c.env as unknown as Record<string, unknown>, namespace);
|
|
125
|
-
if (localDevOptions) {
|
|
126
|
-
await ensureLocalDevPostgresSchema(localDevOptions);
|
|
127
|
-
}
|
|
128
|
-
const result = await withPostgresConnection(connStr, async (query) => {
|
|
129
|
-
if (!localDevOptions) {
|
|
130
|
-
await ensurePgSchema(connStr, namespace, dbBlock.tables ?? {}, query);
|
|
131
|
-
}
|
|
132
|
-
return query(sql, params ?? []);
|
|
133
|
-
}, localDevOptions);
|
|
134
|
-
const rows = result.rows ?? [];
|
|
135
|
-
return c.json({ rows, items: rows, results: rows, columns: result.columns, rowCount: result.rowCount });
|
|
136
|
-
} catch (err) {
|
|
137
|
-
const message = err instanceof Error ? err.message : 'SQL execution failed';
|
|
138
|
-
return c.json({ code: 500, message }, 500);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (!id && shouldRouteToD1(namespace, config)) {
|
|
143
|
-
const bindingName = getD1BindingName(namespace);
|
|
144
|
-
const d1 = (c.env as unknown as Record<string, unknown>)[bindingName] as D1Database | undefined;
|
|
145
|
-
if (!d1) {
|
|
146
|
-
return c.json({ code: 500, message: `D1 binding '${bindingName}' not found.` }, 500);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
try {
|
|
150
|
-
const result = await executeD1Sql(d1, sql, params ?? []);
|
|
151
|
-
return c.json({
|
|
152
|
-
rows: result.rows,
|
|
153
|
-
items: result.rows,
|
|
154
|
-
results: result.rows,
|
|
155
|
-
rowCount: result.rowCount,
|
|
156
|
-
});
|
|
157
|
-
} catch (err) {
|
|
158
|
-
const message = err instanceof Error ? err.message : 'SQL execution failed';
|
|
159
|
-
return c.json({ code: 500, message }, 500);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
128
|
try {
|
|
164
|
-
const
|
|
165
|
-
|
|
129
|
+
const result = await executeProviderAwareSql(
|
|
130
|
+
{
|
|
131
|
+
env: c.env,
|
|
132
|
+
config,
|
|
133
|
+
databaseNamespace: c.env.DATABASE,
|
|
134
|
+
},
|
|
166
135
|
namespace,
|
|
167
136
|
id,
|
|
168
|
-
|
|
169
|
-
params
|
|
137
|
+
sql,
|
|
138
|
+
params ?? [],
|
|
139
|
+
);
|
|
140
|
+
return c.json({
|
|
141
|
+
rows: result.rows,
|
|
142
|
+
items: result.rows,
|
|
143
|
+
results: result.rows,
|
|
144
|
+
columns: result.columns,
|
|
145
|
+
rowCount: result.rowCount,
|
|
170
146
|
});
|
|
171
|
-
return c.json({ rows, items: rows, results: rows });
|
|
172
147
|
} catch (err) {
|
|
173
148
|
const message = err instanceof Error ? err.message : 'SQL execution failed';
|
|
174
149
|
return c.json({ code: 500, message }, 500);
|
package/src/routes/storage.ts
CHANGED
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
buildFunctionPushProxy,
|
|
45
45
|
buildAdminAuthContext,
|
|
46
46
|
buildAdminDbProxy,
|
|
47
|
-
|
|
47
|
+
executeSqlProviderAware,
|
|
48
48
|
getWorkerUrl,
|
|
49
49
|
} from '../lib/functions.js';
|
|
50
50
|
|
|
@@ -166,8 +166,13 @@ function buildStorageHookAdminContext(
|
|
|
166
166
|
db: adminDb,
|
|
167
167
|
table: (name: string) => adminDb('shared').table(name),
|
|
168
168
|
auth: buildAdminAuthContext({ d1Database: env.AUTH_DB, serviceKey, workerUrl }),
|
|
169
|
+
sqlProviderAware: (namespace: string, id: string | undefined, query: string, params?: unknown[]) =>
|
|
170
|
+
executeSqlProviderAware(
|
|
171
|
+
{ env, config, databaseNamespace: env.DATABASE, workerUrl, serviceKey },
|
|
172
|
+
namespace, id, query, params,
|
|
173
|
+
),
|
|
169
174
|
sqlWithDirectD1Access: (namespace: string, id: string | undefined, query: string, params?: unknown[]) =>
|
|
170
|
-
|
|
175
|
+
executeSqlProviderAware(
|
|
171
176
|
{ env, config, databaseNamespace: env.DATABASE, workerUrl, serviceKey },
|
|
172
177
|
namespace, id, query, params,
|
|
173
178
|
),
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as r}from"../chunks/qiZXAKh-.js";import{w as t}from"../chunks/5PDcRlfX.js";export{t as load_css,r as start};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{_ as m}from"../chunks/C-DsDCNG.js";export{m as component};
|