@loom-framework/core 0.1.0-alpha.142 → 0.1.0-alpha.143

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.
Files changed (77) hide show
  1. package/dist/adapters/base.d.ts +31 -0
  2. package/dist/adapters/base.d.ts.map +1 -0
  3. package/dist/adapters/base.js +69 -0
  4. package/dist/adapters/base.js.map +1 -0
  5. package/dist/adapters/factory.d.ts +8 -0
  6. package/dist/adapters/factory.d.ts.map +1 -0
  7. package/dist/adapters/factory.js +25 -0
  8. package/dist/adapters/factory.js.map +1 -0
  9. package/dist/adapters/filesystem.d.ts +46 -0
  10. package/dist/adapters/filesystem.d.ts.map +1 -0
  11. package/dist/adapters/filesystem.js +321 -0
  12. package/dist/adapters/filesystem.js.map +1 -0
  13. package/dist/adapters/index.d.ts +10 -0
  14. package/dist/adapters/index.d.ts.map +1 -0
  15. package/dist/adapters/index.js +8 -0
  16. package/dist/adapters/index.js.map +1 -0
  17. package/dist/adapters/sqlite.d.ts +37 -0
  18. package/dist/adapters/sqlite.d.ts.map +1 -0
  19. package/dist/adapters/sqlite.js +264 -0
  20. package/dist/adapters/sqlite.js.map +1 -0
  21. package/dist/backend/index.js +1 -1
  22. package/dist/backend/index.js.map +1 -1
  23. package/dist/backend/routes/skills.d.ts +3 -3
  24. package/dist/backend/routes/skills.d.ts.map +1 -1
  25. package/dist/backend/routes/skills.js +3 -3
  26. package/dist/backend/routes/skills.js.map +1 -1
  27. package/dist/backend/services/skill-archive.d.ts +13 -0
  28. package/dist/backend/services/skill-archive.d.ts.map +1 -0
  29. package/dist/backend/services/skill-archive.js +84 -0
  30. package/dist/backend/services/skill-archive.js.map +1 -0
  31. package/dist/backend/services/skill-parser.d.ts +41 -0
  32. package/dist/backend/services/skill-parser.d.ts.map +1 -0
  33. package/dist/backend/services/skill-parser.js +184 -0
  34. package/dist/backend/services/skill-parser.js.map +1 -0
  35. package/dist/backend/services/skill-service.d.ts +113 -0
  36. package/dist/backend/services/skill-service.d.ts.map +1 -0
  37. package/dist/backend/services/skill-service.js +265 -0
  38. package/dist/backend/services/skill-service.js.map +1 -0
  39. package/dist/cli/commands/data.js +2 -2
  40. package/dist/cli/commands/data.js.map +1 -1
  41. package/dist/cli/commands/generate-dashboard.d.ts.map +1 -1
  42. package/dist/cli/commands/generate-dashboard.js +1 -450
  43. package/dist/cli/commands/generate-dashboard.js.map +1 -1
  44. package/dist/cli/commands/generate-page.d.ts.map +1 -1
  45. package/dist/cli/commands/generate-page.js +4 -436
  46. package/dist/cli/commands/generate-page.js.map +1 -1
  47. package/dist/cli/commands/serve.d.ts +12 -0
  48. package/dist/cli/commands/serve.d.ts.map +1 -0
  49. package/dist/cli/commands/serve.js +43 -0
  50. package/dist/cli/commands/serve.js.map +1 -0
  51. package/dist/cli/framework.d.ts +28 -0
  52. package/dist/cli/framework.d.ts.map +1 -0
  53. package/dist/cli/framework.js +29 -0
  54. package/dist/cli/framework.js.map +1 -0
  55. package/dist/cli/helpers/i18n-template.d.ts +13 -0
  56. package/dist/cli/helpers/i18n-template.d.ts.map +1 -0
  57. package/dist/cli/helpers/i18n-template.js +48 -0
  58. package/dist/cli/helpers/i18n-template.js.map +1 -0
  59. package/dist/cli/templates/crud-page.d.ts +14 -0
  60. package/dist/cli/templates/crud-page.d.ts.map +1 -0
  61. package/dist/cli/templates/crud-page.js +405 -0
  62. package/dist/cli/templates/crud-page.js.map +1 -0
  63. package/dist/cli/templates/dashboard-page.d.ts +11 -0
  64. package/dist/cli/templates/dashboard-page.d.ts.map +1 -0
  65. package/dist/cli/templates/dashboard-page.js +456 -0
  66. package/dist/cli/templates/dashboard-page.js.map +1 -0
  67. package/dist/cli/templates/index.d.ts +2 -0
  68. package/dist/cli/templates/index.d.ts.map +1 -1
  69. package/dist/cli/templates/index.js +2 -0
  70. package/dist/cli/templates/index.js.map +1 -1
  71. package/dist/config.d.ts +22 -22
  72. package/dist/dashboard-config.d.ts +10 -10
  73. package/dist/index.d.ts +7 -7
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +5 -5
  76. package/dist/index.js.map +1 -1
  77. package/package.json +2 -2
@@ -0,0 +1,31 @@
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
+ /** Default count() — delegates to read(), overridden by adapters for efficiency */
20
+ count(model: string, options?: Omit<import('../types.js').ReadOptions, 'limit' | 'offset' | 'sort'>): Promise<number>;
21
+ getSchema(model: string): Promise<ModelSchema | undefined>;
22
+ listModels(): Promise<string[]>;
23
+ protected requireModel(model: string): void;
24
+ protected generateId(): string;
25
+ /**
26
+ * Validate required fields and apply defaults on a record.
27
+ * Returns the validated record with defaults applied.
28
+ */
29
+ protected validateAndApplyDefaults(model: string, record: DataRecord, skipIdValidation?: boolean): DataRecord;
30
+ }
31
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEpF,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,aAAa,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI,CAAC;IACpH,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;IAEzD,mFAAmF;IAC7E,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,OAAO,aAAa,EAAE,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAMrH,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,69 @@
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
+ /** Default count() — delegates to read(), overridden by adapters for efficiency */
17
+ async count(model, options) {
18
+ const result = await this.read(model, { filter: options?.filter, id: options?.id });
19
+ if (Array.isArray(result))
20
+ return result.length;
21
+ return result ? 1 : 0;
22
+ }
23
+ async getSchema(model) {
24
+ return this.schemas.get(model);
25
+ }
26
+ async listModels() {
27
+ return Array.from(this.schemas.keys());
28
+ }
29
+ // ── Shared Helpers ──
30
+ requireModel(model) {
31
+ if (!this.schemas.has(model)) {
32
+ throw new Error(`Unknown model: ${model}. Available: ${Array.from(this.schemas.keys()).join(', ')}`);
33
+ }
34
+ }
35
+ generateId() {
36
+ const timestamp = Date.now().toString(36);
37
+ const random = Math.random().toString(36).substring(2, 10);
38
+ return `rec_${timestamp}_${random}`;
39
+ }
40
+ /**
41
+ * Validate required fields and apply defaults on a record.
42
+ * Returns the validated record with defaults applied.
43
+ */
44
+ validateAndApplyDefaults(model, record, skipIdValidation = false) {
45
+ const schema = this.schemas.get(model);
46
+ // Apply default values for missing fields
47
+ for (const field of schema.fields) {
48
+ if (record[field.name] === undefined && field.default !== undefined) {
49
+ record[field.name] = field.default;
50
+ }
51
+ }
52
+ // Validate required fields
53
+ for (const field of schema.fields) {
54
+ if (skipIdValidation && field.name === 'id')
55
+ continue;
56
+ if (field.required && record[field.name] === undefined) {
57
+ throw new Error(`Missing required field: ${field.name}`);
58
+ }
59
+ }
60
+ // Validate enum constraints
61
+ for (const field of schema.fields) {
62
+ if (field.enum && record[field.name] !== undefined && !field.enum.includes(record[field.name])) {
63
+ throw new Error(`Invalid value for field '${field.name}': ${record[field.name]}. Allowed values: ${field.enum.join(', ')}`);
64
+ }
65
+ }
66
+ return record;
67
+ }
68
+ }
69
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/adapters/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=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/adapters/factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D,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 './filesystem.js';
8
+ import { SQLiteAdapter } from './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=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/adapters/factory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * FileSystem DataAdapter
3
+ *
4
+ * Stores data as JSON files, organized by model.
5
+ * Default adapter for development and small deployments.
6
+ * Supports date-pattern sub-directories (e.g. 'YYYY-MM') for time-partitioned data.
7
+ */
8
+ import type { DataRecord, ReadOptions, LoomConfig } from '../types.js';
9
+ import { BaseAdapter } from './base.js';
10
+ export interface FileSystemAdapterOptions {
11
+ dataDir: string;
12
+ config: LoomConfig;
13
+ }
14
+ export declare class FileSystemAdapter extends BaseAdapter {
15
+ readonly name = "filesystem";
16
+ private dataDir;
17
+ constructor(options: FileSystemAdapterOptions);
18
+ initialize(): Promise<void>;
19
+ healthCheck(): Promise<boolean>;
20
+ read(model: string, options?: ReadOptions): Promise<DataRecord | DataRecord[] | null>;
21
+ write(model: string, data: DataRecord): Promise<DataRecord>;
22
+ update(model: string, id: string, data: DataRecord): Promise<DataRecord>;
23
+ delete(model: string, id: string): Promise<void>;
24
+ count(model: string, options?: Omit<ReadOptions, 'limit' | 'offset' | 'sort'>): Promise<number>;
25
+ private getModelDir;
26
+ /** Get datePattern for a model, if configured */
27
+ private getDatePattern;
28
+ /**
29
+ * Get record file path.
30
+ * When datePattern is set, records are stored in date-partitioned sub-directories.
31
+ * The date is derived from the first date field in the record data.
32
+ */
33
+ private getRecordPath;
34
+ /**
35
+ * Find a record's actual file path by searching date-partitioned sub-directories.
36
+ * Returns null if not found.
37
+ */
38
+ private findRecordPath;
39
+ /**
40
+ * Collect all .json file paths from a directory.
41
+ * When recursive is true, also scans immediate sub-directories (for date-partitioned data).
42
+ */
43
+ private collectJsonFiles;
44
+ private matchesFilter;
45
+ }
46
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/adapters/filesystem.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAsBxC,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;IAmErF,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;IAsBxE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAchD,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAyCrG,OAAO,CAAC,WAAW;IAOnB,iDAAiD;IACjD,OAAO,CAAC,cAAc;IAKtB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAsBrB;;;OAGG;YACW,cAAc;IAiC5B;;;OAGG;YACW,gBAAgB;IA6B9B,OAAO,CAAC,aAAa;CAoBtB"}
@@ -0,0 +1,321 @@
1
+ /**
2
+ * FileSystem DataAdapter
3
+ *
4
+ * Stores data as JSON files, organized by model.
5
+ * Default adapter for development and small deployments.
6
+ * Supports date-pattern sub-directories (e.g. 'YYYY-MM') for time-partitioned data.
7
+ */
8
+ import { promises as fs } from 'fs';
9
+ import path from 'path';
10
+ import { BaseAdapter } from './base.js';
11
+ /**
12
+ * Resolve a datePattern (e.g. 'YYYY-MM') against a date string (e.g. '2026-04-20').
13
+ * Returns a sub-directory path segment like '2026-04'.
14
+ */
15
+ function resolveDatePattern(datePattern, dateValue) {
16
+ // Simple replacement: YYYY → year, MM → month, DD → day
17
+ const d = new Date(dateValue);
18
+ if (isNaN(d.getTime()))
19
+ return dateValue; // not a valid date, use as-is
20
+ let result = datePattern;
21
+ result = result.replace('YYYY', String(d.getFullYear()));
22
+ result = result.replace('MM', String(d.getMonth() + 1).padStart(2, '0'));
23
+ result = result.replace('DD', String(d.getDate()).padStart(2, '0'));
24
+ return result;
25
+ }
26
+ /** Detect the first date field in a model schema */
27
+ function findDateField(schema) {
28
+ return schema.fields.find(f => f.type === 'date')?.name;
29
+ }
30
+ export class FileSystemAdapter extends BaseAdapter {
31
+ name = 'filesystem';
32
+ dataDir;
33
+ constructor(options) {
34
+ super(options.config);
35
+ this.dataDir = options.dataDir;
36
+ }
37
+ async initialize() {
38
+ await fs.mkdir(this.dataDir, { recursive: true });
39
+ // Create model directories
40
+ for (const model of this.config.data.models) {
41
+ const modelDir = this.getModelDir(model.name);
42
+ await fs.mkdir(modelDir, { recursive: true });
43
+ }
44
+ }
45
+ async healthCheck() {
46
+ try {
47
+ await fs.access(this.dataDir);
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ async read(model, options) {
55
+ this.requireModel(model);
56
+ // Read by ID
57
+ if (options?.id) {
58
+ // For date-partitioned models, find the record across partitions
59
+ const filePath = this.getDatePattern(model)
60
+ ? (await this.findRecordPath(model, options.id))
61
+ : this.getRecordPath(model, options.id);
62
+ if (!filePath)
63
+ return null;
64
+ try {
65
+ const content = await fs.readFile(filePath, 'utf-8');
66
+ return JSON.parse(content);
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ // Read all records for model (including date-partitioned sub-directories)
73
+ const modelDir = this.getModelDir(model);
74
+ const records = [];
75
+ const datePattern = this.getDatePattern(model);
76
+ // Collect JSON files from model dir and sub-dirs
77
+ const jsonFiles = await this.collectJsonFiles(modelDir, !!datePattern);
78
+ for (const filePath of jsonFiles) {
79
+ const content = await fs.readFile(filePath, 'utf-8');
80
+ const parsed = JSON.parse(content);
81
+ // Handle both single records and arrays (e.g. init.json seed data)
82
+ const items = Array.isArray(parsed) ? parsed : [parsed];
83
+ for (const record of items) {
84
+ // Apply filter if provided
85
+ if (options?.filter && !this.matchesFilter(record, options.filter)) {
86
+ continue;
87
+ }
88
+ records.push(record);
89
+ }
90
+ }
91
+ // Apply sort if provided
92
+ if (options?.sort) {
93
+ const { field, order } = options.sort;
94
+ records.sort((a, b) => {
95
+ const va = a[field];
96
+ const vb = b[field];
97
+ if (va == null && vb == null)
98
+ return 0;
99
+ if (va == null)
100
+ return 1;
101
+ if (vb == null)
102
+ return -1;
103
+ let cmp;
104
+ if (typeof va === 'number' && typeof vb === 'number') {
105
+ cmp = va - vb;
106
+ }
107
+ else {
108
+ cmp = String(va).localeCompare(String(vb));
109
+ }
110
+ return order === 'desc' ? -cmp : cmp;
111
+ });
112
+ }
113
+ // Apply offset and limit
114
+ const start = options?.offset || 0;
115
+ const end = options?.limit ? start + options.limit : undefined;
116
+ return records.slice(start, end);
117
+ }
118
+ async write(model, data) {
119
+ this.requireModel(model);
120
+ const id = data.id || this.generateId();
121
+ const record = { id, ...data };
122
+ this.validateAndApplyDefaults(model, record);
123
+ const filePath = this.getRecordPath(model, id, record);
124
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
125
+ await fs.writeFile(filePath, JSON.stringify(record, null, 2), 'utf-8');
126
+ return record;
127
+ }
128
+ async update(model, id, data) {
129
+ this.requireModel(model);
130
+ const filePath = this.getDatePattern(model)
131
+ ? (await this.findRecordPath(model, id))
132
+ : this.getRecordPath(model, id);
133
+ if (!filePath)
134
+ throw new Error(`Record not found: ${model}/${id}`);
135
+ let existing;
136
+ try {
137
+ const content = await fs.readFile(filePath, 'utf-8');
138
+ existing = JSON.parse(content);
139
+ }
140
+ catch {
141
+ throw new Error(`Record not found: ${model}/${id}`);
142
+ }
143
+ const updated = { ...existing, ...data, id }; // Preserve ID
144
+ await fs.writeFile(filePath, JSON.stringify(updated, null, 2), 'utf-8');
145
+ return updated;
146
+ }
147
+ async delete(model, id) {
148
+ this.requireModel(model);
149
+ const filePath = this.getDatePattern(model)
150
+ ? (await this.findRecordPath(model, id))
151
+ : this.getRecordPath(model, id);
152
+ if (!filePath)
153
+ throw new Error(`Record not found: ${model}/${id}`);
154
+ try {
155
+ await fs.unlink(filePath);
156
+ }
157
+ catch {
158
+ throw new Error(`Record not found: ${model}/${id}`);
159
+ }
160
+ }
161
+ async count(model, options) {
162
+ this.requireModel(model);
163
+ // Count by ID
164
+ if (options?.id) {
165
+ if (this.getDatePattern(model)) {
166
+ const filePath = await this.findRecordPath(model, options.id);
167
+ return filePath ? 1 : 0;
168
+ }
169
+ const filePath = this.getRecordPath(model, options.id);
170
+ try {
171
+ await fs.access(filePath);
172
+ return 1;
173
+ }
174
+ catch {
175
+ return 0;
176
+ }
177
+ }
178
+ // Count all matching records
179
+ const modelDir = this.getModelDir(model);
180
+ const datePattern = this.getDatePattern(model);
181
+ const jsonFiles = await this.collectJsonFiles(modelDir, !!datePattern);
182
+ let count = 0;
183
+ for (const filePath of jsonFiles) {
184
+ const content = await fs.readFile(filePath, 'utf-8');
185
+ const parsed = JSON.parse(content);
186
+ const items = Array.isArray(parsed) ? parsed : [parsed];
187
+ for (const record of items) {
188
+ if (options?.filter && !this.matchesFilter(record, options.filter)) {
189
+ continue;
190
+ }
191
+ count++;
192
+ }
193
+ }
194
+ return count;
195
+ }
196
+ // ── Private Helpers ──
197
+ getModelDir(model) {
198
+ const schema = this.schemas.get(model);
199
+ const adapterConfig = schema.adapters?.filesystem;
200
+ const subDir = adapterConfig?.dir || model;
201
+ return path.join(this.dataDir, subDir);
202
+ }
203
+ /** Get datePattern for a model, if configured */
204
+ getDatePattern(model) {
205
+ const schema = this.schemas.get(model);
206
+ return schema.adapters?.filesystem?.datePattern;
207
+ }
208
+ /**
209
+ * Get record file path.
210
+ * When datePattern is set, records are stored in date-partitioned sub-directories.
211
+ * The date is derived from the first date field in the record data.
212
+ */
213
+ getRecordPath(model, id, data) {
214
+ const baseDir = this.getModelDir(model);
215
+ const datePattern = this.getDatePattern(model);
216
+ if (datePattern && data) {
217
+ const dateField = findDateField(this.schemas.get(model));
218
+ const dateValue = dateField ? data[dateField] : undefined;
219
+ if (dateValue) {
220
+ const dateDir = resolveDatePattern(datePattern, dateValue);
221
+ return path.join(baseDir, dateDir, `${id}.json`);
222
+ }
223
+ }
224
+ // No datePattern or no date value — search for the record in existing sub-directories
225
+ if (datePattern && !data) {
226
+ // We don't know which partition the record is in; caller should use findRecordPath
227
+ return path.join(baseDir, `${id}.json`); // fallback, may not exist
228
+ }
229
+ return path.join(baseDir, `${id}.json`);
230
+ }
231
+ /**
232
+ * Find a record's actual file path by searching date-partitioned sub-directories.
233
+ * Returns null if not found.
234
+ */
235
+ async findRecordPath(model, id) {
236
+ const baseDir = this.getModelDir(model);
237
+ const datePattern = this.getDatePattern(model);
238
+ // No datePattern — record is directly in model dir
239
+ if (!datePattern) {
240
+ const directPath = path.join(baseDir, `${id}.json`);
241
+ try {
242
+ await fs.access(directPath);
243
+ return directPath;
244
+ }
245
+ catch {
246
+ return null;
247
+ }
248
+ }
249
+ // Search sub-directories for the record
250
+ try {
251
+ const entries = await fs.readdir(baseDir, { withFileTypes: true });
252
+ for (const entry of entries) {
253
+ if (!entry.isDirectory())
254
+ continue;
255
+ const candidate = path.join(baseDir, entry.name, `${id}.json`);
256
+ try {
257
+ await fs.access(candidate);
258
+ return candidate;
259
+ }
260
+ catch {
261
+ continue;
262
+ }
263
+ }
264
+ }
265
+ catch { /* model dir doesn't exist yet */ }
266
+ return null;
267
+ }
268
+ /**
269
+ * Collect all .json file paths from a directory.
270
+ * When recursive is true, also scans immediate sub-directories (for date-partitioned data).
271
+ */
272
+ async collectJsonFiles(dir, recursive) {
273
+ const files = [];
274
+ let entries;
275
+ try {
276
+ entries = await fs.readdir(dir, { withFileTypes: true });
277
+ }
278
+ catch {
279
+ return files; // directory doesn't exist yet
280
+ }
281
+ for (const entry of entries) {
282
+ const fullPath = path.join(dir, entry.name);
283
+ if (entry.isFile() && entry.name.endsWith('.json')) {
284
+ files.push(fullPath);
285
+ }
286
+ else if (recursive && entry.isDirectory()) {
287
+ // Scan one level deep for date-partitioned sub-directories
288
+ try {
289
+ const subEntries = await fs.readdir(fullPath, { withFileTypes: true });
290
+ for (const subEntry of subEntries) {
291
+ if (subEntry.isFile() && subEntry.name.endsWith('.json')) {
292
+ files.push(path.join(fullPath, subEntry.name));
293
+ }
294
+ }
295
+ }
296
+ catch { /* skip unreadable sub-dirs */ }
297
+ }
298
+ }
299
+ return files;
300
+ }
301
+ matchesFilter(record, filter) {
302
+ return Object.entries(filter).every(([key, value]) => {
303
+ const recordVal = record[key];
304
+ // Range filter: { __range: [start, end] }
305
+ if (value && typeof value === 'object' && !Array.isArray(value) && '__range' in value) {
306
+ const range = value.__range;
307
+ if (!range?.[0] || !range?.[1])
308
+ return true;
309
+ if (recordVal == null)
310
+ return false;
311
+ return recordVal >= range[0] && recordVal <= range[1];
312
+ }
313
+ // Array filter: match any value in the array
314
+ if (Array.isArray(value)) {
315
+ return value.includes(recordVal);
316
+ }
317
+ return recordVal === value;
318
+ });
319
+ }
320
+ }
321
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../src/adapters/filesystem.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Adapters - Barrel Export
3
+ */
4
+ export { BaseAdapter } from './base.js';
5
+ export { createAdapter } from './factory.js';
6
+ export { FileSystemAdapter } from './filesystem.js';
7
+ export type { FileSystemAdapterOptions } from './filesystem.js';
8
+ export { SQLiteAdapter } from './sqlite.js';
9
+ export type { SQLiteAdapterOptions } from './sqlite.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,YAAY,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Adapters - Barrel Export
3
+ */
4
+ export { BaseAdapter } from './base.js';
5
+ export { createAdapter } from './factory.js';
6
+ export { FileSystemAdapter } from './filesystem.js';
7
+ export { SQLiteAdapter } from './sqlite.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * SQLite DataAdapter
3
+ *
4
+ * Stores data in a SQLite database using better-sqlite3.
5
+ * Suitable for medium-scale and embedded deployments.
6
+ */
7
+ import type { DataRecord, ReadOptions, LoomConfig } from '../types.js';
8
+ import { BaseAdapter } from './base.js';
9
+ export interface SQLiteAdapterOptions {
10
+ /** Path to the SQLite database file */
11
+ dbPath: string;
12
+ config: LoomConfig;
13
+ }
14
+ export declare class SQLiteAdapter extends BaseAdapter {
15
+ readonly name = "sqlite";
16
+ private dbPath;
17
+ private db;
18
+ constructor(options: SQLiteAdapterOptions);
19
+ initialize(): Promise<void>;
20
+ healthCheck(): Promise<boolean>;
21
+ read(model: string, options?: ReadOptions): Promise<DataRecord | DataRecord[] | null>;
22
+ count(model: string, options?: Omit<ReadOptions, 'limit' | 'offset' | 'sort'>): Promise<number>;
23
+ write(model: string, data: DataRecord): Promise<DataRecord>;
24
+ update(model: string, id: string, data: DataRecord): Promise<DataRecord>;
25
+ delete(model: string, id: string): Promise<void>;
26
+ /**
27
+ * Close the database connection
28
+ */
29
+ close(): void;
30
+ /** Build WHERE clause from filter object, returns SQL clause fragment and params */
31
+ private buildWhereClause;
32
+ private createTable;
33
+ private mapFieldType;
34
+ private serializeValue;
35
+ private deserializeRow;
36
+ }
37
+ //# sourceMappingURL=sqlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../../src/adapters/sqlite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,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;IAwCrF,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAuB/F,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,oFAAoF;IACpF,OAAO,CAAC,gBAAgB;IA0BxB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,cAAc;CAyBvB"}