@aigne/afs-sqlite 1.11.0-beta → 1.11.0-beta.1
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/LICENSE.md +17 -84
- package/README.md +0 -3
- package/dist/actions/built-in.cjs +142 -0
- package/dist/actions/built-in.d.cts +10 -0
- package/dist/actions/built-in.d.cts.map +1 -0
- package/dist/actions/built-in.d.mts +10 -0
- package/dist/actions/built-in.d.mts.map +1 -0
- package/dist/actions/built-in.mjs +143 -0
- package/dist/actions/built-in.mjs.map +1 -0
- package/dist/actions/registry.cjs +91 -0
- package/dist/actions/registry.d.cts +54 -0
- package/dist/actions/registry.d.cts.map +1 -0
- package/dist/actions/registry.d.mts +54 -0
- package/dist/actions/registry.d.mts.map +1 -0
- package/dist/actions/registry.mjs +91 -0
- package/dist/actions/registry.mjs.map +1 -0
- package/dist/actions/types.d.cts +56 -0
- package/dist/actions/types.d.cts.map +1 -0
- package/dist/actions/types.d.mts +56 -0
- package/dist/actions/types.d.mts.map +1 -0
- package/dist/config.cjs +27 -0
- package/dist/config.d.cts +81 -0
- package/dist/config.d.cts.map +1 -0
- package/dist/config.d.mts +81 -0
- package/dist/config.d.mts.map +1 -0
- package/dist/config.mjs +28 -0
- package/dist/config.mjs.map +1 -0
- package/dist/index.cjs +38 -1324
- package/dist/index.d.cts +14 -758
- package/dist/index.d.mts +14 -758
- package/dist/index.mjs +12 -1299
- package/dist/node/builder.cjs +179 -0
- package/dist/node/builder.d.cts +48 -0
- package/dist/node/builder.d.cts.map +1 -0
- package/dist/node/builder.d.mts +48 -0
- package/dist/node/builder.d.mts.map +1 -0
- package/dist/node/builder.mjs +172 -0
- package/dist/node/builder.mjs.map +1 -0
- package/dist/operations/crud.cjs +176 -0
- package/dist/operations/crud.d.cts +69 -0
- package/dist/operations/crud.d.cts.map +1 -0
- package/dist/operations/crud.d.mts +69 -0
- package/dist/operations/crud.d.mts.map +1 -0
- package/dist/operations/crud.mjs +177 -0
- package/dist/operations/crud.mjs.map +1 -0
- package/dist/operations/query-builder.cjs +77 -0
- package/dist/operations/query-builder.d.cts +34 -0
- package/dist/operations/query-builder.d.cts.map +1 -0
- package/dist/operations/query-builder.d.mts +34 -0
- package/dist/operations/query-builder.d.mts.map +1 -0
- package/dist/operations/query-builder.mjs +72 -0
- package/dist/operations/query-builder.mjs.map +1 -0
- package/dist/operations/search.cjs +141 -0
- package/dist/operations/search.d.cts +79 -0
- package/dist/operations/search.d.cts.map +1 -0
- package/dist/operations/search.d.mts +79 -0
- package/dist/operations/search.d.mts.map +1 -0
- package/dist/operations/search.mjs +141 -0
- package/dist/operations/search.mjs.map +1 -0
- package/dist/router/path-router.cjs +79 -0
- package/dist/router/path-router.d.cts +42 -0
- package/dist/router/path-router.d.cts.map +1 -0
- package/dist/router/path-router.d.mts +42 -0
- package/dist/router/path-router.d.mts.map +1 -0
- package/dist/router/path-router.mjs +76 -0
- package/dist/router/path-router.mjs.map +1 -0
- package/dist/router/types.d.cts +34 -0
- package/dist/router/types.d.cts.map +1 -0
- package/dist/router/types.d.mts +34 -0
- package/dist/router/types.d.mts.map +1 -0
- package/dist/schema/introspector.cjs +160 -0
- package/dist/schema/introspector.d.cts +49 -0
- package/dist/schema/introspector.d.cts.map +1 -0
- package/dist/schema/introspector.d.mts +49 -0
- package/dist/schema/introspector.d.mts.map +1 -0
- package/dist/schema/introspector.mjs +161 -0
- package/dist/schema/introspector.mjs.map +1 -0
- package/dist/schema/types.cjs +15 -0
- package/dist/schema/types.d.cts +104 -0
- package/dist/schema/types.d.cts.map +1 -0
- package/dist/schema/types.d.mts +104 -0
- package/dist/schema/types.d.mts.map +1 -0
- package/dist/schema/types.mjs +15 -0
- package/dist/schema/types.mjs.map +1 -0
- package/dist/sqlite-afs.cjs +264 -0
- package/dist/sqlite-afs.d.cts +152 -0
- package/dist/sqlite-afs.d.cts.map +1 -0
- package/dist/sqlite-afs.d.mts +152 -0
- package/dist/sqlite-afs.d.mts.map +1 -0
- package/dist/sqlite-afs.mjs +265 -0
- package/dist/sqlite-afs.mjs.map +1 -0
- package/package.json +3 -3
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/node/builder.ts
|
|
3
|
+
/**
|
|
4
|
+
* Builds an AFSEntry from a database row
|
|
5
|
+
*/
|
|
6
|
+
function buildRowEntry(table, schema, row, options) {
|
|
7
|
+
const pkColumn = schema.primaryKey[0] ?? "rowid";
|
|
8
|
+
const pk = String(row[pkColumn] ?? row.rowid);
|
|
9
|
+
const basePath = options?.basePath ?? "";
|
|
10
|
+
return {
|
|
11
|
+
id: `${table}:${pk}`,
|
|
12
|
+
path: `${basePath}/${table}/${pk}`,
|
|
13
|
+
content: row,
|
|
14
|
+
metadata: {
|
|
15
|
+
table,
|
|
16
|
+
primaryKey: pkColumn,
|
|
17
|
+
primaryKeyValue: pk
|
|
18
|
+
},
|
|
19
|
+
createdAt: parseDate(row.created_at ?? row.createdAt),
|
|
20
|
+
updatedAt: parseDate(row.updated_at ?? row.updatedAt)
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Builds an AFSEntry for a table listing
|
|
25
|
+
*/
|
|
26
|
+
function buildTableEntry(table, schema, options) {
|
|
27
|
+
return {
|
|
28
|
+
id: table,
|
|
29
|
+
path: `${options?.basePath ?? ""}/${table}`,
|
|
30
|
+
description: `Table: ${table} (${schema.columns.length} columns)`,
|
|
31
|
+
metadata: {
|
|
32
|
+
table,
|
|
33
|
+
columnCount: schema.columns.length,
|
|
34
|
+
primaryKey: schema.primaryKey,
|
|
35
|
+
childrenCount: options?.rowCount
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Builds an AFSEntry for table schema
|
|
41
|
+
*/
|
|
42
|
+
function buildSchemaEntry(table, schema, options) {
|
|
43
|
+
const basePath = options?.basePath ?? "";
|
|
44
|
+
return {
|
|
45
|
+
id: `${table}:@schema`,
|
|
46
|
+
path: `${basePath}/${table}/@schema`,
|
|
47
|
+
description: `Schema for table: ${table}`,
|
|
48
|
+
content: {
|
|
49
|
+
name: schema.name,
|
|
50
|
+
columns: schema.columns.map((col) => ({
|
|
51
|
+
name: col.name,
|
|
52
|
+
type: col.type,
|
|
53
|
+
nullable: !col.notnull,
|
|
54
|
+
primaryKey: col.pk > 0,
|
|
55
|
+
defaultValue: col.dfltValue
|
|
56
|
+
})),
|
|
57
|
+
primaryKey: schema.primaryKey,
|
|
58
|
+
foreignKeys: schema.foreignKeys.map((fk) => ({
|
|
59
|
+
column: fk.from,
|
|
60
|
+
references: {
|
|
61
|
+
table: fk.table,
|
|
62
|
+
column: fk.to
|
|
63
|
+
},
|
|
64
|
+
onUpdate: fk.onUpdate,
|
|
65
|
+
onDelete: fk.onDelete
|
|
66
|
+
})),
|
|
67
|
+
indexes: schema.indexes.map((idx) => ({
|
|
68
|
+
name: idx.name,
|
|
69
|
+
unique: idx.unique,
|
|
70
|
+
origin: idx.origin
|
|
71
|
+
}))
|
|
72
|
+
},
|
|
73
|
+
metadata: {
|
|
74
|
+
table,
|
|
75
|
+
type: "schema"
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Builds an AFSEntry for an attribute (single column value)
|
|
81
|
+
*/
|
|
82
|
+
function buildAttributeEntry(table, pk, column, value, options) {
|
|
83
|
+
const basePath = options?.basePath ?? "";
|
|
84
|
+
return {
|
|
85
|
+
id: `${table}:${pk}:@attr:${column}`,
|
|
86
|
+
path: `${basePath}/${table}/${pk}/@attr/${column}`,
|
|
87
|
+
content: value,
|
|
88
|
+
metadata: {
|
|
89
|
+
table,
|
|
90
|
+
primaryKeyValue: pk,
|
|
91
|
+
column,
|
|
92
|
+
type: "attribute"
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Builds an AFSEntry listing all attributes for a row
|
|
98
|
+
*/
|
|
99
|
+
function buildAttributeListEntry(table, schema, pk, row, options) {
|
|
100
|
+
const basePath = options?.basePath ?? "";
|
|
101
|
+
return schema.columns.map((col) => ({
|
|
102
|
+
id: `${table}:${pk}:@attr:${col.name}`,
|
|
103
|
+
path: `${basePath}/${table}/${pk}/@attr/${col.name}`,
|
|
104
|
+
summary: col.name,
|
|
105
|
+
description: `${col.type}${col.notnull ? " NOT NULL" : ""}`,
|
|
106
|
+
content: row[col.name],
|
|
107
|
+
metadata: {
|
|
108
|
+
column: col.name,
|
|
109
|
+
type: col.type
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Builds an AFSEntry for row metadata
|
|
115
|
+
*/
|
|
116
|
+
function buildMetaEntry(table, schema, pk, row, options) {
|
|
117
|
+
const basePath = options?.basePath ?? "";
|
|
118
|
+
return {
|
|
119
|
+
id: `${table}:${pk}:@meta`,
|
|
120
|
+
path: `${basePath}/${table}/${pk}/@meta`,
|
|
121
|
+
content: {
|
|
122
|
+
table,
|
|
123
|
+
primaryKey: schema.primaryKey[0] ?? "rowid",
|
|
124
|
+
primaryKeyValue: pk,
|
|
125
|
+
schema: {
|
|
126
|
+
columns: schema.columns.map((c) => c.name),
|
|
127
|
+
types: Object.fromEntries(schema.columns.map((c) => [c.name, c.type]))
|
|
128
|
+
},
|
|
129
|
+
foreignKeys: schema.foreignKeys.filter((fk) => Object.keys(row).includes(fk.from)),
|
|
130
|
+
rowid: row.rowid
|
|
131
|
+
},
|
|
132
|
+
metadata: {
|
|
133
|
+
table,
|
|
134
|
+
type: "meta"
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Builds AFSEntry for actions list
|
|
140
|
+
*/
|
|
141
|
+
function buildActionsListEntry(table, pk, actions, options) {
|
|
142
|
+
const basePath = options?.basePath ?? "";
|
|
143
|
+
return actions.map((action) => ({
|
|
144
|
+
id: `${table}:${pk}:@actions:${action}`,
|
|
145
|
+
path: `${basePath}/${table}/${pk}/@actions/${action}`,
|
|
146
|
+
summary: action,
|
|
147
|
+
metadata: { execute: {
|
|
148
|
+
name: action,
|
|
149
|
+
description: `Execute ${action} action on ${table}:${pk}`
|
|
150
|
+
} }
|
|
151
|
+
}));
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Builds a search result entry with highlights
|
|
155
|
+
*/
|
|
156
|
+
function buildSearchEntry(table, schema, row, snippet, options) {
|
|
157
|
+
const entry = buildRowEntry(table, schema, row, options);
|
|
158
|
+
if (snippet) entry.summary = snippet;
|
|
159
|
+
return entry;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Parses a date from various formats
|
|
163
|
+
*/
|
|
164
|
+
function parseDate(value) {
|
|
165
|
+
if (!value) return void 0;
|
|
166
|
+
if (value instanceof Date) return value;
|
|
167
|
+
if (typeof value === "string") return new Date(value);
|
|
168
|
+
if (typeof value === "number") return new Date(value);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//#endregion
|
|
172
|
+
exports.buildActionsListEntry = buildActionsListEntry;
|
|
173
|
+
exports.buildAttributeEntry = buildAttributeEntry;
|
|
174
|
+
exports.buildAttributeListEntry = buildAttributeListEntry;
|
|
175
|
+
exports.buildMetaEntry = buildMetaEntry;
|
|
176
|
+
exports.buildRowEntry = buildRowEntry;
|
|
177
|
+
exports.buildSchemaEntry = buildSchemaEntry;
|
|
178
|
+
exports.buildSearchEntry = buildSearchEntry;
|
|
179
|
+
exports.buildTableEntry = buildTableEntry;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { TableSchema } from "../schema/types.cjs";
|
|
2
|
+
import { AFSEntry } from "@aigne/afs";
|
|
3
|
+
|
|
4
|
+
//#region src/node/builder.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Options for building an AFSEntry
|
|
7
|
+
*/
|
|
8
|
+
interface BuildEntryOptions {
|
|
9
|
+
/** Base path prefix (e.g., empty string or module mount path) */
|
|
10
|
+
basePath?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Builds an AFSEntry from a database row
|
|
14
|
+
*/
|
|
15
|
+
declare function buildRowEntry(table: string, schema: TableSchema, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry;
|
|
16
|
+
/**
|
|
17
|
+
* Builds an AFSEntry for a table listing
|
|
18
|
+
*/
|
|
19
|
+
declare function buildTableEntry(table: string, schema: TableSchema, options?: BuildEntryOptions & {
|
|
20
|
+
rowCount?: number;
|
|
21
|
+
}): AFSEntry;
|
|
22
|
+
/**
|
|
23
|
+
* Builds an AFSEntry for table schema
|
|
24
|
+
*/
|
|
25
|
+
declare function buildSchemaEntry(table: string, schema: TableSchema, options?: BuildEntryOptions): AFSEntry;
|
|
26
|
+
/**
|
|
27
|
+
* Builds an AFSEntry for an attribute (single column value)
|
|
28
|
+
*/
|
|
29
|
+
declare function buildAttributeEntry(table: string, pk: string, column: string, value: unknown, options?: BuildEntryOptions): AFSEntry;
|
|
30
|
+
/**
|
|
31
|
+
* Builds an AFSEntry listing all attributes for a row
|
|
32
|
+
*/
|
|
33
|
+
declare function buildAttributeListEntry(table: string, schema: TableSchema, pk: string, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry[];
|
|
34
|
+
/**
|
|
35
|
+
* Builds an AFSEntry for row metadata
|
|
36
|
+
*/
|
|
37
|
+
declare function buildMetaEntry(table: string, schema: TableSchema, pk: string, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry;
|
|
38
|
+
/**
|
|
39
|
+
* Builds AFSEntry for actions list
|
|
40
|
+
*/
|
|
41
|
+
declare function buildActionsListEntry(table: string, pk: string, actions: string[], options?: BuildEntryOptions): AFSEntry[];
|
|
42
|
+
/**
|
|
43
|
+
* Builds a search result entry with highlights
|
|
44
|
+
*/
|
|
45
|
+
declare function buildSearchEntry(table: string, schema: TableSchema, row: Record<string, unknown>, snippet?: string, options?: BuildEntryOptions): AFSEntry;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { BuildEntryOptions, buildActionsListEntry, buildAttributeEntry, buildAttributeListEntry, buildMetaEntry, buildRowEntry, buildSchemaEntry, buildSearchEntry, buildTableEntry };
|
|
48
|
+
//# sourceMappingURL=builder.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.cts","names":[],"sources":["../../src/node/builder.ts"],"mappings":";;;;;AAMA;AAQA;UARiB,iBAAA;EAAA;EAAA,QAAA;AAAA;AAAA;AAQjB;;AARiB,iBAQD,aAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,GAAA,EACH,MAAA,mBAAA,OAAA,GACK,iBAAA,GACT,QAAA;AAAA;;AAsBH;AAtBG,iBAsBa,eAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,OAAA,GACE,iBAAA;EAAA,QAAA;AAAA,IACT,QAAA;AAAA;;AAmBH;AAnBG,iBAmBa,gBAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,OAAA,GACE,iBAAA,GACT,QAAA;AAAA;;AA0CH;AA1CG,iBA0Ca,mBAAA,CAAA,KAAA,UAAA,EAAA,UAAA,MAAA,UAAA,KAAA,WAAA,OAAA,GAKJ,iBAAA,GACT,QAAA;AAAA;AAmBH;;AAnBG,iBAmBa,uBAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,EAAA,UAAA,GAAA,EAEH,MAAA,mBAAA,OAAA,GACK,iBAAA,GACT,QAAA;AAAA;;AAmBH;AAnBG,iBAmBa,cAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,EAAA,UAAA,GAAA,EAEH,MAAA,mBAAA,OAAA,GACK,iBAAA,GACT,QAAA;AAAA;;AA2BH;AA3BG,iBA2Ba,qBAAA,CAAA,KAAA,UAAA,EAAA,UAAA,OAAA,YAAA,OAAA,GAIJ,iBAAA,GACT,QAAA;AAAA;AAmBH;;AAnBG,iBAmBa,gBAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,GAAA,EACH,MAAA,mBAAA,OAAA,WAAA,OAAA,GAEK,iBAAA,GACT,QAAA"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { TableSchema } from "../schema/types.mjs";
|
|
2
|
+
import { AFSEntry } from "@aigne/afs";
|
|
3
|
+
|
|
4
|
+
//#region src/node/builder.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Options for building an AFSEntry
|
|
7
|
+
*/
|
|
8
|
+
interface BuildEntryOptions {
|
|
9
|
+
/** Base path prefix (e.g., empty string or module mount path) */
|
|
10
|
+
basePath?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Builds an AFSEntry from a database row
|
|
14
|
+
*/
|
|
15
|
+
declare function buildRowEntry(table: string, schema: TableSchema, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry;
|
|
16
|
+
/**
|
|
17
|
+
* Builds an AFSEntry for a table listing
|
|
18
|
+
*/
|
|
19
|
+
declare function buildTableEntry(table: string, schema: TableSchema, options?: BuildEntryOptions & {
|
|
20
|
+
rowCount?: number;
|
|
21
|
+
}): AFSEntry;
|
|
22
|
+
/**
|
|
23
|
+
* Builds an AFSEntry for table schema
|
|
24
|
+
*/
|
|
25
|
+
declare function buildSchemaEntry(table: string, schema: TableSchema, options?: BuildEntryOptions): AFSEntry;
|
|
26
|
+
/**
|
|
27
|
+
* Builds an AFSEntry for an attribute (single column value)
|
|
28
|
+
*/
|
|
29
|
+
declare function buildAttributeEntry(table: string, pk: string, column: string, value: unknown, options?: BuildEntryOptions): AFSEntry;
|
|
30
|
+
/**
|
|
31
|
+
* Builds an AFSEntry listing all attributes for a row
|
|
32
|
+
*/
|
|
33
|
+
declare function buildAttributeListEntry(table: string, schema: TableSchema, pk: string, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry[];
|
|
34
|
+
/**
|
|
35
|
+
* Builds an AFSEntry for row metadata
|
|
36
|
+
*/
|
|
37
|
+
declare function buildMetaEntry(table: string, schema: TableSchema, pk: string, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry;
|
|
38
|
+
/**
|
|
39
|
+
* Builds AFSEntry for actions list
|
|
40
|
+
*/
|
|
41
|
+
declare function buildActionsListEntry(table: string, pk: string, actions: string[], options?: BuildEntryOptions): AFSEntry[];
|
|
42
|
+
/**
|
|
43
|
+
* Builds a search result entry with highlights
|
|
44
|
+
*/
|
|
45
|
+
declare function buildSearchEntry(table: string, schema: TableSchema, row: Record<string, unknown>, snippet?: string, options?: BuildEntryOptions): AFSEntry;
|
|
46
|
+
//#endregion
|
|
47
|
+
export { BuildEntryOptions, buildActionsListEntry, buildAttributeEntry, buildAttributeListEntry, buildMetaEntry, buildRowEntry, buildSchemaEntry, buildSearchEntry, buildTableEntry };
|
|
48
|
+
//# sourceMappingURL=builder.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.d.mts","names":[],"sources":["../../src/node/builder.ts"],"mappings":";;;;;AAMA;AAQA;UARiB,iBAAA;EAAA;EAAA,QAAA;AAAA;AAAA;AAQjB;;AARiB,iBAQD,aAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,GAAA,EACH,MAAA,mBAAA,OAAA,GACK,iBAAA,GACT,QAAA;AAAA;;AAsBH;AAtBG,iBAsBa,eAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,OAAA,GACE,iBAAA;EAAA,QAAA;AAAA,IACT,QAAA;AAAA;;AAmBH;AAnBG,iBAmBa,gBAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,OAAA,GACE,iBAAA,GACT,QAAA;AAAA;;AA0CH;AA1CG,iBA0Ca,mBAAA,CAAA,KAAA,UAAA,EAAA,UAAA,MAAA,UAAA,KAAA,WAAA,OAAA,GAKJ,iBAAA,GACT,QAAA;AAAA;AAmBH;;AAnBG,iBAmBa,uBAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,EAAA,UAAA,GAAA,EAEH,MAAA,mBAAA,OAAA,GACK,iBAAA,GACT,QAAA;AAAA;;AAmBH;AAnBG,iBAmBa,cAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,EAAA,UAAA,GAAA,EAEH,MAAA,mBAAA,OAAA,GACK,iBAAA,GACT,QAAA;AAAA;;AA2BH;AA3BG,iBA2Ba,qBAAA,CAAA,KAAA,UAAA,EAAA,UAAA,OAAA,YAAA,OAAA,GAIJ,iBAAA,GACT,QAAA;AAAA;AAmBH;;AAnBG,iBAmBa,gBAAA,CAAA,KAAA,UAAA,MAAA,EAEN,WAAA,EAAA,GAAA,EACH,MAAA,mBAAA,OAAA,WAAA,OAAA,GAEK,iBAAA,GACT,QAAA"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
//#region src/node/builder.ts
|
|
2
|
+
/**
|
|
3
|
+
* Builds an AFSEntry from a database row
|
|
4
|
+
*/
|
|
5
|
+
function buildRowEntry(table, schema, row, options) {
|
|
6
|
+
const pkColumn = schema.primaryKey[0] ?? "rowid";
|
|
7
|
+
const pk = String(row[pkColumn] ?? row.rowid);
|
|
8
|
+
const basePath = options?.basePath ?? "";
|
|
9
|
+
return {
|
|
10
|
+
id: `${table}:${pk}`,
|
|
11
|
+
path: `${basePath}/${table}/${pk}`,
|
|
12
|
+
content: row,
|
|
13
|
+
metadata: {
|
|
14
|
+
table,
|
|
15
|
+
primaryKey: pkColumn,
|
|
16
|
+
primaryKeyValue: pk
|
|
17
|
+
},
|
|
18
|
+
createdAt: parseDate(row.created_at ?? row.createdAt),
|
|
19
|
+
updatedAt: parseDate(row.updated_at ?? row.updatedAt)
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Builds an AFSEntry for a table listing
|
|
24
|
+
*/
|
|
25
|
+
function buildTableEntry(table, schema, options) {
|
|
26
|
+
return {
|
|
27
|
+
id: table,
|
|
28
|
+
path: `${options?.basePath ?? ""}/${table}`,
|
|
29
|
+
description: `Table: ${table} (${schema.columns.length} columns)`,
|
|
30
|
+
metadata: {
|
|
31
|
+
table,
|
|
32
|
+
columnCount: schema.columns.length,
|
|
33
|
+
primaryKey: schema.primaryKey,
|
|
34
|
+
childrenCount: options?.rowCount
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Builds an AFSEntry for table schema
|
|
40
|
+
*/
|
|
41
|
+
function buildSchemaEntry(table, schema, options) {
|
|
42
|
+
const basePath = options?.basePath ?? "";
|
|
43
|
+
return {
|
|
44
|
+
id: `${table}:@schema`,
|
|
45
|
+
path: `${basePath}/${table}/@schema`,
|
|
46
|
+
description: `Schema for table: ${table}`,
|
|
47
|
+
content: {
|
|
48
|
+
name: schema.name,
|
|
49
|
+
columns: schema.columns.map((col) => ({
|
|
50
|
+
name: col.name,
|
|
51
|
+
type: col.type,
|
|
52
|
+
nullable: !col.notnull,
|
|
53
|
+
primaryKey: col.pk > 0,
|
|
54
|
+
defaultValue: col.dfltValue
|
|
55
|
+
})),
|
|
56
|
+
primaryKey: schema.primaryKey,
|
|
57
|
+
foreignKeys: schema.foreignKeys.map((fk) => ({
|
|
58
|
+
column: fk.from,
|
|
59
|
+
references: {
|
|
60
|
+
table: fk.table,
|
|
61
|
+
column: fk.to
|
|
62
|
+
},
|
|
63
|
+
onUpdate: fk.onUpdate,
|
|
64
|
+
onDelete: fk.onDelete
|
|
65
|
+
})),
|
|
66
|
+
indexes: schema.indexes.map((idx) => ({
|
|
67
|
+
name: idx.name,
|
|
68
|
+
unique: idx.unique,
|
|
69
|
+
origin: idx.origin
|
|
70
|
+
}))
|
|
71
|
+
},
|
|
72
|
+
metadata: {
|
|
73
|
+
table,
|
|
74
|
+
type: "schema"
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Builds an AFSEntry for an attribute (single column value)
|
|
80
|
+
*/
|
|
81
|
+
function buildAttributeEntry(table, pk, column, value, options) {
|
|
82
|
+
const basePath = options?.basePath ?? "";
|
|
83
|
+
return {
|
|
84
|
+
id: `${table}:${pk}:@attr:${column}`,
|
|
85
|
+
path: `${basePath}/${table}/${pk}/@attr/${column}`,
|
|
86
|
+
content: value,
|
|
87
|
+
metadata: {
|
|
88
|
+
table,
|
|
89
|
+
primaryKeyValue: pk,
|
|
90
|
+
column,
|
|
91
|
+
type: "attribute"
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Builds an AFSEntry listing all attributes for a row
|
|
97
|
+
*/
|
|
98
|
+
function buildAttributeListEntry(table, schema, pk, row, options) {
|
|
99
|
+
const basePath = options?.basePath ?? "";
|
|
100
|
+
return schema.columns.map((col) => ({
|
|
101
|
+
id: `${table}:${pk}:@attr:${col.name}`,
|
|
102
|
+
path: `${basePath}/${table}/${pk}/@attr/${col.name}`,
|
|
103
|
+
summary: col.name,
|
|
104
|
+
description: `${col.type}${col.notnull ? " NOT NULL" : ""}`,
|
|
105
|
+
content: row[col.name],
|
|
106
|
+
metadata: {
|
|
107
|
+
column: col.name,
|
|
108
|
+
type: col.type
|
|
109
|
+
}
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Builds an AFSEntry for row metadata
|
|
114
|
+
*/
|
|
115
|
+
function buildMetaEntry(table, schema, pk, row, options) {
|
|
116
|
+
const basePath = options?.basePath ?? "";
|
|
117
|
+
return {
|
|
118
|
+
id: `${table}:${pk}:@meta`,
|
|
119
|
+
path: `${basePath}/${table}/${pk}/@meta`,
|
|
120
|
+
content: {
|
|
121
|
+
table,
|
|
122
|
+
primaryKey: schema.primaryKey[0] ?? "rowid",
|
|
123
|
+
primaryKeyValue: pk,
|
|
124
|
+
schema: {
|
|
125
|
+
columns: schema.columns.map((c) => c.name),
|
|
126
|
+
types: Object.fromEntries(schema.columns.map((c) => [c.name, c.type]))
|
|
127
|
+
},
|
|
128
|
+
foreignKeys: schema.foreignKeys.filter((fk) => Object.keys(row).includes(fk.from)),
|
|
129
|
+
rowid: row.rowid
|
|
130
|
+
},
|
|
131
|
+
metadata: {
|
|
132
|
+
table,
|
|
133
|
+
type: "meta"
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Builds AFSEntry for actions list
|
|
139
|
+
*/
|
|
140
|
+
function buildActionsListEntry(table, pk, actions, options) {
|
|
141
|
+
const basePath = options?.basePath ?? "";
|
|
142
|
+
return actions.map((action) => ({
|
|
143
|
+
id: `${table}:${pk}:@actions:${action}`,
|
|
144
|
+
path: `${basePath}/${table}/${pk}/@actions/${action}`,
|
|
145
|
+
summary: action,
|
|
146
|
+
metadata: { execute: {
|
|
147
|
+
name: action,
|
|
148
|
+
description: `Execute ${action} action on ${table}:${pk}`
|
|
149
|
+
} }
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Builds a search result entry with highlights
|
|
154
|
+
*/
|
|
155
|
+
function buildSearchEntry(table, schema, row, snippet, options) {
|
|
156
|
+
const entry = buildRowEntry(table, schema, row, options);
|
|
157
|
+
if (snippet) entry.summary = snippet;
|
|
158
|
+
return entry;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Parses a date from various formats
|
|
162
|
+
*/
|
|
163
|
+
function parseDate(value) {
|
|
164
|
+
if (!value) return void 0;
|
|
165
|
+
if (value instanceof Date) return value;
|
|
166
|
+
if (typeof value === "string") return new Date(value);
|
|
167
|
+
if (typeof value === "number") return new Date(value);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
//#endregion
|
|
171
|
+
export { buildActionsListEntry, buildAttributeEntry, buildAttributeListEntry, buildMetaEntry, buildRowEntry, buildSchemaEntry, buildSearchEntry, buildTableEntry };
|
|
172
|
+
//# sourceMappingURL=builder.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.mjs","names":[],"sources":["../../src/node/builder.ts"],"sourcesContent":["import type { AFSEntry } from \"@aigne/afs\";\nimport type { TableSchema } from \"../schema/types.js\";\n\n/**\n * Options for building an AFSEntry\n */\nexport interface BuildEntryOptions {\n /** Base path prefix (e.g., empty string or module mount path) */\n basePath?: string;\n}\n\n/**\n * Builds an AFSEntry from a database row\n */\nexport function buildRowEntry(\n table: string,\n schema: TableSchema,\n row: Record<string, unknown>,\n options?: BuildEntryOptions,\n): AFSEntry {\n const pkColumn = schema.primaryKey[0] ?? \"rowid\";\n const pk = String(row[pkColumn] ?? row.rowid);\n const basePath = options?.basePath ?? \"\";\n\n return {\n id: `${table}:${pk}`,\n path: `${basePath}/${table}/${pk}`,\n content: row,\n metadata: {\n table,\n primaryKey: pkColumn,\n primaryKeyValue: pk,\n },\n createdAt: parseDate(row.created_at ?? row.createdAt),\n updatedAt: parseDate(row.updated_at ?? row.updatedAt),\n };\n}\n\n/**\n * Builds an AFSEntry for a table listing\n */\nexport function buildTableEntry(\n table: string,\n schema: TableSchema,\n options?: BuildEntryOptions & { rowCount?: number },\n): AFSEntry {\n const basePath = options?.basePath ?? \"\";\n\n return {\n id: table,\n path: `${basePath}/${table}`,\n description: `Table: ${table} (${schema.columns.length} columns)`,\n metadata: {\n table,\n columnCount: schema.columns.length,\n primaryKey: schema.primaryKey,\n childrenCount: options?.rowCount,\n },\n };\n}\n\n/**\n * Builds an AFSEntry for table schema\n */\nexport function buildSchemaEntry(\n table: string,\n schema: TableSchema,\n options?: BuildEntryOptions,\n): AFSEntry {\n const basePath = options?.basePath ?? \"\";\n\n return {\n id: `${table}:@schema`,\n path: `${basePath}/${table}/@schema`,\n description: `Schema for table: ${table}`,\n content: {\n name: schema.name,\n columns: schema.columns.map((col) => ({\n name: col.name,\n type: col.type,\n nullable: !col.notnull,\n primaryKey: col.pk > 0,\n defaultValue: col.dfltValue,\n })),\n primaryKey: schema.primaryKey,\n foreignKeys: schema.foreignKeys.map((fk) => ({\n column: fk.from,\n references: {\n table: fk.table,\n column: fk.to,\n },\n onUpdate: fk.onUpdate,\n onDelete: fk.onDelete,\n })),\n indexes: schema.indexes.map((idx) => ({\n name: idx.name,\n unique: idx.unique,\n origin: idx.origin,\n })),\n },\n metadata: {\n table,\n type: \"schema\",\n },\n };\n}\n\n/**\n * Builds an AFSEntry for an attribute (single column value)\n */\nexport function buildAttributeEntry(\n table: string,\n pk: string,\n column: string,\n value: unknown,\n options?: BuildEntryOptions,\n): AFSEntry {\n const basePath = options?.basePath ?? \"\";\n\n return {\n id: `${table}:${pk}:@attr:${column}`,\n path: `${basePath}/${table}/${pk}/@attr/${column}`,\n content: value,\n metadata: {\n table,\n primaryKeyValue: pk,\n column,\n type: \"attribute\",\n },\n };\n}\n\n/**\n * Builds an AFSEntry listing all attributes for a row\n */\nexport function buildAttributeListEntry(\n table: string,\n schema: TableSchema,\n pk: string,\n row: Record<string, unknown>,\n options?: BuildEntryOptions,\n): AFSEntry[] {\n const basePath = options?.basePath ?? \"\";\n\n return schema.columns.map((col) => ({\n id: `${table}:${pk}:@attr:${col.name}`,\n path: `${basePath}/${table}/${pk}/@attr/${col.name}`,\n summary: col.name,\n description: `${col.type}${col.notnull ? \" NOT NULL\" : \"\"}`,\n content: row[col.name],\n metadata: {\n column: col.name,\n type: col.type,\n },\n }));\n}\n\n/**\n * Builds an AFSEntry for row metadata\n */\nexport function buildMetaEntry(\n table: string,\n schema: TableSchema,\n pk: string,\n row: Record<string, unknown>,\n options?: BuildEntryOptions,\n): AFSEntry {\n const basePath = options?.basePath ?? \"\";\n\n return {\n id: `${table}:${pk}:@meta`,\n path: `${basePath}/${table}/${pk}/@meta`,\n content: {\n table,\n primaryKey: schema.primaryKey[0] ?? \"rowid\",\n primaryKeyValue: pk,\n schema: {\n columns: schema.columns.map((c) => c.name),\n types: Object.fromEntries(schema.columns.map((c) => [c.name, c.type])),\n },\n foreignKeys: schema.foreignKeys.filter((fk) => Object.keys(row).includes(fk.from)),\n rowid: row.rowid,\n },\n metadata: {\n table,\n type: \"meta\",\n },\n };\n}\n\n/**\n * Builds AFSEntry for actions list\n */\nexport function buildActionsListEntry(\n table: string,\n pk: string,\n actions: string[],\n options?: BuildEntryOptions,\n): AFSEntry[] {\n const basePath = options?.basePath ?? \"\";\n\n return actions.map((action) => ({\n id: `${table}:${pk}:@actions:${action}`,\n path: `${basePath}/${table}/${pk}/@actions/${action}`,\n summary: action,\n metadata: {\n execute: {\n name: action,\n description: `Execute ${action} action on ${table}:${pk}`,\n },\n },\n }));\n}\n\n/**\n * Builds a search result entry with highlights\n */\nexport function buildSearchEntry(\n table: string,\n schema: TableSchema,\n row: Record<string, unknown>,\n snippet?: string,\n options?: BuildEntryOptions,\n): AFSEntry {\n const entry = buildRowEntry(table, schema, row, options);\n\n if (snippet) {\n entry.summary = snippet;\n }\n\n return entry;\n}\n\n/**\n * Parses a date from various formats\n */\nfunction parseDate(value: unknown): Date | undefined {\n if (!value) return undefined;\n if (value instanceof Date) return value;\n if (typeof value === \"string\") return new Date(value);\n if (typeof value === \"number\") return new Date(value);\n return undefined;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
const require_builder = require('../node/builder.cjs');
|
|
2
|
+
const require_query_builder = require('./query-builder.cjs');
|
|
3
|
+
let _aigne_sqlite = require("@aigne/sqlite");
|
|
4
|
+
|
|
5
|
+
//#region src/operations/crud.ts
|
|
6
|
+
/**
|
|
7
|
+
* Executes a raw SQL query and returns all rows
|
|
8
|
+
*/
|
|
9
|
+
async function execAll(db, query) {
|
|
10
|
+
return db.all(_aigne_sqlite.sql.raw(query)).execute();
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Executes a raw SQL query (for INSERT, UPDATE, DELETE)
|
|
14
|
+
*/
|
|
15
|
+
async function execRun(db, query) {
|
|
16
|
+
await db.run(_aigne_sqlite.sql.raw(query)).execute();
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* CRUD operations for SQLite AFS
|
|
20
|
+
*/
|
|
21
|
+
var CRUDOperations = class {
|
|
22
|
+
constructor(db, schemas, basePath = "") {
|
|
23
|
+
this.db = db;
|
|
24
|
+
this.schemas = schemas;
|
|
25
|
+
this.basePath = basePath;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Lists all tables
|
|
29
|
+
*/
|
|
30
|
+
async listTables() {
|
|
31
|
+
const entries = [];
|
|
32
|
+
const buildOptions = { basePath: this.basePath };
|
|
33
|
+
for (const [name, schema] of this.schemas) {
|
|
34
|
+
const rowCount = (await execAll(this.db, `SELECT COUNT(*) as count FROM "${name}"`))[0]?.count ?? 0;
|
|
35
|
+
entries.push(require_builder.buildTableEntry(name, schema, {
|
|
36
|
+
...buildOptions,
|
|
37
|
+
rowCount
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
return { data: entries };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Lists rows in a table
|
|
44
|
+
*/
|
|
45
|
+
async listTable(table, options) {
|
|
46
|
+
const schema = this.schemas.get(table);
|
|
47
|
+
if (!schema) return {
|
|
48
|
+
data: [],
|
|
49
|
+
message: `Table '${table}' not found`
|
|
50
|
+
};
|
|
51
|
+
const buildOptions = { basePath: this.basePath };
|
|
52
|
+
const queryStr = require_query_builder.buildSelectAll(table, {
|
|
53
|
+
limit: options?.limit ?? 100,
|
|
54
|
+
orderBy: options?.orderBy
|
|
55
|
+
});
|
|
56
|
+
return { data: (await execAll(this.db, queryStr)).map((row) => require_builder.buildRowEntry(table, schema, row, buildOptions)) };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Reads a single row by primary key
|
|
60
|
+
*/
|
|
61
|
+
async readRow(table, pk) {
|
|
62
|
+
const schema = this.schemas.get(table);
|
|
63
|
+
if (!schema) return { message: `Table '${table}' not found` };
|
|
64
|
+
const buildOptions = { basePath: this.basePath };
|
|
65
|
+
const row = (await execAll(this.db, require_query_builder.buildSelectByPK(table, schema, pk)))[0];
|
|
66
|
+
if (!row) return { message: `Row with pk '${pk}' not found in table '${table}'` };
|
|
67
|
+
return { data: require_builder.buildRowEntry(table, schema, row, buildOptions) };
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Gets table schema
|
|
71
|
+
*/
|
|
72
|
+
getSchema(table) {
|
|
73
|
+
const schema = this.schemas.get(table);
|
|
74
|
+
if (!schema) return { message: `Table '${table}' not found` };
|
|
75
|
+
return { data: require_builder.buildSchemaEntry(table, schema, { basePath: this.basePath }) };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Lists attributes (columns) for a row
|
|
79
|
+
*/
|
|
80
|
+
async listAttributes(table, pk) {
|
|
81
|
+
const schema = this.schemas.get(table);
|
|
82
|
+
if (!schema) return {
|
|
83
|
+
data: [],
|
|
84
|
+
message: `Table '${table}' not found`
|
|
85
|
+
};
|
|
86
|
+
const buildOptions = { basePath: this.basePath };
|
|
87
|
+
const row = (await execAll(this.db, require_query_builder.buildSelectByPK(table, schema, pk)))[0];
|
|
88
|
+
if (!row) return {
|
|
89
|
+
data: [],
|
|
90
|
+
message: `Row with pk '${pk}' not found`
|
|
91
|
+
};
|
|
92
|
+
return { data: require_builder.buildAttributeListEntry(table, schema, pk, row, buildOptions) };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Gets a single attribute (column value) for a row
|
|
96
|
+
*/
|
|
97
|
+
async getAttribute(table, pk, column) {
|
|
98
|
+
const schema = this.schemas.get(table);
|
|
99
|
+
if (!schema) return { message: `Table '${table}' not found` };
|
|
100
|
+
if (!schema.columns.find((c) => c.name === column)) return { message: `Column '${column}' not found in table '${table}'` };
|
|
101
|
+
const buildOptions = { basePath: this.basePath };
|
|
102
|
+
const rows = await execAll(this.db, require_query_builder.buildSelectByPK(table, schema, pk));
|
|
103
|
+
if (rows.length === 0) return { message: `Row with pk '${pk}' not found` };
|
|
104
|
+
return { data: require_builder.buildAttributeEntry(table, pk, column, rows[0]?.[column], buildOptions) };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Gets row metadata
|
|
108
|
+
*/
|
|
109
|
+
async getMeta(table, pk) {
|
|
110
|
+
const schema = this.schemas.get(table);
|
|
111
|
+
if (!schema) return { message: `Table '${table}' not found` };
|
|
112
|
+
const buildOptions = { basePath: this.basePath };
|
|
113
|
+
const row = (await execAll(this.db, require_query_builder.buildSelectByPK(table, schema, pk)))[0];
|
|
114
|
+
if (!row) return { message: `Row with pk '${pk}' not found` };
|
|
115
|
+
return { data: require_builder.buildMetaEntry(table, schema, pk, row, buildOptions) };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Creates a new row in a table
|
|
119
|
+
*/
|
|
120
|
+
async createRow(table, content) {
|
|
121
|
+
const schema = this.schemas.get(table);
|
|
122
|
+
if (!schema) throw new Error(`Table '${table}' not found`);
|
|
123
|
+
const buildOptions = { basePath: this.basePath };
|
|
124
|
+
await execRun(this.db, require_query_builder.buildInsert(table, schema, content));
|
|
125
|
+
const lastId = (await execAll(this.db, require_query_builder.buildGetLastRowId()))[0]?.id;
|
|
126
|
+
if (lastId === void 0) throw new Error("Failed to get last inserted row ID");
|
|
127
|
+
const pkColumn = schema.primaryKey[0] ?? "rowid";
|
|
128
|
+
const pk = content[pkColumn] !== void 0 ? String(content[pkColumn]) : String(lastId);
|
|
129
|
+
const row = (await execAll(this.db, require_query_builder.buildSelectByPK(table, schema, pk)))[0];
|
|
130
|
+
if (!row) throw new Error("Failed to fetch inserted row");
|
|
131
|
+
return { data: require_builder.buildRowEntry(table, schema, row, buildOptions) };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Updates an existing row
|
|
135
|
+
*/
|
|
136
|
+
async updateRow(table, pk, content) {
|
|
137
|
+
const schema = this.schemas.get(table);
|
|
138
|
+
if (!schema) throw new Error(`Table '${table}' not found`);
|
|
139
|
+
const buildOptions = { basePath: this.basePath };
|
|
140
|
+
await execRun(this.db, require_query_builder.buildUpdate(table, schema, pk, content));
|
|
141
|
+
const row = (await execAll(this.db, require_query_builder.buildSelectByPK(table, schema, pk)))[0];
|
|
142
|
+
if (!row) throw new Error(`Row with pk '${pk}' not found after update`);
|
|
143
|
+
return { data: require_builder.buildRowEntry(table, schema, row, buildOptions) };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Deletes a row by primary key
|
|
147
|
+
*/
|
|
148
|
+
async deleteRow(table, pk) {
|
|
149
|
+
const schema = this.schemas.get(table);
|
|
150
|
+
if (!schema) throw new Error(`Table '${table}' not found`);
|
|
151
|
+
if ((await execAll(this.db, require_query_builder.buildSelectByPK(table, schema, pk))).length === 0) return { message: `Row with pk '${pk}' not found in table '${table}'` };
|
|
152
|
+
await execRun(this.db, require_query_builder.buildDelete(table, schema, pk));
|
|
153
|
+
return { message: `Deleted row '${pk}' from table '${table}'` };
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Checks if a table exists
|
|
157
|
+
*/
|
|
158
|
+
hasTable(table) {
|
|
159
|
+
return this.schemas.has(table);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Gets the schema for a table
|
|
163
|
+
*/
|
|
164
|
+
getTableSchema(table) {
|
|
165
|
+
return this.schemas.get(table);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Updates the schemas map (after refresh)
|
|
169
|
+
*/
|
|
170
|
+
setSchemas(schemas) {
|
|
171
|
+
this.schemas = schemas;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
//#endregion
|
|
176
|
+
exports.CRUDOperations = CRUDOperations;
|