admindb 2.4.0 → 2.5.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 (135) hide show
  1. package/LICENSE +20 -20
  2. package/dist/app.js +36 -25
  3. package/dist/core/context.d.ts +1 -0
  4. package/dist/core/context.js +2 -0
  5. package/dist/core/errors.d.ts +1 -0
  6. package/dist/core/errors.js +39 -0
  7. package/dist/core/index.d.ts +1 -0
  8. package/dist/core/index.js +20 -0
  9. package/dist/core/result.d.ts +1 -0
  10. package/dist/core/result.js +10 -0
  11. package/dist/core/router.d.ts +1 -0
  12. package/dist/core/router.js +37 -0
  13. package/dist/data/chain.js +1 -1
  14. package/dist/data/engine.js +1 -1
  15. package/dist/db/database.d.ts +1 -1
  16. package/dist/db/database.js +9 -31
  17. package/dist/db/dialects/index.d.ts +1 -0
  18. package/dist/db/dialects/index.js +58 -0
  19. package/dist/db/dialects/postgres/ddl.d.ts +1 -0
  20. package/dist/db/dialects/postgres/ddl.js +107 -0
  21. package/dist/db/dialects/postgres/dialect.d.ts +1 -0
  22. package/dist/db/dialects/postgres/dialect.js +28 -0
  23. package/dist/db/dialects/postgres/introspector.d.ts +1 -0
  24. package/dist/db/dialects/postgres/introspector.js +265 -0
  25. package/dist/db/dialects/postgres/types.d.ts +1 -0
  26. package/dist/db/dialects/postgres/types.js +83 -0
  27. package/dist/db/dialects/sqlite/ddl.d.ts +1 -0
  28. package/dist/db/dialects/sqlite/ddl.js +244 -0
  29. package/dist/db/dialects/sqlite/dialect.d.ts +1 -0
  30. package/dist/db/dialects/sqlite/dialect.js +25 -0
  31. package/dist/db/dialects/sqlite/introspector.d.ts +1 -0
  32. package/dist/db/dialects/sqlite/introspector.js +214 -0
  33. package/dist/db/dialects/sqlite/types.d.ts +1 -0
  34. package/dist/db/dialects/sqlite/types.js +69 -0
  35. package/dist/db/dialects/types.d.ts +1 -0
  36. package/dist/db/dialects/types.js +15 -0
  37. package/dist/db/export.js +1 -1
  38. package/dist/db/index.d.ts +1 -1
  39. package/dist/db/index.js +1 -1
  40. package/dist/db/manager.d.ts +1 -1
  41. package/dist/db/manager.js +101 -21
  42. package/dist/db/postgres.d.ts +1 -1
  43. package/dist/db/postgres.js +20 -284
  44. package/dist/db/types.d.ts +1 -1
  45. package/dist/db/types.js +0 -4
  46. package/dist/index.d.ts +1 -1
  47. package/dist/index.js +4 -1
  48. package/dist/modules/databases/databases.routes.d.ts +1 -0
  49. package/dist/modules/databases/databases.routes.js +150 -0
  50. package/dist/modules/databases/databases.service.d.ts +1 -0
  51. package/dist/modules/databases/databases.service.js +134 -0
  52. package/dist/modules/databases/index.d.ts +1 -0
  53. package/dist/{routes → modules/databases}/index.js +2 -3
  54. package/dist/modules/erd/erd.routes.d.ts +1 -0
  55. package/dist/modules/erd/erd.routes.js +32 -0
  56. package/dist/modules/erd/erd.service.d.ts +1 -0
  57. package/dist/modules/erd/erd.service.js +39 -0
  58. package/dist/modules/erd/index.d.ts +1 -0
  59. package/dist/modules/erd/index.js +18 -0
  60. package/dist/modules/index.d.ts +1 -0
  61. package/dist/modules/index.js +62 -0
  62. package/dist/modules/query/index.d.ts +1 -0
  63. package/dist/modules/query/index.js +18 -0
  64. package/dist/modules/query/query.routes.d.ts +1 -0
  65. package/dist/modules/query/query.routes.js +54 -0
  66. package/dist/modules/query/query.service.d.ts +1 -0
  67. package/dist/modules/query/query.service.js +95 -0
  68. package/dist/modules/rows/blob.helper.d.ts +1 -0
  69. package/dist/modules/rows/blob.helper.js +40 -0
  70. package/dist/modules/rows/display.helper.d.ts +1 -0
  71. package/dist/modules/rows/display.helper.js +73 -0
  72. package/dist/modules/rows/index.d.ts +1 -0
  73. package/dist/modules/rows/index.js +20 -0
  74. package/dist/modules/rows/rows.routes.d.ts +1 -0
  75. package/dist/modules/rows/rows.routes.js +555 -0
  76. package/dist/modules/rows/rows.service.d.ts +1 -0
  77. package/dist/modules/rows/rows.service.js +433 -0
  78. package/dist/modules/schema/index.d.ts +1 -0
  79. package/dist/modules/schema/index.js +18 -0
  80. package/dist/modules/schema/schema.routes.d.ts +1 -0
  81. package/dist/modules/schema/schema.routes.js +171 -0
  82. package/dist/modules/schema/schema.service.d.ts +1 -0
  83. package/dist/modules/schema/schema.service.js +58 -0
  84. package/dist/modules/seed/index.d.ts +1 -0
  85. package/dist/modules/seed/index.js +18 -0
  86. package/dist/modules/seed/seed.routes.d.ts +1 -0
  87. package/dist/modules/seed/seed.routes.js +212 -0
  88. package/dist/modules/seed/seed.service.d.ts +1 -0
  89. package/dist/{routes/api/helpers.js → modules/seed/seed.service.js} +86 -109
  90. package/dist/modules/tables/index.d.ts +1 -0
  91. package/dist/modules/tables/index.js +18 -0
  92. package/dist/modules/tables/tables.routes.d.ts +1 -0
  93. package/dist/modules/tables/tables.routes.js +194 -0
  94. package/dist/modules/tables/tables.service.d.ts +1 -0
  95. package/dist/modules/tables/tables.service.js +218 -0
  96. package/dist/public/js/browse.js +1 -1
  97. package/dist/public/js/query.js +1 -1
  98. package/dist/types/api.d.ts +1 -1
  99. package/dist/utils/common.d.ts +1 -1
  100. package/dist/utils/common.js +1 -3
  101. package/dist/utils/stream.d.ts +1 -0
  102. package/dist/utils/stream.js +131 -0
  103. package/dist/views/pages/error.hbs +10 -1
  104. package/dist/views/pages/home.hbs +1 -1
  105. package/dist/views/pages/query.hbs +1 -1
  106. package/dist/views/pages/seed-select.hbs +1 -252
  107. package/dist/views/pages/seed.hbs +1 -307
  108. package/dist/views/pages/table.hbs +1 -1
  109. package/dist/views/partials/sidebar.hbs +1 -1
  110. package/docs/API.md +4 -17
  111. package/docs/EXAMPLES.md +579 -579
  112. package/docs/SECURITY.md +265 -265
  113. package/package.json +4 -2
  114. package/dist/db/introspection.d.ts +0 -1
  115. package/dist/db/introspection.js +0 -164
  116. package/dist/routes/api/erd.d.ts +0 -1
  117. package/dist/routes/api/erd.js +0 -45
  118. package/dist/routes/api/helpers.d.ts +0 -1
  119. package/dist/routes/api/import-export.d.ts +0 -1
  120. package/dist/routes/api/import-export.js +0 -84
  121. package/dist/routes/api/index.d.ts +0 -1
  122. package/dist/routes/api/index.js +0 -55
  123. package/dist/routes/api/query.d.ts +0 -1
  124. package/dist/routes/api/query.js +0 -77
  125. package/dist/routes/api/rows.d.ts +0 -1
  126. package/dist/routes/api/rows.js +0 -373
  127. package/dist/routes/api/seed.d.ts +0 -1
  128. package/dist/routes/api/seed.js +0 -180
  129. package/dist/routes/api/tables.d.ts +0 -1
  130. package/dist/routes/api/tables.js +0 -230
  131. package/dist/routes/databases.d.ts +0 -1
  132. package/dist/routes/databases.js +0 -212
  133. package/dist/routes/index.d.ts +0 -1
  134. package/dist/routes/pages.d.ts +0 -1
  135. package/dist/routes/pages.js +0 -540
@@ -1,373 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerRowRoutes = registerRowRoutes;
4
- const common_1 = require("../../utils/common");
5
- const datatype_1 = require("../../utils/datatype");
6
- const csv_1 = require("../../utils/csv");
7
- const generator_1 = require("../../sql/generator");
8
- const helpers_1 = require("./helpers");
9
- function registerRowRoutes(router, ctx) {
10
- router.get('/api/tables/:db/:table/rows', (0, helpers_1.wrap)(async (req, res) => {
11
- const db = ctx.getDb(req);
12
- const page = Number.parseInt(String(req.query.page ?? '1'), 10);
13
- const limit = Number.parseInt(String(req.query.limit ?? '50'), 10);
14
- const orderBy = req.query.orderBy ? String(req.query.orderBy) : undefined;
15
- const orderDir = req.query.orderDir === 'desc' ? 'desc' : 'asc';
16
- const filters = (0, common_1.parseFilters)(req.query.f);
17
- const [rowsR, totalR] = await Promise.all([
18
- db.getRows(req.params.table, { page, limit, orderBy, orderDir, filters }),
19
- db.getRowCount(req.params.table, filters),
20
- ]);
21
- if (!rowsR.success)
22
- return (0, helpers_1.fail)(res, rowsR.error ?? 'Failed to load rows.');
23
- const rows = (rowsR.data ?? []).map(common_1.normalizeRow);
24
- (0, helpers_1.ok)(res, {
25
- rows,
26
- total: totalR.success ? totalR.data : rows.length,
27
- page,
28
- limit,
29
- });
30
- }));
31
- router.get('/api/tables/:db/:table/rows/count', (0, helpers_1.wrap)(async (req, res) => {
32
- const db = ctx.getDb(req);
33
- const filters = (0, common_1.parseFilters)(req.query.f);
34
- const r = await db.getRowCount(req.params.table, filters);
35
- if (!r.success)
36
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to count rows.');
37
- (0, helpers_1.ok)(res, { count: r.data });
38
- }));
39
- router.get('/api/tables/:db/:table/row/:id', (0, helpers_1.wrap)(async (req, res) => {
40
- const db = ctx.getDb(req);
41
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
42
- if (!info)
43
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
44
- const where = (0, helpers_1.pkWhere)(info, req.params.id);
45
- if (!where)
46
- return (0, helpers_1.fail)(res, 'Invalid primary key.', 400);
47
- const r = await db.getRow(req.params.table, where);
48
- if (!r.success)
49
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to load row.');
50
- if (!r.data)
51
- return (0, helpers_1.fail)(res, 'Row not found.', 404);
52
- (0, helpers_1.ok)(res, (0, common_1.normalizeRow)(r.data));
53
- }));
54
- router.get('/api/tables/:db/:table/row/:id/blob/:column', (0, helpers_1.wrap)(async (req, res) => {
55
- const db = ctx.getDb(req);
56
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
57
- if (!info)
58
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
59
- const where = (0, helpers_1.pkWhere)(info, req.params.id);
60
- if (!where)
61
- return (0, helpers_1.fail)(res, 'Invalid primary key.', 400);
62
- const r = await db.getRow(req.params.table, where);
63
- if (!r.success)
64
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to load row.');
65
- if (!r.data)
66
- return (0, helpers_1.fail)(res, 'Row not found.', 404);
67
- const colName = req.params.column;
68
- const rawVal = r.data[colName];
69
- if (rawVal === null || rawVal === undefined) {
70
- return (0, helpers_1.fail)(res, 'Column value is NULL.', 404);
71
- }
72
- let buf;
73
- if (Buffer.isBuffer(rawVal) || rawVal instanceof Uint8Array) {
74
- buf = Buffer.isBuffer(rawVal) ? rawVal : Buffer.from(rawVal);
75
- }
76
- else if (typeof rawVal === 'string' && (/^0x[0-9a-f]*$/i.test(rawVal))) {
77
- buf = Buffer.from(rawVal.slice(2), 'hex');
78
- }
79
- else {
80
- buf = Buffer.from(String(rawVal), 'utf8');
81
- }
82
- const mimeInfo = (0, datatype_1.sniffMimeType)(buf);
83
- res.setHeader('Content-Type', mimeInfo.mime);
84
- res.setHeader('Content-Length', buf.length);
85
- res.setHeader('Cache-Control', 'no-cache');
86
- if (req.query.download === '1' || req.query.download === 'true') {
87
- const filename = `${req.params.table}_${colName}_${req.params.id}.${mimeInfo.ext}`;
88
- res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
89
- }
90
- res.end(buf);
91
- }));
92
- router.get('/api/tables/:db/:table/row/:id/blob/:column/meta', (0, helpers_1.wrap)(async (req, res) => {
93
- const db = ctx.getDb(req);
94
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
95
- if (!info)
96
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
97
- const where = (0, helpers_1.pkWhere)(info, req.params.id);
98
- if (!where)
99
- return (0, helpers_1.fail)(res, 'Invalid primary key.', 400);
100
- const r = await db.getRow(req.params.table, where);
101
- if (!r.success)
102
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to load row.');
103
- if (!r.data)
104
- return (0, helpers_1.fail)(res, 'Row not found.', 404);
105
- const colName = req.params.column;
106
- const rawVal = r.data[colName];
107
- if (rawVal === null || rawVal === undefined) {
108
- return (0, helpers_1.ok)(res, { isNull: true, size: 0, sizeFormatted: '0 B' });
109
- }
110
- const meta = (0, datatype_1.analyzeBlob)(rawVal);
111
- (0, helpers_1.ok)(res, { isNull: false, ...meta });
112
- }));
113
- router.put('/api/tables/:db/:table/row/:id/blob/:column', (0, helpers_1.wrap)(async (req, res) => {
114
- const db = ctx.getDb(req);
115
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
116
- if (!info)
117
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
118
- const where = (0, helpers_1.pkWhere)(info, req.params.id);
119
- if (!where)
120
- return (0, helpers_1.fail)(res, 'Invalid primary key.', 400);
121
- const colName = req.params.column;
122
- let buf;
123
- if (req.body?.data !== undefined) {
124
- const format = req.body.format || 'base64';
125
- if (format === 'base64') {
126
- const base64Str = String(req.body.data).replace(/^data:[^;]+;base64,/, '');
127
- buf = Buffer.from(base64Str, 'base64');
128
- }
129
- else if (format === 'hex') {
130
- const hexStr = String(req.body.data).replace(/^0x/i, '');
131
- buf = Buffer.from(hexStr, 'hex');
132
- }
133
- else {
134
- buf = Buffer.from(String(req.body.data), 'utf8');
135
- }
136
- }
137
- else {
138
- return (0, helpers_1.fail)(res, 'Payload data is required.');
139
- }
140
- const updateRes = await db.updateRow(req.params.table, [{ column: colName, value: buf }], where);
141
- if (!updateRes.success)
142
- return (0, helpers_1.fail)(res, updateRes.error ?? 'Failed to update BLOB.');
143
- (0, helpers_1.ok)(res, { message: `Updated BLOB in column "${colName}".`, size: buf.length });
144
- }));
145
- router.post('/api/tables/:db/:table/rows/generate', (0, helpers_1.wrap)(async (req, res) => {
146
- const db = ctx.getDb(req);
147
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
148
- if (!info)
149
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
150
- const fields = (0, helpers_1.buildFields)(info, req.body?.values ?? req.body ?? {});
151
- if (!fields.length)
152
- return (0, helpers_1.fail)(res, 'No valid column values provided.');
153
- (0, helpers_1.ok)(res, { sql: (0, generator_1.generateInsert)(req.params.table, fields) });
154
- }));
155
- const generateUpdateHandler = (0, helpers_1.wrap)(async (req, res) => {
156
- const db = ctx.getDb(req);
157
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
158
- if (!info)
159
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
160
- const id = req.params.id || (req.query.id ? String(req.query.id) : null);
161
- if (!id)
162
- return (0, helpers_1.fail)(res, 'Primary key id is required.');
163
- const where = (0, helpers_1.pkWhere)(info, id);
164
- if (!where)
165
- return (0, helpers_1.fail)(res, 'Invalid primary key.', 400);
166
- const nulls = Array.isArray(req.body?.nulls) ? req.body.nulls : [];
167
- const fields = (0, helpers_1.buildUpdateFields)(info, req.body?.values ?? req.body ?? {}, nulls);
168
- if (!fields.length)
169
- return (0, helpers_1.fail)(res, 'No fields to update.');
170
- (0, helpers_1.ok)(res, { sql: (0, generator_1.generateUpdate)(req.params.table, fields, where) });
171
- });
172
- router.put('/api/tables/:db/:table/row/:id/generate', generateUpdateHandler);
173
- router.post('/api/tables/:db/:table/row/:id/generate', generateUpdateHandler);
174
- router.put('/api/tables/:db/:table/rows/generate', generateUpdateHandler);
175
- router.post('/api/tables/:db/:table/rows', (0, helpers_1.wrap)(async (req, res) => {
176
- const db = ctx.getDb(req);
177
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
178
- if (!info)
179
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
180
- const isBatch = Array.isArray(req.body?.rows);
181
- const rowList = isBatch
182
- ? req.body.rows
183
- : [req.body?.values ?? req.body ?? {}];
184
- if (!rowList.length)
185
- return (0, helpers_1.fail)(res, 'No rows provided.');
186
- const fieldsList = rowList.map((row) => (0, helpers_1.buildFields)(info, row));
187
- if (!isBatch) {
188
- const fields = fieldsList[0];
189
- if (!fields.length)
190
- return (0, helpers_1.fail)(res, 'No valid column values provided.');
191
- const r = await db.insertRow(req.params.table, fields);
192
- if (!r.success)
193
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to insert row.');
194
- return (0, helpers_1.ok)(res, { message: 'Row inserted.', id: r.data?.lastInsertRowid }, 201);
195
- }
196
- const r = await db.insertRows(req.params.table, fieldsList);
197
- if (!r.success)
198
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to insert rows.');
199
- (0, helpers_1.ok)(res, { message: `${r.data?.inserted ?? 0} row(s) inserted.`, inserted: r.data?.inserted }, 201);
200
- }));
201
- const updateSingleRowHandler = (0, helpers_1.wrap)(async (req, res) => {
202
- const db = ctx.getDb(req);
203
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
204
- if (!info)
205
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
206
- const id = req.params.id || (req.query.id ? String(req.query.id) : null);
207
- if (!id)
208
- return (0, helpers_1.fail)(res, 'Primary key id is required.');
209
- const where = (0, helpers_1.pkWhere)(info, id);
210
- if (!where)
211
- return (0, helpers_1.fail)(res, 'Invalid primary key.');
212
- const nulls = Array.isArray(req.body?.nulls) ? req.body.nulls : [];
213
- const fields = (0, helpers_1.buildUpdateFields)(info, req.body?.values ?? req.body ?? {}, nulls);
214
- if (!fields.length)
215
- return (0, helpers_1.fail)(res, 'No fields to update.');
216
- const r = await db.updateRow(req.params.table, fields, where);
217
- if (!r.success)
218
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to update row.');
219
- (0, helpers_1.ok)(res, { message: 'Row updated.' });
220
- });
221
- const bulkUpdateHandler = (0, helpers_1.wrap)(async (req, res) => {
222
- const db = ctx.getDb(req);
223
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
224
- if (!info)
225
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
226
- if (Array.isArray(req.body?.updates)) {
227
- const updates = req.body.updates;
228
- if (!updates.length)
229
- return (0, helpers_1.fail)(res, 'No updates provided.');
230
- if (updates.length > helpers_1.MAX_BULK_ROWS)
231
- return (0, helpers_1.fail)(res, `Cannot update more than ${helpers_1.MAX_BULK_ROWS} rows at once.`);
232
- const rowUpdates = [];
233
- for (const u of updates) {
234
- if (!u.id)
235
- return (0, helpers_1.fail)(res, 'Every update requires an id.');
236
- const where = (0, helpers_1.pkWhere)(info, String(u.id));
237
- if (!where)
238
- return (0, helpers_1.fail)(res, `Invalid primary key: "${u.id}".`);
239
- const nulls = Array.isArray(u.nulls) ? u.nulls.map(String) : [];
240
- const fields = (0, helpers_1.buildUpdateFields)(info, u.values ?? {}, nulls);
241
- if (fields.length)
242
- rowUpdates.push({ fields, where });
243
- }
244
- if (!rowUpdates.length)
245
- return (0, helpers_1.ok)(res, { message: 'No changes to apply.', updated: 0 });
246
- const r = await db.updateRows(req.params.table, rowUpdates);
247
- if (!r.success)
248
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to update rows.');
249
- return (0, helpers_1.ok)(res, { message: `${r.data?.updated ?? 0} row(s) updated.`, updated: r.data?.updated });
250
- }
251
- return updateSingleRowHandler(req, res);
252
- });
253
- router.put('/api/tables/:db/:table/row/:id', updateSingleRowHandler);
254
- router.put('/api/tables/:db/:table/rows', bulkUpdateHandler);
255
- router.post('/api/tables/:db/:table/rows/bulk-update', bulkUpdateHandler);
256
- const deleteSingleRowHandler = (0, helpers_1.wrap)(async (req, res) => {
257
- const db = ctx.getDb(req);
258
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
259
- if (!info)
260
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
261
- const id = req.params.id || (req.query.id ? String(req.query.id) : null);
262
- if (!id)
263
- return (0, helpers_1.fail)(res, 'Primary key id is required.');
264
- const where = (0, helpers_1.pkWhere)(info, id);
265
- if (!where)
266
- return (0, helpers_1.fail)(res, 'Invalid primary key.');
267
- const r = await db.deleteRow(req.params.table, where);
268
- if (!r.success)
269
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to delete row.');
270
- (0, helpers_1.ok)(res, { message: 'Row deleted.' });
271
- });
272
- router.delete('/api/tables/:db/:table/row/:id', deleteSingleRowHandler);
273
- router.delete('/api/tables/:db/:table/rows', deleteSingleRowHandler);
274
- router.get('/api/tables/:db/:table/rows/:id/references', (0, helpers_1.wrap)(async (req, res) => {
275
- const db = ctx.getDb(req);
276
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
277
- if (!info)
278
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
279
- const where = (0, helpers_1.pkWhere)(info, req.params.id);
280
- if (!where)
281
- return (0, helpers_1.fail)(res, 'Invalid primary key.', 400);
282
- const rowR = await db.getRow(req.params.table, where);
283
- if (!rowR.success || !rowR.data)
284
- return (0, helpers_1.fail)(res, 'Row not found.', 404);
285
- const refInfoR = await db.getReferencingTables(req.params.table);
286
- const referencing = refInfoR.data ?? [];
287
- const results = [];
288
- for (const item of referencing) {
289
- for (const ref of item.refs) {
290
- const targetCol = ref.to || info.primaryKey[0];
291
- if (!targetCol)
292
- continue;
293
- const val = rowR.data[targetCol];
294
- if (val == null)
295
- continue;
296
- const fkR = await db.getRowsByFk(item.table, ref.from, val);
297
- if (fkR.success && fkR.data) {
298
- const rows = fkR.data.rows.map(common_1.normalizeRow);
299
- results.push({
300
- table: item.table,
301
- from: ref.from,
302
- to: targetCol,
303
- value: val,
304
- columns: rows.length > 0 ? Object.keys(rows[0]) : [],
305
- rows,
306
- count: fkR.data.total,
307
- total: fkR.data.total,
308
- });
309
- }
310
- }
311
- }
312
- (0, helpers_1.ok)(res, { references: results });
313
- }));
314
- router.post('/api/tables/:db/:table/rows/bulk-delete', (0, helpers_1.wrap)(async (req, res) => {
315
- const db = ctx.getDb(req);
316
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
317
- if (!info)
318
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
319
- const ids = (req.body?.ids ?? []);
320
- if (!Array.isArray(ids) || !ids.length)
321
- return (0, helpers_1.fail)(res, 'No row IDs provided.');
322
- if (ids.length > helpers_1.MAX_BULK_ROWS)
323
- return (0, helpers_1.fail)(res, `Cannot delete more than ${helpers_1.MAX_BULK_ROWS} rows at once.`);
324
- const wheres = (0, helpers_1.resolvePkRows)(info, ids);
325
- if (!wheres)
326
- return (0, helpers_1.fail)(res, 'Invalid or unresolvable row IDs.');
327
- const r = await db.deleteRows(req.params.table, wheres);
328
- if (!r.success)
329
- return (0, helpers_1.fail)(res, r.error ?? 'Failed to delete rows.');
330
- (0, helpers_1.ok)(res, { message: `${r.data?.deleted ?? 0} row(s) deleted.`, deleted: r.data?.deleted });
331
- }));
332
- router.post('/api/tables/:db/:table/rows/bulk-impact', (0, helpers_1.wrap)(async (req, res) => {
333
- const db = ctx.getDb(req);
334
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
335
- if (!info)
336
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
337
- const ids = (req.body?.ids ?? []);
338
- if (!Array.isArray(ids) || !ids.length)
339
- return (0, helpers_1.ok)(res, { references: [], total: 0 });
340
- const wheres = (0, helpers_1.resolvePkRows)(info, ids);
341
- if (!wheres)
342
- return (0, helpers_1.ok)(res, { references: [], total: 0 });
343
- (0, helpers_1.ok)(res, await (0, helpers_1.computeBulkImpact)(db, info, wheres));
344
- }));
345
- router.post('/api/tables/:db/:table/rows/bulk-export', (0, helpers_1.wrap)(async (req, res) => {
346
- const db = ctx.getDb(req);
347
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
348
- if (!info)
349
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
350
- const ids = (req.body?.ids ?? []);
351
- if (!Array.isArray(ids) || !ids.length)
352
- return (0, helpers_1.fail)(res, 'No row IDs provided.');
353
- if (ids.length > helpers_1.MAX_BULK_ROWS)
354
- return (0, helpers_1.fail)(res, `Cannot export more than ${helpers_1.MAX_BULK_ROWS} rows at once.`);
355
- const wheres = (0, helpers_1.resolvePkRows)(info, ids);
356
- if (!wheres)
357
- return (0, helpers_1.fail)(res, 'Invalid or unresolvable row IDs.');
358
- const format = String(req.body?.format ?? 'csv').toLowerCase();
359
- const rowsR = await db.getRowsByPks(req.params.table, wheres);
360
- if (!rowsR.success)
361
- return (0, helpers_1.fail)(res, rowsR.error ?? 'Failed to load rows.');
362
- const rows = (rowsR.data ?? []).map(common_1.normalizeRow);
363
- const columns = info.columns.map((c) => c.name);
364
- if (format === 'json') {
365
- res.setHeader('Content-Type', 'application/json; charset=utf-8');
366
- res.setHeader('Content-Disposition', `attachment; filename="${req.params.table}_selected.json"`);
367
- return res.send((0, csv_1.toJson)(rows));
368
- }
369
- res.setHeader('Content-Type', 'text/csv; charset=utf-8');
370
- res.setHeader('Content-Disposition', `attachment; filename="${req.params.table}_selected.csv"`);
371
- res.send((0, csv_1.toCsv)(rows, columns));
372
- }));
373
- }
@@ -1 +0,0 @@
1
- import type {Router} from 'express';import{type ApiContext} from './helpers';export declare function registerSeedRoutes(router:Router,ctx:ApiContext):void;
@@ -1,180 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerSeedRoutes = registerSeedRoutes;
4
- const generator_1 = require("../../sql/generator");
5
- const index_1 = require("../../data/index");
6
- const helpers_1 = require("./helpers");
7
- function registerSeedRoutes(router, ctx) {
8
- router.post('/api/seed/:db/validate', (0, helpers_1.wrap)(async (req, res) => {
9
- const db = ctx.getDb(req);
10
- (0, helpers_1.ok)(res, await (0, index_1.validateGenerationPlan)(db, (0, helpers_1.parseUnifiedGenerationPlan)(req.body)));
11
- }));
12
- router.post('/api/seed/:db/preview', (0, helpers_1.wrap)(async (req, res) => {
13
- const db = ctx.getDb(req);
14
- (0, helpers_1.ok)(res, await index_1.SeedEngine.executePlan(db, (0, helpers_1.parseUnifiedGenerationPlan)(req.body), { previewLimit: 50 }));
15
- }));
16
- router.post('/api/seed/:db/generate', (0, helpers_1.wrap)(async (req, res) => {
17
- const db = ctx.getDb(req);
18
- (0, helpers_1.ok)(res, await index_1.SeedEngine.executePlan(db, (0, helpers_1.parseUnifiedGenerationPlan)(req.body)));
19
- }));
20
- router.post('/api/seed/:db/execute', (0, helpers_1.wrap)(async (req, res) => {
21
- const db = ctx.getDb(req);
22
- const plan = (0, helpers_1.parseUnifiedGenerationPlan)(req.body);
23
- const truncate = Boolean(req.body?.truncate || plan.options?.truncateAll);
24
- const gen = await index_1.SeedEngine.executePlan(db, plan, { truncateAll: truncate });
25
- const exec = await (0, index_1.executeChainInsert)(db, gen, truncate);
26
- (0, helpers_1.ok)(res, {
27
- message: `${truncate ? 'Cleared tables and seeded' : 'Seeded'} ${exec.totalInserted} row(s) across ${Object.keys(exec.inserted).length} table(s) in ${exec.elapsedMs}ms.`,
28
- inserted: exec.inserted,
29
- totalInserted: exec.totalInserted,
30
- elapsedMs: exec.elapsedMs,
31
- warnings: exec.warnings,
32
- }, 201);
33
- }));
34
- const getSeedConfigHandler = (0, helpers_1.wrap)(async (req, res) => {
35
- const db = ctx.getDb(req);
36
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
37
- if (!info)
38
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
39
- (0, helpers_1.ok)(res, { table: req.params.table, columns: (0, index_1.buildColumnConfigs)(info), maxRows: index_1.MAX_SEED_ROWS });
40
- });
41
- router.get('/api/tables/:db/:table/seed/config', getSeedConfigHandler);
42
- router.get('/api/tables/:db/:table/seed/plan', getSeedConfigHandler);
43
- router.post('/api/tables/:db/:table/seed/generate', (0, helpers_1.wrap)(async (req, res) => {
44
- const db = ctx.getDb(req);
45
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
46
- if (!info)
47
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
48
- const { count, plan } = (0, helpers_1.parseSeedRequest)(req.body);
49
- const configs = (0, index_1.buildColumnConfigs)(info);
50
- const gen = await (0, index_1.generateRows)(db, info, configs, count, plan);
51
- (0, helpers_1.ok)(res, {
52
- table: req.params.table,
53
- count: gen.rows.length,
54
- sql: (0, index_1.buildSeedInsertSql)(req.params.table, gen.rows),
55
- previewRows: gen.previewRows,
56
- warnings: gen.warnings,
57
- });
58
- }));
59
- router.post('/api/tables/:db/:table/seed/preview', (0, helpers_1.wrap)(async (req, res) => {
60
- const db = ctx.getDb(req);
61
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
62
- if (!info)
63
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
64
- const { count, plan } = (0, helpers_1.parseSeedRequest)(req.body);
65
- const configs = (0, index_1.buildColumnConfigs)(info);
66
- const gen = await (0, index_1.generateRows)(db, info, configs, Math.min(50, count), plan);
67
- (0, helpers_1.ok)(res, {
68
- table: req.params.table,
69
- previewRows: gen.previewRows,
70
- warnings: gen.warnings,
71
- });
72
- }));
73
- router.post('/api/tables/:db/:table/seed', (0, helpers_1.wrap)(async (req, res) => {
74
- const db = ctx.getDb(req);
75
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
76
- if (!info)
77
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
78
- const { count, plan, truncate } = (0, helpers_1.parseSeedRequest)(req.body);
79
- const configs = (0, index_1.buildColumnConfigs)(info);
80
- const t0 = Date.now();
81
- if (truncate) {
82
- const clearRes = await db.run(`DELETE FROM ${(0, generator_1.quoteIdentifier)(req.params.table)}`);
83
- if (!clearRes.success) {
84
- return (0, helpers_1.fail)(res, clearRes.error ?? 'Failed to clear table before seeding.', 400);
85
- }
86
- }
87
- const gen = await (0, index_1.generateRows)(db, info, configs, count, plan, truncate);
88
- const result = await db.insertRows(req.params.table, gen.rows);
89
- if (!result.success)
90
- return (0, helpers_1.fail)(res, result.error ?? 'Seed failed.', 400);
91
- const elapsedMs = Date.now() - t0;
92
- (0, helpers_1.ok)(res, {
93
- message: `${truncate ? 'Cleared table and inserted' : 'Inserted'} ${result.data?.inserted ?? 0} row(s) in ${elapsedMs}ms.`,
94
- inserted: result.data?.inserted ?? 0,
95
- skipped: result.data?.skipped ?? 0,
96
- warnings: gen.warnings,
97
- elapsedMs,
98
- }, 201);
99
- }));
100
- router.get('/api/tables/:db/:table/seed/chain', (0, helpers_1.wrap)(async (req, res) => {
101
- const db = ctx.getDb(req);
102
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
103
- if (!info)
104
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
105
- const rawScope = String(req.query.scope ?? 'chain');
106
- const scope = rawScope === 'ancestors' || rawScope === 'descendants' || rawScope === 'all' || rawScope === 'single'
107
- ? rawScope
108
- : 'chain';
109
- (0, helpers_1.ok)(res, await (0, index_1.getErChainConfig)(db, req.params.table, scope));
110
- }));
111
- router.post('/api/tables/:db/:table/seed/chain/preview', (0, helpers_1.wrap)(async (req, res) => {
112
- const db = ctx.getDb(req);
113
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
114
- if (!info)
115
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
116
- const { scope, counts, plans, modes, seed } = (0, helpers_1.parseChainSeedRequest)(req.body);
117
- const config = await (0, index_1.getErChainConfig)(db, req.params.table, scope);
118
- const previewCounts = {};
119
- for (const t of config.tables) {
120
- previewCounts[t.name] = Math.min(50, counts[t.name] ?? t.suggestedCount ?? 10);
121
- }
122
- (0, helpers_1.ok)(res, await (0, index_1.generateChainRows)(db, config, plans, previewCounts, false, modes, seed));
123
- }));
124
- router.post('/api/tables/:db/:table/seed/chain/generate', (0, helpers_1.wrap)(async (req, res) => {
125
- const db = ctx.getDb(req);
126
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
127
- if (!info)
128
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
129
- const { scope, counts, plans, modes, seed } = (0, helpers_1.parseChainSeedRequest)(req.body);
130
- const config = await (0, index_1.getErChainConfig)(db, req.params.table, scope);
131
- (0, helpers_1.ok)(res, await (0, index_1.generateChainRows)(db, config, plans, counts, false, modes, seed));
132
- }));
133
- router.post('/api/tables/:db/:table/seed/chain', (0, helpers_1.wrap)(async (req, res) => {
134
- const db = ctx.getDb(req);
135
- const info = await (0, helpers_1.requireTable)(db, req.params.table);
136
- if (!info)
137
- return (0, helpers_1.fail)(res, `Table "${req.params.table}" does not exist.`, 404);
138
- const { scope, counts, plans, truncate, modes, seed } = (0, helpers_1.parseChainSeedRequest)(req.body);
139
- const config = await (0, index_1.getErChainConfig)(db, req.params.table, scope);
140
- const gen = await (0, index_1.generateChainRows)(db, config, plans, counts, truncate, modes, seed);
141
- const exec = await (0, index_1.executeChainInsert)(db, gen, truncate);
142
- (0, helpers_1.ok)(res, {
143
- message: `${truncate ? 'Cleared tables in reverse order and seeded' : 'Seeded'} ${exec.totalInserted} row(s) across ${Object.keys(exec.inserted).length} table(s) in ${exec.elapsedMs}ms.`,
144
- inserted: exec.inserted,
145
- totalInserted: exec.totalInserted,
146
- elapsedMs: exec.elapsedMs,
147
- warnings: exec.warnings,
148
- }, 201);
149
- }));
150
- router.get('/api/seed/:db/chain', (0, helpers_1.wrap)(async (req, res) => {
151
- const db = ctx.getDb(req);
152
- const rawRoot = String(req.query.table ?? '');
153
- const rawScope = String(req.query.scope ?? (rawRoot ? 'chain' : 'all'));
154
- const scope = rawScope === 'ancestors' || rawScope === 'descendants' || rawScope === 'all' || rawScope === 'single'
155
- ? rawScope
156
- : 'all';
157
- const rootTable = rawRoot || (await db.listTables()).data?.[0]?.name || '';
158
- if (!rootTable)
159
- return (0, helpers_1.fail)(res, 'No tables found in database.', 404);
160
- (0, helpers_1.ok)(res, await (0, index_1.getErChainConfig)(db, rootTable, scope));
161
- }));
162
- router.post('/api/seed/:db/chain', (0, helpers_1.wrap)(async (req, res) => {
163
- const db = ctx.getDb(req);
164
- const { scope, counts, plans, truncate, modes, seed } = (0, helpers_1.parseChainSeedRequest)(req.body);
165
- const rawRoot = String(req.body?.rootTable ?? '');
166
- const rootTable = rawRoot || (await db.listTables()).data?.[0]?.name || '';
167
- if (!rootTable)
168
- return (0, helpers_1.fail)(res, 'No tables found in database.', 404);
169
- const config = await (0, index_1.getErChainConfig)(db, rootTable, scope);
170
- const gen = await (0, index_1.generateChainRows)(db, config, plans, counts, truncate, modes, seed);
171
- const exec = await (0, index_1.executeChainInsert)(db, gen, truncate);
172
- (0, helpers_1.ok)(res, {
173
- message: `${truncate ? 'Cleared tables in reverse order and seeded' : 'Seeded'} ${exec.totalInserted} row(s) across ${Object.keys(exec.inserted).length} table(s) in ${exec.elapsedMs}ms.`,
174
- inserted: exec.inserted,
175
- totalInserted: exec.totalInserted,
176
- elapsedMs: exec.elapsedMs,
177
- warnings: exec.warnings,
178
- }, 201);
179
- }));
180
- }
@@ -1 +0,0 @@
1
- import type {Router} from 'express';import{type ApiContext} from './helpers';export declare function registerTableRoutes(router:Router,ctx:ApiContext):void;