forge-sql-orm 2.0.16 → 2.0.18
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/ForgeSQLORM.js +80 -15
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +80 -15
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts +1 -1
- package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +8 -13
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/utils/forgeDriverProxy.d.ts +11 -0
- package/dist/utils/forgeDriverProxy.d.ts.map +1 -0
- package/dist/utils/sqlHints.d.ts +21 -0
- package/dist/utils/sqlHints.d.ts.map +1 -0
- package/dist/utils/sqlUtils.d.ts +0 -6
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/ForgeSQLCrudOperations.ts +21 -6
- package/src/core/ForgeSQLORM.ts +3 -2
- package/src/core/ForgeSQLQueryBuilder.ts +9 -15
- package/src/utils/forgeDriverProxy.ts +27 -0
- package/src/utils/sqlHints.ts +63 -0
- package/src/utils/sqlUtils.ts +29 -19
|
@@ -27,7 +27,7 @@ export declare class ForgeSQLCrudOperations implements CRUDForgeSQL {
|
|
|
27
27
|
* @returns {Promise<number>} The number of inserted rows
|
|
28
28
|
* @throws {Error} If the insert operation fails
|
|
29
29
|
*/
|
|
30
|
-
insert<T extends AnyMySqlTable>(schema: T, models:
|
|
30
|
+
insert<T extends AnyMySqlTable>(schema: T, models: InferInsertModel<T>[], updateIfExists?: boolean): Promise<number>;
|
|
31
31
|
/**
|
|
32
32
|
* Deletes a record by its primary key with optional version check.
|
|
33
33
|
* If versioning is enabled, ensures the record hasn't been modified since last read.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLCrudOperations.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLCrudOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAa,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,YAAY;IACzD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoB;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAE7C;;;;OAIG;gBACS,kBAAkB,EAAE,iBAAiB,EAAE,OAAO,EAAE,kBAAkB;IAK9E;;;;;;;;;;OAUG;IACG,MAAM,CAAC,CAAC,SAAS,aAAa,EAClC,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"ForgeSQLCrudOperations.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLCrudOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAa,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGlC;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,YAAY;IACzD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoB;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAE7C;;;;OAIG;gBACS,kBAAkB,EAAE,iBAAiB,EAAE,OAAO,EAAE,kBAAkB;IAK9E;;;;;;;;;;OAUG;IACG,MAAM,CAAC,CAAC,SAAS,aAAa,EAClC,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAC7B,cAAc,GAAE,OAAe,GAC9B,OAAO,CAAC,MAAM,CAAC;IA+BlB;;;;;;;;;;OAUG;IACG,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAqClF;;;;;;;;;;;;;;OAcG;IACG,UAAU,CAAC,CAAC,SAAS,aAAa,EACtC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EACpC,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,MAAM,CAAC;IAyDlB;;;;;;;;;;;OAWG;IACG,YAAY,CAAC,CAAC,SAAS,aAAa,EACxC,UAAU,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EACxC,MAAM,EAAE,CAAC,EACT,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GACnB,OAAO,CAAC,MAAM,CAAC;IAiBlB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAStB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAoD5B;;;;;;;;;OASG;YACW,iBAAiB;IAyB/B;;;;;;;OAOG;IACH,OAAO,CAAC,uBAAuB;IA0B/B;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;IAsBzB;;;;;;;;OAQG;YACW,WAAW;CA4B1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLORM.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLORM.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAW,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"ForgeSQLORM.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLORM.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAW,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAoI5D;;;GAGG;AACH,cAAM,WAAY,YAAW,iBAAiB;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;gBAEpC,OAAO,CAAC,EAAE,kBAAkB;IAIxC;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,SAAS,cAAc,EACtC,MAAM,EAAE,UAAU,GACjB,kBAAkB,CAAC,UAAU,EAAE,2BAA2B,CAAC;IAI9D;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,UAAU,SAAS,cAAc,EAC9C,MAAM,EAAE,UAAU,GACjB,kBAAkB,CAAC,UAAU,EAAE,2BAA2B,CAAC;IAI9D;;;OAGG;IACH,IAAI,IAAI,YAAY;IAIpB;;;OAGG;IACH,KAAK,IAAI,iBAAiB;IAI1B;;;;;;;;OAQG;IACH,sBAAsB;CAGvB;AAED,eAAe,WAAW,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { AnyMySqlSelectQueryBuilder, AnyMySqlTable, MySqlSelectBuilder } from "d
|
|
|
4
4
|
import { MySqlSelectDynamic, type SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
5
5
|
import { InferInsertModel, SQL } from "drizzle-orm";
|
|
6
6
|
import { MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from "drizzle-orm/mysql-proxy/index";
|
|
7
|
+
import { SqlHints } from "../utils/sqlHints";
|
|
7
8
|
/**
|
|
8
9
|
* Interface representing the main ForgeSQL operations.
|
|
9
10
|
* Provides access to CRUD operations and schema-level SQL operations.
|
|
@@ -74,12 +75,12 @@ export interface CRUDForgeSQL {
|
|
|
74
75
|
* Inserts multiple records into the database.
|
|
75
76
|
* @template T - The type of the table schema
|
|
76
77
|
* @param {T} schema - The entity schema
|
|
77
|
-
* @param {
|
|
78
|
+
* @param {<InferInsertModel<T>[]} models - The list of entities to insert
|
|
78
79
|
* @param {boolean} [updateIfExists] - Whether to update the row if it already exists (default: false)
|
|
79
80
|
* @returns {Promise<number>} The number of inserted rows
|
|
80
81
|
* @throws {Error} If the insert operation fails
|
|
81
82
|
*/
|
|
82
|
-
insert<T extends AnyMySqlTable>(schema: T, models:
|
|
83
|
+
insert<T extends AnyMySqlTable>(schema: T, models: InferInsertModel<T>[], updateIfExists?: boolean): Promise<number>;
|
|
83
84
|
/**
|
|
84
85
|
* Deletes a record by its ID.
|
|
85
86
|
* @template T - The type of the table schema
|
|
@@ -175,21 +176,15 @@ export interface TableMetadata {
|
|
|
175
176
|
*/
|
|
176
177
|
export type AdditionalMetadata = Record<string, TableMetadata>;
|
|
177
178
|
/**
|
|
178
|
-
*
|
|
179
|
+
* Interface for ForgeSQL ORM options
|
|
179
180
|
*/
|
|
180
181
|
export interface ForgeSqlOrmOptions {
|
|
181
|
-
/**
|
|
182
|
-
* Enables logging of raw SQL queries in the Atlassian Forge Developer Console.
|
|
183
|
-
* Useful for debugging and monitoring SQL operations.
|
|
184
|
-
* @default false
|
|
185
|
-
*/
|
|
182
|
+
/** Whether to log raw SQL queries */
|
|
186
183
|
logRawSqlQuery?: boolean;
|
|
187
|
-
/**
|
|
188
|
-
* Disables optimistic locking for all operations.
|
|
189
|
-
* When enabled, version checks are skipped during updates.
|
|
190
|
-
* @default false
|
|
191
|
-
*/
|
|
184
|
+
/** Whether to disable optimistic locking */
|
|
192
185
|
disableOptimisticLocking?: boolean;
|
|
186
|
+
/** SQL hints to be applied to queries */
|
|
187
|
+
hints?: SqlHints;
|
|
193
188
|
/**
|
|
194
189
|
* Additional metadata for table configuration.
|
|
195
190
|
* Allows specifying table-specific settings and behaviors.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForgeSQLQueryBuilder.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLQueryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EACL,0BAA0B,EAC1B,aAAa,EAEb,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EACpB,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"ForgeSQLQueryBuilder.d.ts","sourceRoot":"","sources":["../../src/core/ForgeSQLQueryBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EACL,0BAA0B,EAC1B,aAAa,EAEb,kBAAkB,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,KAAK,cAAc,EACpB,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAGpD,OAAO,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AACjG,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAI7C;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC7D;;;OAGG;IACH,IAAI,IAAI,YAAY,CAAC;IAErB;;;OAGG;IACH,KAAK,IAAI,iBAAiB,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,sBAAsB,IAAI,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvE;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,UAAU,SAAS,cAAc,EACtC,MAAM,EAAE,UAAU,GACjB,kBAAkB,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;IAE/D;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,UAAU,SAAS,cAAc,EAC9C,MAAM,EAAE,UAAU,GACjB,kBAAkB,CAAC,UAAU,EAAE,2BAA2B,CAAC,CAAC;CAChE;AAID;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;OAQG;IACH,MAAM,CAAC,CAAC,SAAS,aAAa,EAC5B,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,EAC7B,cAAc,CAAC,EAAE,OAAO,GACvB,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;;;;OAOG;IACH,UAAU,CAAC,CAAC,SAAS,aAAa,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAE7E;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,CAAC,SAAS,aAAa,EAChC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EACpC,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,MAAM,CAAC,CAAC;IAEnB;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,CAAC,SAAS,aAAa,EAClC,UAAU,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EACxC,MAAM,EAAE,CAAC,EACT,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GACnB,OAAO,CAAC,MAAM,CAAC,CAAC;CACpB;AAID;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;;;OAOG;IACH,mBAAmB,CAAC,CAAC,SAAS,kBAAkB,CAAC,0BAA0B,CAAC,EAC1E,KAAK,EAAE,CAAC,GACP,OAAO,CACR,OAAO,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,CACxF,CAAC;IAEF;;;;;;;OAOG;IACH,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC;IAEjG;;;;;;OAMG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACtF;AAID;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,YAAY,EAAE,oBAAoB,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,4CAA4C;IAC5C,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,yCAAyC;IACzC,KAAK,CAAC,EAAE,QAAQ,CAAC;IAEjB;;;;;;;;;;;;;;;;OAgBG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAID;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;iBAGX,MAAM;;;;;;;;;;iBAAN,MAAM;;;;;;;;;CAYzB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;iBAGZ,MAAM;;;;;;;;;;iBAAN,MAAM;;;;;;;;;CAYzB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;iBAGP,MAAM;;;;;;;;;;iBAAN,MAAM;;;;;;;;;CAYzB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;iBAGP,MAAM;;;;;;;;;;iBAAN,MAAM;;;;;;;;;CAWzB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SqlHints } from "./sqlHints";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a proxy for the forgeDriver that injects SQL hints
|
|
4
|
+
* @returns A proxied version of the forgeDriver
|
|
5
|
+
*/
|
|
6
|
+
export declare function createForgeDriverProxy(options?: SqlHints, logRawSqlQuery?: boolean): (query: string, params: any[], method: "all" | "execute") => Promise<{
|
|
7
|
+
rows: any[];
|
|
8
|
+
insertId?: number;
|
|
9
|
+
affectedRows?: number;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=forgeDriverProxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forgeDriverProxy.d.ts","sourceRoot":"","sources":["../../src/utils/forgeDriverProxy.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,EAAE,OAAO,IAE/E,OAAO,MAAM,EACb,QAAQ,GAAG,EAAE,EACb,QAAQ,KAAK,GAAG,SAAS,KACxB,OAAO,CAAC;IACT,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC,CAUH"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for SQL hints configuration
|
|
3
|
+
*/
|
|
4
|
+
export interface SqlHints {
|
|
5
|
+
/** SQL hints for SELECT queries */
|
|
6
|
+
select?: string[];
|
|
7
|
+
/** SQL hints for INSERT queries */
|
|
8
|
+
insert?: string[];
|
|
9
|
+
/** SQL hints for UPDATE queries */
|
|
10
|
+
update?: string[];
|
|
11
|
+
/** SQL hints for DELETE queries */
|
|
12
|
+
delete?: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Detects the type of SQL query and injects appropriate hints
|
|
16
|
+
* @param query - The SQL query to analyze
|
|
17
|
+
* @param hints - The hints configuration
|
|
18
|
+
* @returns The modified query with injected hints
|
|
19
|
+
*/
|
|
20
|
+
export declare function injectSqlHints(query: string, hints?: SqlHints): string;
|
|
21
|
+
//# sourceMappingURL=sqlHints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlHints.d.ts","sourceRoot":"","sources":["../../src/utils/sqlHints.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CA0CtE"}
|
package/dist/utils/sqlUtils.d.ts
CHANGED
|
@@ -34,12 +34,6 @@ export interface MetadataInfo {
|
|
|
34
34
|
* @returns Date object
|
|
35
35
|
*/
|
|
36
36
|
export declare const parseDateTime: (value: string, format: string) => Date;
|
|
37
|
-
/**
|
|
38
|
-
* Extracts the alias from a SQL query
|
|
39
|
-
* @param query - The SQL query to extract the alias from
|
|
40
|
-
* @returns The extracted alias or the original query if no alias found
|
|
41
|
-
*/
|
|
42
|
-
export declare function extractAlias(query: string): string;
|
|
43
37
|
/**
|
|
44
38
|
* Gets primary keys from the schema.
|
|
45
39
|
* @template T - The type of the table schema
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/sqlUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAA0C,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,aAAa,EAAqB,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AAIzF;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC,8BAA8B;IAC9B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,yCAAyC;IACzC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,oCAAoC;IACpC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,oCAAoC;IACpC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,0CAA0C;IAC1C,iBAAiB,EAAE,uBAAuB,EAAE,CAAC;IAC7C,kCAAkC;IAClC,MAAM,EAAE,GAAG,EAAE,CAAC;CACf;AAUD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"sqlUtils.d.ts","sourceRoot":"","sources":["../../src/utils/sqlUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAA0C,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,aAAa,EAAqB,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oDAAoD,CAAC;AAIzF;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC,8BAA8B;IAC9B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,yCAAyC;IACzC,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,oCAAoC;IACpC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,oCAAoC;IACpC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,0CAA0C;IAC1C,iBAAiB,EAAE,uBAAuB,EAAE,CAAC;IAC7C,kCAAkC;IAClC,MAAM,EAAE,GAAG,EAAE,CAAC;CACf;AAUD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,QAAQ,MAAM,KAAG,IAiB7D,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAkCvF;AA0DD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,CAoEnE;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,EAAE,CAc7E;AAED,KAAK,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAuBhD,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,GAAG,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,GAAG,EACX,QAAQ,EAAE,cAAc,GACvB,GAAG,CAmBL;AACD,wBAAgB,wBAAwB,CAAC,UAAU,SAAS,cAAc,EACxE,MAAM,EAAE,UAAU,GACjB;IAAE,UAAU,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,cAAc,CAAA;CAAE,CAUtD;AAsED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,UAAU,EACpD,IAAI,EAAE,CAAC,EAAE,EACT,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAClC,CAAC,EAAE,CAUL"}
|
package/package.json
CHANGED
|
@@ -37,7 +37,7 @@ export class ForgeSQLCrudOperations implements CRUDForgeSQL {
|
|
|
37
37
|
*/
|
|
38
38
|
async insert<T extends AnyMySqlTable>(
|
|
39
39
|
schema: T,
|
|
40
|
-
models:
|
|
40
|
+
models: InferInsertModel<T>[],
|
|
41
41
|
updateIfExists: boolean = false,
|
|
42
42
|
): Promise<number> {
|
|
43
43
|
if (!models?.length) return 0;
|
|
@@ -257,8 +257,16 @@ export class ForgeSQLCrudOperations implements CRUDForgeSQL {
|
|
|
257
257
|
}
|
|
258
258
|
const versionMetadata = this.options.additionalMetadata?.[tableName]?.versionField;
|
|
259
259
|
if (!versionMetadata) return undefined;
|
|
260
|
+
let fieldName = versionMetadata.fieldName;
|
|
260
261
|
|
|
261
|
-
|
|
262
|
+
let versionField = columns[versionMetadata.fieldName];
|
|
263
|
+
if (!versionField) {
|
|
264
|
+
const find = Object.entries(columns).find(([, c]) => c.name === versionMetadata.fieldName);
|
|
265
|
+
if (find) {
|
|
266
|
+
fieldName = find[0];
|
|
267
|
+
versionField = find[1];
|
|
268
|
+
}
|
|
269
|
+
}
|
|
262
270
|
if (!versionField) {
|
|
263
271
|
console.warn(
|
|
264
272
|
`Version field "${versionMetadata.fieldName}" not found in table ${tableName}. Versioning will be skipped.`,
|
|
@@ -289,7 +297,7 @@ export class ForgeSQLCrudOperations implements CRUDForgeSQL {
|
|
|
289
297
|
return undefined;
|
|
290
298
|
}
|
|
291
299
|
|
|
292
|
-
return { fieldName
|
|
300
|
+
return { fieldName, type: fieldType };
|
|
293
301
|
}
|
|
294
302
|
|
|
295
303
|
/**
|
|
@@ -341,15 +349,22 @@ export class ForgeSQLCrudOperations implements CRUDForgeSQL {
|
|
|
341
349
|
columns: Record<string, AnyColumn>,
|
|
342
350
|
): InferInsertModel<T> {
|
|
343
351
|
if (!versionMetadata || !columns) return model as InferInsertModel<T>;
|
|
352
|
+
let fieldName = versionMetadata.fieldName;
|
|
353
|
+
let versionField = columns[versionMetadata.fieldName];
|
|
354
|
+
if (!versionField) {
|
|
355
|
+
const find = Object.entries(columns).find(([, c]) => c.name === versionMetadata.fieldName);
|
|
356
|
+
if (find) {
|
|
357
|
+
fieldName = find[0];
|
|
358
|
+
versionField = find[1];
|
|
359
|
+
}
|
|
360
|
+
}
|
|
344
361
|
|
|
345
|
-
const versionField = columns[versionMetadata.fieldName];
|
|
346
362
|
if (!versionField) return model as InferInsertModel<T>;
|
|
347
363
|
|
|
348
364
|
const modelWithVersion = { ...model };
|
|
349
365
|
const fieldType = versionField.getSQLType();
|
|
350
366
|
const versionValue = fieldType === "datetime" || fieldType === "timestamp" ? new Date() : 1;
|
|
351
|
-
modelWithVersion[
|
|
352
|
-
versionValue as any;
|
|
367
|
+
modelWithVersion[fieldName as keyof typeof modelWithVersion] = versionValue as any;
|
|
353
368
|
|
|
354
369
|
return modelWithVersion as InferInsertModel<T>;
|
|
355
370
|
}
|
package/src/core/ForgeSQLORM.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./ForgeSQLQueryBuilder";
|
|
8
8
|
import { ForgeSQLSelectOperations } from "./ForgeSQLSelectOperations";
|
|
9
9
|
import { drizzle, MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from "drizzle-orm/mysql-proxy";
|
|
10
|
-
import {
|
|
10
|
+
import { createForgeDriverProxy } from "../utils/forgeDriverProxy";
|
|
11
11
|
import type { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
|
|
12
12
|
import { MySqlSelectBuilder } from "drizzle-orm/mysql-core";
|
|
13
13
|
import { patchDbWithSelectAliased } from "../lib/drizzle/extensions/selectAliased";
|
|
@@ -37,8 +37,9 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
|
|
|
37
37
|
console.debug("Initializing ForgeSQLORM...");
|
|
38
38
|
}
|
|
39
39
|
// Initialize Drizzle instance with our custom driver
|
|
40
|
+
const proxiedDriver = createForgeDriverProxy(newOptions.hints, newOptions.logRawSqlQuery);
|
|
40
41
|
this.drizzle = patchDbWithSelectAliased(
|
|
41
|
-
drizzle(
|
|
42
|
+
drizzle(proxiedDriver, { logger: newOptions.logRawSqlQuery }),
|
|
42
43
|
);
|
|
43
44
|
this.crudOperations = new ForgeSQLCrudOperations(this, newOptions);
|
|
44
45
|
this.fetchOperations = new ForgeSQLSelectOperations(newOptions);
|
|
@@ -14,6 +14,7 @@ import { InferInsertModel, SQL } from "drizzle-orm";
|
|
|
14
14
|
import moment from "moment/moment";
|
|
15
15
|
import { parseDateTime } from "../utils/sqlUtils";
|
|
16
16
|
import { MySqlRemoteDatabase, MySqlRemotePreparedQueryHKT } from "drizzle-orm/mysql-proxy/index";
|
|
17
|
+
import { SqlHints } from "../utils/sqlHints";
|
|
17
18
|
|
|
18
19
|
// ============= Core Types =============
|
|
19
20
|
|
|
@@ -98,14 +99,14 @@ export interface CRUDForgeSQL {
|
|
|
98
99
|
* Inserts multiple records into the database.
|
|
99
100
|
* @template T - The type of the table schema
|
|
100
101
|
* @param {T} schema - The entity schema
|
|
101
|
-
* @param {
|
|
102
|
+
* @param {<InferInsertModel<T>[]} models - The list of entities to insert
|
|
102
103
|
* @param {boolean} [updateIfExists] - Whether to update the row if it already exists (default: false)
|
|
103
104
|
* @returns {Promise<number>} The number of inserted rows
|
|
104
105
|
* @throws {Error} If the insert operation fails
|
|
105
106
|
*/
|
|
106
107
|
insert<T extends AnyMySqlTable>(
|
|
107
108
|
schema: T,
|
|
108
|
-
models:
|
|
109
|
+
models: InferInsertModel<T>[],
|
|
109
110
|
updateIfExists?: boolean,
|
|
110
111
|
): Promise<number>;
|
|
111
112
|
|
|
@@ -228,22 +229,15 @@ export interface TableMetadata {
|
|
|
228
229
|
export type AdditionalMetadata = Record<string, TableMetadata>;
|
|
229
230
|
|
|
230
231
|
/**
|
|
231
|
-
*
|
|
232
|
+
* Interface for ForgeSQL ORM options
|
|
232
233
|
*/
|
|
233
234
|
export interface ForgeSqlOrmOptions {
|
|
234
|
-
/**
|
|
235
|
-
* Enables logging of raw SQL queries in the Atlassian Forge Developer Console.
|
|
236
|
-
* Useful for debugging and monitoring SQL operations.
|
|
237
|
-
* @default false
|
|
238
|
-
*/
|
|
235
|
+
/** Whether to log raw SQL queries */
|
|
239
236
|
logRawSqlQuery?: boolean;
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Disables optimistic locking for all operations.
|
|
243
|
-
* When enabled, version checks are skipped during updates.
|
|
244
|
-
* @default false
|
|
245
|
-
*/
|
|
237
|
+
/** Whether to disable optimistic locking */
|
|
246
238
|
disableOptimisticLocking?: boolean;
|
|
239
|
+
/** SQL hints to be applied to queries */
|
|
240
|
+
hints?: SqlHints;
|
|
247
241
|
|
|
248
242
|
/**
|
|
249
243
|
* Additional metadata for table configuration.
|
|
@@ -301,7 +295,7 @@ export const forgeTimestampString = customType<{
|
|
|
301
295
|
return "timestamp";
|
|
302
296
|
},
|
|
303
297
|
toDriver(value: Date) {
|
|
304
|
-
return moment(
|
|
298
|
+
return moment(new Date(value)).format("YYYY-MM-DDTHH:mm:ss.SSS");
|
|
305
299
|
},
|
|
306
300
|
fromDriver(value: unknown) {
|
|
307
301
|
const format = "YYYY-MM-DDTHH:mm:ss.SSS";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { forgeDriver } from "./forgeDriver";
|
|
2
|
+
import { injectSqlHints, SqlHints } from "./sqlHints";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a proxy for the forgeDriver that injects SQL hints
|
|
6
|
+
* @returns A proxied version of the forgeDriver
|
|
7
|
+
*/
|
|
8
|
+
export function createForgeDriverProxy(options?: SqlHints, logRawSqlQuery?: boolean) {
|
|
9
|
+
return async (
|
|
10
|
+
query: string,
|
|
11
|
+
params: any[],
|
|
12
|
+
method: "all" | "execute",
|
|
13
|
+
): Promise<{
|
|
14
|
+
rows: any[];
|
|
15
|
+
insertId?: number;
|
|
16
|
+
affectedRows?: number;
|
|
17
|
+
}> => {
|
|
18
|
+
// Inject SQL hints into the query
|
|
19
|
+
const modifiedQuery = injectSqlHints(query, options);
|
|
20
|
+
|
|
21
|
+
if (options && logRawSqlQuery) {
|
|
22
|
+
console.warn("modified query: " + modifiedQuery);
|
|
23
|
+
}
|
|
24
|
+
// Call the original forgeDriver with the modified query
|
|
25
|
+
return forgeDriver(modifiedQuery, params, method);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for SQL hints configuration
|
|
3
|
+
*/
|
|
4
|
+
export interface SqlHints {
|
|
5
|
+
/** SQL hints for SELECT queries */
|
|
6
|
+
select?: string[];
|
|
7
|
+
/** SQL hints for INSERT queries */
|
|
8
|
+
insert?: string[];
|
|
9
|
+
/** SQL hints for UPDATE queries */
|
|
10
|
+
update?: string[];
|
|
11
|
+
/** SQL hints for DELETE queries */
|
|
12
|
+
delete?: string[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Detects the type of SQL query and injects appropriate hints
|
|
17
|
+
* @param query - The SQL query to analyze
|
|
18
|
+
* @param hints - The hints configuration
|
|
19
|
+
* @returns The modified query with injected hints
|
|
20
|
+
*/
|
|
21
|
+
export function injectSqlHints(query: string, hints?: SqlHints): string {
|
|
22
|
+
if (!hints) {
|
|
23
|
+
return query;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Normalize the query for easier matching
|
|
27
|
+
const normalizedQuery = query.trim().toUpperCase();
|
|
28
|
+
|
|
29
|
+
// Get the appropriate hints based on query type
|
|
30
|
+
let queryHints: string[] | undefined;
|
|
31
|
+
|
|
32
|
+
if (normalizedQuery.startsWith("SELECT")) {
|
|
33
|
+
queryHints = hints.select;
|
|
34
|
+
} else if (normalizedQuery.startsWith("INSERT")) {
|
|
35
|
+
queryHints = hints.insert;
|
|
36
|
+
} else if (normalizedQuery.startsWith("UPDATE")) {
|
|
37
|
+
queryHints = hints.update;
|
|
38
|
+
} else if (normalizedQuery.startsWith("DELETE")) {
|
|
39
|
+
queryHints = hints.delete;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// If no hints for this query type, return original query
|
|
43
|
+
if (!queryHints || queryHints.length === 0) {
|
|
44
|
+
return query;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Join all hints with spaces
|
|
48
|
+
const hintsString = queryHints.join(" ");
|
|
49
|
+
|
|
50
|
+
// Inject hints into the query
|
|
51
|
+
if (normalizedQuery.startsWith("SELECT")) {
|
|
52
|
+
return `SELECT /*+ ${hintsString} */ ${query.substring(6)}`;
|
|
53
|
+
} else if (normalizedQuery.startsWith("INSERT")) {
|
|
54
|
+
return `INSERT /*+ ${hintsString} */ ${query.substring(6)}`;
|
|
55
|
+
} else if (normalizedQuery.startsWith("UPDATE")) {
|
|
56
|
+
return `UPDATE /*+ ${hintsString} */ ${query.substring(6)}`;
|
|
57
|
+
} else if (normalizedQuery.startsWith("DELETE")) {
|
|
58
|
+
return `DELETE /*+ ${hintsString} */ ${query.substring(6)}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// If no match found, return original query
|
|
62
|
+
return query;
|
|
63
|
+
}
|
package/src/utils/sqlUtils.ts
CHANGED
|
@@ -47,23 +47,24 @@ interface ConfigBuilderData {
|
|
|
47
47
|
* @returns Date object
|
|
48
48
|
*/
|
|
49
49
|
export const parseDateTime = (value: string, format: string): Date => {
|
|
50
|
+
let result: Date;
|
|
50
51
|
const m = moment(value, format, true);
|
|
51
52
|
if (!m.isValid()) {
|
|
52
|
-
|
|
53
|
+
const momentDate = moment(value);
|
|
54
|
+
if (momentDate.isValid()) {
|
|
55
|
+
result = momentDate.toDate();
|
|
56
|
+
} else {
|
|
57
|
+
result = new Date(value);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
result = m.toDate();
|
|
61
|
+
}
|
|
62
|
+
if (isNaN(result.getTime())) {
|
|
63
|
+
result = new Date(value);
|
|
53
64
|
}
|
|
54
|
-
return
|
|
65
|
+
return result;
|
|
55
66
|
};
|
|
56
67
|
|
|
57
|
-
/**
|
|
58
|
-
* Extracts the alias from a SQL query
|
|
59
|
-
* @param query - The SQL query to extract the alias from
|
|
60
|
-
* @returns The extracted alias or the original query if no alias found
|
|
61
|
-
*/
|
|
62
|
-
export function extractAlias(query: string): string {
|
|
63
|
-
const match = query.match(/\bas\s+(['"`]?)([\w*]+)\1$/i);
|
|
64
|
-
return match ? match[2] : query;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
68
|
/**
|
|
68
69
|
* Gets primary keys from the schema.
|
|
69
70
|
* @template T - The type of the table schema
|
|
@@ -260,7 +261,11 @@ export function generateDropTableStatements(tables: AnyMySqlTable[]): string[] {
|
|
|
260
261
|
|
|
261
262
|
type AliasColumnMap = Record<string, AnyColumn>;
|
|
262
263
|
|
|
263
|
-
function mapSelectTableToAlias(
|
|
264
|
+
function mapSelectTableToAlias(
|
|
265
|
+
table: MySqlTable,
|
|
266
|
+
uniqPrefix: string,
|
|
267
|
+
aliasMap: AliasColumnMap,
|
|
268
|
+
): any {
|
|
264
269
|
const { columns, tableName } = getTableMetadata(table);
|
|
265
270
|
const selectionsTableFields: Record<string, unknown> = {};
|
|
266
271
|
Object.keys(columns).forEach((name) => {
|
|
@@ -280,7 +285,7 @@ function isDrizzleColumn(column: any): boolean {
|
|
|
280
285
|
export function mapSelectAllFieldsToAlias(
|
|
281
286
|
selections: any,
|
|
282
287
|
name: string,
|
|
283
|
-
uniqName:string,
|
|
288
|
+
uniqName: string,
|
|
284
289
|
fields: any,
|
|
285
290
|
aliasMap: AliasColumnMap,
|
|
286
291
|
): any {
|
|
@@ -291,7 +296,7 @@ export function mapSelectAllFieldsToAlias(
|
|
|
291
296
|
const uniqAliasName = `a_${uniqName}_${column.name}`.toLowerCase();
|
|
292
297
|
let aliasName = sql.raw(uniqAliasName);
|
|
293
298
|
selections[name] = sql`${column} as \`${aliasName}\``;
|
|
294
|
-
aliasMap[
|
|
299
|
+
aliasMap[uniqAliasName] = column;
|
|
295
300
|
} else if (isSQLWrapper(fields)) {
|
|
296
301
|
selections[name] = fields;
|
|
297
302
|
} else {
|
|
@@ -312,7 +317,7 @@ export function mapSelectFieldsWithAlias<TSelection extends SelectedFields>(
|
|
|
312
317
|
const aliasMap: AliasColumnMap = {};
|
|
313
318
|
const selections: any = {};
|
|
314
319
|
Object.entries(fields).forEach(([name, fields]) => {
|
|
315
|
-
mapSelectAllFieldsToAlias(selections, name,name, fields, aliasMap);
|
|
320
|
+
mapSelectAllFieldsToAlias(selections, name, name, fields, aliasMap);
|
|
316
321
|
});
|
|
317
322
|
return { selections, aliasMap };
|
|
318
323
|
}
|
|
@@ -402,7 +407,12 @@ export function applyFromDriverTransform<T, TSelection>(
|
|
|
402
407
|
}
|
|
403
408
|
|
|
404
409
|
function processNullBranches(obj: Record<string, unknown>): Record<string, unknown> | null {
|
|
405
|
-
if (obj === null || typeof obj !==
|
|
410
|
+
if (obj === null || typeof obj !== "object" || obj === undefined) {
|
|
411
|
+
return obj;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Skip built-in objects like Date, Array, etc.
|
|
415
|
+
if (obj.constructor && obj.constructor.name !== "Object") {
|
|
406
416
|
return obj;
|
|
407
417
|
}
|
|
408
418
|
|
|
@@ -410,12 +420,12 @@ function processNullBranches(obj: Record<string, unknown>): Record<string, unkno
|
|
|
410
420
|
let allNull = true;
|
|
411
421
|
|
|
412
422
|
for (const [key, value] of Object.entries(obj)) {
|
|
413
|
-
if (value === null || value===undefined) {
|
|
423
|
+
if (value === null || value === undefined) {
|
|
414
424
|
result[key] = null;
|
|
415
425
|
continue;
|
|
416
426
|
}
|
|
417
427
|
|
|
418
|
-
if (typeof value ===
|
|
428
|
+
if (typeof value === "object" && value !== null && value !== undefined) {
|
|
419
429
|
const processed = processNullBranches(value as Record<string, unknown>);
|
|
420
430
|
result[key] = processed;
|
|
421
431
|
if (processed !== null) {
|