@hedystia/db 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +362 -0
  38. package/dist/core/repository.cjs.map +1 -0
  39. package/dist/core/repository.d.cts +100 -0
  40. package/dist/core/repository.d.mts +100 -0
  41. package/dist/core/repository.mjs +362 -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 +55 -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 +129 -0
  98. package/dist/schema/column.cjs.map +1 -0
  99. package/dist/schema/column.d.cts +96 -0
  100. package/dist/schema/column.d.mts +96 -0
  101. package/dist/schema/column.mjs +129 -0
  102. package/dist/schema/column.mjs.map +1 -0
  103. package/dist/schema/columns/index.cjs +110 -0
  104. package/dist/schema/columns/index.cjs.map +1 -0
  105. package/dist/schema/columns/index.d.cts +91 -0
  106. package/dist/schema/columns/index.d.mts +91 -0
  107. package/dist/schema/columns/index.mjs +104 -0
  108. package/dist/schema/columns/index.mjs.map +1 -0
  109. package/dist/schema/registry.cjs +101 -0
  110. package/dist/schema/registry.cjs.map +1 -0
  111. package/dist/schema/registry.d.cts +52 -0
  112. package/dist/schema/registry.d.mts +52 -0
  113. package/dist/schema/registry.mjs +101 -0
  114. package/dist/schema/registry.mjs.map +1 -0
  115. package/dist/schema/table.cjs +36 -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 +36 -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 +227 -0
  128. package/dist/types.d.mts +227 -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 +86 -106
  145. package/index.d.ts +0 -65
  146. package/index.js +0 -1
@@ -0,0 +1,362 @@
1
+ import { QueryError } from "../errors.mjs";
2
+ import { FileDriver } from "../drivers/file.mjs";
3
+ import { compileBulkInsert, compileDelete, compileInsert, compileSelect, compileUpdate, compileWhere } from "../drivers/sql-compiler.mjs";
4
+ //#region src/core/repository.ts
5
+ /**
6
+ * Repository implementation that provides CRUD operations for a table
7
+ * @template T - The row type for this table
8
+ */
9
+ var TableRepository = class {
10
+ tableName;
11
+ driver;
12
+ cache;
13
+ registry;
14
+ meta;
15
+ constructor(tableName, driver, cache, registry) {
16
+ this.tableName = tableName;
17
+ this.driver = driver;
18
+ this.cache = cache;
19
+ this.registry = registry;
20
+ const meta = registry.getTable(tableName);
21
+ if (!meta) throw new QueryError(`Table "${tableName}" is not registered`);
22
+ this.meta = meta;
23
+ }
24
+ /**
25
+ * Find all rows matching the query options
26
+ * @param {QueryOptions<T>} [options] - Query options
27
+ * @returns {Promise<T[]>} Array of matching rows
28
+ */
29
+ async find(options) {
30
+ return this.cache.getOrSet(this.tableName, "find", options, async () => {
31
+ let rows;
32
+ if (this.driver instanceof FileDriver) rows = this.findFile(options);
33
+ else rows = await this.findSQL(options);
34
+ if (options?.with) rows = await this.loadRelations(rows, options.with);
35
+ this.cacheEntities(rows);
36
+ return rows;
37
+ });
38
+ }
39
+ /**
40
+ * Find all rows matching the query options (alias for find)
41
+ * @param {QueryOptions<T>} [options] - Query options
42
+ * @returns {Promise<T[]>} Array of matching rows
43
+ */
44
+ async findMany(options) {
45
+ return this.find(options);
46
+ }
47
+ /**
48
+ * Find the first row matching the query options
49
+ * @param {QueryOptions<T>} [options] - Query options
50
+ * @returns {Promise<T | null>} The first matching row or null
51
+ */
52
+ async findFirst(options) {
53
+ return this.cache.getOrSet(this.tableName, "findFirst", options, async () => {
54
+ const opts = {
55
+ ...options,
56
+ take: 1
57
+ };
58
+ let rows;
59
+ if (this.driver instanceof FileDriver) rows = this.findFile(opts);
60
+ else rows = await this.findSQL(opts);
61
+ if (rows.length === 0) return null;
62
+ if (options?.with) rows = await this.loadRelations(rows, options.with);
63
+ const row = rows[0] ?? null;
64
+ if (row) this.cacheEntity(row);
65
+ return row;
66
+ });
67
+ }
68
+ /**
69
+ * Insert one or more rows
70
+ * @param {Partial<T> | Partial<T>[]} data - Data to insert
71
+ * @returns {Promise<T>} The inserted row
72
+ */
73
+ async insert(data) {
74
+ const single = Array.isArray(data) ? data[0] : data;
75
+ if (!single) throw new QueryError("Insert data cannot be empty");
76
+ this.cache.invalidateTable(this.tableName);
77
+ const cleaned = this.cleanData(single);
78
+ if (this.driver instanceof FileDriver) {
79
+ const id = this.driver.insertRow(this.tableName, cleaned);
80
+ const pk = this.registry.getPrimaryKey(this.tableName);
81
+ if (pk) cleaned[pk] = id;
82
+ this.cacheEntity(cleaned);
83
+ return cleaned;
84
+ }
85
+ const params = [];
86
+ const sql = compileInsert(this.tableName, cleaned, params);
87
+ const result = await this.driver.execute(sql, params);
88
+ const pk = this.registry.getPrimaryKey(this.tableName);
89
+ if (pk && result.insertId) cleaned[pk] = result.insertId;
90
+ this.cacheEntity(cleaned);
91
+ return cleaned;
92
+ }
93
+ /**
94
+ * Insert multiple rows
95
+ * @param {Partial<T>[]} data - Array of data to insert
96
+ * @returns {Promise<T[]>} The inserted rows
97
+ */
98
+ async insertMany(data) {
99
+ if (data.length === 0) return [];
100
+ this.cache.invalidateTable(this.tableName);
101
+ if (this.driver instanceof FileDriver) {
102
+ const results = [];
103
+ for (const item of data) results.push(await this.insert(item));
104
+ return results;
105
+ }
106
+ const cleanedData = data.map((item) => this.cleanData(item));
107
+ const params = [];
108
+ const sql = compileBulkInsert(this.tableName, cleanedData, params);
109
+ const result = await this.driver.execute(sql, params);
110
+ const pk = this.registry.getPrimaryKey(this.tableName);
111
+ if (pk && result.insertId) for (let i = 0; i < cleanedData.length; i++) {
112
+ const row = cleanedData[i];
113
+ if (row) row[pk] = result.insertId + i;
114
+ }
115
+ const finalRows = cleanedData;
116
+ this.cacheEntities(finalRows);
117
+ return finalRows;
118
+ }
119
+ /**
120
+ * Update rows matching the where clause
121
+ * @param {UpdateOptions<T>} options - Update options with where and data
122
+ * @returns {Promise<T[]>} The updated rows
123
+ */
124
+ async update(options) {
125
+ if (!options.where || Object.keys(options.where).length === 0) throw new QueryError("Update requires a where clause");
126
+ this.cache.invalidateTable(this.tableName);
127
+ const cleaned = this.cleanData(options.data);
128
+ if (this.driver instanceof FileDriver) {
129
+ const filter = this.buildFileFilter(options.where);
130
+ this.driver.updateRows(this.tableName, filter, cleaned);
131
+ return this.find({ where: options.where });
132
+ }
133
+ const params = [];
134
+ const sql = compileUpdate(this.tableName, cleaned, options.where, params);
135
+ await this.driver.execute(sql, params);
136
+ return this.find({ where: options.where });
137
+ }
138
+ /**
139
+ * Delete rows matching the where clause
140
+ * @param {DeleteOptions<T>} options - Delete options with where clause
141
+ * @returns {Promise<number>} Number of deleted rows
142
+ */
143
+ async delete(options) {
144
+ if (!options.where || Object.keys(options.where).length === 0) throw new QueryError("Delete requires a where clause");
145
+ this.cache.invalidateTable(this.tableName);
146
+ if (this.driver instanceof FileDriver) {
147
+ const filter = this.buildFileFilter(options.where);
148
+ return this.driver.deleteRows(this.tableName, filter);
149
+ }
150
+ const params = [];
151
+ const sql = compileDelete(this.tableName, options.where, params);
152
+ return (await this.driver.execute(sql, params)).affectedRows;
153
+ }
154
+ /**
155
+ * Count rows matching the where clause
156
+ * @param {Pick<QueryOptions<T>, "where">} [options] - Count options
157
+ * @returns {Promise<number>} Row count
158
+ */
159
+ async count(options) {
160
+ return this.cache.getOrSet(this.tableName, "count", options, async () => {
161
+ if (this.driver instanceof FileDriver) {
162
+ const filter = options?.where ? this.buildFileFilter(options.where) : void 0;
163
+ return this.driver.countRows(this.tableName, filter);
164
+ }
165
+ const params = [];
166
+ let sql = `SELECT COUNT(*) as count FROM \`${this.tableName}\``;
167
+ if (options?.where && Object.keys(options.where).length > 0) sql += ` WHERE ${compileWhere(options.where, params)}`;
168
+ return (await this.driver.query(sql, params))[0]?.count ?? 0;
169
+ });
170
+ }
171
+ /**
172
+ * Check if any row exists matching the where clause
173
+ * @param {Pick<QueryOptions<T>, "where">} options - Exists options
174
+ * @returns {Promise<boolean>} Whether a matching row exists
175
+ */
176
+ async exists(options) {
177
+ return await this.count(options) > 0;
178
+ }
179
+ /**
180
+ * Insert or update a row based on the where clause
181
+ * @param {object} options - Upsert options
182
+ * @param {WhereClause<T>} options.where - Condition to check
183
+ * @param {Partial<T>} options.create - Data to insert if not found
184
+ * @param {Partial<T>} options.update - Data to update if found
185
+ * @returns {Promise<T>} The upserted row
186
+ */
187
+ async upsert(options) {
188
+ const existing = await this.findFirst({ where: options.where });
189
+ if (existing) return (await this.update({
190
+ where: options.where,
191
+ data: options.update
192
+ }))[0] ?? existing;
193
+ return this.insert(options.create);
194
+ }
195
+ /**
196
+ * Remove all rows from the table
197
+ */
198
+ async truncate() {
199
+ this.cache.invalidateTable(this.tableName);
200
+ if (this.driver instanceof FileDriver) {
201
+ this.driver.truncateTable(this.tableName);
202
+ return;
203
+ }
204
+ await this.driver.execute(`DELETE FROM \`${this.tableName}\``);
205
+ }
206
+ async findSQL(options) {
207
+ const params = [];
208
+ const sql = compileSelect(this.tableName, {
209
+ select: options?.select,
210
+ where: options?.where,
211
+ orderBy: options?.orderBy,
212
+ take: options?.take,
213
+ skip: options?.skip
214
+ }, params);
215
+ return this.driver.query(sql, params);
216
+ }
217
+ findFile(options) {
218
+ const fd = this.driver;
219
+ const filter = options?.where ? this.buildFileFilter(options.where) : void 0;
220
+ let rows = fd.findRows(this.tableName, filter);
221
+ if (options?.select) {
222
+ const selectSet = new Set(options.select);
223
+ rows = rows.map((row) => {
224
+ const filtered = {};
225
+ for (const key of selectSet) filtered[key] = row[key];
226
+ return filtered;
227
+ });
228
+ }
229
+ if (options?.orderBy) {
230
+ const entries = Object.entries(options.orderBy);
231
+ rows.sort((a, b) => {
232
+ for (const [col, dir] of entries) {
233
+ const av = a[col];
234
+ const bv = b[col];
235
+ if (av < bv) return dir === "asc" ? -1 : 1;
236
+ if (av > bv) return dir === "asc" ? 1 : -1;
237
+ }
238
+ return 0;
239
+ });
240
+ }
241
+ if (options?.skip) rows = rows.slice(options.skip);
242
+ if (options?.take) rows = rows.slice(0, options.take);
243
+ return rows;
244
+ }
245
+ buildFileFilter(where) {
246
+ return (row) => this.matchWhere(row, where);
247
+ }
248
+ matchWhere(row, where) {
249
+ for (const [key, value] of Object.entries(where)) {
250
+ if (key === "OR" && Array.isArray(value)) {
251
+ if (!value.some((sub) => this.matchWhere(row, sub))) return false;
252
+ continue;
253
+ }
254
+ if (key === "AND" && Array.isArray(value)) {
255
+ if (!value.every((sub) => this.matchWhere(row, sub))) return false;
256
+ continue;
257
+ }
258
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
259
+ const cond = value;
260
+ const rowVal = row[key];
261
+ if (cond.eq !== void 0 && rowVal !== cond.eq) return false;
262
+ if (cond.neq !== void 0 && rowVal === cond.neq) return false;
263
+ if (cond.gt !== void 0 && !(rowVal > cond.gt)) return false;
264
+ if (cond.gte !== void 0 && !(rowVal >= cond.gte)) return false;
265
+ if (cond.lt !== void 0 && !(rowVal < cond.lt)) return false;
266
+ if (cond.lte !== void 0 && !(rowVal <= cond.lte)) return false;
267
+ if (cond.like !== void 0 && !String(rowVal).match(new RegExp(cond.like.replace(/%/g, ".*"), "i"))) return false;
268
+ if (cond.notLike !== void 0 && String(rowVal).match(new RegExp(cond.notLike.replace(/%/g, ".*"), "i"))) return false;
269
+ if (cond.in !== void 0 && !cond.in.includes(rowVal)) return false;
270
+ if (cond.notIn?.includes(rowVal)) return false;
271
+ if (cond.isNull === true && rowVal !== null && rowVal !== void 0) return false;
272
+ if (cond.isNull === false && (rowVal === null || rowVal === void 0)) return false;
273
+ if (cond.between !== void 0) {
274
+ if (rowVal < cond.between[0] || rowVal > cond.between[1]) return false;
275
+ }
276
+ } else if (row[key] !== value) return false;
277
+ }
278
+ return true;
279
+ }
280
+ async loadRelations(rows, withOpts) {
281
+ if (rows.length === 0) return rows;
282
+ const relations = this.registry.getRelations(this.tableName);
283
+ for (const [relationName, opts] of Object.entries(withOpts)) {
284
+ if (!opts) continue;
285
+ const relation = relations.find((r) => r.relationName === relationName);
286
+ if (!relation) continue;
287
+ if (relation.from.table === this.tableName) {
288
+ const ids = rows.map((r) => r[relation.from.column]).filter((v) => v != null);
289
+ if (ids.length === 0) continue;
290
+ const uniqueIds = [...new Set(ids)];
291
+ const relatedOpts = typeof opts === "object" ? opts : {};
292
+ const related = await this.findRelated(relation.to.table, relation.to.column, uniqueIds, relatedOpts);
293
+ const relatedMap = /* @__PURE__ */ new Map();
294
+ for (const r of related) {
295
+ const key = r[relation.to.column];
296
+ if (!relatedMap.has(key)) relatedMap.set(key, []);
297
+ relatedMap.get(key).push(r);
298
+ }
299
+ for (const row of rows) {
300
+ const key = row[relation.from.column];
301
+ row[relationName] = relatedMap.get(key) ?? [];
302
+ }
303
+ } else {
304
+ const pk = this.registry.getPrimaryKey(this.tableName);
305
+ if (!pk) continue;
306
+ const ids = rows.map((r) => r[pk]).filter((v) => v != null);
307
+ if (ids.length === 0) continue;
308
+ const uniqueIds = [...new Set(ids)];
309
+ const relatedOpts = typeof opts === "object" ? opts : {};
310
+ const related = await this.findRelated(relation.to.table, relation.to.column, uniqueIds, relatedOpts);
311
+ const relatedMap = /* @__PURE__ */ new Map();
312
+ for (const r of related) {
313
+ const key = r[relation.to.column];
314
+ if (!relatedMap.has(key)) relatedMap.set(key, []);
315
+ relatedMap.get(key).push(r);
316
+ }
317
+ for (const row of rows) {
318
+ const key = row[pk];
319
+ row[relationName] = relatedMap.get(key) ?? [];
320
+ }
321
+ }
322
+ }
323
+ return rows;
324
+ }
325
+ async findRelated(tableName, column, ids, options) {
326
+ if (this.driver instanceof FileDriver) {
327
+ const fd = this.driver;
328
+ const filter = (row) => ids.includes(row[column]);
329
+ return fd.findRows(tableName, filter);
330
+ }
331
+ const params = [];
332
+ const placeholders = ids.map(() => "?").join(", ");
333
+ params.push(...ids);
334
+ let sql = `SELECT * FROM \`${tableName}\` WHERE \`${column}\` IN (${placeholders})`;
335
+ if (options.orderBy) {
336
+ const orderParts = Object.entries(options.orderBy).map(([col, dir]) => `\`${col}\` ${dir.toUpperCase()}`);
337
+ if (orderParts.length > 0) sql += ` ORDER BY ${orderParts.join(", ")}`;
338
+ }
339
+ if (options.take) sql += ` LIMIT ${options.take}`;
340
+ return this.driver.query(sql, params);
341
+ }
342
+ cleanData(data) {
343
+ const cleaned = {};
344
+ const columnNames = new Set(this.meta.columns.map((c) => c.name));
345
+ for (const [key, value] of Object.entries(data)) if (columnNames.has(key)) cleaned[key] = value;
346
+ return cleaned;
347
+ }
348
+ cacheEntities(rows) {
349
+ const pk = this.registry.getPrimaryKey(this.tableName);
350
+ if (!pk) return;
351
+ for (const row of rows) if (row[pk] != null) this.cache.setEntity(this.tableName, row[pk], row);
352
+ }
353
+ cacheEntity(row) {
354
+ const pk = this.registry.getPrimaryKey(this.tableName);
355
+ if (!pk || row[pk] == null) return;
356
+ this.cache.setEntity(this.tableName, row[pk], row);
357
+ }
358
+ };
359
+ //#endregion
360
+ export { TableRepository };
361
+
362
+ //# sourceMappingURL=repository.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.mjs","names":[],"sources":["../../src/core/repository.ts"],"sourcesContent":["import type { CacheManager } from \"../cache\";\nimport { FileDriver } from \"../drivers/file\";\nimport {\n compileBulkInsert,\n compileDelete,\n compileInsert,\n compileSelect,\n compileUpdate,\n compileWhere,\n} from \"../drivers/sql-compiler\";\nimport { QueryError } from \"../errors\";\nimport type { SchemaRegistry } from \"../schema\";\nimport type {\n DatabaseDriver,\n DeleteOptions,\n QueryOptions,\n Repository,\n TableMetadata,\n UpdateOptions,\n WhereClause,\n} from \"../types\";\n\n/**\n * Repository implementation that provides CRUD operations for a table\n * @template T - The row type for this table\n */\nexport class TableRepository<T extends Record<string, any>> implements Repository<T> {\n private tableName: string;\n private driver: DatabaseDriver;\n private cache: CacheManager;\n private registry: SchemaRegistry;\n private meta: TableMetadata;\n\n constructor(\n tableName: string,\n driver: DatabaseDriver,\n cache: CacheManager,\n registry: SchemaRegistry,\n ) {\n this.tableName = tableName;\n this.driver = driver;\n this.cache = cache;\n this.registry = registry;\n const meta = registry.getTable(tableName);\n if (!meta) {\n throw new QueryError(`Table \"${tableName}\" is not registered`);\n }\n this.meta = meta;\n }\n\n /**\n * Find all rows matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async find(options?: QueryOptions<T>): Promise<T[]> {\n return this.cache.getOrSet(this.tableName, \"find\", options, async () => {\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.findFile(options);\n } else {\n rows = await this.findSQL(options);\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n this.cacheEntities(rows);\n return rows;\n });\n }\n\n /**\n * Find all rows matching the query options (alias for find)\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T[]>} Array of matching rows\n */\n async findMany(options?: QueryOptions<T>): Promise<T[]> {\n return this.find(options);\n }\n\n /**\n * Find the first row matching the query options\n * @param {QueryOptions<T>} [options] - Query options\n * @returns {Promise<T | null>} The first matching row or null\n */\n async findFirst(options?: QueryOptions<T>): Promise<T | null> {\n return this.cache.getOrSet(this.tableName, \"findFirst\", options, async () => {\n const opts = { ...options, take: 1 };\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.findFile(opts);\n } else {\n rows = await this.findSQL(opts);\n }\n if (rows.length === 0) {\n return null;\n }\n if (options?.with) {\n rows = await this.loadRelations(rows, options.with);\n }\n const row = rows[0] ?? null;\n if (row) {\n this.cacheEntity(row);\n }\n return row;\n });\n }\n\n /**\n * Insert one or more rows\n * @param {Partial<T> | Partial<T>[]} data - Data to insert\n * @returns {Promise<T>} The inserted row\n */\n async insert(data: Partial<T> | Partial<T>[]): Promise<T> {\n const single = Array.isArray(data) ? data[0] : data;\n if (!single) {\n throw new QueryError(\"Insert data cannot be empty\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.cleanData(single);\n\n if (this.driver instanceof FileDriver) {\n const id = (this.driver as FileDriver).insertRow(this.tableName, cleaned);\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk) {\n cleaned[pk] = id;\n }\n this.cacheEntity(cleaned as T);\n return cleaned as T;\n }\n\n const params: unknown[] = [];\n const sql = compileInsert(this.tableName, cleaned, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n cleaned[pk] = result.insertId;\n }\n\n this.cacheEntity(cleaned as T);\n return cleaned as T;\n }\n\n /**\n * Insert multiple rows\n * @param {Partial<T>[]} data - Array of data to insert\n * @returns {Promise<T[]>} The inserted rows\n */\n async insertMany(data: Partial<T>[]): Promise<T[]> {\n if (data.length === 0) {\n return [];\n }\n\n this.cache.invalidateTable(this.tableName);\n\n if (this.driver instanceof FileDriver) {\n const results: T[] = [];\n for (const item of data) {\n results.push(await this.insert(item));\n }\n return results;\n }\n\n const cleanedData = data.map((item) => this.cleanData(item));\n const params: unknown[] = [];\n const sql = compileBulkInsert(this.tableName, cleanedData, params);\n const result = await this.driver.execute(sql, params);\n\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (pk && result.insertId) {\n for (let i = 0; i < cleanedData.length; i++) {\n const row = cleanedData[i];\n if (row) {\n row[pk] = result.insertId + i;\n }\n }\n }\n\n const finalRows = cleanedData as T[];\n this.cacheEntities(finalRows);\n return finalRows;\n }\n\n /**\n * Update rows matching the where clause\n * @param {UpdateOptions<T>} options - Update options with where and data\n * @returns {Promise<T[]>} The updated rows\n */\n async update(options: UpdateOptions<T>): Promise<T[]> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Update requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n const cleaned = this.cleanData(options.data);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(options.where as WhereClause);\n (this.driver as FileDriver).updateRows(this.tableName, filter, cleaned);\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n const params: unknown[] = [];\n const sql = compileUpdate(this.tableName, cleaned, options.where as WhereClause, params);\n await this.driver.execute(sql, params);\n\n return this.find({ where: options.where } as QueryOptions<T>);\n }\n\n /**\n * Delete rows matching the where clause\n * @param {DeleteOptions<T>} options - Delete options with where clause\n * @returns {Promise<number>} Number of deleted rows\n */\n async delete(options: DeleteOptions<T>): Promise<number> {\n if (!options.where || Object.keys(options.where).length === 0) {\n throw new QueryError(\"Delete requires a where clause\");\n }\n\n this.cache.invalidateTable(this.tableName);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(options.where as WhereClause);\n return (this.driver as FileDriver).deleteRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n const sql = compileDelete(this.tableName, options.where as WhereClause, params);\n const result = await this.driver.execute(sql, params);\n return result.affectedRows;\n }\n\n /**\n * Count rows matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} [options] - Count options\n * @returns {Promise<number>} Row count\n */\n async count(options?: Pick<QueryOptions<T>, \"where\">): Promise<number> {\n return this.cache.getOrSet(this.tableName, \"count\", options, async () => {\n if (this.driver instanceof FileDriver) {\n const filter = options?.where\n ? this.buildFileFilter(options.where as WhereClause)\n : undefined;\n return (this.driver as FileDriver).countRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n let sql = `SELECT COUNT(*) as count FROM \\`${this.tableName}\\``;\n if (options?.where && Object.keys(options.where).length > 0) {\n sql += ` WHERE ${compileWhere(options.where as WhereClause, params)}`;\n }\n const rows = await this.driver.query(sql, params);\n return rows[0]?.count ?? 0;\n });\n }\n\n /**\n * Check if any row exists matching the where clause\n * @param {Pick<QueryOptions<T>, \"where\">} options - Exists options\n * @returns {Promise<boolean>} Whether a matching row exists\n */\n async exists(options: Pick<QueryOptions<T>, \"where\">): Promise<boolean> {\n const c = await this.count(options);\n return c > 0;\n }\n\n /**\n * Insert or update a row based on the where clause\n * @param {object} options - Upsert options\n * @param {WhereClause<T>} options.where - Condition to check\n * @param {Partial<T>} options.create - Data to insert if not found\n * @param {Partial<T>} options.update - Data to update if found\n * @returns {Promise<T>} The upserted row\n */\n async upsert(options: {\n where: WhereClause<T>;\n create: Partial<T>;\n update: Partial<T>;\n }): Promise<T> {\n const existing = await this.findFirst({ where: options.where } as QueryOptions<T>);\n if (existing) {\n const updated = await this.update({ where: options.where, data: options.update });\n return updated[0] ?? existing;\n }\n return this.insert(options.create);\n }\n\n /**\n * Remove all rows from the table\n */\n async truncate(): Promise<void> {\n this.cache.invalidateTable(this.tableName);\n if (this.driver instanceof FileDriver) {\n (this.driver as FileDriver).truncateTable(this.tableName);\n return;\n }\n await this.driver.execute(`DELETE FROM \\`${this.tableName}\\``);\n }\n\n private async findSQL(options?: QueryOptions<T>): Promise<T[]> {\n const params: unknown[] = [];\n const sql = compileSelect(\n this.tableName,\n {\n select: options?.select as string[] | undefined,\n where: options?.where as WhereClause | undefined,\n orderBy: options?.orderBy as Record<string, \"asc\" | \"desc\"> | undefined,\n take: options?.take,\n skip: options?.skip,\n },\n params,\n );\n return this.driver.query(sql, params);\n }\n\n private findFile(options?: QueryOptions<T>): T[] {\n const fd = this.driver as FileDriver;\n const filter = options?.where ? this.buildFileFilter(options.where as WhereClause) : undefined;\n let rows = fd.findRows(this.tableName, filter) as T[];\n\n if (options?.select) {\n const selectSet = new Set(options.select as string[]);\n rows = rows.map((row) => {\n const filtered: Record<string, any> = {};\n for (const key of selectSet) {\n filtered[key as string] = row[key as string];\n }\n return filtered as T;\n });\n }\n\n if (options?.orderBy) {\n const entries = Object.entries(options.orderBy);\n rows.sort((a, b) => {\n for (const [col, dir] of entries) {\n const av = a[col];\n const bv = b[col];\n if (av < bv) {\n return dir === \"asc\" ? -1 : 1;\n }\n if (av > bv) {\n return dir === \"asc\" ? 1 : -1;\n }\n }\n return 0;\n });\n }\n\n if (options?.skip) {\n rows = rows.slice(options.skip);\n }\n if (options?.take) {\n rows = rows.slice(0, options.take);\n }\n\n return rows;\n }\n\n private buildFileFilter(where: WhereClause): (row: Record<string, unknown>) => boolean {\n return (row) => this.matchWhere(row, where);\n }\n\n private matchWhere(row: Record<string, unknown>, where: WhereClause): boolean {\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" && Array.isArray(value)) {\n const any = (value as WhereClause[]).some((sub) => this.matchWhere(row, sub));\n if (!any) {\n return false;\n }\n continue;\n }\n if (key === \"AND\" && Array.isArray(value)) {\n const all = (value as WhereClause[]).every((sub) => this.matchWhere(row, sub));\n if (!all) {\n return false;\n }\n continue;\n }\n\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) {\n const cond = value as any;\n const rowVal = row[key];\n if (cond.eq !== undefined && rowVal !== cond.eq) {\n return false;\n }\n if (cond.neq !== undefined && rowVal === cond.neq) {\n return false;\n }\n if (cond.gt !== undefined && !((rowVal as any) > cond.gt)) {\n return false;\n }\n if (cond.gte !== undefined && !((rowVal as any) >= cond.gte)) {\n return false;\n }\n if (cond.lt !== undefined && !((rowVal as any) < cond.lt)) {\n return false;\n }\n if (cond.lte !== undefined && !((rowVal as any) <= cond.lte)) {\n return false;\n }\n if (\n cond.like !== undefined &&\n !String(rowVal).match(new RegExp(cond.like.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (\n cond.notLike !== undefined &&\n String(rowVal).match(new RegExp(cond.notLike.replace(/%/g, \".*\"), \"i\"))\n ) {\n return false;\n }\n if (cond.in !== undefined && !cond.in.includes(rowVal)) {\n return false;\n }\n if (cond.notIn?.includes(rowVal)) {\n return false;\n }\n if (cond.isNull === true && rowVal !== null && rowVal !== undefined) {\n return false;\n }\n if (cond.isNull === false && (rowVal === null || rowVal === undefined)) {\n return false;\n }\n if (cond.between !== undefined) {\n if ((rowVal as any) < cond.between[0] || (rowVal as any) > cond.between[1]) {\n return false;\n }\n }\n } else {\n if (row[key] !== value) {\n return false;\n }\n }\n }\n return true;\n }\n\n private async loadRelations(\n rows: T[],\n withOpts: Record<string, boolean | QueryOptions>,\n ): Promise<T[]> {\n if (rows.length === 0) {\n return rows;\n }\n const relations = this.registry.getRelations(this.tableName);\n\n for (const [relationName, opts] of Object.entries(withOpts)) {\n if (!opts) {\n continue;\n }\n const relation = relations.find((r) => r.relationName === relationName);\n if (!relation) {\n continue;\n }\n\n const isParent = relation.from.table === this.tableName;\n if (isParent) {\n const ids = rows.map((r) => r[relation.from.column]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[relation.from.column];\n const relRows = relatedMap.get(key);\n (row as any)[relationName] = relRows ?? [];\n }\n } else {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n continue;\n }\n const ids = rows.map((r) => r[pk]).filter((v) => v != null);\n if (ids.length === 0) {\n continue;\n }\n const uniqueIds = [...new Set(ids)];\n const relatedOpts: QueryOptions = typeof opts === \"object\" ? opts : {};\n const related = await this.findRelated(\n relation.to.table,\n relation.to.column,\n uniqueIds,\n relatedOpts,\n );\n const relatedMap = new Map<unknown, unknown[]>();\n for (const r of related) {\n const key = (r as any)[relation.to.column];\n if (!relatedMap.has(key)) {\n relatedMap.set(key, []);\n }\n relatedMap.get(key)!.push(r);\n }\n for (const row of rows) {\n const key = row[pk];\n (row as any)[relationName] = relatedMap.get(key) ?? [];\n }\n }\n }\n\n return rows;\n }\n\n private async findRelated(\n tableName: string,\n column: string,\n ids: unknown[],\n options: QueryOptions,\n ): Promise<any[]> {\n if (this.driver instanceof FileDriver) {\n const fd = this.driver as FileDriver;\n const filter = (row: Record<string, unknown>) => ids.includes(row[column]);\n return fd.findRows(tableName, filter);\n }\n\n const params: unknown[] = [];\n const placeholders = ids.map(() => \"?\").join(\", \");\n params.push(...ids);\n\n let sql = `SELECT * FROM \\`${tableName}\\` WHERE \\`${column}\\` IN (${placeholders})`;\n if (options.orderBy) {\n const orderParts = Object.entries(options.orderBy).map(\n ([col, dir]) => `\\`${col}\\` ${(dir as string).toUpperCase()}`,\n );\n if (orderParts.length > 0) {\n sql += ` ORDER BY ${orderParts.join(\", \")}`;\n }\n }\n if (options.take) {\n sql += ` LIMIT ${options.take}`;\n }\n\n return this.driver.query(sql, params);\n }\n\n private cleanData(data: Partial<T>): Record<string, unknown> {\n const cleaned: Record<string, unknown> = {};\n const columnNames = new Set(this.meta.columns.map((c) => c.name));\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (columnNames.has(key)) {\n cleaned[key] = value;\n }\n }\n return cleaned;\n }\n\n private cacheEntities(rows: T[]): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk) {\n return;\n }\n for (const row of rows) {\n if (row[pk] != null) {\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n }\n }\n\n private cacheEntity(row: T): void {\n const pk = this.registry.getPrimaryKey(this.tableName);\n if (!pk || row[pk] == null) {\n return;\n }\n this.cache.setEntity(this.tableName, row[pk], row);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ //#region src/drivers/driver.ts
2
+ /**
3
+ * Abstract base class for database drivers
4
+ */
5
+ var BaseDriver = class {
6
+ connected = false;
7
+ };
8
+ //#endregion
9
+ exports.BaseDriver = BaseDriver;
10
+
11
+ //# sourceMappingURL=driver.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.cjs","names":[],"sources":["../../src/drivers/driver.ts"],"sourcesContent":["import type { ColumnMetadata, DatabaseDriver, TableMetadata } from \"../types\";\n\n/**\n * Abstract base class for database drivers\n */\nexport abstract class BaseDriver implements DatabaseDriver {\n protected connected = false;\n\n /**\n * Connect to the database\n */\n abstract connect(): Promise<void>;\n\n /**\n * Disconnect from the database\n */\n abstract disconnect(): Promise<void>;\n\n /**\n * Execute a SQL statement that does not return rows\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n abstract execute(sql: string, params?: unknown[]): Promise<any>;\n\n /**\n * Execute a SQL query that returns rows\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n abstract query(sql: string, params?: unknown[]): Promise<any[]>;\n\n /**\n * Check if a table exists in the database\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n abstract tableExists(name: string): Promise<boolean>;\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata array\n */\n abstract getTableColumns(name: string): Promise<ColumnMetadata[]>;\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n abstract createTable(meta: TableMetadata): Promise<void>;\n\n /**\n * Drop a table by name\n * @param {string} name - Table name\n */\n abstract dropTable(name: string): Promise<void>;\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n abstract addColumn(table: string, column: ColumnMetadata): Promise<void>;\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n abstract dropColumn(table: string, name: string): Promise<void>;\n\n /**\n * Rename a column in a table\n * @param {string} table - Table name\n * @param {string} oldName - Current column name\n * @param {string} newName - New column name\n */\n abstract renameColumn(table: string, oldName: string, newName: string): Promise<void>;\n\n /**\n * Execute a function within a transaction\n * @param {() => Promise<T>} fn - Function to execute within the transaction\n * @returns {Promise<T>} Function result\n */\n abstract transaction<T>(fn: () => Promise<T>): Promise<T>;\n}\n"],"mappings":";;;;AAKA,IAAsB,aAAtB,MAA2D;CACzD,YAAsB"}
@@ -0,0 +1,11 @@
1
+ //#region src/drivers/driver.ts
2
+ /**
3
+ * Abstract base class for database drivers
4
+ */
5
+ var BaseDriver = class {
6
+ connected = false;
7
+ };
8
+ //#endregion
9
+ export { BaseDriver };
10
+
11
+ //# sourceMappingURL=driver.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.mjs","names":[],"sources":["../../src/drivers/driver.ts"],"sourcesContent":["import type { ColumnMetadata, DatabaseDriver, TableMetadata } from \"../types\";\n\n/**\n * Abstract base class for database drivers\n */\nexport abstract class BaseDriver implements DatabaseDriver {\n protected connected = false;\n\n /**\n * Connect to the database\n */\n abstract connect(): Promise<void>;\n\n /**\n * Disconnect from the database\n */\n abstract disconnect(): Promise<void>;\n\n /**\n * Execute a SQL statement that does not return rows\n * @param {string} sql - SQL statement\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any>} Execution result\n */\n abstract execute(sql: string, params?: unknown[]): Promise<any>;\n\n /**\n * Execute a SQL query that returns rows\n * @param {string} sql - SQL query\n * @param {unknown[]} [params] - Query parameters\n * @returns {Promise<any[]>} Query results\n */\n abstract query(sql: string, params?: unknown[]): Promise<any[]>;\n\n /**\n * Check if a table exists in the database\n * @param {string} name - Table name\n * @returns {Promise<boolean>} Whether the table exists\n */\n abstract tableExists(name: string): Promise<boolean>;\n\n /**\n * Get column metadata for a table\n * @param {string} name - Table name\n * @returns {Promise<ColumnMetadata[]>} Column metadata array\n */\n abstract getTableColumns(name: string): Promise<ColumnMetadata[]>;\n\n /**\n * Create a table from metadata\n * @param {TableMetadata} meta - Table metadata\n */\n abstract createTable(meta: TableMetadata): Promise<void>;\n\n /**\n * Drop a table by name\n * @param {string} name - Table name\n */\n abstract dropTable(name: string): Promise<void>;\n\n /**\n * Add a column to a table\n * @param {string} table - Table name\n * @param {ColumnMetadata} column - Column metadata\n */\n abstract addColumn(table: string, column: ColumnMetadata): Promise<void>;\n\n /**\n * Drop a column from a table\n * @param {string} table - Table name\n * @param {string} name - Column name\n */\n abstract dropColumn(table: string, name: string): Promise<void>;\n\n /**\n * Rename a column in a table\n * @param {string} table - Table name\n * @param {string} oldName - Current column name\n * @param {string} newName - New column name\n */\n abstract renameColumn(table: string, oldName: string, newName: string): Promise<void>;\n\n /**\n * Execute a function within a transaction\n * @param {() => Promise<T>} fn - Function to execute within the transaction\n * @returns {Promise<T>} Function result\n */\n abstract transaction<T>(fn: () => Promise<T>): Promise<T>;\n}\n"],"mappings":";;;;AAKA,IAAsB,aAAtB,MAA2D;CACzD,YAAsB"}