@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
@@ -54,7 +54,7 @@ import {
54
54
  buildFunctionPushProxy,
55
55
  buildAdminAuthContext,
56
56
  buildAdminDbProxy,
57
- executeSqlWithDirectD1Access,
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
- executeSqlWithDirectD1Access(
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 on any DatabaseDO.
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 → DatabaseDO sqlExec() → JSON
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, getD1BindingName, shouldRouteToD1 } from '../lib/do-router.js';
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
- ensureLocalDevPostgresSchema,
32
- getLocalDevPostgresExecOptions,
33
- getProviderBindingName,
34
- withPostgresConnection,
35
- } from '../lib/postgres-executor.js';
36
- import { ensurePgSchema } from '../lib/postgres-schema-init.js';
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 SQL via DatabaseDO',
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: { description: 'Query results', content: { 'application/json': { schema: jsonResponseSchema } } },
57
- 400: { description: 'Bad request', content: { 'application/json': { schema: errorResponseSchema } } },
58
- 401: { description: 'Unauthorized', content: { 'application/json': { schema: errorResponseSchema } } },
59
- 403: { description: 'Forbidden', content: { 'application/json': { schema: errorResponseSchema } } },
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: 'id must not contain \':\' (§2)' }, 400);
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 = !!(dbBlock.instance || dbBlock.access?.canCreate || dbBlock.access?.access);
100
+ const isDynamicNamespace = !!(
101
+ dbBlock.instance ||
102
+ dbBlock.access?.canCreate ||
103
+ dbBlock.access?.access
104
+ );
93
105
  if (isDynamicNamespace && !id) {
94
- return c.json({ code: 400, message: `id is required for dynamic namespace '${namespace}'` }, 400);
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 rows = await executeDoSql({
165
- databaseNamespace: c.env.DATABASE,
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
- query: sql,
169
- params: 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);
@@ -44,7 +44,7 @@ import {
44
44
  buildFunctionPushProxy,
45
45
  buildAdminAuthContext,
46
46
  buildAdminDbProxy,
47
- executeSqlWithDirectD1Access,
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
- executeSqlWithDirectD1Access(
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};