@simplysm/orm-common 14.1.2 → 14.1.6

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 (89) hide show
  1. package/dist/db-context.d.ts +11 -10
  2. package/dist/db-context.d.ts.map +1 -1
  3. package/dist/db-context.js +14 -11
  4. package/dist/db-context.js.map +1 -1
  5. package/dist/ddl/initialize.js.map +1 -1
  6. package/dist/ddl/relation-ddl.d.ts +1 -1
  7. package/dist/ddl/relation-ddl.d.ts.map +1 -1
  8. package/dist/ddl/relation-ddl.js.map +1 -1
  9. package/dist/ddl/table-ddl.d.ts +3 -3
  10. package/dist/ddl/table-ddl.d.ts.map +1 -1
  11. package/dist/ddl/table-ddl.js.map +1 -1
  12. package/dist/errors/db-transaction-error.d.ts +4 -5
  13. package/dist/errors/db-transaction-error.d.ts.map +1 -1
  14. package/dist/errors/db-transaction-error.js +5 -6
  15. package/dist/errors/db-transaction-error.js.map +1 -1
  16. package/dist/exec/executable.d.ts +4 -13
  17. package/dist/exec/executable.d.ts.map +1 -1
  18. package/dist/exec/executable.js.map +1 -1
  19. package/dist/exec/queryable.d.ts +11 -9
  20. package/dist/exec/queryable.d.ts.map +1 -1
  21. package/dist/exec/queryable.js +9 -5
  22. package/dist/exec/queryable.js.map +1 -1
  23. package/dist/expr/expr.d.ts +7 -4
  24. package/dist/expr/expr.d.ts.map +1 -1
  25. package/dist/expr/expr.js +5 -2
  26. package/dist/expr/expr.js.map +1 -1
  27. package/dist/models/system-migration.d.ts +1 -1
  28. package/dist/models/system-migration.d.ts.map +1 -1
  29. package/dist/query-builder/base/expr-renderer-base.d.ts +2 -1
  30. package/dist/query-builder/base/expr-renderer-base.d.ts.map +1 -1
  31. package/dist/query-builder/base/expr-renderer-base.js.map +1 -1
  32. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts +2 -2
  33. package/dist/query-builder/mssql/mssql-expr-renderer.d.ts.map +1 -1
  34. package/dist/query-builder/mssql/mssql-expr-renderer.js.map +1 -1
  35. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts +2 -2
  36. package/dist/query-builder/mysql/mysql-expr-renderer.d.ts.map +1 -1
  37. package/dist/query-builder/mysql/mysql-expr-renderer.js.map +1 -1
  38. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts +2 -2
  39. package/dist/query-builder/postgresql/postgresql-expr-renderer.d.ts.map +1 -1
  40. package/dist/query-builder/postgresql/postgresql-expr-renderer.js.map +1 -1
  41. package/dist/query-builder/postgresql/postgresql-query-builder.d.ts.map +1 -1
  42. package/dist/query-builder/postgresql/postgresql-query-builder.js.map +1 -1
  43. package/dist/schema/factory/column-builder.d.ts +1 -1
  44. package/dist/schema/factory/column-builder.d.ts.map +1 -1
  45. package/dist/schema/factory/relation-builder.d.ts +55 -49
  46. package/dist/schema/factory/relation-builder.d.ts.map +1 -1
  47. package/dist/schema/factory/relation-builder.js +12 -15
  48. package/dist/schema/factory/relation-builder.js.map +1 -1
  49. package/dist/schema/table-builder.d.ts +35 -18
  50. package/dist/schema/table-builder.d.ts.map +1 -1
  51. package/dist/schema/table-builder.js +32 -15
  52. package/dist/schema/table-builder.js.map +1 -1
  53. package/dist/schema/view-builder.d.ts +28 -24
  54. package/dist/schema/view-builder.d.ts.map +1 -1
  55. package/dist/schema/view-builder.js +18 -14
  56. package/dist/schema/view-builder.js.map +1 -1
  57. package/dist/types/column.d.ts +6 -17
  58. package/dist/types/column.d.ts.map +1 -1
  59. package/dist/types/column.js +3 -19
  60. package/dist/types/column.js.map +1 -1
  61. package/dist/types/db-context-def.d.ts +7 -7
  62. package/dist/types/db-context-def.d.ts.map +1 -1
  63. package/dist/types/query-def.d.ts +1 -1
  64. package/dist/types/query-def.d.ts.map +1 -1
  65. package/dist/utils/result-parser.d.ts.map +1 -1
  66. package/dist/utils/result-parser.js +3 -7
  67. package/dist/utils/result-parser.js.map +1 -1
  68. package/package.json +3 -3
  69. package/src/db-context.ts +23 -20
  70. package/src/ddl/initialize.ts +4 -4
  71. package/src/ddl/relation-ddl.ts +1 -1
  72. package/src/ddl/table-ddl.ts +3 -3
  73. package/src/errors/db-transaction-error.ts +6 -4
  74. package/src/exec/executable.ts +5 -4
  75. package/src/exec/queryable.ts +31 -24
  76. package/src/expr/expr.ts +10 -4
  77. package/src/query-builder/base/expr-renderer-base.ts +2 -1
  78. package/src/query-builder/mssql/mssql-expr-renderer.ts +5 -5
  79. package/src/query-builder/mysql/mysql-expr-renderer.ts +2 -2
  80. package/src/query-builder/postgresql/postgresql-expr-renderer.ts +5 -5
  81. package/src/query-builder/postgresql/postgresql-query-builder.ts +4 -3
  82. package/src/schema/factory/column-builder.ts +3 -3
  83. package/src/schema/factory/relation-builder.ts +350 -346
  84. package/src/schema/table-builder.ts +209 -193
  85. package/src/schema/view-builder.ts +148 -143
  86. package/src/types/column.ts +7 -26
  87. package/src/types/db-context-def.ts +7 -7
  88. package/src/types/query-def.ts +1 -1
  89. package/src/utils/result-parser.ts +11 -19
@@ -1,143 +1,148 @@
1
- import type { DbContextBase } from "../types/db-context-def";
2
- import type { Queryable } from "../exec/queryable";
3
- import type { DataRecord } from "../types/db";
4
- import {
5
- createRelationFactory,
6
- type InferDeepRelations,
7
- type RelationBuilderRecord,
8
- } from "./factory/relation-builder";
9
-
10
- // ============================================
11
- // ViewBuilder
12
- // ============================================
13
-
14
- /**
15
- * Database View 정의 builder
16
- *
17
- * Fluent API로 View query 관계를 정의
18
- * DbContext의 queryable()과 함께 사용하여 타입 안전한 query 구성
19
- *
20
- * @template TDbContext - DbContext 타입
21
- * @template TData - View 데이터 레코드 타입
22
- * @template TRelations - 관계 정의 레코드 타입
23
- *
24
- * @see {@link View} factory 함수
25
- * @see {@link queryable} Queryable 생성
26
- */
27
- export class ViewBuilder<
28
- TDbContext extends DbContextBase,
29
- TData extends DataRecord,
30
- TRelations extends RelationBuilderRecord,
31
- > {
32
- /** 관계 정의 (타입 추론용) */
33
- readonly $relations!: TRelations;
34
- /** 전체 타입 추론 */
35
- readonly $inferSelect!: TData;
36
-
37
- /**
38
- * @param meta - View 메타데이터
39
- * @param meta.name - View 이름
40
- * @param meta.description - View 설명 (comment)
41
- * @param meta.database - Database 이름
42
- * @param meta.schema - Schema 이름 (MSSQL/PostgreSQL)
43
- * @param meta.viewFn - View query 정의 함수
44
- * @param meta.relations - 관계 정의
45
- */
46
- constructor(
47
- readonly meta: {
48
- name: string;
49
- description?: string;
50
- database?: string;
51
- schema?: string;
52
- viewFn?: (db: TDbContext) => Queryable<TData, any>;
53
- relations?: TRelations;
54
- },
55
- ) {}
56
-
57
- /**
58
- * View 설명 설정
59
- *
60
- * @param desc - View 설명 (DDL Comment로 사용됨)
61
- * @returns 새 ViewBuilder 인스턴스
62
- */
63
- description(desc: string): ViewBuilder<TDbContext, TData, TRelations> {
64
- return new ViewBuilder({ ...this.meta, description: desc });
65
- }
66
-
67
- /**
68
- * Database 이름 설정
69
- *
70
- * @param db - Database 이름
71
- * @returns ViewBuilder 인스턴스
72
- */
73
- database(db: string): ViewBuilder<TDbContext, TData, TRelations> {
74
- return new ViewBuilder({ ...this.meta, database: db });
75
- }
76
-
77
- /**
78
- * Schema 이름 설정
79
- *
80
- * MSSQL, PostgreSQL에서 사용
81
- *
82
- * @param schema - Schema 이름 (MSSQL: dbo, PostgreSQL: public)
83
- * @returns 새 ViewBuilder 인스턴스
84
- */
85
- schema(schema: string): ViewBuilder<TDbContext, TData, TRelations> {
86
- return new ViewBuilder({ ...this.meta, schema });
87
- }
88
-
89
- /**
90
- * View query 정의
91
- *
92
- * SELECT query를 통해 View의 데이터 소스를 정의
93
- *
94
- * @template TViewData - View 데이터 타입
95
- * @template TDb - DbContext 타입
96
- * @param viewFn - DbContext를 받아 Queryable을 반환하는 함수
97
- * @returns ViewBuilder 인스턴스
98
- */
99
- query<TViewData extends DataRecord, TDb extends DbContextBase>(
100
- viewFn: (db: TDb) => Queryable<TViewData, any>,
101
- ): ViewBuilder<TDb, TViewData, TRelations> {
102
- return new ViewBuilder({ ...this.meta, viewFn });
103
- }
104
-
105
- /**
106
- * 관계 정의
107
- *
108
- * 다른 Table/View와의 관계를 설정
109
- *
110
- * @template T - 관계 정의 타입
111
- * @param fn - 관계 factory를 받아 관계 정의를 반환하는 함수
112
- * @returns 새 ViewBuilder 인스턴스
113
- *
114
- * @see {@link ForeignKeyBuilder} FK builder
115
- * @see {@link ForeignKeyTargetBuilder} FK reverse-reference builder
116
- */
117
- relations<T extends RelationBuilderRecord>(
118
- fn: (r: ReturnType<typeof createRelationFactory<this, keyof TData & string>>) => T,
119
- ): ViewBuilder<TDbContext, TData & InferDeepRelations<T>, T> {
120
- return new ViewBuilder({
121
- ...this.meta,
122
- relations: fn(createRelationFactory<this, keyof TData & string>(() => this)),
123
- }) as any;
124
- }
125
- }
126
-
127
- // ============================================
128
- // View 함수
129
- // ============================================
130
-
131
- /**
132
- * View builder factory 함수
133
- *
134
- * Fluent API로 View schema를 정의하기 위한 ViewBuilder를 생성
135
- *
136
- * @param name - View 이름
137
- * @returns ViewBuilder 인스턴스
138
- *
139
- * @see {@link ViewBuilder} builder 클래스
140
- */
141
- export function View(name: string) {
142
- return new ViewBuilder({ name });
143
- }
1
+ import type { DbContextBase } from "../types/db-context-def";
2
+ import type { Queryable } from "../exec/queryable";
3
+ import type { DataRecord } from "../types/db";
4
+ import {
5
+ createRelationFactory,
6
+ type InferDeepRelations,
7
+ type ViewRelationFactory,
8
+ } from "./factory/relation-builder";
9
+
10
+ // ============================================
11
+ // ViewBuilder
12
+ // ============================================
13
+
14
+ /**
15
+ * Database View 정의 builder
16
+ *
17
+ * Fluent API로 View query 정의
18
+ * DbContext의 queryable()과 함께 사용하여 타입 안전한 query 구성
19
+ *
20
+ * 관계는 `.relations((r) => ({ ... }))` 메서드 체이닝으로 정의한다(RelationKey만 사용 가능).
21
+ * 관계를 잡는 4번째 제네릭 `TRelations` **무제약**이라 TS6 순환을 회피한다.
22
+ *
23
+ * @template TDbContext - DbContext 타입
24
+ * @template TName - View 이름
25
+ * @template TData - View 데이터 레코드 타입
26
+ * @template TRelations - 관계 정의 레코드 타입 (무제약, 기본값 `{}`)
27
+ *
28
+ * @see {@link View} factory 함수
29
+ * @see {@link queryable} Queryable 생성
30
+ */
31
+ export class ViewBuilder<
32
+ TDbContext extends DbContextBase,
33
+ TName extends string,
34
+ TData extends DataRecord,
35
+ TRelations = {},
36
+ > {
37
+ /**
38
+ * 전체 타입 추론 (column + 관계).
39
+ *
40
+ * 관계는 `TRelations` 구조적으로 lazy walk 하여 다단계로 해소된다.
41
+ */
42
+ readonly $inferSelect!: TData & InferDeepRelations<TRelations>;
43
+
44
+ /**
45
+ * @param meta - View 메타데이터
46
+ * @param meta.name - View 이름
47
+ * @param meta.description - View 설명 (comment)
48
+ * @param meta.database - Database 이름
49
+ * @param meta.schema - Schema 이름 (MSSQL/PostgreSQL)
50
+ * @param meta.viewFn - View query 정의 함수
51
+ * @param meta.relations - 관계 정의 (런타임: `.relations(fn)` 호출 시 부착됨)
52
+ */
53
+ constructor(
54
+ readonly meta: {
55
+ name: TName;
56
+ description?: string;
57
+ database?: string;
58
+ schema?: string;
59
+ viewFn?: (db: TDbContext) => Queryable<TData, any>;
60
+ relations?: TRelations;
61
+ },
62
+ ) {}
63
+
64
+ /**
65
+ * View 설명 설정
66
+ *
67
+ * @param desc - View 설명 (DDL Comment로 사용됨)
68
+ * @returns ViewBuilder 인스턴스
69
+ */
70
+ description(desc: string): ViewBuilder<TDbContext, TName, TData, TRelations> {
71
+ return new ViewBuilder({ ...this.meta, description: desc });
72
+ }
73
+
74
+ /**
75
+ * Database 이름 설정
76
+ *
77
+ * @param db - Database 이름
78
+ * @returns ViewBuilder 인스턴스
79
+ */
80
+ database(db: string): ViewBuilder<TDbContext, TName, TData, TRelations> {
81
+ return new ViewBuilder({ ...this.meta, database: db });
82
+ }
83
+
84
+ /**
85
+ * Schema 이름 설정
86
+ *
87
+ * MSSQL, PostgreSQL에서 사용
88
+ *
89
+ * @param schema - Schema 이름 (MSSQL: dbo, PostgreSQL: public)
90
+ * @returns ViewBuilder 인스턴스
91
+ */
92
+ schema(schema: string): ViewBuilder<TDbContext, TName, TData, TRelations> {
93
+ return new ViewBuilder({ ...this.meta, schema });
94
+ }
95
+
96
+ /**
97
+ * View query 정의
98
+ *
99
+ * SELECT query 통해 View의 데이터 소스를 정의
100
+ *
101
+ * @template TViewData - View 데이터 타입
102
+ * @template TDb - DbContext 타입
103
+ * @param viewFn - DbContext를 받아 Queryable을 반환하는 함수
104
+ * @returns 새 ViewBuilder 인스턴스
105
+ */
106
+ query<TViewData extends DataRecord, TDb extends DbContextBase>(
107
+ viewFn: (db: TDb) => Queryable<TViewData, any>,
108
+ ): ViewBuilder<TDb, TName, TViewData, TRelations> {
109
+ return new ViewBuilder({ ...this.meta, viewFn });
110
+ }
111
+
112
+ /**
113
+ * 관계 정의 (RelationKey / RelationKeyTarget 만 사용 가능)
114
+ *
115
+ * 관계 타입 `T` **무제약**으로 추론되며, 내부적으로 런타임 결과를
116
+ * `meta.relations` 에 저장한다(`as any`). TS6 순환 회피.
117
+ *
118
+ * @template T - 관계 정의 레코드 타입 (무제약)
119
+ * @param fn - 관계 factory를 받아 관계 정의를 반환하는 함수
120
+ * @returns 관계가 부착된 새 ViewBuilder 인스턴스
121
+ */
122
+ relations<T>(
123
+ fn: (r: ViewRelationFactory<keyof TData & string>) => T,
124
+ ): ViewBuilder<TDbContext, TName, TData, T> {
125
+ return new ViewBuilder<TDbContext, TName, TData, T>({
126
+ ...this.meta,
127
+ relations: fn(createRelationFactory<keyof TData & string>()),
128
+ });
129
+ }
130
+ }
131
+
132
+ // ============================================
133
+ // View 함수
134
+ // ============================================
135
+
136
+ /**
137
+ * View builder factory 함수
138
+ *
139
+ * Fluent API로 View schema를 정의하기 위한 ViewBuilder 생성
140
+ *
141
+ * @param name - View 이름
142
+ * @returns ViewBuilder 인스턴스
143
+ *
144
+ * @see {@link ViewBuilder} builder 클래스
145
+ */
146
+ export function View<TName extends string>(name: TName) {
147
+ return new ViewBuilder<DbContextBase, TName, DataRecord, {}>({ name });
148
+ }
@@ -1,4 +1,4 @@
1
- import { DateOnly, DateTime, Time, Uuid, type Bytes } from "@simplysm/core-common";
1
+ import { primitive, type PrimitiveType, type PrimitiveTypeMap, type PrimitiveTypeStr } from "@simplysm/core-common";
2
2
 
3
3
  // ============================================
4
4
  // DataType (SQL 타입 정의)
@@ -45,31 +45,20 @@ export type DataType =
45
45
 
46
46
  /**
47
47
  * Column 원시 타입 매핑
48
- *
49
- * TypeScript 타입 이름 (문자열) → 실제 TypeScript 타입 매핑
50
48
  */
51
- export type ColumnPrimitiveMap = {
52
- string: string;
53
- number: number;
54
- boolean: boolean;
55
- DateTime: DateTime;
56
- DateOnly: DateOnly;
57
- Time: Time;
58
- Uuid: Uuid;
59
- Bytes: Bytes;
60
- };
49
+ export type ColumnPrimitiveMap = PrimitiveTypeMap;
61
50
 
62
51
  /**
63
52
  * Column 원시 타입 이름 (문자열)
64
53
  */
65
- export type ColumnPrimitiveStr = keyof ColumnPrimitiveMap;
54
+ export type ColumnPrimitiveStr = PrimitiveTypeStr;
66
55
 
67
56
  /**
68
57
  * Column에 저장 가능한 모든 원시 타입
69
58
  *
70
59
  * undefined는 NULL을 나타냄
71
60
  */
72
- export type ColumnPrimitive = ColumnPrimitiveMap[ColumnPrimitiveStr] | undefined;
61
+ export type ColumnPrimitive = PrimitiveType;
73
62
 
74
63
  // ============================================
75
64
  // DataType ↔ ColumnPrimitive Mapping
@@ -108,18 +97,10 @@ export type InferColumnPrimitiveFromDataType<TDataType extends DataType> =
108
97
  *
109
98
  * @param value - Column 값
110
99
  * @returns ColumnPrimitiveStr 타입 이름
111
- * @throws 값 타입이 알 수 없을 때 Error
100
+ * @throws 값 타입이 알 수 없을 때 ArgumentError
112
101
  */
113
- export function inferColumnPrimitiveStr(value: ColumnPrimitive): ColumnPrimitiveStr {
114
- if (typeof value === "string") return "string";
115
- if (typeof value === "number") return "number";
116
- if (typeof value === "boolean") return "boolean";
117
- if (value instanceof DateTime) return "DateTime";
118
- if (value instanceof DateOnly) return "DateOnly";
119
- if (value instanceof Time) return "Time";
120
- if (value instanceof Uuid) return "Uuid";
121
- if (value instanceof Uint8Array) return "Bytes";
122
- throw new Error("NULL 값으로는 타입을 추론할 수 없습니다.");
102
+ export function inferColumnPrimitiveStr(value: Exclude<ColumnPrimitive, undefined>): ColumnPrimitiveStr {
103
+ return primitive.typeStr(value);
123
104
  }
124
105
 
125
106
  // ============================================
@@ -14,7 +14,7 @@ import type { QueryDef, QueryDefObjectName } from "./query-def";
14
14
  * DbContext class가 이 인터페이스를 구현한다.
15
15
  */
16
16
  export interface DbContextBase {
17
- status: DbContextStatus;
17
+ readonly status: DbContextStatus;
18
18
  readonly database: string | undefined;
19
19
  readonly schema: string | undefined;
20
20
  getNextAlias(): string;
@@ -24,7 +24,7 @@ export interface DbContextBase {
24
24
  resultMetas?: (ResultMeta | undefined)[],
25
25
  ): Promise<T[][]>;
26
26
  getQueryDefObjectName(
27
- tableOrView: TableBuilder<any, any, any> | ViewBuilder<any, any, any>,
27
+ tableOrView: TableBuilder<any, any> | ViewBuilder<any, any, any>,
28
28
  ): QueryDefObjectName;
29
29
  switchFk(table: QueryDefObjectName, enabled: boolean): Promise<void>;
30
30
  }
@@ -32,7 +32,7 @@ export interface DbContextBase {
32
32
  export type DbContextStatus = "ready" | "connect" | "transact";
33
33
 
34
34
  export interface DbContextDdlMethods {
35
- createTable(table: TableBuilder<any, any, any>): Promise<void>;
35
+ createTable(table: TableBuilder<any, any>): Promise<void>;
36
36
  dropTable(table: QueryDefObjectName): Promise<void>;
37
37
  renameTable(table: QueryDefObjectName, newName: string): Promise<void>;
38
38
  createView(view: ViewBuilder<any, any, any>): Promise<void>;
@@ -56,7 +56,7 @@ export interface DbContextDdlMethods {
56
56
  addForeignKey(
57
57
  table: QueryDefObjectName,
58
58
  relationName: string,
59
- relationDef: ForeignKeyBuilder<any, any>,
59
+ relationDef: ForeignKeyBuilder<any>,
60
60
  ): Promise<void>;
61
61
  addIndex(table: QueryDefObjectName, indexBuilder: IndexBuilder<string[]>): Promise<void>;
62
62
  dropForeignKey(table: QueryDefObjectName, relationName: string): Promise<void>;
@@ -66,11 +66,11 @@ export interface DbContextDdlMethods {
66
66
  truncate(table: QueryDefObjectName): Promise<void>;
67
67
  switchFk(table: QueryDefObjectName, enabled: boolean): Promise<void>;
68
68
  // QueryDef 생성기
69
- getCreateTableQueryDef(table: TableBuilder<any, any, any>): QueryDef;
69
+ getCreateTableQueryDef(table: TableBuilder<any, any>): QueryDef;
70
70
  getCreateViewQueryDef(view: ViewBuilder<any, any, any>): QueryDef;
71
71
  getCreateProcQueryDef(procedure: ProcedureBuilder<any, any>): QueryDef;
72
72
  getCreateObjectQueryDef(
73
- builder: TableBuilder<any, any, any> | ViewBuilder<any, any, any> | ProcedureBuilder<any, any>,
73
+ builder: TableBuilder<any, any> | ViewBuilder<any, any, any> | ProcedureBuilder<any, any>,
74
74
  ): QueryDef;
75
75
  getDropTableQueryDef(table: QueryDefObjectName): QueryDef;
76
76
  getRenameTableQueryDef(table: QueryDefObjectName, newName: string): QueryDef;
@@ -93,7 +93,7 @@ export interface DbContextDdlMethods {
93
93
  getAddForeignKeyQueryDef(
94
94
  table: QueryDefObjectName,
95
95
  relationName: string,
96
- relationDef: ForeignKeyBuilder<any, any>,
96
+ relationDef: ForeignKeyBuilder<any>,
97
97
  ): QueryDef;
98
98
  getAddIndexQueryDef(table: QueryDefObjectName, indexBuilder: IndexBuilder<string[]>): QueryDef;
99
99
  getDropForeignKeyQueryDef(table: QueryDefObjectName, relationName: string): QueryDef;
@@ -351,7 +351,7 @@ export interface CreateProcQueryDef {
351
351
  name: string;
352
352
  dataType: DataType;
353
353
  nullable?: boolean;
354
- default?: unknown;
354
+ default?: ColumnPrimitive;
355
355
  }>;
356
356
  returns?: Array<{
357
357
  name: string;
@@ -1,9 +1,7 @@
1
- import { bytes, obj, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
1
+ import { bytes, obj, wait, DateOnly, DateTime, Time, Uuid } from "@simplysm/core-common";
2
2
  import type { ColumnPrimitiveStr } from "../types/column";
3
3
  import type { ResultMeta } from "../types/db";
4
4
 
5
- declare function setImmediate(callback: () => void): void;
6
-
7
5
  // ============================================
8
6
  // 타입 파서
9
7
  // ============================================
@@ -164,12 +162,6 @@ function isEmptyJoinObject(record: Record<string, unknown>): boolean {
164
162
  /** 양보 간격: N개 레코드마다 이벤트 루프에 양보 */
165
163
  const YIELD_INTERVAL = 100;
166
164
 
167
- /** 이벤트 루프 양보: Node.js는 setImmediate, 브라우저는 setTimeout 폴백 */
168
- const yieldToEventLoop: () => Promise<void> =
169
- typeof setImmediate !== "undefined"
170
- ? () => new Promise<void>((resolve) => setImmediate(resolve))
171
- : () => new Promise<void>((resolve) => setTimeout(resolve, 0));
172
-
173
165
  /**
174
166
  * ResultMeta를 통해 DB 쿼리 결과를 TypeScript 객체로 변환
175
167
  *
@@ -197,27 +189,27 @@ export async function parseQueryResult<TRecord>(
197
189
 
198
190
  // JOIN 없음: 단순 타입 파싱만 수행
199
191
  if (joinKeys.length === 0) {
200
- return parseSimpleRecords<TRecord>(rawResults, meta.columns);
192
+ return parseSimpleRecords(rawResults, meta.columns) as Promise<TRecord[] | undefined>;
201
193
  }
202
194
 
203
195
  // JOIN 있음: 그룹핑 + 중첩
204
- return parseJoinedRecords<TRecord>(rawResults, meta);
196
+ return parseJoinedRecords(rawResults, meta) as Promise<TRecord[] | undefined>;
205
197
  }
206
198
 
207
199
  /**
208
200
  * JOIN이 없는 단순 레코드 파싱
209
201
  */
210
- async function parseSimpleRecords<TRecord>(
202
+ async function parseSimpleRecords(
211
203
  rawResults: Record<string, unknown>[],
212
204
  columns: Record<string, ColumnPrimitiveStr>,
213
- ): Promise<TRecord[] | undefined> {
205
+ ): Promise<Record<string, unknown>[] | undefined> {
214
206
  const columnInfos = buildColumnInfos(columns);
215
207
  const results: Record<string, unknown>[] = [];
216
208
 
217
209
  for (let i = 0; i < rawResults.length; i++) {
218
210
  // 이벤트 루프에 양보
219
211
  if (i > 0 && i % YIELD_INTERVAL === 0) {
220
- await yieldToEventLoop();
212
+ await wait.immediate();
221
213
  }
222
214
 
223
215
  const parsed = flatToNested(rawResults[i], columnInfos);
@@ -229,7 +221,7 @@ async function parseSimpleRecords<TRecord>(
229
221
  }
230
222
 
231
223
  // 빈 배열은 undefined 반환
232
- return results.length > 0 ? (results as TRecord[]) : undefined;
224
+ return results.length > 0 ? results : undefined;
233
225
  }
234
226
 
235
227
  /**
@@ -247,16 +239,16 @@ function sortJoinKeysByDepth(joinKeys: string[]): string[] {
247
239
  /**
248
240
  * JOIN이 있는 레코드 파싱 (재귀 그룹핑)
249
241
  */
250
- async function parseJoinedRecords<TRecord>(
242
+ async function parseJoinedRecords(
251
243
  rawResults: Record<string, unknown>[],
252
244
  meta: ResultMeta,
253
- ): Promise<TRecord[] | undefined> {
245
+ ): Promise<Record<string, unknown>[] | undefined> {
254
246
  // 1. 모든 레코드를 중첩 구조로 변환
255
247
  const columnInfos = buildColumnInfos(meta.columns);
256
248
  const nestedRecords: Record<string, unknown>[] = [];
257
249
  for (let i = 0; i < rawResults.length; i++) {
258
250
  if (i > 0 && i % YIELD_INTERVAL === 0) {
259
- await yieldToEventLoop();
251
+ await wait.immediate();
260
252
  }
261
253
  nestedRecords.push(flatToNested(rawResults[i], columnInfos));
262
254
  }
@@ -270,7 +262,7 @@ async function parseJoinedRecords<TRecord>(
270
262
  // 4. 빈 결과 필터링
271
263
  const filteredResults = results.filter((r) => !isEmptyObject(r));
272
264
 
273
- return filteredResults.length > 0 ? (filteredResults as TRecord[]) : undefined;
265
+ return filteredResults.length > 0 ? filteredResults : undefined;
274
266
  }
275
267
 
276
268
  /**