forge-sql-orm 2.1.12 → 2.1.14
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 +922 -549
- package/dist/core/ForgeSQLAnalyseOperations.d.ts.map +1 -1
- package/dist/core/ForgeSQLAnalyseOperations.js +257 -0
- package/dist/core/ForgeSQLAnalyseOperations.js.map +1 -0
- package/dist/core/ForgeSQLCacheOperations.js +172 -0
- package/dist/core/ForgeSQLCacheOperations.js.map +1 -0
- package/dist/core/ForgeSQLCrudOperations.js +349 -0
- package/dist/core/ForgeSQLCrudOperations.js.map +1 -0
- package/dist/core/ForgeSQLORM.d.ts +29 -1
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLORM.js +1252 -0
- package/dist/core/ForgeSQLORM.js.map +1 -0
- package/dist/core/ForgeSQLQueryBuilder.d.ts +179 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.js +77 -0
- package/dist/core/ForgeSQLQueryBuilder.js.map +1 -0
- package/dist/core/ForgeSQLSelectOperations.js +81 -0
- package/dist/core/ForgeSQLSelectOperations.js.map +1 -0
- package/dist/core/Rovo.d.ts +116 -0
- package/dist/core/Rovo.d.ts.map +1 -0
- package/dist/core/Rovo.js +647 -0
- package/dist/core/Rovo.js.map +1 -0
- package/dist/core/SystemTables.js +258 -0
- package/dist/core/SystemTables.js.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.js +527 -0
- package/dist/lib/drizzle/extensions/additionalActions.js.map +1 -0
- package/dist/utils/cacheContextUtils.d.ts.map +1 -1
- package/dist/utils/cacheContextUtils.js +198 -0
- package/dist/utils/cacheContextUtils.js.map +1 -0
- package/dist/utils/cacheUtils.d.ts.map +1 -1
- package/dist/utils/cacheUtils.js +383 -0
- package/dist/utils/cacheUtils.js.map +1 -0
- package/dist/utils/forgeDriver.d.ts.map +1 -1
- package/dist/utils/forgeDriver.js +139 -0
- package/dist/utils/forgeDriver.js.map +1 -0
- package/dist/utils/forgeDriverProxy.js +68 -0
- package/dist/utils/forgeDriverProxy.js.map +1 -0
- package/dist/utils/metadataContextUtils.d.ts.map +1 -1
- package/dist/utils/metadataContextUtils.js +26 -0
- package/dist/utils/metadataContextUtils.js.map +1 -0
- package/dist/utils/requestTypeContextUtils.js +10 -0
- package/dist/utils/requestTypeContextUtils.js.map +1 -0
- package/dist/utils/sqlHints.js +52 -0
- package/dist/utils/sqlHints.js.map +1 -0
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/utils/sqlUtils.js +590 -0
- package/dist/utils/sqlUtils.js.map +1 -0
- package/dist/webtriggers/applyMigrationsWebTrigger.js +77 -0
- package/dist/webtriggers/applyMigrationsWebTrigger.js.map +1 -0
- package/dist/webtriggers/clearCacheSchedulerTrigger.js +83 -0
- package/dist/webtriggers/clearCacheSchedulerTrigger.js.map +1 -0
- package/dist/webtriggers/dropMigrationWebTrigger.js +54 -0
- package/dist/webtriggers/dropMigrationWebTrigger.js.map +1 -0
- package/dist/webtriggers/dropTablesMigrationWebTrigger.js +54 -0
- package/dist/webtriggers/dropTablesMigrationWebTrigger.js.map +1 -0
- package/dist/webtriggers/fetchSchemaWebTrigger.js +82 -0
- package/dist/webtriggers/fetchSchemaWebTrigger.js.map +1 -0
- package/dist/webtriggers/index.js +40 -0
- package/dist/webtriggers/index.js.map +1 -0
- package/dist/webtriggers/slowQuerySchedulerTrigger.js +80 -0
- package/dist/webtriggers/slowQuerySchedulerTrigger.js.map +1 -0
- package/package.json +31 -25
- package/src/core/ForgeSQLAnalyseOperations.ts +3 -2
- package/src/core/ForgeSQLORM.ts +64 -0
- package/src/core/ForgeSQLQueryBuilder.ts +200 -1
- package/src/core/Rovo.ts +765 -0
- package/src/lib/drizzle/extensions/additionalActions.ts +11 -0
- package/src/utils/cacheContextUtils.ts +9 -6
- package/src/utils/cacheUtils.ts +6 -4
- package/src/utils/forgeDriver.ts +3 -7
- package/src/utils/metadataContextUtils.ts +1 -3
- package/src/utils/sqlUtils.ts +33 -34
- package/dist/ForgeSQLORM.js +0 -3922
- package/dist/ForgeSQLORM.js.map +0 -1
- package/dist/ForgeSQLORM.mjs +0 -3905
- package/dist/ForgeSQLORM.mjs.map +0 -1
|
@@ -593,6 +593,17 @@ function createAliasedSelectBuilder<TSelection extends SelectedFields>(
|
|
|
593
593
|
}
|
|
594
594
|
};
|
|
595
595
|
}
|
|
596
|
+
if (prop === "catch") {
|
|
597
|
+
return (onrejected: any) => (receiver as any).then(undefined, onrejected);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (prop === "finally") {
|
|
601
|
+
return (onfinally: any) =>
|
|
602
|
+
(receiver as any).then(
|
|
603
|
+
(value: any) => Promise.resolve(value).finally(onfinally),
|
|
604
|
+
(reason: any) => Promise.reject(reason).finally(onfinally),
|
|
605
|
+
);
|
|
606
|
+
}
|
|
596
607
|
|
|
597
608
|
const value = Reflect.get(target, prop, receiver);
|
|
598
609
|
|
|
@@ -159,10 +159,11 @@ export async function getQueryLocalCacheQuery<
|
|
|
159
159
|
} else {
|
|
160
160
|
sql = query as { toSQL: () => Query };
|
|
161
161
|
}
|
|
162
|
-
const
|
|
163
|
-
|
|
162
|
+
const toSQL = sql.toSQL();
|
|
163
|
+
const key = hashKey(toSQL);
|
|
164
|
+
if (context.cache[key] && context.cache[key].sql === toSQL.sql.toLowerCase()) {
|
|
164
165
|
if (options.logCache) {
|
|
165
|
-
const q =
|
|
166
|
+
const q = toSQL;
|
|
166
167
|
// eslint-disable-next-line no-console
|
|
167
168
|
console.debug(
|
|
168
169
|
`[forge-sql-orm][local-cache][HIT] Returned cached result. sql="${q.sql}", params=${JSON.stringify(q.params)}`,
|
|
@@ -201,12 +202,14 @@ export async function evictLocalCacheQuery<T extends AnyMySqlTable>(
|
|
|
201
202
|
const tableName = getTableName(table);
|
|
202
203
|
const searchString = options.cacheWrapTable ? `\`${tableName}\`` : tableName;
|
|
203
204
|
const keyToEvicts: string[] = [];
|
|
204
|
-
Object.keys(context.cache)
|
|
205
|
+
for (const key of Object.keys(context.cache)) {
|
|
205
206
|
if (context.cache[key].sql.includes(searchString)) {
|
|
206
207
|
keyToEvicts.push(key);
|
|
207
208
|
}
|
|
208
|
-
}
|
|
209
|
-
|
|
209
|
+
}
|
|
210
|
+
for (const key of keyToEvicts) {
|
|
211
|
+
delete context.cache[key];
|
|
212
|
+
}
|
|
210
213
|
}
|
|
211
214
|
}
|
|
212
215
|
|
package/src/utils/cacheUtils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DateTime } from "luxon";
|
|
2
|
-
import * as crypto from "crypto";
|
|
2
|
+
import * as crypto from "node:crypto";
|
|
3
3
|
import { Query } from "drizzle-orm";
|
|
4
4
|
import { AnyMySqlTable } from "drizzle-orm/mysql-core";
|
|
5
5
|
import { getTableName } from "drizzle-orm/table";
|
|
@@ -65,7 +65,9 @@ function extractBacktickedValues(sql: string): string {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// Sort to ensure consistent order for the same input
|
|
68
|
-
return Array.from(matches)
|
|
68
|
+
return Array.from(matches)
|
|
69
|
+
.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base", numeric: true }))
|
|
70
|
+
.join(",");
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
/**
|
|
@@ -95,9 +97,9 @@ async function deleteCacheEntriesInBatches(
|
|
|
95
97
|
for (let i = 0; i < results.length; i += CACHE_CONSTANTS.BATCH_SIZE) {
|
|
96
98
|
const batch = results.slice(i, i + CACHE_CONSTANTS.BATCH_SIZE);
|
|
97
99
|
let transactionBuilder = kvs.transact();
|
|
98
|
-
|
|
100
|
+
for (const result of batch) {
|
|
99
101
|
transactionBuilder = transactionBuilder.delete(result.key, { entityName: cacheEntityName });
|
|
100
|
-
}
|
|
102
|
+
}
|
|
101
103
|
await transactionBuilder.execute();
|
|
102
104
|
}
|
|
103
105
|
}
|
package/src/utils/forgeDriver.ts
CHANGED
|
@@ -92,7 +92,7 @@ async function processDDLResult(method: QueryMethod, result: any): Promise<Forge
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
if (isUpdateQueryResponse(result.rows)) {
|
|
95
|
-
const oneRow = result.rows
|
|
95
|
+
const oneRow = result.rows;
|
|
96
96
|
return { ...oneRow, rows: [oneRow] };
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -145,12 +145,8 @@ async function processAllMethod(query: string, params: unknown[]): Promise<Forge
|
|
|
145
145
|
await sqlStatement.bindParams(...params);
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
const result =
|
|
149
|
-
|
|
150
|
-
timeoutMessage,
|
|
151
|
-
timeoutMs,
|
|
152
|
-
)) as ForgeSQLResult;
|
|
153
|
-
await saveMetaDataToContext(result.metadata);
|
|
148
|
+
const result = await withTimeout(sqlStatement.execute(), timeoutMessage, timeoutMs);
|
|
149
|
+
await saveMetaDataToContext(result.metadata as ForgeSQLMetadata);
|
|
154
150
|
|
|
155
151
|
if (!result.rows) {
|
|
156
152
|
return { rows: [] };
|
|
@@ -16,9 +16,7 @@ export async function saveMetaDataToContext(metadata?: ForgeSQLMetadata): Promis
|
|
|
16
16
|
const context = metadataQueryContext.getStore();
|
|
17
17
|
if (context) {
|
|
18
18
|
context.printQueriesWithPlan = async () => {
|
|
19
|
-
|
|
20
|
-
await new Promise((r) => setTimeout(r, 200));
|
|
21
|
-
}
|
|
19
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
22
20
|
await printQueriesWithPlan(context.forgeSQLORM, Date.now() - context.beginTime.getTime());
|
|
23
21
|
};
|
|
24
22
|
if (metadata) {
|
package/src/utils/sqlUtils.ts
CHANGED
|
@@ -93,7 +93,7 @@ export const parseDateTime = (value: string | Date, format: string): Date => {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
// 4. Ensure the result is a valid Date object
|
|
96
|
-
if (isNaN(result.getTime())) {
|
|
96
|
+
if (Number.isNaN(result.getTime())) {
|
|
97
97
|
result = new Date(value);
|
|
98
98
|
}
|
|
99
99
|
return result;
|
|
@@ -127,7 +127,7 @@ export function formatDateTime(
|
|
|
127
127
|
}
|
|
128
128
|
if (!dt?.isValid) {
|
|
129
129
|
const parsed = Number(value);
|
|
130
|
-
if (!isNaN(parsed)) {
|
|
130
|
+
if (!Number.isNaN(parsed)) {
|
|
131
131
|
dt = DateTime.fromMillis(parsed);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -183,17 +183,15 @@ export function getPrimaryKeys<T extends AnyMySqlTable>(table: T): [string, AnyC
|
|
|
183
183
|
// Collect all primary key columns from all primary key builders
|
|
184
184
|
const primaryKeyColumns = new Set<[string, AnyColumn]>();
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
for (const primaryKeyBuilder of primaryKeys) {
|
|
187
187
|
// Get primary key columns from each builder
|
|
188
|
-
Object.entries(columns)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
});
|
|
196
|
-
});
|
|
188
|
+
for (const [name, column1] of Object.entries(columns).filter(([, column]) => {
|
|
189
|
+
// @ts-ignore - PrimaryKeyBuilder has internal columns property
|
|
190
|
+
return primaryKeyBuilder.columns.includes(column);
|
|
191
|
+
})) {
|
|
192
|
+
primaryKeyColumns.add([name, column1]);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
197
195
|
|
|
198
196
|
return Array.from(primaryKeyColumns);
|
|
199
197
|
}
|
|
@@ -220,12 +218,12 @@ function processForeignKeys(
|
|
|
220
218
|
// @ts-ignore
|
|
221
219
|
const fkArray: any[] = table[foreignKeysSymbol];
|
|
222
220
|
if (fkArray) {
|
|
223
|
-
|
|
221
|
+
for (const fk of fkArray) {
|
|
224
222
|
if (fk.reference) {
|
|
225
223
|
const item = fk.reference(fk);
|
|
226
224
|
foreignKeys.push(item);
|
|
227
225
|
}
|
|
228
|
-
}
|
|
226
|
+
}
|
|
229
227
|
}
|
|
230
228
|
}
|
|
231
229
|
|
|
@@ -242,14 +240,14 @@ function processForeignKeys(
|
|
|
242
240
|
(item) => (item as ConfigBuilderData).value ?? item,
|
|
243
241
|
);
|
|
244
242
|
|
|
245
|
-
|
|
246
|
-
if (!builder?.constructor)
|
|
243
|
+
for (const builder of configBuilders) {
|
|
244
|
+
if (!builder?.constructor) continue;
|
|
247
245
|
|
|
248
246
|
const builderName = builder.constructor.name.toLowerCase();
|
|
249
247
|
if (builderName.includes("foreignkeybuilder")) {
|
|
250
248
|
foreignKeys.push(builder);
|
|
251
249
|
}
|
|
252
|
-
}
|
|
250
|
+
}
|
|
253
251
|
}
|
|
254
252
|
}
|
|
255
253
|
}
|
|
@@ -297,8 +295,8 @@ export function getTableMetadata(table: AnyMySqlTable): MetadataInfo {
|
|
|
297
295
|
);
|
|
298
296
|
|
|
299
297
|
// Process each builder
|
|
300
|
-
|
|
301
|
-
if (!builder?.constructor)
|
|
298
|
+
for (const builder of configBuilders) {
|
|
299
|
+
if (!builder?.constructor) continue;
|
|
302
300
|
|
|
303
301
|
const builderName = builder.constructor.name.toLowerCase();
|
|
304
302
|
|
|
@@ -320,7 +318,7 @@ export function getTableMetadata(table: AnyMySqlTable): MetadataInfo {
|
|
|
320
318
|
|
|
321
319
|
// Always add to extras array
|
|
322
320
|
builders.extras.push(builder);
|
|
323
|
-
}
|
|
321
|
+
}
|
|
324
322
|
}
|
|
325
323
|
}
|
|
326
324
|
}
|
|
@@ -352,14 +350,14 @@ export function generateDropTableStatements(
|
|
|
352
350
|
console.warn('No drop operations requested: both "table" and "sequence" options are false');
|
|
353
351
|
return [];
|
|
354
352
|
}
|
|
355
|
-
|
|
353
|
+
for (const tableName of tables) {
|
|
356
354
|
if (validOptions.table) {
|
|
357
355
|
dropStatements.push(`DROP TABLE IF EXISTS \`${tableName}\`;`);
|
|
358
356
|
}
|
|
359
357
|
if (validOptions.sequence) {
|
|
360
358
|
dropStatements.push(`DROP SEQUENCE IF EXISTS \`${tableName}\`;`);
|
|
361
359
|
}
|
|
362
|
-
}
|
|
360
|
+
}
|
|
363
361
|
|
|
364
362
|
return dropStatements;
|
|
365
363
|
}
|
|
@@ -373,13 +371,13 @@ function mapSelectTableToAlias(
|
|
|
373
371
|
): any {
|
|
374
372
|
const { columns, tableName } = getTableMetadata(table);
|
|
375
373
|
const selectionsTableFields: Record<string, unknown> = {};
|
|
376
|
-
Object.keys(columns)
|
|
374
|
+
for (const name of Object.keys(columns)) {
|
|
377
375
|
const column = columns[name] as AnyColumn;
|
|
378
376
|
const uniqName = `a_${uniqPrefix}_${tableName}_${column.name}`.toLowerCase();
|
|
379
377
|
const fieldAlias = sql.raw(uniqName);
|
|
380
378
|
selectionsTableFields[name] = sql`${column} as \`${fieldAlias}\``;
|
|
381
379
|
aliasMap[uniqName] = column;
|
|
382
|
-
}
|
|
380
|
+
}
|
|
383
381
|
return selectionsTableFields;
|
|
384
382
|
}
|
|
385
383
|
|
|
@@ -406,9 +404,9 @@ export function mapSelectAllFieldsToAlias(
|
|
|
406
404
|
selections[name] = fields;
|
|
407
405
|
} else {
|
|
408
406
|
const innerSelections: any = {};
|
|
409
|
-
|
|
407
|
+
for (const [iname, ifields] of Object.entries(fields)) {
|
|
410
408
|
mapSelectAllFieldsToAlias(innerSelections, iname, `${uniqName}_${iname}`, ifields, aliasMap);
|
|
411
|
-
}
|
|
409
|
+
}
|
|
412
410
|
selections[name] = innerSelections;
|
|
413
411
|
}
|
|
414
412
|
return selections;
|
|
@@ -421,9 +419,10 @@ export function mapSelectFieldsWithAlias<TSelection extends SelectedFields>(
|
|
|
421
419
|
}
|
|
422
420
|
const aliasMap: AliasColumnMap = {};
|
|
423
421
|
const selections: any = {};
|
|
424
|
-
Object.entries(fields).
|
|
425
|
-
|
|
426
|
-
|
|
422
|
+
for (let i = 0; i < Object.entries(fields).length; i++) {
|
|
423
|
+
const [name, fields1] = Object.entries(fields)[i];
|
|
424
|
+
mapSelectAllFieldsToAlias(selections, name, name, fields1, aliasMap);
|
|
425
|
+
}
|
|
427
426
|
return { selections, aliasMap };
|
|
428
427
|
}
|
|
429
428
|
|
|
@@ -546,7 +545,7 @@ function processNullBranches(obj: Record<string, unknown>): Record<string, unkno
|
|
|
546
545
|
}
|
|
547
546
|
|
|
548
547
|
export function formatLimitOffset(limitOrOffset: number): number {
|
|
549
|
-
if (typeof limitOrOffset !== "number" || isNaN(limitOrOffset)) {
|
|
548
|
+
if (typeof limitOrOffset !== "number" || Number.isNaN(limitOrOffset)) {
|
|
550
549
|
throw new Error("limitOrOffset must be a valid number");
|
|
551
550
|
}
|
|
552
551
|
return sql.raw(`${limitOrOffset}`) as unknown as number;
|
|
@@ -628,7 +627,7 @@ export async function printQueriesWithPlan(
|
|
|
628
627
|
timeoutMs + 200,
|
|
629
628
|
);
|
|
630
629
|
|
|
631
|
-
|
|
630
|
+
for (const result of results) {
|
|
632
631
|
// Average execution time (convert from nanoseconds to milliseconds)
|
|
633
632
|
const avgTimeMs = Number(result.avgLatency) / 1_000_000;
|
|
634
633
|
const avgMemMB = Number(result.avgMem) / 1_000_000;
|
|
@@ -638,7 +637,7 @@ export async function printQueriesWithPlan(
|
|
|
638
637
|
console.warn(
|
|
639
638
|
`SQL: ${result.digestText} | Memory: ${avgMemMB.toFixed(2)} MB | Time: ${avgTimeMs.toFixed(2)} ms | stmtType: ${result.stmtType} | Executions: ${result.execCount}\n Plan:${result.plan}`,
|
|
640
639
|
);
|
|
641
|
-
}
|
|
640
|
+
}
|
|
642
641
|
} catch (error) {
|
|
643
642
|
// eslint-disable-next-line no-console
|
|
644
643
|
console.debug(
|
|
@@ -714,7 +713,7 @@ export async function slowQueryPerHours(
|
|
|
714
713
|
timeoutMs,
|
|
715
714
|
);
|
|
716
715
|
const response: string[] = [];
|
|
717
|
-
|
|
716
|
+
for (const result of results) {
|
|
718
717
|
// Convert memory from bytes to MB and handle null values
|
|
719
718
|
const memMaxMB = result.memMax ? Number(result.memMax) / 1_000_000 : 0;
|
|
720
719
|
|
|
@@ -723,7 +722,7 @@ export async function slowQueryPerHours(
|
|
|
723
722
|
// 1. Query info: SQL, memory, time, executions
|
|
724
723
|
// eslint-disable-next-line no-console
|
|
725
724
|
console.warn(message);
|
|
726
|
-
}
|
|
725
|
+
}
|
|
727
726
|
return response;
|
|
728
727
|
} catch (error) {
|
|
729
728
|
// eslint-disable-next-line no-console
|