@aigne/afs-sqlite 1.11.0-beta.1 → 1.11.0-beta.10
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/README.md +3 -3
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
- package/dist/_virtual/rolldown_runtime.mjs +7 -0
- package/dist/actions/built-in.cjs +1262 -15
- package/dist/actions/built-in.d.cts.map +1 -1
- package/dist/actions/built-in.d.mts.map +1 -1
- package/dist/actions/built-in.mjs +1262 -15
- package/dist/actions/built-in.mjs.map +1 -1
- package/dist/actions/operators.cjs +156 -0
- package/dist/actions/operators.mjs +157 -0
- package/dist/actions/operators.mjs.map +1 -0
- package/dist/actions/registry.cjs +35 -3
- package/dist/actions/registry.d.cts +36 -17
- package/dist/actions/registry.d.cts.map +1 -1
- package/dist/actions/registry.d.mts +36 -17
- package/dist/actions/registry.d.mts.map +1 -1
- package/dist/actions/registry.mjs +35 -3
- package/dist/actions/registry.mjs.map +1 -1
- package/dist/actions/types.cjs +33 -0
- package/dist/actions/types.d.cts +46 -5
- package/dist/actions/types.d.cts.map +1 -1
- package/dist/actions/types.d.mts +46 -5
- package/dist/actions/types.d.mts.map +1 -1
- package/dist/actions/types.mjs +32 -0
- package/dist/actions/types.mjs.map +1 -0
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +9 -36
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +9 -36
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +1 -1
- package/dist/config.mjs.map +1 -1
- package/dist/index.cjs +4 -3
- package/dist/index.d.cts +4 -3
- package/dist/index.d.mts +4 -3
- package/dist/index.mjs +3 -2
- package/dist/node/builder.cjs +74 -91
- package/dist/node/builder.d.cts +11 -15
- package/dist/node/builder.d.cts.map +1 -1
- package/dist/node/builder.d.mts +11 -15
- package/dist/node/builder.d.mts.map +1 -1
- package/dist/node/builder.mjs +72 -89
- package/dist/node/builder.mjs.map +1 -1
- package/dist/operations/crud.cjs +24 -68
- package/dist/operations/crud.d.cts +23 -38
- package/dist/operations/crud.d.cts.map +1 -1
- package/dist/operations/crud.d.mts +23 -38
- package/dist/operations/crud.d.mts.map +1 -1
- package/dist/operations/crud.mjs +25 -69
- package/dist/operations/crud.mjs.map +1 -1
- package/dist/operations/query-builder.cjs +2 -2
- package/dist/operations/query-builder.d.cts.map +1 -1
- package/dist/operations/query-builder.d.mts.map +1 -1
- package/dist/operations/query-builder.mjs +2 -2
- package/dist/operations/query-builder.mjs.map +1 -1
- package/dist/operations/search.cjs +5 -11
- package/dist/operations/search.d.cts +19 -23
- package/dist/operations/search.d.cts.map +1 -1
- package/dist/operations/search.d.mts +19 -23
- package/dist/operations/search.d.mts.map +1 -1
- package/dist/operations/search.mjs +5 -11
- package/dist/operations/search.mjs.map +1 -1
- package/dist/router/path-router.cjs +7 -15
- package/dist/router/path-router.d.cts +4 -7
- package/dist/router/path-router.d.cts.map +1 -1
- package/dist/router/path-router.d.mts +4 -7
- package/dist/router/path-router.d.mts.map +1 -1
- package/dist/router/path-router.mjs +7 -15
- package/dist/router/path-router.mjs.map +1 -1
- package/dist/router/types.d.cts.map +1 -1
- package/dist/router/types.d.mts.map +1 -1
- package/dist/schema/introspector.d.cts +19 -19
- package/dist/schema/introspector.d.cts.map +1 -1
- package/dist/schema/introspector.d.mts +19 -19
- package/dist/schema/introspector.d.mts.map +1 -1
- package/dist/schema/service.cjs +86 -0
- package/dist/schema/service.d.cts +52 -0
- package/dist/schema/service.d.cts.map +1 -0
- package/dist/schema/service.d.mts +52 -0
- package/dist/schema/service.d.mts.map +1 -0
- package/dist/schema/service.mjs +87 -0
- package/dist/schema/service.mjs.map +1 -0
- package/dist/schema/types.d.cts.map +1 -1
- package/dist/schema/types.d.mts.map +1 -1
- package/dist/sqlite-afs.cjs +693 -121
- package/dist/sqlite-afs.d.cts +279 -101
- package/dist/sqlite-afs.d.cts.map +1 -1
- package/dist/sqlite-afs.d.mts +279 -101
- package/dist/sqlite-afs.d.mts.map +1 -1
- package/dist/sqlite-afs.mjs +696 -123
- package/dist/sqlite-afs.mjs.map +1 -1
- package/package.json +5 -4
package/dist/sqlite-afs.cjs
CHANGED
|
@@ -4,31 +4,44 @@ const require_config = require('./config.cjs');
|
|
|
4
4
|
const require_builder = require('./node/builder.cjs');
|
|
5
5
|
const require_crud = require('./operations/crud.cjs');
|
|
6
6
|
const require_search = require('./operations/search.cjs');
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const require_service = require('./schema/service.cjs');
|
|
8
|
+
const require_decorate = require('./_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs');
|
|
9
9
|
let _aigne_sqlite = require("@aigne/sqlite");
|
|
10
|
+
let _aigne_afs = require("@aigne/afs");
|
|
11
|
+
let zod = require("zod");
|
|
12
|
+
let _aigne_afs_provider = require("@aigne/afs/provider");
|
|
10
13
|
|
|
11
14
|
//#region src/sqlite-afs.ts
|
|
12
15
|
/**
|
|
13
16
|
* SQLite AFS Module
|
|
14
17
|
*
|
|
15
18
|
* Exposes SQLite databases as AFS nodes with full CRUD support,
|
|
16
|
-
* schema introspection, FTS5 search, and virtual paths (
|
|
19
|
+
* schema introspection, FTS5 search, and virtual paths (.meta, .actions).
|
|
17
20
|
*/
|
|
18
|
-
var SQLiteAFS = class SQLiteAFS {
|
|
21
|
+
var SQLiteAFS = class SQLiteAFS extends _aigne_afs_provider.AFSBaseProvider {
|
|
19
22
|
name;
|
|
20
23
|
description;
|
|
21
24
|
accessMode;
|
|
22
25
|
db;
|
|
23
|
-
|
|
24
|
-
router;
|
|
26
|
+
schemaService;
|
|
25
27
|
crud;
|
|
26
28
|
ftsSearch;
|
|
27
29
|
actions;
|
|
28
30
|
ftsConfig;
|
|
29
31
|
initialized = false;
|
|
30
32
|
constructor(options) {
|
|
33
|
+
super();
|
|
31
34
|
this.options = options;
|
|
35
|
+
if (options.localPath && !options.url) options.url = `file:${options.localPath}`;
|
|
36
|
+
if (options.url.startsWith("file:")) {
|
|
37
|
+
const { existsSync, mkdirSync, writeFileSync } = require("node:fs");
|
|
38
|
+
const { dirname } = require("node:path");
|
|
39
|
+
const dbPath = options.url.slice(5);
|
|
40
|
+
if (!existsSync(dbPath)) {
|
|
41
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
42
|
+
writeFileSync(dbPath, "");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
32
45
|
this.name = options.name ?? "sqlite-afs";
|
|
33
46
|
this.description = options.description ?? `SQLite database: ${options.url}`;
|
|
34
47
|
this.accessMode = options.accessMode ?? "readwrite";
|
|
@@ -42,20 +55,24 @@ var SQLiteAFS = class SQLiteAFS {
|
|
|
42
55
|
static schema() {
|
|
43
56
|
return require_config.sqliteAFSConfigSchema;
|
|
44
57
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
static manifest() {
|
|
59
|
+
return {
|
|
60
|
+
name: "sqlite",
|
|
61
|
+
description: "SQLite database — tables as directories, rows as nodes.\n- Browse tables and rows, full-text search (FTS5), schema introspection\n- Exec actions: `insert`, `update`, `delete` at table/row level, custom SQL\n- Path structure: `/{table}/{primary-key}`",
|
|
62
|
+
uriTemplate: "sqlite://{localPath+}",
|
|
63
|
+
category: "database",
|
|
64
|
+
schema: zod.z.object({ localPath: zod.z.string() }),
|
|
65
|
+
tags: ["sqlite", "database"]
|
|
66
|
+
};
|
|
50
67
|
}
|
|
51
68
|
/**
|
|
52
|
-
*
|
|
69
|
+
* Loads a module instance from configuration
|
|
53
70
|
*/
|
|
54
|
-
async
|
|
55
|
-
|
|
71
|
+
static async load({ config } = {}) {
|
|
72
|
+
return new SQLiteAFS(require_config.sqliteAFSConfigSchema.parse(config));
|
|
56
73
|
}
|
|
57
74
|
/**
|
|
58
|
-
* Initializes the database connection and
|
|
75
|
+
* Initializes the database connection and schema service
|
|
59
76
|
*/
|
|
60
77
|
async initialize() {
|
|
61
78
|
if (this.initialized) return;
|
|
@@ -64,158 +81,672 @@ var SQLiteAFS = class SQLiteAFS {
|
|
|
64
81
|
wal: this.options.wal ?? true
|
|
65
82
|
});
|
|
66
83
|
const db = this.db;
|
|
67
|
-
this.
|
|
84
|
+
this.schemaService = new require_service.SchemaService(db, {
|
|
68
85
|
tables: this.options.tables,
|
|
69
86
|
excludeTables: this.options.excludeTables
|
|
70
87
|
});
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this.ftsSearch = new require_search.FTSSearch(db, this.schemas, this.ftsConfig, "");
|
|
88
|
+
this.crud = new require_crud.CRUDOperations(db, this.schemaService, "");
|
|
89
|
+
this.ftsSearch = new require_search.FTSSearch(db, this.schemaService, this.ftsConfig, "");
|
|
74
90
|
this.initialized = true;
|
|
75
91
|
}
|
|
76
92
|
/**
|
|
77
|
-
* Ensures the module is initialized
|
|
93
|
+
* Ensures the module is initialized.
|
|
94
|
+
* This is called automatically by handlers, but can also be called
|
|
95
|
+
* manually to trigger initialization (e.g., in tests).
|
|
78
96
|
*/
|
|
79
97
|
async ensureInitialized() {
|
|
80
98
|
if (!this.initialized) await this.initialize();
|
|
81
99
|
}
|
|
82
100
|
/**
|
|
83
|
-
*
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
* List all tables
|
|
102
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
103
|
+
*/
|
|
104
|
+
async listTablesHandler(_ctx) {
|
|
105
|
+
await this.ensureInitialized();
|
|
106
|
+
return { data: (await this.crud.listTables()).data };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* List rows in a table
|
|
110
|
+
* Note: list() returns only children (rows), never the table itself (per new semantics)
|
|
111
|
+
*/
|
|
112
|
+
async listTableHandler(ctx) {
|
|
113
|
+
await this.ensureInitialized();
|
|
114
|
+
if (!await this.schemaService.getSchema(ctx.params.table)) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
115
|
+
return { data: (await this.crud.listTable(ctx.params.table, ctx.options)).data };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* List a row - rows are leaf nodes with no children
|
|
119
|
+
* Note: list() returns only children, never the path itself (per new semantics)
|
|
120
|
+
*/
|
|
121
|
+
async listRowHandler(ctx) {
|
|
122
|
+
await this.ensureInitialized();
|
|
123
|
+
if (!(await this.crud.readRow(ctx.params.table, ctx.params.pk)).data) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}/${ctx.params.pk}`);
|
|
124
|
+
return { data: [] };
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* List actions for a row
|
|
128
|
+
*/
|
|
129
|
+
async listActionsHandler(ctx) {
|
|
130
|
+
await this.ensureInitialized();
|
|
131
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
132
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
133
|
+
const actions = this.actions.listWithInfo({ rowLevel: true }, {
|
|
134
|
+
tableSchema: schema,
|
|
135
|
+
tableName: ctx.params.table,
|
|
136
|
+
schemaService: this.schemaService
|
|
137
|
+
});
|
|
138
|
+
return { data: require_builder.buildActionsListEntry(ctx.params.table, ctx.params.pk, actions, { basePath: "" }) };
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* List actions for a table (table-level actions)
|
|
142
|
+
*/
|
|
143
|
+
async listTableActionsHandler(ctx) {
|
|
144
|
+
await this.ensureInitialized();
|
|
145
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
146
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
147
|
+
const actions = this.actions.listWithInfo({ tableLevel: true }, {
|
|
148
|
+
tableSchema: schema,
|
|
149
|
+
tableName: ctx.params.table,
|
|
150
|
+
schemaService: this.schemaService
|
|
151
|
+
});
|
|
152
|
+
return { data: require_builder.buildTableActionsListEntry(ctx.params.table, actions, { basePath: "" }) };
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* List actions at root level (database-level actions)
|
|
156
|
+
*/
|
|
157
|
+
async listRootActionsHandler(_ctx) {
|
|
158
|
+
await this.ensureInitialized();
|
|
159
|
+
return { data: require_builder.buildRootActionsListEntry(this.actions.listWithInfo({ rootLevel: true }, { schemaService: this.schemaService }), { basePath: "" }) };
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Read root (database) entry
|
|
163
|
+
*/
|
|
164
|
+
async readRootHandler(_ctx) {
|
|
165
|
+
await this.ensureInitialized();
|
|
166
|
+
return require_builder.buildRootEntry(await this.schemaService.getAllSchemas(), { basePath: "" });
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Read root metadata (database-level schema information)
|
|
170
|
+
*/
|
|
171
|
+
async readRootMetaHandler(_ctx) {
|
|
172
|
+
await this.ensureInitialized();
|
|
173
|
+
const schemas = await this.schemaService.getAllSchemas();
|
|
174
|
+
const tables = Array.from(schemas.entries()).sort((a, b) => a[0].localeCompare(b[0])).map(([name, schema]) => ({
|
|
175
|
+
name,
|
|
176
|
+
description: `Table with ${schema.columns.length} columns`,
|
|
177
|
+
columnCount: schema.columns.length,
|
|
178
|
+
primaryKey: schema.primaryKey
|
|
179
|
+
}));
|
|
180
|
+
return {
|
|
181
|
+
id: "root:.meta",
|
|
182
|
+
path: "/.meta",
|
|
183
|
+
content: {
|
|
184
|
+
type: "sqlite",
|
|
185
|
+
tableCount: schemas.size,
|
|
186
|
+
tables
|
|
187
|
+
},
|
|
188
|
+
meta: {
|
|
189
|
+
childrenCount: tables.length,
|
|
190
|
+
tables: tables.map((t) => t.name)
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Read capabilities manifest
|
|
196
|
+
* Returns information about available actions at different levels
|
|
197
|
+
*/
|
|
198
|
+
async readCapabilitiesHandler(_ctx) {
|
|
199
|
+
await this.ensureInitialized();
|
|
200
|
+
const actionCatalogs = [];
|
|
201
|
+
const rootActions = this.actions.listWithInfo({ rootLevel: true }, { schemaService: this.schemaService });
|
|
202
|
+
if (rootActions.length > 0) actionCatalogs.push({
|
|
203
|
+
kind: "sqlite:root",
|
|
204
|
+
description: "Database-level operations",
|
|
205
|
+
catalog: rootActions.map((a) => ({
|
|
206
|
+
name: a.name,
|
|
207
|
+
description: a.description,
|
|
208
|
+
inputSchema: a.inputSchema
|
|
209
|
+
})),
|
|
210
|
+
discovery: {
|
|
211
|
+
pathTemplate: "/.actions",
|
|
212
|
+
note: "Available at database root"
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
const tableActions = this.actions.listWithInfo({ tableLevel: true }, { schemaService: this.schemaService });
|
|
216
|
+
if (tableActions.length > 0) actionCatalogs.push({
|
|
217
|
+
kind: "sqlite:table",
|
|
218
|
+
description: "Table-level operations",
|
|
219
|
+
catalog: tableActions.map((a) => ({
|
|
220
|
+
name: a.name,
|
|
221
|
+
description: a.description,
|
|
222
|
+
inputSchema: a.inputSchema
|
|
223
|
+
})),
|
|
224
|
+
discovery: {
|
|
225
|
+
pathTemplate: "/:table/.actions",
|
|
226
|
+
note: "Replace :table with actual table name"
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
const rowActions = this.actions.listWithInfo({ rowLevel: true }, { schemaService: this.schemaService });
|
|
230
|
+
if (rowActions.length > 0) actionCatalogs.push({
|
|
231
|
+
kind: "sqlite:row",
|
|
232
|
+
description: "Row-level operations",
|
|
233
|
+
catalog: rowActions.map((a) => ({
|
|
234
|
+
name: a.name,
|
|
235
|
+
description: a.description,
|
|
236
|
+
inputSchema: a.inputSchema
|
|
237
|
+
})),
|
|
238
|
+
discovery: {
|
|
239
|
+
pathTemplate: "/:table/:pk/.actions",
|
|
240
|
+
note: "Replace :table with table name, :pk with primary key value"
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
return {
|
|
244
|
+
id: "/.meta/.capabilities",
|
|
245
|
+
path: "/.meta/.capabilities",
|
|
246
|
+
content: {
|
|
247
|
+
schemaVersion: 1,
|
|
248
|
+
provider: this.name,
|
|
249
|
+
version: "1.0.0",
|
|
250
|
+
description: this.description,
|
|
251
|
+
tools: [],
|
|
252
|
+
actions: actionCatalogs,
|
|
253
|
+
operations: this.getOperationsDeclaration()
|
|
254
|
+
},
|
|
255
|
+
meta: { kind: "afs:capabilities" }
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Read table (directory) entry
|
|
260
|
+
*/
|
|
261
|
+
async readTableHandler(ctx) {
|
|
262
|
+
await this.ensureInitialized();
|
|
263
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
264
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
265
|
+
const rowCount = (await this.db.all(_aigne_sqlite.sql.raw(`SELECT COUNT(*) as count FROM "${ctx.params.table}"`)))[0]?.count ?? 0;
|
|
266
|
+
return require_builder.buildTableEntry(ctx.params.table, schema, {
|
|
267
|
+
basePath: "",
|
|
268
|
+
rowCount
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Read table metadata (table-level schema information)
|
|
273
|
+
*/
|
|
274
|
+
async readTableMetaHandler(ctx) {
|
|
275
|
+
await this.ensureInitialized();
|
|
276
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
277
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
278
|
+
const rowCount = (await this.db.all(_aigne_sqlite.sql.raw(`SELECT COUNT(*) as count FROM "${ctx.params.table}"`)))[0]?.count ?? 0;
|
|
279
|
+
const columns = schema.columns.map((col) => ({
|
|
280
|
+
name: col.name,
|
|
281
|
+
type: col.type,
|
|
282
|
+
nullable: !col.notnull,
|
|
283
|
+
primaryKey: col.pk > 0,
|
|
284
|
+
defaultValue: col.dfltValue
|
|
285
|
+
}));
|
|
286
|
+
return {
|
|
287
|
+
id: `${ctx.params.table}:.meta`,
|
|
288
|
+
path: `/${ctx.params.table}/.meta`,
|
|
289
|
+
content: {
|
|
290
|
+
table: ctx.params.table,
|
|
291
|
+
columns,
|
|
292
|
+
primaryKey: schema.primaryKey,
|
|
293
|
+
foreignKeys: schema.foreignKeys.map((fk) => ({
|
|
294
|
+
column: fk.from,
|
|
295
|
+
referencesTable: fk.table,
|
|
296
|
+
referencesColumn: fk.to,
|
|
297
|
+
onUpdate: fk.onUpdate,
|
|
298
|
+
onDelete: fk.onDelete
|
|
299
|
+
})),
|
|
300
|
+
indexes: schema.indexes.map((idx) => ({
|
|
301
|
+
name: idx.name,
|
|
302
|
+
unique: idx.unique,
|
|
303
|
+
origin: idx.origin
|
|
304
|
+
})),
|
|
305
|
+
rowCount
|
|
306
|
+
},
|
|
307
|
+
meta: {
|
|
308
|
+
table: ctx.params.table,
|
|
309
|
+
description: `Table "${ctx.params.table}" with ${columns.length} columns`,
|
|
310
|
+
childrenCount: rowCount,
|
|
311
|
+
columnCount: columns.length,
|
|
312
|
+
columns: columns.map((c) => c.name),
|
|
313
|
+
primaryKey: schema.primaryKey
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Read a row
|
|
319
|
+
*/
|
|
320
|
+
async readRowHandler(ctx) {
|
|
321
|
+
await this.ensureInitialized();
|
|
322
|
+
return (await this.crud.readRow(ctx.params.table, ctx.params.pk)).data;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Get row metadata (@meta suffix - SQLite-specific)
|
|
326
|
+
*/
|
|
327
|
+
async getMetaHandler(ctx) {
|
|
328
|
+
await this.ensureInitialized();
|
|
329
|
+
return (await this.crud.getMeta(ctx.params.table, ctx.params.pk)).data;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Get row metadata (.meta suffix - row-level schema information)
|
|
333
|
+
*/
|
|
334
|
+
async getRowDotMetaHandler(ctx) {
|
|
335
|
+
await this.ensureInitialized();
|
|
336
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
337
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
338
|
+
if (!(await this.crud.readRow(ctx.params.table, ctx.params.pk)).data) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}/${ctx.params.pk}`);
|
|
339
|
+
const pkColumn = schema.primaryKey[0] ?? "rowid";
|
|
340
|
+
return {
|
|
341
|
+
id: `${ctx.params.table}:${ctx.params.pk}:.meta`,
|
|
342
|
+
path: `/${ctx.params.table}/${ctx.params.pk}/.meta`,
|
|
343
|
+
content: {
|
|
344
|
+
table: ctx.params.table,
|
|
345
|
+
primaryKey: pkColumn,
|
|
346
|
+
primaryKeyValue: ctx.params.pk,
|
|
347
|
+
columns: schema.columns.map((col) => ({
|
|
348
|
+
name: col.name,
|
|
349
|
+
type: col.type,
|
|
350
|
+
nullable: !col.notnull,
|
|
351
|
+
primaryKey: col.pk > 0
|
|
352
|
+
})),
|
|
353
|
+
foreignKeys: schema.foreignKeys.map((fk) => ({
|
|
354
|
+
column: fk.from,
|
|
355
|
+
referencesTable: fk.table,
|
|
356
|
+
referencesColumn: fk.to
|
|
357
|
+
}))
|
|
358
|
+
},
|
|
359
|
+
meta: {
|
|
360
|
+
table: ctx.params.table,
|
|
361
|
+
primaryKeyValue: ctx.params.pk,
|
|
362
|
+
columns: schema.columns.map((col) => col.name)
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Create a new row
|
|
368
|
+
*/
|
|
369
|
+
async createRowHandler(ctx, content) {
|
|
370
|
+
await this.ensureInitialized();
|
|
371
|
+
return this.crud.createRow(ctx.params.table, content.content ?? content);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Update an existing row
|
|
375
|
+
*/
|
|
376
|
+
async updateRowHandler(ctx, content) {
|
|
377
|
+
await this.ensureInitialized();
|
|
378
|
+
return this.crud.updateRow(ctx.params.table, ctx.params.pk, content.content ?? content);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Execute action via write (for triggering row-level actions)
|
|
382
|
+
*/
|
|
383
|
+
async executeActionWriteHandler(ctx, content) {
|
|
384
|
+
await this.ensureInitialized();
|
|
385
|
+
return this.executeAction(ctx.params.table, ctx.params.pk, ctx.params.action, content.content ?? content);
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Execute action via write (for triggering table-level actions)
|
|
389
|
+
*/
|
|
390
|
+
async executeTableActionWriteHandler(ctx, content) {
|
|
391
|
+
await this.ensureInitialized();
|
|
392
|
+
return this.executeAction(ctx.params.table, void 0, ctx.params.action, content.content ?? content);
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Execute action via write (for triggering root-level actions)
|
|
396
|
+
*/
|
|
397
|
+
async executeRootActionWriteHandler(ctx, content) {
|
|
398
|
+
await this.ensureInitialized();
|
|
399
|
+
return this.executeRootAction(ctx.params.action, content.content ?? content);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Delete a table entry (not supported - always throws)
|
|
403
|
+
*/
|
|
404
|
+
async deleteTableHandler(ctx) {
|
|
405
|
+
await this.ensureInitialized();
|
|
406
|
+
if (!await this.schemaService.hasTable(ctx.params.table)) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
407
|
+
throw new Error(`Cannot delete table '${ctx.params.table}'. Use SQL directly to drop tables.`);
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* Delete a row
|
|
411
|
+
*/
|
|
412
|
+
async deleteRowHandler(ctx) {
|
|
413
|
+
await this.ensureInitialized();
|
|
414
|
+
return this.crud.deleteRow(ctx.params.table, ctx.params.pk);
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Search all tables
|
|
418
|
+
*/
|
|
419
|
+
async searchAllHandler(_ctx, query, options) {
|
|
420
|
+
await this.ensureInitialized();
|
|
421
|
+
return this.ftsSearch.search(query, options);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Search a specific table
|
|
425
|
+
*/
|
|
426
|
+
async searchTableHandler(ctx, query, options) {
|
|
427
|
+
await this.ensureInitialized();
|
|
428
|
+
return this.ftsSearch.searchTable(ctx.params.table, query, options);
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Get stat for root (database level)
|
|
432
|
+
*/
|
|
433
|
+
async statRootHandler(_ctx) {
|
|
434
|
+
await this.ensureInitialized();
|
|
435
|
+
const schemas = await this.schemaService.getAllSchemas();
|
|
436
|
+
const actions = this.actions.listWithInfo({ rootLevel: true }, { schemaService: this.schemaService });
|
|
437
|
+
return { data: {
|
|
438
|
+
id: "/",
|
|
439
|
+
path: "/",
|
|
440
|
+
meta: {
|
|
441
|
+
kind: "sqlite:database",
|
|
442
|
+
kinds: ["sqlite:database", "afs:node"],
|
|
443
|
+
tableCount: schemas.size,
|
|
444
|
+
childrenCount: schemas.size
|
|
445
|
+
},
|
|
446
|
+
actions: actions.length > 0 ? actions.map((a) => ({
|
|
447
|
+
name: a.name,
|
|
448
|
+
description: a.description
|
|
449
|
+
})) : void 0
|
|
450
|
+
} };
|
|
102
451
|
}
|
|
103
452
|
/**
|
|
104
|
-
*
|
|
105
|
-
*/
|
|
106
|
-
async
|
|
107
|
-
await this.ensureInitialized();
|
|
108
|
-
const
|
|
109
|
-
if (!
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
453
|
+
* Get stat for a table
|
|
454
|
+
*/
|
|
455
|
+
async statTableHandler(ctx) {
|
|
456
|
+
await this.ensureInitialized();
|
|
457
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
458
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
459
|
+
const rowCount = (await this.db.all(_aigne_sqlite.sql.raw(`SELECT COUNT(*) as count FROM "${ctx.params.table}"`)))[0]?.count ?? 0;
|
|
460
|
+
const actions = this.actions.listWithInfo({ tableLevel: true }, {
|
|
461
|
+
tableSchema: schema,
|
|
462
|
+
tableName: ctx.params.table,
|
|
463
|
+
schemaService: this.schemaService
|
|
464
|
+
});
|
|
465
|
+
const columns = schema.columns.map((col) => ({
|
|
466
|
+
name: col.name,
|
|
467
|
+
type: col.type,
|
|
468
|
+
nullable: !col.notnull,
|
|
469
|
+
primaryKey: col.pk > 0
|
|
470
|
+
}));
|
|
471
|
+
return { data: {
|
|
472
|
+
id: ctx.params.table,
|
|
473
|
+
path: `/${ctx.params.table}`,
|
|
474
|
+
meta: {
|
|
475
|
+
kind: "sqlite:table",
|
|
476
|
+
kinds: ["sqlite:table", "afs:node"],
|
|
477
|
+
table: ctx.params.table,
|
|
478
|
+
columnCount: schema.columns.length,
|
|
479
|
+
columns,
|
|
480
|
+
primaryKey: schema.primaryKey[0],
|
|
481
|
+
childrenCount: rowCount
|
|
482
|
+
},
|
|
483
|
+
actions: actions.length > 0 ? actions.map((a) => ({
|
|
484
|
+
name: a.name,
|
|
485
|
+
description: a.description
|
|
486
|
+
})) : void 0
|
|
487
|
+
} };
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Get stat for a row
|
|
491
|
+
*/
|
|
492
|
+
async statRowHandler(ctx) {
|
|
493
|
+
await this.ensureInitialized();
|
|
494
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
495
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
496
|
+
if (!(await this.crud.readRow(ctx.params.table, ctx.params.pk)).data) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}/${ctx.params.pk}`);
|
|
497
|
+
const actions = this.actions.listWithInfo({ rowLevel: true }, {
|
|
498
|
+
tableSchema: schema,
|
|
499
|
+
tableName: ctx.params.table,
|
|
500
|
+
schemaService: this.schemaService
|
|
501
|
+
});
|
|
502
|
+
const columns = schema.columns.map((col) => ({
|
|
503
|
+
name: col.name,
|
|
504
|
+
type: col.type,
|
|
505
|
+
nullable: !col.notnull,
|
|
506
|
+
primaryKey: col.pk > 0
|
|
507
|
+
}));
|
|
508
|
+
return { data: {
|
|
509
|
+
id: ctx.params.pk,
|
|
510
|
+
path: `/${ctx.params.table}/${ctx.params.pk}`,
|
|
511
|
+
meta: {
|
|
512
|
+
kind: "sqlite:row",
|
|
513
|
+
kinds: ["sqlite:row", "afs:node"],
|
|
514
|
+
table: ctx.params.table,
|
|
515
|
+
primaryKey: ctx.params.pk,
|
|
516
|
+
columnCount: schema.columns.length,
|
|
517
|
+
columns,
|
|
518
|
+
childrenCount: 0
|
|
519
|
+
},
|
|
520
|
+
actions: actions.length > 0 ? actions.map((a) => ({
|
|
521
|
+
name: a.name,
|
|
522
|
+
description: a.description
|
|
523
|
+
})) : void 0
|
|
524
|
+
} };
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Explain root (database level)
|
|
528
|
+
*/
|
|
529
|
+
async explainRootHandler(ctx) {
|
|
530
|
+
await this.ensureInitialized();
|
|
531
|
+
const format = ctx.options?.format || "markdown";
|
|
532
|
+
const schemas = await this.schemaService.getAllSchemas();
|
|
533
|
+
const tables = Array.from(schemas.values());
|
|
534
|
+
const lines = [];
|
|
535
|
+
if (format === "markdown") {
|
|
536
|
+
lines.push(`# ${this.name}`);
|
|
537
|
+
lines.push("");
|
|
538
|
+
lines.push(`**Type:** SQLite Database`);
|
|
539
|
+
lines.push(`**Tables:** ${tables.length}`);
|
|
540
|
+
lines.push("");
|
|
541
|
+
if (tables.length > 0) {
|
|
542
|
+
lines.push("## Tables");
|
|
543
|
+
lines.push("");
|
|
544
|
+
lines.push("| Table | Columns | Primary Key |");
|
|
545
|
+
lines.push("|-------|---------|-------------|");
|
|
546
|
+
for (const table of tables) {
|
|
547
|
+
const pk = table.primaryKey.join(", ") || "rowid";
|
|
548
|
+
lines.push(`| ${table.name} | ${table.columns.length} | ${pk} |`);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
} else {
|
|
552
|
+
lines.push(`${this.name} (SQLite Database)`);
|
|
553
|
+
lines.push(`Tables: ${tables.length}`);
|
|
554
|
+
for (const table of tables) lines.push(` - ${table.name} (${table.columns.length} columns)`);
|
|
124
555
|
}
|
|
556
|
+
return {
|
|
557
|
+
content: lines.join("\n"),
|
|
558
|
+
format
|
|
559
|
+
};
|
|
125
560
|
}
|
|
126
561
|
/**
|
|
127
|
-
*
|
|
128
|
-
*/
|
|
129
|
-
async
|
|
130
|
-
await this.ensureInitialized();
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
if (!
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
562
|
+
* Explain a table
|
|
563
|
+
*/
|
|
564
|
+
async explainTableHandler(ctx) {
|
|
565
|
+
await this.ensureInitialized();
|
|
566
|
+
const format = ctx.options?.format || "markdown";
|
|
567
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
568
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
569
|
+
const rowCount = (await this.db.all(_aigne_sqlite.sql.raw(`SELECT COUNT(*) as count FROM "${ctx.params.table}"`)))[0]?.count ?? 0;
|
|
570
|
+
const lines = [];
|
|
571
|
+
if (format === "markdown") {
|
|
572
|
+
lines.push(`# ${ctx.params.table}`);
|
|
573
|
+
lines.push("");
|
|
574
|
+
lines.push(`**Type:** SQLite Table`);
|
|
575
|
+
lines.push(`**Rows:** ${rowCount}`);
|
|
576
|
+
lines.push(`**Primary Key:** ${schema.primaryKey.join(", ") || "rowid"}`);
|
|
577
|
+
lines.push("");
|
|
578
|
+
lines.push("## Columns");
|
|
579
|
+
lines.push("");
|
|
580
|
+
lines.push("| Column | Type | Nullable | Primary Key | Default |");
|
|
581
|
+
lines.push("|--------|------|----------|-------------|---------|");
|
|
582
|
+
for (const col of schema.columns) {
|
|
583
|
+
const nullable = col.notnull ? "NO" : "YES";
|
|
584
|
+
const pk = col.pk > 0 ? "YES" : "";
|
|
585
|
+
const dflt = col.dfltValue !== null && col.dfltValue !== void 0 ? String(col.dfltValue) : "";
|
|
586
|
+
lines.push(`| ${col.name} | ${col.type} | ${nullable} | ${pk} | ${dflt} |`);
|
|
587
|
+
}
|
|
588
|
+
if (schema.indexes.length > 0) {
|
|
589
|
+
lines.push("");
|
|
590
|
+
lines.push("## Indexes");
|
|
591
|
+
lines.push("");
|
|
592
|
+
for (const idx of schema.indexes) {
|
|
593
|
+
const uniqueStr = idx.unique ? " (UNIQUE)" : "";
|
|
594
|
+
lines.push(`- **${idx.name}**${uniqueStr}`);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (schema.foreignKeys.length > 0) {
|
|
598
|
+
lines.push("");
|
|
599
|
+
lines.push("## Foreign Keys");
|
|
600
|
+
lines.push("");
|
|
601
|
+
for (const fk of schema.foreignKeys) lines.push(`- \`${fk.from}\` → \`${fk.table}\`(\`${fk.to}\`) ON DELETE ${fk.onDelete}`);
|
|
602
|
+
}
|
|
603
|
+
} else {
|
|
604
|
+
lines.push(`${ctx.params.table} (SQLite Table)`);
|
|
605
|
+
lines.push(`Rows: ${rowCount}`);
|
|
606
|
+
lines.push(`Primary Key: ${schema.primaryKey.join(", ") || "rowid"}`);
|
|
607
|
+
lines.push(`Columns: ${schema.columns.map((c) => `${c.name} (${c.type})`).join(", ")}`);
|
|
608
|
+
if (schema.indexes.length > 0) lines.push(`Indexes: ${schema.indexes.map((i) => i.name).join(", ")}`);
|
|
609
|
+
if (schema.foreignKeys.length > 0) lines.push(`Foreign Keys: ${schema.foreignKeys.map((fk) => `${fk.from} → ${fk.table}(${fk.to})`).join(", ")}`);
|
|
145
610
|
}
|
|
611
|
+
return {
|
|
612
|
+
content: lines.join("\n"),
|
|
613
|
+
format
|
|
614
|
+
};
|
|
146
615
|
}
|
|
147
616
|
/**
|
|
148
|
-
*
|
|
617
|
+
* Explain a row
|
|
149
618
|
*/
|
|
150
|
-
async
|
|
619
|
+
async explainRowHandler(ctx) {
|
|
151
620
|
await this.ensureInitialized();
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
if (!
|
|
155
|
-
|
|
156
|
-
|
|
621
|
+
const format = ctx.options?.format || "markdown";
|
|
622
|
+
const schema = await this.schemaService.getSchema(ctx.params.table);
|
|
623
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}`);
|
|
624
|
+
const result = await this.crud.readRow(ctx.params.table, ctx.params.pk);
|
|
625
|
+
if (!result.data) throw new _aigne_afs.AFSNotFoundError(`/${ctx.params.table}/${ctx.params.pk}`);
|
|
626
|
+
const rowContent = result.data.content;
|
|
627
|
+
const pkColumn = schema.primaryKey[0] ?? "rowid";
|
|
628
|
+
const lines = [];
|
|
629
|
+
if (format === "markdown") {
|
|
630
|
+
lines.push(`# ${ctx.params.table}/${ctx.params.pk}`);
|
|
631
|
+
lines.push("");
|
|
632
|
+
lines.push(`**Table:** ${ctx.params.table}`);
|
|
633
|
+
lines.push(`**Primary Key:** ${pkColumn} = ${ctx.params.pk}`);
|
|
634
|
+
lines.push("");
|
|
635
|
+
if (rowContent) {
|
|
636
|
+
lines.push("## Values");
|
|
637
|
+
lines.push("");
|
|
638
|
+
lines.push("| Column | Value |");
|
|
639
|
+
lines.push("|--------|-------|");
|
|
640
|
+
for (const col of schema.columns) {
|
|
641
|
+
const val = rowContent[col.name];
|
|
642
|
+
const displayVal = val === null || val === void 0 ? "*null*" : truncateValue(String(val), 100);
|
|
643
|
+
lines.push(`| ${col.name} | ${displayVal} |`);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
} else {
|
|
647
|
+
lines.push(`${ctx.params.table}/${ctx.params.pk} (SQLite Row)`);
|
|
648
|
+
lines.push(`Table: ${ctx.params.table}, ${pkColumn} = ${ctx.params.pk}`);
|
|
649
|
+
if (rowContent) for (const col of schema.columns) {
|
|
650
|
+
const val = rowContent[col.name];
|
|
651
|
+
lines.push(` ${col.name}: ${val === null || val === void 0 ? "null" : truncateValue(String(val), 100)}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
return {
|
|
655
|
+
content: lines.join("\n"),
|
|
656
|
+
format
|
|
657
|
+
};
|
|
157
658
|
}
|
|
158
659
|
/**
|
|
159
|
-
*
|
|
660
|
+
* Execute action via exec (row-level)
|
|
160
661
|
*/
|
|
161
|
-
async
|
|
662
|
+
async handleRowActionExec(ctx, args) {
|
|
162
663
|
await this.ensureInitialized();
|
|
163
|
-
|
|
164
|
-
if (match?.params.table) return this.ftsSearch.searchTable(match.params.table, query, options);
|
|
165
|
-
return this.ftsSearch.search(query, options);
|
|
664
|
+
return this.executeActionRaw(ctx.params.table, ctx.params.pk, ctx.params.action, args);
|
|
166
665
|
}
|
|
167
666
|
/**
|
|
168
|
-
*
|
|
667
|
+
* Execute action via exec (table-level)
|
|
169
668
|
*/
|
|
170
|
-
async
|
|
669
|
+
async handleTableActionExec(ctx, args) {
|
|
171
670
|
await this.ensureInitialized();
|
|
172
|
-
|
|
173
|
-
if (match?.action === "executeAction" && match.params.table && match.params.action) return { data: (await this.executeAction(match.params.table, match.params.pk, match.params.action, args)).data };
|
|
174
|
-
throw new Error(`Exec not supported for path: ${path}`);
|
|
671
|
+
return this.executeActionRaw(ctx.params.table, void 0, ctx.params.action, args);
|
|
175
672
|
}
|
|
176
673
|
/**
|
|
177
|
-
*
|
|
674
|
+
* Execute action via exec (root-level)
|
|
178
675
|
*/
|
|
179
|
-
|
|
180
|
-
|
|
676
|
+
async handleRootActionExec(ctx, args) {
|
|
677
|
+
await this.ensureInitialized();
|
|
678
|
+
return this.executeRootActionRaw(ctx.params.action, args);
|
|
181
679
|
}
|
|
182
680
|
/**
|
|
183
|
-
* Executes an action
|
|
681
|
+
* Executes an action and returns raw result (for exec handlers)
|
|
682
|
+
* Returns AFSExecResult structure: { success: boolean, data?: Record<string, unknown> }
|
|
184
683
|
*/
|
|
185
|
-
async
|
|
186
|
-
if (!this.
|
|
684
|
+
async executeActionRaw(table, pk, actionName, params) {
|
|
685
|
+
if (!await this.schemaService.getSchema(table)) throw new _aigne_afs.AFSNotFoundError(`/${table}`);
|
|
187
686
|
let row;
|
|
188
687
|
if (pk) row = (await this.crud.readRow(table, pk)).data?.content;
|
|
189
688
|
const ctx = {
|
|
190
689
|
db: this.db,
|
|
191
|
-
|
|
690
|
+
schemaService: this.schemaService,
|
|
192
691
|
table,
|
|
193
692
|
pk,
|
|
194
693
|
row,
|
|
195
|
-
module: {
|
|
196
|
-
refreshSchema: () => this.refreshSchema(),
|
|
197
|
-
exportTable: (t, f) => this.exportTable(t, f)
|
|
198
|
-
}
|
|
694
|
+
module: { exportTable: (t, f) => this.exportTable(t, f) }
|
|
199
695
|
};
|
|
200
696
|
const result = await this.actions.execute(actionName, ctx, params);
|
|
201
697
|
if (!result.success) throw new Error(result.message ?? "Action failed");
|
|
698
|
+
if (Array.isArray(result.data)) return {
|
|
699
|
+
success: true,
|
|
700
|
+
data: { data: result.data }
|
|
701
|
+
};
|
|
702
|
+
return {
|
|
703
|
+
success: true,
|
|
704
|
+
data: result.data
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* Executes a root-level action and returns raw result (for exec handlers)
|
|
709
|
+
* Returns AFSExecResult structure: { success: boolean, data?: Record<string, unknown> }
|
|
710
|
+
*/
|
|
711
|
+
async executeRootActionRaw(actionName, params) {
|
|
712
|
+
const ctx = {
|
|
713
|
+
db: this.db,
|
|
714
|
+
schemaService: this.schemaService,
|
|
715
|
+
table: "",
|
|
716
|
+
module: { exportTable: (t, f) => this.exportTable(t, f) }
|
|
717
|
+
};
|
|
718
|
+
const result = await this.actions.execute(actionName, ctx, params);
|
|
719
|
+
if (!result.success) throw new Error(result.message ?? "Action failed");
|
|
720
|
+
if (Array.isArray(result.data)) return {
|
|
721
|
+
success: true,
|
|
722
|
+
data: { data: result.data }
|
|
723
|
+
};
|
|
724
|
+
return {
|
|
725
|
+
success: true,
|
|
726
|
+
data: result.data
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Executes an action (for write handlers - wraps in AFSEntry)
|
|
731
|
+
*/
|
|
732
|
+
async executeAction(table, pk, actionName, params) {
|
|
733
|
+
const result = await this.executeActionRaw(table, pk, actionName, params);
|
|
202
734
|
return { data: {
|
|
203
|
-
id: `${table}:${pk ?? ""}
|
|
204
|
-
path: pk ? `/${table}/${pk}
|
|
205
|
-
content: result
|
|
735
|
+
id: `${table}:${pk ?? ""}:.actions:${actionName}`,
|
|
736
|
+
path: pk ? `/${table}/${pk}/.actions/${actionName}` : `/${table}/.actions/${actionName}`,
|
|
737
|
+
content: result
|
|
206
738
|
} };
|
|
207
739
|
}
|
|
208
740
|
/**
|
|
209
|
-
*
|
|
741
|
+
* Executes a root-level action (for write handlers - wraps in AFSEntry)
|
|
210
742
|
*/
|
|
211
|
-
async
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
this.ftsSearch.setSchemas(this.schemas);
|
|
743
|
+
async executeRootAction(actionName, params) {
|
|
744
|
+
const result = await this.executeRootActionRaw(actionName, params);
|
|
745
|
+
return { data: {
|
|
746
|
+
id: `:.actions:${actionName}`,
|
|
747
|
+
path: `/.actions/${actionName}`,
|
|
748
|
+
content: result
|
|
749
|
+
} };
|
|
219
750
|
}
|
|
220
751
|
/**
|
|
221
752
|
* Exports table data in specified format
|
|
@@ -223,8 +754,8 @@ var SQLiteAFS = class SQLiteAFS {
|
|
|
223
754
|
async exportTable(table, format) {
|
|
224
755
|
const listResult = await this.crud.listTable(table, { limit: 1e4 });
|
|
225
756
|
if (format === "csv") {
|
|
226
|
-
const schema = this.
|
|
227
|
-
if (!schema) throw new
|
|
757
|
+
const schema = await this.schemaService.getSchema(table);
|
|
758
|
+
if (!schema) throw new _aigne_afs.AFSNotFoundError(`/${table}`);
|
|
228
759
|
return `${schema.columns.map((c) => c.name).join(",")}\n${listResult.data.map((entry) => {
|
|
229
760
|
const content = entry.content;
|
|
230
761
|
return schema.columns.map((c) => {
|
|
@@ -248,9 +779,11 @@ var SQLiteAFS = class SQLiteAFS {
|
|
|
248
779
|
}
|
|
249
780
|
/**
|
|
250
781
|
* Gets table schemas (for external access)
|
|
782
|
+
* Note: This queries the database on-demand
|
|
251
783
|
*/
|
|
252
|
-
getSchemas() {
|
|
253
|
-
|
|
784
|
+
async getSchemas() {
|
|
785
|
+
await this.ensureInitialized();
|
|
786
|
+
return this.schemaService.getAllSchemas();
|
|
254
787
|
}
|
|
255
788
|
/**
|
|
256
789
|
* Gets the database instance (for advanced operations)
|
|
@@ -259,6 +792,45 @@ var SQLiteAFS = class SQLiteAFS {
|
|
|
259
792
|
return this.db;
|
|
260
793
|
}
|
|
261
794
|
};
|
|
795
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/")], SQLiteAFS.prototype, "listTablesHandler", null);
|
|
796
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/:table")], SQLiteAFS.prototype, "listTableHandler", null);
|
|
797
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.List)("/:table/:pk")], SQLiteAFS.prototype, "listRowHandler", null);
|
|
798
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/:table/:pk")], SQLiteAFS.prototype, "listActionsHandler", null);
|
|
799
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/:table")], SQLiteAFS.prototype, "listTableActionsHandler", null);
|
|
800
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Actions)("/")], SQLiteAFS.prototype, "listRootActionsHandler", null);
|
|
801
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/")], SQLiteAFS.prototype, "readRootHandler", null);
|
|
802
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/")], SQLiteAFS.prototype, "readRootMetaHandler", null);
|
|
803
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/.meta/.capabilities")], SQLiteAFS.prototype, "readCapabilitiesHandler", null);
|
|
804
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:table")], SQLiteAFS.prototype, "readTableHandler", null);
|
|
805
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/:table")], SQLiteAFS.prototype, "readTableMetaHandler", null);
|
|
806
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:table/:pk")], SQLiteAFS.prototype, "readRowHandler", null);
|
|
807
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Read)("/:table/:pk/@meta")], SQLiteAFS.prototype, "getMetaHandler", null);
|
|
808
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Meta)("/:table/:pk")], SQLiteAFS.prototype, "getRowDotMetaHandler", null);
|
|
809
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/:table/new")], SQLiteAFS.prototype, "createRowHandler", null);
|
|
810
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/:table/:pk")], SQLiteAFS.prototype, "updateRowHandler", null);
|
|
811
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/:table/:pk/.actions/:action")], SQLiteAFS.prototype, "executeActionWriteHandler", null);
|
|
812
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/:table/.actions/:action")], SQLiteAFS.prototype, "executeTableActionWriteHandler", null);
|
|
813
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Write)("/.actions/:action")], SQLiteAFS.prototype, "executeRootActionWriteHandler", null);
|
|
814
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Delete)("/:table")], SQLiteAFS.prototype, "deleteTableHandler", null);
|
|
815
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Delete)("/:table/:pk")], SQLiteAFS.prototype, "deleteRowHandler", null);
|
|
816
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Search)("/")], SQLiteAFS.prototype, "searchAllHandler", null);
|
|
817
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Search)("/:table")], SQLiteAFS.prototype, "searchTableHandler", null);
|
|
818
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/")], SQLiteAFS.prototype, "statRootHandler", null);
|
|
819
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/:table")], SQLiteAFS.prototype, "statTableHandler", null);
|
|
820
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Stat)("/:table/:pk")], SQLiteAFS.prototype, "statRowHandler", null);
|
|
821
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/")], SQLiteAFS.prototype, "explainRootHandler", null);
|
|
822
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/:table")], SQLiteAFS.prototype, "explainTableHandler", null);
|
|
823
|
+
require_decorate.__decorate([(0, _aigne_afs_provider.Explain)("/:table/:pk")], SQLiteAFS.prototype, "explainRowHandler", null);
|
|
824
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/:table/:pk")], SQLiteAFS.prototype, "handleRowActionExec", null);
|
|
825
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/:table")], SQLiteAFS.prototype, "handleTableActionExec", null);
|
|
826
|
+
require_decorate.__decorate([_aigne_afs_provider.Actions.Exec("/")], SQLiteAFS.prototype, "handleRootActionExec", null);
|
|
827
|
+
/**
|
|
828
|
+
* Truncate a string value for display purposes.
|
|
829
|
+
*/
|
|
830
|
+
function truncateValue(value, maxLength) {
|
|
831
|
+
if (value.length <= maxLength) return value;
|
|
832
|
+
return `${value.slice(0, maxLength)}...`;
|
|
833
|
+
}
|
|
262
834
|
|
|
263
835
|
//#endregion
|
|
264
836
|
exports.SQLiteAFS = SQLiteAFS;
|