@loom-framework/core 0.1.0-alpha.6 → 0.1.0-alpha.61
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/dist/adapter-base.d.ts +29 -0
- package/dist/adapter-base.d.ts.map +1 -0
- package/dist/adapter-base.js +62 -0
- package/dist/adapter-base.js.map +1 -0
- package/dist/adapter-factory.d.ts +8 -0
- package/dist/adapter-factory.d.ts.map +1 -0
- package/dist/adapter-factory.js +25 -0
- package/dist/adapter-factory.js.map +1 -0
- package/dist/adapter-filesystem.d.ts +6 -11
- package/dist/adapter-filesystem.d.ts.map +1 -1
- package/dist/adapter-filesystem.js +17 -38
- package/dist/adapter-filesystem.js.map +1 -1
- package/dist/adapter-sqlite.d.ts +6 -23
- package/dist/adapter-sqlite.d.ts.map +1 -1
- package/dist/adapter-sqlite.js +45 -50
- package/dist/adapter-sqlite.js.map +1 -1
- package/dist/backend/ai/button-resolver.d.ts +18 -0
- package/dist/backend/ai/button-resolver.d.ts.map +1 -0
- package/dist/backend/ai/button-resolver.js +58 -0
- package/dist/backend/ai/button-resolver.js.map +1 -0
- package/dist/backend/ai/engine.d.ts +52 -0
- package/dist/backend/ai/engine.d.ts.map +1 -0
- package/dist/backend/ai/engine.js +189 -0
- package/dist/backend/ai/engine.js.map +1 -0
- package/dist/backend/ai/index.d.ts +11 -0
- package/dist/backend/ai/index.d.ts.map +1 -0
- package/dist/backend/ai/index.js +8 -0
- package/dist/backend/ai/index.js.map +1 -0
- package/dist/backend/ai/output-parser.d.ts +29 -0
- package/dist/backend/ai/output-parser.d.ts.map +1 -0
- package/dist/backend/ai/output-parser.js +247 -0
- package/dist/backend/ai/output-parser.js.map +1 -0
- package/dist/backend/ai/session-manager.d.ts +103 -0
- package/dist/backend/ai/session-manager.d.ts.map +1 -0
- package/dist/backend/ai/session-manager.js +298 -0
- package/dist/backend/ai/session-manager.js.map +1 -0
- package/dist/backend/index.d.ts +61 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +160 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/observe/index.d.ts +6 -0
- package/dist/backend/observe/index.d.ts.map +1 -0
- package/dist/backend/observe/index.js +5 -0
- package/dist/backend/observe/index.js.map +1 -0
- package/dist/backend/observe/logger.d.ts +28 -0
- package/dist/backend/observe/logger.d.ts.map +1 -0
- package/dist/backend/observe/logger.js +80 -0
- package/dist/backend/observe/logger.js.map +1 -0
- package/dist/backend/observe/types.d.ts +26 -0
- package/dist/backend/observe/types.d.ts.map +1 -0
- package/dist/backend/observe/types.js +7 -0
- package/dist/backend/observe/types.js.map +1 -0
- package/dist/backend/routes/chat.d.ts +31 -0
- package/dist/backend/routes/chat.d.ts.map +1 -0
- package/dist/backend/routes/chat.js +426 -0
- package/dist/backend/routes/chat.js.map +1 -0
- package/dist/backend/routes/data.d.ts +13 -0
- package/dist/backend/routes/data.d.ts.map +1 -0
- package/dist/backend/routes/data.js +129 -0
- package/dist/backend/routes/data.js.map +1 -0
- package/dist/backend/routes/health.d.ts +7 -0
- package/dist/backend/routes/health.d.ts.map +1 -0
- package/dist/backend/routes/health.js +15 -0
- package/dist/backend/routes/health.js.map +1 -0
- package/dist/backend/routes/index.d.ts +9 -0
- package/dist/backend/routes/index.d.ts.map +1 -0
- package/dist/backend/routes/index.js +8 -0
- package/dist/backend/routes/index.js.map +1 -0
- package/dist/backend/routes/upload.d.ts +24 -0
- package/dist/backend/routes/upload.d.ts.map +1 -0
- package/dist/backend/routes/upload.js +67 -0
- package/dist/backend/routes/upload.js.map +1 -0
- package/dist/bin.d.ts +8 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +12 -0
- package/dist/bin.js.map +1 -0
- package/dist/capability-generator.d.ts +16 -6
- package/dist/capability-generator.d.ts.map +1 -1
- package/dist/capability-generator.js +160 -248
- package/dist/capability-generator.js.map +1 -1
- package/dist/cli/commands/build.d.ts +11 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +170 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/data.d.ts +12 -0
- package/dist/cli/commands/data.d.ts.map +1 -0
- package/dist/cli/commands/data.js +158 -0
- package/dist/cli/commands/data.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +9 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +114 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate-capabilities.d.ts +8 -0
- package/dist/cli/commands/generate-capabilities.d.ts.map +1 -0
- package/dist/cli/commands/generate-capabilities.js +40 -0
- package/dist/cli/commands/generate-capabilities.js.map +1 -0
- package/dist/cli/commands/generate-cli-command.d.ts +8 -0
- package/dist/cli/commands/generate-cli-command.d.ts.map +1 -0
- package/dist/cli/commands/generate-cli-command.js +64 -0
- package/dist/cli/commands/generate-cli-command.js.map +1 -0
- package/dist/cli/commands/generate-page.d.ts +9 -0
- package/dist/cli/commands/generate-page.d.ts.map +1 -0
- package/dist/cli/commands/generate-page.js +418 -0
- package/dist/cli/commands/generate-page.js.map +1 -0
- package/dist/cli/commands/generate-skill.d.ts +8 -0
- package/dist/cli/commands/generate-skill.d.ts.map +1 -0
- package/dist/cli/commands/generate-skill.js +75 -0
- package/dist/cli/commands/generate-skill.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +6 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +17 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +539 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/observe.d.ts +9 -0
- package/dist/cli/commands/observe.d.ts.map +1 -0
- package/dist/cli/commands/observe.js +142 -0
- package/dist/cli/commands/observe.js.map +1 -0
- package/dist/cli/commands/skill.d.ts +9 -0
- package/dist/cli/commands/skill.d.ts.map +1 -0
- package/dist/cli/commands/skill.js +186 -0
- package/dist/cli/commands/skill.js.map +1 -0
- package/dist/cli/helpers/duration.d.ts +5 -0
- package/dist/cli/helpers/duration.d.ts.map +1 -0
- package/dist/cli/helpers/duration.js +19 -0
- package/dist/cli/helpers/duration.js.map +1 -0
- package/dist/cli/helpers/field-template.d.ts +9 -0
- package/dist/cli/helpers/field-template.d.ts.map +1 -0
- package/dist/cli/helpers/field-template.js +92 -0
- package/dist/cli/helpers/field-template.js.map +1 -0
- package/dist/cli/helpers/naming.d.ts +12 -0
- package/dist/cli/helpers/naming.d.ts.map +1 -0
- package/dist/cli/helpers/naming.js +25 -0
- package/dist/cli/helpers/naming.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +33 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils.d.ts +10 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +31 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/config.d.ts +8 -33
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -7
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/server-bin.d.ts +12 -0
- package/dist/server-bin.d.ts.map +1 -0
- package/dist/server-bin.js +75 -0
- package/dist/server-bin.js.map +1 -0
- package/dist/types.d.ts +28 -18
- package/dist/types.d.ts.map +1 -1
- package/package.json +17 -4
- package/templates/skill/SKILL.md +140 -0
- package/templates/skill/references/README.md +128 -0
- package/templates/skill/references/data-model.md +78 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseAdapter - Shared logic for DataAdapter implementations
|
|
3
|
+
*
|
|
4
|
+
* Extracts common validation, ID generation, and schema management
|
|
5
|
+
* used by both FileSystemAdapter and SQLiteAdapter.
|
|
6
|
+
*/
|
|
7
|
+
import type { DataAdapter, DataRecord, ModelSchema, LoomConfig } from './types.js';
|
|
8
|
+
export declare abstract class BaseAdapter implements DataAdapter {
|
|
9
|
+
abstract readonly name: string;
|
|
10
|
+
protected schemas: Map<string, ModelSchema>;
|
|
11
|
+
protected config: LoomConfig;
|
|
12
|
+
constructor(config: LoomConfig);
|
|
13
|
+
abstract initialize(): Promise<void>;
|
|
14
|
+
abstract healthCheck(): Promise<boolean>;
|
|
15
|
+
abstract read(model: string, options?: import('./types.js').ReadOptions): Promise<DataRecord | DataRecord[] | null>;
|
|
16
|
+
abstract write(model: string, data: DataRecord): Promise<DataRecord>;
|
|
17
|
+
abstract update(model: string, id: string, data: DataRecord): Promise<DataRecord>;
|
|
18
|
+
abstract delete(model: string, id: string): Promise<void>;
|
|
19
|
+
getSchema(model: string): Promise<ModelSchema | undefined>;
|
|
20
|
+
listModels(): Promise<string[]>;
|
|
21
|
+
protected requireModel(model: string): void;
|
|
22
|
+
protected generateId(): string;
|
|
23
|
+
/**
|
|
24
|
+
* Validate required fields and apply defaults on a record.
|
|
25
|
+
* Returns the validated record with defaults applied.
|
|
26
|
+
*/
|
|
27
|
+
protected validateAndApplyDefaults(model: string, record: DataRecord, skipIdValidation?: boolean): DataRecord;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=adapter-base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-base.d.ts","sourceRoot":"","sources":["../src/adapter-base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEnF,8BAAsB,WAAY,YAAW,WAAW;IACtD,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAa;IACxD,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC;gBAEjB,MAAM,EAAE,UAAU;IAO9B,QAAQ,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IACpC,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,YAAY,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;IACnH,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACpE,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACjF,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEnD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAI1D,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAMrC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQ3C,SAAS,CAAC,UAAU,IAAI,MAAM;IAM9B;;;OAGG;IACH,SAAS,CAAC,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,gBAAgB,UAAQ,GAAG,UAAU;CA2B5G"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BaseAdapter - Shared logic for DataAdapter implementations
|
|
3
|
+
*
|
|
4
|
+
* Extracts common validation, ID generation, and schema management
|
|
5
|
+
* used by both FileSystemAdapter and SQLiteAdapter.
|
|
6
|
+
*/
|
|
7
|
+
export class BaseAdapter {
|
|
8
|
+
schemas = new Map();
|
|
9
|
+
config;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
for (const model of config.data.models) {
|
|
13
|
+
this.schemas.set(model.name, model);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
async getSchema(model) {
|
|
17
|
+
return this.schemas.get(model);
|
|
18
|
+
}
|
|
19
|
+
async listModels() {
|
|
20
|
+
return Array.from(this.schemas.keys());
|
|
21
|
+
}
|
|
22
|
+
// ── Shared Helpers ──
|
|
23
|
+
requireModel(model) {
|
|
24
|
+
if (!this.schemas.has(model)) {
|
|
25
|
+
throw new Error(`Unknown model: ${model}. Available: ${Array.from(this.schemas.keys()).join(', ')}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
generateId() {
|
|
29
|
+
const timestamp = Date.now().toString(36);
|
|
30
|
+
const random = Math.random().toString(36).substring(2, 10);
|
|
31
|
+
return `rec_${timestamp}_${random}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Validate required fields and apply defaults on a record.
|
|
35
|
+
* Returns the validated record with defaults applied.
|
|
36
|
+
*/
|
|
37
|
+
validateAndApplyDefaults(model, record, skipIdValidation = false) {
|
|
38
|
+
const schema = this.schemas.get(model);
|
|
39
|
+
// Apply default values for missing fields
|
|
40
|
+
for (const field of schema.fields) {
|
|
41
|
+
if (record[field.name] === undefined && field.default !== undefined) {
|
|
42
|
+
record[field.name] = field.default;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Validate required fields
|
|
46
|
+
for (const field of schema.fields) {
|
|
47
|
+
if (skipIdValidation && field.name === 'id')
|
|
48
|
+
continue;
|
|
49
|
+
if (field.required && record[field.name] === undefined) {
|
|
50
|
+
throw new Error(`Missing required field: ${field.name}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Validate enum constraints
|
|
54
|
+
for (const field of schema.fields) {
|
|
55
|
+
if (field.enum && record[field.name] !== undefined && !field.enum.includes(record[field.name])) {
|
|
56
|
+
throw new Error(`Invalid value for field '${field.name}': ${record[field.name]}. Allowed values: ${field.enum.join(', ')}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return record;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=adapter-base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-base.js","sourceRoot":"","sources":["../src/adapter-base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates the appropriate DataAdapter based on LoomConfig.data.defaultAdapter.
|
|
5
|
+
*/
|
|
6
|
+
import type { LoomConfig, DataAdapter } from './types.js';
|
|
7
|
+
export declare function createAdapter(config: LoomConfig, projectRoot: string): DataAdapter;
|
|
8
|
+
//# sourceMappingURL=adapter-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-factory.d.ts","sourceRoot":"","sources":["../src/adapter-factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE1D,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,WAAW,CAgBlF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates the appropriate DataAdapter based on LoomConfig.data.defaultAdapter.
|
|
5
|
+
*/
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { FileSystemAdapter } from './adapter-filesystem.js';
|
|
8
|
+
import { SQLiteAdapter } from './adapter-sqlite.js';
|
|
9
|
+
export function createAdapter(config, projectRoot) {
|
|
10
|
+
const adapterType = config.data.defaultAdapter || 'filesystem';
|
|
11
|
+
switch (adapterType) {
|
|
12
|
+
case 'sqlite':
|
|
13
|
+
return new SQLiteAdapter({
|
|
14
|
+
dbPath: path.join(projectRoot, 'data', config.data.sqlite?.filename ?? 'loom.db'),
|
|
15
|
+
config,
|
|
16
|
+
});
|
|
17
|
+
case 'filesystem':
|
|
18
|
+
default:
|
|
19
|
+
return new FileSystemAdapter({
|
|
20
|
+
dataDir: path.join(projectRoot, 'data'),
|
|
21
|
+
config,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=adapter-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-factory.js","sourceRoot":"","sources":["../src/adapter-factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,MAAM,UAAU,aAAa,CAAC,MAAkB,EAAE,WAAmB;IACnE,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,IAAI,YAAY,CAAC;IAE/D,QAAQ,WAAW,EAAE,CAAC;QACpB,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC;gBACvB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,SAAS,CAAC;gBACjF,MAAM;aACP,CAAC,CAAC;QACL,KAAK,YAAY,CAAC;QAClB;YACE,OAAO,IAAI,iBAAiB,CAAC;gBAC3B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;gBACvC,MAAM;aACP,CAAC,CAAC;IACP,CAAC;AACH,CAAC"}
|
|
@@ -4,29 +4,24 @@
|
|
|
4
4
|
* Stores data as JSON files, organized by model.
|
|
5
5
|
* Default adapter for development and small deployments.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { DataRecord, ReadOptions, LoomConfig } from './types.js';
|
|
8
|
+
import { BaseAdapter } from './adapter-base.js';
|
|
8
9
|
export interface FileSystemAdapterOptions {
|
|
9
10
|
dataDir: string;
|
|
10
11
|
config: LoomConfig;
|
|
11
12
|
}
|
|
12
|
-
export declare class FileSystemAdapter
|
|
13
|
+
export declare class FileSystemAdapter extends BaseAdapter {
|
|
13
14
|
readonly name = "filesystem";
|
|
14
15
|
private dataDir;
|
|
15
|
-
private config;
|
|
16
|
-
private schemas;
|
|
17
16
|
constructor(options: FileSystemAdapterOptions);
|
|
18
17
|
initialize(): Promise<void>;
|
|
19
18
|
healthCheck(): Promise<boolean>;
|
|
20
|
-
read(model: string, options?: ReadOptions): Promise<
|
|
21
|
-
write(model: string, data:
|
|
22
|
-
update(model: string, id: string, data:
|
|
19
|
+
read(model: string, options?: ReadOptions): Promise<DataRecord | DataRecord[] | null>;
|
|
20
|
+
write(model: string, data: DataRecord): Promise<DataRecord>;
|
|
21
|
+
update(model: string, id: string, data: DataRecord): Promise<DataRecord>;
|
|
23
22
|
delete(model: string, id: string): Promise<void>;
|
|
24
|
-
getSchema(model: string): Promise<ModelSchema | undefined>;
|
|
25
|
-
listModels(): Promise<string[]>;
|
|
26
|
-
private requireModel;
|
|
27
23
|
private getModelDir;
|
|
28
24
|
private getRecordPath;
|
|
29
25
|
private matchesFilter;
|
|
30
|
-
private generateId;
|
|
31
26
|
}
|
|
32
27
|
//# sourceMappingURL=adapter-filesystem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-filesystem.d.ts","sourceRoot":"","sources":["../src/adapter-filesystem.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"adapter-filesystem.d.ts","sourceRoot":"","sources":["../src/adapter-filesystem.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,qBAAa,iBAAkB,SAAQ,WAAW;IAChD,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,wBAAwB;IAKvC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;IA0CrF,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAc3D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAmBxE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatD,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,aAAa;CAQtB"}
|
|
@@ -6,18 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { promises as fs } from 'fs';
|
|
8
8
|
import path from 'path';
|
|
9
|
-
|
|
9
|
+
import { BaseAdapter } from './adapter-base.js';
|
|
10
|
+
export class FileSystemAdapter extends BaseAdapter {
|
|
10
11
|
name = 'filesystem';
|
|
11
12
|
dataDir;
|
|
12
|
-
config;
|
|
13
|
-
schemas = new Map();
|
|
14
13
|
constructor(options) {
|
|
14
|
+
super(options.config);
|
|
15
15
|
this.dataDir = options.dataDir;
|
|
16
|
-
this.config = options.config;
|
|
17
|
-
// Index model schemas
|
|
18
|
-
for (const model of options.config.data.models) {
|
|
19
|
-
this.schemas.set(model.name, model);
|
|
20
|
-
}
|
|
21
16
|
}
|
|
22
17
|
async initialize() {
|
|
23
18
|
await fs.mkdir(this.dataDir, { recursive: true });
|
|
@@ -57,26 +52,27 @@ export class FileSystemAdapter {
|
|
|
57
52
|
if (!file.endsWith('.json'))
|
|
58
53
|
continue;
|
|
59
54
|
const content = await fs.readFile(path.join(modelDir, file), 'utf-8');
|
|
60
|
-
const
|
|
61
|
-
//
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
const parsed = JSON.parse(content);
|
|
56
|
+
// Handle both single records and arrays (e.g. init.json seed data)
|
|
57
|
+
const items = Array.isArray(parsed) ? parsed : [parsed];
|
|
58
|
+
for (const record of items) {
|
|
59
|
+
// Apply filter if provided
|
|
60
|
+
if (options?.filter && !this.matchesFilter(record, options.filter)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
records.push(record);
|
|
64
64
|
}
|
|
65
|
-
records.push(record);
|
|
66
65
|
}
|
|
67
|
-
|
|
66
|
+
// Apply offset and limit
|
|
67
|
+
const start = options?.offset || 0;
|
|
68
|
+
const end = options?.limit ? start + options.limit : undefined;
|
|
69
|
+
return records.slice(start, end);
|
|
68
70
|
}
|
|
69
71
|
async write(model, data) {
|
|
70
72
|
this.requireModel(model);
|
|
71
|
-
const schema = this.schemas.get(model);
|
|
72
73
|
const id = data.id || this.generateId();
|
|
73
|
-
// Validate required fields
|
|
74
|
-
for (const field of schema.fields) {
|
|
75
|
-
if (field.required && data[field.name] === undefined) {
|
|
76
|
-
throw new Error(`Missing required field: ${field.name}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
74
|
const record = { id, ...data };
|
|
75
|
+
this.validateAndApplyDefaults(model, record);
|
|
80
76
|
const filePath = this.getRecordPath(model, id);
|
|
81
77
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
82
78
|
await fs.writeFile(filePath, JSON.stringify(record, null, 2), 'utf-8');
|
|
@@ -107,18 +103,7 @@ export class FileSystemAdapter {
|
|
|
107
103
|
throw new Error(`Record not found: ${model}/${id}`);
|
|
108
104
|
}
|
|
109
105
|
}
|
|
110
|
-
async getSchema(model) {
|
|
111
|
-
return this.schemas.get(model);
|
|
112
|
-
}
|
|
113
|
-
async listModels() {
|
|
114
|
-
return Array.from(this.schemas.keys());
|
|
115
|
-
}
|
|
116
106
|
// ── Private Helpers ──
|
|
117
|
-
requireModel(model) {
|
|
118
|
-
if (!this.schemas.has(model)) {
|
|
119
|
-
throw new Error(`Unknown model: ${model}. Available: ${Array.from(this.schemas.keys()).join(', ')}`);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
107
|
getModelDir(model) {
|
|
123
108
|
const schema = this.schemas.get(model);
|
|
124
109
|
const adapterConfig = schema.adapters?.filesystem;
|
|
@@ -131,11 +116,5 @@ export class FileSystemAdapter {
|
|
|
131
116
|
matchesFilter(record, filter) {
|
|
132
117
|
return Object.entries(filter).every(([key, value]) => record[key] === value);
|
|
133
118
|
}
|
|
134
|
-
generateId() {
|
|
135
|
-
// Simple ID generation without dynamic import
|
|
136
|
-
const timestamp = Date.now().toString(36);
|
|
137
|
-
const random = Math.random().toString(36).substring(2, 10);
|
|
138
|
-
return `rec_${timestamp}_${random}`;
|
|
139
|
-
}
|
|
140
119
|
}
|
|
141
120
|
//# sourceMappingURL=adapter-filesystem.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-filesystem.js","sourceRoot":"","sources":["../src/adapter-filesystem.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter-filesystem.js","sourceRoot":"","sources":["../src/adapter-filesystem.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter-sqlite.d.ts
CHANGED
|
@@ -4,48 +4,31 @@
|
|
|
4
4
|
* Stores data in a SQLite database using better-sqlite3.
|
|
5
5
|
* Suitable for medium-scale and embedded deployments.
|
|
6
6
|
*/
|
|
7
|
-
import type {
|
|
7
|
+
import type { DataRecord, ReadOptions, LoomConfig } from './types.js';
|
|
8
|
+
import { BaseAdapter } from './adapter-base.js';
|
|
8
9
|
export interface SQLiteAdapterOptions {
|
|
9
10
|
/** Path to the SQLite database file */
|
|
10
11
|
dbPath: string;
|
|
11
12
|
config: LoomConfig;
|
|
12
13
|
}
|
|
13
|
-
export declare class SQLiteAdapter
|
|
14
|
+
export declare class SQLiteAdapter extends BaseAdapter {
|
|
14
15
|
readonly name = "sqlite";
|
|
15
16
|
private dbPath;
|
|
16
|
-
private config;
|
|
17
17
|
private db;
|
|
18
|
-
private schemas;
|
|
19
18
|
constructor(options: SQLiteAdapterOptions);
|
|
20
19
|
initialize(): Promise<void>;
|
|
21
20
|
healthCheck(): Promise<boolean>;
|
|
22
|
-
read(model: string, options?: ReadOptions): Promise<
|
|
23
|
-
write(model: string, data:
|
|
24
|
-
update(model: string, id: string, data:
|
|
21
|
+
read(model: string, options?: ReadOptions): Promise<DataRecord | DataRecord[] | null>;
|
|
22
|
+
write(model: string, data: DataRecord): Promise<DataRecord>;
|
|
23
|
+
update(model: string, id: string, data: DataRecord): Promise<DataRecord>;
|
|
25
24
|
delete(model: string, id: string): Promise<void>;
|
|
26
|
-
getSchema(model: string): Promise<ModelSchema | undefined>;
|
|
27
|
-
listModels(): Promise<string[]>;
|
|
28
25
|
/**
|
|
29
26
|
* Close the database connection
|
|
30
27
|
*/
|
|
31
28
|
close(): void;
|
|
32
|
-
private requireModel;
|
|
33
|
-
/**
|
|
34
|
-
* Create a table for a model based on its schema
|
|
35
|
-
*/
|
|
36
29
|
private createTable;
|
|
37
|
-
/**
|
|
38
|
-
* Map Loom field types to SQLite types
|
|
39
|
-
*/
|
|
40
30
|
private mapFieldType;
|
|
41
|
-
/**
|
|
42
|
-
* Serialize a value for SQLite storage
|
|
43
|
-
*/
|
|
44
31
|
private serializeValue;
|
|
45
|
-
/**
|
|
46
|
-
* Deserialize a row from SQLite storage
|
|
47
|
-
*/
|
|
48
32
|
private deserializeRow;
|
|
49
|
-
private generateId;
|
|
50
33
|
}
|
|
51
34
|
//# sourceMappingURL=adapter-sqlite.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-sqlite.d.ts","sourceRoot":"","sources":["../src/adapter-sqlite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"adapter-sqlite.d.ts","sourceRoot":"","sources":["../src/adapter-sqlite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,UAAU,CAAC;CACpB;AAUD,qBAAa,aAAc,SAAQ,WAAW;IAC5C,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,EAAE,CAAqB;gBAEnB,OAAO,EAAE,oBAAoB;IAKnC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;IAuCrF,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAmB3D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAoBxE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,cAAc;CAyBvB"}
|
package/dist/adapter-sqlite.js
CHANGED
|
@@ -7,18 +7,20 @@
|
|
|
7
7
|
import Database from 'better-sqlite3';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import fs from 'fs';
|
|
10
|
-
|
|
10
|
+
import { BaseAdapter } from './adapter-base.js';
|
|
11
|
+
const VALID_IDENTIFIER = /^[a-zA-Z][a-zA-Z0-9_]*$/;
|
|
12
|
+
function validateIdentifier(name, label) {
|
|
13
|
+
if (!VALID_IDENTIFIER.test(name)) {
|
|
14
|
+
throw new Error(`Invalid ${label}: "${name}". Must match /^[a-zA-Z][a-zA-Z0-9_]*$/`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class SQLiteAdapter extends BaseAdapter {
|
|
11
18
|
name = 'sqlite';
|
|
12
19
|
dbPath;
|
|
13
|
-
config;
|
|
14
20
|
db;
|
|
15
|
-
schemas = new Map();
|
|
16
21
|
constructor(options) {
|
|
22
|
+
super(options.config);
|
|
17
23
|
this.dbPath = options.dbPath;
|
|
18
|
-
this.config = options.config;
|
|
19
|
-
for (const model of options.config.data.models) {
|
|
20
|
-
this.schemas.set(model.name, model);
|
|
21
|
-
}
|
|
22
24
|
}
|
|
23
25
|
async initialize() {
|
|
24
26
|
// Ensure directory exists
|
|
@@ -26,9 +28,24 @@ export class SQLiteAdapter {
|
|
|
26
28
|
if (!fs.existsSync(dir)) {
|
|
27
29
|
fs.mkdirSync(dir, { recursive: true });
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
try {
|
|
32
|
+
this.db = new Database(this.dbPath);
|
|
33
|
+
this.db.pragma('journal_mode = WAL');
|
|
34
|
+
this.db.pragma('foreign_keys = ON');
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
const msg = err?.message ?? String(err);
|
|
38
|
+
if (msg.includes('Could not locate the bindings file') || msg.includes('better_sqlite3.node')) {
|
|
39
|
+
throw new Error('better-sqlite3 native module failed to load.\n' +
|
|
40
|
+
'This usually means the native binary was not compiled for your Node.js version.\n\n' +
|
|
41
|
+
'Fix options:\n' +
|
|
42
|
+
' 1. Rebuild from source: cd node_modules/better-sqlite3 && npx node-gyp rebuild\n' +
|
|
43
|
+
' 2. Switch adapter: change defaultAdapter to "filesystem" in loom.config.ts\n' +
|
|
44
|
+
` 3. Check Node.js: better-sqlite3 may not support Node ${process.version} yet\n\n` +
|
|
45
|
+
`Original error: ${msg}`);
|
|
46
|
+
}
|
|
47
|
+
throw err;
|
|
48
|
+
}
|
|
32
49
|
// Auto-create tables from config
|
|
33
50
|
for (const model of this.config.data.models) {
|
|
34
51
|
this.createTable(model);
|
|
@@ -45,6 +62,7 @@ export class SQLiteAdapter {
|
|
|
45
62
|
}
|
|
46
63
|
async read(model, options) {
|
|
47
64
|
this.requireModel(model);
|
|
65
|
+
validateIdentifier(model, 'model name');
|
|
48
66
|
// Read by ID
|
|
49
67
|
if (options?.id) {
|
|
50
68
|
const row = this.db.prepare(`SELECT * FROM "${model}" WHERE id = ?`).get(options.id);
|
|
@@ -56,31 +74,31 @@ export class SQLiteAdapter {
|
|
|
56
74
|
if (options?.filter && Object.keys(options.filter).length > 0) {
|
|
57
75
|
const filter = options.filter;
|
|
58
76
|
const conditions = Object.entries(filter).map(([key, value]) => {
|
|
77
|
+
validateIdentifier(key, 'filter field name');
|
|
59
78
|
params.push(value);
|
|
60
79
|
return `"${key}" = ?`;
|
|
61
80
|
});
|
|
62
81
|
sql += ` WHERE ${conditions.join(' AND ')}`;
|
|
63
82
|
}
|
|
64
|
-
if (options?.limit) {
|
|
65
|
-
|
|
66
|
-
|
|
83
|
+
if (options?.limit || options?.offset) {
|
|
84
|
+
if (options?.limit) {
|
|
85
|
+
sql += ` LIMIT ?`;
|
|
86
|
+
params.push(options.limit);
|
|
87
|
+
}
|
|
88
|
+
if (options?.offset) {
|
|
89
|
+
sql += ` OFFSET ?`;
|
|
90
|
+
params.push(options.offset);
|
|
91
|
+
}
|
|
67
92
|
}
|
|
68
93
|
const rows = this.db.prepare(sql).all(...params);
|
|
69
94
|
return rows.map((row) => this.deserializeRow(row, model));
|
|
70
95
|
}
|
|
71
96
|
async write(model, data) {
|
|
72
97
|
this.requireModel(model);
|
|
73
|
-
|
|
98
|
+
validateIdentifier(model, 'model name');
|
|
74
99
|
const id = data.id || this.generateId();
|
|
75
|
-
// Validate required fields (skip id — auto-generated if not provided)
|
|
76
|
-
for (const field of schema.fields) {
|
|
77
|
-
if (field.name === 'id')
|
|
78
|
-
continue;
|
|
79
|
-
if (field.required && data[field.name] === undefined) {
|
|
80
|
-
throw new Error(`Missing required field: ${field.name}`);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
100
|
const record = { id, ...data };
|
|
101
|
+
this.validateAndApplyDefaults(model, record, true);
|
|
84
102
|
// Insert into table
|
|
85
103
|
const columns = Object.keys(record);
|
|
86
104
|
const values = columns.map((col) => this.serializeValue(record[col], model, col));
|
|
@@ -91,6 +109,7 @@ export class SQLiteAdapter {
|
|
|
91
109
|
}
|
|
92
110
|
async update(model, id, data) {
|
|
93
111
|
this.requireModel(model);
|
|
112
|
+
validateIdentifier(model, 'model name');
|
|
94
113
|
// Check record exists
|
|
95
114
|
const existing = this.db.prepare(`SELECT * FROM "${model}" WHERE id = ?`).get(id);
|
|
96
115
|
if (!existing) {
|
|
@@ -105,17 +124,12 @@ export class SQLiteAdapter {
|
|
|
105
124
|
}
|
|
106
125
|
async delete(model, id) {
|
|
107
126
|
this.requireModel(model);
|
|
127
|
+
validateIdentifier(model, 'model name');
|
|
108
128
|
const result = this.db.prepare(`DELETE FROM "${model}" WHERE id = ?`).run(id);
|
|
109
129
|
if (result.changes === 0) {
|
|
110
130
|
throw new Error(`Record not found: ${model}/${id}`);
|
|
111
131
|
}
|
|
112
132
|
}
|
|
113
|
-
async getSchema(model) {
|
|
114
|
-
return this.schemas.get(model);
|
|
115
|
-
}
|
|
116
|
-
async listModels() {
|
|
117
|
-
return Array.from(this.schemas.keys());
|
|
118
|
-
}
|
|
119
133
|
/**
|
|
120
134
|
* Close the database connection
|
|
121
135
|
*/
|
|
@@ -123,19 +137,12 @@ export class SQLiteAdapter {
|
|
|
123
137
|
this.db?.close();
|
|
124
138
|
}
|
|
125
139
|
// ── Private Helpers ──
|
|
126
|
-
requireModel(model) {
|
|
127
|
-
if (!this.schemas.has(model)) {
|
|
128
|
-
throw new Error(`Unknown model: ${model}. Available: ${Array.from(this.schemas.keys()).join(', ')}`);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Create a table for a model based on its schema
|
|
133
|
-
*/
|
|
134
140
|
createTable(model) {
|
|
135
141
|
const columns = ['id TEXT PRIMARY KEY'];
|
|
136
142
|
for (const field of model.fields) {
|
|
137
143
|
if (field.name === 'id')
|
|
138
144
|
continue; // Already added
|
|
145
|
+
validateIdentifier(field.name, `field name in model "${model.name}"`);
|
|
139
146
|
const colType = this.mapFieldType(field.type);
|
|
140
147
|
const notNull = field.required ? ' NOT NULL' : '';
|
|
141
148
|
const defaultVal = field.default !== undefined ? ` DEFAULT ${JSON.stringify(field.default)}` : '';
|
|
@@ -148,14 +155,13 @@ export class SQLiteAdapter {
|
|
|
148
155
|
for (const index of model.indexes) {
|
|
149
156
|
const indexName = `idx_${model.name}_${index.fields.join('_')}`;
|
|
150
157
|
const unique = index.unique ? 'UNIQUE ' : '';
|
|
158
|
+
for (const f of index.fields)
|
|
159
|
+
validateIdentifier(f, `index field name in model "${model.name}"`);
|
|
151
160
|
const cols = index.fields.map((f) => `"${f}"`).join(', ');
|
|
152
161
|
this.db.exec(`CREATE ${unique}INDEX IF NOT EXISTS "${indexName}" ON "${model.name}" (${cols})`);
|
|
153
162
|
}
|
|
154
163
|
}
|
|
155
164
|
}
|
|
156
|
-
/**
|
|
157
|
-
* Map Loom field types to SQLite types
|
|
158
|
-
*/
|
|
159
165
|
mapFieldType(type) {
|
|
160
166
|
switch (type) {
|
|
161
167
|
case 'string':
|
|
@@ -173,9 +179,6 @@ export class SQLiteAdapter {
|
|
|
173
179
|
return 'TEXT';
|
|
174
180
|
}
|
|
175
181
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Serialize a value for SQLite storage
|
|
178
|
-
*/
|
|
179
182
|
serializeValue(value, model, field) {
|
|
180
183
|
if (value === null || value === undefined)
|
|
181
184
|
return null;
|
|
@@ -188,9 +191,6 @@ export class SQLiteAdapter {
|
|
|
188
191
|
return value ? 1 : 0;
|
|
189
192
|
return value;
|
|
190
193
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Deserialize a row from SQLite storage
|
|
193
|
-
*/
|
|
194
194
|
deserializeRow(row, model) {
|
|
195
195
|
const schema = this.schemas.get(model);
|
|
196
196
|
if (!schema)
|
|
@@ -216,10 +216,5 @@ export class SQLiteAdapter {
|
|
|
216
216
|
}
|
|
217
217
|
return result;
|
|
218
218
|
}
|
|
219
|
-
generateId() {
|
|
220
|
-
const timestamp = Date.now().toString(36);
|
|
221
|
-
const random = Math.random().toString(36).substring(2, 10);
|
|
222
|
-
return `rec_${timestamp}_${random}`;
|
|
223
|
-
}
|
|
224
219
|
}
|
|
225
220
|
//# sourceMappingURL=adapter-sqlite.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-sqlite.js","sourceRoot":"","sources":["../src/adapter-sqlite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter-sqlite.js","sourceRoot":"","sources":["../src/adapter-sqlite.ts"],"names":[],"mappings":"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"}
|