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.
@@ -50,12 +50,34 @@ const parseDateTime = (value, format) => {
50
50
  return result;
51
51
  };
52
52
  function formatDateTime(value, format) {
53
- const fromJSDate = luxon.DateTime.fromJSDate(value);
54
- if (fromJSDate.isValid) {
55
- return fromJSDate.toFormat(format);
53
+ let dt = null;
54
+ if (value instanceof Date) {
55
+ dt = luxon.DateTime.fromJSDate(value);
56
+ } else if (typeof value === "string") {
57
+ for (const parser of [
58
+ luxon.DateTime.fromISO,
59
+ luxon.DateTime.fromRFC2822,
60
+ luxon.DateTime.fromSQL,
61
+ luxon.DateTime.fromHTTP
62
+ ]) {
63
+ dt = parser(value);
64
+ if (dt.isValid) break;
65
+ }
66
+ if (!dt?.isValid) {
67
+ const parsed = Number(value);
68
+ if (!isNaN(parsed)) {
69
+ dt = luxon.DateTime.fromMillis(parsed);
70
+ }
71
+ }
72
+ } else if (typeof value === "number") {
73
+ dt = luxon.DateTime.fromMillis(value);
56
74
  } else {
75
+ throw new Error("Unsupported type");
76
+ }
77
+ if (!dt?.isValid) {
57
78
  throw new Error("Invalid Date");
58
79
  }
80
+ return dt.toFormat(format);
59
81
  }
60
82
  function getPrimaryKeys(table2) {
61
83
  const { columns, primaryKeys } = getTableMetadata(table2);
@@ -1043,11 +1065,34 @@ function createForgeDriverProxy(options, logRawSqlQuery) {
1043
1065
  return forgeDriver(modifiedQuery, params, method);
1044
1066
  };
1045
1067
  }
1068
+ const NON_CACHE_CLEARING_ERROR_CODES = [
1069
+ "VALIDATION_ERROR",
1070
+ "CONSTRAINT_ERROR"
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
+ ];
1046
1085
  function shouldClearCacheOnError(error) {
1047
- if (error?.code === "VALIDATION_ERROR" || error?.code === "CONSTRAINT_ERROR" || error?.message && /validation/i.exec(error.message)) {
1086
+ if (error?.code && NON_CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
1087
+ return false;
1088
+ }
1089
+ if (error?.message && NON_CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))) {
1048
1090
  return false;
1049
1091
  }
1050
- 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)) {
1092
+ if (error?.code && CACHE_CLEARING_ERROR_CODES.includes(error.code)) {
1093
+ return true;
1094
+ }
1095
+ if (error?.message && CACHE_CLEARING_PATTERNS.some((pattern) => pattern.test(error.message))) {
1051
1096
  return true;
1052
1097
  }
1053
1098
  return true;
@@ -1216,6 +1261,41 @@ const DEFAULT_OPTIONS = {
1216
1261
  cacheEntityExpirationName: "expiration",
1217
1262
  cacheEntityDataName: "data"
1218
1263
  };
1264
+ function createRawQueryExecutor(db, options, useGlobalCache = false) {
1265
+ return async function(query, cacheTtl) {
1266
+ let sql$12;
1267
+ if (sql.isSQLWrapper(query)) {
1268
+ const sqlWrapper = query;
1269
+ sql$12 = sqlWrapper.getSQL().toQuery(db.dialect);
1270
+ } else {
1271
+ sql$12 = {
1272
+ sql: query,
1273
+ params: []
1274
+ };
1275
+ }
1276
+ const localCacheResult = await getQueryLocalCacheQuery(sql$12);
1277
+ if (localCacheResult) {
1278
+ return localCacheResult;
1279
+ }
1280
+ if (useGlobalCache) {
1281
+ const cacheResult = await getFromCache({ toSQL: () => sql$12 }, options);
1282
+ if (cacheResult) {
1283
+ return cacheResult;
1284
+ }
1285
+ }
1286
+ const results = await db.execute(query);
1287
+ await saveQueryLocalCacheQuery(sql$12, results);
1288
+ if (useGlobalCache) {
1289
+ await setCacheResult(
1290
+ { toSQL: () => sql$12 },
1291
+ options,
1292
+ results,
1293
+ cacheTtl ?? options.cacheTTL ?? 120
1294
+ );
1295
+ }
1296
+ return results;
1297
+ };
1298
+ }
1219
1299
  function patchDbWithSelectAliased(db, options) {
1220
1300
  const newOptions = { ...DEFAULT_OPTIONS, ...options };
1221
1301
  db.selectAliased = function(fields) {
@@ -1227,15 +1307,6 @@ function patchDbWithSelectAliased(db, options) {
1227
1307
  newOptions
1228
1308
  );
1229
1309
  };
1230
- db.selectAliasedDistinct = function(fields) {
1231
- return createAliasedSelectBuilder(
1232
- db,
1233
- fields,
1234
- (selections) => db.selectDistinct(selections),
1235
- false,
1236
- newOptions
1237
- );
1238
- };
1239
1310
  db.selectAliasedCacheable = function(fields, cacheTtl) {
1240
1311
  return createAliasedSelectBuilder(
1241
1312
  db,
@@ -1246,6 +1317,15 @@ function patchDbWithSelectAliased(db, options) {
1246
1317
  cacheTtl
1247
1318
  );
1248
1319
  };
1320
+ db.selectAliasedDistinct = function(fields) {
1321
+ return createAliasedSelectBuilder(
1322
+ db,
1323
+ fields,
1324
+ (selections) => db.selectDistinct(selections),
1325
+ false,
1326
+ newOptions
1327
+ );
1328
+ };
1249
1329
  db.selectAliasedDistinctCacheable = function(fields, cacheTtl) {
1250
1330
  return createAliasedSelectBuilder(
1251
1331
  db,
@@ -1256,6 +1336,18 @@ function patchDbWithSelectAliased(db, options) {
1256
1336
  cacheTtl
1257
1337
  );
1258
1338
  };
1339
+ db.selectFrom = function(table2) {
1340
+ return db.selectAliased(drizzleOrm.getTableColumns(table2)).from(table2);
1341
+ };
1342
+ db.selectFromCacheable = function(table2, cacheTtl) {
1343
+ return db.selectAliasedCacheable(drizzleOrm.getTableColumns(table2), cacheTtl).from(table2);
1344
+ };
1345
+ db.selectDistinctFrom = function(table2) {
1346
+ return db.selectAliasedDistinct(drizzleOrm.getTableColumns(table2)).from(table2);
1347
+ };
1348
+ db.selectDistinctFromCacheable = function(table2, cacheTtl) {
1349
+ return db.selectAliasedDistinctCacheable(drizzleOrm.getTableColumns(table2), cacheTtl).from(table2);
1350
+ };
1259
1351
  db.insertWithCacheContext = function(table2) {
1260
1352
  return insertAndEvictCacheBuilder(db, table2, newOptions, false);
1261
1353
  };
@@ -1274,6 +1366,8 @@ function patchDbWithSelectAliased(db, options) {
1274
1366
  db.deleteAndEvictCache = function(table2) {
1275
1367
  return deleteAndEvictCacheBuilder(db, table2, newOptions, true);
1276
1368
  };
1369
+ db.executeQuery = createRawQueryExecutor(db, newOptions, false);
1370
+ db.executeQueryCacheable = createRawQueryExecutor(db, newOptions, true);
1277
1371
  return db;
1278
1372
  }
1279
1373
  class ForgeSQLAnalyseOperation {
@@ -1741,7 +1835,7 @@ class ForgeSQLORMImpl {
1741
1835
  */
1742
1836
  async executeWithCacheContextAndReturnValue(cacheContext) {
1743
1837
  return await this.executeWithLocalCacheContextAndReturnValue(
1744
- async () => await cacheApplicationContext.run({ tables: /* @__PURE__ */ new Set() }, async () => {
1838
+ async () => await cacheApplicationContext.run(cacheApplicationContext.getStore() ?? { tables: /* @__PURE__ */ new Set() }, async () => {
1745
1839
  try {
1746
1840
  return await cacheContext();
1747
1841
  } finally {
@@ -1756,19 +1850,19 @@ class ForgeSQLORMImpl {
1756
1850
  /**
1757
1851
  * Executes operations within a local cache context and returns a value.
1758
1852
  * This provides in-memory caching for select queries within a single request scope.
1759
- *
1853
+ *
1760
1854
  * @param cacheContext - Function containing operations that will benefit from local caching
1761
1855
  * @returns Promise that resolves to the return value of the cacheContext function
1762
1856
  */
1763
1857
  async executeWithLocalCacheContextAndReturnValue(cacheContext) {
1764
- return await localCacheApplicationContext.run({ cache: {} }, async () => {
1858
+ return await localCacheApplicationContext.run(localCacheApplicationContext.getStore() ?? { cache: {} }, async () => {
1765
1859
  return await cacheContext();
1766
1860
  });
1767
1861
  }
1768
1862
  /**
1769
1863
  * Executes operations within a local cache context.
1770
1864
  * This provides in-memory caching for select queries within a single request scope.
1771
- *
1865
+ *
1772
1866
  * @param cacheContext - Function containing operations that will benefit from local caching
1773
1867
  * @returns Promise that resolves when all operations are complete
1774
1868
  */
@@ -1992,6 +2086,147 @@ class ForgeSQLORMImpl {
1992
2086
  }
1993
2087
  return this.drizzle.selectAliasedDistinctCacheable(fields, cacheTTL);
1994
2088
  }
2089
+ /**
2090
+ * Creates a select query builder for all columns from a table with field aliasing support.
2091
+ * This is a convenience method that automatically selects all columns from the specified table.
2092
+ *
2093
+ * @template T - The type of the table
2094
+ * @param table - The table to select from
2095
+ * @returns Select query builder with all table columns and field aliasing support
2096
+ * @example
2097
+ * ```typescript
2098
+ * const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
2099
+ * ```
2100
+ */
2101
+ selectFrom(table2) {
2102
+ return this.drizzle.selectFrom(table2);
2103
+ }
2104
+ /**
2105
+ * Creates a select distinct query builder for all columns from a table with field aliasing support.
2106
+ * This is a convenience method that automatically selects all distinct columns from the specified table.
2107
+ *
2108
+ * @template T - The type of the table
2109
+ * @param table - The table to select from
2110
+ * @returns Select distinct query builder with all table columns and field aliasing support
2111
+ * @example
2112
+ * ```typescript
2113
+ * const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
2114
+ * ```
2115
+ */
2116
+ selectDistinctFrom(table2) {
2117
+ return this.drizzle.selectDistinctFrom(table2);
2118
+ }
2119
+ /**
2120
+ * Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
2121
+ * This is a convenience method that automatically selects all columns from the specified table with caching enabled.
2122
+ *
2123
+ * @template T - The type of the table
2124
+ * @param table - The table to select from
2125
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2126
+ * @returns Select query builder with all table columns, field aliasing, and caching support
2127
+ * @example
2128
+ * ```typescript
2129
+ * const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
2130
+ * ```
2131
+ */
2132
+ selectCacheableFrom(table2, cacheTTL) {
2133
+ return this.drizzle.selectFromCacheable(table2, cacheTTL);
2134
+ }
2135
+ /**
2136
+ * Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
2137
+ * This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
2138
+ *
2139
+ * @template T - The type of the table
2140
+ * @param table - The table to select from
2141
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2142
+ * @returns Select distinct query builder with all table columns, field aliasing, and caching support
2143
+ * @example
2144
+ * ```typescript
2145
+ * const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
2146
+ * ```
2147
+ */
2148
+ selectDistinctCacheableFrom(table2, cacheTTL) {
2149
+ return this.drizzle.selectDistinctFromCacheable(table2, cacheTTL);
2150
+ }
2151
+ /**
2152
+ * Executes a raw SQL query with local cache support.
2153
+ * This method provides local caching for raw SQL queries within the current invocation context.
2154
+ * Results are cached locally and will be returned from cache on subsequent identical queries.
2155
+ *
2156
+ * @param query - The SQL query to execute (SQLWrapper or string)
2157
+ * @returns Promise with query results
2158
+ * @example
2159
+ * ```typescript
2160
+ * // Using SQLWrapper
2161
+ * const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
2162
+ *
2163
+ * // Using string
2164
+ * const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
2165
+ * ```
2166
+ */
2167
+ execute(query) {
2168
+ return this.drizzle.executeQuery(query);
2169
+ }
2170
+ /**
2171
+ * Executes a raw SQL query with both local and global cache support.
2172
+ * This method provides comprehensive caching for raw SQL queries:
2173
+ * - Local cache: Within the current invocation context
2174
+ * - Global cache: Cross-invocation caching using @forge/kvs
2175
+ *
2176
+ * @param query - The SQL query to execute (SQLWrapper or string)
2177
+ * @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
2178
+ * @returns Promise with query results
2179
+ * @example
2180
+ * ```typescript
2181
+ * // Using SQLWrapper with custom TTL
2182
+ * const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
2183
+ *
2184
+ * // Using string with default TTL
2185
+ * const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
2186
+ * ```
2187
+ */
2188
+ executeCacheable(query, cacheTtl) {
2189
+ return this.drizzle.executeQueryCacheable(query, cacheTtl);
2190
+ }
2191
+ /**
2192
+ * Creates a Common Table Expression (CTE) builder for complex queries.
2193
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2194
+ *
2195
+ * @returns WithBuilder for creating CTEs
2196
+ * @example
2197
+ * ```typescript
2198
+ * const withQuery = forgeSQL.$with('userStats').as(
2199
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2200
+ * .from(users)
2201
+ * .groupBy(users.id)
2202
+ * );
2203
+ * ```
2204
+ */
2205
+ get $with() {
2206
+ return this.drizzle.$with;
2207
+ }
2208
+ /**
2209
+ * Creates a query builder that uses Common Table Expressions (CTEs).
2210
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2211
+ *
2212
+ * @param queries - Array of CTE queries created with $with()
2213
+ * @returns Query builder with CTE support
2214
+ * @example
2215
+ * ```typescript
2216
+ * const withQuery = forgeSQL.$with('userStats').as(
2217
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2218
+ * .from(users)
2219
+ * .groupBy(users.id)
2220
+ * );
2221
+ *
2222
+ * const result = await forgeSQL.with(withQuery)
2223
+ * .select({ userId: withQuery.userId, count: withQuery.count })
2224
+ * .from(withQuery);
2225
+ * ```
2226
+ */
2227
+ with(...queries) {
2228
+ return this.drizzle.with(...queries);
2229
+ }
1995
2230
  }
1996
2231
  class ForgeSQLORM {
1997
2232
  ormInstance;
@@ -2004,6 +2239,68 @@ class ForgeSQLORM {
2004
2239
  selectDistinctCacheable(fields, cacheTTL) {
2005
2240
  return this.ormInstance.selectDistinctCacheable(fields, cacheTTL);
2006
2241
  }
2242
+ /**
2243
+ * Creates a select query builder for all columns from a table with field aliasing support.
2244
+ * This is a convenience method that automatically selects all columns from the specified table.
2245
+ *
2246
+ * @template T - The type of the table
2247
+ * @param table - The table to select from
2248
+ * @returns Select query builder with all table columns and field aliasing support
2249
+ * @example
2250
+ * ```typescript
2251
+ * const users = await forgeSQL.selectFrom(userTable).where(eq(userTable.id, 1));
2252
+ * ```
2253
+ */
2254
+ selectFrom(table2) {
2255
+ return this.ormInstance.getDrizzleQueryBuilder().selectFrom(table2);
2256
+ }
2257
+ /**
2258
+ * Creates a select distinct query builder for all columns from a table with field aliasing support.
2259
+ * This is a convenience method that automatically selects all distinct columns from the specified table.
2260
+ *
2261
+ * @template T - The type of the table
2262
+ * @param table - The table to select from
2263
+ * @returns Select distinct query builder with all table columns and field aliasing support
2264
+ * @example
2265
+ * ```typescript
2266
+ * const uniqueUsers = await forgeSQL.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
2267
+ * ```
2268
+ */
2269
+ selectDistinctFrom(table2) {
2270
+ return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFrom(table2);
2271
+ }
2272
+ /**
2273
+ * Creates a cacheable select query builder for all columns from a table with field aliasing and caching support.
2274
+ * This is a convenience method that automatically selects all columns from the specified table with caching enabled.
2275
+ *
2276
+ * @template T - The type of the table
2277
+ * @param table - The table to select from
2278
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2279
+ * @returns Select query builder with all table columns, field aliasing, and caching support
2280
+ * @example
2281
+ * ```typescript
2282
+ * const users = await forgeSQL.selectCacheableFrom(userTable, 300).where(eq(userTable.id, 1));
2283
+ * ```
2284
+ */
2285
+ selectCacheableFrom(table2, cacheTTL) {
2286
+ return this.ormInstance.getDrizzleQueryBuilder().selectFromCacheable(table2, cacheTTL);
2287
+ }
2288
+ /**
2289
+ * Creates a cacheable select distinct query builder for all columns from a table with field aliasing and caching support.
2290
+ * This is a convenience method that automatically selects all distinct columns from the specified table with caching enabled.
2291
+ *
2292
+ * @template T - The type of the table
2293
+ * @param table - The table to select from
2294
+ * @param cacheTTL - Optional cache TTL override (defaults to global cache TTL)
2295
+ * @returns Select distinct query builder with all table columns, field aliasing, and caching support
2296
+ * @example
2297
+ * ```typescript
2298
+ * const uniqueUsers = await forgeSQL.selectDistinctCacheableFrom(userTable, 300).where(eq(userTable.status, 'active'));
2299
+ * ```
2300
+ */
2301
+ selectDistinctCacheableFrom(table2, cacheTTL) {
2302
+ return this.ormInstance.getDrizzleQueryBuilder().selectDistinctFromCacheable(table2, cacheTTL);
2303
+ }
2007
2304
  executeWithCacheContext(cacheContext) {
2008
2305
  return this.ormInstance.executeWithCacheContext(cacheContext);
2009
2306
  }
@@ -2013,7 +2310,7 @@ class ForgeSQLORM {
2013
2310
  /**
2014
2311
  * Executes operations within a local cache context.
2015
2312
  * This provides in-memory caching for select queries within a single request scope.
2016
- *
2313
+ *
2017
2314
  * @param cacheContext - Function containing operations that will benefit from local caching
2018
2315
  * @returns Promise that resolves when all operations are complete
2019
2316
  */
@@ -2023,7 +2320,7 @@ class ForgeSQLORM {
2023
2320
  /**
2024
2321
  * Executes operations within a local cache context and returns a value.
2025
2322
  * This provides in-memory caching for select queries within a single request scope.
2026
- *
2323
+ *
2027
2324
  * @param cacheContext - Function containing operations that will benefit from local caching
2028
2325
  * @returns Promise that resolves to the return value of the cacheContext function
2029
2326
  */
@@ -2176,6 +2473,85 @@ class ForgeSQLORM {
2176
2473
  getDrizzleQueryBuilder() {
2177
2474
  return this.ormInstance.getDrizzleQueryBuilder();
2178
2475
  }
2476
+ /**
2477
+ * Executes a raw SQL query with local cache support.
2478
+ * This method provides local caching for raw SQL queries within the current invocation context.
2479
+ * Results are cached locally and will be returned from cache on subsequent identical queries.
2480
+ *
2481
+ * @param query - The SQL query to execute (SQLWrapper or string)
2482
+ * @returns Promise with query results
2483
+ * @example
2484
+ * ```typescript
2485
+ * // Using SQLWrapper
2486
+ * const result = await forgeSQL.execute(sql`SELECT * FROM users WHERE id = ${userId}`);
2487
+ *
2488
+ * // Using string
2489
+ * const result = await forgeSQL.execute("SELECT * FROM users WHERE status = 'active'");
2490
+ * ```
2491
+ */
2492
+ execute(query) {
2493
+ return this.ormInstance.getDrizzleQueryBuilder().executeQuery(query);
2494
+ }
2495
+ /**
2496
+ * Executes a raw SQL query with both local and global cache support.
2497
+ * This method provides comprehensive caching for raw SQL queries:
2498
+ * - Local cache: Within the current invocation context
2499
+ * - Global cache: Cross-invocation caching using @forge/kvs
2500
+ *
2501
+ * @param query - The SQL query to execute (SQLWrapper or string)
2502
+ * @param cacheTtl - Optional cache TTL override (defaults to global cache TTL)
2503
+ * @returns Promise with query results
2504
+ * @example
2505
+ * ```typescript
2506
+ * // Using SQLWrapper with custom TTL
2507
+ * const result = await forgeSQL.executeCacheable(sql`SELECT * FROM users WHERE id = ${userId}`, 300);
2508
+ *
2509
+ * // Using string with default TTL
2510
+ * const result = await forgeSQL.executeCacheable("SELECT * FROM users WHERE status = 'active'");
2511
+ * ```
2512
+ */
2513
+ executeCacheable(query, cacheTtl) {
2514
+ return this.ormInstance.getDrizzleQueryBuilder().executeQueryCacheable(query, cacheTtl);
2515
+ }
2516
+ /**
2517
+ * Creates a Common Table Expression (CTE) builder for complex queries.
2518
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2519
+ *
2520
+ * @returns WithBuilder for creating CTEs
2521
+ * @example
2522
+ * ```typescript
2523
+ * const withQuery = forgeSQL.$with('userStats').as(
2524
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2525
+ * .from(users)
2526
+ * .groupBy(users.id)
2527
+ * );
2528
+ * ```
2529
+ */
2530
+ get $with() {
2531
+ return this.ormInstance.getDrizzleQueryBuilder().$with;
2532
+ }
2533
+ /**
2534
+ * Creates a query builder that uses Common Table Expressions (CTEs).
2535
+ * CTEs allow you to define temporary named result sets that exist within the scope of a single query.
2536
+ *
2537
+ * @param queries - Array of CTE queries created with $with()
2538
+ * @returns Query builder with CTE support
2539
+ * @example
2540
+ * ```typescript
2541
+ * const withQuery = forgeSQL.$with('userStats').as(
2542
+ * forgeSQL.select({ userId: users.id, count: sql<number>`count(*)` })
2543
+ * .from(users)
2544
+ * .groupBy(users.id)
2545
+ * );
2546
+ *
2547
+ * const result = await forgeSQL.with(withQuery)
2548
+ * .select({ userId: withQuery.userId, count: withQuery.count })
2549
+ * .from(withQuery);
2550
+ * ```
2551
+ */
2552
+ with(...queries) {
2553
+ return this.ormInstance.getDrizzleQueryBuilder().with(...queries);
2554
+ }
2179
2555
  }
2180
2556
  const forgeDateTimeString = mysqlCore.customType({
2181
2557
  dataType() {