@hedystia/db 2.0.1 → 2.0.3

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 (50) hide show
  1. package/dist/cli/commands/migration.cjs +3 -2
  2. package/dist/cli/commands/migration.cjs.map +1 -1
  3. package/dist/cli/commands/migration.mjs +3 -2
  4. package/dist/cli/commands/migration.mjs.map +1 -1
  5. package/dist/core/repository.cjs +75 -21
  6. package/dist/core/repository.cjs.map +1 -1
  7. package/dist/core/repository.d.cts +10 -0
  8. package/dist/core/repository.d.mts +10 -0
  9. package/dist/core/repository.mjs +75 -21
  10. package/dist/core/repository.mjs.map +1 -1
  11. package/dist/index.cjs +14 -0
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +2 -2
  14. package/dist/index.d.mts +2 -2
  15. package/dist/index.mjs +2 -2
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/migrations/templates.cjs +4 -4
  18. package/dist/migrations/templates.cjs.map +1 -1
  19. package/dist/migrations/templates.mjs +4 -4
  20. package/dist/migrations/templates.mjs.map +1 -1
  21. package/dist/schema/column.cjs +34 -2
  22. package/dist/schema/column.cjs.map +1 -1
  23. package/dist/schema/column.d.cts +24 -0
  24. package/dist/schema/column.d.mts +24 -0
  25. package/dist/schema/column.mjs +34 -2
  26. package/dist/schema/column.mjs.map +1 -1
  27. package/dist/schema/columns/index.cjs +93 -1
  28. package/dist/schema/columns/index.cjs.map +1 -1
  29. package/dist/schema/columns/index.d.cts +52 -2
  30. package/dist/schema/columns/index.d.mts +52 -2
  31. package/dist/schema/columns/index.mjs +80 -2
  32. package/dist/schema/columns/index.mjs.map +1 -1
  33. package/dist/schema/registry.cjs +28 -4
  34. package/dist/schema/registry.cjs.map +1 -1
  35. package/dist/schema/registry.d.cts +15 -1
  36. package/dist/schema/registry.d.mts +15 -1
  37. package/dist/schema/registry.mjs +28 -4
  38. package/dist/schema/registry.mjs.map +1 -1
  39. package/dist/schema/table.cjs +3 -0
  40. package/dist/schema/table.cjs.map +1 -1
  41. package/dist/schema/table.mjs +3 -0
  42. package/dist/schema/table.mjs.map +1 -1
  43. package/dist/sync/synchronizer.cjs +2 -2
  44. package/dist/sync/synchronizer.cjs.map +1 -1
  45. package/dist/sync/synchronizer.mjs +2 -2
  46. package/dist/sync/synchronizer.mjs.map +1 -1
  47. package/dist/types.d.cts +4 -2
  48. package/dist/types.d.mts +4 -2
  49. package/package.json +1 -1
  50. package/readme.md +11 -9
@@ -12,8 +12,9 @@ let path = require("path");
12
12
  function createMigration(name, path$1) {
13
13
  const dir = path$1 ?? "src/database/migrations";
14
14
  require_fs.ensureDir(dir);
15
- const filePath = (0, path.join)(dir, `${require_naming.generateTimestamp()}_${name}.ts`);
16
- require_fs.writeFileSafe(filePath, require_templates.generateMigrationTemplate(name));
15
+ const timestamp = require_naming.generateTimestamp();
16
+ const filePath = (0, path.join)(dir, `${timestamp}_${name}.ts`);
17
+ require_fs.writeFileSafe(filePath, require_templates.generateMigrationTemplate(`${timestamp}_${name}`));
17
18
  console.log(`Created migration: ${filePath}`);
18
19
  }
19
20
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"migration.cjs","names":["path","generateTimestamp","generateMigrationTemplate"],"sources":["../../../src/cli/commands/migration.ts"],"sourcesContent":["import { join } from \"path\";\nimport { DEFAULT_MIGRATIONS_PATH } from \"../../constants\";\nimport { generateMigrationTemplate } from \"../../migrations\";\nimport { ensureDir, writeFileSafe } from \"../../utils\";\nimport { generateTimestamp } from \"../../utils/naming\";\n\n/**\n * Create a new migration file\n * @param {string} name - Migration name\n * @param {string} [path] - Output directory\n */\nexport function createMigration(name: string, path?: string): void {\n const dir = path ?? DEFAULT_MIGRATIONS_PATH;\n ensureDir(dir);\n\n const timestamp = generateTimestamp();\n const fileName = `${timestamp}_${name}.ts`;\n const filePath = join(dir, fileName);\n const content = generateMigrationTemplate(name);\n\n writeFileSafe(filePath, content);\n console.log(`Created migration: ${filePath}`);\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,gBAAgB,MAAc,QAAqB;CACjE,MAAM,MAAMA,UAAAA;AACZ,YAAA,UAAU,IAAI;CAId,MAAM,YAAA,GAAA,KAAA,MAAgB,KADL,GADCC,eAAAA,mBAAmB,CACP,GAAG,KAAK,KACF;AAGpC,YAAA,cAAc,UAFEC,kBAAAA,0BAA0B,KAAK,CAEf;AAChC,SAAQ,IAAI,sBAAsB,WAAW"}
1
+ {"version":3,"file":"migration.cjs","names":["path","generateTimestamp","generateMigrationTemplate"],"sources":["../../../src/cli/commands/migration.ts"],"sourcesContent":["import { join } from \"path\";\nimport { DEFAULT_MIGRATIONS_PATH } from \"../../constants\";\nimport { generateMigrationTemplate } from \"../../migrations\";\nimport { ensureDir, writeFileSafe } from \"../../utils\";\nimport { generateTimestamp } from \"../../utils/naming\";\n\n/**\n * Create a new migration file\n * @param {string} name - Migration name\n * @param {string} [path] - Output directory\n */\nexport function createMigration(name: string, path?: string): void {\n const dir = path ?? DEFAULT_MIGRATIONS_PATH;\n ensureDir(dir);\n\n const timestamp = generateTimestamp();\n const fileName = `${timestamp}_${name}.ts`;\n const filePath = join(dir, fileName);\n const migrationId = `${timestamp}_${name}`;\n const content = generateMigrationTemplate(migrationId);\n\n writeFileSafe(filePath, content);\n console.log(`Created migration: ${filePath}`);\n}\n"],"mappings":";;;;;;;;;;;AAWA,SAAgB,gBAAgB,MAAc,QAAqB;CACjE,MAAM,MAAMA,UAAAA;AACZ,YAAA,UAAU,IAAI;CAEd,MAAM,YAAYC,eAAAA,mBAAmB;CAErC,MAAM,YAAA,GAAA,KAAA,MAAgB,KADL,GAAG,UAAU,GAAG,KAAK,KACF;AAIpC,YAAA,cAAc,UAFEC,kBAAAA,0BADI,GAAG,UAAU,GAAG,OACkB,CAEtB;AAChC,SAAQ,IAAI,sBAAsB,WAAW"}
@@ -15,8 +15,9 @@ import { join } from "path";
15
15
  function createMigration(name, path) {
16
16
  const dir = path ?? "src/database/migrations";
17
17
  ensureDir(dir);
18
- const filePath = join(dir, `${generateTimestamp()}_${name}.ts`);
19
- writeFileSafe(filePath, generateMigrationTemplate(name));
18
+ const timestamp = generateTimestamp();
19
+ const filePath = join(dir, `${timestamp}_${name}.ts`);
20
+ writeFileSafe(filePath, generateMigrationTemplate(`${timestamp}_${name}`));
20
21
  console.log(`Created migration: ${filePath}`);
21
22
  }
22
23
  var init_migration = __esmMin((() => {
@@ -1 +1 @@
1
- {"version":3,"file":"migration.mjs","names":[],"sources":["../../../src/cli/commands/migration.ts"],"sourcesContent":["import { join } from \"path\";\nimport { DEFAULT_MIGRATIONS_PATH } from \"../../constants\";\nimport { generateMigrationTemplate } from \"../../migrations\";\nimport { ensureDir, writeFileSafe } from \"../../utils\";\nimport { generateTimestamp } from \"../../utils/naming\";\n\n/**\n * Create a new migration file\n * @param {string} name - Migration name\n * @param {string} [path] - Output directory\n */\nexport function createMigration(name: string, path?: string): void {\n const dir = path ?? DEFAULT_MIGRATIONS_PATH;\n ensureDir(dir);\n\n const timestamp = generateTimestamp();\n const fileName = `${timestamp}_${name}.ts`;\n const filePath = join(dir, fileName);\n const content = generateMigrationTemplate(name);\n\n writeFileSafe(filePath, content);\n console.log(`Created migration: ${filePath}`);\n}\n"],"mappings":";;;;;;;;;;;;;;AAWA,SAAgB,gBAAgB,MAAc,MAAqB;CACjE,MAAM,MAAM,QAAA;AACZ,WAAU,IAAI;CAId,MAAM,WAAW,KAAK,KADL,GADC,mBAAmB,CACP,GAAG,KAAK,KACF;AAGpC,eAAc,UAFE,0BAA0B,KAAK,CAEf;AAChC,SAAQ,IAAI,sBAAsB,WAAW;;;iBApBW;kBACG;aACN;cACA"}
1
+ {"version":3,"file":"migration.mjs","names":[],"sources":["../../../src/cli/commands/migration.ts"],"sourcesContent":["import { join } from \"path\";\nimport { DEFAULT_MIGRATIONS_PATH } from \"../../constants\";\nimport { generateMigrationTemplate } from \"../../migrations\";\nimport { ensureDir, writeFileSafe } from \"../../utils\";\nimport { generateTimestamp } from \"../../utils/naming\";\n\n/**\n * Create a new migration file\n * @param {string} name - Migration name\n * @param {string} [path] - Output directory\n */\nexport function createMigration(name: string, path?: string): void {\n const dir = path ?? DEFAULT_MIGRATIONS_PATH;\n ensureDir(dir);\n\n const timestamp = generateTimestamp();\n const fileName = `${timestamp}_${name}.ts`;\n const filePath = join(dir, fileName);\n const migrationId = `${timestamp}_${name}`;\n const content = generateMigrationTemplate(migrationId);\n\n writeFileSafe(filePath, content);\n console.log(`Created migration: ${filePath}`);\n}\n"],"mappings":";;;;;;;;;;;;;;AAWA,SAAgB,gBAAgB,MAAc,MAAqB;CACjE,MAAM,MAAM,QAAA;AACZ,WAAU,IAAI;CAEd,MAAM,YAAY,mBAAmB;CAErC,MAAM,WAAW,KAAK,KADL,GAAG,UAAU,GAAG,KAAK,KACF;AAIpC,eAAc,UAFE,0BADI,GAAG,UAAU,GAAG,OACkB,CAEtB;AAChC,SAAQ,IAAI,sBAAsB,WAAW;;;iBArBW;kBACG;aACN;cACA"}
@@ -12,6 +12,9 @@ var TableRepository = class {
12
12
  cache;
13
13
  registry;
14
14
  meta;
15
+ columnMap;
16
+ reverseColumnMap;
17
+ hasAliases;
15
18
  constructor(tableName, driver, cache, registry) {
16
19
  this.tableName = tableName;
17
20
  this.driver = driver;
@@ -20,6 +23,9 @@ var TableRepository = class {
20
23
  const meta = registry.getTable(tableName);
21
24
  if (!meta) throw new require_errors.QueryError(`Table "${tableName}" is not registered`);
22
25
  this.meta = meta;
26
+ this.columnMap = registry.getColumnMap(tableName);
27
+ this.reverseColumnMap = registry.getReverseColumnMap(tableName);
28
+ this.hasAliases = Object.entries(this.columnMap).some(([codeKey, dbName]) => codeKey !== dbName);
23
29
  }
24
30
  /**
25
31
  * Find all rows matching the query options
@@ -28,9 +34,10 @@ var TableRepository = class {
28
34
  */
29
35
  async find(options) {
30
36
  return this.cache.getOrSet(this.tableName, "find", options, async () => {
37
+ const dbOptions = this.mapOptionsToDb(options);
31
38
  let rows;
32
- if (this.driver instanceof require_file.FileDriver) rows = this.findFile(options);
33
- else rows = await this.findSQL(options);
39
+ if (this.driver instanceof require_file.FileDriver) rows = this.mapRows(this.findFile(dbOptions));
40
+ else rows = this.mapRows(await this.findSQL(dbOptions));
34
41
  if (options?.with) rows = await this.loadRelations(rows, options.with);
35
42
  this.cacheEntities(rows);
36
43
  return rows;
@@ -52,12 +59,12 @@ var TableRepository = class {
52
59
  async findFirst(options) {
53
60
  return this.cache.getOrSet(this.tableName, "findFirst", options, async () => {
54
61
  const opts = {
55
- ...options,
62
+ ...this.mapOptionsToDb(options),
56
63
  take: 1
57
64
  };
58
65
  let rows;
59
- if (this.driver instanceof require_file.FileDriver) rows = this.findFile(opts);
60
- else rows = await this.findSQL(opts);
66
+ if (this.driver instanceof require_file.FileDriver) rows = this.mapRows(this.findFile(opts));
67
+ else rows = this.mapRows(await this.findSQL(opts));
61
68
  if (rows.length === 0) return null;
62
69
  if (options?.with) rows = await this.loadRelations(rows, options.with);
63
70
  const row = rows[0] ?? null;
@@ -74,21 +81,23 @@ var TableRepository = class {
74
81
  const single = Array.isArray(data) ? data[0] : data;
75
82
  if (!single) throw new require_errors.QueryError("Insert data cannot be empty");
76
83
  this.cache.invalidateTable(this.tableName);
77
- const cleaned = this.cleanData(single);
84
+ const cleaned = this.toDbKeys(this.cleanData(single));
78
85
  if (this.driver instanceof require_file.FileDriver) {
79
86
  const id = this.driver.insertRow(this.tableName, cleaned);
80
87
  const pk = this.registry.getPrimaryKey(this.tableName);
81
88
  if (pk) cleaned[pk] = id;
82
- this.cacheEntity(cleaned);
83
- return cleaned;
89
+ const result = this.toCodeKeys(cleaned);
90
+ this.cacheEntity(result);
91
+ return result;
84
92
  }
85
93
  const params = [];
86
94
  const sql = require_sql_compiler.compileInsert(this.tableName, cleaned, params);
87
95
  const result = await this.driver.execute(sql, params);
88
96
  const pk = this.registry.getPrimaryKey(this.tableName);
89
97
  if (pk && result.insertId) cleaned[pk] = result.insertId;
90
- this.cacheEntity(cleaned);
91
- return cleaned;
98
+ const mapped = this.toCodeKeys(cleaned);
99
+ this.cacheEntity(mapped);
100
+ return mapped;
92
101
  }
93
102
  /**
94
103
  * Insert multiple rows
@@ -103,7 +112,7 @@ var TableRepository = class {
103
112
  for (const item of data) results.push(await this.insert(item));
104
113
  return results;
105
114
  }
106
- const cleanedData = data.map((item) => this.cleanData(item));
115
+ const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));
107
116
  const params = [];
108
117
  const sql = require_sql_compiler.compileBulkInsert(this.tableName, cleanedData, params);
109
118
  const result = await this.driver.execute(sql, params);
@@ -112,7 +121,7 @@ var TableRepository = class {
112
121
  const row = cleanedData[i];
113
122
  if (row) row[pk] = result.insertId + i;
114
123
  }
115
- const finalRows = cleanedData;
124
+ const finalRows = this.mapRows(cleanedData);
116
125
  this.cacheEntities(finalRows);
117
126
  return finalRows;
118
127
  }
@@ -124,14 +133,15 @@ var TableRepository = class {
124
133
  async update(options) {
125
134
  if (!options.where || Object.keys(options.where).length === 0) throw new require_errors.QueryError("Update requires a where clause");
126
135
  this.cache.invalidateTable(this.tableName);
127
- const cleaned = this.cleanData(options.data);
136
+ const cleaned = this.toDbKeys(this.cleanData(options.data));
137
+ const dbWhere = this.mapWhereToDb(options.where);
128
138
  if (this.driver instanceof require_file.FileDriver) {
129
- const filter = this.buildFileFilter(options.where);
139
+ const filter = this.buildFileFilter(dbWhere);
130
140
  this.driver.updateRows(this.tableName, filter, cleaned);
131
141
  return this.find({ where: options.where });
132
142
  }
133
143
  const params = [];
134
- const sql = require_sql_compiler.compileUpdate(this.tableName, cleaned, options.where, params);
144
+ const sql = require_sql_compiler.compileUpdate(this.tableName, cleaned, dbWhere, params);
135
145
  await this.driver.execute(sql, params);
136
146
  return this.find({ where: options.where });
137
147
  }
@@ -143,12 +153,13 @@ var TableRepository = class {
143
153
  async delete(options) {
144
154
  if (!options.where || Object.keys(options.where).length === 0) throw new require_errors.QueryError("Delete requires a where clause");
145
155
  this.cache.invalidateTable(this.tableName);
156
+ const dbWhere = this.mapWhereToDb(options.where);
146
157
  if (this.driver instanceof require_file.FileDriver) {
147
- const filter = this.buildFileFilter(options.where);
158
+ const filter = this.buildFileFilter(dbWhere);
148
159
  return this.driver.deleteRows(this.tableName, filter);
149
160
  }
150
161
  const params = [];
151
- const sql = require_sql_compiler.compileDelete(this.tableName, options.where, params);
162
+ const sql = require_sql_compiler.compileDelete(this.tableName, dbWhere, params);
152
163
  return (await this.driver.execute(sql, params)).affectedRows;
153
164
  }
154
165
  /**
@@ -158,13 +169,14 @@ var TableRepository = class {
158
169
  */
159
170
  async count(options) {
160
171
  return this.cache.getOrSet(this.tableName, "count", options, async () => {
172
+ const dbWhere = options?.where ? this.mapWhereToDb(options.where) : void 0;
161
173
  if (this.driver instanceof require_file.FileDriver) {
162
- const filter = options?.where ? this.buildFileFilter(options.where) : void 0;
174
+ const filter = dbWhere ? this.buildFileFilter(dbWhere) : void 0;
163
175
  return this.driver.countRows(this.tableName, filter);
164
176
  }
165
177
  const params = [];
166
178
  let sql = `SELECT COUNT(*) as count FROM \`${this.tableName}\``;
167
- if (options?.where && Object.keys(options.where).length > 0) sql += ` WHERE ${require_sql_compiler.compileWhere(options.where, params)}`;
179
+ if (dbWhere && Object.keys(dbWhere).length > 0) sql += ` WHERE ${require_sql_compiler.compileWhere(dbWhere, params)}`;
168
180
  return (await this.driver.query(sql, params))[0]?.count ?? 0;
169
181
  });
170
182
  }
@@ -341,8 +353,9 @@ var TableRepository = class {
341
353
  }
342
354
  cleanData(data) {
343
355
  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;
356
+ const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));
357
+ const codeKeys = new Set(Object.keys(this.columnMap));
358
+ for (const [key, value] of Object.entries(data)) if (codeKeys.has(key) || dbColumnNames.has(key)) cleaned[key] = value;
346
359
  return cleaned;
347
360
  }
348
361
  cacheEntities(rows) {
@@ -355,6 +368,47 @@ var TableRepository = class {
355
368
  if (!pk || row[pk] == null) return;
356
369
  this.cache.setEntity(this.tableName, row[pk], row);
357
370
  }
371
+ toDbKeys(data) {
372
+ if (!this.hasAliases) return data;
373
+ const result = {};
374
+ for (const [key, value] of Object.entries(data)) result[this.columnMap[key] ?? key] = value;
375
+ return result;
376
+ }
377
+ toCodeKeys(row) {
378
+ if (!this.hasAliases) return row;
379
+ const result = {};
380
+ for (const [key, value] of Object.entries(row)) result[this.reverseColumnMap[key] ?? key] = value;
381
+ return result;
382
+ }
383
+ mapWhereToDb(where) {
384
+ if (!this.hasAliases) return where;
385
+ const result = {};
386
+ for (const [key, value] of Object.entries(where)) if (key === "OR" || key === "AND") result[key] = value.map((sub) => this.mapWhereToDb(sub));
387
+ else result[this.columnMap[key] ?? key] = value;
388
+ return result;
389
+ }
390
+ mapSelectToDb(select) {
391
+ if (!this.hasAliases) return select;
392
+ return select.map((key) => this.columnMap[key] ?? key);
393
+ }
394
+ mapOrderByToDb(orderBy) {
395
+ if (!this.hasAliases) return orderBy;
396
+ const result = {};
397
+ for (const [key, value] of Object.entries(orderBy)) result[this.columnMap[key] ?? key] = value;
398
+ return result;
399
+ }
400
+ mapOptionsToDb(options) {
401
+ if (!options || !this.hasAliases) return options;
402
+ const mapped = { ...options };
403
+ if (options.where) mapped.where = this.mapWhereToDb(options.where);
404
+ if (options.select) mapped.select = this.mapSelectToDb(options.select);
405
+ if (options.orderBy) mapped.orderBy = this.mapOrderByToDb(options.orderBy);
406
+ return mapped;
407
+ }
408
+ mapRows(rows) {
409
+ if (!this.hasAliases) return rows;
410
+ return rows.map((row) => this.toCodeKeys(row));
411
+ }
358
412
  };
359
413
  //#endregion
360
414
  exports.TableRepository = TableRepository;
@@ -1 +1 @@
1
- {"version":3,"file":"repository.cjs","names":["QueryError","FileDriver","compileInsert","compileBulkInsert","compileUpdate","compileDelete","compileWhere","compileSelect"],"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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"}
1
+ {"version":3,"file":"repository.cjs","names":["QueryError","FileDriver","compileInsert","compileBulkInsert","compileUpdate","compileDelete","compileWhere","compileSelect"],"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 private columnMap: Record<string, string>;\n private reverseColumnMap: Record<string, string>;\n private hasAliases: boolean;\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 this.columnMap = registry.getColumnMap(tableName);\n this.reverseColumnMap = registry.getReverseColumnMap(tableName);\n this.hasAliases = Object.entries(this.columnMap).some(\n ([codeKey, dbName]) => codeKey !== dbName,\n );\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 const dbOptions = this.mapOptionsToDb(options);\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.mapRows(this.findFile(dbOptions as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(dbOptions as QueryOptions<T>));\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 dbOptions = this.mapOptionsToDb(options);\n const opts = { ...dbOptions, take: 1 };\n let rows: T[];\n if (this.driver instanceof FileDriver) {\n rows = this.mapRows(this.findFile(opts as QueryOptions<T>));\n } else {\n rows = this.mapRows(await this.findSQL(opts as QueryOptions<T>));\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.toDbKeys(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 const result = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(result);\n return result;\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 const mapped = this.toCodeKeys(cleaned) as T;\n this.cacheEntity(mapped);\n return mapped;\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.toDbKeys(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 = this.mapRows(cleanedData);\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.toDbKeys(this.cleanData(options.data));\n const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(dbWhere);\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, dbWhere, 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 const dbWhere = this.mapWhereToDb(options.where as WhereClause);\n\n if (this.driver instanceof FileDriver) {\n const filter = this.buildFileFilter(dbWhere);\n return (this.driver as FileDriver).deleteRows(this.tableName, filter);\n }\n\n const params: unknown[] = [];\n const sql = compileDelete(this.tableName, dbWhere, 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 const dbWhere = options?.where ? this.mapWhereToDb(options.where as WhereClause) : undefined;\n\n if (this.driver instanceof FileDriver) {\n const filter = dbWhere ? this.buildFileFilter(dbWhere) : 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 (dbWhere && Object.keys(dbWhere).length > 0) {\n sql += ` WHERE ${compileWhere(dbWhere, 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 dbColumnNames = new Set(this.meta.columns.map((c) => c.name));\n const codeKeys = new Set(Object.keys(this.columnMap));\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (codeKeys.has(key) || dbColumnNames.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 private toDbKeys(data: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return data;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private toCodeKeys(row: Record<string, unknown>): Record<string, unknown> {\n if (!this.hasAliases) {\n return row;\n }\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(row)) {\n result[this.reverseColumnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapWhereToDb(where: WhereClause): WhereClause {\n if (!this.hasAliases) {\n return where;\n }\n const result: WhereClause = {};\n for (const [key, value] of Object.entries(where)) {\n if (key === \"OR\" || key === \"AND\") {\n (result as any)[key] = (value as WhereClause[]).map((sub) => this.mapWhereToDb(sub));\n } else {\n result[this.columnMap[key] ?? key] = value;\n }\n }\n return result;\n }\n\n private mapSelectToDb(select: string[]): string[] {\n if (!this.hasAliases) {\n return select;\n }\n return select.map((key) => this.columnMap[key] ?? key);\n }\n\n private mapOrderByToDb(orderBy: Record<string, \"asc\" | \"desc\">): Record<string, \"asc\" | \"desc\"> {\n if (!this.hasAliases) {\n return orderBy;\n }\n const result: Record<string, \"asc\" | \"desc\"> = {};\n for (const [key, value] of Object.entries(orderBy)) {\n result[this.columnMap[key] ?? key] = value;\n }\n return result;\n }\n\n private mapOptionsToDb(options?: QueryOptions<T>): QueryOptions | undefined {\n if (!options || !this.hasAliases) {\n return options as QueryOptions | undefined;\n }\n const mapped: QueryOptions = { ...options } as any;\n if (options.where) {\n mapped.where = this.mapWhereToDb(options.where as WhereClause);\n }\n if (options.select) {\n mapped.select = this.mapSelectToDb(options.select);\n }\n if (options.orderBy) {\n mapped.orderBy = this.mapOrderByToDb(options.orderBy as Record<string, \"asc\" | \"desc\">);\n }\n return mapped;\n }\n\n private mapRows(rows: Record<string, unknown>[]): T[] {\n if (!this.hasAliases) {\n return rows as T[];\n }\n return rows.map((row) => this.toCodeKeys(row) as T);\n }\n}\n"],"mappings":"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"}
@@ -13,6 +13,9 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
13
13
  private cache;
14
14
  private registry;
15
15
  private meta;
16
+ private columnMap;
17
+ private reverseColumnMap;
18
+ private hasAliases;
16
19
  constructor(tableName: string, driver: DatabaseDriver, cache: CacheManager, registry: SchemaRegistry);
17
20
  /**
18
21
  * Find all rows matching the query options
@@ -94,6 +97,13 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
94
97
  private cleanData;
95
98
  private cacheEntities;
96
99
  private cacheEntity;
100
+ private toDbKeys;
101
+ private toCodeKeys;
102
+ private mapWhereToDb;
103
+ private mapSelectToDb;
104
+ private mapOrderByToDb;
105
+ private mapOptionsToDb;
106
+ private mapRows;
97
107
  }
98
108
  //#endregion
99
109
  export { TableRepository };
@@ -13,6 +13,9 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
13
13
  private cache;
14
14
  private registry;
15
15
  private meta;
16
+ private columnMap;
17
+ private reverseColumnMap;
18
+ private hasAliases;
16
19
  constructor(tableName: string, driver: DatabaseDriver, cache: CacheManager, registry: SchemaRegistry);
17
20
  /**
18
21
  * Find all rows matching the query options
@@ -94,6 +97,13 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
94
97
  private cleanData;
95
98
  private cacheEntities;
96
99
  private cacheEntity;
100
+ private toDbKeys;
101
+ private toCodeKeys;
102
+ private mapWhereToDb;
103
+ private mapSelectToDb;
104
+ private mapOrderByToDb;
105
+ private mapOptionsToDb;
106
+ private mapRows;
97
107
  }
98
108
  //#endregion
99
109
  export { TableRepository };
@@ -12,6 +12,9 @@ var TableRepository = class {
12
12
  cache;
13
13
  registry;
14
14
  meta;
15
+ columnMap;
16
+ reverseColumnMap;
17
+ hasAliases;
15
18
  constructor(tableName, driver, cache, registry) {
16
19
  this.tableName = tableName;
17
20
  this.driver = driver;
@@ -20,6 +23,9 @@ var TableRepository = class {
20
23
  const meta = registry.getTable(tableName);
21
24
  if (!meta) throw new QueryError(`Table "${tableName}" is not registered`);
22
25
  this.meta = meta;
26
+ this.columnMap = registry.getColumnMap(tableName);
27
+ this.reverseColumnMap = registry.getReverseColumnMap(tableName);
28
+ this.hasAliases = Object.entries(this.columnMap).some(([codeKey, dbName]) => codeKey !== dbName);
23
29
  }
24
30
  /**
25
31
  * Find all rows matching the query options
@@ -28,9 +34,10 @@ var TableRepository = class {
28
34
  */
29
35
  async find(options) {
30
36
  return this.cache.getOrSet(this.tableName, "find", options, async () => {
37
+ const dbOptions = this.mapOptionsToDb(options);
31
38
  let rows;
32
- if (this.driver instanceof FileDriver) rows = this.findFile(options);
33
- else rows = await this.findSQL(options);
39
+ if (this.driver instanceof FileDriver) rows = this.mapRows(this.findFile(dbOptions));
40
+ else rows = this.mapRows(await this.findSQL(dbOptions));
34
41
  if (options?.with) rows = await this.loadRelations(rows, options.with);
35
42
  this.cacheEntities(rows);
36
43
  return rows;
@@ -52,12 +59,12 @@ var TableRepository = class {
52
59
  async findFirst(options) {
53
60
  return this.cache.getOrSet(this.tableName, "findFirst", options, async () => {
54
61
  const opts = {
55
- ...options,
62
+ ...this.mapOptionsToDb(options),
56
63
  take: 1
57
64
  };
58
65
  let rows;
59
- if (this.driver instanceof FileDriver) rows = this.findFile(opts);
60
- else rows = await this.findSQL(opts);
66
+ if (this.driver instanceof FileDriver) rows = this.mapRows(this.findFile(opts));
67
+ else rows = this.mapRows(await this.findSQL(opts));
61
68
  if (rows.length === 0) return null;
62
69
  if (options?.with) rows = await this.loadRelations(rows, options.with);
63
70
  const row = rows[0] ?? null;
@@ -74,21 +81,23 @@ var TableRepository = class {
74
81
  const single = Array.isArray(data) ? data[0] : data;
75
82
  if (!single) throw new QueryError("Insert data cannot be empty");
76
83
  this.cache.invalidateTable(this.tableName);
77
- const cleaned = this.cleanData(single);
84
+ const cleaned = this.toDbKeys(this.cleanData(single));
78
85
  if (this.driver instanceof FileDriver) {
79
86
  const id = this.driver.insertRow(this.tableName, cleaned);
80
87
  const pk = this.registry.getPrimaryKey(this.tableName);
81
88
  if (pk) cleaned[pk] = id;
82
- this.cacheEntity(cleaned);
83
- return cleaned;
89
+ const result = this.toCodeKeys(cleaned);
90
+ this.cacheEntity(result);
91
+ return result;
84
92
  }
85
93
  const params = [];
86
94
  const sql = compileInsert(this.tableName, cleaned, params);
87
95
  const result = await this.driver.execute(sql, params);
88
96
  const pk = this.registry.getPrimaryKey(this.tableName);
89
97
  if (pk && result.insertId) cleaned[pk] = result.insertId;
90
- this.cacheEntity(cleaned);
91
- return cleaned;
98
+ const mapped = this.toCodeKeys(cleaned);
99
+ this.cacheEntity(mapped);
100
+ return mapped;
92
101
  }
93
102
  /**
94
103
  * Insert multiple rows
@@ -103,7 +112,7 @@ var TableRepository = class {
103
112
  for (const item of data) results.push(await this.insert(item));
104
113
  return results;
105
114
  }
106
- const cleanedData = data.map((item) => this.cleanData(item));
115
+ const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));
107
116
  const params = [];
108
117
  const sql = compileBulkInsert(this.tableName, cleanedData, params);
109
118
  const result = await this.driver.execute(sql, params);
@@ -112,7 +121,7 @@ var TableRepository = class {
112
121
  const row = cleanedData[i];
113
122
  if (row) row[pk] = result.insertId + i;
114
123
  }
115
- const finalRows = cleanedData;
124
+ const finalRows = this.mapRows(cleanedData);
116
125
  this.cacheEntities(finalRows);
117
126
  return finalRows;
118
127
  }
@@ -124,14 +133,15 @@ var TableRepository = class {
124
133
  async update(options) {
125
134
  if (!options.where || Object.keys(options.where).length === 0) throw new QueryError("Update requires a where clause");
126
135
  this.cache.invalidateTable(this.tableName);
127
- const cleaned = this.cleanData(options.data);
136
+ const cleaned = this.toDbKeys(this.cleanData(options.data));
137
+ const dbWhere = this.mapWhereToDb(options.where);
128
138
  if (this.driver instanceof FileDriver) {
129
- const filter = this.buildFileFilter(options.where);
139
+ const filter = this.buildFileFilter(dbWhere);
130
140
  this.driver.updateRows(this.tableName, filter, cleaned);
131
141
  return this.find({ where: options.where });
132
142
  }
133
143
  const params = [];
134
- const sql = compileUpdate(this.tableName, cleaned, options.where, params);
144
+ const sql = compileUpdate(this.tableName, cleaned, dbWhere, params);
135
145
  await this.driver.execute(sql, params);
136
146
  return this.find({ where: options.where });
137
147
  }
@@ -143,12 +153,13 @@ var TableRepository = class {
143
153
  async delete(options) {
144
154
  if (!options.where || Object.keys(options.where).length === 0) throw new QueryError("Delete requires a where clause");
145
155
  this.cache.invalidateTable(this.tableName);
156
+ const dbWhere = this.mapWhereToDb(options.where);
146
157
  if (this.driver instanceof FileDriver) {
147
- const filter = this.buildFileFilter(options.where);
158
+ const filter = this.buildFileFilter(dbWhere);
148
159
  return this.driver.deleteRows(this.tableName, filter);
149
160
  }
150
161
  const params = [];
151
- const sql = compileDelete(this.tableName, options.where, params);
162
+ const sql = compileDelete(this.tableName, dbWhere, params);
152
163
  return (await this.driver.execute(sql, params)).affectedRows;
153
164
  }
154
165
  /**
@@ -158,13 +169,14 @@ var TableRepository = class {
158
169
  */
159
170
  async count(options) {
160
171
  return this.cache.getOrSet(this.tableName, "count", options, async () => {
172
+ const dbWhere = options?.where ? this.mapWhereToDb(options.where) : void 0;
161
173
  if (this.driver instanceof FileDriver) {
162
- const filter = options?.where ? this.buildFileFilter(options.where) : void 0;
174
+ const filter = dbWhere ? this.buildFileFilter(dbWhere) : void 0;
163
175
  return this.driver.countRows(this.tableName, filter);
164
176
  }
165
177
  const params = [];
166
178
  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)}`;
179
+ if (dbWhere && Object.keys(dbWhere).length > 0) sql += ` WHERE ${compileWhere(dbWhere, params)}`;
168
180
  return (await this.driver.query(sql, params))[0]?.count ?? 0;
169
181
  });
170
182
  }
@@ -341,8 +353,9 @@ var TableRepository = class {
341
353
  }
342
354
  cleanData(data) {
343
355
  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;
356
+ const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));
357
+ const codeKeys = new Set(Object.keys(this.columnMap));
358
+ for (const [key, value] of Object.entries(data)) if (codeKeys.has(key) || dbColumnNames.has(key)) cleaned[key] = value;
346
359
  return cleaned;
347
360
  }
348
361
  cacheEntities(rows) {
@@ -355,6 +368,47 @@ var TableRepository = class {
355
368
  if (!pk || row[pk] == null) return;
356
369
  this.cache.setEntity(this.tableName, row[pk], row);
357
370
  }
371
+ toDbKeys(data) {
372
+ if (!this.hasAliases) return data;
373
+ const result = {};
374
+ for (const [key, value] of Object.entries(data)) result[this.columnMap[key] ?? key] = value;
375
+ return result;
376
+ }
377
+ toCodeKeys(row) {
378
+ if (!this.hasAliases) return row;
379
+ const result = {};
380
+ for (const [key, value] of Object.entries(row)) result[this.reverseColumnMap[key] ?? key] = value;
381
+ return result;
382
+ }
383
+ mapWhereToDb(where) {
384
+ if (!this.hasAliases) return where;
385
+ const result = {};
386
+ for (const [key, value] of Object.entries(where)) if (key === "OR" || key === "AND") result[key] = value.map((sub) => this.mapWhereToDb(sub));
387
+ else result[this.columnMap[key] ?? key] = value;
388
+ return result;
389
+ }
390
+ mapSelectToDb(select) {
391
+ if (!this.hasAliases) return select;
392
+ return select.map((key) => this.columnMap[key] ?? key);
393
+ }
394
+ mapOrderByToDb(orderBy) {
395
+ if (!this.hasAliases) return orderBy;
396
+ const result = {};
397
+ for (const [key, value] of Object.entries(orderBy)) result[this.columnMap[key] ?? key] = value;
398
+ return result;
399
+ }
400
+ mapOptionsToDb(options) {
401
+ if (!options || !this.hasAliases) return options;
402
+ const mapped = { ...options };
403
+ if (options.where) mapped.where = this.mapWhereToDb(options.where);
404
+ if (options.select) mapped.select = this.mapSelectToDb(options.select);
405
+ if (options.orderBy) mapped.orderBy = this.mapOrderByToDb(options.orderBy);
406
+ return mapped;
407
+ }
408
+ mapRows(rows) {
409
+ if (!this.hasAliases) return rows;
410
+ return rows.map((row) => this.toCodeKeys(row));
411
+ }
358
412
  };
359
413
  //#endregion
360
414
  export { TableRepository };