sonamu 0.7.53 → 0.8.0
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/config.d.ts +9 -1
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +1 -1
- package/dist/api/sonamu.d.ts +21 -1
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +159 -65
- package/dist/auth/plugins/entity-definitions/anonymous.d.ts +10 -0
- package/dist/auth/plugins/entity-definitions/anonymous.d.ts.map +1 -0
- package/dist/auth/plugins/entity-definitions/anonymous.js +23 -0
- package/dist/auth/plugins/entity-definitions/api-key.d.ts +9 -0
- package/dist/auth/plugins/entity-definitions/api-key.d.ts.map +1 -0
- package/dist/auth/plugins/entity-definitions/api-key.js +199 -0
- package/dist/auth/plugins/entity-definitions/index.d.ts +6 -0
- package/dist/auth/plugins/entity-definitions/index.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/index.js +20 -2
- package/dist/auth/plugins/entity-definitions/jwt.d.ts +9 -0
- package/dist/auth/plugins/entity-definitions/jwt.d.ts.map +1 -0
- package/dist/auth/plugins/entity-definitions/jwt.js +67 -0
- package/dist/auth/plugins/entity-definitions/organization.d.ts +9 -0
- package/dist/auth/plugins/entity-definitions/organization.d.ts.map +1 -0
- package/dist/auth/plugins/entity-definitions/organization.js +424 -0
- package/dist/auth/plugins/entity-definitions/passkey.d.ts +10 -0
- package/dist/auth/plugins/entity-definitions/passkey.d.ts.map +1 -0
- package/dist/auth/plugins/entity-definitions/passkey.js +129 -0
- package/dist/auth/plugins/entity-definitions/sso.d.ts +10 -0
- package/dist/auth/plugins/entity-definitions/sso.d.ts.map +1 -0
- package/dist/auth/plugins/entity-definitions/sso.js +110 -0
- package/dist/auth/plugins/entity-definitions/types.d.ts +1 -1
- package/dist/auth/plugins/entity-definitions/types.d.ts.map +1 -1
- package/dist/auth/plugins/entity-definitions/types.js +1 -1
- package/dist/auth/plugins/wrappers/admin.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/admin.js +2 -4
- package/dist/auth/plugins/wrappers/anonymous.d.ts +18 -0
- package/dist/auth/plugins/wrappers/anonymous.d.ts.map +1 -0
- package/dist/auth/plugins/wrappers/anonymous.js +26 -0
- package/dist/auth/plugins/wrappers/api-key.d.ts +18 -0
- package/dist/auth/plugins/wrappers/api-key.d.ts.map +1 -0
- package/dist/auth/plugins/wrappers/api-key.js +38 -0
- package/dist/auth/plugins/wrappers/index.d.ts +6 -0
- package/dist/auth/plugins/wrappers/index.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/index.js +7 -1
- package/dist/auth/plugins/wrappers/jwt.d.ts +18 -0
- package/dist/auth/plugins/wrappers/jwt.d.ts.map +1 -0
- package/dist/auth/plugins/wrappers/jwt.js +30 -0
- package/dist/auth/plugins/wrappers/organization.d.ts +18 -0
- package/dist/auth/plugins/wrappers/organization.d.ts.map +1 -0
- package/dist/auth/plugins/wrappers/organization.js +67 -0
- package/dist/auth/plugins/wrappers/passkey.d.ts +18 -0
- package/dist/auth/plugins/wrappers/passkey.d.ts.map +1 -0
- package/dist/auth/plugins/wrappers/passkey.js +32 -0
- package/dist/auth/plugins/wrappers/phone-number.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/phone-number.js +2 -4
- package/dist/auth/plugins/wrappers/sso.d.ts +853 -0
- package/dist/auth/plugins/wrappers/sso.d.ts.map +1 -0
- package/dist/auth/plugins/wrappers/sso.js +36 -0
- package/dist/auth/plugins/wrappers/two-factor.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/two-factor.js +2 -4
- package/dist/auth/plugins/wrappers/username.d.ts.map +1 -1
- package/dist/auth/plugins/wrappers/username.js +2 -4
- package/dist/bin/build-config.d.ts +2 -2
- package/dist/bin/build-config.js +6 -7
- package/dist/bin/cli.js +417 -32
- package/dist/bin/fixture.d.ts +27 -0
- package/dist/bin/fixture.d.ts.map +1 -0
- package/dist/bin/fixture.js +245 -0
- package/dist/cache/decorator.d.ts +4 -3
- package/dist/cache/decorator.d.ts.map +1 -1
- package/dist/cache/decorator.js +5 -4
- package/dist/cone/cone-generator.d.ts +33 -0
- package/dist/cone/cone-generator.d.ts.map +1 -0
- package/dist/cone/cone-generator.js +286 -0
- package/dist/database/_batch_update.d.ts.map +1 -1
- package/dist/database/_batch_update.js +16 -2
- package/dist/database/puri-subset.test-d.js +1 -1
- package/dist/database/puri-subset.types.d.ts +1 -1
- package/dist/database/puri-subset.types.d.ts.map +1 -1
- package/dist/database/puri-subset.types.js +1 -1
- package/dist/database/puri.d.ts +4 -0
- package/dist/database/puri.d.ts.map +1 -1
- package/dist/database/puri.js +20 -2
- package/dist/database/upsert-builder.d.ts.map +1 -1
- package/dist/database/upsert-builder.js +19 -3
- package/dist/dict/en.d.ts +15 -0
- package/dist/dict/en.d.ts.map +1 -1
- package/dist/dict/en.js +2 -1
- package/dist/dict/ko.d.ts +15 -0
- package/dist/dict/ko.d.ts.map +1 -1
- package/dist/dict/ko.js +2 -1
- package/dist/dict/rc-keys.d.ts +28 -0
- package/dist/dict/rc-keys.d.ts.map +1 -1
- package/dist/dict/rc-keys.js +31 -1
- package/dist/dict/sd.d.ts.map +1 -1
- package/dist/dict/sd.js +20 -4
- package/dist/entity/entity-manager.d.ts +298 -2
- package/dist/entity/entity-manager.d.ts.map +1 -1
- package/dist/entity/entity-manager.js +4 -1
- package/dist/entity/entity-template-cone.d.ts +14 -0
- package/dist/entity/entity-template-cone.d.ts.map +1 -0
- package/dist/entity/entity-template-cone.js +222 -0
- package/dist/entity/entity.d.ts +47 -2
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +161 -14
- package/dist/ssr/renderer.js +3 -3
- package/dist/syncer/api-parser.js +12 -1
- package/dist/syncer/checksum.d.ts +0 -14
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +1 -23
- package/dist/syncer/syncer-actions.d.ts.map +1 -1
- package/dist/syncer/syncer-actions.js +8 -2
- package/dist/syncer/syncer.d.ts +1 -1
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +17 -10
- package/dist/tasks/workflow-manager.d.ts +13 -1
- package/dist/tasks/workflow-manager.d.ts.map +1 -1
- package/dist/tasks/workflow-manager.js +18 -1
- package/dist/template/entity-converter.js +4 -4
- package/dist/template/helpers.d.ts +10 -0
- package/dist/template/helpers.d.ts.map +1 -1
- package/dist/template/helpers.js +48 -1
- package/dist/template/implementations/entry-server.template.d.ts +1 -1
- package/dist/template/implementations/entry-server.template.js +7 -2
- package/dist/template/implementations/generated.template.d.ts.map +1 -1
- package/dist/template/implementations/generated.template.js +5 -1
- package/dist/template/implementations/generated_http.template.d.ts +1 -0
- package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_http.template.js +6 -2
- package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
- package/dist/template/implementations/generated_sso.template.js +29 -8
- package/dist/template/implementations/queries.template.d.ts.map +1 -1
- package/dist/template/implementations/queries.template.js +9 -1
- package/dist/template/implementations/sd.template.d.ts +1 -1
- package/dist/template/implementations/sd.template.d.ts.map +1 -1
- package/dist/template/implementations/sd.template.js +28 -4
- package/dist/template/implementations/services.template.d.ts.map +1 -1
- package/dist/template/implementations/services.template.js +12 -12
- package/dist/template/implementations/view_form.template.d.ts +11 -7
- package/dist/template/implementations/view_form.template.d.ts.map +1 -1
- package/dist/template/implementations/view_form.template.js +97 -87
- package/dist/template/implementations/view_list.template.d.ts +3 -3
- package/dist/template/implementations/view_list.template.d.ts.map +1 -1
- package/dist/template/implementations/view_list.template.js +115 -109
- package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
- package/dist/template/implementations/view_search_input.template.js +18 -14
- package/dist/template/zod-converter.d.ts.map +1 -1
- package/dist/template/zod-converter.js +95 -7
- package/dist/testing/_relation-graph.js +1 -1
- package/dist/testing/data-explorer.d.ts +61 -0
- package/dist/testing/data-explorer.d.ts.map +1 -0
- package/dist/testing/data-explorer.js +274 -0
- package/dist/testing/faker-mappings.d.ts +20 -0
- package/dist/testing/faker-mappings.d.ts.map +1 -0
- package/dist/testing/faker-mappings.js +421 -0
- package/dist/testing/fixture-generator.d.ts +161 -0
- package/dist/testing/fixture-generator.d.ts.map +1 -0
- package/dist/testing/fixture-generator.js +954 -0
- package/dist/testing/fixture-manager.d.ts +6 -1
- package/dist/testing/fixture-manager.d.ts.map +1 -1
- package/dist/testing/fixture-manager.js +72 -4
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +4 -1
- package/dist/types/types.d.ts +1520 -26
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +136 -22
- package/dist/ui/ai-client.d.ts.map +1 -1
- package/dist/ui/ai-client.js +9 -4
- package/dist/ui/api.d.ts.map +1 -1
- package/dist/ui/api.js +303 -24
- package/dist/ui-web/assets/index-CsUr-_pV.js +254 -0
- package/dist/ui-web/assets/index-T42zzs1K.css +1 -0
- package/dist/ui-web/index.html +2 -2
- package/dist/utils/fs-utils.d.ts +2 -1
- package/dist/utils/fs-utils.d.ts.map +1 -1
- package/dist/utils/fs-utils.js +14 -3
- package/package.json +19 -11
- package/src/api/config.ts +12 -1
- package/src/api/sonamu.ts +179 -65
- package/src/auth/plugins/entity-definitions/anonymous.ts +17 -0
- package/src/auth/plugins/entity-definitions/api-key.ts +93 -0
- package/src/auth/plugins/entity-definitions/index.ts +18 -0
- package/src/auth/plugins/entity-definitions/jwt.ts +35 -0
- package/src/auth/plugins/entity-definitions/organization.ts +215 -0
- package/src/auth/plugins/entity-definitions/passkey.ts +64 -0
- package/src/auth/plugins/entity-definitions/sso.ts +62 -0
- package/src/auth/plugins/entity-definitions/types.ts +11 -1
- package/src/auth/plugins/wrappers/admin.ts +1 -3
- package/src/auth/plugins/wrappers/anonymous.ts +30 -0
- package/src/auth/plugins/wrappers/api-key.ts +42 -0
- package/src/auth/plugins/wrappers/index.ts +6 -0
- package/src/auth/plugins/wrappers/jwt.ts +34 -0
- package/src/auth/plugins/wrappers/organization.ts +73 -0
- package/src/auth/plugins/wrappers/passkey.ts +36 -0
- package/src/auth/plugins/wrappers/phone-number.ts +1 -3
- package/src/auth/plugins/wrappers/sso.ts +40 -0
- package/src/auth/plugins/wrappers/two-factor.ts +1 -3
- package/src/auth/plugins/wrappers/username.ts +1 -3
- package/src/bin/build-config.ts +6 -6
- package/src/bin/cli.ts +452 -31
- package/src/bin/fixture.ts +302 -0
- package/src/cache/decorator.ts +4 -3
- package/src/cone/cone-generator.ts +363 -0
- package/src/database/_batch_update.ts +11 -0
- package/src/database/puri-subset.test-d.ts +13 -13
- package/src/database/puri-subset.types.ts +1 -1
- package/src/database/puri.ts +43 -1
- package/src/database/upsert-builder.ts +16 -2
- package/src/dict/en.ts +1 -0
- package/src/dict/ko.ts +1 -0
- package/src/dict/rc-keys.ts +32 -0
- package/src/dict/sd.ts +23 -3
- package/src/entity/entity-manager.ts +4 -0
- package/src/entity/entity-template-cone.ts +298 -0
- package/src/entity/entity.ts +189 -13
- package/src/shared/app.shared.ts.txt +5 -0
- package/src/shared/web.shared.ts.txt +9 -5
- package/src/skills/project/README.md +21 -0
- package/src/skills/project/architecture.md +373 -0
- package/src/skills/project/business-logic.md +270 -0
- package/src/skills/project/requirements.md +160 -0
- package/src/skills/sonamu/SKILL.md +168 -3
- package/src/skills/sonamu/api.md +102 -0
- package/src/skills/sonamu/database.md +220 -1
- package/src/skills/sonamu/entity-relations.md +89 -1
- package/src/skills/sonamu/fixture-cli.md +501 -0
- package/src/skills/sonamu/frontend.md +214 -0
- package/src/skills/sonamu/i18n.md +95 -0
- package/src/skills/sonamu/model.md +153 -0
- package/src/skills/sonamu/project-init.md +178 -8
- package/src/skills/sonamu/scaffolding.md +112 -0
- package/src/skills/sonamu/subset.md +9 -3
- package/src/skills/sonamu/testing.md +287 -2
- package/src/skills/sonamu/workflow.md +70 -5
- package/src/ssr/renderer.ts +2 -2
- package/src/syncer/api-parser.ts +12 -0
- package/src/syncer/checksum.ts +0 -38
- package/src/syncer/syncer-actions.ts +7 -1
- package/src/syncer/syncer.ts +16 -5
- package/src/tasks/workflow-manager.ts +29 -8
- package/src/template/entity-converter.ts +3 -3
- package/src/template/helpers.ts +49 -0
- package/src/template/implementations/entry-server.template.ts +1 -1
- package/src/template/implementations/generated.template.ts +4 -0
- package/src/template/implementations/generated_http.template.ts +1 -0
- package/src/template/implementations/generated_sso.template.ts +40 -11
- package/src/template/implementations/queries.template.ts +8 -0
- package/src/template/implementations/sd.template.ts +22 -3
- package/src/template/implementations/services.template.ts +11 -10
- package/src/template/implementations/view_form.template.ts +111 -101
- package/src/template/implementations/view_list.template.ts +120 -119
- package/src/template/implementations/view_search_input.template.ts +17 -13
- package/src/template/zod-converter.ts +103 -6
- package/src/testing/_relation-graph.ts +1 -1
- package/src/testing/data-explorer.ts +427 -0
- package/src/testing/faker-mappings.ts +434 -0
- package/src/testing/fixture-generator.ts +1166 -0
- package/src/testing/fixture-manager.ts +91 -6
- package/src/testing/index.ts +3 -0
- package/src/types/types.ts +222 -26
- package/src/ui/ai-client.ts +9 -1
- package/src/ui/api.ts +429 -23
- package/src/utils/fs-utils.ts +14 -1
- package/dist/template/implementations/view_enums_select.template.d.ts +0 -17
- package/dist/template/implementations/view_enums_select.template.d.ts.map +0 -1
- package/dist/template/implementations/view_enums_select.template.js +0 -62
- package/dist/template/implementations/view_id_async_select.template.d.ts +0 -17
- package/dist/template/implementations/view_id_async_select.template.d.ts.map +0 -1
- package/dist/template/implementations/view_id_async_select.template.js +0 -125
- package/dist/ui-web/assets/index-Bd_2AkLb.css +0 -1
- package/dist/ui-web/assets/index-BpSbhQWo.js +0 -225
- package/src/template/implementations/view_enums_select.template.ts +0 -65
- package/src/template/implementations/view_id_async_select.template.ts +0 -139
package/src/syncer/syncer.ts
CHANGED
|
@@ -23,7 +23,7 @@ import { isTest } from "../utils/controller";
|
|
|
23
23
|
import { copyFileWithReplaceCoreToShared, exists } from "../utils/fs-utils";
|
|
24
24
|
import type { AbsolutePath } from "../utils/path-utils";
|
|
25
25
|
import { runWithGracefulShutdown } from "../utils/process-utils";
|
|
26
|
-
import {
|
|
26
|
+
import { findChangedFilesUsingChecksums, renewChecksums } from "./checksum";
|
|
27
27
|
import { generateTemplate, renderTemplate } from "./code-generator";
|
|
28
28
|
import { createEntity, delEntity } from "./entity-operations";
|
|
29
29
|
import {
|
|
@@ -55,13 +55,13 @@ export class Syncer {
|
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* 체크섬이 변경된 부분에 대해 싱크를 진행합니다.
|
|
58
|
-
*
|
|
58
|
+
* sonamu.shared.ts는 파일이 없을 때만 1회 생성하고, 이후에는 덮어쓰지 않습니다.
|
|
59
59
|
* @returns
|
|
60
60
|
*/
|
|
61
61
|
async sync(): Promise<void> {
|
|
62
62
|
const { targets } = Sonamu.config.sync;
|
|
63
63
|
|
|
64
|
-
// sonamu.shared.ts는
|
|
64
|
+
// sonamu.shared.ts는 파일이 없을 때만 1회 생성합니다.
|
|
65
65
|
await this.copySharedToTargets(targets);
|
|
66
66
|
|
|
67
67
|
// 그 다음부터는 변경된 파일을 찾아서 동기화 작업을 실행합니다.
|
|
@@ -239,7 +239,12 @@ export class Syncer {
|
|
|
239
239
|
console.warn(`Created directory '${path.dirname(destPath)}' because it did not exist.`);
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
|
|
242
|
+
// 파일이 이미 존재하면 건너뜁니다.
|
|
243
|
+
// sonamu.shared.ts는 프로젝트에서 자유롭게 커스터마이징할 수 있어야 하므로,
|
|
244
|
+
// 최초 1회만 생성하고 이후에는 덮어쓰지 않습니다.
|
|
245
|
+
// 템플릿 내용($[[dictUtils]] 등)이 변경되었을 때 반영이 필요하면,
|
|
246
|
+
// 해당 파일을 삭제한 뒤 `pnpm sonamu sync`로 재생성하면 됩니다.
|
|
247
|
+
if (await exists(destPath)) {
|
|
243
248
|
continue;
|
|
244
249
|
}
|
|
245
250
|
|
|
@@ -622,7 +627,13 @@ export class Syncer {
|
|
|
622
627
|
const sourceFile = path.join(apiI18nDir, `${locale}.ts`);
|
|
623
628
|
const targetFile = path.join(targetI18nDir, `${locale}.ts`);
|
|
624
629
|
|
|
625
|
-
|
|
630
|
+
const syncHeader = [
|
|
631
|
+
"/**",
|
|
632
|
+
" * @generated",
|
|
633
|
+
" * API에서 동기화된 파일입니다. 직접 수정하지 마세요.",
|
|
634
|
+
" */",
|
|
635
|
+
].join("\n");
|
|
636
|
+
await copyFileWithReplaceCoreToShared(sourceFile, targetFile, syncHeader);
|
|
626
637
|
!isTest() &&
|
|
627
638
|
console.log(chalk.bold("Copied: ") + chalk.cyan(`${target}/src/i18n/${locale}.ts`));
|
|
628
639
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { getLogger, type Logger } from "@logtape/logtape";
|
|
2
2
|
import { BackendPostgres, OpenWorkflow, type Worker } from "@sonamu-kit/tasks";
|
|
3
|
-
import
|
|
4
|
-
RunnableWorkflow,
|
|
5
|
-
SchemaInput,
|
|
6
|
-
SchemaOutput,
|
|
7
|
-
StandardSchemaV1,
|
|
8
|
-
StepApi,
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import {
|
|
4
|
+
type RunnableWorkflow,
|
|
5
|
+
type SchemaInput,
|
|
6
|
+
type SchemaOutput,
|
|
7
|
+
type StandardSchemaV1,
|
|
8
|
+
type StepApi,
|
|
9
|
+
serializeRetryPolicy,
|
|
10
|
+
type WorkflowRunHandle,
|
|
11
|
+
type WorkflowSpec,
|
|
11
12
|
} from "@sonamu-kit/tasks/internal";
|
|
12
13
|
import assert from "assert";
|
|
13
14
|
import type { Knex } from "knex";
|
|
@@ -92,6 +93,26 @@ export class WorkflowManager {
|
|
|
92
93
|
this.#scheduledTasks = new Map();
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
// Sonamu UI API에서 워크플로우 실행 목록 조회, 취소 등에 사용합니다.
|
|
97
|
+
get backend(): BackendPostgres {
|
|
98
|
+
return this.#backend;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get workflowDefinitions() {
|
|
102
|
+
return Array.from(this.#workflowsMap.values())
|
|
103
|
+
.flat()
|
|
104
|
+
.map((wf) => ({
|
|
105
|
+
id: wf.id,
|
|
106
|
+
name: wf.name,
|
|
107
|
+
version: wf.version,
|
|
108
|
+
schedules: wf.schedules.map((s) => ({
|
|
109
|
+
name: s.name,
|
|
110
|
+
expression: s.expression,
|
|
111
|
+
})),
|
|
112
|
+
retryPolicy: wf.retryPolicy ? serializeRetryPolicy(wf.retryPolicy) : undefined,
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
|
|
95
116
|
/**
|
|
96
117
|
* 정의된 워크플로우 및 워크플로우에 대한 scheduled tasks를 동기화합니다.
|
|
97
118
|
*/
|
|
@@ -13,11 +13,11 @@ import { propToZodType, zodTypeToRenderingNode } from "./zod-converter";
|
|
|
13
13
|
*/
|
|
14
14
|
export async function getColumnsNode(entityId: string, subsetKey: string): Promise<RenderingNode> {
|
|
15
15
|
const entity = EntityManager.get(entityId);
|
|
16
|
-
const
|
|
17
|
-
if (
|
|
16
|
+
const subsetDef = entity.subsets[subsetKey];
|
|
17
|
+
if (subsetDef === undefined) {
|
|
18
18
|
throw new ServiceUnavailableException(SD("sonamu.error.subsetNotFound")(subsetKey));
|
|
19
19
|
}
|
|
20
|
-
const propNodes = entity.fieldExprsToPropNodes(
|
|
20
|
+
const propNodes = entity.fieldExprsToPropNodes(subsetDef);
|
|
21
21
|
const rootPropNode: EntityPropNode = {
|
|
22
22
|
nodeType: "object",
|
|
23
23
|
children: propNodes,
|
package/src/template/helpers.ts
CHANGED
|
@@ -77,6 +77,55 @@ export function getRelationPropFromColName(entityId: string, colName: string): R
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* FK 컬럼명에서 실제 relation 이름을 추출합니다.
|
|
82
|
+
* BelongsToOne/OneToOne relation은 subset에서 FK 컬럼명(user_id)으로 생성되므로 변환이 필요하고,
|
|
83
|
+
* ManyToMany relation은 subset에서 relation명(employee)으로 생성되므로 변환이 불필요합니다.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* getRelationNameFromColumnName("Employee", "user_id") // "user"
|
|
87
|
+
* getRelationNameFromColumnName("Project", "tag_ids") // "tags"
|
|
88
|
+
*/
|
|
89
|
+
export function getRelationNameFromColumnName(entityId: string, colName: string): string {
|
|
90
|
+
// _ids (복수) 처리
|
|
91
|
+
if (colName.endsWith("_ids")) {
|
|
92
|
+
const baseName = colName.replace(/_ids$/, "");
|
|
93
|
+
// 먼저 base name으로 찾기
|
|
94
|
+
try {
|
|
95
|
+
const relProp = getRelationPropFromColName(entityId, baseName);
|
|
96
|
+
return relProp.name;
|
|
97
|
+
} catch {
|
|
98
|
+
// pluralize해서 찾기
|
|
99
|
+
try {
|
|
100
|
+
const pluralName = inflection.pluralize(baseName);
|
|
101
|
+
const relProp = getRelationPropFromColName(entityId, pluralName);
|
|
102
|
+
return relProp.name;
|
|
103
|
+
} catch {
|
|
104
|
+
return colName;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// _id (단수) 처리
|
|
109
|
+
if (colName.endsWith("_id") && colName !== "id") {
|
|
110
|
+
const baseName = colName.replace(/_id$/, "");
|
|
111
|
+
// 먼저 base name으로 찾기
|
|
112
|
+
try {
|
|
113
|
+
const relProp = getRelationPropFromColName(entityId, baseName);
|
|
114
|
+
return relProp.name;
|
|
115
|
+
} catch {
|
|
116
|
+
// singularize해서 찾기
|
|
117
|
+
try {
|
|
118
|
+
const singularName = inflection.singularize(baseName);
|
|
119
|
+
const relProp = getRelationPropFromColName(entityId, singularName);
|
|
120
|
+
return relProp.name;
|
|
121
|
+
} catch {
|
|
122
|
+
return colName;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return colName;
|
|
127
|
+
}
|
|
128
|
+
|
|
80
129
|
/**
|
|
81
130
|
* 소스 코드에서 객체 선언을 추출합니다.
|
|
82
131
|
* 중괄호 카운팅 방식으로 중첩된 객체도 정확히 파싱합니다.
|
|
@@ -128,6 +128,10 @@ export class Template__generated extends Template {
|
|
|
128
128
|
body,
|
|
129
129
|
importKeys: sourceCode.importKeys,
|
|
130
130
|
customHeaders: [
|
|
131
|
+
"/**",
|
|
132
|
+
" * @generated",
|
|
133
|
+
" * 직접 수정하지 마세요.",
|
|
134
|
+
" */",
|
|
131
135
|
"/** biome-ignore-all lint: generated는 무시 */",
|
|
132
136
|
"/** biome-ignore-all assist: generated는 무시 */",
|
|
133
137
|
"/** biome-ignore-all format: generated는 무시 */",
|
|
@@ -145,7 +145,13 @@ export class Template__generated_sso extends Template {
|
|
|
145
145
|
.join(", ");
|
|
146
146
|
|
|
147
147
|
// customHeaders 구성
|
|
148
|
-
const customHeaders = [
|
|
148
|
+
const customHeaders = [
|
|
149
|
+
"/**",
|
|
150
|
+
" * @generated",
|
|
151
|
+
" * 직접 수정하지 마세요.",
|
|
152
|
+
" */",
|
|
153
|
+
`import { ${sonamuImports} } from "sonamu";`,
|
|
154
|
+
];
|
|
149
155
|
if (this.hasAuthConfig()) {
|
|
150
156
|
customHeaders.push(`import type { User } from "better-auth";`);
|
|
151
157
|
}
|
|
@@ -173,8 +179,15 @@ export class Template__generated_sso extends Template {
|
|
|
173
179
|
entities.flatMap((entity) =>
|
|
174
180
|
entity.props.filter(isManyToManyRelationProp).map((prop) => {
|
|
175
181
|
const fromTableKey = inflection.singularize(entity.table);
|
|
176
|
-
const
|
|
177
|
-
|
|
182
|
+
const toEntity = EntityManager.get(prop.with);
|
|
183
|
+
const toTableKey = inflection.singularize(toEntity.table);
|
|
184
|
+
return {
|
|
185
|
+
table: prop.joinTable,
|
|
186
|
+
fromTableKey,
|
|
187
|
+
toTableKey,
|
|
188
|
+
fromEntityId: entity.id,
|
|
189
|
+
toEntityId: toEntity.id,
|
|
190
|
+
};
|
|
178
191
|
}),
|
|
179
192
|
),
|
|
180
193
|
(joinTable) => joinTable.table,
|
|
@@ -205,10 +218,14 @@ export class Template__generated_sso extends Template {
|
|
|
205
218
|
`declare module "sonamu" {`,
|
|
206
219
|
` export interface DatabaseSchemaExtend {`,
|
|
207
220
|
...entitySchemaLines,
|
|
208
|
-
...joinTables.map(
|
|
209
|
-
(joinTable)
|
|
210
|
-
|
|
211
|
-
|
|
221
|
+
...joinTables.map((joinTable) => {
|
|
222
|
+
const fromEntity = EntityManager.get(joinTable.fromEntityId);
|
|
223
|
+
const toEntity = EntityManager.get(joinTable.toEntityId);
|
|
224
|
+
const fromPkType = fromEntity.getPkType() === "integer" ? "number" : "string";
|
|
225
|
+
const toPkType = toEntity.getPkType() === "integer" ? "number" : "string";
|
|
226
|
+
|
|
227
|
+
return `${joinTable.table}: ManyToManyBaseSchema<"${joinTable.fromTableKey}", "${joinTable.toTableKey}", ${fromPkType}, ${toPkType}>;`;
|
|
228
|
+
}),
|
|
212
229
|
` }`,
|
|
213
230
|
``,
|
|
214
231
|
` export interface DatabaseForeignKeys {`,
|
|
@@ -285,19 +302,31 @@ export class Template__generated_sso extends Template {
|
|
|
285
302
|
};
|
|
286
303
|
}
|
|
287
304
|
|
|
305
|
+
const importKeys: string[] = [];
|
|
306
|
+
|
|
288
307
|
// additionalFields를 TypeScript 타입으로 변환
|
|
289
308
|
const fieldLines = Object.entries(additionalFields).map(([key, value]) => {
|
|
290
309
|
// biome-ignore lint/suspicious/noExplicitAny: better-auth additionalFields 구조
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
310
|
+
const fieldConfig = value as any;
|
|
311
|
+
const isRequired = fieldConfig.required !== false;
|
|
312
|
+
|
|
313
|
+
let fieldType: string;
|
|
314
|
+
|
|
315
|
+
// sonamuType이 있으면 description을 타입명으로 사용
|
|
316
|
+
if (fieldConfig.sonamuType) {
|
|
317
|
+
fieldType = fieldConfig.sonamuType;
|
|
318
|
+
importKeys.push(fieldType);
|
|
319
|
+
} else {
|
|
320
|
+
fieldType = mapBetterAuthFieldType(fieldConfig.type);
|
|
321
|
+
}
|
|
322
|
+
|
|
294
323
|
return ` ${key}${isRequired ? "" : "?"}: ${fieldType};`;
|
|
295
324
|
});
|
|
296
325
|
|
|
297
326
|
return {
|
|
298
327
|
label: "Auth User Type",
|
|
299
328
|
lines: ["export type SonamuUser = User & {", ...fieldLines, "};"],
|
|
300
|
-
importKeys
|
|
329
|
+
importKeys,
|
|
301
330
|
};
|
|
302
331
|
}
|
|
303
332
|
|
|
@@ -101,6 +101,10 @@ ${functions.join("\n\n")}
|
|
|
101
101
|
importKeys: diff(unique(importKeys), typeParamNames),
|
|
102
102
|
customHeaders: hasQueries
|
|
103
103
|
? [
|
|
104
|
+
"/**",
|
|
105
|
+
" * @generated",
|
|
106
|
+
" * 직접 수정하지 마세요.",
|
|
107
|
+
" */",
|
|
104
108
|
"/** biome-ignore-all lint: generated는 무시 */",
|
|
105
109
|
"/** biome-ignore-all assist: generated는 무시 */",
|
|
106
110
|
"",
|
|
@@ -113,6 +117,10 @@ ${functions.join("\n\n")}
|
|
|
113
117
|
"",
|
|
114
118
|
]
|
|
115
119
|
: [
|
|
120
|
+
"/**",
|
|
121
|
+
" * @generated",
|
|
122
|
+
" * 직접 수정하지 마세요.",
|
|
123
|
+
" */",
|
|
116
124
|
"/** biome-ignore-all lint: generated는 무시 */",
|
|
117
125
|
"/** biome-ignore-all assist: generated는 무시 */",
|
|
118
126
|
"",
|
|
@@ -137,9 +137,28 @@ type SDReturnType<K extends DictKey> = MergedDictionary[K] extends (...args: inf
|
|
|
137
137
|
: LocalizedString;
|
|
138
138
|
|
|
139
139
|
function getDictValue<K extends DictKey>(key: K, locale: string): SDReturnType<K> {
|
|
140
|
+
// 1. 지정된 locale에서 조회
|
|
140
141
|
const dict = dictionaries[locale];
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
if (dict?.[key] !== undefined) {
|
|
143
|
+
return dict[key] as unknown as SDReturnType<K>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 2. default locale에서 조회
|
|
147
|
+
if (locale !== DEFAULT_LOCALE && dictionaries[DEFAULT_LOCALE]?.[key] !== undefined) {
|
|
148
|
+
return dictionaries[DEFAULT_LOCALE][key] as unknown as SDReturnType<K>;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 3. supported locales 순회
|
|
152
|
+
for (const supportedLocale of SUPPORTED_LOCALES) {
|
|
153
|
+
if (supportedLocale !== locale && supportedLocale !== DEFAULT_LOCALE) {
|
|
154
|
+
if (dictionaries[supportedLocale]?.[key] !== undefined) {
|
|
155
|
+
return dictionaries[supportedLocale][key] as unknown as SDReturnType<K>;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// 4. 모두 실패 시 key 반환
|
|
161
|
+
return key as unknown as SDReturnType<K>;
|
|
143
162
|
}
|
|
144
163
|
|
|
145
164
|
/**
|
|
@@ -229,7 +248,7 @@ SD.enumLabels = (enumName: string): Record<string, LocalizedString> => {
|
|
|
229
248
|
...this.getTargetAndPath(undefined, target),
|
|
230
249
|
body,
|
|
231
250
|
importKeys: [],
|
|
232
|
-
customHeaders: [],
|
|
251
|
+
customHeaders: ["/**", " * @generated", " * 직접 수정하지 마세요.", " */"],
|
|
233
252
|
};
|
|
234
253
|
}
|
|
235
254
|
|
|
@@ -321,19 +321,15 @@ ${functions.join("\n\n")}
|
|
|
321
321
|
const hookName = inflection.camelize(assertDefined(listApi.options.resourceName), true);
|
|
322
322
|
const useHookName = `use${inflection.camelize(hookName)}`;
|
|
323
323
|
|
|
324
|
+
// ListParams 타입명 구성
|
|
325
|
+
const listParamsType = `${names.capital}ListParams`;
|
|
326
|
+
|
|
324
327
|
asyncIdConfigs.push(
|
|
325
328
|
`
|
|
326
329
|
// AsyncIdConfig: ${names.capital}
|
|
327
|
-
export const ${names.capital}AsyncIdConfig = {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
params?: Record<string, unknown>,
|
|
331
|
-
options?: { enabled?: boolean }
|
|
332
|
-
) => {
|
|
333
|
-
data?: { rows: Record<string, unknown>[] };
|
|
334
|
-
isLoading: boolean;
|
|
335
|
-
error?: Error;
|
|
336
|
-
},
|
|
330
|
+
export const ${names.capital}AsyncIdConfig: AsyncIdConfig<${names.capital}SubsetKey, ${names.capital}SubsetMapping, ${listParamsType}> = {
|
|
331
|
+
placeholderKey: "entity.${names.capital}",
|
|
332
|
+
useList: ${names.capital}Service.${useHookName},
|
|
337
333
|
};
|
|
338
334
|
`.trim(),
|
|
339
335
|
);
|
|
@@ -369,6 +365,10 @@ export const ${names.capital}AsyncIdConfig = {
|
|
|
369
365
|
...Object.keys(BUILT_IN_TYPES),
|
|
370
366
|
]),
|
|
371
367
|
customHeaders: [
|
|
368
|
+
"/**",
|
|
369
|
+
" * @generated",
|
|
370
|
+
" * 직접 수정하지 마세요.",
|
|
371
|
+
" */",
|
|
372
372
|
"/** biome-ignore-all lint: generated는 무시 */",
|
|
373
373
|
"/** biome-ignore-all assist: generated는 무시 */",
|
|
374
374
|
"",
|
|
@@ -376,6 +376,7 @@ export const ${names.capital}AsyncIdConfig = {
|
|
|
376
376
|
`import type { AxiosProgressEvent } from 'axios';`,
|
|
377
377
|
`import qs from 'qs';`,
|
|
378
378
|
`import { ${sonamuSharedImports} } from './sonamu.shared';`,
|
|
379
|
+
`import type { AsyncIdConfig } from '@sonamu-kit/react-components/components';`,
|
|
379
380
|
],
|
|
380
381
|
};
|
|
381
382
|
}
|