@bakery-framework/plugin-db-explorer 2.2.1 → 2.2.2
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/package.json +3 -3
- package/src/endpoints/common.ts +22 -0
- package/src/endpoints/import.ts +2 -2
- package/src/endpoints/rows.ts +12 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bakery-framework/plugin-db-explorer",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "Bakery database explorer plugin: browse and edit rows, no raw SQL, no DDL.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bakery",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"!src/tests"
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@bakery-framework/core": "^2.2.
|
|
37
|
-
"@bakery-framework/orm": "^2.2.
|
|
36
|
+
"@bakery-framework/core": "^2.2.2",
|
|
37
|
+
"@bakery-framework/orm": "^2.2.2"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"bun": ">=1.4.0"
|
package/src/endpoints/common.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { errorMsg, pluginLog } from '@bakery-framework/core/logger'
|
|
|
19
19
|
import { Case, Try } from '@bakery-framework/core/utils'
|
|
20
20
|
import type { JsonResponseData } from '@bakery-framework/core/utils/common'
|
|
21
21
|
import { response } from '@bakery-framework/core/utils/http'
|
|
22
|
+
import { DB } from '@bakery-framework/orm/orm'
|
|
22
23
|
import { currentCanWrite } from '../access'
|
|
23
24
|
import { introspect, type TableFacts } from '../identity'
|
|
24
25
|
import type { FieldError } from '../validate'
|
|
@@ -29,6 +30,27 @@ export type WriteStart =
|
|
|
29
30
|
| { ok: true; table: TableFacts; body: Record<string, unknown> }
|
|
30
31
|
| { ok: false; response: Envelope }
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* `DB`'s three writers, for a table named at runtime.
|
|
35
|
+
*
|
|
36
|
+
* The explorer writes to whatever the database holds, by names it reads from
|
|
37
|
+
* the database. An app that registers its schema narrows `DB.Insert.into`,
|
|
38
|
+
* `DB.Update.table` and `DB.Delete.from`, and their columns, to its own names,
|
|
39
|
+
* which are not the explorer's to know: every write here failed such an app's
|
|
40
|
+
* typecheck (11 errors in rows.ts and import.ts, 2.1.2 through 2.2.1), while
|
|
41
|
+
* this repo's gates compiled the explorer against no schema at all.
|
|
42
|
+
*
|
|
43
|
+
* `any` is the one table type that gives the builders back their unregistered
|
|
44
|
+
* shape (`never` makes the row `never`), and the ORM's own executables default
|
|
45
|
+
* to it for the same reason. What a schema would have checked, the row against
|
|
46
|
+
* the table, `validate.ts` checks against the live table instead.
|
|
47
|
+
*/
|
|
48
|
+
export const byName = {
|
|
49
|
+
insert: (table: string) => DB.Insert.into<any>(table),
|
|
50
|
+
update: (table: string) => DB.Update.table<any>(table),
|
|
51
|
+
delete: (table: string) => DB.Delete.from<any>(table),
|
|
52
|
+
}
|
|
53
|
+
|
|
32
54
|
/** A 400 carrying every field error, never only the first. */
|
|
33
55
|
export function invalid(errors: FieldError[]): Envelope {
|
|
34
56
|
return response.json.error(400, 'Invalid request', { errors })
|
package/src/endpoints/import.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { DB } from '@bakery-framework/orm/orm'
|
|
|
19
19
|
import { overLimit } from '../policy'
|
|
20
20
|
import { isRollbackSignal, previewRollback } from '../preview'
|
|
21
21
|
import { type FieldError, validateInsertRow } from '../validate'
|
|
22
|
-
import { beginWrite, invalid, refuse } from './common'
|
|
22
|
+
import { beginWrite, byName, invalid, refuse } from './common'
|
|
23
23
|
|
|
24
24
|
export type OnBadRow = 'stop' | 'skip'
|
|
25
25
|
|
|
@@ -70,7 +70,7 @@ export async function handleImport(
|
|
|
70
70
|
return await Try.return(
|
|
71
71
|
async () =>
|
|
72
72
|
await DB.transaction(async () => {
|
|
73
|
-
const result = await
|
|
73
|
+
const result = await byName.insert(table.name).values(records).run()
|
|
74
74
|
const report = {
|
|
75
75
|
inserted: Number(result.changes ?? 0),
|
|
76
76
|
skipped,
|
package/src/endpoints/rows.ts
CHANGED
|
@@ -32,7 +32,13 @@ import {
|
|
|
32
32
|
validateKey,
|
|
33
33
|
validatePartial,
|
|
34
34
|
} from '../validate'
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
beginWrite,
|
|
37
|
+
byName,
|
|
38
|
+
type Envelope,
|
|
39
|
+
invalid,
|
|
40
|
+
refuse,
|
|
41
|
+
} from './common'
|
|
36
42
|
|
|
37
43
|
/**
|
|
38
44
|
* A conflict, as the caller sees it: which edit, which row, and what the row
|
|
@@ -150,7 +156,7 @@ export async function handleInsertRows(
|
|
|
150
156
|
// wraps multiple batches in one transaction, so there is nothing to add
|
|
151
157
|
// here, which is exactly why the insert goes through it rather than
|
|
152
158
|
// through the adapter's own `insert()`.
|
|
153
|
-
const insert =
|
|
159
|
+
const insert = byName.insert(table.name).values(records)
|
|
154
160
|
if (!returning) {
|
|
155
161
|
const result = await insert.run()
|
|
156
162
|
return response.json.success('inserted', {
|
|
@@ -225,7 +231,7 @@ export async function handleUpdateRow(
|
|
|
225
231
|
const predicate = { ...key.where, ...expect.values }
|
|
226
232
|
const result = await chain(
|
|
227
233
|
(column, value) =>
|
|
228
|
-
|
|
234
|
+
byName.update(table.name).set(set.values).where(column, value),
|
|
229
235
|
predicate,
|
|
230
236
|
).run()
|
|
231
237
|
|
|
@@ -404,7 +410,7 @@ async function applyCollapsedGroup(
|
|
|
404
410
|
continue
|
|
405
411
|
}
|
|
406
412
|
|
|
407
|
-
let statement =
|
|
413
|
+
let statement = byName.update(table.name)
|
|
408
414
|
.set(group.set)
|
|
409
415
|
.where(group.column, DB.inList(chunk.map(m => m.value)))
|
|
410
416
|
for (const [column, value] of Object.entries(group.expect)) {
|
|
@@ -523,7 +529,7 @@ export async function handleBulkEdit(
|
|
|
523
529
|
const predicate = { ...edit.key, ...edit.expect }
|
|
524
530
|
const result = await chain(
|
|
525
531
|
(column, value) =>
|
|
526
|
-
|
|
532
|
+
byName.update(table.name).set(edit.set).where(column, value),
|
|
527
533
|
predicate,
|
|
528
534
|
).run()
|
|
529
535
|
|
|
@@ -612,7 +618,7 @@ export async function handleDeleteRows(
|
|
|
612
618
|
const target = prepared[index]!
|
|
613
619
|
const predicate = { ...target.key, ...target.expect }
|
|
614
620
|
const result = await chain(
|
|
615
|
-
(column, value) =>
|
|
621
|
+
(column, value) => byName.delete(table.name).where(column, value),
|
|
616
622
|
predicate,
|
|
617
623
|
).run()
|
|
618
624
|
|