sonamu 0.7.14 → 0.7.16
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.
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +4 -3
- package/dist/database/base-model.d.ts +16 -6
- package/dist/database/base-model.d.ts.map +1 -1
- package/dist/database/base-model.js +44 -3
- package/dist/database/base-model.types.d.ts +29 -48
- package/dist/database/base-model.types.d.ts.map +1 -1
- package/dist/database/base-model.types.js +12 -2
- package/dist/database/puri.d.ts +2 -1
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +2 -1
- package/dist/database/puri.types.d.ts +3 -3
- package/dist/database/puri.types.d.ts.map +1 -1
- package/dist/database/puri.types.js +1 -1
- package/dist/entity/entity-manager.d.ts +8 -4
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity.d.ts +10 -1
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +84 -39
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/tasks/workflow-manager.d.ts +3 -3
- package/dist/tasks/workflow-manager.d.ts.map +1 -1
- package/dist/tasks/workflow-manager.js +15 -11
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +8 -6
- package/dist/types/types.d.ts +41 -11
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +27 -3
- package/dist/ui/api.d.ts.map +1 -1
- package/dist/ui/api.js +12 -3
- package/dist/ui-web/assets/{index-J9MCfjCd.js → index-BcbbB-BB.js} +42 -42
- package/dist/ui-web/index.html +1 -1
- package/package.json +3 -3
- package/src/api/sonamu.ts +3 -2
- package/src/database/base-model.ts +66 -11
- package/src/database/base-model.types.ts +79 -76
- package/src/database/puri.ts +5 -1
- package/src/database/puri.types.ts +3 -6
- package/src/entity/entity.ts +83 -34
- package/src/index.ts +1 -0
- package/src/tasks/workflow-manager.ts +16 -12
- package/src/template/implementations/generated.template.ts +17 -3
- package/src/types/types.ts +31 -2
- package/src/ui/api.ts +11 -2
package/dist/ui-web/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>{{projectName}}: Sonamu UI</title>
|
|
7
|
-
<script type="module" crossorigin src="/sonamu-ui/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/sonamu-ui/assets/index-BcbbB-BB.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/sonamu-ui/assets/index-CpaB9P6g.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonamu",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.16",
|
|
4
4
|
"description": "Sonamu — TypeScript Fullstack API Framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -81,10 +81,10 @@
|
|
|
81
81
|
"tsicli": "^1.0.5",
|
|
82
82
|
"vitest": "^4.0.10",
|
|
83
83
|
"zod": "^4.1.12",
|
|
84
|
+
"@sonamu-kit/hmr-hook": "^0.4.1",
|
|
84
85
|
"@sonamu-kit/hmr-runner": "^0.1.1",
|
|
85
|
-
"@sonamu-kit/tasks": "^0.0.1",
|
|
86
86
|
"@sonamu-kit/ts-loader": "^2.1.3",
|
|
87
|
-
"@sonamu-kit/
|
|
87
|
+
"@sonamu-kit/tasks": "^0.1.1"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@biomejs/biome": "^2.3.7",
|
package/src/api/sonamu.ts
CHANGED
|
@@ -595,7 +595,7 @@ class SonamuClass {
|
|
|
595
595
|
private async initializeWorkflows(options: SonamuTaskOptions | undefined) {
|
|
596
596
|
const { WorkflowManager } = await import("../tasks/workflow-manager");
|
|
597
597
|
// NOTE: @sonamu-kit/tasks 안에선 knex config를 수정하기 때문에 connection이 아닌 config 째로 보냅니다.
|
|
598
|
-
this._workflows =
|
|
598
|
+
this._workflows = new WorkflowManager(DB.getDBConfig("w"));
|
|
599
599
|
if (!options) {
|
|
600
600
|
return;
|
|
601
601
|
}
|
|
@@ -608,7 +608,7 @@ class SonamuClass {
|
|
|
608
608
|
};
|
|
609
609
|
|
|
610
610
|
if (enableWorker) {
|
|
611
|
-
|
|
611
|
+
this.workflows.setupWorker({
|
|
612
612
|
...defaultWorkerOptions,
|
|
613
613
|
...options.workerOptions,
|
|
614
614
|
});
|
|
@@ -645,6 +645,7 @@ class SonamuClass {
|
|
|
645
645
|
server
|
|
646
646
|
.listen({ port, host })
|
|
647
647
|
.then(async () => {
|
|
648
|
+
await this.workflows.startWorker();
|
|
648
649
|
await options.lifecycle?.onStart?.(server);
|
|
649
650
|
})
|
|
650
651
|
.catch(async (err) => {
|
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
/** biome-ignore-all lint/suspicious/noExplicitAny: Puri의 타입은 개별 모델에서 확정되므로 BaseModel에서는 any를 허용함 */
|
|
2
2
|
|
|
3
3
|
import type { Knex } from "knex";
|
|
4
|
-
import { group, isObject, omit, set } from "radashi";
|
|
4
|
+
import { cloneDeep, group, isObject, omit, set } from "radashi";
|
|
5
5
|
import type { ListResult } from "..";
|
|
6
6
|
import { Sonamu } from "../api";
|
|
7
|
+
import { EntityManager } from "../entity/entity-manager";
|
|
7
8
|
import type { DatabaseSchemaExtend, SonamuQueryMode } from "../types/types";
|
|
8
9
|
import { getJoinTables, getTableNamesFromWhere } from "../utils/sql-parser";
|
|
9
10
|
import { chunk } from "../utils/utils";
|
|
10
|
-
import type {
|
|
11
|
-
EnhancerMap,
|
|
12
|
-
ResolveSubsetIntersection,
|
|
13
|
-
UnionExtractedTTables,
|
|
14
|
-
} from "./base-model.types";
|
|
11
|
+
import type { EnhancerMap, ResolveSubsetIntersection } from "./base-model.types";
|
|
15
12
|
import type { DBPreset } from "./db";
|
|
16
13
|
import { DB } from "./db";
|
|
17
14
|
import { Puri } from "./puri";
|
|
15
|
+
import type { UnionExtractedTTables } from "./puri.types";
|
|
18
16
|
import type { InferAllSubsets, PuriLoaderQueries, PuriSubsetFn } from "./puri-subset.types";
|
|
19
17
|
import { PuriWrapper } from "./puri-wrapper";
|
|
20
18
|
import { UpsertBuilder } from "./upsert-builder";
|
|
@@ -137,7 +135,12 @@ export class BaseModelClass<
|
|
|
137
135
|
* 타입 검증 및 추론을 도와줌
|
|
138
136
|
*/
|
|
139
137
|
createEnhancers<T extends TSubsetKey>(
|
|
140
|
-
enhancers: EnhancerMap<
|
|
138
|
+
enhancers: EnhancerMap<
|
|
139
|
+
T,
|
|
140
|
+
InferAllSubsets<TSubsetQueries, TLoaderQueries>,
|
|
141
|
+
TSubsetMapping,
|
|
142
|
+
TSubsetQueries
|
|
143
|
+
>,
|
|
141
144
|
) {
|
|
142
145
|
return enhancers;
|
|
143
146
|
}
|
|
@@ -169,7 +172,7 @@ export class BaseModelClass<
|
|
|
169
172
|
};
|
|
170
173
|
debug?: boolean;
|
|
171
174
|
optimizeCountQuery?: boolean;
|
|
172
|
-
} & EnhancerParam<TSubsetKey, TComputedResults, TSubsetMapping>,
|
|
175
|
+
} & EnhancerParam<TSubsetKey, TComputedResults, TSubsetMapping, TSubsetQueries>,
|
|
173
176
|
): Promise<ListResult<LP, TSubsetMapping[T]>> {
|
|
174
177
|
const { subset, qb, params: queryParams, debug = false, optimizeCountQuery = false } = params;
|
|
175
178
|
|
|
@@ -191,10 +194,18 @@ export class BaseModelClass<
|
|
|
191
194
|
|
|
192
195
|
// Enhancer 적용
|
|
193
196
|
const enhancer = (params as any).enhancers?.[subset];
|
|
194
|
-
const
|
|
197
|
+
const enhancedRows = (await Promise.all(
|
|
195
198
|
computedRows.map((row) => enhancer?.(row) ?? row),
|
|
196
199
|
)) as TSubsetMapping[T][];
|
|
197
200
|
|
|
201
|
+
// Internal 필드 제거
|
|
202
|
+
const entity = EntityManager.get(this.modelName);
|
|
203
|
+
const internalFields = entity.subsetsInternal[subset] ?? [];
|
|
204
|
+
const rows =
|
|
205
|
+
internalFields.length > 0
|
|
206
|
+
? enhancedRows.map((row) => this.omitInternalFields(row, internalFields))
|
|
207
|
+
: enhancedRows;
|
|
208
|
+
|
|
198
209
|
if (queryParams.queryMode === "list") {
|
|
199
210
|
// 리스트만 리턴
|
|
200
211
|
return { rows } as ListResult<LP, TSubsetMapping[T]>;
|
|
@@ -204,6 +215,49 @@ export class BaseModelClass<
|
|
|
204
215
|
}
|
|
205
216
|
}
|
|
206
217
|
|
|
218
|
+
/**
|
|
219
|
+
* 객체에서 internal 필드 제거
|
|
220
|
+
* 중첩 필드(예: "user.email") 및 배열(예: "employees.salary")도 처리
|
|
221
|
+
*/
|
|
222
|
+
omitInternalFields<T extends object>(row: T, fields: string[]): T {
|
|
223
|
+
const result = cloneDeep(row);
|
|
224
|
+
for (const field of fields) {
|
|
225
|
+
this.deleteField(result, field.split("."));
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* 중첩 필드 삭제 (배열 내 객체도 처리)
|
|
232
|
+
*/
|
|
233
|
+
deleteField(obj: any, parts: string[]): void {
|
|
234
|
+
if (!obj || typeof obj !== "object") {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (parts.length === 1) {
|
|
239
|
+
if (Array.isArray(obj)) {
|
|
240
|
+
obj.forEach((item) => {
|
|
241
|
+
if (item && typeof item === "object") {
|
|
242
|
+
delete item[parts[0]];
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
} else {
|
|
246
|
+
delete obj[parts[0]];
|
|
247
|
+
}
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const [first, ...rest] = parts;
|
|
252
|
+
const next = obj[first];
|
|
253
|
+
|
|
254
|
+
if (Array.isArray(next)) {
|
|
255
|
+
next.map((item) => this.deleteField(item, rest));
|
|
256
|
+
} else if (next && typeof next === "object") {
|
|
257
|
+
this.deleteField(next, rest);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
207
261
|
/**
|
|
208
262
|
* COUNT 쿼리 실행 (내부 메서드)
|
|
209
263
|
*/
|
|
@@ -401,9 +455,10 @@ type EnhancerParam<
|
|
|
401
455
|
TSubsetKey extends string,
|
|
402
456
|
TComputedResults extends Record<TSubsetKey, any>,
|
|
403
457
|
TSubsetMapping extends Record<TSubsetKey, any>,
|
|
458
|
+
TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
|
|
404
459
|
> = [RequiredEnhancerKeys<TSubsetKey, TComputedResults, TSubsetMapping>] extends [never]
|
|
405
|
-
? { enhancers?: EnhancerMap<TSubsetKey, TComputedResults, TSubsetMapping> }
|
|
406
|
-
: { enhancers: EnhancerMap<TSubsetKey, TComputedResults, TSubsetMapping> };
|
|
460
|
+
? { enhancers?: EnhancerMap<TSubsetKey, TComputedResults, TSubsetMapping, TSubsetQueries> }
|
|
461
|
+
: { enhancers: EnhancerMap<TSubsetKey, TComputedResults, TSubsetMapping, TSubsetQueries> };
|
|
407
462
|
|
|
408
463
|
type RequiredEnhancerKeys<
|
|
409
464
|
TSubsetKey extends string,
|
|
@@ -7,29 +7,11 @@
|
|
|
7
7
|
* Enhancer, SubsetQuery 교집합 등 Model 계층에서 필요한 타입 정의.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import type { ListResult } from "..";
|
|
11
10
|
import type { DatabaseSchemaExtend } from "../types/types";
|
|
12
11
|
import type { Puri } from "./puri";
|
|
12
|
+
import type { ExtractTTables } from "./puri.types";
|
|
13
13
|
import type { PuriSubsetFn } from "./puri-subset.types";
|
|
14
14
|
|
|
15
|
-
// ============================================================================
|
|
16
|
-
// Puri 테이블 추출 유틸리티
|
|
17
|
-
// ============================================================================
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Puri 인스턴스에서 TTables 타입 추출
|
|
21
|
-
*/
|
|
22
|
-
export type ExtractPuriTables<T> = T extends Puri<any, infer TTables, any> ? TTables : never;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* SubsetQueries에서 모든 TTables의 유니온 추출
|
|
26
|
-
* getSubsetQueries의 qb 타입 정의에 사용
|
|
27
|
-
*/
|
|
28
|
-
export type UnionExtractedTTables<
|
|
29
|
-
TSubsetKey extends string,
|
|
30
|
-
TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
|
|
31
|
-
> = ExtractPuriTables<ReturnType<TSubsetQueries[TSubsetKey]>>;
|
|
32
|
-
|
|
33
15
|
// ============================================================================
|
|
34
16
|
// Subset 교집합 계산 (onSubset 메서드용)
|
|
35
17
|
// ============================================================================
|
|
@@ -37,11 +19,12 @@ export type UnionExtractedTTables<
|
|
|
37
19
|
/**
|
|
38
20
|
* 두 Puri의 테이블 교집합을 가진 새로운 Puri 생성
|
|
39
21
|
*/
|
|
40
|
-
type MergePuriTables<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
22
|
+
type MergePuriTables<
|
|
23
|
+
A extends Puri<any, any, any>,
|
|
24
|
+
B extends Puri<any, any, any>,
|
|
25
|
+
TA = ExtractTTables<A>,
|
|
26
|
+
TB = ExtractTTables<B>,
|
|
27
|
+
> = Puri<DatabaseSchemaExtend, Pick<TA, Extract<keyof TA, keyof TB>>, any>;
|
|
45
28
|
|
|
46
29
|
/**
|
|
47
30
|
* 서브셋 키 배열을 순회하며 테이블 교집합 Puri 계산
|
|
@@ -62,24 +45,79 @@ export type ResolveSubsetIntersection<
|
|
|
62
45
|
// Enhancer
|
|
63
46
|
// ============================================================================
|
|
64
47
|
|
|
48
|
+
/**
|
|
49
|
+
* SubsetQueries의 Puri 반환 타입에서 TTables를 추출하고,
|
|
50
|
+
* TTables의 키 중 DatabaseSchemaExtend의 키와 일치하는 것이 메인 테이블.
|
|
51
|
+
* 해당 테이블의 BaseSchema에서 __virtual_query__ 키를 추출.
|
|
52
|
+
*/
|
|
53
|
+
type ExtractMainTable<TSubsetQueries extends Record<string, PuriSubsetFn>> = Extract<
|
|
54
|
+
keyof ExtractTTables<ReturnType<TSubsetQueries[keyof TSubsetQueries]>>,
|
|
55
|
+
keyof DatabaseSchemaExtend
|
|
56
|
+
>;
|
|
57
|
+
|
|
58
|
+
type ExtractVirtualQueryKeys<TSubsetQueries extends Record<string, PuriSubsetFn>> =
|
|
59
|
+
ExtractMainTable<TSubsetQueries> extends infer TTable extends keyof DatabaseSchemaExtend
|
|
60
|
+
? DatabaseSchemaExtend[TTable] extends { __virtual_query__: readonly (infer K)[] }
|
|
61
|
+
? K
|
|
62
|
+
: never
|
|
63
|
+
: never;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* TSubsetMapping에서 virtualQuery 키를 optional로 만든 타입
|
|
67
|
+
* Enhancer 필수 여부 판단 시 사용
|
|
68
|
+
*/
|
|
69
|
+
type OmitVirtualQueryFromMapping<TMapping, TVirtualQueryKeys> = Omit<
|
|
70
|
+
TMapping,
|
|
71
|
+
TVirtualQueryKeys & keyof TMapping
|
|
72
|
+
> &
|
|
73
|
+
Partial<Pick<TMapping, TVirtualQueryKeys & keyof TMapping>>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Computed가 Mapping에 호환되는지 판단 (virtualQuery 키 제외)
|
|
77
|
+
*/
|
|
78
|
+
type IsEnhancerOptional<
|
|
79
|
+
TSubsetKey extends string,
|
|
80
|
+
TComputedResults extends Record<TSubsetKey, any>,
|
|
81
|
+
TSubsetMapping extends Record<TSubsetKey, any>,
|
|
82
|
+
TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
|
|
83
|
+
K extends TSubsetKey,
|
|
84
|
+
> = TComputedResults[K] extends OmitVirtualQueryFromMapping<
|
|
85
|
+
TSubsetMapping[K],
|
|
86
|
+
ExtractVirtualQueryKeys<TSubsetQueries>
|
|
87
|
+
>
|
|
88
|
+
? true
|
|
89
|
+
: false;
|
|
90
|
+
|
|
65
91
|
/**
|
|
66
92
|
* 단일 Enhancer 함수 타입
|
|
67
|
-
* computed
|
|
93
|
+
* computed 결과 + virtualQuery props를 받아 최종 mapping 타입으로 변환
|
|
68
94
|
*/
|
|
69
|
-
|
|
95
|
+
type EnhancerFnWithVirtualQuery<TComputed, TMapping, TVirtualQueryKeys> = (
|
|
96
|
+
row: TComputed & Pick<TMapping, TVirtualQueryKeys & keyof TMapping>,
|
|
97
|
+
) => TMapping | Promise<TMapping>;
|
|
70
98
|
|
|
71
99
|
/**
|
|
72
100
|
* Enhancer가 필수인 SubsetKey 추출
|
|
73
101
|
*
|
|
74
102
|
* ComputedResults[K]가 SubsetMapping[K]에 할당 불가능하면 해당 K는 필수
|
|
75
103
|
* (즉, virtual 필드 등 추가 변환이 필요한 경우)
|
|
104
|
+
* 단, virtualQuery 키는 무시 (사용자가 appendSelect로 직접 추가)
|
|
76
105
|
*/
|
|
77
106
|
export type RequiredEnhancerKeys<
|
|
78
107
|
TSubsetKey extends string,
|
|
79
108
|
TComputedResults extends Record<TSubsetKey, any>,
|
|
80
109
|
TSubsetMapping extends Record<TSubsetKey, any>,
|
|
110
|
+
TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
|
|
81
111
|
> = {
|
|
82
|
-
[K in TSubsetKey]:
|
|
112
|
+
[K in TSubsetKey]: IsEnhancerOptional<
|
|
113
|
+
TSubsetKey,
|
|
114
|
+
TComputedResults,
|
|
115
|
+
TSubsetMapping,
|
|
116
|
+
TSubsetQueries,
|
|
117
|
+
K
|
|
118
|
+
> extends true
|
|
119
|
+
? never
|
|
120
|
+
: K;
|
|
83
121
|
}[TSubsetKey];
|
|
84
122
|
|
|
85
123
|
/**
|
|
@@ -87,6 +125,7 @@ export type RequiredEnhancerKeys<
|
|
|
87
125
|
*
|
|
88
126
|
* - ComputedResults[K]가 SubsetMapping[K]에 assignable하면 → enhancer 선택적
|
|
89
127
|
* - 그렇지 않으면 → enhancer 필수
|
|
128
|
+
* - 단, virtualQuery 키는 무시 (사용자가 appendSelect로 직접 추가)
|
|
90
129
|
*
|
|
91
130
|
* @example
|
|
92
131
|
* // virtual 필드 employee_count가 있는 경우
|
|
@@ -98,59 +137,23 @@ export type EnhancerMap<
|
|
|
98
137
|
TSubsetKey extends string,
|
|
99
138
|
TComputedResults extends Record<TSubsetKey, any>,
|
|
100
139
|
TSubsetMapping extends Record<TSubsetKey, any>,
|
|
140
|
+
TSubsetQueries extends Record<TSubsetKey, PuriSubsetFn>,
|
|
141
|
+
TRequiredKeys extends TSubsetKey = RequiredEnhancerKeys<
|
|
142
|
+
TSubsetKey,
|
|
143
|
+
TComputedResults,
|
|
144
|
+
TSubsetMapping,
|
|
145
|
+
TSubsetQueries
|
|
146
|
+
>,
|
|
101
147
|
> = {
|
|
102
|
-
|
|
103
|
-
[K in TSubsetKey as TComputedResults[K] extends TSubsetMapping[K] ? K : never]?: EnhancerFn<
|
|
148
|
+
[K in Exclude<TSubsetKey, TRequiredKeys>]?: EnhancerFnWithVirtualQuery<
|
|
104
149
|
TComputedResults[K],
|
|
105
|
-
TSubsetMapping[K]
|
|
150
|
+
TSubsetMapping[K],
|
|
151
|
+
ExtractVirtualQueryKeys<TSubsetQueries>
|
|
106
152
|
>;
|
|
107
153
|
} & {
|
|
108
|
-
|
|
109
|
-
[K in TSubsetKey as TComputedResults[K] extends TSubsetMapping[K] ? never : K]: EnhancerFn<
|
|
154
|
+
[K in TRequiredKeys]: EnhancerFnWithVirtualQuery<
|
|
110
155
|
TComputedResults[K],
|
|
111
|
-
TSubsetMapping[K]
|
|
156
|
+
TSubsetMapping[K],
|
|
157
|
+
ExtractVirtualQueryKeys<TSubsetQueries>
|
|
112
158
|
>;
|
|
113
159
|
};
|
|
114
|
-
|
|
115
|
-
// ============================================================================
|
|
116
|
-
// executeSubsetQuery
|
|
117
|
-
// ============================================================================
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* executeSubsetQuery 기본 파라미터
|
|
121
|
-
*/
|
|
122
|
-
export type ExecuteSubsetQueryBaseParams<TSubsetKey extends string> = {
|
|
123
|
-
subset: TSubsetKey;
|
|
124
|
-
qb: Puri<any, any, any>;
|
|
125
|
-
params: {
|
|
126
|
-
num?: number;
|
|
127
|
-
page?: number;
|
|
128
|
-
queryMode?: "list" | "count" | "both";
|
|
129
|
-
};
|
|
130
|
-
debug?: boolean;
|
|
131
|
-
optimizeCountQuery?: boolean;
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* executeSubsetQuery 파라미터 (Enhancer 포함)
|
|
136
|
-
*
|
|
137
|
-
* RequiredEnhancerKeys가 없으면 enhancers 선택적, 있으면 필수
|
|
138
|
-
*/
|
|
139
|
-
export type ExecuteSubsetQueryParams<
|
|
140
|
-
TSubsetKey extends string,
|
|
141
|
-
TComputedResults extends Record<TSubsetKey, any>,
|
|
142
|
-
TSubsetMapping extends Record<TSubsetKey, any>,
|
|
143
|
-
T extends TSubsetKey,
|
|
144
|
-
> = ExecuteSubsetQueryBaseParams<T> &
|
|
145
|
-
([RequiredEnhancerKeys<TSubsetKey, TComputedResults, TSubsetMapping>] extends [never]
|
|
146
|
-
? { enhancers?: EnhancerMap<TSubsetKey, TComputedResults, TSubsetMapping> }
|
|
147
|
-
: { enhancers: EnhancerMap<TSubsetKey, TComputedResults, TSubsetMapping> });
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* executeSubsetQuery 반환 타입
|
|
151
|
-
*/
|
|
152
|
-
export type ExecuteSubsetQueryResult<
|
|
153
|
-
TSubsetMapping extends Record<string, any>,
|
|
154
|
-
T extends string,
|
|
155
|
-
LP extends { queryMode?: "list" | "count" | "both" },
|
|
156
|
-
> = ListResult<LP, TSubsetMapping[T]>;
|
package/src/database/puri.ts
CHANGED
|
@@ -1205,12 +1205,14 @@ export class JoinClauseGroup<
|
|
|
1205
1205
|
TResolved: 쿼리 실행 후 반환될 결과 타입
|
|
1206
1206
|
TReturning: RETURNING 절에 사용될 타입
|
|
1207
1207
|
*/
|
|
1208
|
-
export class ResolvedPuri<TResolved, TReturning> {
|
|
1208
|
+
export class ResolvedPuri<TResolved, TReturning> implements Promise<TResolved> {
|
|
1209
1209
|
constructor(
|
|
1210
1210
|
public knexQuery: Knex.QueryBuilder,
|
|
1211
1211
|
private knex: Knex,
|
|
1212
1212
|
) {}
|
|
1213
1213
|
|
|
1214
|
+
[Symbol.toStringTag]: string = "Promise";
|
|
1215
|
+
|
|
1214
1216
|
toQuery(): string {
|
|
1215
1217
|
return this.knexQuery.toQuery();
|
|
1216
1218
|
}
|
|
@@ -1227,11 +1229,13 @@ export class ResolvedPuri<TResolved, TReturning> {
|
|
|
1227
1229
|
Naite.t("puri:executed-query", this.toQuery());
|
|
1228
1230
|
return this.knexQuery.then(onfulfilled as any, onrejected);
|
|
1229
1231
|
}
|
|
1232
|
+
|
|
1230
1233
|
catch<TResult2 = never>(
|
|
1231
1234
|
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
|
|
1232
1235
|
): Promise<TResolved | TResult2> {
|
|
1233
1236
|
return this.knexQuery.catch(onrejected);
|
|
1234
1237
|
}
|
|
1238
|
+
|
|
1235
1239
|
finally(onfinally?: (() => void) | null): Promise<TResolved> {
|
|
1236
1240
|
return this.knexQuery.finally(onfinally);
|
|
1237
1241
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import type { QueryResult } from "pg";
|
|
4
4
|
import type { DatabaseForeignKeys, DatabaseSchemaExtend } from "../types/types";
|
|
5
5
|
import type { Puri } from "./puri";
|
|
6
|
-
import type {
|
|
6
|
+
import type { PuriSubsetFn } from "./puri-subset.types";
|
|
7
7
|
|
|
8
8
|
// ============================================
|
|
9
9
|
// 내부 타입 키 (메타데이터)
|
|
@@ -342,15 +342,12 @@ export type InsertData<T> = Omit<
|
|
|
342
342
|
export type InsertResult = Pick<QueryResult<any>, "command" | "rowCount" | "rows" | "oid">;
|
|
343
343
|
|
|
344
344
|
// SubsetQuery를 위한 타입 유틸리티
|
|
345
|
-
type ExtractTTables<T extends Puri<any, any, any>> = T extends Puri<any, infer TTables, any>
|
|
345
|
+
export type ExtractTTables<T extends Puri<any, any, any>> = T extends Puri<any, infer TTables, any>
|
|
346
346
|
? TTables
|
|
347
347
|
: never;
|
|
348
348
|
export type UnionExtractedTTables<
|
|
349
349
|
SubsetKey extends string,
|
|
350
|
-
SubsetQueries extends Record<
|
|
351
|
-
SubsetKey,
|
|
352
|
-
(qbWrapper: PuriWrapper<DatabaseSchemaExtend>) => Puri<any, any, any>
|
|
353
|
-
>,
|
|
350
|
+
SubsetQueries extends Record<SubsetKey, PuriSubsetFn>,
|
|
354
351
|
> = {
|
|
355
352
|
[K in SubsetKey]: ExtractTTables<ReturnType<SubsetQueries[K]>>;
|
|
356
353
|
}[SubsetKey];
|