@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,104 @@
|
|
|
1
|
+
//#region src/schema/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Column information from SQLite PRAGMA table_info
|
|
4
|
+
*/
|
|
5
|
+
interface ColumnInfo {
|
|
6
|
+
/** Column name */
|
|
7
|
+
name: string;
|
|
8
|
+
/** SQLite type (INTEGER, TEXT, REAL, BLOB, etc.) */
|
|
9
|
+
type: string;
|
|
10
|
+
/** Whether the column has NOT NULL constraint */
|
|
11
|
+
notnull: boolean;
|
|
12
|
+
/** Whether this column is part of the primary key */
|
|
13
|
+
pk: number;
|
|
14
|
+
/** Default value for the column */
|
|
15
|
+
dfltValue: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Foreign key information from SQLite PRAGMA foreign_key_list
|
|
19
|
+
*/
|
|
20
|
+
interface ForeignKeyInfo {
|
|
21
|
+
/** Foreign key id */
|
|
22
|
+
id: number;
|
|
23
|
+
/** Sequence number for composite foreign keys */
|
|
24
|
+
seq: number;
|
|
25
|
+
/** Referenced table */
|
|
26
|
+
table: string;
|
|
27
|
+
/** Column in this table */
|
|
28
|
+
from: string;
|
|
29
|
+
/** Column in referenced table */
|
|
30
|
+
to: string;
|
|
31
|
+
/** ON UPDATE action */
|
|
32
|
+
onUpdate: string;
|
|
33
|
+
/** ON DELETE action */
|
|
34
|
+
onDelete: string;
|
|
35
|
+
/** MATCH clause */
|
|
36
|
+
match: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Index information from SQLite PRAGMA index_list
|
|
40
|
+
*/
|
|
41
|
+
interface IndexInfo {
|
|
42
|
+
/** Index sequence number */
|
|
43
|
+
seq: number;
|
|
44
|
+
/** Index name */
|
|
45
|
+
name: string;
|
|
46
|
+
/** Whether this is a unique index */
|
|
47
|
+
unique: boolean;
|
|
48
|
+
/** Origin of the index (c = CREATE INDEX, u = UNIQUE constraint, pk = PRIMARY KEY) */
|
|
49
|
+
origin: string;
|
|
50
|
+
/** Whether the index is partial */
|
|
51
|
+
partial: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Complete schema information for a single table
|
|
55
|
+
*/
|
|
56
|
+
interface TableSchema {
|
|
57
|
+
/** Table name */
|
|
58
|
+
name: string;
|
|
59
|
+
/** Column definitions */
|
|
60
|
+
columns: ColumnInfo[];
|
|
61
|
+
/** Primary key column names */
|
|
62
|
+
primaryKey: string[];
|
|
63
|
+
/** Foreign key relationships */
|
|
64
|
+
foreignKeys: ForeignKeyInfo[];
|
|
65
|
+
/** Indexes on this table */
|
|
66
|
+
indexes: IndexInfo[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Raw PRAGMA table_info result row
|
|
70
|
+
*/
|
|
71
|
+
interface PragmaTableInfoRow {
|
|
72
|
+
cid: number;
|
|
73
|
+
name: string;
|
|
74
|
+
type: string;
|
|
75
|
+
notnull: number;
|
|
76
|
+
dflt_value: unknown;
|
|
77
|
+
pk: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Raw PRAGMA foreign_key_list result row
|
|
81
|
+
*/
|
|
82
|
+
interface PragmaForeignKeyRow {
|
|
83
|
+
id: number;
|
|
84
|
+
seq: number;
|
|
85
|
+
table: string;
|
|
86
|
+
from: string;
|
|
87
|
+
to: string;
|
|
88
|
+
on_update: string;
|
|
89
|
+
on_delete: string;
|
|
90
|
+
match: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Raw PRAGMA index_list result row
|
|
94
|
+
*/
|
|
95
|
+
interface PragmaIndexListRow {
|
|
96
|
+
seq: number;
|
|
97
|
+
name: string;
|
|
98
|
+
unique: number;
|
|
99
|
+
origin: string;
|
|
100
|
+
partial: number;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { ColumnInfo, ForeignKeyInfo, IndexInfo, PragmaForeignKeyRow, PragmaIndexListRow, PragmaTableInfoRow, TableSchema };
|
|
104
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../src/schema/types.ts"],"mappings":";;AAGA;AAgBA;UAhBiB,UAAA;EAAA;EAAA,IAAA;EAAA;EAAA,IAAA;EAAA;EAAA,OAAA;EAAA;EAAA,EAAA;EAAA;EAAA,SAAA;AAAA;AAAA;AAgBjB;AAsBA;AAtCiB,UAgBA,cAAA;EAAA;EAAA,EAAA;EAAA;EAAA,GAAA;EAAA;EAAA,KAAA;EAAA;EAAA,IAAA;EAAA;EAAA,EAAA;EAAA;EAAA,QAAA;EAAA;EAAA,QAAA;EAAA;EAAA,KAAA;AAAA;AAAA;AAsBjB;AAgBA;AAtCiB,UAsBA,SAAA;EAAA;EAAA,GAAA;EAAA;EAAA,IAAA;EAAA;EAAA,MAAA;EAAA;EAAA,MAAA;EAAA;EAAA,OAAA;AAAA;AAAA;AAgBjB;;AAhBiB,UAgBA,WAAA;EAAA;EAAA,IAAA;EAAA;EAAA,OAAA,EAIN,UAAA;EAAA;EAAA,UAAA;EAAA;EAAA,WAAA,EAII,cAAA;EAAA;EAAA,OAAA,EAEJ,SAAA;AAAA;AAAA;;AAMX;AANW,UAMM,kBAAA;EAAA,GAAA;EAAA,IAAA;EAAA,IAAA;EAAA,OAAA;EAAA,UAAA;EAAA,EAAA;AAAA;AAAA;AAYjB;AAcA;AA1BiB,UAYA,mBAAA;EAAA,EAAA;EAAA,GAAA;EAAA,KAAA;EAAA,IAAA;EAAA,EAAA;EAAA,SAAA;EAAA,SAAA;EAAA,KAAA;AAAA;AAAA;AAcjB;;AAdiB,UAcA,kBAAA;EAAA,GAAA;EAAA,IAAA;EAAA,MAAA;EAAA,MAAA;EAAA,OAAA;AAAA"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
//#region src/schema/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Column information from SQLite PRAGMA table_info
|
|
4
|
+
*/
|
|
5
|
+
interface ColumnInfo {
|
|
6
|
+
/** Column name */
|
|
7
|
+
name: string;
|
|
8
|
+
/** SQLite type (INTEGER, TEXT, REAL, BLOB, etc.) */
|
|
9
|
+
type: string;
|
|
10
|
+
/** Whether the column has NOT NULL constraint */
|
|
11
|
+
notnull: boolean;
|
|
12
|
+
/** Whether this column is part of the primary key */
|
|
13
|
+
pk: number;
|
|
14
|
+
/** Default value for the column */
|
|
15
|
+
dfltValue: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Foreign key information from SQLite PRAGMA foreign_key_list
|
|
19
|
+
*/
|
|
20
|
+
interface ForeignKeyInfo {
|
|
21
|
+
/** Foreign key id */
|
|
22
|
+
id: number;
|
|
23
|
+
/** Sequence number for composite foreign keys */
|
|
24
|
+
seq: number;
|
|
25
|
+
/** Referenced table */
|
|
26
|
+
table: string;
|
|
27
|
+
/** Column in this table */
|
|
28
|
+
from: string;
|
|
29
|
+
/** Column in referenced table */
|
|
30
|
+
to: string;
|
|
31
|
+
/** ON UPDATE action */
|
|
32
|
+
onUpdate: string;
|
|
33
|
+
/** ON DELETE action */
|
|
34
|
+
onDelete: string;
|
|
35
|
+
/** MATCH clause */
|
|
36
|
+
match: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Index information from SQLite PRAGMA index_list
|
|
40
|
+
*/
|
|
41
|
+
interface IndexInfo {
|
|
42
|
+
/** Index sequence number */
|
|
43
|
+
seq: number;
|
|
44
|
+
/** Index name */
|
|
45
|
+
name: string;
|
|
46
|
+
/** Whether this is a unique index */
|
|
47
|
+
unique: boolean;
|
|
48
|
+
/** Origin of the index (c = CREATE INDEX, u = UNIQUE constraint, pk = PRIMARY KEY) */
|
|
49
|
+
origin: string;
|
|
50
|
+
/** Whether the index is partial */
|
|
51
|
+
partial: boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Complete schema information for a single table
|
|
55
|
+
*/
|
|
56
|
+
interface TableSchema {
|
|
57
|
+
/** Table name */
|
|
58
|
+
name: string;
|
|
59
|
+
/** Column definitions */
|
|
60
|
+
columns: ColumnInfo[];
|
|
61
|
+
/** Primary key column names */
|
|
62
|
+
primaryKey: string[];
|
|
63
|
+
/** Foreign key relationships */
|
|
64
|
+
foreignKeys: ForeignKeyInfo[];
|
|
65
|
+
/** Indexes on this table */
|
|
66
|
+
indexes: IndexInfo[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Raw PRAGMA table_info result row
|
|
70
|
+
*/
|
|
71
|
+
interface PragmaTableInfoRow {
|
|
72
|
+
cid: number;
|
|
73
|
+
name: string;
|
|
74
|
+
type: string;
|
|
75
|
+
notnull: number;
|
|
76
|
+
dflt_value: unknown;
|
|
77
|
+
pk: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Raw PRAGMA foreign_key_list result row
|
|
81
|
+
*/
|
|
82
|
+
interface PragmaForeignKeyRow {
|
|
83
|
+
id: number;
|
|
84
|
+
seq: number;
|
|
85
|
+
table: string;
|
|
86
|
+
from: string;
|
|
87
|
+
to: string;
|
|
88
|
+
on_update: string;
|
|
89
|
+
on_delete: string;
|
|
90
|
+
match: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Raw PRAGMA index_list result row
|
|
94
|
+
*/
|
|
95
|
+
interface PragmaIndexListRow {
|
|
96
|
+
seq: number;
|
|
97
|
+
name: string;
|
|
98
|
+
unique: number;
|
|
99
|
+
origin: string;
|
|
100
|
+
partial: number;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
export { ColumnInfo, ForeignKeyInfo, IndexInfo, PragmaForeignKeyRow, PragmaIndexListRow, PragmaTableInfoRow, TableSchema };
|
|
104
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../src/schema/types.ts"],"mappings":";;AAGA;AAgBA;UAhBiB,UAAA;EAAA;EAAA,IAAA;EAAA;EAAA,IAAA;EAAA;EAAA,OAAA;EAAA;EAAA,EAAA;EAAA;EAAA,SAAA;AAAA;AAAA;AAgBjB;AAsBA;AAtCiB,UAgBA,cAAA;EAAA;EAAA,EAAA;EAAA;EAAA,GAAA;EAAA;EAAA,KAAA;EAAA;EAAA,IAAA;EAAA;EAAA,EAAA;EAAA;EAAA,QAAA;EAAA;EAAA,QAAA;EAAA;EAAA,KAAA;AAAA;AAAA;AAsBjB;AAgBA;AAtCiB,UAsBA,SAAA;EAAA;EAAA,GAAA;EAAA;EAAA,IAAA;EAAA;EAAA,MAAA;EAAA;EAAA,MAAA;EAAA;EAAA,OAAA;AAAA;AAAA;AAgBjB;;AAhBiB,UAgBA,WAAA;EAAA;EAAA,IAAA;EAAA;EAAA,OAAA,EAIN,UAAA;EAAA;EAAA,UAAA;EAAA;EAAA,WAAA,EAII,cAAA;EAAA;EAAA,OAAA,EAEJ,SAAA;AAAA;AAAA;;AAMX;AANW,UAMM,kBAAA;EAAA,GAAA;EAAA,IAAA;EAAA,IAAA;EAAA,OAAA;EAAA,UAAA;EAAA,EAAA;AAAA;AAAA;AAYjB;AAcA;AA1BiB,UAYA,mBAAA;EAAA,EAAA;EAAA,GAAA;EAAA,KAAA;EAAA,IAAA;EAAA,EAAA;EAAA,SAAA;EAAA,SAAA;EAAA,KAAA;AAAA;AAAA;AAcjB;;AAdiB,UAcA,kBAAA;EAAA,GAAA;EAAA,IAAA;EAAA,MAAA;EAAA,MAAA;EAAA,OAAA;AAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/schema/types.ts
|
|
2
|
+
/**
|
|
3
|
+
* System tables that should be excluded from introspection
|
|
4
|
+
*/
|
|
5
|
+
const SYSTEM_TABLES = [
|
|
6
|
+
"sqlite_sequence",
|
|
7
|
+
"sqlite_stat1",
|
|
8
|
+
"sqlite_stat2",
|
|
9
|
+
"sqlite_stat3",
|
|
10
|
+
"sqlite_stat4"
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { SYSTEM_TABLES };
|
|
15
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../src/schema/types.ts"],"sourcesContent":["/**\n * Column information from SQLite PRAGMA table_info\n */\nexport interface ColumnInfo {\n /** Column name */\n name: string;\n /** SQLite type (INTEGER, TEXT, REAL, BLOB, etc.) */\n type: string;\n /** Whether the column has NOT NULL constraint */\n notnull: boolean;\n /** Whether this column is part of the primary key */\n pk: number;\n /** Default value for the column */\n dfltValue: unknown;\n}\n\n/**\n * Foreign key information from SQLite PRAGMA foreign_key_list\n */\nexport interface ForeignKeyInfo {\n /** Foreign key id */\n id: number;\n /** Sequence number for composite foreign keys */\n seq: number;\n /** Referenced table */\n table: string;\n /** Column in this table */\n from: string;\n /** Column in referenced table */\n to: string;\n /** ON UPDATE action */\n onUpdate: string;\n /** ON DELETE action */\n onDelete: string;\n /** MATCH clause */\n match: string;\n}\n\n/**\n * Index information from SQLite PRAGMA index_list\n */\nexport interface IndexInfo {\n /** Index sequence number */\n seq: number;\n /** Index name */\n name: string;\n /** Whether this is a unique index */\n unique: boolean;\n /** Origin of the index (c = CREATE INDEX, u = UNIQUE constraint, pk = PRIMARY KEY) */\n origin: string;\n /** Whether the index is partial */\n partial: boolean;\n}\n\n/**\n * Complete schema information for a single table\n */\nexport interface TableSchema {\n /** Table name */\n name: string;\n /** Column definitions */\n columns: ColumnInfo[];\n /** Primary key column names */\n primaryKey: string[];\n /** Foreign key relationships */\n foreignKeys: ForeignKeyInfo[];\n /** Indexes on this table */\n indexes: IndexInfo[];\n}\n\n/**\n * Raw PRAGMA table_info result row\n */\nexport interface PragmaTableInfoRow {\n cid: number;\n name: string;\n type: string;\n notnull: number;\n dflt_value: unknown;\n pk: number;\n}\n\n/**\n * Raw PRAGMA foreign_key_list result row\n */\nexport interface PragmaForeignKeyRow {\n id: number;\n seq: number;\n table: string;\n from: string;\n to: string;\n on_update: string;\n on_delete: string;\n match: string;\n}\n\n/**\n * Raw PRAGMA index_list result row\n */\nexport interface PragmaIndexListRow {\n seq: number;\n name: string;\n unique: number;\n origin: string;\n partial: number;\n}\n\n/**\n * System tables that should be excluded from introspection\n */\nexport const SYSTEM_TABLES = [\n \"sqlite_sequence\",\n \"sqlite_stat1\",\n \"sqlite_stat2\",\n \"sqlite_stat3\",\n \"sqlite_stat4\",\n] as const;\n"],"mappings":";;;;AA8GA,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;CACD"}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
const require_built_in = require('./actions/built-in.cjs');
|
|
2
|
+
const require_registry = require('./actions/registry.cjs');
|
|
3
|
+
const require_config = require('./config.cjs');
|
|
4
|
+
const require_builder = require('./node/builder.cjs');
|
|
5
|
+
const require_crud = require('./operations/crud.cjs');
|
|
6
|
+
const require_search = require('./operations/search.cjs');
|
|
7
|
+
const require_path_router = require('./router/path-router.cjs');
|
|
8
|
+
const require_introspector = require('./schema/introspector.cjs');
|
|
9
|
+
let _aigne_sqlite = require("@aigne/sqlite");
|
|
10
|
+
|
|
11
|
+
//#region src/sqlite-afs.ts
|
|
12
|
+
/**
|
|
13
|
+
* SQLite AFS Module
|
|
14
|
+
*
|
|
15
|
+
* Exposes SQLite databases as AFS nodes with full CRUD support,
|
|
16
|
+
* schema introspection, FTS5 search, and virtual paths (@attr, @meta, @actions).
|
|
17
|
+
*/
|
|
18
|
+
var SQLiteAFS = class SQLiteAFS {
|
|
19
|
+
name;
|
|
20
|
+
description;
|
|
21
|
+
accessMode;
|
|
22
|
+
db;
|
|
23
|
+
schemas = /* @__PURE__ */ new Map();
|
|
24
|
+
router;
|
|
25
|
+
crud;
|
|
26
|
+
ftsSearch;
|
|
27
|
+
actions;
|
|
28
|
+
ftsConfig;
|
|
29
|
+
initialized = false;
|
|
30
|
+
constructor(options) {
|
|
31
|
+
this.options = options;
|
|
32
|
+
this.name = options.name ?? "sqlite-afs";
|
|
33
|
+
this.description = options.description ?? `SQLite database: ${options.url}`;
|
|
34
|
+
this.accessMode = options.accessMode ?? "readwrite";
|
|
35
|
+
this.ftsConfig = require_search.createFTSConfig(options.fts);
|
|
36
|
+
this.actions = new require_registry.ActionsRegistry();
|
|
37
|
+
require_built_in.registerBuiltInActions(this.actions);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Returns the Zod schema for configuration validation
|
|
41
|
+
*/
|
|
42
|
+
static schema() {
|
|
43
|
+
return require_config.sqliteAFSConfigSchema;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Loads a module instance from configuration
|
|
47
|
+
*/
|
|
48
|
+
static async load({ parsed }) {
|
|
49
|
+
return new SQLiteAFS(require_config.sqliteAFSConfigSchema.parse(parsed));
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Called when the module is mounted to AFS
|
|
53
|
+
*/
|
|
54
|
+
async onMount(_afs) {
|
|
55
|
+
await this.initialize();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Initializes the database connection and introspects schema
|
|
59
|
+
*/
|
|
60
|
+
async initialize() {
|
|
61
|
+
if (this.initialized) return;
|
|
62
|
+
this.db = await (0, _aigne_sqlite.initDatabase)({
|
|
63
|
+
url: this.options.url,
|
|
64
|
+
wal: this.options.wal ?? true
|
|
65
|
+
});
|
|
66
|
+
const db = this.db;
|
|
67
|
+
this.schemas = await new require_introspector.SchemaIntrospector().introspect(db, {
|
|
68
|
+
tables: this.options.tables,
|
|
69
|
+
excludeTables: this.options.excludeTables
|
|
70
|
+
});
|
|
71
|
+
this.router = require_path_router.createPathRouter();
|
|
72
|
+
this.crud = new require_crud.CRUDOperations(db, this.schemas, "");
|
|
73
|
+
this.ftsSearch = new require_search.FTSSearch(db, this.schemas, this.ftsConfig, "");
|
|
74
|
+
this.initialized = true;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Ensures the module is initialized
|
|
78
|
+
*/
|
|
79
|
+
async ensureInitialized() {
|
|
80
|
+
if (!this.initialized) await this.initialize();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Lists entries at a path
|
|
84
|
+
*/
|
|
85
|
+
async list(path, options) {
|
|
86
|
+
await this.ensureInitialized();
|
|
87
|
+
const match = require_path_router.matchPath(this.router, path);
|
|
88
|
+
if (!match) return { data: [] };
|
|
89
|
+
switch (match.action) {
|
|
90
|
+
case "listTables": return this.crud.listTables();
|
|
91
|
+
case "listTable":
|
|
92
|
+
if (!match.params.table) return { data: [] };
|
|
93
|
+
return this.crud.listTable(match.params.table, options);
|
|
94
|
+
case "listAttributes":
|
|
95
|
+
if (!match.params.table || !match.params.pk) return { data: [] };
|
|
96
|
+
return this.crud.listAttributes(match.params.table, match.params.pk);
|
|
97
|
+
case "listActions":
|
|
98
|
+
if (!match.params.table || !match.params.pk) return { data: [] };
|
|
99
|
+
return this.listActions(match.params.table, match.params.pk);
|
|
100
|
+
default: return { data: [] };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Reads an entry at a path
|
|
105
|
+
*/
|
|
106
|
+
async read(path, _options) {
|
|
107
|
+
await this.ensureInitialized();
|
|
108
|
+
const match = require_path_router.matchPath(this.router, path);
|
|
109
|
+
if (!match) return {};
|
|
110
|
+
switch (match.action) {
|
|
111
|
+
case "readRow":
|
|
112
|
+
if (!match.params.table || !match.params.pk) return {};
|
|
113
|
+
return this.crud.readRow(match.params.table, match.params.pk);
|
|
114
|
+
case "getSchema":
|
|
115
|
+
if (!match.params.table) return {};
|
|
116
|
+
return this.crud.getSchema(match.params.table);
|
|
117
|
+
case "getAttribute":
|
|
118
|
+
if (!match.params.table || !match.params.pk || !match.params.column) return {};
|
|
119
|
+
return this.crud.getAttribute(match.params.table, match.params.pk, match.params.column);
|
|
120
|
+
case "getMeta":
|
|
121
|
+
if (!match.params.table || !match.params.pk) return {};
|
|
122
|
+
return this.crud.getMeta(match.params.table, match.params.pk);
|
|
123
|
+
default: return {};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Writes an entry at a path
|
|
128
|
+
*/
|
|
129
|
+
async write(path, content, _options) {
|
|
130
|
+
await this.ensureInitialized();
|
|
131
|
+
if (this.accessMode === "readonly") throw new Error("Module is in readonly mode");
|
|
132
|
+
const match = require_path_router.matchPath(this.router, path);
|
|
133
|
+
if (!match) throw new Error(`Invalid path: ${path}`);
|
|
134
|
+
switch (match.action) {
|
|
135
|
+
case "createRow":
|
|
136
|
+
if (!match.params.table) throw new Error("Table name required for create");
|
|
137
|
+
return this.crud.createRow(match.params.table, content.content ?? content);
|
|
138
|
+
case "readRow":
|
|
139
|
+
if (!match.params.table || !match.params.pk) throw new Error("Table and primary key required for update");
|
|
140
|
+
return this.crud.updateRow(match.params.table, match.params.pk, content.content ?? content);
|
|
141
|
+
case "executeAction":
|
|
142
|
+
if (!match.params.table || !match.params.action) throw new Error("Table and action name required");
|
|
143
|
+
return this.executeAction(match.params.table, match.params.pk, match.params.action, content.content ?? content);
|
|
144
|
+
default: throw new Error(`Write not supported for path: ${path}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Deletes an entry at a path
|
|
149
|
+
*/
|
|
150
|
+
async delete(path, _options) {
|
|
151
|
+
await this.ensureInitialized();
|
|
152
|
+
if (this.accessMode === "readonly") throw new Error("Module is in readonly mode");
|
|
153
|
+
const match = require_path_router.matchPath(this.router, path);
|
|
154
|
+
if (!match || match.action !== "readRow") throw new Error(`Delete not supported for path: ${path}`);
|
|
155
|
+
if (!match.params.table || !match.params.pk) throw new Error("Table and primary key required for delete");
|
|
156
|
+
return this.crud.deleteRow(match.params.table, match.params.pk);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Searches for entries matching a query
|
|
160
|
+
*/
|
|
161
|
+
async search(path, query, options) {
|
|
162
|
+
await this.ensureInitialized();
|
|
163
|
+
const match = require_path_router.matchPath(this.router, path);
|
|
164
|
+
if (match?.params.table) return this.ftsSearch.searchTable(match.params.table, query, options);
|
|
165
|
+
return this.ftsSearch.search(query, options);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Executes a module operation
|
|
169
|
+
*/
|
|
170
|
+
async exec(path, args, _options) {
|
|
171
|
+
await this.ensureInitialized();
|
|
172
|
+
const match = require_path_router.matchPath(this.router, path);
|
|
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}`);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Lists available actions for a row
|
|
178
|
+
*/
|
|
179
|
+
listActions(table, pk) {
|
|
180
|
+
return { data: require_builder.buildActionsListEntry(table, pk, this.actions.listNames({ rowLevel: true }), { basePath: "" }) };
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Executes an action
|
|
184
|
+
*/
|
|
185
|
+
async executeAction(table, pk, actionName, params) {
|
|
186
|
+
if (!this.schemas.get(table)) throw new Error(`Table '${table}' not found`);
|
|
187
|
+
let row;
|
|
188
|
+
if (pk) row = (await this.crud.readRow(table, pk)).data?.content;
|
|
189
|
+
const ctx = {
|
|
190
|
+
db: this.db,
|
|
191
|
+
schemas: this.schemas,
|
|
192
|
+
table,
|
|
193
|
+
pk,
|
|
194
|
+
row,
|
|
195
|
+
module: {
|
|
196
|
+
refreshSchema: () => this.refreshSchema(),
|
|
197
|
+
exportTable: (t, f) => this.exportTable(t, f)
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
const result = await this.actions.execute(actionName, ctx, params);
|
|
201
|
+
if (!result.success) throw new Error(result.message ?? "Action failed");
|
|
202
|
+
return { data: {
|
|
203
|
+
id: `${table}:${pk ?? ""}:@actions:${actionName}`,
|
|
204
|
+
path: pk ? `/${table}/${pk}/@actions/${actionName}` : `/${table}/@actions/${actionName}`,
|
|
205
|
+
content: result.data
|
|
206
|
+
} };
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Refreshes the schema cache
|
|
210
|
+
*/
|
|
211
|
+
async refreshSchema() {
|
|
212
|
+
const db = this.db;
|
|
213
|
+
this.schemas = await new require_introspector.SchemaIntrospector().introspect(db, {
|
|
214
|
+
tables: this.options.tables,
|
|
215
|
+
excludeTables: this.options.excludeTables
|
|
216
|
+
});
|
|
217
|
+
this.crud.setSchemas(this.schemas);
|
|
218
|
+
this.ftsSearch.setSchemas(this.schemas);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Exports table data in specified format
|
|
222
|
+
*/
|
|
223
|
+
async exportTable(table, format) {
|
|
224
|
+
const listResult = await this.crud.listTable(table, { limit: 1e4 });
|
|
225
|
+
if (format === "csv") {
|
|
226
|
+
const schema = this.schemas.get(table);
|
|
227
|
+
if (!schema) throw new Error(`Table '${table}' not found`);
|
|
228
|
+
return `${schema.columns.map((c) => c.name).join(",")}\n${listResult.data.map((entry) => {
|
|
229
|
+
const content = entry.content;
|
|
230
|
+
return schema.columns.map((c) => {
|
|
231
|
+
const val = content[c.name];
|
|
232
|
+
if (val === null || val === void 0) return "";
|
|
233
|
+
if (typeof val === "string" && (val.includes(",") || val.includes("\""))) return `"${val.replace(/"/g, "\"\"")}"`;
|
|
234
|
+
return String(val);
|
|
235
|
+
}).join(",");
|
|
236
|
+
}).join("\n")}`;
|
|
237
|
+
}
|
|
238
|
+
return listResult.data.map((entry) => entry.content);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Registers a custom action
|
|
242
|
+
*/
|
|
243
|
+
registerAction(name, handler, options) {
|
|
244
|
+
this.actions.registerSimple(name, async (ctx, params) => ({
|
|
245
|
+
success: true,
|
|
246
|
+
data: await handler(ctx, params)
|
|
247
|
+
}), options);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Gets table schemas (for external access)
|
|
251
|
+
*/
|
|
252
|
+
getSchemas() {
|
|
253
|
+
return this.schemas;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Gets the database instance (for advanced operations)
|
|
257
|
+
*/
|
|
258
|
+
getDatabase() {
|
|
259
|
+
return this.db;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
//#endregion
|
|
264
|
+
exports.SQLiteAFS = SQLiteAFS;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { TableSchema } from "./schema/types.cjs";
|
|
2
|
+
import { ActionContext } from "./actions/types.cjs";
|
|
3
|
+
import { SQLiteAFSOptions } from "./config.cjs";
|
|
4
|
+
import { LibSQLDatabase } from "drizzle-orm/libsql";
|
|
5
|
+
import { AFSAccessMode, AFSDeleteOptions, AFSDeleteResult, AFSExecOptions, AFSExecResult, AFSListOptions, AFSListResult, AFSModule, AFSModuleLoadParams, AFSReadOptions, AFSReadResult, AFSRoot, AFSSearchOptions, AFSSearchResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "@aigne/afs";
|
|
6
|
+
import * as zod0 from "zod";
|
|
7
|
+
|
|
8
|
+
//#region src/sqlite-afs.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* SQLite AFS Module
|
|
11
|
+
*
|
|
12
|
+
* Exposes SQLite databases as AFS nodes with full CRUD support,
|
|
13
|
+
* schema introspection, FTS5 search, and virtual paths (@attr, @meta, @actions).
|
|
14
|
+
*/
|
|
15
|
+
declare class SQLiteAFS implements AFSModule {
|
|
16
|
+
private options;
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly description: string;
|
|
19
|
+
readonly accessMode: AFSAccessMode;
|
|
20
|
+
private db;
|
|
21
|
+
private schemas;
|
|
22
|
+
private router;
|
|
23
|
+
private crud;
|
|
24
|
+
private ftsSearch;
|
|
25
|
+
private actions;
|
|
26
|
+
private ftsConfig;
|
|
27
|
+
private initialized;
|
|
28
|
+
constructor(options: SQLiteAFSOptions);
|
|
29
|
+
/**
|
|
30
|
+
* Returns the Zod schema for configuration validation
|
|
31
|
+
*/
|
|
32
|
+
static schema(): zod0.ZodObject<{
|
|
33
|
+
url: zod0.ZodString;
|
|
34
|
+
name: zod0.ZodOptional<zod0.ZodString>;
|
|
35
|
+
description: zod0.ZodOptional<zod0.ZodString>;
|
|
36
|
+
accessMode: zod0.ZodOptional<zod0.ZodEnum<["readonly", "readwrite"]>>;
|
|
37
|
+
tables: zod0.ZodOptional<zod0.ZodArray<zod0.ZodString, "many">>;
|
|
38
|
+
excludeTables: zod0.ZodOptional<zod0.ZodArray<zod0.ZodString, "many">>;
|
|
39
|
+
fts: zod0.ZodOptional<zod0.ZodObject<{
|
|
40
|
+
enabled: zod0.ZodDefault<zod0.ZodBoolean>;
|
|
41
|
+
tables: zod0.ZodOptional<zod0.ZodRecord<zod0.ZodString, zod0.ZodArray<zod0.ZodString, "many">>>;
|
|
42
|
+
}, "strip", zod0.ZodTypeAny, {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
tables?: Record<string, string[]> | undefined;
|
|
45
|
+
}, {
|
|
46
|
+
tables?: Record<string, string[]> | undefined;
|
|
47
|
+
enabled?: boolean | undefined;
|
|
48
|
+
}>>;
|
|
49
|
+
wal: zod0.ZodDefault<zod0.ZodOptional<zod0.ZodBoolean>>;
|
|
50
|
+
}, "strip", zod0.ZodTypeAny, {
|
|
51
|
+
url: string;
|
|
52
|
+
wal: boolean;
|
|
53
|
+
name?: string | undefined;
|
|
54
|
+
description?: string | undefined;
|
|
55
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
56
|
+
tables?: string[] | undefined;
|
|
57
|
+
excludeTables?: string[] | undefined;
|
|
58
|
+
fts?: {
|
|
59
|
+
enabled: boolean;
|
|
60
|
+
tables?: Record<string, string[]> | undefined;
|
|
61
|
+
} | undefined;
|
|
62
|
+
}, {
|
|
63
|
+
url: string;
|
|
64
|
+
name?: string | undefined;
|
|
65
|
+
description?: string | undefined;
|
|
66
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
67
|
+
tables?: string[] | undefined;
|
|
68
|
+
excludeTables?: string[] | undefined;
|
|
69
|
+
fts?: {
|
|
70
|
+
tables?: Record<string, string[]> | undefined;
|
|
71
|
+
enabled?: boolean | undefined;
|
|
72
|
+
} | undefined;
|
|
73
|
+
wal?: boolean | undefined;
|
|
74
|
+
}>;
|
|
75
|
+
/**
|
|
76
|
+
* Loads a module instance from configuration
|
|
77
|
+
*/
|
|
78
|
+
static load({
|
|
79
|
+
parsed
|
|
80
|
+
}: AFSModuleLoadParams): Promise<SQLiteAFS>;
|
|
81
|
+
/**
|
|
82
|
+
* Called when the module is mounted to AFS
|
|
83
|
+
*/
|
|
84
|
+
onMount(_afs: AFSRoot): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Initializes the database connection and introspects schema
|
|
87
|
+
*/
|
|
88
|
+
private initialize;
|
|
89
|
+
/**
|
|
90
|
+
* Ensures the module is initialized
|
|
91
|
+
*/
|
|
92
|
+
private ensureInitialized;
|
|
93
|
+
/**
|
|
94
|
+
* Lists entries at a path
|
|
95
|
+
*/
|
|
96
|
+
list(path: string, options?: AFSListOptions): Promise<AFSListResult>;
|
|
97
|
+
/**
|
|
98
|
+
* Reads an entry at a path
|
|
99
|
+
*/
|
|
100
|
+
read(path: string, _options?: AFSReadOptions): Promise<AFSReadResult>;
|
|
101
|
+
/**
|
|
102
|
+
* Writes an entry at a path
|
|
103
|
+
*/
|
|
104
|
+
write(path: string, content: AFSWriteEntryPayload, _options?: AFSWriteOptions): Promise<AFSWriteResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Deletes an entry at a path
|
|
107
|
+
*/
|
|
108
|
+
delete(path: string, _options?: AFSDeleteOptions): Promise<AFSDeleteResult>;
|
|
109
|
+
/**
|
|
110
|
+
* Searches for entries matching a query
|
|
111
|
+
*/
|
|
112
|
+
search(path: string, query: string, options?: AFSSearchOptions): Promise<AFSSearchResult>;
|
|
113
|
+
/**
|
|
114
|
+
* Executes a module operation
|
|
115
|
+
*/
|
|
116
|
+
exec(path: string, args: Record<string, unknown>, _options: AFSExecOptions): Promise<AFSExecResult>;
|
|
117
|
+
/**
|
|
118
|
+
* Lists available actions for a row
|
|
119
|
+
*/
|
|
120
|
+
private listActions;
|
|
121
|
+
/**
|
|
122
|
+
* Executes an action
|
|
123
|
+
*/
|
|
124
|
+
private executeAction;
|
|
125
|
+
/**
|
|
126
|
+
* Refreshes the schema cache
|
|
127
|
+
*/
|
|
128
|
+
refreshSchema(): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Exports table data in specified format
|
|
131
|
+
*/
|
|
132
|
+
exportTable(table: string, format: string): Promise<unknown>;
|
|
133
|
+
/**
|
|
134
|
+
* Registers a custom action
|
|
135
|
+
*/
|
|
136
|
+
registerAction(name: string, handler: (ctx: ActionContext, params: Record<string, unknown>) => Promise<unknown>, options?: {
|
|
137
|
+
description?: string;
|
|
138
|
+
tableLevel?: boolean;
|
|
139
|
+
rowLevel?: boolean;
|
|
140
|
+
}): void;
|
|
141
|
+
/**
|
|
142
|
+
* Gets table schemas (for external access)
|
|
143
|
+
*/
|
|
144
|
+
getSchemas(): Map<string, TableSchema>;
|
|
145
|
+
/**
|
|
146
|
+
* Gets the database instance (for advanced operations)
|
|
147
|
+
*/
|
|
148
|
+
getDatabase(): LibSQLDatabase;
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
export { SQLiteAFS };
|
|
152
|
+
//# sourceMappingURL=sqlite-afs.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-afs.d.cts","names":[],"sources":["../src/sqlite-afs.ts"],"mappings":";;;;;;;;;AAwCA;;;;;cAAa,SAAA,YAAqB,SAAA;EAAA,QAAA,OAAA;EAAA,SAAA,IAAA;EAAA,SAAA,WAAA;EAAA,SAAA,UAAA,EAGX,aAAA;EAAA,QAAA,EAAA;EAAA,QAAA,OAAA;EAAA,QAAA,MAAA;EAAA,QAAA,IAAA;EAAA,QAAA,SAAA;EAAA,QAAA,OAAA;EAAA,QAAA,SAAA;EAAA,QAAA,WAAA;EAAA,YAAA,OAAA,EAWQ,gBAAA;EAAA;;;EAAA,OAAA,OAAA,QAYhB,SAAA;IAAA,GAAA,EAZgC,IAAA,CAAA,SAAA;IAAA,IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmBf,mBAAA,GAAsB,OAAA,CAAQ,SAAA;EAAA;;;EAAA,QAAA,IAAA,EAQxC,OAAA,GAAU,OAAA;EAAA;;;EAAA,QAAA,UAAA;EAAA;;;EAAA,QAAA,iBAAA;EAAA;;;EAAA,KAAA,IAAA,UAAA,OAAA,GA8CK,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA;;;EAAA,KAAA,IAAA,UAAA,QAAA,GAgCxB,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA;;;EAAA,MAAA,IAAA,UAAA,OAAA,EAmClD,oBAAA,EAAA,QAAA,GACE,eAAA,GACV,OAAA,CAAQ,cAAA;EAAA;;;EAAA,OAAA,IAAA,UAAA,QAAA,GA4C2B,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA;;;EAAA,OAAA,IAAA,UAAA,KAAA,UAAA,OAAA,GAsBb,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA;;;EAAA,KAAA,IAAA,UAAA,IAAA,EAkBvE,MAAA,mBAAA,QAAA,EACI,cAAA,GACT,OAAA,CAAQ,aAAA;EAAA;;;EAAA,QAAA,WAAA;EAAA;;;EAAA,QAAA,aAAA;EAAA;;;EAAA,cAAA,GA8EY,OAAA;EAAA;;;EAAA,YAAA,KAAA,UAAA,MAAA,WAc2B,OAAA;EAAA;;;EAAA,eAAA,IAAA,UAAA,OAAA,GAAA,GAAA,EAkCjC,aAAA,EAAA,MAAA,EAAuB,MAAA,sBAA4B,OAAA,WAAA,OAAA;IAAA,WAAA;IAAA,UAAA;IAAA,QAAA;EAAA;EAAA;;;EAAA,WAAA,GAoBtD,GAAA,SAAY,WAAA;EAAA;;;EAAA,YAAA,GAOX,cAAA;AAAA"}
|