@aigne/afs-sqlite 1.0.1-beta
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/CHANGELOG.md +29 -0
- package/LICENSE.md +93 -0
- package/README.md +277 -0
- package/lib/cjs/actions/built-in.d.ts +5 -0
- package/lib/cjs/actions/built-in.js +165 -0
- package/lib/cjs/actions/registry.d.ts +49 -0
- package/lib/cjs/actions/registry.js +102 -0
- package/lib/cjs/actions/types.d.ts +51 -0
- package/lib/cjs/actions/types.js +2 -0
- package/lib/cjs/config.d.ts +89 -0
- package/lib/cjs/config.js +33 -0
- package/lib/cjs/index.d.ts +13 -0
- package/lib/cjs/index.js +47 -0
- package/lib/cjs/node/builder.d.ts +43 -0
- package/lib/cjs/node/builder.js +187 -0
- package/lib/cjs/operations/crud.d.ts +64 -0
- package/lib/cjs/operations/crud.js +225 -0
- package/lib/cjs/operations/query-builder.d.ts +37 -0
- package/lib/cjs/operations/query-builder.js +102 -0
- package/lib/cjs/operations/search.d.ts +75 -0
- package/lib/cjs/operations/search.js +172 -0
- package/lib/cjs/package.json +3 -0
- package/lib/cjs/router/path-router.d.ts +38 -0
- package/lib/cjs/router/path-router.js +90 -0
- package/lib/cjs/router/types.d.ts +30 -0
- package/lib/cjs/router/types.js +2 -0
- package/lib/cjs/schema/introspector.d.ts +48 -0
- package/lib/cjs/schema/introspector.js +186 -0
- package/lib/cjs/schema/types.d.ts +104 -0
- package/lib/cjs/schema/types.js +13 -0
- package/lib/cjs/sqlite-afs.d.ts +144 -0
- package/lib/cjs/sqlite-afs.js +337 -0
- package/lib/dts/actions/built-in.d.ts +5 -0
- package/lib/dts/actions/registry.d.ts +49 -0
- package/lib/dts/actions/types.d.ts +51 -0
- package/lib/dts/config.d.ts +89 -0
- package/lib/dts/index.d.ts +13 -0
- package/lib/dts/node/builder.d.ts +43 -0
- package/lib/dts/operations/crud.d.ts +64 -0
- package/lib/dts/operations/query-builder.d.ts +37 -0
- package/lib/dts/operations/search.d.ts +75 -0
- package/lib/dts/router/path-router.d.ts +38 -0
- package/lib/dts/router/types.d.ts +30 -0
- package/lib/dts/schema/introspector.d.ts +48 -0
- package/lib/dts/schema/types.d.ts +104 -0
- package/lib/dts/sqlite-afs.d.ts +144 -0
- package/lib/esm/actions/built-in.d.ts +5 -0
- package/lib/esm/actions/built-in.js +162 -0
- package/lib/esm/actions/registry.d.ts +49 -0
- package/lib/esm/actions/registry.js +98 -0
- package/lib/esm/actions/types.d.ts +51 -0
- package/lib/esm/actions/types.js +1 -0
- package/lib/esm/config.d.ts +89 -0
- package/lib/esm/config.js +30 -0
- package/lib/esm/index.d.ts +13 -0
- package/lib/esm/index.js +17 -0
- package/lib/esm/node/builder.d.ts +43 -0
- package/lib/esm/node/builder.js +177 -0
- package/lib/esm/operations/crud.d.ts +64 -0
- package/lib/esm/operations/crud.js +221 -0
- package/lib/esm/operations/query-builder.d.ts +37 -0
- package/lib/esm/operations/query-builder.js +92 -0
- package/lib/esm/operations/search.d.ts +75 -0
- package/lib/esm/operations/search.js +167 -0
- package/lib/esm/package.json +3 -0
- package/lib/esm/router/path-router.d.ts +38 -0
- package/lib/esm/router/path-router.js +83 -0
- package/lib/esm/router/types.d.ts +30 -0
- package/lib/esm/router/types.js +1 -0
- package/lib/esm/schema/introspector.d.ts +48 -0
- package/lib/esm/schema/introspector.js +182 -0
- package/lib/esm/schema/types.d.ts +104 -0
- package/lib/esm/schema/types.js +10 -0
- package/lib/esm/sqlite-afs.d.ts +144 -0
- package/lib/esm/sqlite-afs.js +333 -0
- package/package.json +71 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registry for managing action handlers
|
|
3
|
+
*/
|
|
4
|
+
export class ActionsRegistry {
|
|
5
|
+
handlers = new Map();
|
|
6
|
+
/**
|
|
7
|
+
* Registers an action handler
|
|
8
|
+
*/
|
|
9
|
+
register(definition) {
|
|
10
|
+
this.handlers.set(definition.name, definition);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Registers a simple action with just name and handler
|
|
14
|
+
*/
|
|
15
|
+
registerSimple(name, handler, options) {
|
|
16
|
+
this.register({
|
|
17
|
+
name,
|
|
18
|
+
handler,
|
|
19
|
+
description: options?.description,
|
|
20
|
+
tableLevel: options?.tableLevel ?? false,
|
|
21
|
+
rowLevel: options?.rowLevel ?? true,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Unregisters an action
|
|
26
|
+
*/
|
|
27
|
+
unregister(name) {
|
|
28
|
+
return this.handlers.delete(name);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Checks if an action is registered
|
|
32
|
+
*/
|
|
33
|
+
has(name) {
|
|
34
|
+
return this.handlers.has(name);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Gets an action definition
|
|
38
|
+
*/
|
|
39
|
+
get(name) {
|
|
40
|
+
return this.handlers.get(name);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Lists all registered actions
|
|
44
|
+
*/
|
|
45
|
+
list(options) {
|
|
46
|
+
const actions = Array.from(this.handlers.values());
|
|
47
|
+
if (options?.tableLevel !== undefined || options?.rowLevel !== undefined) {
|
|
48
|
+
return actions.filter((a) => {
|
|
49
|
+
if (options.tableLevel && !a.tableLevel)
|
|
50
|
+
return false;
|
|
51
|
+
if (options.rowLevel && !a.rowLevel)
|
|
52
|
+
return false;
|
|
53
|
+
return true;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return actions;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Lists action names
|
|
60
|
+
*/
|
|
61
|
+
listNames(options) {
|
|
62
|
+
return this.list(options).map((a) => a.name);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Executes an action
|
|
66
|
+
*/
|
|
67
|
+
async execute(name, ctx, params = {}) {
|
|
68
|
+
const definition = this.handlers.get(name);
|
|
69
|
+
if (!definition) {
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
message: `Unknown action: ${name}`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// Validate action level
|
|
76
|
+
if (ctx.pk && !definition.rowLevel) {
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
message: `Action '${name}' is not available at row level`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (!ctx.pk && !definition.tableLevel) {
|
|
83
|
+
return {
|
|
84
|
+
success: false,
|
|
85
|
+
message: `Action '${name}' is not available at table level`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
return await definition.handler(ctx, params);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
return {
|
|
93
|
+
success: false,
|
|
94
|
+
message: error instanceof Error ? error.message : String(error),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { LibSQLDatabase } from "drizzle-orm/libsql";
|
|
2
|
+
import type { TableSchema } from "../schema/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Context provided to action handlers
|
|
5
|
+
*/
|
|
6
|
+
export interface ActionContext {
|
|
7
|
+
/** Database instance */
|
|
8
|
+
db: LibSQLDatabase;
|
|
9
|
+
/** All table schemas */
|
|
10
|
+
schemas: Map<string, TableSchema>;
|
|
11
|
+
/** Table this action is being executed on */
|
|
12
|
+
table: string;
|
|
13
|
+
/** Primary key of the row (if row-level action) */
|
|
14
|
+
pk?: string;
|
|
15
|
+
/** The row data (if available) */
|
|
16
|
+
row?: Record<string, unknown>;
|
|
17
|
+
/** Reference to the parent module for advanced operations */
|
|
18
|
+
module: {
|
|
19
|
+
refreshSchema(): Promise<void>;
|
|
20
|
+
exportTable(table: string, format: string): Promise<unknown>;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Action handler function signature
|
|
25
|
+
*/
|
|
26
|
+
export type ActionHandler = (ctx: ActionContext, params: Record<string, unknown>) => Promise<ActionResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Result from an action execution
|
|
29
|
+
*/
|
|
30
|
+
export interface ActionResult {
|
|
31
|
+
success: boolean;
|
|
32
|
+
data?: unknown;
|
|
33
|
+
message?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Action definition with metadata
|
|
37
|
+
*/
|
|
38
|
+
export interface ActionDefinition {
|
|
39
|
+
/** Action name */
|
|
40
|
+
name: string;
|
|
41
|
+
/** Description of what the action does */
|
|
42
|
+
description?: string;
|
|
43
|
+
/** Whether this action is available at table level (vs row level) */
|
|
44
|
+
tableLevel?: boolean;
|
|
45
|
+
/** Whether this action is available at row level */
|
|
46
|
+
rowLevel?: boolean;
|
|
47
|
+
/** Input schema for the action parameters */
|
|
48
|
+
inputSchema?: Record<string, unknown>;
|
|
49
|
+
/** The handler function */
|
|
50
|
+
handler: ActionHandler;
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { type AFSAccessMode } from "@aigne/afs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* FTS (Full-Text Search) configuration schema
|
|
5
|
+
*/
|
|
6
|
+
export declare const ftsConfigSchema: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
8
|
+
tables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
tables?: Record<string, string[]> | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
enabled?: boolean | undefined;
|
|
14
|
+
tables?: Record<string, string[]> | undefined;
|
|
15
|
+
}>>;
|
|
16
|
+
/**
|
|
17
|
+
* SQLite AFS module configuration schema
|
|
18
|
+
*/
|
|
19
|
+
export declare const sqliteAFSConfigSchema: z.ZodObject<{
|
|
20
|
+
url: z.ZodString;
|
|
21
|
+
name: z.ZodOptional<z.ZodString>;
|
|
22
|
+
description: z.ZodOptional<z.ZodString>;
|
|
23
|
+
accessMode: z.ZodOptional<z.ZodEnum<["readonly", "readwrite"]>>;
|
|
24
|
+
tables: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
25
|
+
excludeTables: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
26
|
+
fts: z.ZodOptional<z.ZodObject<{
|
|
27
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
28
|
+
tables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
tables?: Record<string, string[]> | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
enabled?: boolean | undefined;
|
|
34
|
+
tables?: Record<string, string[]> | undefined;
|
|
35
|
+
}>>;
|
|
36
|
+
wal: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
|
38
|
+
url: string;
|
|
39
|
+
wal: boolean;
|
|
40
|
+
tables?: string[] | undefined;
|
|
41
|
+
name?: string | undefined;
|
|
42
|
+
description?: string | undefined;
|
|
43
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
44
|
+
excludeTables?: string[] | undefined;
|
|
45
|
+
fts?: {
|
|
46
|
+
enabled: boolean;
|
|
47
|
+
tables?: Record<string, string[]> | undefined;
|
|
48
|
+
} | undefined;
|
|
49
|
+
}, {
|
|
50
|
+
url: string;
|
|
51
|
+
tables?: string[] | undefined;
|
|
52
|
+
name?: string | undefined;
|
|
53
|
+
description?: string | undefined;
|
|
54
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
55
|
+
excludeTables?: string[] | undefined;
|
|
56
|
+
fts?: {
|
|
57
|
+
enabled?: boolean | undefined;
|
|
58
|
+
tables?: Record<string, string[]> | undefined;
|
|
59
|
+
} | undefined;
|
|
60
|
+
wal?: boolean | undefined;
|
|
61
|
+
}>;
|
|
62
|
+
/**
|
|
63
|
+
* SQLite AFS module configuration type
|
|
64
|
+
*/
|
|
65
|
+
export type SQLiteAFSConfig = z.infer<typeof sqliteAFSConfigSchema>;
|
|
66
|
+
/**
|
|
67
|
+
* SQLite AFS module options (after parsing)
|
|
68
|
+
*/
|
|
69
|
+
export interface SQLiteAFSOptions {
|
|
70
|
+
/** SQLite database URL */
|
|
71
|
+
url: string;
|
|
72
|
+
/** Module name */
|
|
73
|
+
name?: string;
|
|
74
|
+
/** Module description */
|
|
75
|
+
description?: string;
|
|
76
|
+
/** Access mode */
|
|
77
|
+
accessMode?: AFSAccessMode;
|
|
78
|
+
/** Tables to expose */
|
|
79
|
+
tables?: string[];
|
|
80
|
+
/** Tables to exclude */
|
|
81
|
+
excludeTables?: string[];
|
|
82
|
+
/** FTS configuration */
|
|
83
|
+
fts?: {
|
|
84
|
+
enabled?: boolean;
|
|
85
|
+
tables?: Record<string, string[]>;
|
|
86
|
+
};
|
|
87
|
+
/** Enable WAL mode */
|
|
88
|
+
wal?: boolean;
|
|
89
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { accessModeSchema } from "@aigne/afs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/**
|
|
4
|
+
* FTS (Full-Text Search) configuration schema
|
|
5
|
+
*/
|
|
6
|
+
export const ftsConfigSchema = z
|
|
7
|
+
.object({
|
|
8
|
+
enabled: z.boolean().default(true).describe("Whether FTS is enabled"),
|
|
9
|
+
tables: z
|
|
10
|
+
.record(z.array(z.string()))
|
|
11
|
+
.optional()
|
|
12
|
+
.describe("Map of table name to columns to index for FTS"),
|
|
13
|
+
})
|
|
14
|
+
.optional();
|
|
15
|
+
/**
|
|
16
|
+
* SQLite AFS module configuration schema
|
|
17
|
+
*/
|
|
18
|
+
export const sqliteAFSConfigSchema = z.object({
|
|
19
|
+
url: z.string().describe("SQLite database URL (file:./path or :memory:)"),
|
|
20
|
+
name: z.string().optional().describe("Module name, defaults to 'sqlite-afs'"),
|
|
21
|
+
description: z.string().optional().describe("Description of this module"),
|
|
22
|
+
accessMode: accessModeSchema,
|
|
23
|
+
tables: z
|
|
24
|
+
.array(z.string())
|
|
25
|
+
.optional()
|
|
26
|
+
.describe("Whitelist of tables to expose (if not specified, all tables are exposed)"),
|
|
27
|
+
excludeTables: z.array(z.string()).optional().describe("Tables to exclude from exposure"),
|
|
28
|
+
fts: ftsConfigSchema,
|
|
29
|
+
wal: z.boolean().optional().default(true).describe("Enable WAL mode for better concurrency"),
|
|
30
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { registerBuiltInActions } from "./actions/built-in.js";
|
|
2
|
+
export { ActionsRegistry } from "./actions/registry.js";
|
|
3
|
+
export type { ActionContext, ActionDefinition, ActionHandler, ActionResult, } from "./actions/types.js";
|
|
4
|
+
export { type SQLiteAFSConfig, type SQLiteAFSOptions, sqliteAFSConfigSchema } from "./config.js";
|
|
5
|
+
export { type BuildEntryOptions, buildActionsListEntry, buildAttributeEntry, buildAttributeListEntry, buildMetaEntry, buildRowEntry, buildSchemaEntry, buildSearchEntry, buildTableEntry, } from "./node/builder.js";
|
|
6
|
+
export { CRUDOperations } from "./operations/crud.js";
|
|
7
|
+
export { buildDelete, buildGetLastRowId, buildInsert, buildSelectAll, buildSelectByPK, buildUpdate, } from "./operations/query-builder.js";
|
|
8
|
+
export { createFTSConfig, type FTSConfig, FTSSearch, type FTSTableConfig, } from "./operations/search.js";
|
|
9
|
+
export { buildPath, createPathRouter, getVirtualPathType, isVirtualPath, matchPath, } from "./router/path-router.js";
|
|
10
|
+
export type { RouteAction, RouteData, RouteMatch, RouteParams } from "./router/types.js";
|
|
11
|
+
export { SchemaIntrospector } from "./schema/introspector.js";
|
|
12
|
+
export type { ColumnInfo, ForeignKeyInfo, IndexInfo, PragmaForeignKeyRow, PragmaIndexListRow, PragmaTableInfoRow, TableSchema, } from "./schema/types.js";
|
|
13
|
+
export { SQLiteAFS } from "./sqlite-afs.js";
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Main module export
|
|
2
|
+
export { registerBuiltInActions } from "./actions/built-in.js";
|
|
3
|
+
// Actions
|
|
4
|
+
export { ActionsRegistry } from "./actions/registry.js";
|
|
5
|
+
// Configuration
|
|
6
|
+
export { sqliteAFSConfigSchema } from "./config.js";
|
|
7
|
+
// Node builder
|
|
8
|
+
export { buildActionsListEntry, buildAttributeEntry, buildAttributeListEntry, buildMetaEntry, buildRowEntry, buildSchemaEntry, buildSearchEntry, buildTableEntry, } from "./node/builder.js";
|
|
9
|
+
// Operations
|
|
10
|
+
export { CRUDOperations } from "./operations/crud.js";
|
|
11
|
+
export { buildDelete, buildGetLastRowId, buildInsert, buildSelectAll, buildSelectByPK, buildUpdate, } from "./operations/query-builder.js";
|
|
12
|
+
export { createFTSConfig, FTSSearch, } from "./operations/search.js";
|
|
13
|
+
// Router
|
|
14
|
+
export { buildPath, createPathRouter, getVirtualPathType, isVirtualPath, matchPath, } from "./router/path-router.js";
|
|
15
|
+
// Schema types and introspector
|
|
16
|
+
export { SchemaIntrospector } from "./schema/introspector.js";
|
|
17
|
+
export { SQLiteAFS } from "./sqlite-afs.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { AFSEntry } from "@aigne/afs";
|
|
2
|
+
import type { TableSchema } from "../schema/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Options for building an AFSEntry
|
|
5
|
+
*/
|
|
6
|
+
export interface BuildEntryOptions {
|
|
7
|
+
/** Base path prefix (e.g., empty string or module mount path) */
|
|
8
|
+
basePath?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Builds an AFSEntry from a database row
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildRowEntry(table: string, schema: TableSchema, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry;
|
|
14
|
+
/**
|
|
15
|
+
* Builds an AFSEntry for a table listing
|
|
16
|
+
*/
|
|
17
|
+
export declare function buildTableEntry(table: string, schema: TableSchema, options?: BuildEntryOptions & {
|
|
18
|
+
rowCount?: number;
|
|
19
|
+
}): AFSEntry;
|
|
20
|
+
/**
|
|
21
|
+
* Builds an AFSEntry for table schema
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildSchemaEntry(table: string, schema: TableSchema, options?: BuildEntryOptions): AFSEntry;
|
|
24
|
+
/**
|
|
25
|
+
* Builds an AFSEntry for an attribute (single column value)
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildAttributeEntry(table: string, pk: string, column: string, value: unknown, options?: BuildEntryOptions): AFSEntry;
|
|
28
|
+
/**
|
|
29
|
+
* Builds an AFSEntry listing all attributes for a row
|
|
30
|
+
*/
|
|
31
|
+
export declare function buildAttributeListEntry(table: string, schema: TableSchema, pk: string, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry[];
|
|
32
|
+
/**
|
|
33
|
+
* Builds an AFSEntry for row metadata
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildMetaEntry(table: string, schema: TableSchema, pk: string, row: Record<string, unknown>, options?: BuildEntryOptions): AFSEntry;
|
|
36
|
+
/**
|
|
37
|
+
* Builds AFSEntry for actions list
|
|
38
|
+
*/
|
|
39
|
+
export declare function buildActionsListEntry(table: string, pk: string, actions: string[], options?: BuildEntryOptions): AFSEntry[];
|
|
40
|
+
/**
|
|
41
|
+
* Builds a search result entry with highlights
|
|
42
|
+
*/
|
|
43
|
+
export declare function buildSearchEntry(table: string, schema: TableSchema, row: Record<string, unknown>, snippet?: string, options?: BuildEntryOptions): AFSEntry;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds an AFSEntry from a database row
|
|
3
|
+
*/
|
|
4
|
+
export function buildRowEntry(table, schema, row, options) {
|
|
5
|
+
const pkColumn = schema.primaryKey[0] ?? "rowid";
|
|
6
|
+
const pk = String(row[pkColumn] ?? row.rowid);
|
|
7
|
+
const basePath = options?.basePath ?? "";
|
|
8
|
+
return {
|
|
9
|
+
id: `${table}:${pk}`,
|
|
10
|
+
path: `${basePath}/${table}/${pk}`,
|
|
11
|
+
content: row,
|
|
12
|
+
metadata: {
|
|
13
|
+
table,
|
|
14
|
+
primaryKey: pkColumn,
|
|
15
|
+
primaryKeyValue: pk,
|
|
16
|
+
},
|
|
17
|
+
createdAt: parseDate(row.created_at ?? row.createdAt),
|
|
18
|
+
updatedAt: parseDate(row.updated_at ?? row.updatedAt),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Builds an AFSEntry for a table listing
|
|
23
|
+
*/
|
|
24
|
+
export function buildTableEntry(table, schema, options) {
|
|
25
|
+
const basePath = options?.basePath ?? "";
|
|
26
|
+
return {
|
|
27
|
+
id: table,
|
|
28
|
+
path: `${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
|
+
export 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
|
+
export 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
|
+
export 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
|
+
export 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
|
+
export 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: {
|
|
147
|
+
execute: {
|
|
148
|
+
name: action,
|
|
149
|
+
description: `Execute ${action} action on ${table}:${pk}`,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Builds a search result entry with highlights
|
|
156
|
+
*/
|
|
157
|
+
export function buildSearchEntry(table, schema, row, snippet, options) {
|
|
158
|
+
const entry = buildRowEntry(table, schema, row, options);
|
|
159
|
+
if (snippet) {
|
|
160
|
+
entry.summary = snippet;
|
|
161
|
+
}
|
|
162
|
+
return entry;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Parses a date from various formats
|
|
166
|
+
*/
|
|
167
|
+
function parseDate(value) {
|
|
168
|
+
if (!value)
|
|
169
|
+
return undefined;
|
|
170
|
+
if (value instanceof Date)
|
|
171
|
+
return value;
|
|
172
|
+
if (typeof value === "string")
|
|
173
|
+
return new Date(value);
|
|
174
|
+
if (typeof value === "number")
|
|
175
|
+
return new Date(value);
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { AFSDeleteResult, AFSListOptions, AFSListResult, AFSReadResult, AFSWriteResult } from "@aigne/afs";
|
|
2
|
+
import type { LibSQLDatabase } from "drizzle-orm/libsql";
|
|
3
|
+
import type { TableSchema } from "../schema/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* CRUD operations for SQLite AFS
|
|
6
|
+
*/
|
|
7
|
+
export declare class CRUDOperations {
|
|
8
|
+
private db;
|
|
9
|
+
private schemas;
|
|
10
|
+
private basePath;
|
|
11
|
+
constructor(db: LibSQLDatabase, schemas: Map<string, TableSchema>, basePath?: string);
|
|
12
|
+
/**
|
|
13
|
+
* Lists all tables
|
|
14
|
+
*/
|
|
15
|
+
listTables(): Promise<AFSListResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Lists rows in a table
|
|
18
|
+
*/
|
|
19
|
+
listTable(table: string, options?: AFSListOptions): Promise<AFSListResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Reads a single row by primary key
|
|
22
|
+
*/
|
|
23
|
+
readRow(table: string, pk: string): Promise<AFSReadResult>;
|
|
24
|
+
/**
|
|
25
|
+
* Gets table schema
|
|
26
|
+
*/
|
|
27
|
+
getSchema(table: string): AFSReadResult;
|
|
28
|
+
/**
|
|
29
|
+
* Lists attributes (columns) for a row
|
|
30
|
+
*/
|
|
31
|
+
listAttributes(table: string, pk: string): Promise<AFSListResult>;
|
|
32
|
+
/**
|
|
33
|
+
* Gets a single attribute (column value) for a row
|
|
34
|
+
*/
|
|
35
|
+
getAttribute(table: string, pk: string, column: string): Promise<AFSReadResult>;
|
|
36
|
+
/**
|
|
37
|
+
* Gets row metadata
|
|
38
|
+
*/
|
|
39
|
+
getMeta(table: string, pk: string): Promise<AFSReadResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a new row in a table
|
|
42
|
+
*/
|
|
43
|
+
createRow(table: string, content: Record<string, unknown>): Promise<AFSWriteResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Updates an existing row
|
|
46
|
+
*/
|
|
47
|
+
updateRow(table: string, pk: string, content: Record<string, unknown>): Promise<AFSWriteResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Deletes a row by primary key
|
|
50
|
+
*/
|
|
51
|
+
deleteRow(table: string, pk: string): Promise<AFSDeleteResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a table exists
|
|
54
|
+
*/
|
|
55
|
+
hasTable(table: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Gets the schema for a table
|
|
58
|
+
*/
|
|
59
|
+
getTableSchema(table: string): TableSchema | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Updates the schemas map (after refresh)
|
|
62
|
+
*/
|
|
63
|
+
setSchemas(schemas: Map<string, TableSchema>): void;
|
|
64
|
+
}
|