forge-sql-orm 2.1.0 → 2.1.2
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 +337 -17
- package/dist/ForgeSQLORM.js +424 -34
- package/dist/ForgeSQLORM.js.map +1 -1
- package/dist/ForgeSQLORM.mjs +425 -35
- package/dist/ForgeSQLORM.mjs.map +1 -1
- package/dist/core/ForgeSQLORM.d.ts +144 -0
- package/dist/core/ForgeSQLORM.d.ts.map +1 -1
- package/dist/core/ForgeSQLQueryBuilder.d.ts +149 -2
- package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
- package/dist/lib/drizzle/extensions/additionalActions.d.ts +50 -2
- 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/sqlUtils.d.ts +6 -6
- package/dist/utils/sqlUtils.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/core/ForgeSQLORM.ts +319 -13
- package/src/core/ForgeSQLQueryBuilder.ts +218 -0
- package/src/lib/drizzle/extensions/additionalActions.ts +387 -34
- package/src/lib/drizzle/extensions/types.d.ts +36 -0
- package/src/utils/cacheContextUtils.ts +16 -2
- package/src/utils/sqlUtils.ts +34 -9
package/dist/ForgeSQLORM.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isTable, sql, eq, and } from "drizzle-orm";
|
|
1
|
+
import { isTable, sql, eq, and, getTableColumns } from "drizzle-orm";
|
|
2
2
|
import { DateTime } from "luxon";
|
|
3
3
|
import { isSQLWrapper } from "drizzle-orm/sql/sql";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -31,12 +31,34 @@ const parseDateTime = (value, format) => {
|
|
|
31
31
|
return result;
|
|
32
32
|
};
|
|
33
33
|
function formatDateTime(value, format) {
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
|
|
34
|
+
let dt = null;
|
|
35
|
+
if (value instanceof Date) {
|
|
36
|
+
dt = DateTime.fromJSDate(value);
|
|
37
|
+
} else if (typeof value === "string") {
|
|
38
|
+
for (const parser of [
|
|
39
|
+
DateTime.fromISO,
|
|
40
|
+
DateTime.fromRFC2822,
|
|
41
|
+
DateTime.fromSQL,
|
|
42
|
+
DateTime.fromHTTP
|
|
43
|
+
]) {
|
|
44
|
+
dt = parser(value);
|
|
45
|
+
if (dt.isValid) break;
|
|
46
|
+
}
|
|
47
|
+
if (!dt?.isValid) {
|
|
48
|
+
const parsed = Number(value);
|
|
49
|
+
if (!isNaN(parsed)) {
|
|
50
|
+
dt = DateTime.fromMillis(parsed);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} else if (typeof value === "number") {
|
|
54
|
+
dt = DateTime.fromMillis(value);
|
|
37
55
|
} else {
|
|
56
|
+
throw new Error("Unsupported type");
|
|
57
|
+
}
|
|
58
|
+
if (!dt?.isValid) {
|
|
38
59
|
throw new Error("Invalid Date");
|
|
39
60
|
}
|
|
61
|
+
return dt.toFormat(format);
|
|
40
62
|
}
|
|
41
63
|
function getPrimaryKeys(table) {
|
|
42
64
|
const { columns, primaryKeys } = getTableMetadata(table);
|
|
@@ -512,7 +534,7 @@ async function saveTableIfInsideCacheContext(table) {
|
|
|
512
534
|
context.tables.add(tableName);
|
|
513
535
|
}
|
|
514
536
|
}
|
|
515
|
-
async function saveQueryLocalCacheQuery(query, rows) {
|
|
537
|
+
async function saveQueryLocalCacheQuery(query, rows, options) {
|
|
516
538
|
const context = localCacheApplicationContext.getStore();
|
|
517
539
|
if (context) {
|
|
518
540
|
if (!context.cache) {
|
|
@@ -524,9 +546,15 @@ async function saveQueryLocalCacheQuery(query, rows) {
|
|
|
524
546
|
sql: sql2.toSQL().sql.toLowerCase(),
|
|
525
547
|
data: rows
|
|
526
548
|
};
|
|
549
|
+
if (options.logRawSqlQuery) {
|
|
550
|
+
const q = sql2.toSQL();
|
|
551
|
+
console.log(
|
|
552
|
+
`[forge-sql-orm][local-cache][SAVE] Stored result in cache. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
553
|
+
);
|
|
554
|
+
}
|
|
527
555
|
}
|
|
528
556
|
}
|
|
529
|
-
async function getQueryLocalCacheQuery(query) {
|
|
557
|
+
async function getQueryLocalCacheQuery(query, options) {
|
|
530
558
|
const context = localCacheApplicationContext.getStore();
|
|
531
559
|
if (context) {
|
|
532
560
|
if (!context.cache) {
|
|
@@ -535,6 +563,12 @@ async function getQueryLocalCacheQuery(query) {
|
|
|
535
563
|
const sql2 = query;
|
|
536
564
|
const key = hashKey(sql2.toSQL());
|
|
537
565
|
if (context.cache[key] && context.cache[key].sql === sql2.toSQL().sql.toLowerCase()) {
|
|
566
|
+
if (options.logRawSqlQuery) {
|
|
567
|
+
const q = sql2.toSQL();
|
|
568
|
+
console.log(
|
|
569
|
+
`[forge-sql-orm][local-cache][HIT] Returned cached result. sql="${q.sql}", params=${JSON.stringify(q.params)}`
|
|
570
|
+
);
|
|
571
|
+
}
|
|
538
572
|
return context.cache[key].data;
|
|
539
573
|
}
|
|
540
574
|
}
|
|
@@ -1024,11 +1058,21 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
|
|
|
1024
1058
|
return forgeDriver(modifiedQuery, params, method);
|
|
1025
1059
|
};
|
|
1026
1060
|
}
|
|
1061
|
+
const NON_CACHE_CLEARING_ERROR_CODES = ["VALIDATION_ERROR", "CONSTRAINT_ERROR"];
|
|
1062
|
+
const CACHE_CLEARING_ERROR_CODES = ["DEADLOCK", "LOCK_WAIT_TIMEOUT", "CONNECTION_ERROR"];
|
|
1063
|
+
const NON_CACHE_CLEARING_PATTERNS = [/validation/i, /constraint/i];
|
|
1064
|
+
const CACHE_CLEARING_PATTERNS = [/timeout/i, /connection/i];
|
|
1027
1065
|
function shouldClearCacheOnError(error) {
|
|
1028
|
-
if (error?.code
|
|
1066
|
+
if (error?.code && NON_CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
|
|
1067
|
+
return false;
|
|
1068
|
+
}
|
|
1069
|
+
if (error?.message && NON_CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))) {
|
|
1029
1070
|
return false;
|
|
1030
1071
|
}
|
|
1031
|
-
if (error?.code
|
|
1072
|
+
if (error?.code && CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
|
|
1073
|
+
return true;
|
|
1074
|
+
}
|
|
1075
|
+
if (error?.message && CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))) {
|
|
1032
1076
|
return true;
|
|
1033
1077
|
}
|
|
1034
1078
|
return true;
|
|
@@ -1109,7 +1153,7 @@ function deleteAndEvictCacheBuilder(db, table, options, isCached) {
|
|
|
1109
1153
|
}
|
|
1110
1154
|
async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap, onfulfilled, onrejected) {
|
|
1111
1155
|
try {
|
|
1112
|
-
const localCached = await getQueryLocalCacheQuery(target);
|
|
1156
|
+
const localCached = await getQueryLocalCacheQuery(target, options);
|
|
1113
1157
|
if (localCached) {
|
|
1114
1158
|
return onfulfilled?.(localCached);
|
|
1115
1159
|
}
|
|
@@ -1119,7 +1163,7 @@ async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap
|
|
|
1119
1163
|
}
|
|
1120
1164
|
const rows = await target.execute();
|
|
1121
1165
|
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
1122
|
-
await saveQueryLocalCacheQuery(target, transformed);
|
|
1166
|
+
await saveQueryLocalCacheQuery(target, transformed, options);
|
|
1123
1167
|
await setCacheResult(target, options, transformed, cacheTtl).catch((cacheError) => {
|
|
1124
1168
|
console.warn("Cache set error:", cacheError);
|
|
1125
1169
|
});
|
|
@@ -1128,15 +1172,15 @@ async function handleCachedQuery(target, options, cacheTtl, selections, aliasMap
|
|
|
1128
1172
|
return onrejected?.(error);
|
|
1129
1173
|
}
|
|
1130
1174
|
}
|
|
1131
|
-
async function handleNonCachedQuery(target, selections, aliasMap, onfulfilled, onrejected) {
|
|
1175
|
+
async function handleNonCachedQuery(target, options, selections, aliasMap, onfulfilled, onrejected) {
|
|
1132
1176
|
try {
|
|
1133
|
-
const localCached = await getQueryLocalCacheQuery(target);
|
|
1177
|
+
const localCached = await getQueryLocalCacheQuery(target, options);
|
|
1134
1178
|
if (localCached) {
|
|
1135
1179
|
return onfulfilled?.(localCached);
|
|
1136
1180
|
}
|
|
1137
1181
|
const rows = await target.execute();
|
|
1138
1182
|
const transformed = applyFromDriverTransform(rows, selections, aliasMap);
|
|
1139
|
-
await saveQueryLocalCacheQuery(target, transformed);
|
|
1183
|
+
await saveQueryLocalCacheQuery(target, transformed, options);
|
|
1140
1184
|
return onfulfilled?.(transformed);
|
|
1141
1185
|
} catch (error) {
|
|
1142
1186
|
return onrejected?.(error);
|
|
@@ -1168,7 +1212,14 @@ function createAliasedSelectBuilder(db, fields, selectFn, useCache, options, cac
|
|
|
1168
1212
|
onrejected
|
|
1169
1213
|
);
|
|
1170
1214
|
} else {
|
|
1171
|
-
return handleNonCachedQuery(
|
|
1215
|
+
return handleNonCachedQuery(
|
|
1216
|
+
target,
|
|
1217
|
+
options,
|
|
1218
|
+
selections,
|
|
1219
|
+
aliasMap,
|
|
1220
|
+
onfulfilled,
|
|
1221
|
+
onrejected
|
|
1222
|
+
);
|
|
1172
1223
|
}
|
|
1173
1224
|
};
|
|
1174
1225
|
}
|
|
@@ -1197,6 +1248,43 @@ const DEFAULT_OPTIONS = {
|
|
|
1197
1248
|
cacheEntityExpirationName: "expiration",
|
|
1198
1249
|
cacheEntityDataName: "data"
|
|
1199
1250
|
};
|
|
1251
|
+
function createRawQueryExecutor(db, options, useGlobalCache = false) {
|
|
1252
|
+
return async function(query, cacheTtl) {
|
|
1253
|
+
let sql2;
|
|
1254
|
+
if (isSQLWrapper(query)) {
|
|
1255
|
+
const sqlWrapper = query;
|
|
1256
|
+
sql2 = sqlWrapper.getSQL().toQuery(
|
|
1257
|
+
db.dialect
|
|
1258
|
+
);
|
|
1259
|
+
} else {
|
|
1260
|
+
sql2 = {
|
|
1261
|
+
sql: query,
|
|
1262
|
+
params: []
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
const localCacheResult = await getQueryLocalCacheQuery(sql2, options);
|
|
1266
|
+
if (localCacheResult) {
|
|
1267
|
+
return localCacheResult;
|
|
1268
|
+
}
|
|
1269
|
+
if (useGlobalCache) {
|
|
1270
|
+
const cacheResult = await getFromCache({ toSQL: () => sql2 }, options);
|
|
1271
|
+
if (cacheResult) {
|
|
1272
|
+
return cacheResult;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
const results = await db.execute(query);
|
|
1276
|
+
await saveQueryLocalCacheQuery(sql2, results, options);
|
|
1277
|
+
if (useGlobalCache) {
|
|
1278
|
+
await setCacheResult(
|
|
1279
|
+
{ toSQL: () => sql2 },
|
|
1280
|
+
options,
|
|
1281
|
+
results,
|
|
1282
|
+
cacheTtl ?? options.cacheTTL ?? 120
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
return results;
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1200
1288
|
function patchDbWithSelectAliased(db, options) {
|
|
1201
1289
|
const newOptions = { ...DEFAULT_OPTIONS, ...options };
|
|
1202
1290
|
db.selectAliased = function(fields) {
|
|
@@ -1208,15 +1296,6 @@ function patchDbWithSelectAliased(db, options) {
|
|
|
1208
1296
|
newOptions
|
|
1209
1297
|
);
|
|
1210
1298
|
};
|
|
1211
|
-
db.selectAliasedDistinct = function(fields) {
|
|
1212
|
-
return createAliasedSelectBuilder(
|
|
1213
|
-
db,
|
|
1214
|
-
fields,
|
|
1215
|
-
(selections) => db.selectDistinct(selections),
|
|
1216
|
-
false,
|
|
1217
|
-
newOptions
|
|
1218
|
-
);
|
|
1219
|
-
};
|
|
1220
1299
|
db.selectAliasedCacheable = function(fields, cacheTtl) {
|
|
1221
1300
|
return createAliasedSelectBuilder(
|
|
1222
1301
|
db,
|
|
@@ -1227,6 +1306,15 @@ function patchDbWithSelectAliased(db, options) {
|
|
|
1227
1306
|
cacheTtl
|
|
1228
1307
|
);
|
|
1229
1308
|
};
|
|
1309
|
+
db.selectAliasedDistinct = function(fields) {
|
|
1310
|
+
return createAliasedSelectBuilder(
|
|
1311
|
+
db,
|
|
1312
|
+
fields,
|
|
1313
|
+
(selections) => db.selectDistinct(selections),
|
|
1314
|
+
false,
|
|
1315
|
+
newOptions
|
|
1316
|
+
);
|
|
1317
|
+
};
|
|
1230
1318
|
db.selectAliasedDistinctCacheable = function(fields, cacheTtl) {
|
|
1231
1319
|
return createAliasedSelectBuilder(
|
|
1232
1320
|
db,
|
|
@@ -1237,6 +1325,18 @@ function patchDbWithSelectAliased(db, options) {
|
|
|
1237
1325
|
cacheTtl
|
|
1238
1326
|
);
|
|
1239
1327
|
};
|
|
1328
|
+
db.selectFrom = function(table) {
|
|
1329
|
+
return db.selectAliased(getTableColumns(table)).from(table);
|
|
1330
|
+
};
|
|
1331
|
+
db.selectFromCacheable = function(table, cacheTtl) {
|
|
1332
|
+
return db.selectAliasedCacheable(getTableColumns(table), cacheTtl).from(table);
|
|
1333
|
+
};
|
|
1334
|
+
db.selectDistinctFrom = function(table) {
|
|
1335
|
+
return db.selectAliasedDistinct(getTableColumns(table)).from(table);
|
|
1336
|
+
};
|
|
1337
|
+
db.selectDistinctFromCacheable = function(table, cacheTtl) {
|
|
1338
|
+
return db.selectAliasedDistinctCacheable(getTableColumns(table), cacheTtl).from(table);
|
|
1339
|
+
};
|
|
1240
1340
|
db.insertWithCacheContext = function(table) {
|
|
1241
1341
|
return insertAndEvictCacheBuilder(db, table, newOptions, false);
|
|
1242
1342
|
};
|
|
@@ -1255,6 +1355,8 @@ function patchDbWithSelectAliased(db, options) {
|
|
|
1255
1355
|
db.deleteAndEvictCache = function(table) {
|
|
1256
1356
|
return deleteAndEvictCacheBuilder(db, table, newOptions, true);
|
|
1257
1357
|
};
|
|
1358
|
+
db.executeQuery = createRawQueryExecutor(db, newOptions, false);
|
|
1359
|
+
db.executeQueryCacheable = createRawQueryExecutor(db, newOptions, true);
|
|
1258
1360
|
return db;
|
|
1259
1361
|
}
|
|
1260
1362
|
class ForgeSQLAnalyseOperation {
|
|
@@ -1722,16 +1824,19 @@ class ForgeSQLORMImpl {
|
|
|
1722
1824
|
*/
|
|
1723
1825
|
async executeWithCacheContextAndReturnValue(cacheContext) {
|
|
1724
1826
|
return await this.executeWithLocalCacheContextAndReturnValue(
|
|
1725
|
-
async () => await cacheApplicationContext.run(
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1827
|
+
async () => await cacheApplicationContext.run(
|
|
1828
|
+
cacheApplicationContext.getStore() ?? { tables: /* @__PURE__ */ new Set() },
|
|
1829
|
+
async () => {
|
|
1830
|
+
try {
|
|
1831
|
+
return await cacheContext();
|
|
1832
|
+
} finally {
|
|
1833
|
+
await clearTablesCache(
|
|
1834
|
+
Array.from(cacheApplicationContext.getStore()?.tables ?? []),
|
|
1835
|
+
this.options
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1733
1838
|
}
|
|
1734
|
-
|
|
1839
|
+
)
|
|
1735
1840
|
);
|
|
1736
1841
|
}
|
|
1737
1842
|
/**
|
|
@@ -1742,9 +1847,12 @@ class ForgeSQLORMImpl {
|
|
|
1742
1847
|
* @returns Promise that resolves to the return value of the cacheContext function
|
|
1743
1848
|
*/
|
|
1744
1849
|
async executeWithLocalCacheContextAndReturnValue(cacheContext) {
|
|
1745
|
-
return await localCacheApplicationContext.run(
|
|
1746
|
-
|
|
1747
|
-
|
|
1850
|
+
return await localCacheApplicationContext.run(
|
|
1851
|
+
localCacheApplicationContext.getStore() ?? { cache: {} },
|
|
1852
|
+
async () => {
|
|
1853
|
+
return await cacheContext();
|
|
1854
|
+
}
|
|
1855
|
+
);
|
|
1748
1856
|
}
|
|
1749
1857
|
/**
|
|
1750
1858
|
* Executes operations within a local cache context.
|
|
@@ -1973,6 +2081,147 @@ class ForgeSQLORMImpl {
|
|
|
1973
2081
|
}
|
|
1974
2082
|
return this.drizzle.selectAliasedDistinctCacheable(fields, cacheTTL);
|
|
1975
2083
|
}
|
|
2084
|
+
/**
|
|
2085
|
+
* Creates a select query builder for all columns from a table with field aliasing support.
|
|
2086
|
+
* This is a convenience method that automatically selects all columns from the specified table.
|
|
2087
|
+
*
|
|
2088
|
+
* @template T - The type of the table
|
|
2089
|
+
* @param table - The table to select from
|
|
2090
|
+
* @returns Select query builder with all table columns and field aliasing support
|
|
2091
|
+
* @example
|
|
2092
|
+
* ```typescript
|
|
2093
|
+
* const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
|
|
2094
|
+
* ```
|
|
2095
|
+
*/
|
|
2096
|
+
selectFrom(table) {
|
|
2097
|
+
return this.drizzle.selectFrom(table);
|
|
2098
|
+
}
|
|
2099
|
+
/**
|
|
2100
|
+
* Creates a select distinct query builder for all columns from a table with field aliasing support.
|
|
2101
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table.
|
|
2102
|
+
*
|
|
2103
|
+
* @template T - The type of the table
|
|
2104
|
+
* @param table - The table to select from
|
|
2105
|
+
* @returns Select distinct query builder with all table columns and field aliasing support
|
|
2106
|
+
* @example
|
|
2107
|
+
* ```typescript
|
|
2108
|
+
* const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
|
|
2109
|
+
* ```
|
|
2110
|
+
*/
|
|
2111
|
+
selectDistinctFrom(table) {
|
|
2112
|
+
return this.drizzle.selectDistinctFrom(table);
|
|
2113
|
+
}
|
|
2114
|
+
/**
|
|
2115
|
+
* Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
|
|
2116
|
+
* This is a convenience method that automatically selects all columns from the specified table with caching enabled.
|
|
2117
|
+
*
|
|
2118
|
+
* @template T - The type of the table
|
|
2119
|
+
* @param table - The table to select from
|
|
2120
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
2121
|
+
* @returns Select query builder with all table columns, field aliasing, and caching support
|
|
2122
|
+
* @example
|
|
2123
|
+
* ```typescript
|
|
2124
|
+
* const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
|
|
2125
|
+
* ```
|
|
2126
|
+
*/
|
|
2127
|
+
selectCacheableFrom(table, cacheTTL) {
|
|
2128
|
+
return this.drizzle.selectFromCacheable(table, cacheTTL);
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
|
|
2132
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
|
|
2133
|
+
*
|
|
2134
|
+
* @template T - The type of the table
|
|
2135
|
+
* @param table - The table to select from
|
|
2136
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
2137
|
+
* @returns Select distinct query builder with all table columns, field aliasing, and caching support
|
|
2138
|
+
* @example
|
|
2139
|
+
* ```typescript
|
|
2140
|
+
* const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
|
|
2141
|
+
* ```
|
|
2142
|
+
*/
|
|
2143
|
+
selectDistinctCacheableFrom(table, cacheTTL) {
|
|
2144
|
+
return this.drizzle.selectDistinctFromCacheable(table, cacheTTL);
|
|
2145
|
+
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Executes a raw SQL query with local cache support.
|
|
2148
|
+
* This method provides local caching for raw SQL queries within the current invocation context.
|
|
2149
|
+
* Results are cached locally and will be returned from cache on subsequent identical queries.
|
|
2150
|
+
*
|
|
2151
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
2152
|
+
* @returns Promise with query results
|
|
2153
|
+
* @example
|
|
2154
|
+
* ```typescript
|
|
2155
|
+
* // Using SQLWrapper
|
|
2156
|
+
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
2157
|
+
*
|
|
2158
|
+
* // Using string
|
|
2159
|
+
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
2160
|
+
* ```
|
|
2161
|
+
*/
|
|
2162
|
+
execute(query) {
|
|
2163
|
+
return this.drizzle.executeQuery(query);
|
|
2164
|
+
}
|
|
2165
|
+
/**
|
|
2166
|
+
* Executes a raw SQL query with both local and global cache support.
|
|
2167
|
+
* This method provides comprehensive caching for raw SQL queries:
|
|
2168
|
+
* - Local cache: Within the current invocation context
|
|
2169
|
+
* - Global cache: Cross-invocation caching using @forge/kvs
|
|
2170
|
+
*
|
|
2171
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
2172
|
+
* @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
|
|
2173
|
+
* @returns Promise with query results
|
|
2174
|
+
* @example
|
|
2175
|
+
* ```typescript
|
|
2176
|
+
* // Using SQLWrapper with custom TTL
|
|
2177
|
+
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
2178
|
+
*
|
|
2179
|
+
* // Using string with default TTL
|
|
2180
|
+
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
2181
|
+
* ```
|
|
2182
|
+
*/
|
|
2183
|
+
executeCacheable(query, cacheTtl) {
|
|
2184
|
+
return this.drizzle.executeQueryCacheable(query, cacheTtl);
|
|
2185
|
+
}
|
|
2186
|
+
/**
|
|
2187
|
+
* Creates a Common Table Expression (CTE) builder for complex queries.
|
|
2188
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
2189
|
+
*
|
|
2190
|
+
* @returns WithBuilder for creating CTEs
|
|
2191
|
+
* @example
|
|
2192
|
+
* ```typescript
|
|
2193
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
2194
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
2195
|
+
* .from(users)
|
|
2196
|
+
* .groupBy(users.id)
|
|
2197
|
+
* );
|
|
2198
|
+
* ```
|
|
2199
|
+
*/
|
|
2200
|
+
get $with() {
|
|
2201
|
+
return this.drizzle.$with;
|
|
2202
|
+
}
|
|
2203
|
+
/**
|
|
2204
|
+
* Creates a query builder that uses Common Table Expressions (CTEs).
|
|
2205
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
2206
|
+
*
|
|
2207
|
+
* @param queries - Array of CTE queries created with $with()
|
|
2208
|
+
* @returns Query builder with CTE support
|
|
2209
|
+
* @example
|
|
2210
|
+
* ```typescript
|
|
2211
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
2212
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
2213
|
+
* .from(users)
|
|
2214
|
+
* .groupBy(users.id)
|
|
2215
|
+
* );
|
|
2216
|
+
*
|
|
2217
|
+
* const result = await forgeSQL.with(withQuery)
|
|
2218
|
+
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
2219
|
+
* .from(withQuery);
|
|
2220
|
+
* ```
|
|
2221
|
+
*/
|
|
2222
|
+
with(...queries) {
|
|
2223
|
+
return this.drizzle.with(...queries);
|
|
2224
|
+
}
|
|
1976
2225
|
}
|
|
1977
2226
|
class ForgeSQLORM {
|
|
1978
2227
|
ormInstance;
|
|
@@ -1985,6 +2234,68 @@ class ForgeSQLORM {
|
|
|
1985
2234
|
selectDistinctCacheable(fields, cacheTTL) {
|
|
1986
2235
|
return this.ormInstance.selectDistinctCacheable(fields, cacheTTL);
|
|
1987
2236
|
}
|
|
2237
|
+
/**
|
|
2238
|
+
* Creates a select query builder for all columns from a table with field aliasing support.
|
|
2239
|
+
* This is a convenience method that automatically selects all columns from the specified table.
|
|
2240
|
+
*
|
|
2241
|
+
* @template T - The type of the table
|
|
2242
|
+
* @param table - The table to select from
|
|
2243
|
+
* @returns Select query builder with all table columns and field aliasing support
|
|
2244
|
+
* @example
|
|
2245
|
+
* ```typescript
|
|
2246
|
+
* const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
|
|
2247
|
+
* ```
|
|
2248
|
+
*/
|
|
2249
|
+
selectFrom(table) {
|
|
2250
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectFrom(table);
|
|
2251
|
+
}
|
|
2252
|
+
/**
|
|
2253
|
+
* Creates a select distinct query builder for all columns from a table with field aliasing support.
|
|
2254
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table.
|
|
2255
|
+
*
|
|
2256
|
+
* @template T - The type of the table
|
|
2257
|
+
* @param table - The table to select from
|
|
2258
|
+
* @returns Select distinct query builder with all table columns and field aliasing support
|
|
2259
|
+
* @example
|
|
2260
|
+
* ```typescript
|
|
2261
|
+
* const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
|
|
2262
|
+
* ```
|
|
2263
|
+
*/
|
|
2264
|
+
selectDistinctFrom(table) {
|
|
2265
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFrom(table);
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
|
|
2269
|
+
* This is a convenience method that automatically selects all columns from the specified table with caching enabled.
|
|
2270
|
+
*
|
|
2271
|
+
* @template T - The type of the table
|
|
2272
|
+
* @param table - The table to select from
|
|
2273
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
2274
|
+
* @returns Select query builder with all table columns, field aliasing, and caching support
|
|
2275
|
+
* @example
|
|
2276
|
+
* ```typescript
|
|
2277
|
+
* const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
|
|
2278
|
+
* ```
|
|
2279
|
+
*/
|
|
2280
|
+
selectCacheableFrom(table, cacheTTL) {
|
|
2281
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectFromCacheable(table, cacheTTL);
|
|
2282
|
+
}
|
|
2283
|
+
/**
|
|
2284
|
+
* Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
|
|
2285
|
+
* This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
|
|
2286
|
+
*
|
|
2287
|
+
* @template T - The type of the table
|
|
2288
|
+
* @param table - The table to select from
|
|
2289
|
+
* @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
|
|
2290
|
+
* @returns Select distinct query builder with all table columns, field aliasing, and caching support
|
|
2291
|
+
* @example
|
|
2292
|
+
* ```typescript
|
|
2293
|
+
* const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
|
|
2294
|
+
* ```
|
|
2295
|
+
*/
|
|
2296
|
+
selectDistinctCacheableFrom(table, cacheTTL) {
|
|
2297
|
+
return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFromCacheable(table, cacheTTL);
|
|
2298
|
+
}
|
|
1988
2299
|
executeWithCacheContext(cacheContext) {
|
|
1989
2300
|
return this.ormInstance.executeWithCacheContext(cacheContext);
|
|
1990
2301
|
}
|
|
@@ -2157,6 +2468,85 @@ class ForgeSQLORM {
|
|
|
2157
2468
|
getDrizzleQueryBuilder() {
|
|
2158
2469
|
return this.ormInstance.getDrizzleQueryBuilder();
|
|
2159
2470
|
}
|
|
2471
|
+
/**
|
|
2472
|
+
* Executes a raw SQL query with local cache support.
|
|
2473
|
+
* This method provides local caching for raw SQL queries within the current invocation context.
|
|
2474
|
+
* Results are cached locally and will be returned from cache on subsequent identical queries.
|
|
2475
|
+
*
|
|
2476
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
2477
|
+
* @returns Promise with query results
|
|
2478
|
+
* @example
|
|
2479
|
+
* ```typescript
|
|
2480
|
+
* // Using SQLWrapper
|
|
2481
|
+
* const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
|
|
2482
|
+
*
|
|
2483
|
+
* // Using string
|
|
2484
|
+
* const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
|
|
2485
|
+
* ```
|
|
2486
|
+
*/
|
|
2487
|
+
execute(query) {
|
|
2488
|
+
return this.ormInstance.getDrizzleQueryBuilder().executeQuery(query);
|
|
2489
|
+
}
|
|
2490
|
+
/**
|
|
2491
|
+
* Executes a raw SQL query with both local and global cache support.
|
|
2492
|
+
* This method provides comprehensive caching for raw SQL queries:
|
|
2493
|
+
* - Local cache: Within the current invocation context
|
|
2494
|
+
* - Global cache: Cross-invocation caching using @forge/kvs
|
|
2495
|
+
*
|
|
2496
|
+
* @param query - The SQL query to execute (SQLWrapper or string)
|
|
2497
|
+
* @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
|
|
2498
|
+
* @returns Promise with query results
|
|
2499
|
+
* @example
|
|
2500
|
+
* ```typescript
|
|
2501
|
+
* // Using SQLWrapper with custom TTL
|
|
2502
|
+
* const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
|
|
2503
|
+
*
|
|
2504
|
+
* // Using string with default TTL
|
|
2505
|
+
* const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
|
|
2506
|
+
* ```
|
|
2507
|
+
*/
|
|
2508
|
+
executeCacheable(query, cacheTtl) {
|
|
2509
|
+
return this.ormInstance.getDrizzleQueryBuilder().executeQueryCacheable(query, cacheTtl);
|
|
2510
|
+
}
|
|
2511
|
+
/**
|
|
2512
|
+
* Creates a Common Table Expression (CTE) builder for complex queries.
|
|
2513
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
2514
|
+
*
|
|
2515
|
+
* @returns WithBuilder for creating CTEs
|
|
2516
|
+
* @example
|
|
2517
|
+
* ```typescript
|
|
2518
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
2519
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
2520
|
+
* .from(users)
|
|
2521
|
+
* .groupBy(users.id)
|
|
2522
|
+
* );
|
|
2523
|
+
* ```
|
|
2524
|
+
*/
|
|
2525
|
+
get $with() {
|
|
2526
|
+
return this.ormInstance.getDrizzleQueryBuilder().$with;
|
|
2527
|
+
}
|
|
2528
|
+
/**
|
|
2529
|
+
* Creates a query builder that uses Common Table Expressions (CTEs).
|
|
2530
|
+
* CTEs allow you to define temporary named result sets that exist within the scope of a single query.
|
|
2531
|
+
*
|
|
2532
|
+
* @param queries - Array of CTE queries created with $with()
|
|
2533
|
+
* @returns Query builder with CTE support
|
|
2534
|
+
* @example
|
|
2535
|
+
* ```typescript
|
|
2536
|
+
* const withQuery = forgeSQL.$with('userStats').as(
|
|
2537
|
+
* forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
|
|
2538
|
+
* .from(users)
|
|
2539
|
+
* .groupBy(users.id)
|
|
2540
|
+
* );
|
|
2541
|
+
*
|
|
2542
|
+
* const result = await forgeSQL.with(withQuery)
|
|
2543
|
+
* .select({ userId: withQuery.userId, count: withQuery.count })
|
|
2544
|
+
* .from(withQuery);
|
|
2545
|
+
* ```
|
|
2546
|
+
*/
|
|
2547
|
+
with(...queries) {
|
|
2548
|
+
return this.ormInstance.getDrizzleQueryBuilder().with(...queries);
|
|
2549
|
+
}
|
|
2160
2550
|
}
|
|
2161
2551
|
const forgeDateTimeString = customType({
|
|
2162
2552
|
dataType() {
|