forge-sql-orm 2.1.0 → 2.1.1

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.
@@ -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
- const fromJSDate = DateTime.fromJSDate(value);
35
- if (fromJSDate.isValid) {
36
- return fromJSDate.toFormat(format);
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);
@@ -1024,11 +1046,34 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
1024
1046
  return forgeDriver(modifiedQuery, params, method);
1025
1047
  };
1026
1048
  }
1049
+ const NON_CACHE_CLEARING_ERROR_CODES = [
1050
+ "VALIDATION_ERROR",
1051
+ "CONSTRAINT_ERROR"
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
+ ];
1027
1066
  function shouldClearCacheOnError(error) {
1028
- if (error?.code === "VALIDATION_ERROR" || error?.code === "CONSTRAINT_ERROR" || error?.message && /validation/i.exec(error.message)) {
1067
+ if (error?.code && NON_CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
1068
+ return false;
1069
+ }
1070
+ if (error?.message && NON_CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))) {
1029
1071
  return false;
1030
1072
  }
1031
- if (error?.code === "DEADLOCK" || error?.code === "LOCK_WAIT_TIMEOUT" || error?.code === "CONNECTION_ERROR" || error?.message && /timeout/i.exec(error.message) || error?.message && /connection/i.exec(error.message)) {
1073
+ if (error?.code && CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
1074
+ return true;
1075
+ }
1076
+ if (error?.message && CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))) {
1032
1077
  return true;
1033
1078
  }
1034
1079
  return true;
@@ -1197,6 +1242,41 @@ const DEFAULT_OPTIONS = {
1197
1242
  cacheEntityExpirationName: "expiration",
1198
1243
  cacheEntityDataName: "data"
1199
1244
  };
1245
+ function createRawQueryExecutor(db, options, useGlobalCache = false) {
1246
+ return async function(query, cacheTtl) {
1247
+ let sql2;
1248
+ if (isSQLWrapper(query)) {
1249
+ const sqlWrapper = query;
1250
+ sql2 = sqlWrapper.getSQL().toQuery(db.dialect);
1251
+ } else {
1252
+ sql2 = {
1253
+ sql: query,
1254
+ params: []
1255
+ };
1256
+ }
1257
+ const localCacheResult = await getQueryLocalCacheQuery(sql2);
1258
+ if (localCacheResult) {
1259
+ return localCacheResult;
1260
+ }
1261
+ if (useGlobalCache) {
1262
+ const cacheResult = await getFromCache({ toSQL: () => sql2 }, options);
1263
+ if (cacheResult) {
1264
+ return cacheResult;
1265
+ }
1266
+ }
1267
+ const results = await db.execute(query);
1268
+ await saveQueryLocalCacheQuery(sql2, results);
1269
+ if (useGlobalCache) {
1270
+ await setCacheResult(
1271
+ { toSQL: () => sql2 },
1272
+ options,
1273
+ results,
1274
+ cacheTtl ?? options.cacheTTL ?? 120
1275
+ );
1276
+ }
1277
+ return results;
1278
+ };
1279
+ }
1200
1280
  function patchDbWithSelectAliased(db, options) {
1201
1281
  const newOptions = { ...DEFAULT_OPTIONS, ...options };
1202
1282
  db.selectAliased = function(fields) {
@@ -1208,15 +1288,6 @@ function patchDbWithSelectAliased(db, options) {
1208
1288
  newOptions
1209
1289
  );
1210
1290
  };
1211
- db.selectAliasedDistinct = function(fields) {
1212
- return createAliasedSelectBuilder(
1213
- db,
1214
- fields,
1215
- (selections) => db.selectDistinct(selections),
1216
- false,
1217
- newOptions
1218
- );
1219
- };
1220
1291
  db.selectAliasedCacheable = function(fields, cacheTtl) {
1221
1292
  return createAliasedSelectBuilder(
1222
1293
  db,
@@ -1227,6 +1298,15 @@ function patchDbWithSelectAliased(db, options) {
1227
1298
  cacheTtl
1228
1299
  );
1229
1300
  };
1301
+ db.selectAliasedDistinct = function(fields) {
1302
+ return createAliasedSelectBuilder(
1303
+ db,
1304
+ fields,
1305
+ (selections) => db.selectDistinct(selections),
1306
+ false,
1307
+ newOptions
1308
+ );
1309
+ };
1230
1310
  db.selectAliasedDistinctCacheable = function(fields, cacheTtl) {
1231
1311
  return createAliasedSelectBuilder(
1232
1312
  db,
@@ -1237,6 +1317,18 @@ function patchDbWithSelectAliased(db, options) {
1237
1317
  cacheTtl
1238
1318
  );
1239
1319
  };
1320
+ db.selectFrom = function(table) {
1321
+ return db.selectAliased(getTableColumns(table)).from(table);
1322
+ };
1323
+ db.selectFromCacheable = function(table, cacheTtl) {
1324
+ return db.selectAliasedCacheable(getTableColumns(table), cacheTtl).from(table);
1325
+ };
1326
+ db.selectDistinctFrom = function(table) {
1327
+ return db.selectAliasedDistinct(getTableColumns(table)).from(table);
1328
+ };
1329
+ db.selectDistinctFromCacheable = function(table, cacheTtl) {
1330
+ return db.selectAliasedDistinctCacheable(getTableColumns(table), cacheTtl).from(table);
1331
+ };
1240
1332
  db.insertWithCacheContext = function(table) {
1241
1333
  return insertAndEvictCacheBuilder(db, table, newOptions, false);
1242
1334
  };
@@ -1255,6 +1347,8 @@ function patchDbWithSelectAliased(db, options) {
1255
1347
  db.deleteAndEvictCache = function(table) {
1256
1348
  return deleteAndEvictCacheBuilder(db, table, newOptions, true);
1257
1349
  };
1350
+ db.executeQuery = createRawQueryExecutor(db, newOptions, false);
1351
+ db.executeQueryCacheable = createRawQueryExecutor(db, newOptions, true);
1258
1352
  return db;
1259
1353
  }
1260
1354
  class ForgeSQLAnalyseOperation {
@@ -1722,7 +1816,7 @@ class ForgeSQLORMImpl {
1722
1816
  */
1723
1817
  async executeWithCacheContextAndReturnValue(cacheContext) {
1724
1818
  return await this.executeWithLocalCacheContextAndReturnValue(
1725
- async () => await cacheApplicationContext.run({ tables: /* @__PURE__ */ new Set() }, async () => {
1819
+ async () => await cacheApplicationContext.run(cacheApplicationContext.getStore() ?? { tables: /* @__PURE__ */ new Set() }, async () => {
1726
1820
  try {
1727
1821
  return await cacheContext();
1728
1822
  } finally {
@@ -1737,19 +1831,19 @@ class ForgeSQLORMImpl {
1737
1831
  /**
1738
1832
  * Executes operations within a local cache context and returns a value.
1739
1833
  * This provides in-memory caching for select queries within a single request scope.
1740
- *
1834
+ *
1741
1835
  * @param cacheContext - Function containing operations that will benefit from local caching
1742
1836
  * @returns Promise that resolves to the return value of the cacheContext function
1743
1837
  */
1744
1838
  async executeWithLocalCacheContextAndReturnValue(cacheContext) {
1745
- return await localCacheApplicationContext.run({ cache: {} }, async () => {
1839
+ return await localCacheApplicationContext.run(localCacheApplicationContext.getStore() ?? { cache: {} }, async () => {
1746
1840
  return await cacheContext();
1747
1841
  });
1748
1842
  }
1749
1843
  /**
1750
1844
  * Executes operations within a local cache context.
1751
1845
  * This provides in-memory caching for select queries within a single request scope.
1752
- *
1846
+ *
1753
1847
  * @param cacheContext - Function containing operations that will benefit from local caching
1754
1848
  * @returns Promise that resolves when all operations are complete
1755
1849
  */
@@ -1973,6 +2067,147 @@ class ForgeSQLORMImpl {
1973
2067
  }
1974
2068
  return this.drizzle.selectAliasedDistinctCacheable(fields, cacheTTL);
1975
2069
  }
2070
+ /**
2071
+ * Creates a select query builder for all columns from a table with field aliasing support.
2072
+ * This is a convenience method that automatically selects all columns from the specified table.
2073
+ *
2074
+ * @template T - The type of the table
2075
+ * @param table - The table to select from
2076
+ * @returns Select query builder with all table columns and field aliasing support
2077
+ * @example
2078
+ * ```typescript
2079
+ * const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
2080
+ * ```
2081
+ */
2082
+ selectFrom(table) {
2083
+ return this.drizzle.selectFrom(table);
2084
+ }
2085
+ /**
2086
+ * Creates a select distinct query builder for all columns from a table with field aliasing support.
2087
+ * This is a convenience method that automatically selects all distinct columns from the specified table.
2088
+ *
2089
+ * @template T - The type of the table
2090
+ * @param table - The table to select from
2091
+ * @returns Select distinct query builder with all table columns and field aliasing support
2092
+ * @example
2093
+ * ```typescript
2094
+ * const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
2095
+ * ```
2096
+ */
2097
+ selectDistinctFrom(table) {
2098
+ return this.drizzle.selectDistinctFrom(table);
2099
+ }
2100
+ /**
2101
+ * Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
2102
+ * This is a convenience method that automatically selects all columns from the specified table with caching enabled.
2103
+ *
2104
+ * @template T - The type of the table
2105
+ * @param table - The table to select from
2106
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2107
+ * @returns Select query builder with all table columns, field aliasing, and caching support
2108
+ * @example
2109
+ * ```typescript
2110
+ * const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
2111
+ * ```
2112
+ */
2113
+ selectCacheableFrom(table, cacheTTL) {
2114
+ return this.drizzle.selectFromCacheable(table, cacheTTL);
2115
+ }
2116
+ /**
2117
+ * Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
2118
+ * This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
2119
+ *
2120
+ * @template T - The type of the table
2121
+ * @param table - The table to select from
2122
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2123
+ * @returns Select distinct query builder with all table columns, field aliasing, and caching support
2124
+ * @example
2125
+ * ```typescript
2126
+ * const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
2127
+ * ```
2128
+ */
2129
+ selectDistinctCacheableFrom(table, cacheTTL) {
2130
+ return this.drizzle.selectDistinctFromCacheable(table, cacheTTL);
2131
+ }
2132
+ /**
2133
+ * Executes a raw SQL query with local cache support.
2134
+ * This method provides local caching for raw SQL queries within the current invocation context.
2135
+ * Results are cached locally and will be returned from cache on subsequent identical queries.
2136
+ *
2137
+ * @param query - The SQL query to execute (SQLWrapper or string)
2138
+ * @returns Promise with query results
2139
+ * @example
2140
+ * ```typescript
2141
+ * // Using SQLWrapper
2142
+ * const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
2143
+ *
2144
+ * // Using string
2145
+ * const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
2146
+ * ```
2147
+ */
2148
+ execute(query) {
2149
+ return this.drizzle.executeQuery(query);
2150
+ }
2151
+ /**
2152
+ * Executes a raw SQL query with both local and global cache support.
2153
+ * This method provides comprehensive caching for raw SQL queries:
2154
+ * - Local cache: Within the current invocation context
2155
+ * - Global cache: Cross-invocation caching using @forge/kvs
2156
+ *
2157
+ * @param query - The SQL query to execute (SQLWrapper or string)
2158
+ * @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
2159
+ * @returns Promise with query results
2160
+ * @example
2161
+ * ```typescript
2162
+ * // Using SQLWrapper with custom TTL
2163
+ * const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
2164
+ *
2165
+ * // Using string with default TTL
2166
+ * const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
2167
+ * ```
2168
+ */
2169
+ executeCacheable(query, cacheTtl) {
2170
+ return this.drizzle.executeQueryCacheable(query, cacheTtl);
2171
+ }
2172
+ /**
2173
+ * Creates a Common Table Expression (CTE) builder for complex queries.
2174
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2175
+ *
2176
+ * @returns WithBuilder for creating CTEs
2177
+ * @example
2178
+ * ```typescript
2179
+ * const withQuery = forgeSQL.$with('userStats').as(
2180
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2181
+ * .from(users)
2182
+ * .groupBy(users.id)
2183
+ * );
2184
+ * ```
2185
+ */
2186
+ get $with() {
2187
+ return this.drizzle.$with;
2188
+ }
2189
+ /**
2190
+ * Creates a query builder that uses Common Table Expressions (CTEs).
2191
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2192
+ *
2193
+ * @param queries - Array of CTE queries created with $with()
2194
+ * @returns Query builder with CTE support
2195
+ * @example
2196
+ * ```typescript
2197
+ * const withQuery = forgeSQL.$with('userStats').as(
2198
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2199
+ * .from(users)
2200
+ * .groupBy(users.id)
2201
+ * );
2202
+ *
2203
+ * const result = await forgeSQL.with(withQuery)
2204
+ * .select({ userId: withQuery.userId, count: withQuery.count })
2205
+ * .from(withQuery);
2206
+ * ```
2207
+ */
2208
+ with(...queries) {
2209
+ return this.drizzle.with(...queries);
2210
+ }
1976
2211
  }
1977
2212
  class ForgeSQLORM {
1978
2213
  ormInstance;
@@ -1985,6 +2220,68 @@ class ForgeSQLORM {
1985
2220
  selectDistinctCacheable(fields, cacheTTL) {
1986
2221
  return this.ormInstance.selectDistinctCacheable(fields, cacheTTL);
1987
2222
  }
2223
+ /**
2224
+ * Creates a select query builder for all columns from a table with field aliasing support.
2225
+ * This is a convenience method that automatically selects all columns from the specified table.
2226
+ *
2227
+ * @template T - The type of the table
2228
+ * @param table - The table to select from
2229
+ * @returns Select query builder with all table columns and field aliasing support
2230
+ * @example
2231
+ * ```typescript
2232
+ * const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
2233
+ * ```
2234
+ */
2235
+ selectFrom(table) {
2236
+ return this.ormInstance.getDrizzleQueryBuilder().selectFrom(table);
2237
+ }
2238
+ /**
2239
+ * Creates a select distinct query builder for all columns from a table with field aliasing support.
2240
+ * This is a convenience method that automatically selects all distinct columns from the specified table.
2241
+ *
2242
+ * @template T - The type of the table
2243
+ * @param table - The table to select from
2244
+ * @returns Select distinct query builder with all table columns and field aliasing support
2245
+ * @example
2246
+ * ```typescript
2247
+ * const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
2248
+ * ```
2249
+ */
2250
+ selectDistinctFrom(table) {
2251
+ return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFrom(table);
2252
+ }
2253
+ /**
2254
+ * Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
2255
+ * This is a convenience method that automatically selects all columns from the specified table with caching enabled.
2256
+ *
2257
+ * @template T - The type of the table
2258
+ * @param table - The table to select from
2259
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2260
+ * @returns Select query builder with all table columns, field aliasing, and caching support
2261
+ * @example
2262
+ * ```typescript
2263
+ * const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
2264
+ * ```
2265
+ */
2266
+ selectCacheableFrom(table, cacheTTL) {
2267
+ return this.ormInstance.getDrizzleQueryBuilder().selectFromCacheable(table, cacheTTL);
2268
+ }
2269
+ /**
2270
+ * Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
2271
+ * This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
2272
+ *
2273
+ * @template T - The type of the table
2274
+ * @param table - The table to select from
2275
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2276
+ * @returns Select distinct query builder with all table columns, field aliasing, and caching support
2277
+ * @example
2278
+ * ```typescript
2279
+ * const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
2280
+ * ```
2281
+ */
2282
+ selectDistinctCacheableFrom(table, cacheTTL) {
2283
+ return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFromCacheable(table, cacheTTL);
2284
+ }
1988
2285
  executeWithCacheContext(cacheContext) {
1989
2286
  return this.ormInstance.executeWithCacheContext(cacheContext);
1990
2287
  }
@@ -1994,7 +2291,7 @@ class ForgeSQLORM {
1994
2291
  /**
1995
2292
  * Executes operations within a local cache context.
1996
2293
  * This provides in-memory caching for select queries within a single request scope.
1997
- *
2294
+ *
1998
2295
  * @param cacheContext - Function containing operations that will benefit from local caching
1999
2296
  * @returns Promise that resolves when all operations are complete
2000
2297
  */
@@ -2004,7 +2301,7 @@ class ForgeSQLORM {
2004
2301
  /**
2005
2302
  * Executes operations within a local cache context and returns a value.
2006
2303
  * This provides in-memory caching for select queries within a single request scope.
2007
- *
2304
+ *
2008
2305
  * @param cacheContext - Function containing operations that will benefit from local caching
2009
2306
  * @returns Promise that resolves to the return value of the cacheContext function
2010
2307
  */
@@ -2157,6 +2454,85 @@ class ForgeSQLORM {
2157
2454
  getDrizzleQueryBuilder() {
2158
2455
  return this.ormInstance.getDrizzleQueryBuilder();
2159
2456
  }
2457
+ /**
2458
+ * Executes a raw SQL query with local cache support.
2459
+ * This method provides local caching for raw SQL queries within the current invocation context.
2460
+ * Results are cached locally and will be returned from cache on subsequent identical queries.
2461
+ *
2462
+ * @param query - The SQL query to execute (SQLWrapper or string)
2463
+ * @returns Promise with query results
2464
+ * @example
2465
+ * ```typescript
2466
+ * // Using SQLWrapper
2467
+ * const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
2468
+ *
2469
+ * // Using string
2470
+ * const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
2471
+ * ```
2472
+ */
2473
+ execute(query) {
2474
+ return this.ormInstance.getDrizzleQueryBuilder().executeQuery(query);
2475
+ }
2476
+ /**
2477
+ * Executes a raw SQL query with both local and global cache support.
2478
+ * This method provides comprehensive caching for raw SQL queries:
2479
+ * - Local cache: Within the current invocation context
2480
+ * - Global cache: Cross-invocation caching using @forge/kvs
2481
+ *
2482
+ * @param query - The SQL query to execute (SQLWrapper or string)
2483
+ * @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
2484
+ * @returns Promise with query results
2485
+ * @example
2486
+ * ```typescript
2487
+ * // Using SQLWrapper with custom TTL
2488
+ * const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
2489
+ *
2490
+ * // Using string with default TTL
2491
+ * const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
2492
+ * ```
2493
+ */
2494
+ executeCacheable(query, cacheTtl) {
2495
+ return this.ormInstance.getDrizzleQueryBuilder().executeQueryCacheable(query, cacheTtl);
2496
+ }
2497
+ /**
2498
+ * Creates a Common Table Expression (CTE) builder for complex queries.
2499
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2500
+ *
2501
+ * @returns WithBuilder for creating CTEs
2502
+ * @example
2503
+ * ```typescript
2504
+ * const withQuery = forgeSQL.$with('userStats').as(
2505
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2506
+ * .from(users)
2507
+ * .groupBy(users.id)
2508
+ * );
2509
+ * ```
2510
+ */
2511
+ get $with() {
2512
+ return this.ormInstance.getDrizzleQueryBuilder().$with;
2513
+ }
2514
+ /**
2515
+ * Creates a query builder that uses Common Table Expressions (CTEs).
2516
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2517
+ *
2518
+ * @param queries - Array of CTE queries created with $with()
2519
+ * @returns Query builder with CTE support
2520
+ * @example
2521
+ * ```typescript
2522
+ * const withQuery = forgeSQL.$with('userStats').as(
2523
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2524
+ * .from(users)
2525
+ * .groupBy(users.id)
2526
+ * );
2527
+ *
2528
+ * const result = await forgeSQL.with(withQuery)
2529
+ * .select({ userId: withQuery.userId, count: withQuery.count })
2530
+ * .from(withQuery);
2531
+ * ```
2532
+ */
2533
+ with(...queries) {
2534
+ return this.ormInstance.getDrizzleQueryBuilder().with(...queries);
2535
+ }
2160
2536
  }
2161
2537
  const forgeDateTimeString = customType({
2162
2538
  dataType() {