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.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) {
|
|
@@ -534,7 +555,7 @@ async function saveTableIfInsideCacheContext(table) {
|
|
|
534
555
|
context.tables.add(tableName);
|
|
535
556
|
}
|
|
536
557
|
}
|
|
537
|
-
async function saveQueryLocalCacheQuery(query, rows) {
|
|
558
|
+
async function saveQueryLocalCacheQuery(query, rows, options) {
|
|
538
559
|
const context = localCacheApplicationContext.getStore();
|
|
539
560
|
if (context) {
|
|
540
561
|
if (!context.cache) {
|
|
@@ -546,9 +567,15 @@ async function saveQueryLocalCacheQuery(query, rows) {
|
|
|
546
567
|
sql: sql2.toSQL().sql.toLowerCase(),
|
|
547
568
|
data: rows
|
|
548
569
|
};
|
|
570
|
+
if (options.logRawSqlQuery) {
|
|
571
|
+
const q = sql2.toSQL();
|
|
572
|
+
console.debug(
|
|
573
|
+
`[forge-sql-orm][local-cache][SAVE] Stored result in cache. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
574
|
+
);
|
|
575
|
+
}
|
|
549
576
|
}
|
|
550
577
|
}
|
|
551
|
-
async function getQueryLocalCacheQuery(query) {
|
|
578
|
+
async function getQueryLocalCacheQuery(query, options) {
|
|
552
579
|
const context = localCacheApplicationContext.getStore();
|
|
553
580
|
if (context) {
|
|
554
581
|
if (!context.cache) {
|
|
@@ -557,6 +584,12 @@ async function getQueryLocalCacheQuery(query) {
|
|
|
557
584
|
const sql2 = query;
|
|
558
585
|
const key = hashKey(sql2.toSQL());
|
|
559
586
|
if (context.cache[key] && context.cache[key].sql === sql2.toSQL().sql.toLowerCase()) {
|
|
587
|
+
if (options.logRawSqlQuery) {
|
|
588
|
+
const q = sql2.toSQL();
|
|
589
|
+
console.debug(
|
|
590
|
+
`[forge-sql-orm][local-cache][HIT] Returned cached result. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
591
|
+
);
|
|
592
|
+
}
|
|
560
593
|
return context.cache[key].data;
|
|
561
594
|
}
|
|
562
595
|
}
|
|
@@ -983,28 +1016,23 @@ class ForgeSQLSelectOperations {
|
|
|
983
1016
|
}
|
|
984
1017
|
}
|
|
985
1018
|
const forgeDriver = async (query, params, method) => {
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
sqlStatement.bindParams(...params);
|
|
991
|
-
}
|
|
992
|
-
const updateQueryResponseResults = await sqlStatement.execute();
|
|
993
|
-
let result = updateQueryResponseResults.rows;
|
|
994
|
-
return { ...result, rows: [result] };
|
|
995
|
-
} else {
|
|
996
|
-
const sqlStatement = await sql$1.prepare(query);
|
|
997
|
-
if (params) {
|
|
998
|
-
await sqlStatement.bindParams(...params);
|
|
999
|
-
}
|
|
1000
|
-
const result = await sqlStatement.execute();
|
|
1001
|
-
let rows;
|
|
1002
|
-
rows = result.rows.map((r) => Object.values(r));
|
|
1003
|
-
return { rows };
|
|
1019
|
+
if (method == "execute") {
|
|
1020
|
+
const sqlStatement = sql$1.prepare(query);
|
|
1021
|
+
if (params) {
|
|
1022
|
+
sqlStatement.bindParams(...params);
|
|
1004
1023
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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 };
|
|
1008
1036
|
}
|
|
1009
1037
|
};
|
|
1010
1038
|
function injectSqlHints(query, hints) {
|
|
@@ -1041,28 +1069,22 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
|
|
|
1041
1069
|
return async (query, params, method) => {
|
|
1042
1070
|
const modifiedQuery = injectSqlHints(query, options);
|
|
1043
1071
|
if (options && logRawSqlQuery && modifiedQuery !== query) {
|
|
1044
|
-
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;
|
|
1045
1081
|
}
|
|
1046
|
-
return forgeDriver(modifiedQuery, params, method);
|
|
1047
1082
|
};
|
|
1048
1083
|
}
|
|
1049
|
-
const NON_CACHE_CLEARING_ERROR_CODES = [
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
];
|
|
1053
|
-
const CACHE_CLEARING_ERROR_CODES = [
|
|
1054
|
-
"DEADLOCK",
|
|
1055
|
-
"LOCK_WAIT_TIMEOUT",
|
|
1056
|
-
"CONNECTION_ERROR"
|
|
1057
|
-
];
|
|
1058
|
-
const NON_CACHE_CLEARING_PATTERNS = [
|
|
1059
|
-
/validation/i,
|
|
1060
|
-
/constraint/i
|
|
1061
|
-
];
|
|
1062
|
-
const CACHE_CLEARING_PATTERNS = [
|
|
1063
|
-
/timeout/i,
|
|
1064
|
-
/connection/i
|
|
1065
|
-
];
|
|
1084
|
+
const NON_CACHE_CLEARING_ERROR_CODES = ["VALIDATION_ERROR", "CONSTRAINT_ERROR"];
|
|
1085
|
+
const CACHE_CLEARING_ERROR_CODES = ["DEADLOCK", "LOCK_WAIT_TIMEOUT", "CONNECTION_ERROR"];
|
|
1086
|
+
const NON_CACHE_CLEARING_PATTERNS = [/validation/i, /constraint/i];
|
|
1087
|
+
const CACHE_CLEARING_PATTERNS = [/timeout/i, /connection/i];
|
|
1066
1088
|
function shouldClearCacheOnError(error) {
|
|
1067
1089
|
if (error?.code && NON_CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
|
|
1068
1090
|
return false;
|
|
@@ -1091,8 +1113,8 @@ async function handleSuccessfulExecution(rows, onfulfilled, table, options, isCa
|
|
|
1091
1113
|
if (shouldClearCacheOnError(error)) {
|
|
1092
1114
|
await evictLocalCacheQuery(table, options);
|
|
1093
1115
|
if (isCached) {
|
|
1094
|
-
await clearCache(table, options).catch(() => {
|
|
1095
|
-
console.warn("Ignore cache clear errors");
|
|
1116
|
+
await clearCache(table, options).catch((e) => {
|
|
1117
|
+
console.warn("Ignore cache clear errors", e);
|
|
1096
1118
|
});
|
|
1097
1119
|
} else {
|
|
1098
1120
|
await saveTableIfInsideCacheContext(table);
|
|
@@ -1154,7 +1176,7 @@ function deleteAndEvictCacheBuilder(db, table, options, isCached) {
|
|
|
1154
1176
|
}
|
|
1155
1177
|
async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap, onfulfilled, onrejected) {
|
|
1156
1178
|
try {
|
|
1157
|
-
const localCached = await getQueryLocalCacheQuery(target);
|
|
1179
|
+
const localCached = await getQueryLocalCacheQuery(target, options);
|
|
1158
1180
|
if (localCached) {
|
|
1159
1181
|
return onfulfilled?.(localCached);
|
|
1160
1182
|
}
|
|
@@ -1164,7 +1186,7 @@ async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap
|
|
|
1164
1186
|
}
|
|
1165
1187
|
const rows = await target.execute();
|
|
1166
1188
|
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
1167
|
-
await saveQueryLocalCacheQuery(target, transformed);
|
|
1189
|
+
await saveQueryLocalCacheQuery(target, transformed, options);
|
|
1168
1190
|
await setCacheResult(target, options, transformed, cacheTtl).catch((cacheError) => {
|
|
1169
1191
|
console.warn("Cache set error:", cacheError);
|
|
1170
1192
|
});
|
|
@@ -1173,15 +1195,15 @@ async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap
|
|
|
1173
1195
|
return onrejected?.(error);
|
|
1174
1196
|
}
|
|
1175
1197
|
}
|
|
1176
|
-
async function handleNonCachedQuery(target, selections, aliasMap, onfulfilled, onrejected) {
|
|
1198
|
+
async function handleNonCachedQuery(target, options, selections, aliasMap, onfulfilled, onrejected) {
|
|
1177
1199
|
try {
|
|
1178
|
-
const localCached = await getQueryLocalCacheQuery(target);
|
|
1200
|
+
const localCached = await getQueryLocalCacheQuery(target, options);
|
|
1179
1201
|
if (localCached) {
|
|
1180
1202
|
return onfulfilled?.(localCached);
|
|
1181
1203
|
}
|
|
1182
1204
|
const rows = await target.execute();
|
|
1183
1205
|
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
1184
|
-
await saveQueryLocalCacheQuery(target, transformed);
|
|
1206
|
+
await saveQueryLocalCacheQuery(target, transformed, options);
|
|
1185
1207
|
return onfulfilled?.(transformed);
|
|
1186
1208
|
} catch (error) {
|
|
1187
1209
|
return onrejected?.(error);
|
|
@@ -1213,7 +1235,14 @@ function createAliasedSelectBuilder(db, fields, selectFn, useCache, options, cac
|
|
|
1213
1235
|
onrejected
|
|
1214
1236
|
);
|
|
1215
1237
|
} else {
|
|
1216
|
-
return handleNonCachedQuery(
|
|
1238
|
+
return handleNonCachedQuery(
|
|
1239
|
+
target,
|
|
1240
|
+
options,
|
|
1241
|
+
selections,
|
|
1242
|
+
aliasMap,
|
|
1243
|
+
onfulfilled,
|
|
1244
|
+
onrejected
|
|
1245
|
+
);
|
|
1217
1246
|
}
|
|
1218
1247
|
};
|
|
1219
1248
|
}
|
|
@@ -1247,14 +1276,16 @@ function createRawQueryExecutor(db, options, useGlobalCache = false) {
|
|
|
1247
1276
|
let sql2;
|
|
1248
1277
|
if (isSQLWrapper(query)) {
|
|
1249
1278
|
const sqlWrapper = query;
|
|
1250
|
-
sql2 = sqlWrapper.getSQL().toQuery(
|
|
1279
|
+
sql2 = sqlWrapper.getSQL().toQuery(
|
|
1280
|
+
db.dialect
|
|
1281
|
+
);
|
|
1251
1282
|
} else {
|
|
1252
1283
|
sql2 = {
|
|
1253
1284
|
sql: query,
|
|
1254
1285
|
params: []
|
|
1255
1286
|
};
|
|
1256
1287
|
}
|
|
1257
|
-
const localCacheResult = await getQueryLocalCacheQuery(sql2);
|
|
1288
|
+
const localCacheResult = await getQueryLocalCacheQuery(sql2, options);
|
|
1258
1289
|
if (localCacheResult) {
|
|
1259
1290
|
return localCacheResult;
|
|
1260
1291
|
}
|
|
@@ -1265,7 +1296,7 @@ function createRawQueryExecutor(db, options, useGlobalCache = false) {
|
|
|
1265
1296
|
}
|
|
1266
1297
|
}
|
|
1267
1298
|
const results = await db.execute(query);
|
|
1268
|
-
await saveQueryLocalCacheQuery(sql2, results);
|
|
1299
|
+
await saveQueryLocalCacheQuery(sql2, results, options);
|
|
1269
1300
|
if (useGlobalCache) {
|
|
1270
1301
|
await setCacheResult(
|
|
1271
1302
|
{ toSQL: () => sql2 },
|
|
@@ -1816,34 +1847,40 @@ class ForgeSQLORMImpl {
|
|
|
1816
1847
|
*/
|
|
1817
1848
|
async executeWithCacheContextAndReturnValue(cacheContext) {
|
|
1818
1849
|
return await this.executeWithLocalCacheContextAndReturnValue(
|
|
1819
|
-
async () => await cacheApplicationContext.run(
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1850
|
+
async () => await cacheApplicationContext.run(
|
|
1851
|
+
cacheApplicationContext.getStore() ?? { tables: /* @__PURE__ */ new Set() },
|
|
1852
|
+
async () => {
|
|
1853
|
+
try {
|
|
1854
|
+
return await cacheContext();
|
|
1855
|
+
} finally {
|
|
1856
|
+
await clearTablesCache(
|
|
1857
|
+
Array.from(cacheApplicationContext.getStore()?.tables ?? []),
|
|
1858
|
+
this.options
|
|
1859
|
+
);
|
|
1860
|
+
}
|
|
1827
1861
|
}
|
|
1828
|
-
|
|
1862
|
+
)
|
|
1829
1863
|
);
|
|
1830
1864
|
}
|
|
1831
1865
|
/**
|
|
1832
1866
|
* Executes operations within a local cache context and returns a value.
|
|
1833
1867
|
* This provides in-memory caching for select queries within a single request scope.
|
|
1834
|
-
*
|
|
1868
|
+
*
|
|
1835
1869
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
1836
1870
|
* @returns Promise that resolves to the return value of the cacheContext function
|
|
1837
1871
|
*/
|
|
1838
1872
|
async executeWithLocalCacheContextAndReturnValue(cacheContext) {
|
|
1839
|
-
return await localCacheApplicationContext.run(
|
|
1840
|
-
|
|
1841
|
-
|
|
1873
|
+
return await localCacheApplicationContext.run(
|
|
1874
|
+
localCacheApplicationContext.getStore() ?? { cache: {} },
|
|
1875
|
+
async () => {
|
|
1876
|
+
return await cacheContext();
|
|
1877
|
+
}
|
|
1878
|
+
);
|
|
1842
1879
|
}
|
|
1843
1880
|
/**
|
|
1844
1881
|
* Executes operations within a local cache context.
|
|
1845
1882
|
* This provides in-memory caching for select queries within a single request scope.
|
|
1846
|
-
*
|
|
1883
|
+
*
|
|
1847
1884
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
1848
1885
|
* @returns Promise that resolves when all operations are complete
|
|
1849
1886
|
*/
|
|
@@ -2140,7 +2177,7 @@ class ForgeSQLORMImpl {
|
|
|
2140
2177
|
* ```typescript
|
|
2141
2178
|
* // Using SQLWrapper
|
|
2142
2179
|
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
2143
|
-
*
|
|
2180
|
+
*
|
|
2144
2181
|
* // Using string
|
|
2145
2182
|
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
2146
2183
|
* ```
|
|
@@ -2161,7 +2198,7 @@ class ForgeSQLORMImpl {
|
|
|
2161
2198
|
* ```typescript
|
|
2162
2199
|
* // Using SQLWrapper with custom TTL
|
|
2163
2200
|
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
2164
|
-
*
|
|
2201
|
+
*
|
|
2165
2202
|
* // Using string with default TTL
|
|
2166
2203
|
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
2167
2204
|
* ```
|
|
@@ -2199,7 +2236,7 @@ class ForgeSQLORMImpl {
|
|
|
2199
2236
|
* .from(users)
|
|
2200
2237
|
* .groupBy(users.id)
|
|
2201
2238
|
* );
|
|
2202
|
-
*
|
|
2239
|
+
*
|
|
2203
2240
|
* const result = await forgeSQL.with(withQuery)
|
|
2204
2241
|
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
2205
2242
|
* .from(withQuery);
|
|
@@ -2291,7 +2328,7 @@ class ForgeSQLORM {
|
|
|
2291
2328
|
/**
|
|
2292
2329
|
* Executes operations within a local cache context.
|
|
2293
2330
|
* This provides in-memory caching for select queries within a single request scope.
|
|
2294
|
-
*
|
|
2331
|
+
*
|
|
2295
2332
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
2296
2333
|
* @returns Promise that resolves when all operations are complete
|
|
2297
2334
|
*/
|
|
@@ -2301,7 +2338,7 @@ class ForgeSQLORM {
|
|
|
2301
2338
|
/**
|
|
2302
2339
|
* Executes operations within a local cache context and returns a value.
|
|
2303
2340
|
* This provides in-memory caching for select queries within a single request scope.
|
|
2304
|
-
*
|
|
2341
|
+
*
|
|
2305
2342
|
* @param cacheContext - Function containing operations that will benefit from local caching
|
|
2306
2343
|
* @returns Promise that resolves to the return value of the cacheContext function
|
|
2307
2344
|
*/
|
|
@@ -2465,7 +2502,7 @@ class ForgeSQLORM {
|
|
|
2465
2502
|
* ```typescript
|
|
2466
2503
|
* // Using SQLWrapper
|
|
2467
2504
|
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
2468
|
-
*
|
|
2505
|
+
*
|
|
2469
2506
|
* // Using string
|
|
2470
2507
|
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
2471
2508
|
* ```
|
|
@@ -2486,7 +2523,7 @@ class ForgeSQLORM {
|
|
|
2486
2523
|
* ```typescript
|
|
2487
2524
|
* // Using SQLWrapper with custom TTL
|
|
2488
2525
|
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
2489
|
-
*
|
|
2526
|
+
*
|
|
2490
2527
|
* // Using string with default TTL
|
|
2491
2528
|
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
2492
2529
|
* ```
|
|
@@ -2524,7 +2561,7 @@ class ForgeSQLORM {
|
|
|
2524
2561
|
* .from(users)
|
|
2525
2562
|
* .groupBy(users.id)
|
|
2526
2563
|
* );
|
|
2527
|
-
*
|
|
2564
|
+
*
|
|
2528
2565
|
* const result = await forgeSQL.with(withQuery)
|
|
2529
2566
|
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
2530
2567
|
* .from(withQuery);
|
|
@@ -2539,10 +2576,10 @@ const forgeDateTimeString = customType({
|
|
|
2539
2576
|
return "datetime";
|
|
2540
2577
|
},
|
|
2541
2578
|
toDriver(value) {
|
|
2542
|
-
return formatDateTime(value, "yyyy-
|
|
2579
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", false);
|
|
2543
2580
|
},
|
|
2544
2581
|
fromDriver(value) {
|
|
2545
|
-
const format = "yyyy-
|
|
2582
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2546
2583
|
return parseDateTime(value, format);
|
|
2547
2584
|
}
|
|
2548
2585
|
});
|
|
@@ -2551,10 +2588,10 @@ const forgeTimestampString = customType({
|
|
|
2551
2588
|
return "timestamp";
|
|
2552
2589
|
},
|
|
2553
2590
|
toDriver(value) {
|
|
2554
|
-
return formatDateTime(value, "yyyy-
|
|
2591
|
+
return formatDateTime(value, "yyyy-MM-dd' 'HH:mm:ss.SSS", true);
|
|
2555
2592
|
},
|
|
2556
2593
|
fromDriver(value) {
|
|
2557
|
-
const format = "yyyy-
|
|
2594
|
+
const format = "yyyy-MM-dd' 'HH:mm:ss.SSS";
|
|
2558
2595
|
return parseDateTime(value, format);
|
|
2559
2596
|
}
|
|
2560
2597
|
});
|
|
@@ -2563,10 +2600,10 @@ const forgeDateString = customType({
|
|
|
2563
2600
|
return "date";
|
|
2564
2601
|
},
|
|
2565
2602
|
toDriver(value) {
|
|
2566
|
-
return formatDateTime(value, "yyyy-
|
|
2603
|
+
return formatDateTime(value, "yyyy-MM-dd", false);
|
|
2567
2604
|
},
|
|
2568
2605
|
fromDriver(value) {
|
|
2569
|
-
const format = "yyyy-
|
|
2606
|
+
const format = "yyyy-MM-dd";
|
|
2570
2607
|
return parseDateTime(value, format);
|
|
2571
2608
|
}
|
|
2572
2609
|
});
|
|
@@ -2575,7 +2612,7 @@ const forgeTimeString = customType({
|
|
|
2575
2612
|
return "time";
|
|
2576
2613
|
},
|
|
2577
2614
|
toDriver(value) {
|
|
2578
|
-
return formatDateTime(value, "HH:mm:ss.SSS");
|
|
2615
|
+
return formatDateTime(value, "HH:mm:ss.SSS", false);
|
|
2579
2616
|
},
|
|
2580
2617
|
fromDriver(value) {
|
|
2581
2618
|
return parseDateTime(value, "HH:mm:ss.SSS");
|
|
@@ -2596,7 +2633,7 @@ async function dropSchemaMigrations() {
|
|
|
2596
2633
|
const tables = await getTables();
|
|
2597
2634
|
const dropStatements = generateDropTableStatements(tables, { sequence: true, table: true });
|
|
2598
2635
|
for (const statement of dropStatements) {
|
|
2599
|
-
console.
|
|
2636
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2600
2637
|
await sql$1.executeDDL(statement);
|
|
2601
2638
|
}
|
|
2602
2639
|
return getHttpResponse(
|
|
@@ -2604,8 +2641,8 @@ async function dropSchemaMigrations() {
|
|
|
2604
2641
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2605
2642
|
);
|
|
2606
2643
|
} catch (error) {
|
|
2607
|
-
|
|
2608
|
-
|
|
2644
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2645
|
+
console.error(errorMessage);
|
|
2609
2646
|
return getHttpResponse(500, errorMessage);
|
|
2610
2647
|
}
|
|
2611
2648
|
}
|
|
@@ -2621,7 +2658,13 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2621
2658
|
const successfulMigrations = await migrations2.run();
|
|
2622
2659
|
console.info("Migrations applied:", successfulMigrations);
|
|
2623
2660
|
const migrationList = await migrationRunner.list();
|
|
2624
|
-
|
|
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
|
+
}
|
|
2625
2668
|
console.info("Migrations history:\nid, name, migrated_at\n", migrationHistory);
|
|
2626
2669
|
return {
|
|
2627
2670
|
headers: { "Content-Type": ["application/json"] },
|
|
@@ -2630,12 +2673,8 @@ const applySchemaMigrations = async (migration) => {
|
|
|
2630
2673
|
body: "Migrations successfully executed"
|
|
2631
2674
|
};
|
|
2632
2675
|
} catch (error) {
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
} catch (e) {
|
|
2636
|
-
console.trace("Error stringify:", e);
|
|
2637
|
-
console.error("Error during migration:", error);
|
|
2638
|
-
}
|
|
2676
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2677
|
+
console.error("Error during migration:", errorMessage);
|
|
2639
2678
|
return {
|
|
2640
2679
|
headers: { "Content-Type": ["application/json"] },
|
|
2641
2680
|
statusCode: 500,
|
|
@@ -2651,8 +2690,8 @@ async function fetchSchemaWebTrigger() {
|
|
|
2651
2690
|
const sqlStatements = wrapWithForeignKeyChecks(createTableStatements);
|
|
2652
2691
|
return getHttpResponse(200, sqlStatements.join(";\n"));
|
|
2653
2692
|
} catch (error) {
|
|
2654
|
-
|
|
2655
|
-
|
|
2693
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2694
|
+
console.error(errorMessage);
|
|
2656
2695
|
return getHttpResponse(500, errorMessage);
|
|
2657
2696
|
}
|
|
2658
2697
|
}
|
|
@@ -2679,7 +2718,7 @@ async function dropTableSchemaMigrations() {
|
|
|
2679
2718
|
const tables = await getTables();
|
|
2680
2719
|
const dropStatements = generateDropTableStatements(tables, { sequence: false, table: true });
|
|
2681
2720
|
for (const statement of dropStatements) {
|
|
2682
|
-
console.
|
|
2721
|
+
console.debug(`execute DDL: ${statement}`);
|
|
2683
2722
|
await sql$1.executeDDL(statement);
|
|
2684
2723
|
}
|
|
2685
2724
|
return getHttpResponse(
|
|
@@ -2687,8 +2726,8 @@ async function dropTableSchemaMigrations() {
|
|
|
2687
2726
|
"⚠️ All data in these tables has been permanently deleted. This operation cannot be undone."
|
|
2688
2727
|
);
|
|
2689
2728
|
} catch (error) {
|
|
2690
|
-
|
|
2691
|
-
|
|
2729
|
+
const errorMessage = error?.debug?.sqlMessage ?? error?.debug?.message ?? error.message ?? "Unknown error occurred";
|
|
2730
|
+
console.error(errorMessage);
|
|
2692
2731
|
return getHttpResponse(500, errorMessage);
|
|
2693
2732
|
}
|
|
2694
2733
|
}
|