forge-sql-orm 2.1.1 → 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 +142 -103
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +142 -103
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +24 -25
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
- package/dist/utils/cacheContextUtils.d.ts +4 -2
- package/dist/utils/cacheContextUtils.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/ForgeSQLORM.ts +29 -23
- package/src/core/ForgeSQLQueryBuilder.ts +185 -128
- package/src/lib/drizzle/extensions/additionalActions.ts +125 -76
- package/src/lib/drizzle/extensions/types.d.ts +16 -11
- package/src/utils/cacheContextUtils.ts +16 -4
- 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 +59 -35
- 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) {
|
|
@@ -553,7 +574,7 @@ async function saveTableIfInsideCacheContext(table$1) {
|
|
|
553
574
|
context.tables.add(tableName);
|
|
554
575
|
}
|
|
555
576
|
}
|
|
556
|
-
async function saveQueryLocalCacheQuery(query, rows) {
|
|
577
|
+
async function saveQueryLocalCacheQuery(query, rows, options) {
|
|
557
578
|
const context = localCacheApplicationContext.getStore();
|
|
558
579
|
if (context) {
|
|
559
580
|
if (!context.cache) {
|
|
@@ -565,9 +586,15 @@ async function saveQueryLocalCacheQuery(query, rows) {
|
|
|
565
586
|
sql: sql2.toSQL().sql.toLowerCase(),
|
|
566
587
|
data: rows
|
|
567
588
|
};
|
|
589
|
+
if (options.logRawSqlQuery) {
|
|
590
|
+
const q = sql2.toSQL();
|
|
591
|
+
console.debug(
|
|
592
|
+
`[forge-sql-orm][local-cache][SAVE] Stored result in cache. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
593
|
+
);
|
|
594
|
+
}
|
|
568
595
|
}
|
|
569
596
|
}
|
|
570
|
-
async function getQueryLocalCacheQuery(query) {
|
|
597
|
+
async function getQueryLocalCacheQuery(query, options) {
|
|
571
598
|
const context = localCacheApplicationContext.getStore();
|
|
572
599
|
if (context) {
|
|
573
600
|
if (!context.cache) {
|
|
@@ -576,6 +603,12 @@ async function getQueryLocalCacheQuery(query) {
|
|
|
576
603
|
const sql2 = query;
|
|
577
604
|
const key = hashKey(sql2.toSQL());
|
|
578
605
|
if (context.cache[key] && context.cache[key].sql === sql2.toSQL().sql.toLowerCase()) {
|
|
606
|
+
if (options.logRawSqlQuery) {
|
|
607
|
+
const q = sql2.toSQL();
|
|
608
|
+
console.debug(
|
|
609
|
+
`[forge-sql-orm][local-cache][HIT] Returned cached result. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
610
|
+
);
|
|
611
|
+
}
|
|
579
612
|
return context.cache[key].data;
|
|
580
613
|
}
|
|
581
614
|
}
|
|
@@ -1002,28 +1035,23 @@ class ForgeSQLSelectOperations {
|
|
|
1002
1035
|
}
|
|
1003
1036
|
}
|
|
1004
1037
|
const forgeDriver = async (query, params, method) => {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
sqlStatement.bindParams(...params);
|
|
1010
|
-
}
|
|
1011
|
-
const updateQueryResponseResults = await sqlStatement.execute();
|
|
1012
|
-
let result = updateQueryResponseResults.rows;
|
|
1013
|
-
return { ...result, rows: [result] };
|
|
1014
|
-
} else {
|
|
1015
|
-
const sqlStatement = await sql$1.sql.prepare(query);
|
|
1016
|
-
if (params) {
|
|
1017
|
-
await sqlStatement.bindParams(...params);
|
|
1018
|
-
}
|
|
1019
|
-
const result = await sqlStatement.execute();
|
|
1020
|
-
let rows;
|
|
1021
|
-
rows = result.rows.map((r) => Object.values(r));
|
|
1022
|
-
return { rows };
|
|
1038
|
+
if (method == "execute") {
|
|
1039
|
+
const sqlStatement = sql$1.sql.prepare(query);
|
|
1040
|
+
if (params) {
|
|
1041
|
+
sqlStatement.bindParams(...params);
|
|
1023
1042
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
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 };
|
|
1027
1055
|
}
|
|
1028
1056
|
};
|
|
1029
1057
|
function injectSqlHints(query, hints) {
|
|
@@ -1060,28 +1088,22 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
|
|
|
1060
1088
|
return async (query, params, method) => {
|
|
1061
1089
|
const modifiedQuery = injectSqlHints(query, options);
|
|
1062
1090
|
if (options && logRawSqlQuery && modifiedQuery !== query) {
|
|
1063
|
-
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;
|
|
1064
1100
|
}
|
|
1065
|
-
return forgeDriver(modifiedQuery, params, method);
|
|
1066
1101
|
};
|
|
1067
1102
|
}
|
|
1068
|
-
const NON_CACHE_CLEARING_ERROR_CODES = [
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
];
|
|
1072
|
-
const CACHE_CLEARING_ERROR_CODES = [
|
|
1073
|
-
"DEADLOCK",
|
|
1074
|
-
"LOCK_WAIT_TIMEOUT",
|
|
1075
|
-
"CONNECTION_ERROR"
|
|
1076
|
-
];
|
|
1077
|
-
const NON_CACHE_CLEARING_PATTERNS = [
|
|
1078
|
-
/validation/i,
|
|
1079
|
-
/constraint/i
|
|
1080
|
-
];
|
|
1081
|
-
const CACHE_CLEARING_PATTERNS = [
|
|
1082
|
-
/timeout/i,
|
|
1083
|
-
/connection/i
|
|
1084
|
-
];
|
|
1103
|
+
const NON_CACHE_CLEARING_ERROR_CODES = ["VALIDATION_ERROR", "CONSTRAINT_ERROR"];
|
|
1104
|
+
const CACHE_CLEARING_ERROR_CODES = ["DEADLOCK", "LOCK_WAIT_TIMEOUT", "CONNECTION_ERROR"];
|
|
1105
|
+
const NON_CACHE_CLEARING_PATTERNS = [/validation/i, /constraint/i];
|
|
1106
|
+
const CACHE_CLEARING_PATTERNS = [/timeout/i, /connection/i];
|
|
1085
1107
|
function shouldClearCacheOnError(error) {
|
|
1086
1108
|
if (error?.code && NON_CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
|
|
1087
1109
|
return false;
|
|
@@ -1110,8 +1132,8 @@ async function handleSuccessfulExecution(rows, onfulfilled, table2, options, isC
|
|
|
1110
1132
|
if (shouldClearCacheOnError(error)) {
|
|
1111
1133
|
await evictLocalCacheQuery(table2, options);
|
|
1112
1134
|
if (isCached) {
|
|
1113
|
-
await clearCache(table2, options).catch(() => {
|
|
1114
|
-
console.warn("Ignore cache clear errors");
|
|
1135
|
+
await clearCache(table2, options).catch((e) => {
|
|
1136
|
+
console.warn("Ignore cache clear errors", e);
|
|
1115
1137
|
});
|
|
1116
1138
|
} else {
|
|
1117
1139
|
await saveTableIfInsideCacheContext(table2);
|
|
@@ -1173,7 +1195,7 @@ function deleteAndEvictCacheBuilder(db, table2, options, isCached) {
|
|
|
1173
1195
|
}
|
|
1174
1196
|
async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap, onfulfilled, onrejected) {
|
|
1175
1197
|
try {
|
|
1176
|
-
const localCached = await getQueryLocalCacheQuery(target);
|
|
1198
|
+
const localCached = await getQueryLocalCacheQuery(target, options);
|
|
1177
1199
|
if (localCached) {
|
|
1178
1200
|
return onfulfilled?.(localCached);
|
|
1179
1201
|
}
|
|
@@ -1183,7 +1205,7 @@ async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap
|
|
|
1183
1205
|
}
|
|
1184
1206
|
const rows = await target.execute();
|
|
1185
1207
|
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
1186
|
-
await saveQueryLocalCacheQuery(target, transformed);
|
|
1208
|
+
await saveQueryLocalCacheQuery(target, transformed, options);
|
|
1187
1209
|
await setCacheResult(target, options, transformed, cacheTtl).catch((cacheError) => {
|
|
1188
1210
|
console.warn("Cache set error:", cacheError);
|
|
1189
1211
|
});
|
|
@@ -1192,15 +1214,15 @@ async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap
|
|
|
1192
1214
|
return onrejected?.(error);
|
|
1193
1215
|
}
|
|
1194
1216
|
}
|
|
1195
|
-
async function handleNonCachedQuery(target, selections, aliasMap, onfulfilled, onrejected) {
|
|
1217
|
+
async function handleNonCachedQuery(target, options, selections, aliasMap, onfulfilled, onrejected) {
|
|
1196
1218
|
try {
|
|
1197
|
-
const localCached = await getQueryLocalCacheQuery(target);
|
|
1219
|
+
const localCached = await getQueryLocalCacheQuery(target, options);
|
|
1198
1220
|
if (localCached) {
|
|
1199
1221
|
return onfulfilled?.(localCached);
|
|
1200
1222
|
}
|
|
1201
1223
|
const rows = await target.execute();
|
|
1202
1224
|
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
1203
|
-
await saveQueryLocalCacheQuery(target, transformed);
|
|
1225
|
+
await saveQueryLocalCacheQuery(target, transformed, options);
|
|
1204
1226
|
return onfulfilled?.(transformed);
|
|
1205
1227
|
} catch (error) {
|
|
1206
1228
|
return onrejected?.(error);
|
|
@@ -1232,7 +1254,14 @@ function createAliasedSelectBuilder(db, fields, selectFn, useCache, options, cac
|
|
|
1232
1254
|
onrejected
|
|
1233
1255
|
);
|
|
1234
1256
|
} else {
|
|
1235
|
-
return handleNonCachedQuery(
|
|
1257
|
+
return handleNonCachedQuery(
|
|
1258
|
+
target,
|
|
1259
|
+
options,
|
|
1260
|
+
selections,
|
|
1261
|
+
aliasMap,
|
|
1262
|
+
onfulfilled,
|
|
1263
|
+
onrejected
|
|
1264
|
+
);
|
|
1236
1265
|
}
|
|
1237
1266
|
};
|
|
1238
1267
|
}
|
|
@@ -1266,14 +1295,16 @@ function createRawQueryExecutor(db, options, useGlobalCache = false) {
|
|
|
1266
1295
|
let sql$12;
|
|
1267
1296
|
if (sql.isSQLWrapper(query)) {
|
|
1268
1297
|
const sqlWrapper = query;
|
|
1269
|
-
sql$12 = sqlWrapper.getSQL().toQuery(
|
|
1298
|
+
sql$12 = sqlWrapper.getSQL().toQuery(
|
|
1299
|
+
db.dialect
|
|
1300
|
+
);
|
|
1270
1301
|
} else {
|
|
1271
1302
|
sql$12 = {
|
|
1272
1303
|
sql: query,
|
|
1273
1304
|
params: []
|
|
1274
1305
|
};
|
|
1275
1306
|
}
|
|
1276
|
-
const localCacheResult = await getQueryLocalCacheQuery(sql$12);
|
|
1307
|
+
const localCacheResult = await getQueryLocalCacheQuery(sql$12, options);
|
|
1277
1308
|
if (localCacheResult) {
|
|
1278
1309
|
return localCacheResult;
|
|
1279
1310
|
}
|
|
@@ -1284,7 +1315,7 @@ function createRawQueryExecutor(db, options, useGlobalCache = false) {
|
|
|
1284
1315
|
}
|
|
1285
1316
|
}
|
|
1286
1317
|
const results = await db.execute(query);
|
|
1287
|
-
await saveQueryLocalCacheQuery(sql$12, results);
|
|
1318
|
+
await saveQueryLocalCacheQuery(sql$12, results, options);
|
|
1288
1319
|
if (useGlobalCache) {
|
|
1289
1320
|
await setCacheResult(
|
|
1290
1321
|
{ toSQL: () => sql$12 },
|
|
@@ -1835,34 +1866,40 @@ class ForgeSQLORMImpl {
|
|
|
1835
1866
|
*/
|
|
1836
1867
|
async executeWithCacheContextAndReturnValue(cacheContext) {
|
|
1837
1868
|
return await this.executeWithLocalCacheContextAndReturnValue(
|
|
1838
|
-
async () => await cacheApplicationContext.run(
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1869
|
+
async () => await cacheApplicationContext.run(
|
|
1870
|
+
cacheApplicationContext.getStore() ?? { tables: /* @__PURE__ */ new Set() },
|
|
1871
|
+
async () => {
|
|
1872
|
+
try {
|
|
1873
|
+
return await cacheContext();
|
|
1874
|
+
} finally {
|
|
1875
|
+
await clearTablesCache(
|
|
1876
|
+
Array.from(cacheApplicationContext.getStore()?.tables ?? []),
|
|
1877
|
+
this.options
|
|
1878
|
+
);
|
|
1879
|
+
}
|
|
1846
1880
|
}
|
|
1847
|
-
|
|
1881
|
+
)
|
|
1848
1882
|
);
|
|
1849
1883
|
}
|
|
1850
1884
|
/**
|
|
1851
1885
|
* Executes operations within a local cache context and returns a value.
|
|
1852
1886
|
* This provides in-memory caching for select queries within a single request scope.
|
|
1853
|
-
*
|
|
1887
|
+
*
|
|
1854
1888
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
1855
1889
|
* @returns Promise that resolves to the return value of the cacheContext function
|
|
1856
1890
|
*/
|
|
1857
1891
|
async executeWithLocalCacheContextAndReturnValue(cacheContext) {
|
|
1858
|
-
return await localCacheApplicationContext.run(
|
|
1859
|
-
|
|
1860
|
-
|
|
1892
|
+
return await localCacheApplicationContext.run(
|
|
1893
|
+
localCacheApplicationContext.getStore() ?? { cache: {} },
|
|
1894
|
+
async () => {
|
|
1895
|
+
return await cacheContext();
|
|
1896
|
+
}
|
|
1897
|
+
);
|
|
1861
1898
|
}
|
|
1862
1899
|
/**
|
|
1863
1900
|
* Executes operations within a local cache context.
|
|
1864
1901
|
* This provides in-memory caching for select queries within a single request scope.
|
|
1865
|
-
*
|
|
1902
|
+
*
|
|
1866
1903
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
1867
1904
|
* @returns Promise that resolves when all operations are complete
|
|
1868
1905
|
*/
|
|
@@ -2159,7 +2196,7 @@ class ForgeSQLORMImpl {
|
|
|
2159
2196
|
* ```typescript
|
|
2160
2197
|
* // Using SQLWrapper
|
|
2161
2198
|
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
2162
|
-
*
|
|
2199
|
+
*
|
|
2163
2200
|
* // Using string
|
|
2164
2201
|
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
2165
2202
|
* ```
|
|
@@ -2180,7 +2217,7 @@ class ForgeSQLORMImpl {
|
|
|
2180
2217
|
* ```typescript
|
|
2181
2218
|
* // Using SQLWrapper with custom TTL
|
|
2182
2219
|
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
2183
|
-
*
|
|
2220
|
+
*
|
|
2184
2221
|
* // Using string with default TTL
|
|
2185
2222
|
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
2186
2223
|
* ```
|
|
@@ -2218,7 +2255,7 @@ class ForgeSQLORMImpl {
|
|
|
2218
2255
|
* .from(users)
|
|
2219
2256
|
* .groupBy(users.id)
|
|
2220
2257
|
* );
|
|
2221
|
-
*
|
|
2258
|
+
*
|
|
2222
2259
|
* const result = await forgeSQL.with(withQuery)
|
|
2223
2260
|
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
2224
2261
|
* .from(withQuery);
|
|
@@ -2310,7 +2347,7 @@ class ForgeSQLORM {
|
|
|
2310
2347
|
/**
|
|
2311
2348
|
* Executes operations within a local cache context.
|
|
2312
2349
|
* This provides in-memory caching for select queries within a single request scope.
|
|
2313
|
-
*
|
|
2350
|
+
*
|
|
2314
2351
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
2315
2352
|
* @returns Promise that resolves when all operations are complete
|
|
2316
2353
|
*/
|
|
@@ -2320,7 +2357,7 @@ class ForgeSQLORM {
|
|
|
2320
2357
|
/**
|
|
2321
2358
|
* Executes operations within a local cache context and returns a value.
|
|
2322
2359
|
* This provides in-memory caching for select queries within a single request scope.
|
|
2323
|
-
*
|
|
2360
|
+
*
|
|
2324
2361
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
2325
2362
|
* @returns Promise that resolves to the return value of the cacheContext function
|
|
2326
2363
|
*/
|
|
@@ -2484,7 +2521,7 @@ class ForgeSQLORM {
|
|
|
2484
2521
|
* ```typescript
|
|
2485
2522
|
* // Using SQLWrapper
|
|
2486
2523
|
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
2487
|
-
*
|
|
2524
|
+
*
|
|
2488
2525
|
* // Using string
|
|
2489
2526
|
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
2490
2527
|
* ```
|
|
@@ -2505,7 +2542,7 @@ class ForgeSQLORM {
|
|
|
2505
2542
|
* ```typescript
|
|
2506
2543
|
* // Using SQLWrapper with custom TTL
|
|
2507
2544
|
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
2508
|
-
*
|
|
2545
|
+
*
|
|
2509
2546
|
* // Using string with default TTL
|
|
2510
2547
|
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
2511
2548
|
* ```
|
|
@@ -2543,7 +2580,7 @@ class ForgeSQLORM {
|
|
|
2543
2580
|
* .from(users)
|
|
2544
2581
|
* .groupBy(users.id)
|
|
2545
2582
|
* );
|
|
2546
|
-
*
|
|
2583
|
+
*
|
|
2547
2584
|
* const result = await forgeSQL.with(withQuery)
|
|
2548
2585
|
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
2549
2586
|
* .from(withQuery);
|
|
@@ -2558,10 +2595,10 @@ const forgeDateTimeString = mysqlCore.customType({
|
|
|
2558
2595
|
return "datetime";
|
|
2559
2596
|
},
|
|
2560
2597
|
toDriver(value) {
|
|
2561
|
-
return formatDateTime(value, "yyyy-
|
|
2598
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", false);
|
|
2562
2599
|
},
|
|
2563
2600
|
fromDriver(value) {
|
|
2564
|
-
const format = "yyyy-
|
|
2601
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2565
2602
|
return parseDateTime(value, format);
|
|
2566
2603
|
}
|
|
2567
2604
|
});
|
|
@@ -2570,10 +2607,10 @@ const forgeTimestampString = mysqlCore.customType({
|
|
|
2570
2607
|
return "timestamp";
|
|
2571
2608
|
},
|
|
2572
2609
|
toDriver(value) {
|
|
2573
|
-
return formatDateTime(value, "yyyy-
|
|
2610
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", true);
|
|
2574
2611
|
},
|
|
2575
2612
|
fromDriver(value) {
|
|
2576
|
-
const format = "yyyy-
|
|
2613
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2577
2614
|
return parseDateTime(value, format);
|
|
2578
2615
|
}
|
|
2579
2616
|
});
|
|
@@ -2582,10 +2619,10 @@ const forgeDateString = mysqlCore.customType({
|
|
|
2582
2619
|
return "date";
|
|
2583
2620
|
},
|
|
2584
2621
|
toDriver(value) {
|
|
2585
|
-
return formatDateTime(value, "yyyy-
|
|
2622
|
+
return formatDateTime(value, "yyyy-MM-dd", false);
|
|
2586
2623
|
},
|
|
2587
2624
|
fromDriver(value) {
|
|
2588
|
-
const format = "yyyy-
|
|
2625
|
+
const format = "yyyy-MM-dd";
|
|
2589
2626
|
return parseDateTime(value, format);
|
|
2590
2627
|
}
|
|
2591
2628
|
});
|
|
@@ -2594,7 +2631,7 @@ const forgeTimeString = mysqlCore.customType({
|
|
|
2594
2631
|
return "time";
|
|
2595
2632
|
},
|
|
2596
2633
|
toDriver(value) {
|
|
2597
|
-
return formatDateTime(value, "HH:mm:ss.SSS");
|
|
2634
|
+
return formatDateTime(value, "HH:mm:ss.SSS", false);
|
|
2598
2635
|
},
|
|
2599
2636
|
fromDriver(value) {
|
|
2600
2637
|
return parseDateTime(value, "HH:mm:ss.SSS");
|
|
@@ -2615,7 +2652,7 @@ async function dropSchemaMigrations() {
|
|
|
2615
2652
|
const tables = await getTables();
|
|
2616
2653
|
const dropStatements = generateDropTableStatements(tables, { sequence: true, table: true });
|
|
2617
2654
|
for (const statement of dropStatements) {
|
|
2618
|
-
console.
|
|
2655
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2619
2656
|
await sql$1.sql.executeDDL(statement);
|
|
2620
2657
|
}
|
|
2621
2658
|
return getHttpResponse(
|
|
@@ -2623,8 +2660,8 @@ async function dropSchemaMigrations() {
|
|
|
2623
2660
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2624
2661
|
);
|
|
2625
2662
|
} catch (error) {
|
|
2626
|
-
|
|
2627
|
-
|
|
2663
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2664
|
+
console.error(errorMessage);
|
|
2628
2665
|
return getHttpResponse(500, errorMessage);
|
|
2629
2666
|
}
|
|
2630
2667
|
}
|
|
@@ -2640,7 +2677,13 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2640
2677
|
const successfulMigrations = await migrations2.run();
|
|
2641
2678
|
console.info("Migrations applied:", successfulMigrations);
|
|
2642
2679
|
const migrationList = await sql$1.migrationRunner.list();
|
|
2643
|
-
|
|
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
|
+
}
|
|
2644
2687
|
console.info("Migrations history:\nid, name, migrated_at\n", migrationHistory);
|
|
2645
2688
|
return {
|
|
2646
2689
|
headers: { "Content-Type": ["application/json"] },
|
|
@@ -2649,12 +2692,8 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2649
2692
|
body: "Migrations successfully executed"
|
|
2650
2693
|
};
|
|
2651
2694
|
} catch (error) {
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
} catch (e) {
|
|
2655
|
-
console.trace("Error stringify:", e);
|
|
2656
|
-
console.error("Error during migration:", error);
|
|
2657
|
-
}
|
|
2695
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2696
|
+
console.error("Error during migration:", errorMessage);
|
|
2658
2697
|
return {
|
|
2659
2698
|
headers: { "Content-Type": ["application/json"] },
|
|
2660
2699
|
statusCode: 500,
|
|
@@ -2670,8 +2709,8 @@ async function fetchSchemaWebTrigger() {
|
|
|
2670
2709
|
const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);
|
|
2671
2710
|
return getHttpResponse(200, sqlStatements.join(";\n"));
|
|
2672
2711
|
} catch (error) {
|
|
2673
|
-
|
|
2674
|
-
|
|
2712
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2713
|
+
console.error(errorMessage);
|
|
2675
2714
|
return getHttpResponse(500, errorMessage);
|
|
2676
2715
|
}
|
|
2677
2716
|
}
|
|
@@ -2698,7 +2737,7 @@ async function dropTableSchemaMigrations() {
|
|
|
2698
2737
|
const tables = await getTables();
|
|
2699
2738
|
const dropStatements = generateDropTableStatements(tables, { sequence: false, table: true });
|
|
2700
2739
|
for (const statement of dropStatements) {
|
|
2701
|
-
console.
|
|
2740
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2702
2741
|
await sql$1.sql.executeDDL(statement);
|
|
2703
2742
|
}
|
|
2704
2743
|
return getHttpResponse(
|
|
@@ -2706,8 +2745,8 @@ async function dropTableSchemaMigrations() {
|
|
|
2706
2745
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2707
2746
|
);
|
|
2708
2747
|
} catch (error) {
|
|
2709
|
-
|
|
2710
|
-
|
|
2748
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2749
|
+
console.error(errorMessage);
|
|
2711
2750
|
return getHttpResponse(500, errorMessage);
|
|
2712
2751
|
}
|
|
2713
2752
|
}
|