forge-sql-orm 2.1.2 → 2.1.3
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 -55
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +80 -55
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +1 -2
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/utils/cacheUtils.d.ts.map +1 -1
- package/dist/utils/forgeDriver.d.ts.map +1 -1
- package/dist/utils/forgeDriverProxy.d.ts.map +1 -1
- package/dist/utils/sqlUtils.d.ts +1 -1
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/dist/webtriggers/applyMigrationsWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/dropTablesMigrationWebTrigger.d.ts.map +1 -1
- package/dist/webtriggers/fetchSchemaWebTrigger.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/core/ForgeSQLQueryBuilder.ts +13 -9
- package/src/lib/drizzle/extensions/additionalActions.ts +2 -2
- package/src/utils/cacheContextUtils.ts +2 -2
- package/src/utils/cacheUtils.ts +3 -1
- package/src/utils/forgeDriver.ts +16 -21
- package/src/utils/forgeDriverProxy.ts +10 -3
- package/src/utils/sqlUtils.ts +32 -7
- package/src/webtriggers/applyMigrationsWebTrigger.ts +18 -14
- package/src/webtriggers/dropMigrationWebTrigger.ts +8 -4
- package/src/webtriggers/dropTablesMigrationWebTrigger.ts +8 -4
- package/src/webtriggers/fetchSchemaWebTrigger.ts +7 -3
package/dist/ForgeSQLORM.mjs
CHANGED
|
@@ -17,11 +17,16 @@ const parseDateTime = (value, format) => {
|
|
|
17
17
|
if (dt.isValid) {
|
|
18
18
|
result = dt.toJSDate();
|
|
19
19
|
} else {
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
result =
|
|
20
|
+
const sqlDt = DateTime.fromSQL(value);
|
|
21
|
+
if (sqlDt.isValid) {
|
|
22
|
+
result = sqlDt.toJSDate();
|
|
23
23
|
} else {
|
|
24
|
-
|
|
24
|
+
const isoDt = DateTime.fromRFC2822(value);
|
|
25
|
+
if (isoDt.isValid) {
|
|
26
|
+
result = isoDt.toJSDate();
|
|
27
|
+
} else {
|
|
28
|
+
result = new Date(value);
|
|
29
|
+
}
|
|
25
30
|
}
|
|
26
31
|
}
|
|
27
32
|
}
|
|
@@ -30,7 +35,7 @@ const parseDateTime = (value, format) => {
|
|
|
30
35
|
}
|
|
31
36
|
return result;
|
|
32
37
|
};
|
|
33
|
-
function formatDateTime(value, format) {
|
|
38
|
+
function formatDateTime(value, format, isTimeStamp) {
|
|
34
39
|
let dt = null;
|
|
35
40
|
if (value instanceof Date) {
|
|
36
41
|
dt = DateTime.fromJSDate(value);
|
|
@@ -58,6 +63,20 @@ function formatDateTime(value, format) {
|
|
|
58
63
|
if (!dt?.isValid) {
|
|
59
64
|
throw new Error("Invalid Date");
|
|
60
65
|
}
|
|
66
|
+
const minDate = DateTime.fromSeconds(1);
|
|
67
|
+
const maxDate = DateTime.fromMillis(2147483647 * 1e3);
|
|
68
|
+
if (isTimeStamp) {
|
|
69
|
+
if (dt < minDate) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
"Atlassian Forge does not support zero or negative timestamps. Allowed range: from '1970-01-01 00:00:01.000000' to '2038-01-19 03:14:07.999999'."
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (dt > maxDate) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
"Atlassian Forge does not support timestamps beyond 2038-01-19 03:14:07.999999. Please use a smaller date within the supported range."
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
61
80
|
return dt.toFormat(format);
|
|
62
81
|
}
|
|
63
82
|
function getPrimaryKeys(table) {
|
|
@@ -461,7 +480,9 @@ async function clearExpiredCache(options) {
|
|
|
461
480
|
);
|
|
462
481
|
} finally {
|
|
463
482
|
const duration = DateTime.now().toSeconds() - startTime.toSeconds();
|
|
464
|
-
|
|
483
|
+
if (options?.logRawSqlQuery) {
|
|
484
|
+
console.debug(`Cleared ${totalRecords} expired cache records in ${duration} seconds`);
|
|
485
|
+
}
|
|
465
486
|
}
|
|
466
487
|
}
|
|
467
488
|
async function getFromCache(query, options) {
|
|
@@ -548,7 +569,7 @@ async function saveQueryLocalCacheQuery(query, rows, options) {
|
|
|
548
569
|
};
|
|
549
570
|
if (options.logRawSqlQuery) {
|
|
550
571
|
const q = sql2.toSQL();
|
|
551
|
-
console.
|
|
572
|
+
console.debug(
|
|
552
573
|
`[forge-sql-orm][local-cache][SAVE] Stored result in cache. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
553
574
|
);
|
|
554
575
|
}
|
|
@@ -565,7 +586,7 @@ async function getQueryLocalCacheQuery(query, options) {
|
|
|
565
586
|
if (context.cache[key] && context.cache[key].sql === sql2.toSQL().sql.toLowerCase()) {
|
|
566
587
|
if (options.logRawSqlQuery) {
|
|
567
588
|
const q = sql2.toSQL();
|
|
568
|
-
console.
|
|
589
|
+
console.debug(
|
|
569
590
|
`[forge-sql-orm][local-cache][HIT] Returned cached result. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
570
591
|
);
|
|
571
592
|
}
|
|
@@ -995,28 +1016,23 @@ class ForgeSQLSelectOperations {
|
|
|
995
1016
|
}
|
|
996
1017
|
}
|
|
997
1018
|
const forgeDriver = async (query, params, method) => {
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
sqlStatement.bindParams(...params);
|
|
1003
|
-
}
|
|
1004
|
-
const updateQueryResponseResults = await sqlStatement.execute();
|
|
1005
|
-
let result = updateQueryResponseResults.rows;
|
|
1006
|
-
return { ...result, rows: [result] };
|
|
1007
|
-
} else {
|
|
1008
|
-
const sqlStatement = await sql$1.prepare(query);
|
|
1009
|
-
if (params) {
|
|
1010
|
-
await sqlStatement.bindParams(...params);
|
|
1011
|
-
}
|
|
1012
|
-
const result = await sqlStatement.execute();
|
|
1013
|
-
let rows;
|
|
1014
|
-
rows = result.rows.map((r) => Object.values(r));
|
|
1015
|
-
return { rows };
|
|
1019
|
+
if (method == "execute") {
|
|
1020
|
+
const sqlStatement = sql$1.prepare(query);
|
|
1021
|
+
if (params) {
|
|
1022
|
+
sqlStatement.bindParams(...params);
|
|
1016
1023
|
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1024
|
+
const updateQueryResponseResults = await sqlStatement.execute();
|
|
1025
|
+
let result = updateQueryResponseResults.rows;
|
|
1026
|
+
return { ...result, rows: [result] };
|
|
1027
|
+
} else {
|
|
1028
|
+
const sqlStatement = await sql$1.prepare(query);
|
|
1029
|
+
if (params) {
|
|
1030
|
+
await sqlStatement.bindParams(...params);
|
|
1031
|
+
}
|
|
1032
|
+
const result = await sqlStatement.execute();
|
|
1033
|
+
let rows;
|
|
1034
|
+
rows = result.rows.map((r) => Object.values(r));
|
|
1035
|
+
return { rows };
|
|
1020
1036
|
}
|
|
1021
1037
|
};
|
|
1022
1038
|
function injectSqlHints(query, hints) {
|
|
@@ -1053,9 +1069,16 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
|
|
|
1053
1069
|
return async (query, params, method) => {
|
|
1054
1070
|
const modifiedQuery = injectSqlHints(query, options);
|
|
1055
1071
|
if (options && logRawSqlQuery && modifiedQuery !== query) {
|
|
1056
|
-
console.
|
|
1072
|
+
console.debug("injected Hints: " + modifiedQuery);
|
|
1073
|
+
}
|
|
1074
|
+
try {
|
|
1075
|
+
return await forgeDriver(modifiedQuery, params, method);
|
|
1076
|
+
} catch (error) {
|
|
1077
|
+
if (logRawSqlQuery) {
|
|
1078
|
+
console.debug("SQL Error:", JSON.stringify(error));
|
|
1079
|
+
}
|
|
1080
|
+
throw error;
|
|
1057
1081
|
}
|
|
1058
|
-
return forgeDriver(modifiedQuery, params, method);
|
|
1059
1082
|
};
|
|
1060
1083
|
}
|
|
1061
1084
|
const NON_CACHE_CLEARING_ERROR_CODES = ["VALIDATION_ERROR", "CONSTRAINT_ERROR"];
|
|
@@ -1090,8 +1113,8 @@ async function handleSuccessfulExecution(rows, onfulfilled, table, options, isCa
|
|
|
1090
1113
|
if (shouldClearCacheOnError(error)) {
|
|
1091
1114
|
await evictLocalCacheQuery(table, options);
|
|
1092
1115
|
if (isCached) {
|
|
1093
|
-
await clearCache(table, options).catch(() => {
|
|
1094
|
-
console.warn("Ignore cache clear errors");
|
|
1116
|
+
await clearCache(table, options).catch((e) => {
|
|
1117
|
+
console.warn("Ignore cache clear errors", e);
|
|
1095
1118
|
});
|
|
1096
1119
|
} else {
|
|
1097
1120
|
await saveTableIfInsideCacheContext(table);
|
|
@@ -2553,10 +2576,10 @@ const forgeDateTimeString = customType({
|
|
|
2553
2576
|
return "datetime";
|
|
2554
2577
|
},
|
|
2555
2578
|
toDriver(value) {
|
|
2556
|
-
return formatDateTime(value, "yyyy-
|
|
2579
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", false);
|
|
2557
2580
|
},
|
|
2558
2581
|
fromDriver(value) {
|
|
2559
|
-
const format = "yyyy-
|
|
2582
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2560
2583
|
return parseDateTime(value, format);
|
|
2561
2584
|
}
|
|
2562
2585
|
});
|
|
@@ -2565,10 +2588,10 @@ const forgeTimestampString = customType({
|
|
|
2565
2588
|
return "timestamp";
|
|
2566
2589
|
},
|
|
2567
2590
|
toDriver(value) {
|
|
2568
|
-
return formatDateTime(value, "yyyy-
|
|
2591
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", true);
|
|
2569
2592
|
},
|
|
2570
2593
|
fromDriver(value) {
|
|
2571
|
-
const format = "yyyy-
|
|
2594
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2572
2595
|
return parseDateTime(value, format);
|
|
2573
2596
|
}
|
|
2574
2597
|
});
|
|
@@ -2577,10 +2600,10 @@ const forgeDateString = customType({
|
|
|
2577
2600
|
return "date";
|
|
2578
2601
|
},
|
|
2579
2602
|
toDriver(value) {
|
|
2580
|
-
return formatDateTime(value, "yyyy-
|
|
2603
|
+
return formatDateTime(value, "yyyy-MM-dd", false);
|
|
2581
2604
|
},
|
|
2582
2605
|
fromDriver(value) {
|
|
2583
|
-
const format = "yyyy-
|
|
2606
|
+
const format = "yyyy-MM-dd";
|
|
2584
2607
|
return parseDateTime(value, format);
|
|
2585
2608
|
}
|
|
2586
2609
|
});
|
|
@@ -2589,7 +2612,7 @@ const forgeTimeString = customType({
|
|
|
2589
2612
|
return "time";
|
|
2590
2613
|
},
|
|
2591
2614
|
toDriver(value) {
|
|
2592
|
-
return formatDateTime(value, "HH:mm:ss.SSS");
|
|
2615
|
+
return formatDateTime(value, "HH:mm:ss.SSS", false);
|
|
2593
2616
|
},
|
|
2594
2617
|
fromDriver(value) {
|
|
2595
2618
|
return parseDateTime(value, "HH:mm:ss.SSS");
|
|
@@ -2610,7 +2633,7 @@ async function dropSchemaMigrations() {
|
|
|
2610
2633
|
const tables = await getTables();
|
|
2611
2634
|
const dropStatements = generateDropTableStatements(tables, { sequence: true, table: true });
|
|
2612
2635
|
for (const statement of dropStatements) {
|
|
2613
|
-
console.
|
|
2636
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2614
2637
|
await sql$1.executeDDL(statement);
|
|
2615
2638
|
}
|
|
2616
2639
|
return getHttpResponse(
|
|
@@ -2618,8 +2641,8 @@ async function dropSchemaMigrations() {
|
|
|
2618
2641
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2619
2642
|
);
|
|
2620
2643
|
} catch (error) {
|
|
2621
|
-
|
|
2622
|
-
|
|
2644
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2645
|
+
console.error(errorMessage);
|
|
2623
2646
|
return getHttpResponse(500, errorMessage);
|
|
2624
2647
|
}
|
|
2625
2648
|
}
|
|
@@ -2635,7 +2658,13 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2635
2658
|
const successfulMigrations = await migrations2.run();
|
|
2636
2659
|
console.info("Migrations applied:", successfulMigrations);
|
|
2637
2660
|
const migrationList = await migrationRunner.list();
|
|
2638
|
-
|
|
2661
|
+
let migrationHistory = "No migrations found";
|
|
2662
|
+
if (Array.isArray(migrationList) && migrationList.length > 0) {
|
|
2663
|
+
const sortedMigrations = migrationList.toSorted(
|
|
2664
|
+
(a, b) => a.migratedAt.getTime() - b.migratedAt.getTime()
|
|
2665
|
+
);
|
|
2666
|
+
migrationHistory = sortedMigrations.map((y) => `${y.id}, ${y.name}, ${y.migratedAt.toUTCString()}`).join("\n");
|
|
2667
|
+
}
|
|
2639
2668
|
console.info("Migrations history:\nid, name, migrated_at\n", migrationHistory);
|
|
2640
2669
|
return {
|
|
2641
2670
|
headers: { "Content-Type": ["application/json"] },
|
|
@@ -2644,12 +2673,8 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2644
2673
|
body: "Migrations successfully executed"
|
|
2645
2674
|
};
|
|
2646
2675
|
} catch (error) {
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
} catch (e) {
|
|
2650
|
-
console.trace("Error stringify:", e);
|
|
2651
|
-
console.error("Error during migration:", error);
|
|
2652
|
-
}
|
|
2676
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2677
|
+
console.error("Error during migration:", errorMessage);
|
|
2653
2678
|
return {
|
|
2654
2679
|
headers: { "Content-Type": ["application/json"] },
|
|
2655
2680
|
statusCode: 500,
|
|
@@ -2665,8 +2690,8 @@ async function fetchSchemaWebTrigger() {
|
|
|
2665
2690
|
const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);
|
|
2666
2691
|
return getHttpResponse(200, sqlStatements.join(";\n"));
|
|
2667
2692
|
} catch (error) {
|
|
2668
|
-
|
|
2669
|
-
|
|
2693
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2694
|
+
console.error(errorMessage);
|
|
2670
2695
|
return getHttpResponse(500, errorMessage);
|
|
2671
2696
|
}
|
|
2672
2697
|
}
|
|
@@ -2693,7 +2718,7 @@ async function dropTableSchemaMigrations() {
|
|
|
2693
2718
|
const tables = await getTables();
|
|
2694
2719
|
const dropStatements = generateDropTableStatements(tables, { sequence: false, table: true });
|
|
2695
2720
|
for (const statement of dropStatements) {
|
|
2696
|
-
console.
|
|
2721
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2697
2722
|
await sql$1.executeDDL(statement);
|
|
2698
2723
|
}
|
|
2699
2724
|
return getHttpResponse(
|
|
@@ -2701,8 +2726,8 @@ async function dropTableSchemaMigrations() {
|
|
|
2701
2726
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2702
2727
|
);
|
|
2703
2728
|
} catch (error) {
|
|
2704
|
-
|
|
2705
|
-
|
|
2729
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2730
|
+
console.error(errorMessage);
|
|
2706
2731
|
return getHttpResponse(500, errorMessage);
|
|
2707
2732
|
}
|
|
2708
2733
|
}
|