@simplysm/orm-common 13.0.83 → 13.0.84

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 (73) hide show
  1. package/dist/ddl/initialize.d.ts +2 -2
  2. package/dist/ddl/initialize.js +1 -1
  3. package/dist/ddl/initialize.js.map +1 -1
  4. package/dist/ddl/table-ddl.d.ts +1 -1
  5. package/dist/exec/queryable.d.ts +115 -115
  6. package/dist/exec/queryable.js +68 -68
  7. package/dist/exec/queryable.js.map +1 -1
  8. package/dist/expr/expr.d.ts +248 -248
  9. package/dist/expr/expr.js +250 -250
  10. package/dist/query-builder/base/expr-renderer-base.d.ts +7 -7
  11. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +3 -3
  12. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  13. package/dist/query-builder/mssql/mssql-expr-renderer.js +5 -5
  14. package/dist/query-builder/mssql/mssql-query-builder.d.ts +2 -2
  15. package/dist/query-builder/mssql/mssql-query-builder.d.ts.map +1 -1
  16. package/dist/query-builder/mssql/mssql-query-builder.js +7 -7
  17. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +2 -2
  18. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  19. package/dist/query-builder/mysql/mysql-expr-renderer.js +4 -4
  20. package/dist/query-builder/mysql/mysql-query-builder.d.ts +10 -10
  21. package/dist/query-builder/mysql/mysql-query-builder.d.ts.map +1 -1
  22. package/dist/query-builder/mysql/mysql-query-builder.js +4 -4
  23. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +2 -2
  24. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  25. package/dist/query-builder/postgresql/postgresql-expr-renderer.js +4 -4
  26. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts +8 -8
  27. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  28. package/dist/query-builder/postgresql/postgresql-query-builder.js +7 -7
  29. package/dist/query-builder/query-builder.d.ts +1 -1
  30. package/dist/schema/factory/column-builder.d.ts +46 -46
  31. package/dist/schema/factory/column-builder.js +25 -25
  32. package/dist/schema/factory/index-builder.d.ts +22 -22
  33. package/dist/schema/factory/index-builder.js +14 -14
  34. package/dist/schema/factory/relation-builder.d.ts +93 -93
  35. package/dist/schema/factory/relation-builder.d.ts.map +1 -1
  36. package/dist/schema/factory/relation-builder.js +37 -37
  37. package/dist/schema/procedure-builder.d.ts +38 -38
  38. package/dist/schema/procedure-builder.d.ts.map +1 -1
  39. package/dist/schema/procedure-builder.js +26 -26
  40. package/dist/schema/table-builder.d.ts +38 -38
  41. package/dist/schema/table-builder.d.ts.map +1 -1
  42. package/dist/schema/table-builder.js +29 -29
  43. package/dist/schema/view-builder.d.ts +26 -26
  44. package/dist/schema/view-builder.d.ts.map +1 -1
  45. package/dist/schema/view-builder.js +18 -18
  46. package/dist/types/db.d.ts +40 -40
  47. package/dist/types/expr.d.ts +75 -75
  48. package/dist/types/expr.d.ts.map +1 -1
  49. package/dist/types/query-def.d.ts +32 -32
  50. package/dist/types/query-def.d.ts.map +1 -1
  51. package/package.json +2 -2
  52. package/src/ddl/initialize.ts +16 -16
  53. package/src/ddl/table-ddl.ts +1 -1
  54. package/src/exec/queryable.ts +163 -163
  55. package/src/expr/expr.ts +257 -257
  56. package/src/query-builder/base/expr-renderer-base.ts +8 -8
  57. package/src/query-builder/mssql/mssql-expr-renderer.ts +20 -20
  58. package/src/query-builder/mssql/mssql-query-builder.ts +28 -28
  59. package/src/query-builder/mysql/mysql-expr-renderer.ts +22 -22
  60. package/src/query-builder/mysql/mysql-query-builder.ts +65 -65
  61. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +15 -15
  62. package/src/query-builder/postgresql/postgresql-query-builder.ts +43 -43
  63. package/src/query-builder/query-builder.ts +1 -1
  64. package/src/schema/factory/column-builder.ts +48 -48
  65. package/src/schema/factory/index-builder.ts +22 -22
  66. package/src/schema/factory/relation-builder.ts +95 -95
  67. package/src/schema/procedure-builder.ts +38 -38
  68. package/src/schema/table-builder.ts +38 -38
  69. package/src/schema/view-builder.ts +28 -28
  70. package/src/types/db.ts +41 -41
  71. package/src/types/expr.ts +79 -79
  72. package/src/types/query-def.ts +37 -37
  73. package/tests/ddl/basic.expected.ts +8 -8
@@ -407,13 +407,13 @@ export class Queryable<
407
407
  *
408
408
  * @param fn - function returning columns to sort by
409
409
  * @param orderBy - Sort direction (ASC/DESC). Default: ASC
410
- * @returns sorting 조건이 추가된 Queryable
410
+ * @returns Queryable with sorting conditions added
411
411
  *
412
412
  * @example
413
413
  * ```typescript
414
414
  * db.user
415
- * .orderBy((u) => u.name) // 이름 ASC
416
- * .orderBy((u) => u.age, "DESC") // 나이 DESC
415
+ * .orderBy((u) => u.name) // name ASC
416
+ * .orderBy((u) => u.age, "DESC") // age DESC
417
417
  * ```
418
418
  */
419
419
  orderBy(
@@ -438,13 +438,13 @@ export class Queryable<
438
438
 
439
439
  //#endregion
440
440
 
441
- //#region ========== 검색 - WHERE ==========
441
+ //#region ========== Search - WHERE ==========
442
442
 
443
443
  /**
444
- * WHERE condition 추가합니다. 여러 호출하면 AND로 결합됩니다.
444
+ * Add WHERE condition. Multiple calls are combined with AND.
445
445
  *
446
- * @param predicate - Condition 배열을 반환하는 function
447
- * @returns 조건이 추가된 Queryable
446
+ * @param predicate - Function returning an array of conditions
447
+ * @returns Queryable with conditions added
448
448
  *
449
449
  * @example
450
450
  * ```typescript
@@ -471,21 +471,21 @@ export class Queryable<
471
471
  }
472
472
 
473
473
  /**
474
- * 텍스트 검색을 수행
474
+ * Perform text search
475
475
  *
476
- * 검색 문법은 {@link parseSearchQuery} 참조
477
- * - 공백으로 구분된 단어는 OR condition
478
- * - `+`로 시작하는 단어는 required include (AND Condition)
479
- * - `-`로 시작하는 단어는 exclude (NOT Condition)
476
+ * See {@link parseSearchQuery} for search syntax
477
+ * - Space-separated words are OR conditions
478
+ * - Words starting with `+` are required includes (AND condition)
479
+ * - Words starting with `-` are excludes (NOT condition)
480
480
  *
481
- * @param fn - 검색 대상 column을 반환하는 function
482
- * @param searchText - 검색 텍스트
483
- * @returns 검색 조건이 추가된 Queryable
481
+ * @param fn - Function returning target columns to search
482
+ * @param searchText - Search text
483
+ * @returns Queryable with search conditions added
484
484
  *
485
485
  * @example
486
486
  * ```typescript
487
487
  * db.user()
488
- * .search((u) => [u.name, u.email], "Gildong Hong -탈퇴")
488
+ * .search((u) => [u.name, u.email], "John Doe -withdrawn")
489
489
  * ```
490
490
  */
491
491
  search(
@@ -509,7 +509,7 @@ export class Queryable<
509
509
 
510
510
  const conditions: WhereExprUnit[] = [];
511
511
 
512
- // OR condition: column에서 pattern 하나라도 매치하면 OK
512
+ // OR condition: match if any pattern matches in any column
513
513
  if (parsed.or.length === 1) {
514
514
  const pattern = parsed.or[0];
515
515
  const columnMatches = columns.map((col) => expr.like(expr.lower(col), pattern.toLowerCase()));
@@ -524,13 +524,13 @@ export class Queryable<
524
524
  conditions.push(expr.or(orConditions));
525
525
  }
526
526
 
527
- // MUST condition: pattern 어떤 column에서든 매치해야 (AND)
527
+ // MUST condition: each pattern must match in at least one column (AND)
528
528
  for (const pattern of parsed.must) {
529
529
  const columnMatches = columns.map((col) => expr.like(expr.lower(col), pattern.toLowerCase()));
530
530
  conditions.push(expr.or(columnMatches));
531
531
  }
532
532
 
533
- // NOT condition: 모든 column에서 매치하지 않아야 (AND NOT)
533
+ // NOT condition: must not match in any column (AND NOT)
534
534
  for (const pattern of parsed.not) {
535
535
  const columnMatches = columns.map((col) => expr.like(expr.lower(col), pattern.toLowerCase()));
536
536
  conditions.push(expr.not(expr.or(columnMatches)));
@@ -545,12 +545,12 @@ export class Queryable<
545
545
 
546
546
  //#endregion
547
547
 
548
- //#region ========== 그룹 - GROUP BY / HAVING ==========
548
+ //#region ========== Group - GROUP BY / HAVING ==========
549
549
 
550
550
  /**
551
- * GROUP BY 절을 Add
551
+ * Add GROUP BY clause
552
552
  *
553
- * @param fn - Group화 기준 column을 반환하는 function
553
+ * @param fn - Function returning columns to group by
554
554
  * @returns Queryable with GROUP BY applied
555
555
  *
556
556
  * @example
@@ -580,10 +580,10 @@ export class Queryable<
580
580
  }
581
581
 
582
582
  /**
583
- * HAVING 절을 Add (GROUP BY 후 filtering)
583
+ * Add HAVING clause (filtering after GROUP BY)
584
584
  *
585
- * @param predicate - Condition 배열을 반환하는 function
586
- * @returns HAVING apply된 Queryable
585
+ * @param predicate - Function returning an array of conditions
586
+ * @returns Queryable with HAVING applied
587
587
  *
588
588
  * @example
589
589
  * ```typescript
@@ -618,11 +618,11 @@ export class Queryable<
618
618
  //#region ========== join - JOIN / JOIN SINGLE ==========
619
619
 
620
620
  /**
621
- * 1:N 관계의 LEFT OUTER JOIN 수행 (배열로 result Add)
621
+ * Perform LEFT OUTER JOIN for 1:N relation (added as array to result)
622
622
  *
623
- * @param as - Result에 추가할 property 이름
624
- * @param fn - Join 조건을 정의하는 콜백 function
625
- * @returns join 결과가 배열로 추가된 Queryable
623
+ * @param as - Property name to add to result
624
+ * @param fn - Callback function defining join conditions
625
+ * @returns Queryable with join result added as array
626
626
  *
627
627
  * @example
628
628
  * ```typescript
@@ -650,13 +650,13 @@ export class Queryable<
650
650
  // 1. join alias Generate
651
651
  const joinAlias = `${this.meta.as}.${as}`;
652
652
 
653
- // 2. target → Queryable Transform (alias 전달)
653
+ // 2. Transform target → Queryable (pass alias)
654
654
  const joinQr = new JoinQueryable(this.meta.db, joinAlias);
655
655
 
656
- // 3. fn 실행 (where condition 추가된 Queryable return)
656
+ // 3. Execute fn (returns Queryable with conditions like where added)
657
657
  const resultQr = fn(joinQr, this.meta.columns);
658
658
 
659
- // 4. columns에 join result Add
659
+ // 4. Add join result to new columns
660
660
  const joinColumns = transformColumnsAlias(resultQr.meta.columns, joinAlias);
661
661
 
662
662
  return new Queryable({
@@ -671,11 +671,11 @@ export class Queryable<
671
671
  }
672
672
 
673
673
  /**
674
- * N:1 또는 1:1 관계의 LEFT OUTER JOIN을 수행 (단일 객체로 result Add)
674
+ * Perform LEFT OUTER JOIN for N:1 or 1:1 relation (added as single object to result)
675
675
  *
676
- * @param as - Result에 추가할 property 이름
677
- * @param fn - Join 조건을 정의하는 콜백 function
678
- * @returns join 결과가 단일 객체로 추가된 Queryable
676
+ * @param as - Property name to add to result
677
+ * @param fn - Callback function defining join conditions
678
+ * @returns Queryable with join result added as single object
679
679
  *
680
680
  * @example
681
681
  * ```typescript
@@ -706,13 +706,13 @@ export class Queryable<
706
706
  // 1. join alias Generate
707
707
  const joinAlias = `${this.meta.as}.${as}`;
708
708
 
709
- // 2. target → Queryable Transform (alias 전달)
709
+ // 2. Transform target → Queryable (pass alias)
710
710
  const joinQr = new JoinQueryable(this.meta.db, joinAlias);
711
711
 
712
- // 3. fn 실행 (where condition 추가된 Queryable return)
712
+ // 3. Execute fn (returns Queryable with conditions like where added)
713
713
  const resultQr = fn(joinQr, this.meta.columns);
714
714
 
715
- // 4. columns에 join result Add
715
+ // 4. Add join result to new columns
716
716
  const joinColumns = transformColumnsAlias(resultQr.meta.columns, joinAlias);
717
717
 
718
718
  return new Queryable({
@@ -731,22 +731,22 @@ export class Queryable<
731
731
  //#region ========== join - INCLUDE ==========
732
732
 
733
733
  /**
734
- * 관계된 Table을 automatic으로 JOIN합니다.
735
- * TableBuilder에 정의된 FK/FKT 관계를 기반으로 동작합니다.
734
+ * Automatically JOIN related tables.
735
+ * Operates based on FK/FKT relations defined in TableBuilder.
736
736
  *
737
- * @param fn - 포함할 관계를 선택하는 function (PathProxy를 통해 type 체크됨)
738
- * @returns JOIN이 추가된 Queryable
739
- * @throws 관계가 정의되지 않은 경우 에러
737
+ * @param fn - Function selecting relations to include (type-checked via PathProxy)
738
+ * @returns Queryable with JOINs added
739
+ * @throws Error if relation is not defined
740
740
  *
741
741
  * @example
742
742
  * ```typescript
743
- * // 단일 relationship include
743
+ * // Single relationship include
744
744
  * db.post.include((p) => p.user)
745
745
  *
746
- * // 중첩 relationship include
746
+ * // Nested relationship include
747
747
  * db.post.include((p) => p.user.company)
748
748
  *
749
- * // 다중 relationship include
749
+ * // Multiple relationship include
750
750
  * db.user
751
751
  * .include((u) => u.company)
752
752
  * .include((u) => u.posts)
@@ -784,11 +784,11 @@ export class Queryable<
784
784
  const parentChain = chainParts.join(".");
785
785
  chainParts.push(relationName);
786
786
 
787
- // 이미 JOIN된 경우 중복 Add 방지
787
+ // Prevent duplicate add if already JOINed
788
788
  const targetAlias = `${result.meta.as}.${chainParts.join(".")}`;
789
789
  const existingJoin = result.meta.joins?.find((j) => j.queryable.meta.as === targetAlias);
790
790
  if (existingJoin) {
791
- // 기존 JOIN의 Table로 currentTable 업데이트 continue
791
+ // Update currentTable to the existing JOIN's table and continue
792
792
  const existingFrom = existingJoin.queryable.meta.from;
793
793
  if (existingFrom instanceof TableBuilder) {
794
794
  currentTable = existingFrom;
@@ -811,7 +811,7 @@ export class Queryable<
811
811
  result = result.joinSingle(chainParts.join("."), (joinQr, parentCols) => {
812
812
  const qr = joinQr.from(targetTable);
813
813
 
814
- // FKT join 배열로 저장되므로 배열인 경우 번째 요소 사용
814
+ // FKT join is stored as array, so use first element if array
815
815
  const srcColsRaw = parentChain ? parentCols[parentChain] : parentCols;
816
816
  const srcCols = (
817
817
  Array.isArray(srcColsRaw) ? srcColsRaw[0] : srcColsRaw
@@ -833,15 +833,15 @@ export class Queryable<
833
833
  relationDef instanceof ForeignKeyTargetBuilder ||
834
834
  relationDef instanceof RelationKeyTargetBuilder
835
835
  ) {
836
- // FKT/RelationKeyTarget (1:N 또는 1:1): User.posts → Post[]
836
+ // FKT/RelationKeyTarget (1:N or 1:1): User.posts → Post[]
837
837
  // condition: Post.userId = User.id
838
838
  const targetTable = relationDef.meta.targetTableFn();
839
839
  const fkRelName = relationDef.meta.relationName;
840
840
  const sourceFk = targetTable.meta.relations?.[fkRelName];
841
841
  if (!(sourceFk instanceof ForeignKeyBuilder) && !(sourceFk instanceof RelationKeyBuilder)) {
842
842
  throw new Error(
843
- `'${relationName}' 참조하는 '${fkRelName}'이(가) ` +
844
- `${targetTable.meta.name} Table의 유효한 ForeignKey/RelationKey가 아닙니다.`,
843
+ `'${fkRelName}' referenced by '${relationName}' ` +
844
+ `is not a valid ForeignKey/RelationKey in ${targetTable.meta.name} table.`,
845
845
  );
846
846
  }
847
847
  const sourceTable = targetTable;
@@ -853,7 +853,7 @@ export class Queryable<
853
853
  const buildJoin = (joinQr: JoinQueryable, parentCols: QueryableRecord<DataRecord>) => {
854
854
  const qr = joinQr.from(sourceTable);
855
855
 
856
- // FKT join 배열로 저장되므로 배열인 경우 번째 요소 사용
856
+ // FKT join is stored as array, so use first element if array
857
857
  const srcColsRaw = parentChain ? parentCols[parentChain] : parentCols;
858
858
  const srcCols = (
859
859
  Array.isArray(srcColsRaw) ? srcColsRaw[0] : srcColsRaw
@@ -886,15 +886,15 @@ export class Queryable<
886
886
  //#region ========== Subquery - WRAP / UNION ==========
887
887
 
888
888
  /**
889
- * 현재 Queryable Subquery로 감싸기
889
+ * Wrap the current Queryable as a Subquery
890
890
  *
891
- * distinct() 또는 groupBy() count() 사용 시 필요
891
+ * Required when using count() after distinct() or groupBy()
892
892
  *
893
- * @returns Subquery로 감싸진 Queryable
893
+ * @returns Queryable wrapped as a Subquery
894
894
  *
895
895
  * @example
896
896
  * ```typescript
897
- * // DISTINCT 카운트
897
+ * // Count after DISTINCT
898
898
  * const count = await db.user()
899
899
  * .select((u) => ({ name: u.name }))
900
900
  * .distinct()
@@ -903,7 +903,7 @@ export class Queryable<
903
903
  * ```
904
904
  */
905
905
  wrap(): Queryable<TData, never> {
906
- // 현재 Queryable Subquery로 감싸기
906
+ // Wrap the current Queryable as a Subquery
907
907
  const wrapAlias = this.meta.db.getNextAlias();
908
908
  return new Queryable({
909
909
  db: this.meta.db,
@@ -953,18 +953,18 @@ export class Queryable<
953
953
  //#region ========== recursive - WITH RECURSIVE ==========
954
954
 
955
955
  /**
956
- * recursive CTE(Common Table Expression)를 Generate
956
+ * Generate a recursive CTE (Common Table Expression)
957
957
  *
958
- * 계층 structure data(조직도, 카테고리 트리 )를 조회할 때 사용
958
+ * Used for querying hierarchical data (org charts, category trees, etc.)
959
959
  *
960
- * @param fn - recursive part을 정의하는 콜백 function
961
- * @returns recursive CTE apply된 Queryable
960
+ * @param fn - Callback function that defines the recursive part
961
+ * @returns Queryable with the recursive CTE applied
962
962
  *
963
963
  * @example
964
964
  * ```typescript
965
- * // 조직도 계층 조회
965
+ * // Query org chart hierarchy
966
966
  * db.employee()
967
- * .where((e) => [expr.null(e.managerId)]) // 루트 노드
967
+ * .where((e) => [expr.null(e.managerId)]) // Root nodes
968
968
  * .recursive((cte) =>
969
969
  * cte.from(Employee)
970
970
  * .where((e) => [expr.eq(e.managerId, e.self[0].id)])
@@ -982,13 +982,13 @@ export class Queryable<
982
982
  columns: transformColumnsAlias(newFroms[0].meta.columns, this.meta.as, ""),
983
983
  });
984
984
  }
985
- // 동적 CTE 이름 Generate
985
+ // Generate dynamic CTE name
986
986
  const cteName = this.meta.db.getNextAlias();
987
987
 
988
- // 2. target Queryable Transform (CTE 이름 전달)
988
+ // 2. Transform target to Queryable (pass CTE name)
989
989
  const cteQr = new RecursiveQueryable(this, cteName);
990
990
 
991
- // 3. fn 실행 (where condition 추가된 Queryable return)
991
+ // 3. Execute fn (returns Queryable with conditions like where added)
992
992
  const resultQr = fn(cteQr);
993
993
 
994
994
  return new Queryable({
@@ -998,7 +998,7 @@ export class Queryable<
998
998
  columns: transformColumnsAlias(this.meta.columns, this.meta.as, ""),
999
999
  with: {
1000
1000
  name: cteName,
1001
- base: this as any, // circular 참조 Type inference 차단
1001
+ base: this as any, // Block circular reference type inference
1002
1002
  recursive: resultQr,
1003
1003
  },
1004
1004
  });
@@ -1006,10 +1006,10 @@ export class Queryable<
1006
1006
 
1007
1007
  //#endregion
1008
1008
 
1009
- //#region ========== [query] 조회 - SELECT ==========
1009
+ //#region ========== [query] Select - SELECT ==========
1010
1010
 
1011
1011
  /**
1012
- * SELECT query 실행하고 result 배열을 return
1012
+ * Execute a SELECT query and return the result array
1013
1013
  *
1014
1014
  * @returns Query result array
1015
1015
  *
@@ -1029,10 +1029,10 @@ export class Queryable<
1029
1029
  }
1030
1030
 
1031
1031
  /**
1032
- * 단일 결과를 return (2개 이상이면 Error)
1032
+ * Return a single result (Error if more than 1)
1033
1033
  *
1034
- * @returns 단일 result 또는 undefined
1035
- * @throws 2개 이상의 결과가 반환된 경우
1034
+ * @returns Single result or undefined
1035
+ * @throws When more than one result is returned
1036
1036
  *
1037
1037
  * @example
1038
1038
  * ```typescript
@@ -1053,7 +1053,7 @@ export class Queryable<
1053
1053
  }
1054
1054
 
1055
1055
  /**
1056
- * query 소스 이름 return (error message용)
1056
+ * Return query source name (for error messages)
1057
1057
  */
1058
1058
  private _getSourceName(): string {
1059
1059
  const from = this.meta.from;
@@ -1067,9 +1067,9 @@ export class Queryable<
1067
1067
  }
1068
1068
 
1069
1069
  /**
1070
- * 번째 결과를 return (여러 개여도 번째만)
1070
+ * Return the first result (only the first even if multiple exist)
1071
1071
  *
1072
- * @returns 번째 result 또는 undefined
1072
+ * @returns First result or undefined
1073
1073
  *
1074
1074
  * @example
1075
1075
  * ```typescript
@@ -1084,11 +1084,11 @@ export class Queryable<
1084
1084
  }
1085
1085
 
1086
1086
  /**
1087
- * result row 수를 return
1087
+ * Return the number of result rows
1088
1088
  *
1089
- * @param fn - 카운트할 column 지정하는 function (Select)
1090
- * @returns row
1091
- * @throws distinct() 또는 groupBy() 직접 호출 시 에러 (wrap() 필요)
1089
+ * @param fn - Function to specify the column to count (optional)
1090
+ * @returns Number of rows
1091
+ * @throws Error when called directly after distinct() or groupBy() (use wrap() first)
1092
1092
  *
1093
1093
  * @example
1094
1094
  * ```typescript
@@ -1115,9 +1115,9 @@ export class Queryable<
1115
1115
  }
1116
1116
 
1117
1117
  /**
1118
- * 조건에 맞는 data 존재 여부를 확인
1118
+ * Check whether data matching the conditions exists
1119
1119
  *
1120
- * @returns 존재하면 true, 없으면 false
1120
+ * @returns true if exists, false otherwise
1121
1121
  *
1122
1122
  * @example
1123
1123
  * ```typescript
@@ -1239,7 +1239,7 @@ export class Queryable<
1239
1239
  buildResultMeta(val[0], fullKey);
1240
1240
  }
1241
1241
  } else if (typeof val === "object") {
1242
- // 단일 object (N:1, 1:1 relationship)
1242
+ // Single object (N:1, 1:1 relationship)
1243
1243
  joins[fullKey] = { isSingle: true };
1244
1244
  buildResultMeta(val, fullKey);
1245
1245
  }
@@ -1253,25 +1253,25 @@ export class Queryable<
1253
1253
 
1254
1254
  //#endregion
1255
1255
 
1256
- //#region ========== [query] 삽입 - INSERT ==========
1256
+ //#region ========== [query] Insert - INSERT ==========
1257
1257
 
1258
1258
  /**
1259
- * INSERT query를 실행
1259
+ * Execute an INSERT query
1260
1260
  *
1261
- * MSSQL의 1000개 제한을 위해 automatic으로 1000개씩 청크로 분할하여 실행
1261
+ * Automatically splits into chunks of 1000 for MSSQL's row limit
1262
1262
  *
1263
- * @param records - Insert할 레코드 array
1264
- * @param outputColumns - column name array to receive (Select)
1265
- * @returns outputColumns 지정 삽입된 레코드 array return
1263
+ * @param records - Array of records to insert
1264
+ * @param outputColumns - Column name array to receive (optional)
1265
+ * @returns When outputColumns specified, returns array of inserted records
1266
1266
  *
1267
1267
  * @example
1268
1268
  * ```typescript
1269
- * // 단순 삽입
1269
+ * // Simple insert
1270
1270
  * await db.user().insert([
1271
1271
  * { name: "Gildong Hong", email: "hong@test.com" },
1272
1272
  * ]);
1273
1273
  *
1274
- * // 삽입 ID return
1274
+ * // Return ID after insert
1275
1275
  * const [inserted] = await db.user().insert(
1276
1276
  * [{ name: "Gildong Hong" }],
1277
1277
  * ["id"],
@@ -1291,7 +1291,7 @@ export class Queryable<
1291
1291
  return outputColumns ? [] : undefined;
1292
1292
  }
1293
1293
 
1294
- // MSSQL 1000 제한을 위해 청크 split
1294
+ // Split into chunks for MSSQL's 1000 row limit
1295
1295
  const CHUNK_SIZE = 1000;
1296
1296
  const allResults: Pick<TFrom["$inferColumns"], K>[] = [];
1297
1297
 
@@ -1314,11 +1314,11 @@ export class Queryable<
1314
1314
  }
1315
1315
 
1316
1316
  /**
1317
- * WHERE condition에 맞는 data 없으면 INSERT
1317
+ * INSERT if no data matches the WHERE condition
1318
1318
  *
1319
- * @param record - Insert할 레코드
1320
- * @param outputColumns - column name array to receive (Select)
1321
- * @returns outputColumns 지정 삽입된 레코드 return
1319
+ * @param record - Record to insert
1320
+ * @param outputColumns - Column name array to receive (optional)
1321
+ * @returns When outputColumns specified, returns the inserted record
1322
1322
  *
1323
1323
  * @example
1324
1324
  * ```typescript
@@ -1347,11 +1347,11 @@ export class Queryable<
1347
1347
  }
1348
1348
 
1349
1349
  /**
1350
- * INSERT INTO ... SELECT (현재 SELECT 결과를 다른 Table에 INSERT)
1350
+ * INSERT INTO ... SELECT (INSERT the current SELECT results into another Table)
1351
1351
  *
1352
- * @param targetTable - Insert 대상 Table
1353
- * @param outputColumns - column name array to receive (Select)
1354
- * @returns outputColumns 지정 삽입된 레코드 array return
1352
+ * @param targetTable - Target Table to insert into
1353
+ * @param outputColumns - Column name array to receive (optional)
1354
+ * @returns When outputColumns specified, returns array of inserted records
1355
1355
  *
1356
1356
  * @example
1357
1357
  * ```typescript
@@ -1389,7 +1389,7 @@ export class Queryable<
1389
1389
  const from = this.meta.from as TableBuilder<any, any> | ViewBuilder<any, any, any>;
1390
1390
  const outputDef = this._getCudOutputDef();
1391
1391
 
1392
- // AI column explicit 값이 있으면 overrideIdentity 설정
1392
+ // Set overrideIdentity if AI column has explicit values
1393
1393
  const overrideIdentity =
1394
1394
  outputDef.aiColName != null &&
1395
1395
  records.some((r) => (r as Record<string, unknown>)[outputDef.aiColName!] !== undefined);
@@ -1458,15 +1458,15 @@ export class Queryable<
1458
1458
  //#region ========== [query] Modify - UPDATE / DELETE ==========
1459
1459
 
1460
1460
  /**
1461
- * UPDATE query를 실행
1461
+ * Execute an UPDATE query
1462
1462
  *
1463
- * @param recordFwd - Update할 column과 값을 반환하는 function
1464
- * @param outputColumns - column name array to receive (Select)
1465
- * @returns outputColumns 지정 업데이트된 레코드 array return
1463
+ * @param recordFwd - Function that returns the columns and values to update
1464
+ * @param outputColumns - Column name array to receive (optional)
1465
+ * @returns When outputColumns specified, returns array of updated records
1466
1466
  *
1467
1467
  * @example
1468
1468
  * ```typescript
1469
- * // 단순 업데이트
1469
+ * // Simple update
1470
1470
  * await db.user()
1471
1471
  * .where((u) => [expr.eq(u.id, 1)])
1472
1472
  * .update((u) => ({
@@ -1474,7 +1474,7 @@ export class Queryable<
1474
1474
  * updatedAt: expr.val("DateTime", DateTime.now()),
1475
1475
  * }));
1476
1476
  *
1477
- * // 기존 value 참조
1477
+ * // Reference existing value
1478
1478
  * await db.product()
1479
1479
  * .update((p) => ({
1480
1480
  * price: expr.mul(p.price, expr.val("number", 1.1)),
@@ -1503,19 +1503,19 @@ export class Queryable<
1503
1503
  }
1504
1504
 
1505
1505
  /**
1506
- * DELETE query를 실행
1506
+ * Execute a DELETE query
1507
1507
  *
1508
- * @param outputColumns - column name array to receive (Select)
1509
- * @returns outputColumns 지정 삭제된 레코드 array return
1508
+ * @param outputColumns - Column name array to receive (optional)
1509
+ * @returns When outputColumns specified, returns array of deleted records
1510
1510
  *
1511
1511
  * @example
1512
1512
  * ```typescript
1513
- * // 단순 Delete
1513
+ * // Simple delete
1514
1514
  * await db.user()
1515
1515
  * .where((u) => [expr.eq(u.id, 1)])
1516
1516
  * .delete();
1517
1517
  *
1518
- * // 삭제된 data return
1518
+ * // Return deleted data
1519
1519
  * const deleted = await db.user()
1520
1520
  * .where((u) => [expr.eq(u.isExpired, true)])
1521
1521
  * .delete(["id", "name"]);
@@ -1591,18 +1591,18 @@ export class Queryable<
1591
1591
  //#region ========== [query] Modify - UPSERT ==========
1592
1592
 
1593
1593
  /**
1594
- * UPSERT (UPDATE or INSERT) query를 실행
1594
+ * Execute an UPSERT (UPDATE or INSERT) query
1595
1595
  *
1596
- * WHERE condition에 맞는 data 있으면 UPDATE, 없으면 INSERT
1596
+ * UPDATE if data matching the WHERE condition exists, otherwise INSERT
1597
1597
  *
1598
- * @param updateFn - Update할 column과 값을 반환하는 function
1599
- * @param insertFn - Insert할 레코드를 반환하는 function (selection, 미지정 updateFn와 동일)
1600
- * @param outputColumns - column name array to receive (Select)
1601
- * @returns outputColumns 지정 영향받은 레코드 array return
1598
+ * @param updateFn - Function that returns the columns and values to update
1599
+ * @param insertFn - Function that returns the record to insert (optional, defaults to same as updateFn)
1600
+ * @param outputColumns - Column name array to receive (optional)
1601
+ * @returns When outputColumns specified, returns array of affected records
1602
1602
  *
1603
1603
  * @example
1604
1604
  * ```typescript
1605
- * // UPDATE/INSERT 동일 data
1605
+ * // Same data for UPDATE/INSERT
1606
1606
  * await db.user()
1607
1607
  * .where((u) => [expr.eq(u.email, "test@test.com")])
1608
1608
  * .upsert(() => ({
@@ -1610,7 +1610,7 @@ export class Queryable<
1610
1610
  * email: expr.val("string", "test@test.com"),
1611
1611
  * }));
1612
1612
  *
1613
- * // UPDATE/INSERT 다른 data
1613
+ * // Different data for UPDATE/INSERT
1614
1614
  * await db.user()
1615
1615
  * .where((u) => [expr.eq(u.email, "test@test.com")])
1616
1616
  * .upsert(
@@ -1679,14 +1679,14 @@ export class Queryable<
1679
1679
 
1680
1680
  const { select: _sel, ...existsSelectQuery } = this.getSelectQueryDef();
1681
1681
 
1682
- // updateRecord Generate
1682
+ // Generate updateRecord
1683
1683
  const updateQrRecord = updateRecordFn(this.meta.columns);
1684
1684
  const updateRecord: Record<string, Expr> = {};
1685
1685
  for (const [key, value] of Object.entries(updateQrRecord)) {
1686
1686
  updateRecord[key] = expr.toExpr(value);
1687
1687
  }
1688
1688
 
1689
- // insertRecord Generate (updateRecordRaw 번째 인자로)
1689
+ // Generate insertRecord (pass updateRecordRaw as second argument)
1690
1690
  const insertRecordRaw = insertRecordFn(updateQrRecord);
1691
1691
  const insertRecord = Object.fromEntries(
1692
1692
  Object.entries(insertRecordRaw).map(([key, value]) => [key, expr.toExpr(value)]),
@@ -1713,13 +1713,13 @@ export class Queryable<
1713
1713
  //#region ========== DDL Helper ==========
1714
1714
 
1715
1715
  /**
1716
- * FK constraint on/off (transaction 사용 가능)
1716
+ * FK constraint on/off (can be used within a transaction)
1717
1717
  */
1718
1718
  async switchFk(enabled: boolean): Promise<void> {
1719
1719
  const from = this.meta.from;
1720
1720
  if (!(from instanceof TableBuilder) && !(from instanceof ViewBuilder)) {
1721
1721
  throw new Error(
1722
- "switchFk TableBuilder 또는 ViewBuilder 기반 queryable에서만 사용할 있습니다.",
1722
+ "switchFk can only be used on TableBuilder or ViewBuilder based queryables.",
1723
1723
  );
1724
1724
  }
1725
1725
  await this.meta.db.switchFk(this.meta.db.getQueryDefObjectName(from), enabled);
@@ -1727,7 +1727,7 @@ export class Queryable<
1727
1727
 
1728
1728
  //#endregion
1729
1729
 
1730
- //#region ========== CUD 공통 ==========
1730
+ //#region ========== CUD Common ==========
1731
1731
 
1732
1732
  private _getCudOutputDef(): {
1733
1733
  pkColNames: string[];
@@ -1762,12 +1762,12 @@ export class Queryable<
1762
1762
  //#region ========== Helper Functions ==========
1763
1763
 
1764
1764
  /**
1765
- * FK column 배열과 대상 Table PK 매칭하여 PK column 배열을 return
1765
+ * Match FK column array with the target Table's PK and return PK column name array
1766
1766
  *
1767
- * @param fkCols - FK column array
1768
- * @param targetTable - 참조 대상 Table builder
1769
- * @returns 매칭된 PK column array
1770
- * @throws FK/PK column 불일치 시
1767
+ * @param fkCols - FK column name array
1768
+ * @param targetTable - Target Table builder being referenced
1769
+ * @returns Matched PK column name array
1770
+ * @throws When FK/PK column count mismatch
1771
1771
  */
1772
1772
  export function getMatchedPrimaryKeys(
1773
1773
  fkCols: string[],
@@ -1776,25 +1776,25 @@ export function getMatchedPrimaryKeys(
1776
1776
  const pk = targetTable.meta.primaryKey;
1777
1777
  if (pk == null || fkCols.length !== pk.length) {
1778
1778
  throw new Error(
1779
- `FK/PK column 개수가 일치하지 않습니다 (대상: ${targetTable.meta.name}, FK: ${fkCols.length}개, PK: ${pk?.length ?? 0})`,
1779
+ `FK/PK column count mismatch (target: ${targetTable.meta.name}, FK: ${fkCols.length}, PK: ${pk?.length ?? 0})`,
1780
1780
  );
1781
1781
  }
1782
1782
  return pk;
1783
1783
  }
1784
1784
 
1785
1785
  /**
1786
- * 중첩 columns structure alias로 Transform하는 공용 헬퍼
1786
+ * Common helper to transform nested columns structure to a new alias
1787
1787
  *
1788
- * Subquery/JOIN 기존 alias alias Transform하면서,
1789
- * 중첩 (posts.userId) 평면화된 키로 유지한다.
1788
+ * When wrapping as Subquery/JOIN, transforms existing alias to new alias while
1789
+ * keeping nested keys (posts.userId) as flattened keys.
1790
1790
  *
1791
- * 예: posts[0].userId column 경로가 ["T1.posts", "userId"]인 경우,
1792
- * alias "T2" Transform하면 ["T2", "posts.userId"]가 된다.
1791
+ * e.g.: If the path of posts[0].userId column is ["T1.posts", "userId"],
1792
+ * transforming to new alias "T2" yields ["T2", "posts.userId"].
1793
1793
  *
1794
- * @param columns - Transform할 column 레코드
1795
- * @param alias - Table alias (예: "T2")
1796
- * @param keyPrefix - 현재 중첩 경로 (recursive 호출용, Default value "")
1797
- * @returns Transform된 column 레코드
1794
+ * @param columns - Column record to transform
1795
+ * @param alias - New Table alias (e.g., "T2")
1796
+ * @param keyPrefix - Current nested path (for recursive calls, default "")
1797
+ * @returns Transformed column record
1798
1798
  */
1799
1799
  function transformColumnsAlias<TRecord extends DataRecord>(
1800
1800
  columns: QueryableRecord<TRecord>,
@@ -1898,9 +1898,9 @@ export type NullableQueryableRecord<TData extends DataRecord> = {
1898
1898
  };
1899
1899
 
1900
1900
  /**
1901
- * QueryableRecord에서 DataRecord로 역transform
1901
+ * Reverse-transform from QueryableRecord to DataRecord
1902
1902
  *
1903
- * ExprUnit<T>를 T로, 중첩 object/배열을 재귀적으로 풀어냄
1903
+ * Unwraps ExprUnit<T> to T, recursively unwrapping nested objects/arrays
1904
1904
  */
1905
1905
  export type UnwrapQueryableRecord<R> = {
1906
1906
  [K in keyof R]: R[K] extends ExprUnit<infer T>
@@ -1914,30 +1914,30 @@ export type UnwrapQueryableRecord<R> = {
1914
1914
  : never;
1915
1915
  };
1916
1916
 
1917
- //#region ========== PathProxy - include용 type 안전 경로 builder ==========
1917
+ //#region ========== PathProxy - Type-safe path builder for include ==========
1918
1918
 
1919
1919
  /**
1920
- * include()에서 relationship 경로를 type 안전하게 지정하기 위한 Proxy type
1921
- * ColumnPrimitive 아닌 필드(FK, FKT relationship) access 가능
1920
+ * Proxy type for specifying relationship paths in include() in a type-safe manner
1921
+ * Only non-ColumnPrimitive fields (FK, FKT relationships) are accessible
1922
1922
  *
1923
1923
  * @example
1924
1924
  * ```typescript
1925
- * // item.user.company access 내부적으로 ["user", "company"] 경로 수집
1925
+ * // Accessing item.user.company internally collects path ["user", "company"]
1926
1926
  * db.post.include(item => item.user.company)
1927
1927
  *
1928
- * // item.title string(ColumnPrimitive)이므로 컴파일 에러
1929
- * db.post.include(item => item.title) // 에러
1928
+ * // item.title is string (ColumnPrimitive), so this is a compile error
1929
+ * db.post.include(item => item.title) // compile error
1930
1930
  * ```
1931
1931
  */
1932
1932
  /**
1933
- * 배열이면 요소 type 추출
1933
+ * Extract element type if array
1934
1934
  */
1935
1935
  type UnwrapArray<TArray> = TArray extends (infer TElement)[] ? TElement : TArray;
1936
1936
 
1937
1937
  const PATH_SYMBOL = Symbol("path");
1938
1938
 
1939
1939
  /**
1940
- * include()용 type 안전 경로 프록시
1940
+ * Type-safe path proxy for include()
1941
1941
  */
1942
1942
  export type PathProxy<TObject> = {
1943
1943
  [K in keyof TObject as TObject[K] extends ColumnPrimitive ? never : K]-?: PathProxy<
@@ -1946,8 +1946,8 @@ export type PathProxy<TObject> = {
1946
1946
  } & { readonly [PATH_SYMBOL]: string[] };
1947
1947
 
1948
1948
  /**
1949
- * PathProxy instance Generate
1950
- * Proxy 사용하여 프로퍼티 접근을 가로채고 경로를 수집
1949
+ * Generate PathProxy instance
1950
+ * Uses Proxy to intercept property access and collect paths
1951
1951
  */
1952
1952
  function createPathProxy<TObject>(path: string[] = []): PathProxy<TObject> {
1953
1953
  return new Proxy({} as PathProxy<TObject>, {
@@ -1962,22 +1962,22 @@ function createPathProxy<TObject>(path: string[] = []): PathProxy<TObject> {
1962
1962
  //#endregion
1963
1963
 
1964
1964
  /**
1965
- * Table 또는 View에 대한 Queryable factory 함수를 Generate
1965
+ * Generate a Queryable factory function for a Table or View
1966
1966
  *
1967
- * DbContext에서 Table/View getter를 정의할 때 사용
1967
+ * Used when defining per-Table/View getters in DbContext
1968
1968
  *
1969
1969
  * @param db - DbContext instance
1970
- * @param tableOrView - TableBuilder 또는 ViewBuilder instance
1971
- * @param as - alias 지정 (selection, 미지정 automatic Create)
1972
- * @returns Queryable을 반환하는 factory function
1970
+ * @param tableOrView - TableBuilder or ViewBuilder instance
1971
+ * @param as - Alias specification (optional, auto-created if not specified)
1972
+ * @returns Factory function that returns a Queryable
1973
1973
  *
1974
1974
  * @example
1975
1975
  * ```typescript
1976
1976
  * class AppDbContext extends DbContext {
1977
- * // 호출 시마다 새로운 alias 할당
1977
+ * // A new alias is assigned on each call
1978
1978
  * user = queryable(this, User);
1979
1979
  *
1980
- * // 사용 예시
1980
+ * // Usage example
1981
1981
  * async getActiveUsers() {
1982
1982
  * return this.user()
1983
1983
  * .where((u) => [expr.eq(u.isActive, true)])
@@ -1992,8 +1992,8 @@ export function queryable<TBuilder extends TableBuilder<any, any> | ViewBuilder<
1992
1992
  as?: string,
1993
1993
  ): () => Queryable<TBuilder["$inferSelect"], TBuilder extends TableBuilder<any, any> ? TBuilder : never> {
1994
1994
  return () => {
1995
- // as 명시되지 않으면 db.getNextAlias() 사용 (카운터 증가)
1996
- // as 명시되면 그대로 사용 (카운터 증가 안함)
1995
+ // If as is not specified, use db.getNextAlias() (counter increments)
1996
+ // If as is specified, use it as-is (counter does not increment)
1997
1997
  const finalAs = as ?? db.getNextAlias();
1998
1998
 
1999
1999
  // TableBuilder + columns
@@ -2017,7 +2017,7 @@ export function queryable<TBuilder extends TableBuilder<any, any> | ViewBuilder<
2017
2017
  if (tableOrView instanceof ViewBuilder && tableOrView.meta.viewFn != null) {
2018
2018
  const baseQr = tableOrView.meta.viewFn(db);
2019
2019
 
2020
- // TFrom ViewBuilder로 설정하여 return
2020
+ // Return with TFrom set to ViewBuilder
2021
2021
  return new Queryable({
2022
2022
  db,
2023
2023
  from: tableOrView,