forge-sql-orm 2.1.14 → 2.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +294 -20
  2. package/dist/core/ForgeSQLORM.d.ts +16 -7
  3. package/dist/core/ForgeSQLORM.d.ts.map +1 -1
  4. package/dist/core/ForgeSQLORM.js +73 -15
  5. package/dist/core/ForgeSQLORM.js.map +1 -1
  6. package/dist/core/ForgeSQLQueryBuilder.d.ts +15 -7
  7. package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
  8. package/dist/core/ForgeSQLQueryBuilder.js.map +1 -1
  9. package/dist/core/ForgeSQLSelectOperations.d.ts +2 -1
  10. package/dist/core/ForgeSQLSelectOperations.d.ts.map +1 -1
  11. package/dist/core/ForgeSQLSelectOperations.js.map +1 -1
  12. package/dist/core/Rovo.d.ts +40 -0
  13. package/dist/core/Rovo.d.ts.map +1 -1
  14. package/dist/core/Rovo.js +164 -138
  15. package/dist/core/Rovo.js.map +1 -1
  16. package/dist/index.d.ts +1 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +3 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
  21. package/dist/lib/drizzle/extensions/additionalActions.js +72 -22
  22. package/dist/lib/drizzle/extensions/additionalActions.js.map +1 -1
  23. package/dist/utils/cacheTableUtils.d.ts +11 -0
  24. package/dist/utils/cacheTableUtils.d.ts.map +1 -0
  25. package/dist/utils/cacheTableUtils.js +450 -0
  26. package/dist/utils/cacheTableUtils.js.map +1 -0
  27. package/dist/utils/cacheUtils.d.ts.map +1 -1
  28. package/dist/utils/cacheUtils.js +3 -22
  29. package/dist/utils/cacheUtils.js.map +1 -1
  30. package/dist/utils/forgeDriver.d.ts +3 -2
  31. package/dist/utils/forgeDriver.d.ts.map +1 -1
  32. package/dist/utils/forgeDriver.js +24 -27
  33. package/dist/utils/forgeDriver.js.map +1 -1
  34. package/dist/utils/metadataContextUtils.d.ts +27 -1
  35. package/dist/utils/metadataContextUtils.d.ts.map +1 -1
  36. package/dist/utils/metadataContextUtils.js +237 -10
  37. package/dist/utils/metadataContextUtils.js.map +1 -1
  38. package/dist/utils/sqlUtils.d.ts +1 -0
  39. package/dist/utils/sqlUtils.d.ts.map +1 -1
  40. package/dist/utils/sqlUtils.js +217 -119
  41. package/dist/utils/sqlUtils.js.map +1 -1
  42. package/dist/webtriggers/applyMigrationsWebTrigger.js +1 -1
  43. package/dist/webtriggers/index.d.ts +1 -0
  44. package/dist/webtriggers/index.d.ts.map +1 -1
  45. package/dist/webtriggers/index.js +1 -0
  46. package/dist/webtriggers/index.js.map +1 -1
  47. package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts +60 -0
  48. package/dist/webtriggers/topSlowestStatementLastHourTrigger.d.ts.map +1 -0
  49. package/dist/webtriggers/topSlowestStatementLastHourTrigger.js +55 -0
  50. package/dist/webtriggers/topSlowestStatementLastHourTrigger.js.map +1 -0
  51. package/package.json +11 -10
  52. package/src/core/ForgeSQLORM.ts +78 -14
  53. package/src/core/ForgeSQLQueryBuilder.ts +15 -5
  54. package/src/core/ForgeSQLSelectOperations.ts +2 -1
  55. package/src/core/Rovo.ts +209 -167
  56. package/src/index.ts +1 -3
  57. package/src/lib/drizzle/extensions/additionalActions.ts +98 -42
  58. package/src/utils/cacheTableUtils.ts +511 -0
  59. package/src/utils/cacheUtils.ts +3 -25
  60. package/src/utils/forgeDriver.ts +38 -29
  61. package/src/utils/metadataContextUtils.ts +290 -10
  62. package/src/utils/sqlUtils.ts +298 -142
  63. package/src/webtriggers/applyMigrationsWebTrigger.ts +1 -1
  64. package/src/webtriggers/index.ts +1 -0
  65. package/src/webtriggers/topSlowestStatementLastHourTrigger.ts +69 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-sql-orm",
3
- "version": "2.1.14",
3
+ "version": "2.1.16",
4
4
  "description": "Drizzle ORM integration for Atlassian @forge/sql. Provides a custom driver, schema migration, two levels of caching (local and global via @forge/kvs), optimistic locking, and query analysis.",
5
5
  "main": "dist/index.js",
6
6
  "homepage": "https://github.com/vzakharchenko/forge-sql-orm#readme",
@@ -21,28 +21,29 @@
21
21
  "drizzle-driver",
22
22
  "drizzle-custom-driver",
23
23
  "orm",
24
+ "rovo",
24
25
  "database"
25
26
  ],
26
27
  "devDependencies": {
27
28
  "@eslint/js": "^9.39.1",
28
29
  "@types/luxon": "^3.7.1",
29
30
  "@types/node": "^24.10.1",
30
- "@typescript-eslint/eslint-plugin": "^8.47.0",
31
- "@typescript-eslint/parser": "^8.47.0",
32
- "@vitest/coverage-v8": "^4.0.13",
33
- "@vitest/ui": "^4.0.13",
31
+ "@typescript-eslint/eslint-plugin": "^8.48.1",
32
+ "@typescript-eslint/parser": "^8.48.1",
33
+ "@vitest/coverage-v8": "^4.0.15",
34
+ "@vitest/ui": "^4.0.15",
34
35
  "eslint": "^9.39.1",
35
36
  "eslint-config-prettier": "^10.1.8",
36
37
  "eslint-plugin-import": "^2.32.0",
37
38
  "eslint-plugin-vitest": "^0.5.4",
38
39
  "husky": "^9.1.7",
39
- "knip": "^5.70.1",
40
+ "knip": "^5.71.0",
40
41
  "patch-package": "^8.0.1",
41
- "prettier": "^3.6.2",
42
+ "prettier": "^3.7.4",
42
43
  "ts-node": "^10.9.2",
43
44
  "typescript": "^5.9.3",
44
45
  "uuid": "^13.0.0",
45
- "vitest": "^4.0.13"
46
+ "vitest": "^4.0.15"
46
47
  },
47
48
  "license": "MIT",
48
49
  "author": "Vasyl Zakharchenko",
@@ -70,8 +71,8 @@
70
71
  "README.md"
71
72
  ],
72
73
  "peerDependencies": {
73
- "@forge/sql": "^3.0.10",
74
- "drizzle-orm": "^0.44.7"
74
+ "@forge/sql": "^3.0.12",
75
+ "drizzle-orm": "^0.45.0"
75
76
  },
76
77
  "optionalDependencies": {
77
78
  "@forge/kvs": "^1.2.0"
@@ -39,7 +39,11 @@ import { cacheApplicationContext, localCacheApplicationContext } from "../utils/
39
39
  import { clearTablesCache } from "../utils/cacheUtils";
40
40
  import { SQLWrapper } from "drizzle-orm/sql/sql";
41
41
  import { WithSubquery } from "drizzle-orm/subquery";
42
- import { getLastestMetadata, metadataQueryContext } from "../utils/metadataContextUtils";
42
+ import {
43
+ getLastestMetadata,
44
+ metadataQueryContext,
45
+ MetadataQueryOptions,
46
+ } from "../utils/metadataContextUtils";
43
47
  import { operationTypeQueryContext } from "../utils/requestTypeContextUtils";
44
48
  import type { MySqlQueryResultKind } from "drizzle-orm/mysql-core/session";
45
49
  import { Rovo } from "./Rovo";
@@ -124,7 +128,15 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
124
128
  * @param onMetadata - Callback function that receives aggregated execution metadata
125
129
  * @param onMetadata.totalDbExecutionTime - Total database execution time across all operations in the query function (in milliseconds)
126
130
  * @param onMetadata.totalResponseSize - Total response size across all operations (in bytes)
127
- * @param onMetadata.printQueries - Function to analyze and print query execution plans from CLUSTER_STATEMENTS_SUMMARY
131
+ * @param onMetadata.printQueriesWithPlan - Function to analyze and print query execution plans. Supports two modes:
132
+ * - TopSlowest: Prints execution plans for the slowest queries from the current resolver (default)
133
+ * - SummaryTable: Uses CLUSTER_STATEMENTS_SUMMARY if within time window
134
+ * @param options - Optional configuration for query plan printing behavior
135
+ * @param options.mode - Query plan printing mode: 'TopSlowest' (default) or 'SummaryTable'
136
+ * @param options.summaryTableWindowTime - Time window in milliseconds for summary table queries (default: 15000ms). Only used when mode is 'SummaryTable'
137
+ * @param options.topQueries - Number of top slowest queries to analyze when mode is 'TopSlowest' (default: 1)
138
+ * @param options.showSlowestPlans - Whether to show execution plans for slowest queries in TopSlowest mode (default: true)
139
+ * @param options.normalizeQuery - Whether to normalize SQL queries by replacing parameter values with '?' placeholders (default: true). Set to false to disable normalization if it causes issues
128
140
  * @returns Promise with the query result
129
141
  *
130
142
  * @example
@@ -136,12 +148,12 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
136
148
  * const orders = await forgeSQL.selectFrom(ordersTable).where(eq(ordersTable.userId, usersTable.id));
137
149
  * return { users, orders };
138
150
  * },
139
- * (totalDbExecutionTime, totalResponseSize, printQueries) => {
151
+ * (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
140
152
  * const threshold = 500; // ms baseline for this resolver
141
153
  *
142
154
  * if (totalDbExecutionTime > threshold * 1.5) {
143
155
  * console.warn(`[Performance Warning] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
144
- * await printQueries(); // Analyze and print query execution plans
156
+ * await printQueriesWithPlan(); // Analyze and print query execution plans
145
157
  * } else if (totalDbExecutionTime > threshold) {
146
158
  * console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
147
159
  * }
@@ -164,12 +176,12 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
164
176
  * .where(eq(demoOrders.userId, demoUsers.id));
165
177
  * return { users, orders };
166
178
  * },
167
- * async (totalDbExecutionTime, totalResponseSize, printQueries) => {
179
+ * async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
168
180
  * const threshold = 500; // ms baseline for this resolver
169
181
  *
170
182
  * if (totalDbExecutionTime > threshold * 1.5) {
171
183
  * console.warn(`[Performance Warning fetch] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
172
- * await printQueries(); // Optionally log or capture diagnostics for further analysis
184
+ * await printQueriesWithPlan(); // Optionally log or capture diagnostics for further analysis
173
185
  * } else if (totalDbExecutionTime > threshold) {
174
186
  * console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
175
187
  * }
@@ -185,7 +197,47 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
185
197
  * });
186
198
  * ```
187
199
  *
188
- * @note **Important**: When multiple resolvers are running concurrently, their query data may also appear in `printQueries()` analysis, as it queries the global `CLUSTER_STATEMENTS_SUMMARY` table.
200
+ * @example
201
+ * ```typescript
202
+ * // Using TopSlowest mode with custom topQueries
203
+ * const result = await forgeSQL.executeWithMetadata(
204
+ * async () => {
205
+ * const users = await forgeSQL.selectFrom(usersTable);
206
+ * return users;
207
+ * },
208
+ * async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
209
+ * if (totalDbExecutionTime > 1000) {
210
+ * await printQueriesWithPlan(); // Will print top 3 slowest queries
211
+ * }
212
+ * },
213
+ * {
214
+ * mode: 'TopSlowest', // Print top slowest queries (default)
215
+ * topQueries: 3, // Print top 3 slowest queries
216
+ * }
217
+ * );
218
+ * ```
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * // Using SummaryTable mode for query analysis
223
+ * const result = await forgeSQL.executeWithMetadata(
224
+ * async () => {
225
+ * const users = await forgeSQL.selectFrom(usersTable);
226
+ * return users;
227
+ * },
228
+ * async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
229
+ * if (totalDbExecutionTime > 1000) {
230
+ * await printQueriesWithPlan(); // Will use CLUSTER_STATEMENTS_SUMMARY if within time window
231
+ * }
232
+ * },
233
+ * {
234
+ * mode: 'SummaryTable', // Use summary tables mode
235
+ * summaryTableWindowTime: 10000, // 10 second window
236
+ * }
237
+ * );
238
+ * ```
239
+ *
240
+ * @note **Important**: When multiple resolvers are running concurrently, their query data may also appear in `printQueriesWithPlan()` analysis, as it queries the global `CLUSTER_STATEMENTS_SUMMARY` table.
189
241
  */
190
242
  async executeWithMetadata<T>(
191
243
  query: () => Promise<T>,
@@ -194,6 +246,7 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
194
246
  totalResponseSize: number,
195
247
  printQueriesWithPlan: () => Promise<void>,
196
248
  ) => Promise<void> | void,
249
+ options?: MetadataQueryOptions,
197
250
  ): Promise<T> {
198
251
  return metadataQueryContext.run(
199
252
  {
@@ -204,6 +257,8 @@ class ForgeSQLORMImpl implements ForgeSqlOperation {
204
257
  printQueriesWithPlan: async () => {
205
258
  return;
206
259
  },
260
+ options: options,
261
+ statistics: [],
207
262
  },
208
263
  async () => {
209
264
  const result = await query();
@@ -886,7 +941,15 @@ class ForgeSQLORM implements ForgeSqlOperation {
886
941
  * @param onMetadata - Callback function that receives aggregated execution metadata
887
942
  * @param onMetadata.totalDbExecutionTime - Total database execution time across all operations in the query function (in milliseconds)
888
943
  * @param onMetadata.totalResponseSize - Total response size across all operations (in bytes)
889
- * @param onMetadata.printQueries - Function to analyze and print query execution plans from CLUSTER_STATEMENTS_SUMMARY
944
+ * @param onMetadata.printQueriesWithPlan - Function to analyze and print query execution plans. Supports two modes:
945
+ * - TopSlowest: Prints execution plans for the slowest queries from the current resolver (default)
946
+ * - SummaryTable: Uses CLUSTER_STATEMENTS_SUMMARY if within time window
947
+ * @param options - Optional configuration for query plan printing behavior
948
+ * @param options.mode - Query plan printing mode: 'TopSlowest' (default) or 'SummaryTable'
949
+ * @param options.summaryTableWindowTime - Time window in milliseconds for summary table queries (default: 15000ms). Only used when mode is 'SummaryTable'
950
+ * @param options.topQueries - Number of top slowest queries to analyze when mode is 'TopSlowest' (default: 1)
951
+ * @param options.showSlowestPlans - Whether to show execution plans for slowest queries in TopSlowest mode (default: true)
952
+ * @param options.normalizeQuery - Whether to normalize SQL queries by replacing parameter values with '?' placeholders (default: true). Set to false to disable normalization if it causes issues
890
953
  * @returns Promise with the query result
891
954
  *
892
955
  * @example
@@ -898,12 +961,12 @@ class ForgeSQLORM implements ForgeSqlOperation {
898
961
  * const orders = await forgeSQL.selectFrom(ordersTable).where(eq(ordersTable.userId, usersTable.id));
899
962
  * return { users, orders };
900
963
  * },
901
- * (totalDbExecutionTime, totalResponseSize, printQueries) => {
964
+ * (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
902
965
  * const threshold = 500; // ms baseline for this resolver
903
966
  *
904
967
  * if (totalDbExecutionTime > threshold * 1.5) {
905
968
  * console.warn(`[Performance Warning] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
906
- * await printQueries(); // Analyze and print query execution plans
969
+ * await printQueriesWithPlan(); // Analyze and print query execution plans
907
970
  * } else if (totalDbExecutionTime > threshold) {
908
971
  * console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
909
972
  * }
@@ -926,12 +989,12 @@ class ForgeSQLORM implements ForgeSqlOperation {
926
989
  * .where(eq(demoOrders.userId, demoUsers.id));
927
990
  * return { users, orders };
928
991
  * },
929
- * async (totalDbExecutionTime, totalResponseSize, printQueries) => {
992
+ * async (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
930
993
  * const threshold = 500; // ms baseline for this resolver
931
994
  *
932
995
  * if (totalDbExecutionTime > threshold * 1.5) {
933
996
  * console.warn(`[Performance Warning fetch] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
934
- * await printQueries(); // Optionally log or capture diagnostics for further analysis
997
+ * await printQueriesWithPlan(); // Optionally log or capture diagnostics for further analysis
935
998
  * } else if (totalDbExecutionTime > threshold) {
936
999
  * console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
937
1000
  * }
@@ -947,7 +1010,7 @@ class ForgeSQLORM implements ForgeSqlOperation {
947
1010
  * });
948
1011
  * ```
949
1012
  *
950
- * @note **Important**: When multiple resolvers are running concurrently, their query data may also appear in `printQueries()` analysis, as it queries the global `CLUSTER_STATEMENTS_SUMMARY` table.
1013
+ * @note **Important**: When multiple resolvers are running concurrently, their query data may also appear in `printQueriesWithPlan()` analysis, as it queries the global `CLUSTER_STATEMENTS_SUMMARY` table.
951
1014
  */
952
1015
  async executeWithMetadata<T>(
953
1016
  query: () => Promise<T>,
@@ -956,8 +1019,9 @@ class ForgeSQLORM implements ForgeSqlOperation {
956
1019
  totalResponseSize: number,
957
1020
  printQueriesWithPlan: () => Promise<void>,
958
1021
  ) => Promise<void> | void,
1022
+ options?: MetadataQueryOptions,
959
1023
  ): Promise<T> {
960
- return this.ormInstance.executeWithMetadata(query, onMetadata);
1024
+ return this.ormInstance.executeWithMetadata(query, onMetadata, options);
961
1025
  }
962
1026
 
963
1027
  selectCacheable<TSelection extends SelectedFields>(
@@ -6,6 +6,7 @@ import {
6
6
  customType,
7
7
  MySqlSelectBuilder,
8
8
  MySqlTable,
9
+ MySqlColumn,
9
10
  } from "drizzle-orm/mysql-core";
10
11
  import {
11
12
  MySqlSelectDynamic,
@@ -56,7 +57,7 @@ import { SQLWrapper } from "drizzle-orm/sql/sql";
56
57
  import type { MySqlQueryResultKind } from "drizzle-orm/mysql-core/session";
57
58
  import type { WithBuilder } from "drizzle-orm/mysql-core/subquery";
58
59
  import { WithSubquery } from "drizzle-orm/subquery";
59
- import { MySqlColumn } from "drizzle-orm/mysql-core";
60
+ import { MetadataQueryOptions } from "../utils/metadataContextUtils";
60
61
 
61
62
  /**
62
63
  * Core interface for ForgeSQL operations.
@@ -585,7 +586,15 @@ export interface QueryBuilderForgeSql {
585
586
  * @param onMetadata - Callback function that receives aggregated execution metadata
586
587
  * @param onMetadata.totalDbExecutionTime - Total database execution time across all operations in the query function (in milliseconds)
587
588
  * @param onMetadata.totalResponseSize - Total response size across all operations (in bytes)
588
- * @param onMetadata.printQueries - Function to analyze and print query execution plans from CLUSTER_STATEMENTS_SUMMARY
589
+ * @param onMetadata.printQueriesWithPlan - Function to analyze and print query execution plans. Supports two modes:
590
+ * - TopSlowest: Prints execution plans for the slowest queries from the current resolver (default)
591
+ * - SummaryTable: Uses CLUSTER_STATEMENTS_SUMMARY if within time window
592
+ * @param options - Optional configuration for query plan printing behavior
593
+ * @param options.mode - Query plan printing mode: 'TopSlowest' (default) or 'SummaryTable'
594
+ * @param options.summaryTableWindowTime - Time window in milliseconds for summary table queries (default: 15000ms). Only used when mode is 'SummaryTable'
595
+ * @param options.topQueries - Number of top slowest queries to analyze when mode is 'TopSlowest' (default: 1)
596
+ * @param options.showSlowestPlans - Whether to show execution plans for slowest queries in TopSlowest mode (default: true)
597
+ * @param options.normalizeQuery - Whether to normalize SQL queries by replacing parameter values with '?' placeholders (default: true). Set to false to disable normalization if it causes issues
589
598
  * @returns Promise with the query result
590
599
  *
591
600
  * @example
@@ -597,12 +606,12 @@ export interface QueryBuilderForgeSql {
597
606
  * const orders = await forgeSQL.selectFrom(ordersTable).where(eq(ordersTable.userId, usersTable.id));
598
607
  * return { users, orders };
599
608
  * },
600
- * (totalDbExecutionTime, totalResponseSize, printQueries) => {
609
+ * (totalDbExecutionTime, totalResponseSize, printQueriesWithPlan) => {
601
610
  * const threshold = 500; // ms baseline for this resolver
602
611
  *
603
612
  * if (totalDbExecutionTime > threshold * 1.5) {
604
613
  * console.warn(`[Performance Warning] Resolver exceeded DB time: ${totalDbExecutionTime} ms`);
605
- * await printQueries(); // Analyze and print query execution plans
614
+ * await printQueriesWithPlan(); // Analyze and print query execution plans
606
615
  * } else if (totalDbExecutionTime > threshold) {
607
616
  * console.debug(`[Performance Debug] High DB time: ${totalDbExecutionTime} ms`);
608
617
  * }
@@ -655,6 +664,7 @@ export interface QueryBuilderForgeSql {
655
664
  totalResponseSize: number,
656
665
  printQueriesWithPlan: () => Promise<void>,
657
666
  ) => Promise<void> | void,
667
+ options?: MetadataQueryOptions,
658
668
  ): Promise<T>;
659
669
  /**
660
670
  * Executes a raw SQL query with local cache support.
@@ -1015,7 +1025,7 @@ export interface SchemaSqlForgeSql {
1015
1025
  * @returns {Promise<T[]>} A list of results as objects
1016
1026
  * @throws {Error} If the query execution fails
1017
1027
  */
1018
- executeRawSQL<T extends object | unknown>(query: string, params?: SqlParameters[]): Promise<T[]>;
1028
+ executeRawSQL<T>(query: string, params?: SqlParameters[]): Promise<T[]>;
1019
1029
 
1020
1030
  /**
1021
1031
  * Executes a raw SQL update query.
@@ -4,6 +4,7 @@ import {
4
4
  AnyMySqlSelectQueryBuilder,
5
5
  MySqlSelectDynamic,
6
6
  } from "drizzle-orm/mysql-core/query-builders/select.types";
7
+ import { SqlParameters } from "@forge/sql/out/sql-statement";
7
8
 
8
9
  /**
9
10
  * Class implementing SQL select operations for ForgeSQL ORM.
@@ -55,7 +56,7 @@ export class ForgeSQLSelectOperations implements SchemaSqlForgeSql {
55
56
  * @param {SqlParameters[]} [params] - Optional SQL parameters
56
57
  * @returns {Promise<T[]>} A list of results as objects
57
58
  */
58
- async executeRawSQL<T extends object | unknown>(query: string, params?: unknown[]): Promise<T[]> {
59
+ async executeRawSQL<T>(query: string, params?: SqlParameters[]): Promise<T[]> {
59
60
  if (this.options.logRawSqlQuery) {
60
61
  const paramsStr = params ? `, with params: ${JSON.stringify(params)}` : "";
61
62
  // eslint-disable-next-line no-console