@hedystia/db 2.0.0 → 2.0.2

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 (146) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +13 -0
  2. package/dist/_virtual/_rolldown/runtime.mjs +17 -0
  3. package/dist/cache/manager.cjs +137 -0
  4. package/dist/cache/manager.cjs.map +1 -0
  5. package/dist/cache/manager.d.cts +72 -0
  6. package/dist/cache/manager.d.mts +72 -0
  7. package/dist/cache/manager.mjs +140 -0
  8. package/dist/cache/manager.mjs.map +1 -0
  9. package/dist/cache/memory-store.cjs +122 -0
  10. package/dist/cache/memory-store.cjs.map +1 -0
  11. package/dist/cache/memory-store.mjs +122 -0
  12. package/dist/cache/memory-store.mjs.map +1 -0
  13. package/dist/cli/commands/migration.cjs +22 -0
  14. package/dist/cli/commands/migration.cjs.map +1 -0
  15. package/dist/cli/commands/migration.mjs +32 -0
  16. package/dist/cli/commands/migration.mjs.map +1 -0
  17. package/dist/cli/commands/schema.cjs +21 -0
  18. package/dist/cli/commands/schema.cjs.map +1 -0
  19. package/dist/cli/commands/schema.mjs +30 -0
  20. package/dist/cli/commands/schema.mjs.map +1 -0
  21. package/dist/cli.cjs +50 -0
  22. package/dist/cli.cjs.map +1 -0
  23. package/dist/cli.d.cts +1 -0
  24. package/dist/cli.d.mts +1 -0
  25. package/dist/cli.mjs +57 -0
  26. package/dist/cli.mjs.map +1 -0
  27. package/dist/constants.cjs +16 -0
  28. package/dist/constants.cjs.map +1 -0
  29. package/dist/constants.mjs +16 -0
  30. package/dist/constants.mjs.map +1 -0
  31. package/dist/core/database.cjs +158 -0
  32. package/dist/core/database.cjs.map +1 -0
  33. package/dist/core/database.d.cts +74 -0
  34. package/dist/core/database.d.mts +74 -0
  35. package/dist/core/database.mjs +159 -0
  36. package/dist/core/database.mjs.map +1 -0
  37. package/dist/core/repository.cjs +416 -0
  38. package/dist/core/repository.cjs.map +1 -0
  39. package/dist/core/repository.d.cts +110 -0
  40. package/dist/core/repository.d.mts +110 -0
  41. package/dist/core/repository.mjs +416 -0
  42. package/dist/core/repository.mjs.map +1 -0
  43. package/dist/drivers/driver.cjs +11 -0
  44. package/dist/drivers/driver.cjs.map +1 -0
  45. package/dist/drivers/driver.mjs +11 -0
  46. package/dist/drivers/driver.mjs.map +1 -0
  47. package/dist/drivers/file.cjs +336 -0
  48. package/dist/drivers/file.cjs.map +1 -0
  49. package/dist/drivers/file.mjs +337 -0
  50. package/dist/drivers/file.mjs.map +1 -0
  51. package/dist/drivers/index.cjs +28 -0
  52. package/dist/drivers/index.cjs.map +1 -0
  53. package/dist/drivers/index.d.cts +14 -0
  54. package/dist/drivers/index.d.mts +14 -0
  55. package/dist/drivers/index.mjs +28 -0
  56. package/dist/drivers/index.mjs.map +1 -0
  57. package/dist/drivers/mysql.cjs +272 -0
  58. package/dist/drivers/mysql.cjs.map +1 -0
  59. package/dist/drivers/mysql.mjs +272 -0
  60. package/dist/drivers/mysql.mjs.map +1 -0
  61. package/dist/drivers/sql-compiler.cjs +284 -0
  62. package/dist/drivers/sql-compiler.cjs.map +1 -0
  63. package/dist/drivers/sql-compiler.d.cts +66 -0
  64. package/dist/drivers/sql-compiler.d.mts +66 -0
  65. package/dist/drivers/sql-compiler.mjs +276 -0
  66. package/dist/drivers/sql-compiler.mjs.map +1 -0
  67. package/dist/drivers/sqlite.cjs +262 -0
  68. package/dist/drivers/sqlite.cjs.map +1 -0
  69. package/dist/drivers/sqlite.mjs +262 -0
  70. package/dist/drivers/sqlite.mjs.map +1 -0
  71. package/dist/errors.cjs +74 -0
  72. package/dist/errors.cjs.map +1 -0
  73. package/dist/errors.d.cts +46 -0
  74. package/dist/errors.d.mts +46 -0
  75. package/dist/errors.mjs +68 -0
  76. package/dist/errors.mjs.map +1 -0
  77. package/dist/index.cjs +69 -0
  78. package/dist/index.cjs.map +1 -0
  79. package/dist/index.d.cts +15 -0
  80. package/dist/index.d.mts +15 -0
  81. package/dist/index.mjs +21 -0
  82. package/dist/index.mjs.map +1 -0
  83. package/dist/migrations/definition.cjs +20 -0
  84. package/dist/migrations/definition.cjs.map +1 -0
  85. package/dist/migrations/definition.d.cts +18 -0
  86. package/dist/migrations/definition.d.mts +18 -0
  87. package/dist/migrations/definition.mjs +23 -0
  88. package/dist/migrations/definition.mjs.map +1 -0
  89. package/dist/migrations/index.mjs +12 -0
  90. package/dist/migrations/index.mjs.map +1 -0
  91. package/dist/migrations/templates.cjs +39 -0
  92. package/dist/migrations/templates.cjs.map +1 -0
  93. package/dist/migrations/templates.d.cts +16 -0
  94. package/dist/migrations/templates.d.mts +16 -0
  95. package/dist/migrations/templates.mjs +41 -0
  96. package/dist/migrations/templates.mjs.map +1 -0
  97. package/dist/schema/column.cjs +161 -0
  98. package/dist/schema/column.cjs.map +1 -0
  99. package/dist/schema/column.d.cts +120 -0
  100. package/dist/schema/column.d.mts +120 -0
  101. package/dist/schema/column.mjs +161 -0
  102. package/dist/schema/column.mjs.map +1 -0
  103. package/dist/schema/columns/index.cjs +202 -0
  104. package/dist/schema/columns/index.cjs.map +1 -0
  105. package/dist/schema/columns/index.d.cts +141 -0
  106. package/dist/schema/columns/index.d.mts +141 -0
  107. package/dist/schema/columns/index.mjs +182 -0
  108. package/dist/schema/columns/index.mjs.map +1 -0
  109. package/dist/schema/registry.cjs +125 -0
  110. package/dist/schema/registry.cjs.map +1 -0
  111. package/dist/schema/registry.d.cts +66 -0
  112. package/dist/schema/registry.d.mts +66 -0
  113. package/dist/schema/registry.mjs +125 -0
  114. package/dist/schema/registry.mjs.map +1 -0
  115. package/dist/schema/table.cjs +39 -0
  116. package/dist/schema/table.cjs.map +1 -0
  117. package/dist/schema/table.d.cts +17 -0
  118. package/dist/schema/table.d.mts +17 -0
  119. package/dist/schema/table.mjs +39 -0
  120. package/dist/schema/table.mjs.map +1 -0
  121. package/dist/sync/synchronizer.cjs +43 -0
  122. package/dist/sync/synchronizer.cjs.map +1 -0
  123. package/dist/sync/synchronizer.d.cts +22 -0
  124. package/dist/sync/synchronizer.d.mts +22 -0
  125. package/dist/sync/synchronizer.mjs +43 -0
  126. package/dist/sync/synchronizer.mjs.map +1 -0
  127. package/dist/types.d.cts +229 -0
  128. package/dist/types.d.mts +229 -0
  129. package/dist/utils/fs.cjs +24 -0
  130. package/dist/utils/fs.cjs.map +1 -0
  131. package/dist/utils/fs.mjs +26 -0
  132. package/dist/utils/fs.mjs.map +1 -0
  133. package/dist/utils/index.mjs +14 -0
  134. package/dist/utils/index.mjs.map +1 -0
  135. package/dist/utils/naming.cjs +13 -0
  136. package/dist/utils/naming.cjs.map +1 -0
  137. package/dist/utils/naming.mjs +16 -0
  138. package/dist/utils/naming.mjs.map +1 -0
  139. package/dist/utils/stable-stringify.cjs +19 -0
  140. package/dist/utils/stable-stringify.cjs.map +1 -0
  141. package/dist/utils/stable-stringify.mjs +22 -0
  142. package/dist/utils/stable-stringify.mjs.map +1 -0
  143. package/package.json +64 -27
  144. package/readme.md +87 -105
  145. package/index.d.ts +0 -65
  146. package/index.js +0 -1
@@ -0,0 +1,336 @@
1
+ const require_errors = require("../errors.cjs");
2
+ const require_driver = require("./driver.cjs");
3
+ let fs = require("fs");
4
+ let path = require("path");
5
+ //#region src/drivers/file.ts
6
+ /**
7
+ * File-based database driver using JSON files for storage
8
+ */
9
+ var FileDriver = class extends require_driver.BaseDriver {
10
+ config;
11
+ data = /* @__PURE__ */ new Map();
12
+ constructor(config) {
13
+ super();
14
+ this.config = config;
15
+ }
16
+ /**
17
+ * Connect to the file database (ensures directory exists and loads data)
18
+ */
19
+ async connect() {
20
+ if (this.connected) return;
21
+ if (!(0, fs.existsSync)(this.config.directory)) (0, fs.mkdirSync)(this.config.directory, { recursive: true });
22
+ this.loadAll();
23
+ this.connected = true;
24
+ }
25
+ /**
26
+ * Disconnect from the file database (flushes data to disk)
27
+ */
28
+ async disconnect() {
29
+ this.flushAll();
30
+ this.data.clear();
31
+ this.connected = false;
32
+ }
33
+ /**
34
+ * Execute a SQL-like statement (parsed internally for file driver)
35
+ * @param {string} sql - SQL statement
36
+ * @param {unknown[]} [params] - Query parameters
37
+ * @returns {Promise<any>} Execution result
38
+ */
39
+ async execute(sql, params = []) {
40
+ return this.executeParsed(sql, params);
41
+ }
42
+ /**
43
+ * Execute a SQL-like query
44
+ * @param {string} sql - SQL query
45
+ * @param {unknown[]} [params] - Query parameters
46
+ * @returns {Promise<any[]>} Query results
47
+ */
48
+ async query(sql, params = []) {
49
+ const result = this.executeParsed(sql, params);
50
+ return Array.isArray(result) ? result : [];
51
+ }
52
+ /**
53
+ * Check if a table exists
54
+ * @param {string} name - Table name
55
+ * @returns {Promise<boolean>} Whether the table exists
56
+ */
57
+ async tableExists(name) {
58
+ return this.data.has(name);
59
+ }
60
+ /**
61
+ * Get column metadata for a table
62
+ * @param {string} name - Table name
63
+ * @returns {Promise<ColumnMetadata[]>} Column metadata
64
+ */
65
+ async getTableColumns(name) {
66
+ const table = this.data.get(name);
67
+ if (!table) return [];
68
+ return Object.values(table.meta.columns);
69
+ }
70
+ /**
71
+ * Create a table from metadata
72
+ * @param {TableMetadata} meta - Table metadata
73
+ */
74
+ async createTable(meta) {
75
+ if (this.data.has(meta.name)) return;
76
+ this.data.set(meta.name, {
77
+ rows: [],
78
+ autoIncrementId: 0,
79
+ meta: { columns: [...meta.columns] }
80
+ });
81
+ this.flush(meta.name);
82
+ }
83
+ /**
84
+ * Drop a table
85
+ * @param {string} name - Table name
86
+ */
87
+ async dropTable(name) {
88
+ this.data.delete(name);
89
+ const filePath = (0, path.join)(this.config.directory, `${name}.json`);
90
+ try {
91
+ const { unlinkSync } = await import("fs");
92
+ if ((0, fs.existsSync)(filePath)) unlinkSync(filePath);
93
+ } catch {}
94
+ }
95
+ /**
96
+ * Add a column to a table
97
+ * @param {string} table - Table name
98
+ * @param {ColumnMetadata} column - Column metadata
99
+ */
100
+ async addColumn(table, column) {
101
+ const tableData = this.data.get(table);
102
+ if (!tableData) throw new require_errors.DriverError(`Table "${table}" does not exist`);
103
+ tableData.meta.columns.push(column);
104
+ for (const row of tableData.rows) row[column.name] = column.defaultValue ?? null;
105
+ this.flush(table);
106
+ }
107
+ /**
108
+ * Drop a column from a table
109
+ * @param {string} table - Table name
110
+ * @param {string} name - Column name
111
+ */
112
+ async dropColumn(table, name) {
113
+ const tableData = this.data.get(table);
114
+ if (!tableData) throw new require_errors.DriverError(`Table "${table}" does not exist`);
115
+ tableData.meta.columns = tableData.meta.columns.filter((c) => c.name !== name);
116
+ for (const row of tableData.rows) delete row[name];
117
+ this.flush(table);
118
+ }
119
+ /**
120
+ * Rename a column
121
+ * @param {string} table - Table name
122
+ * @param {string} oldName - Current name
123
+ * @param {string} newName - New name
124
+ */
125
+ async renameColumn(table, oldName, newName) {
126
+ const tableData = this.data.get(table);
127
+ if (!tableData) throw new require_errors.DriverError(`Table "${table}" does not exist`);
128
+ const col = tableData.meta.columns.find((c) => c.name === oldName);
129
+ if (col) col.name = newName;
130
+ for (const row of tableData.rows) {
131
+ row[newName] = row[oldName];
132
+ delete row[oldName];
133
+ }
134
+ this.flush(table);
135
+ }
136
+ /**
137
+ * Execute within a transaction (pseudo-transaction for file driver)
138
+ * @param {() => Promise<T>} fn - Function to execute
139
+ * @returns {Promise<T>} Result
140
+ */
141
+ async transaction(fn) {
142
+ const snapshot = /* @__PURE__ */ new Map();
143
+ for (const [name, tableData] of this.data) snapshot.set(name, JSON.stringify(tableData));
144
+ try {
145
+ const result = await fn();
146
+ this.flushAll();
147
+ return result;
148
+ } catch (err) {
149
+ for (const [name, json] of snapshot) this.data.set(name, JSON.parse(json));
150
+ throw err;
151
+ }
152
+ }
153
+ /**
154
+ * Batch fetch all table columns (already in memory for file driver)
155
+ */
156
+ async getAllTableColumns() {
157
+ const result = {};
158
+ for (const [name, tableData] of this.data) result[name] = [...tableData.meta.columns];
159
+ return result;
160
+ }
161
+ /**
162
+ * Direct access for the repository to perform typed operations
163
+ * @param {string} tableName - Table name
164
+ * @returns {FileTableData | undefined} Table data
165
+ */
166
+ getTableData(tableName) {
167
+ return this.data.get(tableName);
168
+ }
169
+ /**
170
+ * Insert a row directly into the file store
171
+ * @param {string} tableName - Table name
172
+ * @param {Record<string, unknown>} row - Row data
173
+ * @returns {number} The insert ID
174
+ */
175
+ insertRow(tableName, row) {
176
+ const tableData = this.data.get(tableName);
177
+ if (!tableData) throw new require_errors.DriverError(`Table "${tableName}" does not exist`);
178
+ let pkCol = null;
179
+ for (const col of tableData.meta.columns) if (col.autoIncrement) {
180
+ pkCol = col.name;
181
+ break;
182
+ }
183
+ if (pkCol && row[pkCol] === void 0) {
184
+ tableData.autoIncrementId++;
185
+ row[pkCol] = tableData.autoIncrementId;
186
+ }
187
+ tableData.rows.push({ ...row });
188
+ this.flush(tableName);
189
+ return pkCol ? row[pkCol] : 0;
190
+ }
191
+ /**
192
+ * Find rows matching a filter function
193
+ * @param {string} tableName - Table name
194
+ * @param {(row: Record<string, unknown>) => boolean} filter - Filter function
195
+ * @returns {Record<string, unknown>[]} Matching rows
196
+ */
197
+ findRows(tableName, filter) {
198
+ const tableData = this.data.get(tableName);
199
+ if (!tableData) return [];
200
+ if (!filter) return tableData.rows.map((r) => ({ ...r }));
201
+ return tableData.rows.filter(filter).map((r) => ({ ...r }));
202
+ }
203
+ /**
204
+ * Update rows matching a filter
205
+ * @param {string} tableName - Table name
206
+ * @param {(row: Record<string, unknown>) => boolean} filter - Filter function
207
+ * @param {Record<string, unknown>} data - Update data
208
+ * @returns {number} Number of affected rows
209
+ */
210
+ updateRows(tableName, filter, data) {
211
+ const tableData = this.data.get(tableName);
212
+ if (!tableData) return 0;
213
+ let count = 0;
214
+ for (const row of tableData.rows) if (filter(row)) {
215
+ Object.assign(row, data);
216
+ count++;
217
+ }
218
+ if (count > 0) this.flush(tableName);
219
+ return count;
220
+ }
221
+ /**
222
+ * Delete rows matching a filter
223
+ * @param {string} tableName - Table name
224
+ * @param {(row: Record<string, unknown>) => boolean} filter - Filter function
225
+ * @returns {number} Number of deleted rows
226
+ */
227
+ deleteRows(tableName, filter) {
228
+ const tableData = this.data.get(tableName);
229
+ if (!tableData) return 0;
230
+ const before = tableData.rows.length;
231
+ tableData.rows = tableData.rows.filter((r) => !filter(r));
232
+ const deleted = before - tableData.rows.length;
233
+ if (deleted > 0) this.flush(tableName);
234
+ return deleted;
235
+ }
236
+ /**
237
+ * Truncate a table
238
+ * @param {string} tableName - Table name
239
+ */
240
+ truncateTable(tableName) {
241
+ const tableData = this.data.get(tableName);
242
+ if (tableData) {
243
+ tableData.rows = [];
244
+ tableData.autoIncrementId = 0;
245
+ this.flush(tableName);
246
+ }
247
+ }
248
+ /**
249
+ * Count rows matching a filter
250
+ * @param {string} tableName - Table name
251
+ * @param {(row: Record<string, unknown>) => boolean} [filter] - Filter function
252
+ * @returns {number} Row count
253
+ */
254
+ countRows(tableName, filter) {
255
+ const tableData = this.data.get(tableName);
256
+ if (!tableData) return 0;
257
+ if (!filter) return tableData.rows.length;
258
+ return tableData.rows.filter(filter).length;
259
+ }
260
+ loadAll() {
261
+ if (!(0, fs.existsSync)(this.config.directory)) return;
262
+ const { readdirSync } = require("fs");
263
+ const files = readdirSync(this.config.directory);
264
+ for (const file of files) if (file.endsWith(".json")) {
265
+ const name = file.replace(".json", "");
266
+ try {
267
+ const content = (0, fs.readFileSync)((0, path.join)(this.config.directory, file), "utf-8");
268
+ this.data.set(name, JSON.parse(content));
269
+ } catch {}
270
+ }
271
+ }
272
+ flush(tableName) {
273
+ const tableData = this.data.get(tableName);
274
+ if (!tableData) return;
275
+ (0, fs.writeFileSync)((0, path.join)(this.config.directory, `${tableName}.json`), JSON.stringify(tableData, null, 2), "utf-8");
276
+ }
277
+ flushAll() {
278
+ for (const [name] of this.data) this.flush(name);
279
+ }
280
+ executeParsed(sql, params) {
281
+ const trimmed = sql.trim().toUpperCase();
282
+ if (trimmed.startsWith("CREATE TABLE")) return {
283
+ insertId: 0,
284
+ affectedRows: 0
285
+ };
286
+ if (trimmed.startsWith("DROP TABLE")) {
287
+ const match = sql.match(/DROP\s+TABLE\s+(?:IF\s+EXISTS\s+)?`?(\w+)`?/i);
288
+ if (match?.[1]) this.data.delete(match[1]);
289
+ return {
290
+ insertId: 0,
291
+ affectedRows: 0
292
+ };
293
+ }
294
+ if (trimmed.startsWith("SELECT")) {
295
+ const tableMatch = sql.match(/FROM\s+`?(\w+)`?/i);
296
+ if (!tableMatch) return [];
297
+ const tableName = tableMatch[1];
298
+ if (!tableName) return [];
299
+ return this.findRows(tableName);
300
+ }
301
+ if (trimmed.startsWith("INSERT")) {
302
+ const tableMatch = sql.match(/INTO\s+`?(\w+)`?/i);
303
+ if (!tableMatch) return {
304
+ insertId: 0,
305
+ affectedRows: 0
306
+ };
307
+ const colMatch = sql.match(/\(([^)]+)\)\s+VALUES/i);
308
+ if (!colMatch) return {
309
+ insertId: 0,
310
+ affectedRows: 0
311
+ };
312
+ const cols = colMatch[1]?.split(",").map((c) => c.trim().replace(/`/g, ""));
313
+ if (!cols) return {
314
+ insertId: 0,
315
+ affectedRows: 0
316
+ };
317
+ const row = {};
318
+ for (let i = 0; i < cols.length; i++) {
319
+ const col = cols[i];
320
+ if (col) row[col] = params[i];
321
+ }
322
+ return {
323
+ insertId: this.insertRow(tableMatch[1], row),
324
+ affectedRows: 1
325
+ };
326
+ }
327
+ return {
328
+ insertId: 0,
329
+ affectedRows: 0
330
+ };
331
+ }
332
+ };
333
+ //#endregion
334
+ exports.FileDriver = FileDriver;
335
+
336
+ //# sourceMappingURL=file.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.cjs","names":["BaseDriver","DriverError"],"sources":["../../src/drivers/file.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { DriverError } from \"../errors\";\nimport type { ColumnMetadata, FileConnectionConfig, TableMetadata } from \"../types\";\nimport { BaseDriver } from \"./driver\";\n\ninterface FileTableData {\n rows: Record<string, unknown>[];\n autoIncrementId: number;\n meta: {\n columns: ColumnMetadata[];\n };\n}\n\n/**\n * File-based database driver using JSON files for storage\n */\nexport class FileDriver extends BaseDriver {\n private config: FileConnectionConfig;\n private data = new Map<string, FileTableData>();\n\n constructor(config: FileConnectionConfig) {\n super();\n this.config = config;\n }\n\n /**\n * Connect to the file database (ensures directory exists and loads data)\n */\n async connect(): Promise<void> {\n if (this.connected) {\n return;\n }\n if (!existsSync(this.config.directory)) {\n mkdirSync(this.config.directory, { recursive: true });\n }\n this.loadAll();\n this.connected = true;\n }\n\n /**\n * Disconnect from the file database (flushes data to disk)\n */\n async disconnect(): Promise<void> {\n this.flushAll();\n this.data.clear();\n this.connected = false;\n }\n\n /**\n * Execute a SQL-like statement (parsed internally for file driver)\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n async execute(sql: string, params: unknown[] = []): Promise<any> {\n return this.executeParsed(sql, params);\n }\n\n /**\n * Execute a SQL-like query\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n async query(sql: string, params: unknown[] = []): Promise<any[]> {\n const result = this.executeParsed(sql, params);\n return Array.isArray(result) ? result : [];\n }\n\n /**\n * Check if a table exists\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n async tableExists(name: string): Promise<boolean> {\n return this.data.has(name);\n }\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata\n */\n async getTableColumns(name: string): Promise<ColumnMetadata[]> {\n const table = this.data.get(name);\n if (!table) {\n return [];\n }\n return Object.values(table.meta.columns);\n }\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n async createTable(meta: TableMetadata): Promise<void> {\n if (this.data.has(meta.name)) {\n return;\n }\n this.data.set(meta.name, {\n rows: [],\n autoIncrementId: 0,\n meta: { columns: [...meta.columns] },\n });\n this.flush(meta.name);\n }\n\n /**\n * Drop a table\n * @param {string} name - Table name\n */\n async dropTable(name: string): Promise<void> {\n this.data.delete(name);\n const filePath = join(this.config.directory, `${name}.json`);\n try {\n const { unlinkSync } = await import(\"fs\");\n if (existsSync(filePath)) {\n unlinkSync(filePath);\n }\n } catch {}\n }\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n async addColumn(table: string, column: ColumnMetadata): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns.push(column);\n for (const row of tableData.rows) {\n row[column.name] = column.defaultValue ?? null;\n }\n this.flush(table);\n }\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n async dropColumn(table: string, name: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n tableData.meta.columns = tableData.meta.columns.filter((c) => c.name !== name);\n for (const row of tableData.rows) {\n delete row[name];\n }\n this.flush(table);\n }\n\n /**\n * Rename a column\n * @param {string} table - Table name\n * @param {string} oldName - Current name\n * @param {string} newName - New name\n */\n async renameColumn(table: string, oldName: string, newName: string): Promise<void> {\n const tableData = this.data.get(table);\n if (!tableData) {\n throw new DriverError(`Table \"${table}\" does not exist`);\n }\n const col = tableData.meta.columns.find((c) => c.name === oldName);\n if (col) {\n col.name = newName;\n }\n for (const row of tableData.rows) {\n row[newName] = row[oldName];\n delete row[oldName];\n }\n this.flush(table);\n }\n\n /**\n * Execute within a transaction (pseudo-transaction for file driver)\n * @param {() => Promise<T>} fn - Function to execute\n * @returns {Promise<T>} Result\n */\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n const snapshot = new Map<string, string>();\n for (const [name, tableData] of this.data) {\n snapshot.set(name, JSON.stringify(tableData));\n }\n try {\n const result = await fn();\n this.flushAll();\n return result;\n } catch (err) {\n for (const [name, json] of snapshot) {\n this.data.set(name, JSON.parse(json));\n }\n throw err;\n }\n }\n\n /**\n * Batch fetch all table columns (already in memory for file driver)\n */\n async getAllTableColumns(): Promise<Record<string, ColumnMetadata[]>> {\n const result: Record<string, ColumnMetadata[]> = {};\n for (const [name, tableData] of this.data) {\n result[name] = [...tableData.meta.columns];\n }\n return result;\n }\n\n /**\n * Direct access for the repository to perform typed operations\n * @param {string} tableName - Table name\n * @returns {FileTableData | undefined} Table data\n */\n getTableData(tableName: string): FileTableData | undefined {\n return this.data.get(tableName);\n }\n\n /**\n * Insert a row directly into the file store\n * @param {string} tableName - Table name\n * @param {Record<string, unknown>} row - Row data\n * @returns {number} The insert ID\n */\n insertRow(tableName: string, row: Record<string, unknown>): number {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n throw new DriverError(`Table \"${tableName}\" does not exist`);\n }\n let pkCol: string | null = null;\n for (const col of tableData.meta.columns) {\n if (col.autoIncrement) {\n pkCol = col.name;\n break;\n }\n }\n if (pkCol && row[pkCol] === undefined) {\n tableData.autoIncrementId++;\n row[pkCol] = tableData.autoIncrementId;\n }\n tableData.rows.push({ ...row });\n this.flush(tableName);\n return pkCol ? (row[pkCol] as number) : 0;\n }\n\n /**\n * Find rows matching a filter function\n * @param {string} tableName - Table name\n * @param {(row: Record<string, unknown>) => boolean} filter - Filter function\n * @returns {Record<string, unknown>[]} Matching rows\n */\n findRows(\n tableName: string,\n filter?: (row: Record<string, unknown>) => boolean,\n ): Record<string, unknown>[] {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return [];\n }\n if (!filter) {\n return tableData.rows.map((r) => ({ ...r }));\n }\n return tableData.rows.filter(filter).map((r) => ({ ...r }));\n }\n\n /**\n * Update rows matching a filter\n * @param {string} tableName - Table name\n * @param {(row: Record<string, unknown>) => boolean} filter - Filter function\n * @param {Record<string, unknown>} data - Update data\n * @returns {number} Number of affected rows\n */\n updateRows(\n tableName: string,\n filter: (row: Record<string, unknown>) => boolean,\n data: Record<string, unknown>,\n ): number {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return 0;\n }\n let count = 0;\n for (const row of tableData.rows) {\n if (filter(row)) {\n Object.assign(row, data);\n count++;\n }\n }\n if (count > 0) {\n this.flush(tableName);\n }\n return count;\n }\n\n /**\n * Delete rows matching a filter\n * @param {string} tableName - Table name\n * @param {(row: Record<string, unknown>) => boolean} filter - Filter function\n * @returns {number} Number of deleted rows\n */\n deleteRows(tableName: string, filter: (row: Record<string, unknown>) => boolean): number {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return 0;\n }\n const before = tableData.rows.length;\n tableData.rows = tableData.rows.filter((r) => !filter(r));\n const deleted = before - tableData.rows.length;\n if (deleted > 0) {\n this.flush(tableName);\n }\n return deleted;\n }\n\n /**\n * Truncate a table\n * @param {string} tableName - Table name\n */\n truncateTable(tableName: string): void {\n const tableData = this.data.get(tableName);\n if (tableData) {\n tableData.rows = [];\n tableData.autoIncrementId = 0;\n this.flush(tableName);\n }\n }\n\n /**\n * Count rows matching a filter\n * @param {string} tableName - Table name\n * @param {(row: Record<string, unknown>) => boolean} [filter] - Filter function\n * @returns {number} Row count\n */\n countRows(tableName: string, filter?: (row: Record<string, unknown>) => boolean): number {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return 0;\n }\n if (!filter) {\n return tableData.rows.length;\n }\n return tableData.rows.filter(filter).length;\n }\n\n private loadAll(): void {\n if (!existsSync(this.config.directory)) {\n return;\n }\n const { readdirSync } = require(\"fs\");\n const files = readdirSync(this.config.directory) as string[];\n for (const file of files) {\n if (file.endsWith(\".json\")) {\n const name = file.replace(\".json\", \"\");\n try {\n const content = readFileSync(join(this.config.directory, file), \"utf-8\");\n this.data.set(name, JSON.parse(content));\n } catch {}\n }\n }\n }\n\n private flush(tableName: string): void {\n const tableData = this.data.get(tableName);\n if (!tableData) {\n return;\n }\n const filePath = join(this.config.directory, `${tableName}.json`);\n writeFileSync(filePath, JSON.stringify(tableData, null, 2), \"utf-8\");\n }\n\n private flushAll(): void {\n for (const [name] of this.data) {\n this.flush(name);\n }\n }\n\n private executeParsed(sql: string, params: unknown[]): any {\n const trimmed = sql.trim().toUpperCase();\n if (trimmed.startsWith(\"CREATE TABLE\")) {\n return { insertId: 0, affectedRows: 0 };\n }\n if (trimmed.startsWith(\"DROP TABLE\")) {\n const match = sql.match(/DROP\\s+TABLE\\s+(?:IF\\s+EXISTS\\s+)?`?(\\w+)`?/i);\n if (match?.[1]) {\n this.data.delete(match[1]);\n }\n return { insertId: 0, affectedRows: 0 };\n }\n if (trimmed.startsWith(\"SELECT\")) {\n const tableMatch = sql.match(/FROM\\s+`?(\\w+)`?/i);\n if (!tableMatch) {\n return [];\n }\n const tableName = tableMatch[1];\n if (!tableName) {\n return [];\n }\n return this.findRows(tableName);\n }\n if (trimmed.startsWith(\"INSERT\")) {\n const tableMatch = sql.match(/INTO\\s+`?(\\w+)`?/i);\n if (!tableMatch) {\n return { insertId: 0, affectedRows: 0 };\n }\n const colMatch = sql.match(/\\(([^)]+)\\)\\s+VALUES/i);\n if (!colMatch) {\n return { insertId: 0, affectedRows: 0 };\n }\n const cols = colMatch[1]?.split(\",\").map((c) => c.trim().replace(/`/g, \"\"));\n if (!cols) {\n return { insertId: 0, affectedRows: 0 };\n }\n const row: Record<string, unknown> = {};\n for (let i = 0; i < cols.length; i++) {\n const col = cols[i];\n if (col) {\n row[col] = params[i];\n }\n }\n const id = this.insertRow(tableMatch[1]!, row);\n return { insertId: id, affectedRows: 1 };\n }\n return { insertId: 0, affectedRows: 0 };\n }\n}\n"],"mappings":"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"}