forge-sql-orm 2.0.12 → 2.0.13
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/README.md +10 -24
- package/dist/ForgeSQLORM.js +17 -10
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +17 -10
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/selectAliased.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/package.json +8 -18
- package/src/core/ForgeSQLCrudOperations.ts +1 -1
- package/src/core/ForgeSQLORM.ts +5 -4
- package/src/lib/drizzle/extensions/selectAliased.ts +56 -58
- package/src/lib/drizzle/extensions/types.d.ts +13 -13
- package/src/utils/sqlUtils.ts +57 -39
- package/dist-cli/cli.js +0 -965
- package/dist-cli/cli.js.map +0 -1
- package/dist-cli/cli.mjs +0 -964
- package/dist-cli/cli.mjs.map +0 -1
- package/dist-cli/forgeSqlOrmCLI.js +0 -19
package/src/core/ForgeSQLORM.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { drizzle, MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from "drizz
|
|
|
10
10
|
import { forgeDriver } from "../utils/forgeDriver";
|
|
11
11
|
import type { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
12
12
|
import { MySqlSelectBuilder } from "drizzle-orm/mysql-core";
|
|
13
|
-
import {patchDbWithSelectAliased} from "../lib/drizzle/extensions/selectAliased";
|
|
13
|
+
import { patchDbWithSelectAliased } from "../lib/drizzle/extensions/selectAliased";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Implementation of ForgeSQLORM that uses Drizzle ORM for query building.
|
|
@@ -37,7 +37,9 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
37
37
|
console.debug("Initializing ForgeSQLORM...");
|
|
38
38
|
}
|
|
39
39
|
// Initialize Drizzle instance with our custom driver
|
|
40
|
-
this.drizzle =
|
|
40
|
+
this.drizzle = patchDbWithSelectAliased(
|
|
41
|
+
drizzle(forgeDriver, { logger: newOptions.logRawSqlQuery }),
|
|
42
|
+
);
|
|
41
43
|
this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);
|
|
42
44
|
this.fetchOperations = new ForgeSQLSelectOperations(newOptions);
|
|
43
45
|
} catch (error) {
|
|
@@ -190,8 +192,7 @@ class ForgeSQLORM implements ForgeSqlOperation {
|
|
|
190
192
|
selectDistinct<TSelection extends SelectedFields>(
|
|
191
193
|
fields: TSelection,
|
|
192
194
|
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
193
|
-
return this.ormInstance
|
|
194
|
-
.selectDistinct(fields);
|
|
195
|
+
return this.ormInstance.selectDistinct(fields);
|
|
195
196
|
}
|
|
196
197
|
|
|
197
198
|
/**
|
|
@@ -1,74 +1,72 @@
|
|
|
1
|
-
import {MySqlRemoteDatabase} from "drizzle-orm/mysql-proxy";
|
|
2
|
-
import type {SelectedFields} from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
3
|
-
import {applyFromDriverTransform, mapSelectFieldsWithAlias} from "../../..";
|
|
4
|
-
import {MySqlSelectBuilder} from "drizzle-orm/mysql-core";
|
|
5
|
-
import {MySqlRemotePreparedQueryHKT} from "drizzle-orm/mysql-proxy";
|
|
1
|
+
import { MySqlRemoteDatabase } from "drizzle-orm/mysql-proxy";
|
|
2
|
+
import type { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
3
|
+
import { applyFromDriverTransform, mapSelectFieldsWithAlias } from "../../..";
|
|
4
|
+
import { MySqlSelectBuilder } from "drizzle-orm/mysql-core";
|
|
5
|
+
import { MySqlRemotePreparedQueryHKT } from "drizzle-orm/mysql-proxy";
|
|
6
6
|
|
|
7
7
|
function createAliasedSelectBuilder<TSelection extends SelectedFields>(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
db: MySqlRemoteDatabase<any>,
|
|
9
|
+
fields: TSelection,
|
|
10
|
+
selectFn: (selections: any) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>,
|
|
11
11
|
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
const { selections, aliasMap } = mapSelectFieldsWithAlias(fields);
|
|
13
|
+
const builder = selectFn(selections);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
const wrapBuilder = (rawBuilder: any): any => {
|
|
16
|
+
return new Proxy(rawBuilder, {
|
|
17
|
+
get(target, prop, receiver) {
|
|
18
|
+
if (prop === "execute") {
|
|
19
|
+
return async (...args: any[]) => {
|
|
20
|
+
const rows = await target.execute(...args);
|
|
21
|
+
return applyFromDriverTransform(rows, selections, aliasMap);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
onrejected,
|
|
33
|
-
);
|
|
34
|
-
}
|
|
25
|
+
if (prop === "then") {
|
|
26
|
+
return (onfulfilled: any, onrejected: any) =>
|
|
27
|
+
target.execute().then((rows: unknown[]) => {
|
|
28
|
+
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
29
|
+
return onfulfilled?.(transformed);
|
|
30
|
+
}, onrejected);
|
|
31
|
+
}
|
|
35
32
|
|
|
36
|
-
|
|
33
|
+
const value = Reflect.get(target, prop, receiver);
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
if (typeof value === "function") {
|
|
36
|
+
return (...args: any[]) => {
|
|
37
|
+
const result = value.apply(target, args);
|
|
41
38
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
if (typeof result === "object" && result !== null && "execute" in result) {
|
|
40
|
+
return wrapBuilder(result);
|
|
41
|
+
}
|
|
45
42
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
return result;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
49
46
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
return value;
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
};
|
|
54
51
|
|
|
55
|
-
|
|
52
|
+
return wrapBuilder(builder);
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
export function patchDbWithSelectAliased(db: MySqlRemoteDatabase<any>): MySqlRemoteDatabase<any> & {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
56
|
+
selectAliased: <TSelection extends SelectedFields>(
|
|
57
|
+
fields: TSelection,
|
|
58
|
+
) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
59
|
+
selectAliasedDistinct: <TSelection extends SelectedFields>(
|
|
60
|
+
fields: TSelection,
|
|
61
|
+
) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
62
|
+
} {
|
|
63
|
+
db.selectAliased = function <TSelection extends SelectedFields>(fields: TSelection) {
|
|
64
|
+
return createAliasedSelectBuilder(db, fields, (selections) => db.select(selections));
|
|
65
|
+
};
|
|
68
66
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
db.selectAliasedDistinct = function <TSelection extends SelectedFields>(fields: TSelection) {
|
|
68
|
+
return createAliasedSelectBuilder(db, fields, (selections) => db.selectDistinct(selections));
|
|
69
|
+
};
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
}
|
|
71
|
+
return db;
|
|
72
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { SelectedFields } from
|
|
2
|
-
import {MySqlSelectBuilder} from "drizzle-orm/mysql-core";
|
|
3
|
-
import {MySqlRemotePreparedQueryHKT} from "drizzle-orm/mysql-proxy";
|
|
1
|
+
import { SelectedFields } from "drizzle-orm";
|
|
2
|
+
import { MySqlSelectBuilder } from "drizzle-orm/mysql-core";
|
|
3
|
+
import { MySqlRemotePreparedQueryHKT } from "drizzle-orm/mysql-proxy";
|
|
4
4
|
|
|
5
|
-
declare module
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
5
|
+
declare module "drizzle-orm/mysql-proxy" {
|
|
6
|
+
interface MySqlRemoteDatabase<> {
|
|
7
|
+
selectAliased<TSelection extends SelectedFields>(
|
|
8
|
+
fields: TSelection,
|
|
9
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
10
|
+
selectAliasedDistinct<TSelection extends SelectedFields>(
|
|
11
|
+
fields: TSelection,
|
|
12
|
+
): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
|
|
13
|
+
}
|
|
14
|
+
}
|
package/src/utils/sqlUtils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import moment from "moment";
|
|
2
|
-
import {AnyColumn, Column, isTable, SQL, sql, StringChunk} from "drizzle-orm";
|
|
3
|
-
import {AnyMySqlTable, MySqlCustomColumn} from "drizzle-orm/mysql-core/index";
|
|
2
|
+
import { AnyColumn, Column, isTable, SQL, sql, StringChunk } from "drizzle-orm";
|
|
3
|
+
import { AnyMySqlTable, MySqlCustomColumn } from "drizzle-orm/mysql-core/index";
|
|
4
4
|
import { PrimaryKeyBuilder } from "drizzle-orm/mysql-core/primary-keys";
|
|
5
5
|
import { AnyIndexBuilder } from "drizzle-orm/mysql-core/indexes";
|
|
6
6
|
import { CheckBuilder } from "drizzle-orm/mysql-core/checks";
|
|
@@ -9,7 +9,7 @@ import { UniqueConstraintBuilder } from "drizzle-orm/mysql-core/unique-constrain
|
|
|
9
9
|
import type { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
10
10
|
import { MySqlTable } from "drizzle-orm/mysql-core";
|
|
11
11
|
import { getTableName } from "drizzle-orm/table";
|
|
12
|
-
import {isSQLWrapper} from "drizzle-orm/sql/sql";
|
|
12
|
+
import { isSQLWrapper } from "drizzle-orm/sql/sql";
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Interface representing table metadata information
|
|
@@ -48,11 +48,11 @@ interface ConfigBuilderData {
|
|
|
48
48
|
* @returns Date object
|
|
49
49
|
*/
|
|
50
50
|
export const parseDateTime = (value: string, format: string): Date => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
const m = moment(value, format, true);
|
|
52
|
+
if (!m.isValid()) {
|
|
53
|
+
return moment(value).toDate();
|
|
54
|
+
}
|
|
55
|
+
return m.toDate();
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
/**
|
|
@@ -61,8 +61,8 @@ export const parseDateTime = (value: string, format: string): Date => {
|
|
|
61
61
|
* @returns The extracted alias or the original query if no alias found
|
|
62
62
|
*/
|
|
63
63
|
export function extractAlias(query: string): string {
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
const match = query.match(/\bas\s+(['"`]?)([\w*]+)\1$/i);
|
|
65
|
+
return match ? match[2] : query;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
@@ -189,8 +189,8 @@ export function getTableMetadata(table: AnyMySqlTable): MetadataInfo {
|
|
|
189
189
|
builders.foreignKeys = processForeignKeys(table, foreignKeysSymbol, extraSymbol);
|
|
190
190
|
|
|
191
191
|
// Process extra configuration if available
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
if (extraSymbol) {
|
|
193
|
+
// @ts-ignore
|
|
194
194
|
const extraConfigBuilder = table[extraSymbol];
|
|
195
195
|
if (extraConfigBuilder && typeof extraConfigBuilder === "function") {
|
|
196
196
|
const configBuilderData = extraConfigBuilder(table);
|
|
@@ -231,7 +231,7 @@ export function getTableMetadata(table: AnyMySqlTable): MetadataInfo {
|
|
|
231
231
|
}
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
|
|
234
|
+
return {
|
|
235
235
|
tableName: nameSymbol ? (table as any)[nameSymbol] : "",
|
|
236
236
|
columns: columnsSymbol ? ((table as any)[columnsSymbol] as Record<string, AnyColumn>) : {},
|
|
237
237
|
...builders,
|
|
@@ -269,7 +269,7 @@ function mapSelectTableToAlias(table: MySqlTable, aliasMap: AliasColumnMap): any
|
|
|
269
269
|
const uniqName = `a_${tableName}_${column.name}`;
|
|
270
270
|
const fieldAlias = sql.raw(uniqName);
|
|
271
271
|
selectionsTableFields[name] = sql`${column} as \`${fieldAlias}\``;
|
|
272
|
-
aliasMap[uniqName]= column;
|
|
272
|
+
aliasMap[uniqName] = column;
|
|
273
273
|
});
|
|
274
274
|
return selectionsTableFields;
|
|
275
275
|
}
|
|
@@ -278,7 +278,12 @@ function isDrizzleColumn(column: any): boolean {
|
|
|
278
278
|
return column && typeof column === "object" && "table" in column;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
-
export function mapSelectAllFieldsToAlias(
|
|
281
|
+
export function mapSelectAllFieldsToAlias(
|
|
282
|
+
selections: any,
|
|
283
|
+
name: string,
|
|
284
|
+
fields: any,
|
|
285
|
+
aliasMap: AliasColumnMap,
|
|
286
|
+
): any {
|
|
282
287
|
if (isTable(fields)) {
|
|
283
288
|
selections[name] = mapSelectTableToAlias(fields as MySqlTable, aliasMap);
|
|
284
289
|
} else if (isDrizzleColumn(fields)) {
|
|
@@ -309,38 +314,39 @@ export function mapSelectFieldsWithAlias<TSelection extends SelectedFields>(
|
|
|
309
314
|
Object.entries(fields).forEach(([name, fields]) => {
|
|
310
315
|
mapSelectAllFieldsToAlias(selections, name, fields, aliasMap);
|
|
311
316
|
});
|
|
312
|
-
return {selections, aliasMap};
|
|
317
|
+
return { selections, aliasMap };
|
|
313
318
|
}
|
|
314
319
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
isSQLWrapper(value) && 'queryChunks' in value;
|
|
321
|
-
if (isSQL){
|
|
322
|
-
const sql = value as SQL;
|
|
320
|
+
function getAliasFromDrizzleAlias(value: unknown): string | undefined {
|
|
321
|
+
const isSQL =
|
|
322
|
+
value !== null && typeof value === "object" && isSQLWrapper(value) && "queryChunks" in value;
|
|
323
|
+
if (isSQL) {
|
|
324
|
+
const sql = value as SQL;
|
|
323
325
|
const queryChunks = sql.queryChunks;
|
|
324
|
-
if (queryChunks.length>3){
|
|
325
|
-
const aliasNameChunk = queryChunks[queryChunks.length-2];
|
|
326
|
-
if (isSQLWrapper(aliasNameChunk) &&
|
|
327
|
-
const
|
|
326
|
+
if (queryChunks.length > 3) {
|
|
327
|
+
const aliasNameChunk = queryChunks[queryChunks.length - 2];
|
|
328
|
+
if (isSQLWrapper(aliasNameChunk) && "queryChunks" in aliasNameChunk) {
|
|
329
|
+
const aliasNameChunkSql = aliasNameChunk as SQL;
|
|
328
330
|
if (aliasNameChunkSql && aliasNameChunkSql.queryChunks.length === 1) {
|
|
329
331
|
const queryChunksStringChunc = aliasNameChunkSql.queryChunks[0];
|
|
330
|
-
if (queryChunksStringChunc &&
|
|
332
|
+
if (queryChunksStringChunc && "value" in queryChunksStringChunc) {
|
|
331
333
|
const values = (queryChunksStringChunc as StringChunk).value;
|
|
332
|
-
if (values && values.length===1){
|
|
333
|
-
return values[0]
|
|
334
|
+
if (values && values.length === 1) {
|
|
335
|
+
return values[0];
|
|
334
336
|
}
|
|
335
337
|
}
|
|
336
338
|
}
|
|
337
339
|
}
|
|
338
340
|
}
|
|
339
341
|
}
|
|
340
|
-
return undefined
|
|
342
|
+
return undefined;
|
|
341
343
|
}
|
|
342
344
|
|
|
343
|
-
function transformValue(
|
|
345
|
+
function transformValue(
|
|
346
|
+
value: unknown,
|
|
347
|
+
alias: string,
|
|
348
|
+
aliasMap: Record<string, AnyColumn>,
|
|
349
|
+
): unknown {
|
|
344
350
|
const column = aliasMap[alias];
|
|
345
351
|
if (!column) return value;
|
|
346
352
|
|
|
@@ -353,16 +359,24 @@ function transformValue(value: unknown, alias: string, aliasMap: Record<string,
|
|
|
353
359
|
return value;
|
|
354
360
|
}
|
|
355
361
|
|
|
356
|
-
function transformObject(
|
|
362
|
+
function transformObject(
|
|
363
|
+
obj: Record<string, unknown>,
|
|
364
|
+
selections: Record<string, unknown>,
|
|
365
|
+
aliasMap: Record<string, AnyColumn>,
|
|
366
|
+
): Record<string, unknown> {
|
|
357
367
|
const result: Record<string, unknown> = {};
|
|
358
368
|
|
|
359
369
|
for (const [key, value] of Object.entries(obj)) {
|
|
360
370
|
const selection = selections[key];
|
|
361
371
|
const alias = getAliasFromDrizzleAlias(selection);
|
|
362
372
|
if (alias && aliasMap[alias]) {
|
|
363
|
-
|
|
364
|
-
} else if (selection && typeof selection ===
|
|
365
|
-
result[key] = transformObject(
|
|
373
|
+
result[key] = transformValue(value, alias, aliasMap);
|
|
374
|
+
} else if (selection && typeof selection === "object" && !isSQLWrapper(selection)) {
|
|
375
|
+
result[key] = transformObject(
|
|
376
|
+
value as Record<string, unknown>,
|
|
377
|
+
selection as Record<string, unknown>,
|
|
378
|
+
aliasMap,
|
|
379
|
+
);
|
|
366
380
|
} else {
|
|
367
381
|
result[key] = value;
|
|
368
382
|
}
|
|
@@ -374,9 +388,13 @@ function transformObject(obj: Record<string, unknown>, selections: Record<string
|
|
|
374
388
|
export function applyFromDriverTransform<T, TSelection>(
|
|
375
389
|
rows: T[],
|
|
376
390
|
selections: TSelection,
|
|
377
|
-
aliasMap: Record<string, AnyColumn
|
|
391
|
+
aliasMap: Record<string, AnyColumn>,
|
|
378
392
|
): T[] {
|
|
379
393
|
return rows.map((row) => {
|
|
380
|
-
return transformObject(
|
|
394
|
+
return transformObject(
|
|
395
|
+
row as Record<string, unknown>,
|
|
396
|
+
selections as Record<string, unknown>,
|
|
397
|
+
aliasMap,
|
|
398
|
+
) as T;
|
|
381
399
|
});
|
|
382
400
|
}
|