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.js
CHANGED
|
@@ -36,11 +36,16 @@ const parseDateTime = (value, format) => {
|
|
|
36
36
|
if (dt.isValid) {
|
|
37
37
|
result = dt.toJSDate();
|
|
38
38
|
} else {
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
result =
|
|
39
|
+
const sqlDt = luxon.DateTime.fromSQL(value);
|
|
40
|
+
if (sqlDt.isValid) {
|
|
41
|
+
result = sqlDt.toJSDate();
|
|
42
42
|
} else {
|
|
43
|
-
|
|
43
|
+
const isoDt = luxon.DateTime.fromRFC2822(value);
|
|
44
|
+
if (isoDt.isValid) {
|
|
45
|
+
result = isoDt.toJSDate();
|
|
46
|
+
} else {
|
|
47
|
+
result = new Date(value);
|
|
48
|
+
}
|
|
44
49
|
}
|
|
45
50
|
}
|
|
46
51
|
}
|
|
@@ -49,7 +54,7 @@ const parseDateTime = (value, format) => {
|
|
|
49
54
|
}
|
|
50
55
|
return result;
|
|
51
56
|
};
|
|
52
|
-
function formatDateTime(value, format) {
|
|
57
|
+
function formatDateTime(value, format, isTimeStamp) {
|
|
53
58
|
let dt = null;
|
|
54
59
|
if (value instanceof Date) {
|
|
55
60
|
dt = luxon.DateTime.fromJSDate(value);
|
|
@@ -77,6 +82,20 @@ function formatDateTime(value, format) {
|
|
|
77
82
|
if (!dt?.isValid) {
|
|
78
83
|
throw new Error("Invalid Date");
|
|
79
84
|
}
|
|
85
|
+
const minDate = luxon.DateTime.fromSeconds(1);
|
|
86
|
+
const maxDate = luxon.DateTime.fromMillis(2147483647 * 1e3);
|
|
87
|
+
if (isTimeStamp) {
|
|
88
|
+
if (dt < minDate) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
"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'."
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
if (dt > maxDate) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
"Atlassian Forge does not support timestamps beyond 2038-01-19 03:14:07.999999. Please use a smaller date within the supported range."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
80
99
|
return dt.toFormat(format);
|
|
81
100
|
}
|
|
82
101
|
function getPrimaryKeys(table2) {
|
|
@@ -480,7 +499,9 @@ async function clearExpiredCache(options) {
|
|
|
480
499
|
);
|
|
481
500
|
} finally {
|
|
482
501
|
const duration = luxon.DateTime.now().toSeconds() - startTime.toSeconds();
|
|
483
|
-
|
|
502
|
+
if (options?.logRawSqlQuery) {
|
|
503
|
+
console.debug(`Cleared ${totalRecords} expired cache records in ${duration} seconds`);
|
|
504
|
+
}
|
|
484
505
|
}
|
|
485
506
|
}
|
|
486
507
|
async function getFromCache(query, options) {
|
|
@@ -567,7 +588,7 @@ async function saveQueryLocalCacheQuery(query, rows, options) {
|
|
|
567
588
|
};
|
|
568
589
|
if (options.logRawSqlQuery) {
|
|
569
590
|
const q = sql2.toSQL();
|
|
570
|
-
console.
|
|
591
|
+
console.debug(
|
|
571
592
|
`[forge-sql-orm][local-cache][SAVE] Stored result in cache. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
572
593
|
);
|
|
573
594
|
}
|
|
@@ -584,7 +605,7 @@ async function getQueryLocalCacheQuery(query, options) {
|
|
|
584
605
|
if (context.cache[key] && context.cache[key].sql === sql2.toSQL().sql.toLowerCase()) {
|
|
585
606
|
if (options.logRawSqlQuery) {
|
|
586
607
|
const q = sql2.toSQL();
|
|
587
|
-
console.
|
|
608
|
+
console.debug(
|
|
588
609
|
`[forge-sql-orm][local-cache][HIT] Returned cached result. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
589
610
|
);
|
|
590
611
|
}
|
|
@@ -1014,28 +1035,23 @@ class ForgeSQLSelectOperations {
|
|
|
1014
1035
|
}
|
|
1015
1036
|
}
|
|
1016
1037
|
const forgeDriver = async (query, params, method) => {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
sqlStatement.bindParams(...params);
|
|
1022
|
-
}
|
|
1023
|
-
const updateQueryResponseResults = await sqlStatement.execute();
|
|
1024
|
-
let result = updateQueryResponseResults.rows;
|
|
1025
|
-
return { ...result, rows: [result] };
|
|
1026
|
-
} else {
|
|
1027
|
-
const sqlStatement = await sql$1.sql.prepare(query);
|
|
1028
|
-
if (params) {
|
|
1029
|
-
await sqlStatement.bindParams(...params);
|
|
1030
|
-
}
|
|
1031
|
-
const result = await sqlStatement.execute();
|
|
1032
|
-
let rows;
|
|
1033
|
-
rows = result.rows.map((r) => Object.values(r));
|
|
1034
|
-
return { rows };
|
|
1038
|
+
if (method == "execute") {
|
|
1039
|
+
const sqlStatement = sql$1.sql.prepare(query);
|
|
1040
|
+
if (params) {
|
|
1041
|
+
sqlStatement.bindParams(...params);
|
|
1035
1042
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1043
|
+
const updateQueryResponseResults = await sqlStatement.execute();
|
|
1044
|
+
let result = updateQueryResponseResults.rows;
|
|
1045
|
+
return { ...result, rows: [result] };
|
|
1046
|
+
} else {
|
|
1047
|
+
const sqlStatement = await sql$1.sql.prepare(query);
|
|
1048
|
+
if (params) {
|
|
1049
|
+
await sqlStatement.bindParams(...params);
|
|
1050
|
+
}
|
|
1051
|
+
const result = await sqlStatement.execute();
|
|
1052
|
+
let rows;
|
|
1053
|
+
rows = result.rows.map((r) => Object.values(r));
|
|
1054
|
+
return { rows };
|
|
1039
1055
|
}
|
|
1040
1056
|
};
|
|
1041
1057
|
function injectSqlHints(query, hints) {
|
|
@@ -1072,9 +1088,16 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
|
|
|
1072
1088
|
return async (query, params, method) => {
|
|
1073
1089
|
const modifiedQuery = injectSqlHints(query, options);
|
|
1074
1090
|
if (options && logRawSqlQuery && modifiedQuery !== query) {
|
|
1075
|
-
console.
|
|
1091
|
+
console.debug("injected Hints: " + modifiedQuery);
|
|
1092
|
+
}
|
|
1093
|
+
try {
|
|
1094
|
+
return await forgeDriver(modifiedQuery, params, method);
|
|
1095
|
+
} catch (error) {
|
|
1096
|
+
if (logRawSqlQuery) {
|
|
1097
|
+
console.debug("SQL Error:", JSON.stringify(error));
|
|
1098
|
+
}
|
|
1099
|
+
throw error;
|
|
1076
1100
|
}
|
|
1077
|
-
return forgeDriver(modifiedQuery, params, method);
|
|
1078
1101
|
};
|
|
1079
1102
|
}
|
|
1080
1103
|
const NON_CACHE_CLEARING_ERROR_CODES = ["VALIDATION_ERROR", "CONSTRAINT_ERROR"];
|
|
@@ -1109,8 +1132,8 @@ async function handleSuccessfulExecution(rows, onfulfilled, table2, options, isC
|
|
|
1109
1132
|
if (shouldClearCacheOnError(error)) {
|
|
1110
1133
|
await evictLocalCacheQuery(table2, options);
|
|
1111
1134
|
if (isCached) {
|
|
1112
|
-
await clearCache(table2, options).catch(() => {
|
|
1113
|
-
console.warn("Ignore cache clear errors");
|
|
1135
|
+
await clearCache(table2, options).catch((e) => {
|
|
1136
|
+
console.warn("Ignore cache clear errors", e);
|
|
1114
1137
|
});
|
|
1115
1138
|
} else {
|
|
1116
1139
|
await saveTableIfInsideCacheContext(table2);
|
|
@@ -2572,10 +2595,10 @@ const forgeDateTimeString = mysqlCore.customType({
|
|
|
2572
2595
|
return "datetime";
|
|
2573
2596
|
},
|
|
2574
2597
|
toDriver(value) {
|
|
2575
|
-
return formatDateTime(value, "yyyy-
|
|
2598
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", false);
|
|
2576
2599
|
},
|
|
2577
2600
|
fromDriver(value) {
|
|
2578
|
-
const format = "yyyy-
|
|
2601
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2579
2602
|
return parseDateTime(value, format);
|
|
2580
2603
|
}
|
|
2581
2604
|
});
|
|
@@ -2584,10 +2607,10 @@ const forgeTimestampString = mysqlCore.customType({
|
|
|
2584
2607
|
return "timestamp";
|
|
2585
2608
|
},
|
|
2586
2609
|
toDriver(value) {
|
|
2587
|
-
return formatDateTime(value, "yyyy-
|
|
2610
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", true);
|
|
2588
2611
|
},
|
|
2589
2612
|
fromDriver(value) {
|
|
2590
|
-
const format = "yyyy-
|
|
2613
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2591
2614
|
return parseDateTime(value, format);
|
|
2592
2615
|
}
|
|
2593
2616
|
});
|
|
@@ -2596,10 +2619,10 @@ const forgeDateString = mysqlCore.customType({
|
|
|
2596
2619
|
return "date";
|
|
2597
2620
|
},
|
|
2598
2621
|
toDriver(value) {
|
|
2599
|
-
return formatDateTime(value, "yyyy-
|
|
2622
|
+
return formatDateTime(value, "yyyy-MM-dd", false);
|
|
2600
2623
|
},
|
|
2601
2624
|
fromDriver(value) {
|
|
2602
|
-
const format = "yyyy-
|
|
2625
|
+
const format = "yyyy-MM-dd";
|
|
2603
2626
|
return parseDateTime(value, format);
|
|
2604
2627
|
}
|
|
2605
2628
|
});
|
|
@@ -2608,7 +2631,7 @@ const forgeTimeString = mysqlCore.customType({
|
|
|
2608
2631
|
return "time";
|
|
2609
2632
|
},
|
|
2610
2633
|
toDriver(value) {
|
|
2611
|
-
return formatDateTime(value, "HH:mm:ss.SSS");
|
|
2634
|
+
return formatDateTime(value, "HH:mm:ss.SSS", false);
|
|
2612
2635
|
},
|
|
2613
2636
|
fromDriver(value) {
|
|
2614
2637
|
return parseDateTime(value, "HH:mm:ss.SSS");
|
|
@@ -2629,7 +2652,7 @@ async function dropSchemaMigrations() {
|
|
|
2629
2652
|
const tables = await getTables();
|
|
2630
2653
|
const dropStatements = generateDropTableStatements(tables, { sequence: true, table: true });
|
|
2631
2654
|
for (const statement of dropStatements) {
|
|
2632
|
-
console.
|
|
2655
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2633
2656
|
await sql$1.sql.executeDDL(statement);
|
|
2634
2657
|
}
|
|
2635
2658
|
return getHttpResponse(
|
|
@@ -2637,8 +2660,8 @@ async function dropSchemaMigrations() {
|
|
|
2637
2660
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2638
2661
|
);
|
|
2639
2662
|
} catch (error) {
|
|
2640
|
-
|
|
2641
|
-
|
|
2663
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2664
|
+
console.error(errorMessage);
|
|
2642
2665
|
return getHttpResponse(500, errorMessage);
|
|
2643
2666
|
}
|
|
2644
2667
|
}
|
|
@@ -2654,7 +2677,13 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2654
2677
|
const successfulMigrations = await migrations2.run();
|
|
2655
2678
|
console.info("Migrations applied:", successfulMigrations);
|
|
2656
2679
|
const migrationList = await sql$1.migrationRunner.list();
|
|
2657
|
-
|
|
2680
|
+
let migrationHistory = "No migrations found";
|
|
2681
|
+
if (Array.isArray(migrationList) && migrationList.length > 0) {
|
|
2682
|
+
const sortedMigrations = migrationList.toSorted(
|
|
2683
|
+
(a, b) => a.migratedAt.getTime() - b.migratedAt.getTime()
|
|
2684
|
+
);
|
|
2685
|
+
migrationHistory = sortedMigrations.map((y) => `${y.id}, ${y.name}, ${y.migratedAt.toUTCString()}`).join("\n");
|
|
2686
|
+
}
|
|
2658
2687
|
console.info("Migrations history:\nid, name, migrated_at\n", migrationHistory);
|
|
2659
2688
|
return {
|
|
2660
2689
|
headers: { "Content-Type": ["application/json"] },
|
|
@@ -2663,12 +2692,8 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2663
2692
|
body: "Migrations successfully executed"
|
|
2664
2693
|
};
|
|
2665
2694
|
} catch (error) {
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
} catch (e) {
|
|
2669
|
-
console.trace("Error stringify:", e);
|
|
2670
|
-
console.error("Error during migration:", error);
|
|
2671
|
-
}
|
|
2695
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2696
|
+
console.error("Error during migration:", errorMessage);
|
|
2672
2697
|
return {
|
|
2673
2698
|
headers: { "Content-Type": ["application/json"] },
|
|
2674
2699
|
statusCode: 500,
|
|
@@ -2684,8 +2709,8 @@ async function fetchSchemaWebTrigger() {
|
|
|
2684
2709
|
const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);
|
|
2685
2710
|
return getHttpResponse(200, sqlStatements.join(";\n"));
|
|
2686
2711
|
} catch (error) {
|
|
2687
|
-
|
|
2688
|
-
|
|
2712
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2713
|
+
console.error(errorMessage);
|
|
2689
2714
|
return getHttpResponse(500, errorMessage);
|
|
2690
2715
|
}
|
|
2691
2716
|
}
|
|
@@ -2712,7 +2737,7 @@ async function dropTableSchemaMigrations() {
|
|
|
2712
2737
|
const tables = await getTables();
|
|
2713
2738
|
const dropStatements = generateDropTableStatements(tables, { sequence: false, table: true });
|
|
2714
2739
|
for (const statement of dropStatements) {
|
|
2715
|
-
console.
|
|
2740
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2716
2741
|
await sql$1.sql.executeDDL(statement);
|
|
2717
2742
|
}
|
|
2718
2743
|
return getHttpResponse(
|
|
@@ -2720,8 +2745,8 @@ async function dropTableSchemaMigrations() {
|
|
|
2720
2745
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2721
2746
|
);
|
|
2722
2747
|
} catch (error) {
|
|
2723
|
-
|
|
2724
|
-
|
|
2748
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2749
|
+
console.error(errorMessage);
|
|
2725
2750
|
return getHttpResponse(500, errorMessage);
|
|
2726
2751
|
}
|
|
2727
2752
|
}
|