forge-sql-orm 2.1.22 → 2.1.24

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.
Files changed (44) hide show
  1. package/README.md +6 -2
  2. package/dist/core/ForgeSQLAnalyseOperations.d.ts +4 -0
  3. package/dist/core/ForgeSQLAnalyseOperations.d.ts.map +1 -1
  4. package/dist/core/ForgeSQLAnalyseOperations.js +17 -21
  5. package/dist/core/ForgeSQLAnalyseOperations.js.map +1 -1
  6. package/dist/core/ForgeSQLCrudOperations.d.ts +16 -0
  7. package/dist/core/ForgeSQLCrudOperations.d.ts.map +1 -1
  8. package/dist/core/ForgeSQLCrudOperations.js +60 -28
  9. package/dist/core/ForgeSQLCrudOperations.js.map +1 -1
  10. package/dist/core/ForgeSQLQueryBuilder.d.ts +15 -28
  11. package/dist/core/ForgeSQLQueryBuilder.d.ts.map +1 -1
  12. package/dist/core/ForgeSQLQueryBuilder.js +20 -47
  13. package/dist/core/ForgeSQLQueryBuilder.js.map +1 -1
  14. package/dist/core/Rovo.d.ts +32 -0
  15. package/dist/core/Rovo.d.ts.map +1 -1
  16. package/dist/core/Rovo.js +116 -67
  17. package/dist/core/Rovo.js.map +1 -1
  18. package/dist/lib/drizzle/extensions/additionalActions.d.ts.map +1 -1
  19. package/dist/lib/drizzle/extensions/additionalActions.js +168 -118
  20. package/dist/lib/drizzle/extensions/additionalActions.js.map +1 -1
  21. package/dist/utils/cacheTableUtils.d.ts +0 -8
  22. package/dist/utils/cacheTableUtils.d.ts.map +1 -1
  23. package/dist/utils/cacheTableUtils.js +183 -126
  24. package/dist/utils/cacheTableUtils.js.map +1 -1
  25. package/dist/utils/forgeDriverProxy.d.ts.map +1 -1
  26. package/dist/utils/forgeDriverProxy.js +31 -20
  27. package/dist/utils/forgeDriverProxy.js.map +1 -1
  28. package/dist/utils/sqlHints.d.ts.map +1 -1
  29. package/dist/utils/sqlHints.js +19 -29
  30. package/dist/utils/sqlHints.js.map +1 -1
  31. package/dist/utils/sqlUtils.d.ts +0 -29
  32. package/dist/utils/sqlUtils.d.ts.map +1 -1
  33. package/dist/utils/sqlUtils.js +107 -78
  34. package/dist/utils/sqlUtils.js.map +1 -1
  35. package/package.json +13 -13
  36. package/src/core/ForgeSQLAnalyseOperations.ts +18 -21
  37. package/src/core/ForgeSQLCrudOperations.ts +83 -33
  38. package/src/core/ForgeSQLQueryBuilder.ts +59 -154
  39. package/src/core/Rovo.ts +158 -98
  40. package/src/lib/drizzle/extensions/additionalActions.ts +287 -382
  41. package/src/utils/cacheTableUtils.ts +202 -144
  42. package/src/utils/forgeDriverProxy.ts +39 -21
  43. package/src/utils/sqlHints.ts +21 -26
  44. package/src/utils/sqlUtils.ts +151 -101
@@ -1,3 +1,4 @@
1
+ // qlty-ignore: +qlty:file-complexity
1
2
  import {
2
3
  MySqlRawQueryResult,
3
4
  MySqlRemoteDatabase,
@@ -6,7 +7,12 @@ import {
6
7
  } from "drizzle-orm/mysql-proxy";
7
8
 
8
9
  import { SelectedFields } from "drizzle-orm/mysql-core/query-builders/select.types";
9
- import { applyFromDriverTransform, ForgeSqlOrmOptions, mapSelectFieldsWithAlias } from "../../..";
10
+ import {
11
+ applyFromDriverTransform,
12
+ ForgeSqlOrmOptions,
13
+ mapSelectFieldsWithAlias,
14
+ SelectFromReturnType,
15
+ } from "../../..";
10
16
  import { MySqlSelectBase, MySqlSelectBuilder } from "drizzle-orm/mysql-core";
11
17
  import { MySqlTable } from "drizzle-orm/mysql-core/table";
12
18
  import {
@@ -308,25 +314,26 @@ async function handleSuccessfulExecution(
308
314
  }
309
315
  }
310
316
 
317
+ /**
318
+ * Configuration for function call handling.
319
+ */
320
+ interface FunctionCallConfig {
321
+ value: Function;
322
+ target: any;
323
+ args: any[];
324
+ table: MySqlTable;
325
+ options: ForgeSqlOrmOptions;
326
+ isCached: boolean;
327
+ }
328
+
311
329
  /**
312
330
  * Handles function calls on the wrapped builder.
313
331
  *
314
- * @param value - The function to call
315
- * @param target - The target object
316
- * @param args - Function arguments
317
- * @param table - The table being modified
318
- * @param options - ForgeSQL ORM options
319
- * @param isCached - Whether to clear cache immediately
332
+ * @param config - Configuration for function call handling
320
333
  * @returns Function result or wrapped builder
321
334
  */
322
- function handleFunctionCall(
323
- value: Function,
324
- target: any,
325
- args: any[],
326
- table: MySqlTable,
327
- options: ForgeSqlOrmOptions,
328
- isCached: boolean,
329
- ): any {
335
+ function handleFunctionCall(config: FunctionCallConfig): any {
336
+ const { value, target, args, table, options, isCached } = config;
330
337
  const result = value.apply(target, args);
331
338
  if (typeof result === "object" && result !== null && "execute" in result) {
332
339
  return wrapCacheEvictBuilder(result as QueryBuilder, table, options, isCached);
@@ -367,7 +374,14 @@ const wrapCacheEvictBuilder = <TTable extends MySqlTable>(
367
374
 
368
375
  if (typeof value === "function") {
369
376
  return (...args: any[]) =>
370
- handleFunctionCall(value, target, args, table, options, isCached);
377
+ handleFunctionCall({
378
+ value,
379
+ target,
380
+ args,
381
+ table,
382
+ options,
383
+ isCached,
384
+ });
371
385
  }
372
386
 
373
387
  return value;
@@ -375,6 +389,19 @@ const wrapCacheEvictBuilder = <TTable extends MySqlTable>(
375
389
  });
376
390
  };
377
391
 
392
+ /**
393
+ * Creates a query builder with cache eviction wrapper.
394
+ * Generic helper to reduce duplication between insert/update/delete builders.
395
+ */
396
+ function createCacheEvictBuilder<TTable extends MySqlTable, TBuilder>(
397
+ builder: QueryBuilder,
398
+ table: TTable,
399
+ options: ForgeSqlOrmOptions,
400
+ isCached: boolean,
401
+ ): TBuilder {
402
+ return wrapCacheEvictBuilder(builder, table, options, isCached) as unknown as TBuilder;
403
+ }
404
+
378
405
  /**
379
406
  * Creates an insert query builder that automatically evicts cache after execution.
380
407
  *
@@ -390,16 +417,10 @@ function insertAndEvictCacheBuilder<TTable extends MySqlTable>(
390
417
  isCached: boolean,
391
418
  ): MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
392
419
  const builder = db.insert(table);
393
- return wrapCacheEvictBuilder(
394
- builder as unknown as QueryBuilder,
395
- table,
396
- options,
397
- isCached,
398
- ) as unknown as MySqlInsertBuilder<
420
+ return createCacheEvictBuilder<
399
421
  TTable,
400
- MySqlRemoteQueryResultHKT,
401
- MySqlRemotePreparedQueryHKT
402
- >;
422
+ MySqlInsertBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT>
423
+ >(builder as unknown as QueryBuilder, table, options, isCached);
403
424
  }
404
425
 
405
426
  /**
@@ -417,16 +438,10 @@ function updateAndEvictCacheBuilder<TTable extends MySqlTable>(
417
438
  isCached: boolean,
418
439
  ): MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
419
440
  const builder = db.update(table);
420
- return wrapCacheEvictBuilder(
421
- builder as unknown as QueryBuilder,
422
- table,
423
- options,
424
- isCached,
425
- ) as unknown as MySqlUpdateBuilder<
441
+ return createCacheEvictBuilder<
426
442
  TTable,
427
- MySqlRemoteQueryResultHKT,
428
- MySqlRemotePreparedQueryHKT
429
- >;
443
+ MySqlUpdateBuilder<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT>
444
+ >(builder as unknown as QueryBuilder, table, options, isCached);
430
445
  }
431
446
 
432
447
  /**
@@ -444,35 +459,33 @@ function deleteAndEvictCacheBuilder<TTable extends MySqlTable>(
444
459
  isCached: boolean,
445
460
  ): MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT> {
446
461
  const builder = db.delete(table);
447
- return wrapCacheEvictBuilder(
448
- builder as unknown as QueryBuilder,
449
- table,
450
- options,
451
- isCached,
452
- ) as unknown as MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT>;
462
+ return createCacheEvictBuilder<
463
+ TTable,
464
+ MySqlDeleteBase<TTable, MySqlRemoteQueryResultHKT, MySqlRemotePreparedQueryHKT>
465
+ >(builder as unknown as QueryBuilder, table, options, isCached);
466
+ }
467
+
468
+ /**
469
+ * Configuration for cached query handling.
470
+ */
471
+ interface CachedQueryConfig {
472
+ target: any;
473
+ options: ForgeSqlOrmOptions;
474
+ cacheTtl: number;
475
+ selections: any;
476
+ aliasMap: any;
477
+ onfulfilled?: any;
478
+ onrejected?: any;
453
479
  }
454
480
 
455
481
  /**
456
482
  * Handles cached query execution with proper error handling.
457
483
  *
458
- * @param target - The query target
459
- * @param options - ForgeSQL ORM options
460
- * @param cacheTtl - Cache TTL
461
- * @param selections - Field selections
462
- * @param aliasMap - Field alias mapping
463
- * @param onfulfilled - Success callback
464
- * @param onrejected - Error callback
484
+ * @param config - Configuration for cached query handling
465
485
  * @returns Promise with cached result
466
486
  */
467
- async function handleCachedQuery(
468
- target: any,
469
- options: ForgeSqlOrmOptions,
470
- cacheTtl: number,
471
- selections: any,
472
- aliasMap: any,
473
- onfulfilled?: any,
474
- onrejected?: any,
475
- ): Promise<any> {
487
+ async function handleCachedQuery(config: CachedQueryConfig): Promise<any> {
488
+ const { target, options, cacheTtl, selections, aliasMap, onfulfilled, onrejected } = config;
476
489
  try {
477
490
  const localCached = await getQueryLocalCacheQuery(target, options);
478
491
  if (localCached) {
@@ -500,25 +513,26 @@ async function handleCachedQuery(
500
513
  }
501
514
  }
502
515
 
516
+ /**
517
+ * Configuration for non-cached query handling.
518
+ */
519
+ interface NonCachedQueryConfig {
520
+ target: any;
521
+ options: any;
522
+ selections: any;
523
+ aliasMap: any;
524
+ onfulfilled?: any;
525
+ onrejected?: any;
526
+ }
527
+
503
528
  /**
504
529
  * Handles non-cached query execution.
505
530
  *
506
- * @param target - The query target
507
- * @param options - ForgeSQL ORM options
508
- * @param selections - Field selections
509
- * @param aliasMap - Field alias mapping
510
- * @param onfulfilled - Success callback
511
- * @param onrejected - Error callback
531
+ * @param config - Configuration for non-cached query handling
512
532
  * @returns Promise with transformed result
513
533
  */
514
- async function handleNonCachedQuery(
515
- target: any,
516
- options: any,
517
- selections: any,
518
- aliasMap: any,
519
- onfulfilled?: any,
520
- onrejected?: any,
521
- ): Promise<any> {
534
+ async function handleNonCachedQuery(config: NonCachedQueryConfig): Promise<any> {
535
+ const { target, options, selections, aliasMap, onfulfilled, onrejected } = config;
522
536
  try {
523
537
  const localCached = await getQueryLocalCacheQuery(target, options);
524
538
  if (localCached) {
@@ -577,7 +591,15 @@ function createCachedThenHandler(
577
591
  ): (onfulfilled?: any, onrejected?: any) => Promise<any> {
578
592
  return (onfulfilled?: any, onrejected?: any) => {
579
593
  const ttl = cacheTtl ?? options.cacheTTL ?? 120;
580
- return handleCachedQuery(target, options, ttl, selections, aliasMap, onfulfilled, onrejected);
594
+ return handleCachedQuery({
595
+ target,
596
+ options,
597
+ cacheTtl: ttl,
598
+ selections,
599
+ aliasMap,
600
+ onfulfilled,
601
+ onrejected,
602
+ });
581
603
  };
582
604
  }
583
605
 
@@ -591,7 +613,14 @@ function createNonCachedThenHandler(
591
613
  aliasMap: any,
592
614
  ): (onfulfilled?: any, onrejected?: any) => Promise<any> {
593
615
  return (onfulfilled?: any, onrejected?: any) => {
594
- return handleNonCachedQuery(target, options, selections, aliasMap, onfulfilled, onrejected);
616
+ return handleNonCachedQuery({
617
+ target,
618
+ options,
619
+ selections,
620
+ aliasMap,
621
+ onfulfilled,
622
+ onrejected,
623
+ });
595
624
  };
596
625
  }
597
626
 
@@ -637,47 +666,83 @@ function createFunctionCallHandler(
637
666
  * @param cacheTtl - Optional cache TTL override
638
667
  * @returns Select query builder with aliasing and optional caching
639
668
  */
669
+ /**
670
+ * Configuration for aliased select proxy handler.
671
+ */
672
+ interface AliasedSelectProxyConfig {
673
+ selections: any;
674
+ aliasMap: any;
675
+ useCache: boolean;
676
+ options: ForgeSqlOrmOptions;
677
+ cacheTtl: number | undefined;
678
+ wrapBuilder: (rawBuilder: any) => any;
679
+ }
680
+
681
+ /**
682
+ * Creates a Proxy handler for aliased select builders.
683
+ */
684
+ function createAliasedSelectProxyHandler(config: AliasedSelectProxyConfig) {
685
+ const { selections, aliasMap, useCache, options, cacheTtl, wrapBuilder } = config;
686
+ return {
687
+ get(target: any, prop: string | symbol, receiver: any) {
688
+ // Handle 'then' separately to avoid thenable object issues
689
+ if (prop === "then") {
690
+ return useCache
691
+ ? createCachedThenHandler(target, options, cacheTtl, selections, aliasMap)
692
+ : createNonCachedThenHandler(target, options, selections, aliasMap);
693
+ }
694
+
695
+ // Handle other special properties with a map
696
+ const specialHandlers: Record<string | symbol, () => any> = {
697
+ execute: () => createExecuteHandler(target, selections, aliasMap),
698
+ catch: () => createCatchHandler(receiver),
699
+ finally: () => createFinallyHandler(receiver),
700
+ };
701
+
702
+ if (prop in specialHandlers) {
703
+ return specialHandlers[prop]();
704
+ }
705
+
706
+ const value = Reflect.get(target, prop, receiver);
707
+
708
+ if (typeof value === "function") {
709
+ return createFunctionCallHandler(value, target, wrapBuilder);
710
+ }
711
+
712
+ return value;
713
+ },
714
+ };
715
+ }
716
+
717
+ /**
718
+ * Configuration for creating aliased select builder.
719
+ */
720
+ interface AliasedSelectBuilderConfig<TSelection extends SelectedFields> {
721
+ db: MySqlRemoteDatabase<any>;
722
+ fields: TSelection;
723
+ selectFn: (selections: any) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>;
724
+ useCache: boolean;
725
+ options: ForgeSqlOrmOptions;
726
+ cacheTtl?: number;
727
+ }
728
+
640
729
  function createAliasedSelectBuilder<TSelection extends SelectedFields>(
641
- db: MySqlRemoteDatabase<any>,
642
- fields: TSelection,
643
- selectFn: (selections: any) => MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT>,
644
- useCache: boolean,
645
- options: ForgeSqlOrmOptions,
646
- cacheTtl?: number,
730
+ config: AliasedSelectBuilderConfig<TSelection>,
647
731
  ): MySqlSelectBuilder<TSelection, MySqlRemotePreparedQueryHKT> {
732
+ const { fields, selectFn, useCache, options, cacheTtl } = config;
648
733
  const { selections, aliasMap } = mapSelectFieldsWithAlias(fields);
649
734
  const builder = selectFn(selections);
650
735
 
651
736
  const wrapBuilder = (rawBuilder: any): any => {
652
- return new Proxy(rawBuilder, {
653
- get(target, prop, receiver) {
654
- if (prop === "execute") {
655
- return createExecuteHandler(target, selections, aliasMap);
656
- }
657
-
658
- if (prop === "then") {
659
- return useCache
660
- ? createCachedThenHandler(target, options, cacheTtl, selections, aliasMap)
661
- : createNonCachedThenHandler(target, options, selections, aliasMap);
662
- }
663
-
664
- if (prop === "catch") {
665
- return createCatchHandler(receiver);
666
- }
667
-
668
- if (prop === "finally") {
669
- return createFinallyHandler(receiver);
670
- }
671
-
672
- const value = Reflect.get(target, prop, receiver);
673
-
674
- if (typeof value === "function") {
675
- return createFunctionCallHandler(value, target, wrapBuilder);
676
- }
677
-
678
- return value;
679
- },
737
+ const handler = createAliasedSelectProxyHandler({
738
+ selections,
739
+ aliasMap,
740
+ useCache,
741
+ options,
742
+ cacheTtl,
743
+ wrapBuilder,
680
744
  });
745
+ return new Proxy(rawBuilder, handler);
681
746
  };
682
747
 
683
748
  return wrapBuilder(builder);
@@ -763,55 +828,25 @@ function createRawQueryExecutor(
763
828
  }
764
829
 
765
830
  // ============================================================================
766
- // MAIN PATCH FUNCTION
831
+ // HELPER FUNCTIONS FOR PATCHING
767
832
  // ============================================================================
768
833
 
769
834
  /**
770
- * Patches a Drizzle database instance with additional methods for aliased selects and cache management.
771
- *
772
- * This function extends the database instance with:
773
- * - selectAliased: Select with field aliasing support
774
- * - selectAliasedDistinct: Select distinct with field aliasing support
775
- * - selectAliasedCacheable: Select with field aliasing and caching
776
- * - selectAliasedDistinctCacheable: Select distinct with field aliasing and caching
777
- * - insertAndEvictCache: Insert operations that automatically evict cache
778
- * - updateAndEvictCache: Update operations that automatically evict cache
779
- * - deleteAndEvictCache: Delete operations that automatically evict cache
780
- *
781
- * @param db - The Drizzle database instance to patch
782
- * @param options - Optional ForgeSQL ORM configuration
783
- * @returns The patched database instance with additional methods
835
+ * Sets up select methods with field aliasing.
784
836
  */
785
- export function patchDbWithSelectAliased(
837
+ function setupSelectAliasedMethods(
786
838
  db: MySqlRemoteDatabase<any>,
787
- options?: ForgeSqlOrmOptions,
788
- ): MySqlRemoteDatabase<any> & {
789
- selectAliased: SelectAliasedType;
790
- selectAliasedDistinct: SelectAliasedDistinctType;
791
- selectAliasedCacheable: SelectAliasedCacheableType;
792
- selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
793
- insertWithCacheContext: InsertAndEvictCacheType;
794
- insertAndEvictCache: InsertAndEvictCacheType;
795
- updateAndEvictCache: UpdateAndEvictCacheType;
796
- updateWithCacheContext: UpdateAndEvictCacheType;
797
- deleteAndEvictCache: DeleteAndEvictCacheType;
798
- deleteWithCacheContext: DeleteAndEvictCacheType;
799
- } {
800
- const newOptions = { ...DEFAULT_OPTIONS, ...options };
801
-
802
- // ============================================================================
803
- // SELECT METHODS WITH FIELD ALIASING
804
- // ============================================================================
805
-
839
+ newOptions: ForgeSqlOrmOptions,
840
+ ): void {
806
841
  // Select aliased without cache
807
842
  db.selectAliased = function <TSelection extends SelectedFields>(fields: TSelection) {
808
- return createAliasedSelectBuilder(
843
+ return createAliasedSelectBuilder({
809
844
  db,
810
845
  fields,
811
- (selections) => db.select(selections),
812
- false,
813
- newOptions,
814
- );
846
+ selectFn: (selections) => db.select(selections),
847
+ useCache: false,
848
+ options: newOptions,
849
+ });
815
850
  };
816
851
 
817
852
  // Select aliased with cache
@@ -819,25 +854,25 @@ export function patchDbWithSelectAliased(
819
854
  fields: TSelection,
820
855
  cacheTtl?: number,
821
856
  ) {
822
- return createAliasedSelectBuilder(
857
+ return createAliasedSelectBuilder({
823
858
  db,
824
859
  fields,
825
- (selections) => db.select(selections),
826
- true,
827
- newOptions,
860
+ selectFn: (selections) => db.select(selections),
861
+ useCache: true,
862
+ options: newOptions,
828
863
  cacheTtl,
829
- );
864
+ });
830
865
  };
831
866
 
832
867
  // Select aliased distinct without cache
833
868
  db.selectAliasedDistinct = function <TSelection extends SelectedFields>(fields: TSelection) {
834
- return createAliasedSelectBuilder(
869
+ return createAliasedSelectBuilder({
835
870
  db,
836
871
  fields,
837
- (selections) => db.selectDistinct(selections),
838
- false,
839
- newOptions,
840
- );
872
+ selectFn: (selections) => db.selectDistinct(selections),
873
+ useCache: false,
874
+ options: newOptions,
875
+ });
841
876
  };
842
877
 
843
878
  // Select aliased distinct with cache
@@ -845,20 +880,21 @@ export function patchDbWithSelectAliased(
845
880
  fields: TSelection,
846
881
  cacheTtl?: number,
847
882
  ) {
848
- return createAliasedSelectBuilder(
883
+ return createAliasedSelectBuilder({
849
884
  db,
850
885
  fields,
851
- (selections) => db.selectDistinct(selections),
852
- true,
853
- newOptions,
886
+ selectFn: (selections) => db.selectDistinct(selections),
887
+ useCache: true,
888
+ options: newOptions,
854
889
  cacheTtl,
855
- );
890
+ });
856
891
  };
892
+ }
857
893
 
858
- // ============================================================================
859
- // TABLE-BASED SELECT METHODS
860
- // ============================================================================
861
-
894
+ /**
895
+ * Sets up table-based select methods.
896
+ */
897
+ function setupTableBasedSelectMethods(db: MySqlRemoteDatabase<any>): void {
862
898
  /**
863
899
  * Creates a select query builder for all columns from a table with field aliasing support.
864
900
  * This is a convenience method that automatically selects all columns from the specified table.
@@ -870,52 +906,10 @@ export function patchDbWithSelectAliased(
870
906
  * const users = await db.selectFrom(userTable).where(eq(userTable.id, 1));
871
907
  * ```
872
908
  */
873
- db.selectFrom = function <T extends MySqlTable>(
874
- table: T,
875
- ): MySqlSelectBase<
876
- GetSelectTableName<T>,
877
- GetSelectTableSelection<T>,
878
- "single",
879
- MySqlRemotePreparedQueryHKT,
880
- GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
881
- false,
882
- never,
883
- {
884
- [K in keyof {
885
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
886
- GetSelectTableSelection<T>[Key]
887
- >;
888
- }]: {
889
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
890
- GetSelectTableSelection<T>[Key]
891
- >;
892
- }[K];
893
- }[],
894
- any
895
- > {
896
- return db.selectAliased(getTableColumns(table)).from(table) as unknown as MySqlSelectBase<
897
- GetSelectTableName<T>,
898
- GetSelectTableSelection<T>,
899
- "single",
900
- MySqlRemotePreparedQueryHKT,
901
- GetSelectTableName<T> extends string
902
- ? Record<string & GetSelectTableName<T>, "not-null">
903
- : {},
904
- false,
905
- never,
906
- {
907
- [K in keyof {
908
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
909
- GetSelectTableSelection<T>[Key]
910
- >;
911
- }]: {
912
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
913
- GetSelectTableSelection<T>[Key]
914
- >;
915
- }[K];
916
- }[],
917
- any
918
- >;
909
+ db.selectFrom = function <T extends MySqlTable>(table: T): SelectFromReturnType<T> {
910
+ return db
911
+ .selectAliased(getTableColumns(table))
912
+ .from(table) as unknown as SelectFromReturnType<T>;
919
913
  };
920
914
 
921
915
  /**
@@ -933,52 +927,10 @@ export function patchDbWithSelectAliased(
933
927
  db.selectFromCacheable = function <T extends MySqlTable>(
934
928
  table: T,
935
929
  cacheTtl?: number,
936
- ): MySqlSelectBase<
937
- GetSelectTableName<T>,
938
- GetSelectTableSelection<T>,
939
- "single",
940
- MySqlRemotePreparedQueryHKT,
941
- GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
942
- false,
943
- never,
944
- {
945
- [K in keyof {
946
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
947
- GetSelectTableSelection<T>[Key]
948
- >;
949
- }]: {
950
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
951
- GetSelectTableSelection<T>[Key]
952
- >;
953
- }[K];
954
- }[],
955
- any
956
- > {
930
+ ): SelectFromReturnType<T> {
957
931
  return db
958
932
  .selectAliasedCacheable(getTableColumns(table), cacheTtl)
959
- .from(table) as unknown as MySqlSelectBase<
960
- GetSelectTableName<T>,
961
- GetSelectTableSelection<T>,
962
- "single",
963
- MySqlRemotePreparedQueryHKT,
964
- GetSelectTableName<T> extends string
965
- ? Record<string & GetSelectTableName<T>, "not-null">
966
- : {},
967
- false,
968
- never,
969
- {
970
- [K in keyof {
971
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
972
- GetSelectTableSelection<T>[Key]
973
- >;
974
- }]: {
975
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
976
- GetSelectTableSelection<T>[Key]
977
- >;
978
- }[K];
979
- }[],
980
- any
981
- >;
933
+ .from(table) as unknown as SelectFromReturnType<T>;
982
934
  };
983
935
 
984
936
  /**
@@ -992,54 +944,10 @@ export function patchDbWithSelectAliased(
992
944
  * const uniqueUsers = await db.selectDistinctFrom(userTable).where(eq(userTable.status, 'active'));
993
945
  * ```
994
946
  */
995
- db.selectDistinctFrom = function <T extends MySqlTable>(
996
- table: T,
997
- ): MySqlSelectBase<
998
- GetSelectTableName<T>,
999
- GetSelectTableSelection<T>,
1000
- "single",
1001
- MySqlRemotePreparedQueryHKT,
1002
- GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
1003
- false,
1004
- never,
1005
- {
1006
- [K in keyof {
1007
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1008
- GetSelectTableSelection<T>[Key]
1009
- >;
1010
- }]: {
1011
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1012
- GetSelectTableSelection<T>[Key]
1013
- >;
1014
- }[K];
1015
- }[],
1016
- any
1017
- > {
947
+ db.selectDistinctFrom = function <T extends MySqlTable>(table: T): SelectFromReturnType<T> {
1018
948
  return db
1019
949
  .selectAliasedDistinct(getTableColumns(table))
1020
- .from(table) as unknown as MySqlSelectBase<
1021
- GetSelectTableName<T>,
1022
- GetSelectTableSelection<T>,
1023
- "single",
1024
- MySqlRemotePreparedQueryHKT,
1025
- GetSelectTableName<T> extends string
1026
- ? Record<string & GetSelectTableName<T>, "not-null">
1027
- : {},
1028
- false,
1029
- never,
1030
- {
1031
- [K in keyof {
1032
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1033
- GetSelectTableSelection<T>[Key]
1034
- >;
1035
- }]: {
1036
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1037
- GetSelectTableSelection<T>[Key]
1038
- >;
1039
- }[K];
1040
- }[],
1041
- any
1042
- >;
950
+ .from(table) as unknown as SelectFromReturnType<T>;
1043
951
  };
1044
952
 
1045
953
  /**
@@ -1057,92 +965,46 @@ export function patchDbWithSelectAliased(
1057
965
  db.selectDistinctFromCacheable = function <T extends MySqlTable>(
1058
966
  table: T,
1059
967
  cacheTtl?: number,
1060
- ): MySqlSelectBase<
1061
- GetSelectTableName<T>,
1062
- GetSelectTableSelection<T>,
1063
- "single",
1064
- MySqlRemotePreparedQueryHKT,
1065
- GetSelectTableName<T> extends string ? Record<string & GetSelectTableName<T>, "not-null"> : {},
1066
- false,
1067
- never,
1068
- {
1069
- [K in keyof {
1070
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1071
- GetSelectTableSelection<T>[Key]
1072
- >;
1073
- }]: {
1074
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1075
- GetSelectTableSelection<T>[Key]
1076
- >;
1077
- }[K];
1078
- }[],
1079
- any
1080
- > {
968
+ ): SelectFromReturnType<T> {
1081
969
  return db
1082
970
  .selectAliasedDistinctCacheable(getTableColumns(table), cacheTtl)
1083
- .from(table) as unknown as MySqlSelectBase<
1084
- GetSelectTableName<T>,
1085
- GetSelectTableSelection<T>,
1086
- "single",
1087
- MySqlRemotePreparedQueryHKT,
1088
- GetSelectTableName<T> extends string
1089
- ? Record<string & GetSelectTableName<T>, "not-null">
1090
- : {},
1091
- false,
1092
- never,
1093
- {
1094
- [K in keyof {
1095
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1096
- GetSelectTableSelection<T>[Key]
1097
- >;
1098
- }]: {
1099
- [Key in keyof GetSelectTableSelection<T>]: SelectResultField<
1100
- GetSelectTableSelection<T>[Key]
1101
- >;
1102
- }[K];
1103
- }[],
1104
- any
1105
- >;
1106
- };
1107
-
1108
- // ============================================================================
1109
- // CACHE-AWARE MODIFY OPERATIONS
1110
- // ============================================================================
1111
-
1112
- // Insert with cache context support (participates in cache clearing when used within cache context)
1113
- db.insertWithCacheContext = function <TTable extends MySqlTable>(table: TTable) {
1114
- return insertAndEvictCacheBuilder(db, table, newOptions, false);
1115
- };
1116
-
1117
- // Insert with cache eviction
1118
- db.insertAndEvictCache = function <TTable extends MySqlTable>(table: TTable) {
1119
- return insertAndEvictCacheBuilder(db, table, newOptions, true);
1120
- };
1121
-
1122
- // Update with cache context support (participates in cache clearing when used within cache context)
1123
- db.updateWithCacheContext = function <TTable extends MySqlTable>(table: TTable) {
1124
- return updateAndEvictCacheBuilder(db, table, newOptions, false);
1125
- };
1126
-
1127
- // Update with cache eviction
1128
- db.updateAndEvictCache = function <TTable extends MySqlTable>(table: TTable) {
1129
- return updateAndEvictCacheBuilder(db, table, newOptions, true);
1130
- };
1131
-
1132
- // Delete with cache context support (participates in cache clearing when used within cache context)
1133
- db.deleteWithCacheContext = function <TTable extends MySqlTable>(table: TTable) {
1134
- return deleteAndEvictCacheBuilder(db, table, newOptions, false);
1135
- };
1136
-
1137
- // Delete with cache eviction
1138
- db.deleteAndEvictCache = function <TTable extends MySqlTable>(table: TTable) {
1139
- return deleteAndEvictCacheBuilder(db, table, newOptions, true);
971
+ .from(table) as unknown as SelectFromReturnType<T>;
1140
972
  };
973
+ }
1141
974
 
1142
- // ============================================================================
1143
- // RAW SQL QUERY EXECUTORS
1144
- // ============================================================================
975
+ /**
976
+ * Sets up cache-aware modify operations.
977
+ */
978
+ function setupCacheAwareModifyMethods(
979
+ db: MySqlRemoteDatabase<any>,
980
+ newOptions: ForgeSqlOrmOptions,
981
+ ): void {
982
+ // Insert operations
983
+ db.insertWithCacheContext = <TTable extends MySqlTable>(table: TTable) =>
984
+ insertAndEvictCacheBuilder(db, table, newOptions, false);
985
+ db.insertAndEvictCache = <TTable extends MySqlTable>(table: TTable) =>
986
+ insertAndEvictCacheBuilder(db, table, newOptions, true);
987
+
988
+ // Update operations
989
+ db.updateWithCacheContext = <TTable extends MySqlTable>(table: TTable) =>
990
+ updateAndEvictCacheBuilder(db, table, newOptions, false);
991
+ db.updateAndEvictCache = <TTable extends MySqlTable>(table: TTable) =>
992
+ updateAndEvictCacheBuilder(db, table, newOptions, true);
993
+
994
+ // Delete operations
995
+ db.deleteWithCacheContext = <TTable extends MySqlTable>(table: TTable) =>
996
+ deleteAndEvictCacheBuilder(db, table, newOptions, false);
997
+ db.deleteAndEvictCache = <TTable extends MySqlTable>(table: TTable) =>
998
+ deleteAndEvictCacheBuilder(db, table, newOptions, true);
999
+ }
1145
1000
 
1001
+ /**
1002
+ * Sets up raw SQL query executors.
1003
+ */
1004
+ function setupRawQueryExecutors(
1005
+ db: MySqlRemoteDatabase<any>,
1006
+ newOptions: ForgeSqlOrmOptions,
1007
+ ): void {
1146
1008
  /**
1147
1009
  * Executes a raw SQL query with local cache support.
1148
1010
  * This method provides local caching for raw SQL queries within the current invocation context.
@@ -1180,6 +1042,49 @@ export function patchDbWithSelectAliased(
1180
1042
  * ```
1181
1043
  */
1182
1044
  db.executeQueryCacheable = createRawQueryExecutor(db, newOptions, true);
1045
+ }
1046
+
1047
+ // ============================================================================
1048
+ // MAIN PATCH FUNCTION
1049
+ // ============================================================================
1050
+
1051
+ /**
1052
+ * Patches a Drizzle database instance with additional methods for aliased selects and cache management.
1053
+ *
1054
+ * This function extends the database instance with:
1055
+ * - selectAliased: Select with field aliasing support
1056
+ * - selectAliasedDistinct: Select distinct with field aliasing support
1057
+ * - selectAliasedCacheable: Select with field aliasing and caching
1058
+ * - selectAliasedDistinctCacheable: Select distinct with field aliasing and caching
1059
+ * - insertAndEvictCache: Insert operations that automatically evict cache
1060
+ * - updateAndEvictCache: Update operations that automatically evict cache
1061
+ * - deleteAndEvictCache: Delete operations that automatically evict cache
1062
+ *
1063
+ * @param db - The Drizzle database instance to patch
1064
+ * @param options - Optional ForgeSQL ORM configuration
1065
+ * @returns The patched database instance with additional methods
1066
+ */
1067
+ export function patchDbWithSelectAliased(
1068
+ db: MySqlRemoteDatabase<any>,
1069
+ options?: ForgeSqlOrmOptions,
1070
+ ): MySqlRemoteDatabase<any> & {
1071
+ selectAliased: SelectAliasedType;
1072
+ selectAliasedDistinct: SelectAliasedDistinctType;
1073
+ selectAliasedCacheable: SelectAliasedCacheableType;
1074
+ selectAliasedDistinctCacheable: SelectAliasedDistinctCacheableType;
1075
+ insertWithCacheContext: InsertAndEvictCacheType;
1076
+ insertAndEvictCache: InsertAndEvictCacheType;
1077
+ updateAndEvictCache: UpdateAndEvictCacheType;
1078
+ updateWithCacheContext: UpdateAndEvictCacheType;
1079
+ deleteAndEvictCache: DeleteAndEvictCacheType;
1080
+ deleteWithCacheContext: DeleteAndEvictCacheType;
1081
+ } {
1082
+ const newOptions = { ...DEFAULT_OPTIONS, ...options };
1083
+
1084
+ setupSelectAliasedMethods(db, newOptions);
1085
+ setupTableBasedSelectMethods(db);
1086
+ setupCacheAwareModifyMethods(db, newOptions);
1087
+ setupRawQueryExecutors(db, newOptions);
1183
1088
 
1184
1089
  return db;
1185
1090
  }