@hedystia/db 2.0.14 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/repository.cjs +13 -84
- package/dist/core/repository.cjs.map +1 -1
- package/dist/core/repository.d.cts +0 -3
- package/dist/core/repository.d.mts +0 -3
- package/dist/core/repository.mjs +13 -86
- package/dist/core/repository.mjs.map +1 -1
- package/dist/drivers/file.cjs +289 -124
- package/dist/drivers/file.cjs.map +1 -1
- package/dist/drivers/file.mjs +289 -124
- package/dist/drivers/file.mjs.map +1 -1
- package/dist/drivers/s3.cjs +289 -84
- package/dist/drivers/s3.cjs.map +1 -1
- package/dist/drivers/s3.mjs +289 -84
- package/dist/drivers/s3.mjs.map +1 -1
- package/package.json +2 -2
package/dist/core/repository.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const require_errors = require("../errors.cjs");
|
|
2
|
-
const require_file = require("../drivers/file.cjs");
|
|
3
2
|
const require_sql_compiler = require("../drivers/sql-compiler.cjs");
|
|
4
|
-
const require_s3 = require("../drivers/s3.cjs");
|
|
5
3
|
//#region src/core/repository.ts
|
|
6
4
|
/**
|
|
7
5
|
* Repository implementation that provides CRUD operations for a table
|
|
@@ -19,7 +17,6 @@ var TableRepository = class {
|
|
|
19
17
|
tableCacheConfig;
|
|
20
18
|
jsonColumns;
|
|
21
19
|
jsonCodeKeys;
|
|
22
|
-
isFileLikeDriver;
|
|
23
20
|
dateColumns;
|
|
24
21
|
constructor(tableName, driver, cache, registry, tableCacheConfig) {
|
|
25
22
|
this.tableName = tableName;
|
|
@@ -44,7 +41,6 @@ var TableRepository = class {
|
|
|
44
41
|
const codeKey = this.reverseColumnMap[col.name] ?? col.name;
|
|
45
42
|
this.dateColumns.add(codeKey);
|
|
46
43
|
}
|
|
47
|
-
this.isFileLikeDriver = driver instanceof require_file.FileDriver || driver instanceof require_s3.S3Driver;
|
|
48
44
|
}
|
|
49
45
|
/**
|
|
50
46
|
* Find all rows matching the query options
|
|
@@ -54,10 +50,8 @@ var TableRepository = class {
|
|
|
54
50
|
async find(options) {
|
|
55
51
|
return this.cache.getOrSetWithTableConfig(this.tableName, "find", options, async () => {
|
|
56
52
|
const dbOptions = this.mapOptionsToDb(options);
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
else rows = this.mapRows(await this.findSQL(dbOptions));
|
|
60
|
-
if (options?.with) rows = await this.loadRelations(rows, options.with);
|
|
53
|
+
const rows = this.mapRows(await this.findSQL(dbOptions));
|
|
54
|
+
if (options?.with) return this.loadRelations(rows, options.with);
|
|
61
55
|
this.cacheEntities(rows);
|
|
62
56
|
return rows;
|
|
63
57
|
}, this.tableCacheConfig);
|
|
@@ -81,11 +75,13 @@ var TableRepository = class {
|
|
|
81
75
|
...this.mapOptionsToDb(options),
|
|
82
76
|
take: 1
|
|
83
77
|
};
|
|
84
|
-
|
|
85
|
-
if (this.isFileLikeDriver) rows = this.mapRows(this.findFile(opts));
|
|
86
|
-
else rows = this.mapRows(await this.findSQL(opts));
|
|
78
|
+
const rows = this.mapRows(await this.findSQL(opts));
|
|
87
79
|
if (rows.length === 0) return null;
|
|
88
|
-
if (options?.with)
|
|
80
|
+
if (options?.with) {
|
|
81
|
+
const row = (await this.loadRelations(rows, options.with))[0] ?? null;
|
|
82
|
+
if (row) this.cacheEntity(row);
|
|
83
|
+
return row;
|
|
84
|
+
}
|
|
89
85
|
const row = rows[0] ?? null;
|
|
90
86
|
if (row) this.cacheEntity(row);
|
|
91
87
|
return row;
|
|
@@ -101,22 +97,14 @@ var TableRepository = class {
|
|
|
101
97
|
if (!single) throw new require_errors.QueryError("Insert data cannot be empty");
|
|
102
98
|
this.cache.invalidateTable(this.tableName);
|
|
103
99
|
const cleaned = this.toDbKeys(this.cleanData(single));
|
|
104
|
-
if (this.isFileLikeDriver) {
|
|
105
|
-
const id = this.driver.insertRow(this.tableName, cleaned);
|
|
106
|
-
const pk = this.registry.getPrimaryKey(this.tableName);
|
|
107
|
-
if (pk) cleaned[pk] = id;
|
|
108
|
-
const result = this.toCodeKeys(cleaned);
|
|
109
|
-
this.cacheEntity(result);
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
100
|
const params = [];
|
|
113
101
|
const sql = require_sql_compiler.compileInsert(this.tableName, cleaned, params);
|
|
114
102
|
const result = await this.driver.execute(sql, params);
|
|
115
103
|
const pk = this.registry.getPrimaryKey(this.tableName);
|
|
116
104
|
if (pk && result.insertId) cleaned[pk] = result.insertId;
|
|
117
|
-
const
|
|
118
|
-
this.cacheEntity(
|
|
119
|
-
return
|
|
105
|
+
const [mappedResult] = this.mapRows([cleaned]);
|
|
106
|
+
this.cacheEntity(mappedResult);
|
|
107
|
+
return mappedResult;
|
|
120
108
|
}
|
|
121
109
|
/**
|
|
122
110
|
* Insert multiple rows
|
|
@@ -126,11 +114,6 @@ var TableRepository = class {
|
|
|
126
114
|
async insertMany(data) {
|
|
127
115
|
if (data.length === 0) return [];
|
|
128
116
|
this.cache.invalidateTable(this.tableName);
|
|
129
|
-
if (this.isFileLikeDriver) {
|
|
130
|
-
const results = [];
|
|
131
|
-
for (const item of data) results.push(await this.insert(item));
|
|
132
|
-
return results;
|
|
133
|
-
}
|
|
134
117
|
const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));
|
|
135
118
|
const params = [];
|
|
136
119
|
const sql = require_sql_compiler.compileBulkInsert(this.tableName, cleanedData, params);
|
|
@@ -154,11 +137,6 @@ var TableRepository = class {
|
|
|
154
137
|
this.cache.invalidateTable(this.tableName);
|
|
155
138
|
const cleaned = this.toDbKeys(this.cleanData(options.data));
|
|
156
139
|
const dbWhere = this.mapWhereToDb(options.where);
|
|
157
|
-
if (this.isFileLikeDriver) {
|
|
158
|
-
const filter = this.buildFileFilter(dbWhere);
|
|
159
|
-
this.driver.updateRows(this.tableName, filter, cleaned);
|
|
160
|
-
return this.find({ where: options.where });
|
|
161
|
-
}
|
|
162
140
|
const params = [];
|
|
163
141
|
const sql = require_sql_compiler.compileUpdate(this.tableName, cleaned, dbWhere, params);
|
|
164
142
|
await this.driver.execute(sql, params);
|
|
@@ -173,10 +151,6 @@ var TableRepository = class {
|
|
|
173
151
|
if (!options.where || Object.keys(options.where).length === 0) throw new require_errors.QueryError("Delete requires a where clause");
|
|
174
152
|
this.cache.invalidateTable(this.tableName);
|
|
175
153
|
const dbWhere = this.mapWhereToDb(options.where);
|
|
176
|
-
if (this.isFileLikeDriver) {
|
|
177
|
-
const filter = this.buildFileFilter(dbWhere);
|
|
178
|
-
return this.driver.deleteRows(this.tableName, filter);
|
|
179
|
-
}
|
|
180
154
|
const params = [];
|
|
181
155
|
const sql = require_sql_compiler.compileDelete(this.tableName, dbWhere, params);
|
|
182
156
|
return (await this.driver.execute(sql, params)).affectedRows;
|
|
@@ -189,10 +163,6 @@ var TableRepository = class {
|
|
|
189
163
|
async count(options) {
|
|
190
164
|
return this.cache.getOrSetWithTableConfig(this.tableName, "count", options, async () => {
|
|
191
165
|
const dbWhere = options?.where ? this.mapWhereToDb(options.where) : void 0;
|
|
192
|
-
if (this.isFileLikeDriver) {
|
|
193
|
-
const filter = dbWhere ? this.buildFileFilter(dbWhere) : void 0;
|
|
194
|
-
return this.driver.countRows(this.tableName, filter);
|
|
195
|
-
}
|
|
196
166
|
const params = [];
|
|
197
167
|
let sql = `SELECT COUNT(*) as count FROM \`${this.tableName}\``;
|
|
198
168
|
if (dbWhere && Object.keys(dbWhere).length > 0) sql += ` WHERE ${require_sql_compiler.compileWhere(dbWhere, params)}`;
|
|
@@ -228,10 +198,6 @@ var TableRepository = class {
|
|
|
228
198
|
*/
|
|
229
199
|
async truncate() {
|
|
230
200
|
this.cache.invalidateTable(this.tableName);
|
|
231
|
-
if (this.isFileLikeDriver) {
|
|
232
|
-
this.driver.truncateTable(this.tableName);
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
201
|
await this.driver.execute(`DELETE FROM \`${this.tableName}\``);
|
|
236
202
|
}
|
|
237
203
|
async findSQL(options) {
|
|
@@ -245,37 +211,6 @@ var TableRepository = class {
|
|
|
245
211
|
}, params);
|
|
246
212
|
return this.driver.query(sql, params);
|
|
247
213
|
}
|
|
248
|
-
findFile(options) {
|
|
249
|
-
const fd = this.driver;
|
|
250
|
-
const filter = options?.where ? this.buildFileFilter(options.where) : void 0;
|
|
251
|
-
let rows = fd.findRows(this.tableName, filter);
|
|
252
|
-
if (options?.select) {
|
|
253
|
-
const selectSet = new Set(options.select);
|
|
254
|
-
rows = rows.map((row) => {
|
|
255
|
-
const filtered = {};
|
|
256
|
-
for (const key of selectSet) filtered[key] = row[key];
|
|
257
|
-
return filtered;
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
if (options?.orderBy) {
|
|
261
|
-
const entries = Object.entries(options.orderBy);
|
|
262
|
-
rows.sort((a, b) => {
|
|
263
|
-
for (const [col, dir] of entries) {
|
|
264
|
-
const av = a[col];
|
|
265
|
-
const bv = b[col];
|
|
266
|
-
if (av < bv) return dir === "asc" ? -1 : 1;
|
|
267
|
-
if (av > bv) return dir === "asc" ? 1 : -1;
|
|
268
|
-
}
|
|
269
|
-
return 0;
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
if (options?.skip) rows = rows.slice(options.skip);
|
|
273
|
-
if (options?.take) rows = rows.slice(0, options.take);
|
|
274
|
-
return rows;
|
|
275
|
-
}
|
|
276
|
-
buildFileFilter(where) {
|
|
277
|
-
return (row) => this.matchWhere(row, where);
|
|
278
|
-
}
|
|
279
214
|
matchWhere(row, where) {
|
|
280
215
|
for (const [key, value] of Object.entries(where)) {
|
|
281
216
|
if (key === "OR" && Array.isArray(value)) {
|
|
@@ -354,11 +289,6 @@ var TableRepository = class {
|
|
|
354
289
|
return rows;
|
|
355
290
|
}
|
|
356
291
|
async findRelated(tableName, column, ids, options) {
|
|
357
|
-
if (this.isFileLikeDriver) {
|
|
358
|
-
const fd = this.driver;
|
|
359
|
-
const filter = (row) => ids.includes(row[column]);
|
|
360
|
-
return fd.findRows(tableName, filter);
|
|
361
|
-
}
|
|
362
292
|
const params = [];
|
|
363
293
|
const placeholders = ids.map(() => "?").join(", ");
|
|
364
294
|
params.push(...ids);
|
|
@@ -374,8 +304,7 @@ var TableRepository = class {
|
|
|
374
304
|
const cleaned = {};
|
|
375
305
|
const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));
|
|
376
306
|
const codeKeys = new Set(Object.keys(this.columnMap));
|
|
377
|
-
const
|
|
378
|
-
for (const [key, value] of Object.entries(data)) if (codeKeys.has(key) || dbColumnNames.has(key)) if (shouldSerialize && (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) && value != null && typeof value === "object") cleaned[key] = JSON.stringify(value);
|
|
307
|
+
for (const [key, value] of Object.entries(data)) if (codeKeys.has(key) || dbColumnNames.has(key)) if ((this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) && value != null && typeof value === "object") cleaned[key] = JSON.stringify(value);
|
|
379
308
|
else cleaned[key] = value;
|
|
380
309
|
return cleaned;
|
|
381
310
|
}
|
|
@@ -427,7 +356,7 @@ var TableRepository = class {
|
|
|
427
356
|
return mapped;
|
|
428
357
|
}
|
|
429
358
|
mapRows(rows) {
|
|
430
|
-
const shouldDeserialize =
|
|
359
|
+
const shouldDeserialize = this.jsonCodeKeys.size > 0 || this.dateColumns.size > 0;
|
|
431
360
|
if (!this.hasAliases && !shouldDeserialize) return rows;
|
|
432
361
|
return rows.map((row) => {
|
|
433
362
|
const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repository.cjs","names":["QueryError","FileDriver","S3Driver","compileInsert","compileBulkInsert","compileUpdate","compileDelete","compileWhere","compileSelect"],"sources":["../../src/core/repository.ts"],"sourcesContent":["import type { CacheManager } from \"../cache\";\nimport { FileDriver } from \"../drivers/file\";\nimport { S3Driver } from \"../drivers/s3\";\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 private tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number };\n private jsonColumns: Set<string>;\n private jsonCodeKeys: Set<string>;\n private isFileLikeDriver: boolean;\n private dateColumns: Set<string>;\n\n constructor(\n tableName: string,\n driver: DatabaseDriver,\n cache: CacheManager,\n registry: SchemaRegistry,\n tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number },\n ) {\n this.tableName = tableName;\n this.driver = driver;\n this.cache = cache;\n this.registry = registry;\n this.tableCacheConfig = tableCacheConfig;\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 this.jsonColumns = new Set(\n meta.columns.filter((c) => c.type === \"json\" || c.type === \"array\").map((c) => c.name),\n );\n this.jsonCodeKeys = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"json\" || col.type === \"array\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.jsonCodeKeys.add(codeKey);\n }\n }\n this.dateColumns = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"datetime\" || col.type === \"timestamp\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.dateColumns.add(codeKey);\n }\n }\n this.isFileLikeDriver = driver instanceof FileDriver || driver instanceof S3Driver;\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.getOrSetWithTableConfig(\n this.tableName,\n \"find\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n let rows: T[];\n if (this.isFileLikeDriver) {\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 this.tableCacheConfig,\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.getOrSetWithTableConfig(\n this.tableName,\n \"findFirst\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n const opts = { ...dbOptions, take: 1 };\n let rows: T[];\n if (this.isFileLikeDriver) {\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 this.tableCacheConfig,\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.isFileLikeDriver) {\n const id = (this.driver as FileDriver | S3Driver).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.isFileLikeDriver) {\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.isFileLikeDriver) {\n const filter = this.buildFileFilter(dbWhere);\n (this.driver as FileDriver | S3Driver).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.isFileLikeDriver) {\n const filter = this.buildFileFilter(dbWhere);\n return (this.driver as FileDriver | S3Driver).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.getOrSetWithTableConfig(\n this.tableName,\n \"count\",\n options,\n async () => {\n const dbWhere = options?.where\n ? this.mapWhereToDb(options.where as WhereClause)\n : undefined;\n\n if (this.isFileLikeDriver) {\n const filter = dbWhere ? this.buildFileFilter(dbWhere) : undefined;\n return (this.driver as FileDriver | S3Driver).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 this.tableCacheConfig,\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.isFileLikeDriver) {\n (this.driver as FileDriver | S3Driver).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 | S3Driver;\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.isFileLikeDriver) {\n const fd = this.driver as FileDriver | S3Driver;\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 const shouldSerialize = !this.isFileLikeDriver;\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (codeKeys.has(key) || dbColumnNames.has(key)) {\n if (\n shouldSerialize &&\n (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) &&\n value != null &&\n typeof value === \"object\"\n ) {\n cleaned[key] = JSON.stringify(value);\n } else {\n cleaned[key] = value;\n }\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 const shouldDeserialize =\n (this.jsonCodeKeys.size > 0 || this.dateColumns.size > 0) && !this.isFileLikeDriver;\n if (!this.hasAliases && !shouldDeserialize) {\n return rows as T[];\n }\n return rows.map((row) => {\n const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };\n if (shouldDeserialize) {\n for (const key of this.jsonCodeKeys) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n try {\n mapped[key] = JSON.parse(val);\n } catch {}\n }\n }\n for (const key of this.dateColumns) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n mapped[key] = new Date(val);\n } else if (typeof val === \"number\") {\n mapped[key] = new Date(val);\n }\n }\n }\n return mapped as T;\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"repository.cjs","names":["QueryError","compileInsert","compileBulkInsert","compileUpdate","compileDelete","compileWhere","compileSelect"],"sources":["../../src/core/repository.ts"],"sourcesContent":["import type { CacheManager } from \"../cache\";\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 private tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number };\n private jsonColumns: Set<string>;\n private jsonCodeKeys: Set<string>;\n private dateColumns: Set<string>;\n\n constructor(\n tableName: string,\n driver: DatabaseDriver,\n cache: CacheManager,\n registry: SchemaRegistry,\n tableCacheConfig?: { enabled: boolean; ttl?: number; maxTtl?: number },\n ) {\n this.tableName = tableName;\n this.driver = driver;\n this.cache = cache;\n this.registry = registry;\n this.tableCacheConfig = tableCacheConfig;\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 this.jsonColumns = new Set(\n meta.columns.filter((c) => c.type === \"json\" || c.type === \"array\").map((c) => c.name),\n );\n this.jsonCodeKeys = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"json\" || col.type === \"array\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.jsonCodeKeys.add(codeKey);\n }\n }\n this.dateColumns = new Set<string>();\n for (const col of meta.columns) {\n if (col.type === \"datetime\" || col.type === \"timestamp\") {\n const codeKey = this.reverseColumnMap[col.name] ?? col.name;\n this.dateColumns.add(codeKey);\n }\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.getOrSetWithTableConfig(\n this.tableName,\n \"find\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n const rows = this.mapRows(await this.findSQL(dbOptions as QueryOptions<T>));\n if (options?.with) {\n return this.loadRelations(rows, options.with);\n }\n this.cacheEntities(rows);\n return rows;\n },\n this.tableCacheConfig,\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.getOrSetWithTableConfig(\n this.tableName,\n \"findFirst\",\n options,\n async () => {\n const dbOptions = this.mapOptionsToDb(options);\n const opts = { ...dbOptions, take: 1 };\n const rows = this.mapRows(await this.findSQL(opts as QueryOptions<T>));\n if (rows.length === 0) {\n return null;\n }\n if (options?.with) {\n const loaded = await this.loadRelations(rows, options.with);\n const row = loaded[0] ?? null;\n if (row) {\n this.cacheEntity(row);\n }\n return row;\n }\n const row = rows[0] ?? null;\n if (row) {\n this.cacheEntity(row);\n }\n return row;\n },\n this.tableCacheConfig,\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 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 [mappedResult] = this.mapRows([cleaned]) as [T];\n this.cacheEntity(mappedResult);\n return mappedResult;\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 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 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 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.getOrSetWithTableConfig(\n this.tableName,\n \"count\",\n options,\n async () => {\n const dbWhere = options?.where\n ? this.mapWhereToDb(options.where as WhereClause)\n : undefined;\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 this.tableCacheConfig,\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 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 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 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 const shouldSerialize = true;\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (codeKeys.has(key) || dbColumnNames.has(key)) {\n if (\n shouldSerialize &&\n (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) &&\n value != null &&\n typeof value === \"object\"\n ) {\n cleaned[key] = JSON.stringify(value);\n } else {\n cleaned[key] = value;\n }\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 const shouldDeserialize = this.jsonCodeKeys.size > 0 || this.dateColumns.size > 0;\n if (!this.hasAliases && !shouldDeserialize) {\n return rows as T[];\n }\n return rows.map((row) => {\n const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };\n if (shouldDeserialize) {\n for (const key of this.jsonCodeKeys) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n try {\n mapped[key] = JSON.parse(val);\n } catch {}\n }\n }\n for (const key of this.dateColumns) {\n const val = mapped[key];\n if (typeof val === \"string\") {\n mapped[key] = new Date(val);\n } else if (typeof val === \"number\") {\n mapped[key] = new Date(val);\n }\n }\n }\n return mapped as T;\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -19,7 +19,6 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
|
|
|
19
19
|
private tableCacheConfig?;
|
|
20
20
|
private jsonColumns;
|
|
21
21
|
private jsonCodeKeys;
|
|
22
|
-
private isFileLikeDriver;
|
|
23
22
|
private dateColumns;
|
|
24
23
|
constructor(tableName: string, driver: DatabaseDriver, cache: CacheManager, registry: SchemaRegistry, tableCacheConfig?: {
|
|
25
24
|
enabled: boolean;
|
|
@@ -98,8 +97,6 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
|
|
|
98
97
|
*/
|
|
99
98
|
truncate(): Promise<void>;
|
|
100
99
|
private findSQL;
|
|
101
|
-
private findFile;
|
|
102
|
-
private buildFileFilter;
|
|
103
100
|
private matchWhere;
|
|
104
101
|
private loadRelations;
|
|
105
102
|
private findRelated;
|
|
@@ -19,7 +19,6 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
|
|
|
19
19
|
private tableCacheConfig?;
|
|
20
20
|
private jsonColumns;
|
|
21
21
|
private jsonCodeKeys;
|
|
22
|
-
private isFileLikeDriver;
|
|
23
22
|
private dateColumns;
|
|
24
23
|
constructor(tableName: string, driver: DatabaseDriver, cache: CacheManager, registry: SchemaRegistry, tableCacheConfig?: {
|
|
25
24
|
enabled: boolean;
|
|
@@ -98,8 +97,6 @@ declare class TableRepository<T extends Record<string, any>> implements Reposito
|
|
|
98
97
|
*/
|
|
99
98
|
truncate(): Promise<void>;
|
|
100
99
|
private findSQL;
|
|
101
|
-
private findFile;
|
|
102
|
-
private buildFileFilter;
|
|
103
100
|
private matchWhere;
|
|
104
101
|
private loadRelations;
|
|
105
102
|
private findRelated;
|
package/dist/core/repository.mjs
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { __esmMin } from "../_virtual/_rolldown/runtime.mjs";
|
|
2
2
|
import { QueryError, init_errors } from "../errors.mjs";
|
|
3
|
-
import { FileDriver, init_file } from "../drivers/file.mjs";
|
|
4
3
|
import { compileBulkInsert, compileDelete, compileInsert, compileSelect, compileUpdate, compileWhere, init_sql_compiler } from "../drivers/sql-compiler.mjs";
|
|
5
|
-
import { S3Driver, init_s3 } from "../drivers/s3.mjs";
|
|
6
4
|
//#region src/core/repository.ts
|
|
7
5
|
var TableRepository;
|
|
8
6
|
var init_repository = __esmMin((() => {
|
|
9
|
-
init_file();
|
|
10
|
-
init_s3();
|
|
11
7
|
init_sql_compiler();
|
|
12
8
|
init_errors();
|
|
13
9
|
TableRepository = class {
|
|
@@ -22,7 +18,6 @@ var init_repository = __esmMin((() => {
|
|
|
22
18
|
tableCacheConfig;
|
|
23
19
|
jsonColumns;
|
|
24
20
|
jsonCodeKeys;
|
|
25
|
-
isFileLikeDriver;
|
|
26
21
|
dateColumns;
|
|
27
22
|
constructor(tableName, driver, cache, registry, tableCacheConfig) {
|
|
28
23
|
this.tableName = tableName;
|
|
@@ -47,7 +42,6 @@ var init_repository = __esmMin((() => {
|
|
|
47
42
|
const codeKey = this.reverseColumnMap[col.name] ?? col.name;
|
|
48
43
|
this.dateColumns.add(codeKey);
|
|
49
44
|
}
|
|
50
|
-
this.isFileLikeDriver = driver instanceof FileDriver || driver instanceof S3Driver;
|
|
51
45
|
}
|
|
52
46
|
/**
|
|
53
47
|
* Find all rows matching the query options
|
|
@@ -57,10 +51,8 @@ var init_repository = __esmMin((() => {
|
|
|
57
51
|
async find(options) {
|
|
58
52
|
return this.cache.getOrSetWithTableConfig(this.tableName, "find", options, async () => {
|
|
59
53
|
const dbOptions = this.mapOptionsToDb(options);
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
else rows = this.mapRows(await this.findSQL(dbOptions));
|
|
63
|
-
if (options?.with) rows = await this.loadRelations(rows, options.with);
|
|
54
|
+
const rows = this.mapRows(await this.findSQL(dbOptions));
|
|
55
|
+
if (options?.with) return this.loadRelations(rows, options.with);
|
|
64
56
|
this.cacheEntities(rows);
|
|
65
57
|
return rows;
|
|
66
58
|
}, this.tableCacheConfig);
|
|
@@ -84,11 +76,13 @@ var init_repository = __esmMin((() => {
|
|
|
84
76
|
...this.mapOptionsToDb(options),
|
|
85
77
|
take: 1
|
|
86
78
|
};
|
|
87
|
-
|
|
88
|
-
if (this.isFileLikeDriver) rows = this.mapRows(this.findFile(opts));
|
|
89
|
-
else rows = this.mapRows(await this.findSQL(opts));
|
|
79
|
+
const rows = this.mapRows(await this.findSQL(opts));
|
|
90
80
|
if (rows.length === 0) return null;
|
|
91
|
-
if (options?.with)
|
|
81
|
+
if (options?.with) {
|
|
82
|
+
const row = (await this.loadRelations(rows, options.with))[0] ?? null;
|
|
83
|
+
if (row) this.cacheEntity(row);
|
|
84
|
+
return row;
|
|
85
|
+
}
|
|
92
86
|
const row = rows[0] ?? null;
|
|
93
87
|
if (row) this.cacheEntity(row);
|
|
94
88
|
return row;
|
|
@@ -104,22 +98,14 @@ var init_repository = __esmMin((() => {
|
|
|
104
98
|
if (!single) throw new QueryError("Insert data cannot be empty");
|
|
105
99
|
this.cache.invalidateTable(this.tableName);
|
|
106
100
|
const cleaned = this.toDbKeys(this.cleanData(single));
|
|
107
|
-
if (this.isFileLikeDriver) {
|
|
108
|
-
const id = this.driver.insertRow(this.tableName, cleaned);
|
|
109
|
-
const pk = this.registry.getPrimaryKey(this.tableName);
|
|
110
|
-
if (pk) cleaned[pk] = id;
|
|
111
|
-
const result = this.toCodeKeys(cleaned);
|
|
112
|
-
this.cacheEntity(result);
|
|
113
|
-
return result;
|
|
114
|
-
}
|
|
115
101
|
const params = [];
|
|
116
102
|
const sql = compileInsert(this.tableName, cleaned, params);
|
|
117
103
|
const result = await this.driver.execute(sql, params);
|
|
118
104
|
const pk = this.registry.getPrimaryKey(this.tableName);
|
|
119
105
|
if (pk && result.insertId) cleaned[pk] = result.insertId;
|
|
120
|
-
const
|
|
121
|
-
this.cacheEntity(
|
|
122
|
-
return
|
|
106
|
+
const [mappedResult] = this.mapRows([cleaned]);
|
|
107
|
+
this.cacheEntity(mappedResult);
|
|
108
|
+
return mappedResult;
|
|
123
109
|
}
|
|
124
110
|
/**
|
|
125
111
|
* Insert multiple rows
|
|
@@ -129,11 +115,6 @@ var init_repository = __esmMin((() => {
|
|
|
129
115
|
async insertMany(data) {
|
|
130
116
|
if (data.length === 0) return [];
|
|
131
117
|
this.cache.invalidateTable(this.tableName);
|
|
132
|
-
if (this.isFileLikeDriver) {
|
|
133
|
-
const results = [];
|
|
134
|
-
for (const item of data) results.push(await this.insert(item));
|
|
135
|
-
return results;
|
|
136
|
-
}
|
|
137
118
|
const cleanedData = data.map((item) => this.toDbKeys(this.cleanData(item)));
|
|
138
119
|
const params = [];
|
|
139
120
|
const sql = compileBulkInsert(this.tableName, cleanedData, params);
|
|
@@ -157,11 +138,6 @@ var init_repository = __esmMin((() => {
|
|
|
157
138
|
this.cache.invalidateTable(this.tableName);
|
|
158
139
|
const cleaned = this.toDbKeys(this.cleanData(options.data));
|
|
159
140
|
const dbWhere = this.mapWhereToDb(options.where);
|
|
160
|
-
if (this.isFileLikeDriver) {
|
|
161
|
-
const filter = this.buildFileFilter(dbWhere);
|
|
162
|
-
this.driver.updateRows(this.tableName, filter, cleaned);
|
|
163
|
-
return this.find({ where: options.where });
|
|
164
|
-
}
|
|
165
141
|
const params = [];
|
|
166
142
|
const sql = compileUpdate(this.tableName, cleaned, dbWhere, params);
|
|
167
143
|
await this.driver.execute(sql, params);
|
|
@@ -176,10 +152,6 @@ var init_repository = __esmMin((() => {
|
|
|
176
152
|
if (!options.where || Object.keys(options.where).length === 0) throw new QueryError("Delete requires a where clause");
|
|
177
153
|
this.cache.invalidateTable(this.tableName);
|
|
178
154
|
const dbWhere = this.mapWhereToDb(options.where);
|
|
179
|
-
if (this.isFileLikeDriver) {
|
|
180
|
-
const filter = this.buildFileFilter(dbWhere);
|
|
181
|
-
return this.driver.deleteRows(this.tableName, filter);
|
|
182
|
-
}
|
|
183
155
|
const params = [];
|
|
184
156
|
const sql = compileDelete(this.tableName, dbWhere, params);
|
|
185
157
|
return (await this.driver.execute(sql, params)).affectedRows;
|
|
@@ -192,10 +164,6 @@ var init_repository = __esmMin((() => {
|
|
|
192
164
|
async count(options) {
|
|
193
165
|
return this.cache.getOrSetWithTableConfig(this.tableName, "count", options, async () => {
|
|
194
166
|
const dbWhere = options?.where ? this.mapWhereToDb(options.where) : void 0;
|
|
195
|
-
if (this.isFileLikeDriver) {
|
|
196
|
-
const filter = dbWhere ? this.buildFileFilter(dbWhere) : void 0;
|
|
197
|
-
return this.driver.countRows(this.tableName, filter);
|
|
198
|
-
}
|
|
199
167
|
const params = [];
|
|
200
168
|
let sql = `SELECT COUNT(*) as count FROM \`${this.tableName}\``;
|
|
201
169
|
if (dbWhere && Object.keys(dbWhere).length > 0) sql += ` WHERE ${compileWhere(dbWhere, params)}`;
|
|
@@ -231,10 +199,6 @@ var init_repository = __esmMin((() => {
|
|
|
231
199
|
*/
|
|
232
200
|
async truncate() {
|
|
233
201
|
this.cache.invalidateTable(this.tableName);
|
|
234
|
-
if (this.isFileLikeDriver) {
|
|
235
|
-
this.driver.truncateTable(this.tableName);
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
202
|
await this.driver.execute(`DELETE FROM \`${this.tableName}\``);
|
|
239
203
|
}
|
|
240
204
|
async findSQL(options) {
|
|
@@ -248,37 +212,6 @@ var init_repository = __esmMin((() => {
|
|
|
248
212
|
}, params);
|
|
249
213
|
return this.driver.query(sql, params);
|
|
250
214
|
}
|
|
251
|
-
findFile(options) {
|
|
252
|
-
const fd = this.driver;
|
|
253
|
-
const filter = options?.where ? this.buildFileFilter(options.where) : void 0;
|
|
254
|
-
let rows = fd.findRows(this.tableName, filter);
|
|
255
|
-
if (options?.select) {
|
|
256
|
-
const selectSet = new Set(options.select);
|
|
257
|
-
rows = rows.map((row) => {
|
|
258
|
-
const filtered = {};
|
|
259
|
-
for (const key of selectSet) filtered[key] = row[key];
|
|
260
|
-
return filtered;
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
if (options?.orderBy) {
|
|
264
|
-
const entries = Object.entries(options.orderBy);
|
|
265
|
-
rows.sort((a, b) => {
|
|
266
|
-
for (const [col, dir] of entries) {
|
|
267
|
-
const av = a[col];
|
|
268
|
-
const bv = b[col];
|
|
269
|
-
if (av < bv) return dir === "asc" ? -1 : 1;
|
|
270
|
-
if (av > bv) return dir === "asc" ? 1 : -1;
|
|
271
|
-
}
|
|
272
|
-
return 0;
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
if (options?.skip) rows = rows.slice(options.skip);
|
|
276
|
-
if (options?.take) rows = rows.slice(0, options.take);
|
|
277
|
-
return rows;
|
|
278
|
-
}
|
|
279
|
-
buildFileFilter(where) {
|
|
280
|
-
return (row) => this.matchWhere(row, where);
|
|
281
|
-
}
|
|
282
215
|
matchWhere(row, where) {
|
|
283
216
|
for (const [key, value] of Object.entries(where)) {
|
|
284
217
|
if (key === "OR" && Array.isArray(value)) {
|
|
@@ -357,11 +290,6 @@ var init_repository = __esmMin((() => {
|
|
|
357
290
|
return rows;
|
|
358
291
|
}
|
|
359
292
|
async findRelated(tableName, column, ids, options) {
|
|
360
|
-
if (this.isFileLikeDriver) {
|
|
361
|
-
const fd = this.driver;
|
|
362
|
-
const filter = (row) => ids.includes(row[column]);
|
|
363
|
-
return fd.findRows(tableName, filter);
|
|
364
|
-
}
|
|
365
293
|
const params = [];
|
|
366
294
|
const placeholders = ids.map(() => "?").join(", ");
|
|
367
295
|
params.push(...ids);
|
|
@@ -377,8 +305,7 @@ var init_repository = __esmMin((() => {
|
|
|
377
305
|
const cleaned = {};
|
|
378
306
|
const dbColumnNames = new Set(this.meta.columns.map((c) => c.name));
|
|
379
307
|
const codeKeys = new Set(Object.keys(this.columnMap));
|
|
380
|
-
const
|
|
381
|
-
for (const [key, value] of Object.entries(data)) if (codeKeys.has(key) || dbColumnNames.has(key)) if (shouldSerialize && (this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) && value != null && typeof value === "object") cleaned[key] = JSON.stringify(value);
|
|
308
|
+
for (const [key, value] of Object.entries(data)) if (codeKeys.has(key) || dbColumnNames.has(key)) if ((this.jsonCodeKeys.has(key) || this.jsonColumns.has(key)) && value != null && typeof value === "object") cleaned[key] = JSON.stringify(value);
|
|
382
309
|
else cleaned[key] = value;
|
|
383
310
|
return cleaned;
|
|
384
311
|
}
|
|
@@ -430,7 +357,7 @@ var init_repository = __esmMin((() => {
|
|
|
430
357
|
return mapped;
|
|
431
358
|
}
|
|
432
359
|
mapRows(rows) {
|
|
433
|
-
const shouldDeserialize =
|
|
360
|
+
const shouldDeserialize = this.jsonCodeKeys.size > 0 || this.dateColumns.size > 0;
|
|
434
361
|
if (!this.hasAliases && !shouldDeserialize) return rows;
|
|
435
362
|
return rows.map((row) => {
|
|
436
363
|
const mapped = this.hasAliases ? this.toCodeKeys(row) : { ...row };
|