@ailnaf/zoddb 0.0.0-stage → 0.1.0

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 (93) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +15 -0
  3. package/README.md +412 -2
  4. package/dist/aggregate.d.ts +42 -0
  5. package/dist/aggregate.d.ts.map +1 -0
  6. package/dist/aggregate.js +77 -0
  7. package/dist/aggregate.js.map +1 -0
  8. package/dist/auth-schema.d.ts +26 -0
  9. package/dist/auth-schema.d.ts.map +1 -0
  10. package/dist/auth-schema.js +139 -0
  11. package/dist/auth-schema.js.map +1 -0
  12. package/dist/better-auth-adapter.d.ts +21 -0
  13. package/dist/better-auth-adapter.d.ts.map +1 -0
  14. package/dist/better-auth-adapter.js +175 -0
  15. package/dist/better-auth-adapter.js.map +1 -0
  16. package/dist/cli.d.ts +3 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +341 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/config.d.ts +22 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +52 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/db.d.ts +183 -0
  25. package/dist/db.d.ts.map +1 -0
  26. package/dist/db.js +946 -0
  27. package/dist/db.js.map +1 -0
  28. package/dist/ddl.d.ts +21 -0
  29. package/dist/ddl.d.ts.map +1 -0
  30. package/dist/ddl.js +127 -0
  31. package/dist/ddl.js.map +1 -0
  32. package/dist/dev.d.ts +9 -0
  33. package/dist/dev.d.ts.map +1 -0
  34. package/dist/dev.js +21 -0
  35. package/dist/dev.js.map +1 -0
  36. package/dist/errors.d.ts +63 -0
  37. package/dist/errors.d.ts.map +1 -0
  38. package/dist/errors.js +122 -0
  39. package/dist/errors.js.map +1 -0
  40. package/dist/filter.d.ts +66 -0
  41. package/dist/filter.d.ts.map +1 -0
  42. package/dist/filter.js +219 -0
  43. package/dist/filter.js.map +1 -0
  44. package/dist/graph.d.ts +54 -0
  45. package/dist/graph.d.ts.map +1 -0
  46. package/dist/graph.js +52 -0
  47. package/dist/graph.js.map +1 -0
  48. package/dist/index.d.ts +8 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +6 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/init.d.ts +12 -0
  53. package/dist/init.d.ts.map +1 -0
  54. package/dist/init.js +62 -0
  55. package/dist/init.js.map +1 -0
  56. package/dist/migrate.d.ts +58 -0
  57. package/dist/migrate.d.ts.map +1 -0
  58. package/dist/migrate.js +447 -0
  59. package/dist/migrate.js.map +1 -0
  60. package/dist/migrations.d.ts +80 -0
  61. package/dist/migrations.d.ts.map +1 -0
  62. package/dist/migrations.js +281 -0
  63. package/dist/migrations.js.map +1 -0
  64. package/dist/relation-graph.d.ts +50 -0
  65. package/dist/relation-graph.d.ts.map +1 -0
  66. package/dist/relation-graph.js +93 -0
  67. package/dist/relation-graph.js.map +1 -0
  68. package/dist/relations.d.ts +94 -0
  69. package/dist/relations.d.ts.map +1 -0
  70. package/dist/relations.js +21 -0
  71. package/dist/relations.js.map +1 -0
  72. package/dist/schema.d.ts +247 -0
  73. package/dist/schema.d.ts.map +1 -0
  74. package/dist/schema.js +584 -0
  75. package/dist/schema.js.map +1 -0
  76. package/dist/studio/page.d.ts +3 -0
  77. package/dist/studio/page.d.ts.map +1 -0
  78. package/dist/studio/page.js +708 -0
  79. package/dist/studio/page.js.map +1 -0
  80. package/dist/studio/server.d.ts +26 -0
  81. package/dist/studio/server.d.ts.map +1 -0
  82. package/dist/studio/server.js +415 -0
  83. package/dist/studio/server.js.map +1 -0
  84. package/dist/table.d.ts +156 -0
  85. package/dist/table.d.ts.map +1 -0
  86. package/dist/table.js +165 -0
  87. package/dist/table.js.map +1 -0
  88. package/dist/where.d.ts +18 -0
  89. package/dist/where.d.ts.map +1 -0
  90. package/dist/where.js +76 -0
  91. package/dist/where.js.map +1 -0
  92. package/docs/api.md +444 -0
  93. package/package.json +70 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/studio/page.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAisB7B,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { type Server } from 'node:http';
2
+ import { type SchemaDefinition } from '../index.js';
3
+ export interface StudioOptions {
4
+ schema: SchemaDefinition;
5
+ url?: string;
6
+ write?: boolean;
7
+ port?: number;
8
+ host?: string;
9
+ token?: string;
10
+ /** CLI 用于读取迁移状态;studio 不直接导入迁移模块。 */
11
+ schemaPath?: string;
12
+ migrationsDir?: string;
13
+ cli?: {
14
+ command: string;
15
+ args?: readonly string[];
16
+ };
17
+ }
18
+ export interface StudioServer {
19
+ readonly origin: string;
20
+ readonly url: string;
21
+ readonly token: string;
22
+ readonly server: Server;
23
+ close(): Promise<void>;
24
+ }
25
+ export declare function startStudio(options: StudioOptions): Promise<StudioServer>;
26
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/studio/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAsC,KAAK,MAAM,EAAuB,MAAM,WAAW,CAAA;AAEhG,OAAO,EAA4C,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAG7F,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,gBAAgB,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,GAAG,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAA;CACpD;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAkPD,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CA+M/E"}
@@ -0,0 +1,415 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { randomBytes } from 'node:crypto';
3
+ import { createServer } from 'node:http';
4
+ import { basename } from 'node:path';
5
+ import { relationGraph, zoddb } from '../index.js';
6
+ import { STUDIO_HTML } from './page.js';
7
+ const DEFAULT_PORT = 5555;
8
+ const DEFAULT_HOST = '127.0.0.1';
9
+ function send(res, status, type, body) {
10
+ res.writeHead(status, {
11
+ 'content-type': type,
12
+ 'cache-control': 'no-store',
13
+ 'x-content-type-options': 'nosniff',
14
+ 'referrer-policy': 'no-referrer',
15
+ 'x-frame-options': 'DENY',
16
+ 'content-security-policy': "default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline'; connect-src 'self'; img-src 'self' data:; base-uri 'none'; frame-ancestors 'none'",
17
+ });
18
+ res.end(body);
19
+ }
20
+ function sendJson(res, status, value) {
21
+ send(res, status, 'application/json; charset=utf-8', JSON.stringify(value));
22
+ }
23
+ function authorized(req, url, token) {
24
+ const header = req.headers['x-zoddb-studio-token'];
25
+ return header === token || url.searchParams.get('token') === token;
26
+ }
27
+ const FILTER_OPS = new Set(['eq', 'ne', 'contains', 'startsWith', 'endsWith', 'gt', 'gte', 'lt', 'lte', 'isNull']);
28
+ function isRecord(value) {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
30
+ }
31
+ function requireRecord(value, name) {
32
+ if (!isRecord(value) || Object.keys(value).length === 0)
33
+ throw new Error(`${name} 必须是非空对象`);
34
+ return value;
35
+ }
36
+ async function readJsonBody(req) {
37
+ let body = '';
38
+ for await (const chunk of req) {
39
+ body += typeof chunk === 'string' ? chunk : chunk.toString();
40
+ if (body.length > 1_000_000)
41
+ throw new Error('请求体超过 1MB');
42
+ }
43
+ if (!body)
44
+ throw new Error('请求体为空');
45
+ return JSON.parse(body);
46
+ }
47
+ function writeClient(scope, graph, table) {
48
+ const node = graph.nodes.find(n => n.key === table);
49
+ if (!node)
50
+ throw new Error(`未知表: ${table ?? ''}`);
51
+ const client = scope[node.key];
52
+ if (!client || typeof client !== 'object')
53
+ throw new Error(`表客户端不存在: ${node.key}`);
54
+ return client;
55
+ }
56
+ async function executeInTransaction(scope, graph, raw) {
57
+ if (raw.op === 'transaction')
58
+ throw new Error('transaction 不能嵌套');
59
+ if (raw.op === 'create') {
60
+ const client = writeClient(scope, graph, raw.table);
61
+ return client.create(requireRecord(raw.input, 'input'));
62
+ }
63
+ if (raw.op === 'update') {
64
+ const client = writeClient(scope, graph, raw.table);
65
+ const rows = await client.update(requireRecord(raw.where, 'where'), requireRecord(raw.values, 'values'));
66
+ if (rows.length !== 1)
67
+ throw new Error('update 必须恰好命中 1 行');
68
+ return rows;
69
+ }
70
+ if (raw.op === 'delete') {
71
+ const client = writeClient(scope, graph, raw.table);
72
+ const count = await client.delete(requireRecord(raw.where, 'where'));
73
+ if (count !== 1)
74
+ throw new Error('delete 必须恰好命中 1 行');
75
+ return count;
76
+ }
77
+ if (raw.op === 'upsert') {
78
+ const client = writeClient(scope, graph, raw.table);
79
+ if (!Array.isArray(raw.conflict) || raw.conflict.some(v => typeof v !== 'string')) {
80
+ throw new Error('conflict 必须是列名数组');
81
+ }
82
+ if (raw.update !== undefined && (!Array.isArray(raw.update) || raw.update.some(v => typeof v !== 'string'))) {
83
+ throw new Error('update 必须是列名数组');
84
+ }
85
+ return client.upsert(requireRecord(raw.values, 'values'), {
86
+ conflict: raw.conflict,
87
+ ...(raw.update ? { update: raw.update } : {}),
88
+ });
89
+ }
90
+ throw new Error(`未知写操作: ${String(raw.op)}`);
91
+ }
92
+ async function executeWrite(scope, graph, raw) {
93
+ if (raw.op === 'transaction') {
94
+ if (!Array.isArray(raw.ops) || raw.ops.length === 0)
95
+ throw new Error('transaction.ops 必须是非空数组');
96
+ return scope.transaction(async (tx) => {
97
+ const results = [];
98
+ for (const child of raw.ops)
99
+ results.push(await executeInTransaction(tx, graph, child));
100
+ return results;
101
+ });
102
+ }
103
+ return scope.transaction(async (tx) => executeInTransaction(tx, graph, raw));
104
+ }
105
+ const MIGRATION_KEYS = ['applied', 'pending', 'missing', 'outOfOrder', 'empty', 'tampered', 'drift'];
106
+ function isMigrationStatus(value) {
107
+ if (!isRecord(value))
108
+ return false;
109
+ if (!Array.isArray(value.applied))
110
+ return false;
111
+ if (!value.applied.every(item => typeof item === 'string' || (isRecord(item) && typeof item.id === 'string')))
112
+ return false;
113
+ return MIGRATION_KEYS.filter(key => key !== 'applied').every(key => Array.isArray(value[key]) && value[key].every(item => typeof item === 'string'));
114
+ }
115
+ /** 只读调用公开 CLI `status --json`;不导入 migrations 内部模块。 */
116
+ function readMigrationStatus(opts) {
117
+ return new Promise((resolve, reject) => {
118
+ const args = [...(opts.cli.args ?? []), 'status', '--schema', opts.schemaPath, '--dir', opts.migrationsDir, '--url', opts.url, '--json'];
119
+ const child = spawn(opts.cli.command, args, {
120
+ cwd: process.cwd(),
121
+ env: process.env,
122
+ stdio: ['ignore', 'pipe', 'pipe'],
123
+ });
124
+ let stdout = '';
125
+ let stderr = '';
126
+ let settled = false;
127
+ const finish = (fn) => {
128
+ if (settled)
129
+ return;
130
+ settled = true;
131
+ clearTimeout(timer);
132
+ fn();
133
+ };
134
+ const timer = setTimeout(() => {
135
+ child.kill();
136
+ finish(() => reject(new Error('status --json 超时')));
137
+ }, 15_000);
138
+ child.stdout.setEncoding('utf8');
139
+ child.stderr.setEncoding('utf8');
140
+ child.stdout.on('data', (chunk) => {
141
+ stdout += chunk;
142
+ if (stdout.length > 1_000_000) {
143
+ child.kill();
144
+ finish(() => reject(new Error('status --json 输出超过 1MB')));
145
+ }
146
+ });
147
+ child.stderr.on('data', (chunk) => { stderr += chunk; });
148
+ child.on('error', err => finish(() => reject(err)));
149
+ child.on('close', code => {
150
+ finish(() => {
151
+ let parsed;
152
+ try {
153
+ parsed = JSON.parse(stdout.trim());
154
+ }
155
+ catch {
156
+ reject(new Error(stderr.trim() || `status --json 没有返回 JSON(exit ${code ?? 'unknown'})`));
157
+ return;
158
+ }
159
+ if (!isMigrationStatus(parsed)) {
160
+ reject(new Error('status --json 返回结构无效'));
161
+ return;
162
+ }
163
+ resolve({
164
+ status: {
165
+ ...parsed,
166
+ applied: parsed.applied.map(item => typeof item === 'string' ? item : item.id),
167
+ },
168
+ exitCode: code ?? 1,
169
+ });
170
+ });
171
+ });
172
+ });
173
+ }
174
+ function errorText(err) {
175
+ return err instanceof Error ? err.message : String(err);
176
+ }
177
+ function parseFilterValue(raw, sqlType) {
178
+ if (raw === 'null')
179
+ return null;
180
+ if (sqlType === 'bool' || sqlType === 'boolean')
181
+ return raw === 'true';
182
+ if (/^(int|int2|int4|int8|smallint|integer|bigint|numeric|decimal|real|double|float)/.test(sqlType)) {
183
+ const n = Number(raw);
184
+ return Number.isFinite(n) ? n : raw;
185
+ }
186
+ return raw;
187
+ }
188
+ function buildFilter(node, column, op, raw) {
189
+ if (!FILTER_OPS.has(op))
190
+ throw new Error(`未知过滤操作符: ${op}`);
191
+ const meta = node.columns.find(c => c.key === column);
192
+ if (!meta)
193
+ throw new Error(`未知过滤列: ${column}`);
194
+ const value = parseFilterValue(raw, meta.type);
195
+ if (op === 'eq')
196
+ return { [column]: value };
197
+ if (op === 'isNull')
198
+ return { [column]: { isNull: raw !== 'false' } };
199
+ return { [column]: { [op]: value } };
200
+ }
201
+ export async function startStudio(options) {
202
+ const graph = relationGraph(options.schema);
203
+ const db = options.url ? zoddb({ schema: options.schema, url: options.url }) : undefined;
204
+ const host = options.host ?? DEFAULT_HOST;
205
+ const token = options.token ?? randomBytes(24).toString('base64url');
206
+ const server = createServer(async (req, res) => {
207
+ try {
208
+ const url = new URL(req.url ?? '/', `http://${req.headers.host ?? host}`);
209
+ if (url.pathname === '/api/write' && req.method === 'POST') {
210
+ const requestOrigin = req.headers.origin;
211
+ if (requestOrigin && requestOrigin !== `http://${req.headers.host}`) {
212
+ sendJson(res, 403, { error: '拒绝跨源写请求', code: 'CROSS_ORIGIN' });
213
+ return;
214
+ }
215
+ if (!authorized(req, url, token)) {
216
+ sendJson(res, 401, { error: 'unauthorized', code: 'UNAUTHORIZED' });
217
+ return;
218
+ }
219
+ if (!db || !options.write) {
220
+ sendJson(res, 403, { error: '写模式未开启;使用 --write 启动 Studio', code: 'WRITE_DISABLED' });
221
+ return;
222
+ }
223
+ try {
224
+ const raw = await readJsonBody(req);
225
+ const result = await executeWrite(db, graph, raw);
226
+ sendJson(res, 200, { ok: true, result });
227
+ }
228
+ catch (err) {
229
+ sendJson(res, 400, { error: errorText(err), code: 'WRITE_FAILED' });
230
+ }
231
+ return;
232
+ }
233
+ if (req.method !== 'GET') {
234
+ sendJson(res, 405, { error: 'method not allowed', code: 'METHOD_NOT_ALLOWED' });
235
+ return;
236
+ }
237
+ if (url.pathname === '/api/schema') {
238
+ if (!authorized(req, url, token)) {
239
+ sendJson(res, 401, { error: 'unauthorized', code: 'UNAUTHORIZED' });
240
+ return;
241
+ }
242
+ sendJson(res, 200, { ...graph, dataEnabled: Boolean(db), writeEnabled: Boolean(db && options.write), migrationsEnabled: Boolean(db && options.schemaPath && options.migrationsDir && options.cli) });
243
+ return;
244
+ }
245
+ if (url.pathname === '/api/migrations') {
246
+ if (!authorized(req, url, token)) {
247
+ sendJson(res, 401, { error: 'unauthorized', code: 'UNAUTHORIZED' });
248
+ return;
249
+ }
250
+ if (!db) {
251
+ sendJson(res, 503, { error: '未配置数据库;使用 --url 或 DATABASE_URL 启动 Studio', code: 'MIGRATIONS_UNAVAILABLE' });
252
+ return;
253
+ }
254
+ if (!options.schemaPath || !options.migrationsDir || !options.cli) {
255
+ sendJson(res, 400, { error: '未配置迁移状态:需要 schema、迁移目录和 CLI 入口', code: 'MIGRATIONS_UNAVAILABLE' });
256
+ return;
257
+ }
258
+ try {
259
+ const result = await readMigrationStatus({
260
+ url: options.url,
261
+ schemaPath: options.schemaPath,
262
+ migrationsDir: options.migrationsDir,
263
+ cli: options.cli,
264
+ });
265
+ sendJson(res, 200, {
266
+ ...result,
267
+ migrations: basename(options.migrationsDir),
268
+ checkedAt: new Date().toISOString(),
269
+ });
270
+ }
271
+ catch (err) {
272
+ sendJson(res, 502, { error: errorText(err), code: 'MIGRATION_STATUS_FAILED' });
273
+ }
274
+ return;
275
+ }
276
+ if (url.pathname === '/api/rows') {
277
+ if (!authorized(req, url, token)) {
278
+ sendJson(res, 401, { error: 'unauthorized', code: 'UNAUTHORIZED' });
279
+ return;
280
+ }
281
+ if (!db) {
282
+ sendJson(res, 503, { error: '未配置数据库;使用 --url 或 DATABASE_URL 启动 Studio', code: 'DB_UNAVAILABLE' });
283
+ return;
284
+ }
285
+ const table = url.searchParams.get('table');
286
+ const node = graph.nodes.find(n => n.key === table);
287
+ if (!node) {
288
+ sendJson(res, 404, { error: `未知表: ${table ?? ''}`, code: 'UNKNOWN_TABLE' });
289
+ return;
290
+ }
291
+ const limit = Math.min(Math.max(Number(url.searchParams.get('limit') ?? 50) || 50, 1), 200);
292
+ const offset = Math.max(Number(url.searchParams.get('offset') ?? 0) || 0, 0);
293
+ const sort = url.searchParams.get('sort') || undefined;
294
+ const dir = url.searchParams.get('dir') === 'desc' ? 'desc' : 'asc';
295
+ if (sort !== undefined && !node.columns.some(c => c.key === sort)) {
296
+ sendJson(res, 400, { error: `未知排序列: ${sort}` });
297
+ return;
298
+ }
299
+ const filterColumn = url.searchParams.get('filterColumn') || undefined;
300
+ const filterOp = url.searchParams.get('filterOp') || 'eq';
301
+ const filterValue = url.searchParams.get('filterValue') ?? '';
302
+ const parentWhere = filterColumn ? buildFilter(node, filterColumn, filterOp, filterValue) : undefined;
303
+ const relationName = url.searchParams.get('relation') || undefined;
304
+ let relationWhere;
305
+ if (relationName) {
306
+ const edge = graph.edges.find(e => e.from === node.key && e.name === relationName);
307
+ if (!edge) {
308
+ sendJson(res, 400, { error: `未知关系: ${node.key}.${relationName}` });
309
+ return;
310
+ }
311
+ const mode = url.searchParams.get('relationMode') === 'none' ? 'none' : 'some';
312
+ const target = graph.nodes.find(n => n.key === edge.to);
313
+ if (!target) {
314
+ sendJson(res, 400, { error: `关系目标不存在: ${edge.to}` });
315
+ return;
316
+ }
317
+ const relationColumn = url.searchParams.get('relationColumn') || undefined;
318
+ const relationOp = url.searchParams.get('relationOp') || 'eq';
319
+ const relationValue = url.searchParams.get('relationValue') ?? '';
320
+ const targetWhere = relationColumn ? buildFilter(target, relationColumn, relationOp, relationValue) : {};
321
+ relationWhere = { [relationName]: { [mode]: targetWhere } };
322
+ }
323
+ const whereParts = [parentWhere, relationWhere].filter((w) => Boolean(w));
324
+ const where = whereParts.length === 0 ? undefined : whereParts.length === 1 ? whereParts[0] : { AND: whereParts };
325
+ const withName = url.searchParams.get('with') || undefined;
326
+ if (withName) {
327
+ const edge = graph.edges.find(e => e.from === node.key && e.name === withName);
328
+ if (!edge) {
329
+ sendJson(res, 400, { error: `未知关系: ${node.key}.${withName}` });
330
+ return;
331
+ }
332
+ }
333
+ const selectRaw = url.searchParams.get('select');
334
+ const select = selectRaw ? selectRaw.split(',').filter(Boolean) : undefined;
335
+ if (select) {
336
+ if (select.length === 0) {
337
+ sendJson(res, 400, { error: 'select 不能为空' });
338
+ return;
339
+ }
340
+ for (const key of select) {
341
+ if (!node.columns.some(c => c.key === key)) {
342
+ sendJson(res, 400, { error: `未知投影列: ${key}` });
343
+ return;
344
+ }
345
+ }
346
+ }
347
+ const client = db[node.key];
348
+ if (!client) {
349
+ sendJson(res, 404, { error: `未知表: ${node.key}` });
350
+ return;
351
+ }
352
+ const opts = { limit, offset };
353
+ if (sort)
354
+ opts.orderBy = { [sort]: dir };
355
+ if (where)
356
+ opts.where = where;
357
+ if (select)
358
+ opts.select = Object.fromEntries(select.map(key => [key, true]));
359
+ if (withName)
360
+ opts.with = { [withName]: true };
361
+ try {
362
+ const [rows, total] = await Promise.all([
363
+ client.findMany(opts),
364
+ client.count(where),
365
+ ]);
366
+ sendJson(res, 200, { table: node.key, rows, total, limit, offset });
367
+ }
368
+ catch (err) {
369
+ sendJson(res, 400, { error: errorText(err), code: 'ROWS_FAILED' });
370
+ }
371
+ return;
372
+ }
373
+ if (url.pathname === '/' || url.pathname === '/index.html') {
374
+ send(res, 200, 'text/html; charset=utf-8', STUDIO_HTML);
375
+ return;
376
+ }
377
+ sendJson(res, 404, { error: 'not found' });
378
+ }
379
+ catch (err) {
380
+ sendJson(res, 500, { error: errorText(err), code: 'INTERNAL' });
381
+ }
382
+ });
383
+ await new Promise((resolve, reject) => {
384
+ server.once('error', reject);
385
+ server.listen(options.port ?? DEFAULT_PORT, host, () => {
386
+ server.off('error', reject);
387
+ resolve();
388
+ });
389
+ });
390
+ const address = server.address();
391
+ if (!address || typeof address === 'string') {
392
+ server.close();
393
+ throw new Error('studio: 无法确定监听端口');
394
+ }
395
+ const origin = `http://${host}:${address.port}`;
396
+ let closed = false;
397
+ return {
398
+ origin,
399
+ url: `${origin}/?token=${encodeURIComponent(token)}`,
400
+ token,
401
+ server,
402
+ close: async () => {
403
+ if (closed)
404
+ return;
405
+ closed = true;
406
+ await new Promise((resolve) => {
407
+ server.closeIdleConnections?.();
408
+ server.closeAllConnections?.();
409
+ server.close(() => resolve());
410
+ });
411
+ await db?.close();
412
+ },
413
+ };
414
+ }
415
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/studio/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,156 @@
1
+ import { z } from 'zod';
2
+ import { RowValidationError } from './errors.js';
3
+ /** SQL 片段(用于列默认值,如 gen_random_uuid())。不是可执行查询 */
4
+ export interface SqlFragment {
5
+ readonly _tag: 'sql';
6
+ readonly strings: readonly string[];
7
+ readonly params: readonly unknown[];
8
+ }
9
+ export declare function sql(strings: TemplateStringsArray, ...params: unknown[]): SqlFragment;
10
+ export declare const isSqlFragment: (v: unknown) => v is SqlFragment;
11
+ export declare const snakeCase: (s: string) => string;
12
+ export type ColumnRef = {
13
+ readonly thunk: () => ColumnBuilder<any, any, boolean, boolean>;
14
+ readonly onDelete?: 'cascade' | 'restrict' | 'set null' | 'no action' | 'set default';
15
+ };
16
+ export declare class ColumnBuilder<TOut = unknown, TIn = TOut, TNullable extends boolean = false, THasDefault extends boolean = false> {
17
+ readonly schema: z.ZodType<TOut, TIn>;
18
+ readonly sqlType: string;
19
+ readonly column: string | undefined;
20
+ readonly nullableFlag: boolean;
21
+ readonly defaultFlag: boolean;
22
+ readonly pkFlag: boolean;
23
+ readonly defaultValue: unknown;
24
+ readonly uniqueFlag: boolean;
25
+ readonly ref: ColumnRef | undefined;
26
+ readonly enumDef: EnumDef | undefined;
27
+ readonly _phantom: {
28
+ out: TOut;
29
+ in: TIn;
30
+ nullable: TNullable;
31
+ hasDefault: THasDefault;
32
+ };
33
+ /** 由 table() 盖章,供 .references(() => other.id) 反查表名/列名 */
34
+ _owner: {
35
+ table: Table;
36
+ outKey: string;
37
+ } | undefined;
38
+ constructor(schema: z.ZodType<TOut, TIn>, sqlType: string, column?: string | undefined, nullableFlag?: boolean, defaultFlag?: boolean, pkFlag?: boolean, defaultValue?: unknown, uniqueFlag?: boolean, ref?: ColumnRef | undefined, enumDef?: EnumDef | undefined);
39
+ /** 覆盖 DB 列名(默认 camelCase → snake_case) */
40
+ as(column: string): ColumnBuilder<TOut, TIn, TNullable, THasDefault>;
41
+ nullable(): ColumnBuilder<TOut, TIn, true, THasDefault>;
42
+ pk(): ColumnBuilder<TOut, TIn, TNullable, THasDefault>;
43
+ default(v: SqlFragment | TIn): ColumnBuilder<TOut, TIn, TNullable, true>;
44
+ /** 单列唯一约束(PG 自动命名 {table}_{col}_key) */
45
+ unique(): ColumnBuilder<TOut, TIn, TNullable, THasDefault>;
46
+ /** 外键;目标列必须来自 table() 定义(延迟解析,支持前向引用) */
47
+ references(target: () => ColumnBuilder<any, any, boolean, boolean>, opts?: {
48
+ onDelete?: ColumnRef['onDelete'];
49
+ }): ColumnBuilder<TOut, TIn, TNullable, THasDefault>;
50
+ }
51
+ export interface EnumDef {
52
+ readonly name: string;
53
+ readonly values: readonly string[];
54
+ }
55
+ export interface IndexPlan {
56
+ readonly name: string;
57
+ readonly columns: readonly string[];
58
+ readonly unique: boolean;
59
+ }
60
+ export interface CheckPlan {
61
+ readonly name: string;
62
+ readonly expression: string;
63
+ }
64
+ export type ColumnMap = Record<string, ColumnBuilder<any, any, boolean, boolean>>;
65
+ type ColOut<C> = C extends ColumnBuilder<infer O, any, infer N, any> ? (N extends true ? O | null : O) : never;
66
+ type ColIn<C> = C extends ColumnBuilder<any, infer I, infer N, any> ? (N extends true ? I | null : I) : never;
67
+ type ColOptionalOnInsert<C> = C extends ColumnBuilder<any, any, infer N, infer D> ? N extends true ? true : D extends true ? true : false : false;
68
+ export type Simplify<T> = {
69
+ [K in keyof T]: T[K];
70
+ };
71
+ export interface ColumnPlan {
72
+ readonly outKey: string;
73
+ readonly dbKey: string;
74
+ readonly nullable: boolean;
75
+ readonly parse: z.ZodType;
76
+ readonly sqlType: string;
77
+ readonly pk: boolean;
78
+ readonly unique: boolean;
79
+ readonly defaultValue: unknown;
80
+ readonly ref: ColumnRef | undefined;
81
+ readonly enum: EnumDef | undefined;
82
+ }
83
+ export type FastMapper = (row: Record<string, unknown>) => Record<string, unknown>;
84
+ export interface Table<C extends ColumnMap = ColumnMap> {
85
+ readonly _tag: 'table';
86
+ readonly name: string;
87
+ readonly columns: C;
88
+ readonly __plan: readonly ColumnPlan[];
89
+ /** 表级复合主键的 DB 列名;单列 PK 使用 ColumnPlan.pk */
90
+ readonly __primaryKey: readonly string[];
91
+ readonly insertSchema: z.ZodTypeAny;
92
+ readonly updateSchema: z.ZodTypeAny;
93
+ /** 生成的映射器:只碰已知列,无通用遍历(读热路径) */
94
+ readonly __mapFast: FastMapper;
95
+ /** 生成的映射器 + 每列 zod 校验 */
96
+ readonly __mapValid: (row: Record<string, unknown>, index: number) => Record<string, unknown>;
97
+ /** 复合唯一约束的 DB 列名分组(单列唯一用列上的 .unique()) */
98
+ readonly __uniques: readonly (readonly string[])[];
99
+ readonly __indexes: readonly IndexPlan[];
100
+ readonly __checks: readonly CheckPlan[];
101
+ }
102
+ /**
103
+ * 生成按表定制的映射函数:字面量 key → 单态对象形状,避免通用遍历/动态查表。
104
+ * key 来自开发者写的 schema,JSON.stringify 转义后内联,不接受用户输入。
105
+ */
106
+ export declare function compilePlanMappers(name: string, plan: readonly ColumnPlan[]): {
107
+ fast: FastMapper;
108
+ valid: (row: Record<string, unknown>, index: number, parsers: z.ZodType[], tableName: string, Err: typeof RowValidationError) => Record<string, unknown>;
109
+ };
110
+ export type RowOf<T> = T extends Table<infer C> ? Simplify<{
111
+ [K in keyof C]: ColOut<C[K]>;
112
+ }> : never;
113
+ export type InputRowOf<T> = T extends Table<infer C> ? Simplify<{
114
+ [K in keyof C]: ColIn<C[K]>;
115
+ }> : never;
116
+ export type InsertOf<T> = T extends Table<infer C> ? Simplify<{
117
+ [K in keyof C as ColOptionalOnInsert<C[K]> extends true ? never : K]: ColIn<C[K]>;
118
+ } & {
119
+ [K in keyof C as ColOptionalOnInsert<C[K]> extends true ? K : never]?: ColIn<C[K]>;
120
+ }> : never;
121
+ export type UpdateOf<T> = T extends Table ? Partial<InputRowOf<T>> : never;
122
+ export interface TableOptions<C extends ColumnMap> {
123
+ /** 复合主键(至少 2 列);单列主键请用 ColumnBuilder.pk() */
124
+ primaryKey?: readonly (keyof C & string)[];
125
+ unique?: (keyof C & string)[][];
126
+ indexes?: readonly {
127
+ columns: readonly (keyof C & string)[];
128
+ name?: string;
129
+ unique?: boolean;
130
+ }[];
131
+ checks?: Readonly<Record<string, string>>;
132
+ }
133
+ export declare function table<C extends ColumnMap>(name: string, columns: C, opts?: TableOptions<C>): Table<C>;
134
+ export declare const pg: {
135
+ uuid: () => ColumnBuilder<string, string, false, false>;
136
+ text: () => ColumnBuilder<string, string, false, false>;
137
+ varchar: (length?: number) => ColumnBuilder<string, string, false, false>;
138
+ int: () => ColumnBuilder<number, number, false, false>;
139
+ /** postgres.js 把 int8 以字符串返回(避免精度丢失),这里转成 bigint;入参两种都收 */
140
+ bigint: () => ColumnBuilder<bigint, string | bigint, false, false>;
141
+ /** numeric 由 postgres.js 以字符串返回,避免精度丢失 */
142
+ numeric: () => ColumnBuilder<string, string, false, false>;
143
+ bool: () => ColumnBuilder<boolean, boolean, false, false>;
144
+ /** 只提供 timestamptz:timestamp(no tz) 是时区事故源头 */
145
+ timestamptz: () => ColumnBuilder<Date, string | Date, false, false>;
146
+ /** postgres.js 把 date 解析成 Date(UTC 零点),对外统一成 YYYY-MM-DD 字符串,避免时区歧义 */
147
+ date: () => ColumnBuilder<string, string | Date, false, false>;
148
+ jsonb: <S extends z.ZodType>(schema: S) => ColumnBuilder<z.output<S>, z.input<S>, false, false>;
149
+ /** 数组:pg.array(pg.text()) → text[] */
150
+ array: <C extends ColumnBuilder<any, any, boolean, boolean>>(item: C) => ColumnBuilder<z.output<C['schema']>[], z.input<C['schema']>[], false, false>;
151
+ bytea: () => ColumnBuilder<Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>, false, false>;
152
+ /** PG enum:type 名 + 值列表;建类型由 createSchema/diffSchema 负责 */
153
+ enum: <const V extends readonly [string, ...string[]]>(enumName: string, values: V) => ColumnBuilder<V[number], V[number], false, false>;
154
+ };
155
+ export {};
156
+ //# sourceMappingURL=table.d.ts.map