sonamu 0.8.24 → 0.8.26

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 (88) hide show
  1. package/dist/api/__tests__/config.test.js +189 -0
  2. package/dist/api/config.d.ts.map +1 -1
  3. package/dist/api/config.js +7 -2
  4. package/dist/api/sonamu.d.ts.map +1 -1
  5. package/dist/api/sonamu.js +14 -10
  6. package/dist/auth/index.d.ts +1 -0
  7. package/dist/auth/index.d.ts.map +1 -1
  8. package/dist/auth/index.js +2 -1
  9. package/dist/auth/knex-adapter.d.ts +23 -0
  10. package/dist/auth/knex-adapter.d.ts.map +1 -0
  11. package/dist/auth/knex-adapter.js +163 -0
  12. package/dist/auth/plugins/wrappers/admin.d.ts +2 -2
  13. package/dist/bin/__tests__/ts-loader-register.test.js +45 -0
  14. package/dist/bin/cli.js +47 -9
  15. package/dist/bin/ts-loader-register.js +3 -29
  16. package/dist/bin/ts-loader-registration.d.ts +2 -0
  17. package/dist/bin/ts-loader-registration.d.ts.map +1 -0
  18. package/dist/bin/ts-loader-registration.js +42 -0
  19. package/dist/cone/cone-generator.js +3 -3
  20. package/dist/database/puri-subset.test-d.js +9 -1
  21. package/dist/database/puri-subset.types.d.ts +1 -1
  22. package/dist/database/puri-subset.types.d.ts.map +1 -1
  23. package/dist/database/puri-subset.types.js +1 -1
  24. package/dist/testing/fixture-generator.js +5 -5
  25. package/dist/ui/ai-client.js +2 -2
  26. package/dist/ui/api.d.ts.map +1 -1
  27. package/dist/ui/api.js +14 -14
  28. package/dist/ui/cdd-service.d.ts +15 -18
  29. package/dist/ui/cdd-service.d.ts.map +1 -1
  30. package/dist/ui/cdd-service.js +246 -222
  31. package/dist/ui/cdd-types.d.ts +41 -68
  32. package/dist/ui/cdd-types.d.ts.map +1 -1
  33. package/dist/ui/cdd-types.js +2 -2
  34. package/dist/ui-web/assets/index-CKo0Z2Iu.css +1 -0
  35. package/dist/ui-web/assets/{index-CxiydzeC.js → index-DK-2aacv.js} +83 -83
  36. package/dist/ui-web/index.html +2 -2
  37. package/package.json +6 -2
  38. package/src/api/__tests__/config.test.ts +225 -0
  39. package/src/api/config.ts +10 -4
  40. package/src/api/sonamu.ts +16 -13
  41. package/src/auth/index.ts +1 -0
  42. package/src/auth/knex-adapter.ts +208 -0
  43. package/src/bin/__tests__/ts-loader-register.test.ts +62 -0
  44. package/src/bin/cli.ts +52 -9
  45. package/src/bin/ts-loader-register.ts +2 -32
  46. package/src/bin/ts-loader-registration.ts +55 -0
  47. package/src/cone/cone-generator.ts +2 -2
  48. package/src/database/puri-subset.test-d.ts +102 -0
  49. package/src/database/puri-subset.types.ts +1 -1
  50. package/src/skills/commands/sonamu-skills.md +20 -0
  51. package/src/skills/sonamu/SKILL.md +179 -137
  52. package/src/skills/sonamu/ai-agents.md +69 -69
  53. package/src/skills/sonamu/api.md +147 -147
  54. package/src/skills/sonamu/auth-migration.md +220 -220
  55. package/src/skills/sonamu/auth-plugins.md +83 -83
  56. package/src/skills/sonamu/auth.md +106 -106
  57. package/src/skills/sonamu/cdd.md +65 -200
  58. package/src/skills/sonamu/cone.md +138 -138
  59. package/src/skills/sonamu/config.md +191 -191
  60. package/src/skills/sonamu/create-sonamu.md +66 -66
  61. package/src/skills/sonamu/database.md +158 -158
  62. package/src/skills/sonamu/entity-basic.md +292 -293
  63. package/src/skills/sonamu/entity-relations.md +246 -246
  64. package/src/skills/sonamu/entity-validation-checklist.md +124 -124
  65. package/src/skills/sonamu/fixture-cli.md +231 -231
  66. package/src/skills/sonamu/framework-change.md +37 -37
  67. package/src/skills/sonamu/frontend.md +223 -223
  68. package/src/skills/sonamu/i18n.md +82 -82
  69. package/src/skills/sonamu/migration.md +77 -77
  70. package/src/skills/sonamu/model.md +222 -222
  71. package/src/skills/sonamu/naite.md +86 -86
  72. package/src/skills/sonamu/project-init.md +228 -228
  73. package/src/skills/sonamu/puri.md +122 -122
  74. package/src/skills/sonamu/scaffolding.md +154 -154
  75. package/src/skills/sonamu/skill-contribution.md +124 -124
  76. package/src/skills/sonamu/subset.md +46 -46
  77. package/src/skills/sonamu/tasks.md +82 -82
  78. package/src/skills/sonamu/testing-devrunner.md +147 -147
  79. package/src/skills/sonamu/testing.md +673 -673
  80. package/src/skills/sonamu/upsert.md +79 -79
  81. package/src/skills/sonamu/vector.md +67 -67
  82. package/src/testing/fixture-generator.ts +4 -4
  83. package/src/ui/ai-client.ts +1 -1
  84. package/src/ui/api.ts +18 -17
  85. package/src/ui/cdd-service.ts +264 -254
  86. package/src/ui/cdd-types.ts +40 -75
  87. package/dist/ui-web/assets/index-BrQKU3j9.css +0 -1
  88. package/src/skills/sonamu/workflow.md +0 -317
@@ -1,41 +1,41 @@
1
1
  ---
2
2
  name: sonamu-scaffolding
3
- description: Sonamu UI Scaffolding 사용 참조. 흔한 오류와 해결 방법. Use when scaffolding models or views.
3
+ description: Reference for using Sonamu UI Scaffolding. Common errors and solutions. Use when scaffolding models or views.
4
4
  ---
5
5
 
6
- # Scaffolding 트러블슈팅
6
+ # Scaffolding Troubleshooting
7
7
 
8
- ## CRITICAL: Scaffolding 필수 항목
8
+ ## CRITICAL: Required Scaffolding Items
9
9
 
10
- **모든 엔티티에 대해 다음 5가지를 모두 scaffolding 해야 한다:**
10
+ **The following 5 items must all be scaffolded for every entity:**
11
11
 
12
- | 항목 | 설명 |
12
+ | Item | Description |
13
13
  |------|------|
14
- | `model` | BaseModelClass 기반 CRUD 모델 |
15
- | `model_test` | 모델 테스트 파일 |
16
- | `view_list` | 목록 화면 컴포넌트 |
17
- | `view_search_input` | 검색 입력 컴포넌트 |
18
- | `view_form` | 생성/수정 컴포넌트 |
14
+ | `model` | CRUD model based on BaseModelClass |
15
+ | `model_test` | Model test file |
16
+ | `view_list` | List view component |
17
+ | `view_search_input` | Search input component |
18
+ | `view_form` | Create/edit form component |
19
19
 
20
- **DO NOT:** model model_test scaffolding하고 view 관련을 건너뛰는
20
+ **DO NOT:** scaffold only model and model_test and skip the view-related items
21
21
 
22
22
  ---
23
23
 
24
- ## Scaffolding 전 체크리스트
24
+ ## Pre-Scaffolding Checklist
25
25
 
26
- **`packages/api`** 디렉토리에서 실행:
26
+ Run from the **`packages/api`** directory:
27
27
 
28
- 1. **Entity 변경 감지 대기**: Entity 생성 syncer `types.ts` 자동 생성할 때까지 대기 (2-3)
29
- 2. **types.ts 파일 확인**: 자동 생성되지 않았다면 수동 생성
30
- 3. **Migration 생성 실행**: Sonamu UI에서 Migration 생성 → `pnpm sonamu migrate run`
31
- 4. **TypeScript 빌드 완료**: `pnpm build`로 `dist/` 폴더에 `.js` 파일 생성
32
- 5. **개발 서버 재시작**: `pnpm dev` (빌드 재시작 필요)
28
+ 1. **Wait for entity change detection**: After creating an entity, wait for the syncer to auto-generate `types.ts` (2-3 seconds)
29
+ 2. **Check types.ts file**: If not auto-generated, create it manually
30
+ 3. **Create and run migration**: Create migration from Sonamu UI → `pnpm sonamu migrate run`
31
+ 4. **Complete TypeScript build**: Run `pnpm build` to generate `.js` files in `dist/`
32
+ 5. **Restart dev server**: `pnpm dev` (restart required after build)
33
33
 
34
- ## Scaffolding 필수 체크리스트
34
+ ## Post-Scaffolding Required Checklist
35
35
 
36
- **CRITICAL: Scaffolding 완료 반드시 다음 작업을 수행하세요.**
36
+ **CRITICAL: After scaffolding is complete, you must perform the following steps.**
37
37
 
38
- ### 1. Build 테스트
38
+ ### 1. Build Test
39
39
  ```bash
40
40
  cd packages/api
41
41
  pnpm build
@@ -43,57 +43,57 @@ pnpm build
43
43
  cd packages/web
44
44
  pnpm build
45
45
  ```
46
- - [ ] API 빌드 성공
47
- - [ ] Web 빌드 성공
46
+ - [ ] API build succeeds
47
+ - [ ] Web build succeeds
48
48
 
49
- ### 2. Dev 서버 재시작
49
+ ### 2. Restart Dev Server
50
50
  ```bash
51
51
  cd packages/api
52
52
  pnpm dev
53
53
  ```
54
- - [ ] 서버 정상 작동
54
+ - [ ] Server running normally
55
55
 
56
- ### 3. Relation이 있는 경우 (i18n 키 추가)
56
+ ### 3. If Relations Exist (Add i18n Keys)
57
57
 
58
- **필수**: Entity에 BelongsToOne 또는 relation이 있으면 반드시 수행
58
+ **Required**: Must be done if the entity has a BelongsToOne or any relation
59
59
 
60
60
  ```typescript
61
61
  // packages/api/src/i18n/ko.ts
62
62
  export default {
63
- // ... 기존 키들
63
+ // ... existing keys
64
64
 
65
- // Relation 있는 Entity마다 추가
66
- "entity.Post.author_id": "작성자",
67
- "entity.Question.collection_id": "소속 모음집",
68
- "entity.Question.parent_id": "상위 질문",
69
- "entity.Employee.department_id": "부서",
70
- "entity.Task.principal_investigator_id": "연구책임자",
65
+ // Add for each entity with relations
66
+ "entity.Post.author_id": "Author",
67
+ "entity.Question.collection_id": "Collection",
68
+ "entity.Question.parent_id": "Parent Question",
69
+ "entity.Employee.department_id": "Department",
70
+ "entity.Task.principal_investigator_id": "Principal Investigator",
71
71
 
72
72
  // ...
73
73
  } as const;
74
74
  ```
75
75
 
76
- **패턴**: `entity.{EntityId}.{relation}_id`
77
- - relation 이름에 `_id` 접미사 추가
78
- - 예: `author` relation → `author_id`
76
+ **Pattern**: `entity.{EntityId}.{relation}_id`
77
+ - Add `_id` suffix to the relation name
78
+ - Example: `author` relation → `author_id` key
79
79
 
80
- - [ ] Relation 있는 모든 Entity의 i18n 추가 완료
80
+ - [ ] i18n keys added for all entities with relations
81
81
 
82
- ### 4. OrderBy 케이스 추가 (id-desc 사용 시)
82
+ ### 4. Add OrderBy Cases (When values other than id-desc are used)
83
83
 
84
- **선택**: entity.json OrderBy enum에 `id-desc` 외 값이 있으면 수행
84
+ **Optional**: Perform if the OrderBy enum in entity.json has values other than `id-desc`
85
85
 
86
86
  ```typescript
87
87
  // packages/api/src/application/{entity}/{entity}.model.ts
88
88
 
89
- // 생성된 코드
89
+ // Generated code
90
90
  if (params.orderBy === "id-desc") {
91
91
  qb.orderBy("posts.id", "desc");
92
92
  } else {
93
- exhaustive(params.orderBy); // 타입 에러 발생!
93
+ exhaustive(params.orderBy); // type error!
94
94
  }
95
95
 
96
- // 수정: 나머지 case 추가
96
+ // Fix: add the remaining cases
97
97
  if (params.orderBy === "id-desc") {
98
98
  qb.orderBy("posts.id", "desc");
99
99
  } else if (params.orderBy === "created_at-desc") {
@@ -101,33 +101,33 @@ if (params.orderBy === "id-desc") {
101
101
  } else if (params.orderBy === "name-asc") {
102
102
  qb.orderBy("posts.name", "asc");
103
103
  } else {
104
- exhaustive(params.orderBy); // 이제 타입 에러 없음
104
+ exhaustive(params.orderBy); // no more type errors
105
105
  }
106
106
  ```
107
107
 
108
- - [ ] OrderBy 케이스 추가 완료
108
+ - [ ] OrderBy cases added
109
109
 
110
- ### 5. types.ts nullable 필드 처리 (테스트 필수!)
110
+ ### 5. Handle Nullable Fields in types.ts (Required Before Testing!)
111
111
 
112
- **필수**: 모든 Entity의 types.ts에서 nullable 필드 처리
112
+ **Required**: Handle nullable fields in types.ts for all entities
113
113
 
114
114
  ```typescript
115
115
  // packages/api/src/application/{entity}/{entity}.types.ts
116
116
 
117
- // 생성된 코드
117
+ // Generated code
118
118
  export const PostSaveParams = PostBaseSchema.partial({
119
119
  id: true,
120
120
  created_at: true,
121
121
  });
122
122
 
123
- // 수정: nullable 필드 추가
123
+ // Fix: add nullable fields
124
124
  export const PostSaveParams = PostBaseSchema
125
125
  .partial({
126
126
  id: true,
127
127
  created_at: true,
128
- updated_at: true, // nullable 필드
129
- category: true, // nullable 필드
130
- description: true, // nullable 필드
128
+ updated_at: true, // nullable field
129
+ category: true, // nullable field
130
+ description: true, // nullable field
131
131
  })
132
132
  .extend({
133
133
  updated_at: z.date().nullish(),
@@ -136,36 +136,36 @@ export const PostSaveParams = PostBaseSchema
136
136
  });
137
137
  ```
138
138
 
139
- **상세 가이드**: `testing.md`의 "엔티티 생성 즉시 해야 작업" 참조
139
+ **Detailed guide**: See "Tasks to do immediately after entity creation" in `testing.md`
140
140
 
141
- - [ ] 모든 Entity의 types.ts nullable 필드 처리 완료
141
+ - [ ] Nullable fields handled in types.ts for all entities
142
142
 
143
- ### 완료 확인
143
+ ### Completion Confirmation
144
144
 
145
145
  ```
146
- Scaffolding 필수 체크리스트 완료
147
- 다음 단계: 테스트 작성 (testing.md)
146
+ Post-scaffolding required checklist complete
147
+ Next step: write tests (testing.md)
148
148
 
149
- ⚠️ types.ts nullable 필드 처리를 하지 않으면
150
- 테스트 작성 타입 에러가 발생합니다!
149
+ ⚠️ If nullable fields in types.ts are not handled,
150
+ type errors will occur when writing tests!
151
151
  ```
152
152
 
153
153
  ---
154
154
 
155
- ## 흔한 오류
155
+ ## Common Errors
156
156
 
157
- | 오류 | 원인 | 해결 |
157
+ | Error | Cause | Fix |
158
158
  |------|------|------|
159
- | "존재하지 않는 모듈 패스 요청 {Type}" | types.ts 미생성 또는 미컴파일 | 대기/수동생성 → build → dev 재시작 |
160
- | exhaustive() 타입 에러 | OrderBy 번째 값만 자동 처리 | "4. OrderBy 케이스 추가" 참조 |
161
- | i18n 없음 (relation) | `author_id` vs `author` | "3. Relation이 있는 경우" 참조 |
162
- | IdAsyncSelect API 불일치 | 구버전 scaffolding 템플릿 사용 | 아래 "IdAsyncSelect API 마이그레이션" 참조 |
159
+ | "Non-existent module path requested {Type}" | types.ts not created or not compiled | Wait/create manually → build → restart dev |
160
+ | exhaustive() type error | Only the first OrderBy value is handled automatically | See "4. Add OrderBy Cases" above |
161
+ | Missing i18n key (relation) | `author_id` vs `author` | See "3. If Relations Exist" above |
162
+ | IdAsyncSelect API mismatch | Old scaffolding template used | See "IdAsyncSelect API Migration" below |
163
163
 
164
- ## 상세 설명
164
+ ## Detailed Explanations
165
165
 
166
- ### "존재하지 않는 모듈 패스 요청" 오류
166
+ ### "Non-existent module path requested" Error
167
167
 
168
- Scaffolding `dist/application/{entity}/{entity}.types.js`에서 export된 타입을 읽어 모듈 경로를 등록합니다.
168
+ Scaffolding reads types exported from `dist/application/{entity}/{entity}.types.js` to register module paths.
169
169
 
170
170
  ```typescript
171
171
  // modules/sonamu/src/entity/entity.ts
@@ -174,16 +174,16 @@ const typesFilePath = path.join(
174
174
  runtimePath(`dist/application/${typesModulePath}.js`),
175
175
  );
176
176
  if (await exists(typesFilePath)) {
177
- // 타입 등록
177
+ // register type
178
178
  }
179
179
  ```
180
180
 
181
- ### types.ts 자동 생성 메커니즘
181
+ ### Automatic types.ts Generation Mechanism
182
182
 
183
- Entity 생성 syncer `handleTruthSourceChanges`가 자동으로 `init_types` 템플릿을 실행합니다:
183
+ When an entity is created, the syncer's `handleTruthSourceChanges` automatically runs the `init_types` template:
184
184
 
185
185
  ```typescript
186
- // modules/sonamu/src/syncer/syncer.ts - handleTruthSourceChanges 함수
186
+ // modules/sonamu/src/syncer/syncer.ts - handleTruthSourceChanges function
187
187
  if (entityId) {
188
188
  const entity = EntityManager.get(entityId);
189
189
  const typeFilePath = path.join(...);
@@ -193,25 +193,25 @@ if (entityId) {
193
193
  }
194
194
  ```
195
195
 
196
- **자동 생성 조건**:
197
- - `parentId`가 없는 경우 (최상위 Entity)
198
- - `types.ts` 파일이 아직 존재하지 않는 경우
196
+ **Auto-generation conditions**:
197
+ - When `parentId` is absent (top-level entity)
198
+ - When the `types.ts` file does not yet exist
199
199
 
200
- **오류 발생 원인**:
201
- - Entity 생성 직후 syncer가 아직 실행되지 않은 상태에서 scaffolding 시도
202
- - types.ts 생성되었으나 빌드가 완료되지 않아 `.js` 파일이 없는 상태
200
+ **Causes of errors**:
201
+ - Attempting scaffolding immediately after entity creation before the syncer has run
202
+ - types.ts was created but the build has not completed so the `.js` file is missing
203
203
 
204
- **해결 순서** (`packages/api`에서 실행):
205
- 1. Entity 생성 syncer types.ts 생성할 때까지 잠시 대기 (2-3)
206
- 2. types.ts 없으면 수동 생성 (아래 템플릿 참고)
207
- 3. Migration 생성 (Sonamu UI) 실행 (`pnpm sonamu migrate run`)
208
- 4. `pnpm build`로 TypeScript 컴파일
209
- 5. `pnpm dev` 재시작
210
- 6. Scaffolding 재시도
204
+ **Resolution order** (run from `packages/api`):
205
+ 1. Wait briefly after entity creation for the syncer to generate types.ts (2-3 seconds)
206
+ 2. If types.ts is missing, create it manually (see template below)
207
+ 3. Create migration (Sonamu UI) and run it (`pnpm sonamu migrate run`)
208
+ 4. Compile TypeScript with `pnpm build`
209
+ 5. Restart `pnpm dev`
210
+ 6. Retry scaffolding
211
211
 
212
- ### types.ts 수동 생성 (필요시)
212
+ ### Manual types.ts Creation (If Needed)
213
213
 
214
- syncer 타이밍 문제로 자동 생성되지 않은 경우:
214
+ For cases where auto-generation did not occur due to a syncer timing issue:
215
215
 
216
216
  ```typescript
217
217
  // {entity}.types.ts
@@ -229,38 +229,38 @@ export type {Entity}SaveParams = z.infer<typeof {Entity}SaveParams>;
229
229
 
230
230
  **IMPORTANT: Entity with `updated_at` field**:
231
231
 
232
- Entity에 `updated_at` 필드가 정의되어 있으면 SaveParams의 partial에도 포함해야 합니다.
233
- Form에서 `updated_at`을 직접 입력받지 않으므로 optional 설정해야 타입 오류가 발생하지 않습니다.
232
+ If the entity has an `updated_at` field defined, it must also be included in the partial of SaveParams.
233
+ Since the form does not accept `updated_at` as direct input, it must be optional to avoid type errors.
234
234
 
235
235
  ```typescript
236
- // updated_at이 있는 Entity의 경우
236
+ // For entities with updated_at
237
237
  export const {Entity}SaveParams = {Entity}BaseSchema.partial({
238
238
  id: true,
239
239
  created_at: true,
240
- updated_at: true // ← 추가
240
+ updated_at: true // ← add this
241
241
  });
242
242
  ```
243
243
 
244
- ### exhaustive() 타입 에러
244
+ ### exhaustive() Type Error
245
245
 
246
- `exhaustive`는 sonamu에서 제공하는 유틸리티 함수입니다.
246
+ `exhaustive` is a utility function provided by sonamu.
247
247
 
248
248
  ```typescript
249
249
  import { exhaustive } from "sonamu";
250
250
  ```
251
251
 
252
- Scaffolding 템플릿은 `OrderBy` enum **첫 번째 값만** 자동 처리합니다.
252
+ The scaffolding template only handles the **first value** of the `OrderBy` enum automatically.
253
253
 
254
254
  ```typescript
255
- // 생성된 코드
255
+ // Generated code
256
256
  if (params.orderBy === "id-desc") {
257
257
  qb.orderBy("posts.id", "desc");
258
258
  } else {
259
- exhaustive(params.orderBy); // 나머지 case 미처리타입 에러
259
+ exhaustive(params.orderBy); // remaining cases unhandledtype error
260
260
  }
261
261
  ```
262
262
 
263
- **해결**: 모든 OrderBy case를 직접 추가
263
+ **Fix**: Manually add all OrderBy cases
264
264
 
265
265
  ```typescript
266
266
  if (params.orderBy === "id-desc") {
@@ -272,63 +272,63 @@ if (params.orderBy === "id-desc") {
272
272
  }
273
273
  ```
274
274
 
275
- ### i18n 오류 (relation prop)
275
+ ### i18n Key Error (relation prop)
276
276
 
277
- Entity의 relation prop `author`로 정의되고, `sd.generated.ts`의 i18n label은 `entity.Post.author`로 생성됩니다.
278
- **하지만** 스캐폴딩된 form.tsx 템플릿은 FK 컬럼명인 `author_id`를 사용합니다.
277
+ An entity's relation prop is defined as `author`, and the i18n label in `sd.generated.ts` is generated as `entity.Post.author`.
278
+ **However**, the scaffolded form.tsx template uses the FK column name `author_id`.
279
279
 
280
280
  ```typescript
281
- // 스캐폴딩된 form.tsx (실제 생성되는 코드)
282
- {SD("entity.Post.author_id")} // ← _id 접미사 사용
281
+ // Scaffolded form.tsx (actually generated code)
282
+ {SD("entity.Post.author_id")} // ← uses _id suffix
283
283
 
284
- // sd.generated.ts (자동 생성되는 키)
285
- "entity.Post.author": "작성자" // ← _id 없음
284
+ // sd.generated.ts (auto-generated keys)
285
+ "entity.Post.author": "Author" // ← no _id
286
286
  ```
287
287
 
288
- **해결 방법 ( 중 하나 선택)**:
288
+ **Fix (choose one)**:
289
289
 
290
- 1. **ko.ts에 `_id` 수동 추가** (권장):
290
+ 1. **Manually add `_id` key to ko.ts** (recommended):
291
291
  ```typescript
292
292
  // packages/api/src/i18n/ko.ts
293
293
  export default {
294
- // ... 기존 키들
295
- "entity.Post.author_id": "작성자",
296
- "entity.Question.collection_id": "소속 모음집",
297
- "entity.Question.parent_id": "상위 질문",
294
+ // ... existing keys
295
+ "entity.Post.author_id": "Author",
296
+ "entity.Question.collection_id": "Collection",
297
+ "entity.Question.parent_id": "Parent Question",
298
298
  // ...
299
299
  } as const;
300
300
  ```
301
301
 
302
- 2. **form.tsx에서 `_id` 제거** (수동 수정 필요):
302
+ 2. **Remove `_id` from form.tsx** (requires manual edit):
303
303
  ```typescript
304
- // 스캐폴딩 수동 수정
305
- {SD("entity.Post.author")} // _id 제거
304
+ // Manual edit after scaffolding
305
+ {SD("entity.Post.author")} // remove _id
306
306
  ```
307
307
 
308
- **권장**: 번째 방법 - ko.ts에 `_id` 추가. sync 유지되며 여러 form에서 재사용 가능.
308
+ **Recommended**: First option - add the `_id` key to ko.ts. It is preserved during sync and can be reused across multiple forms.
309
309
 
310
- ### IdAsyncSelect API 마이그레이션
310
+ ### IdAsyncSelect API Migration
311
311
 
312
- #### 발생 배경
312
+ #### Background
313
313
 
314
- Sonamu의 `@sonamu-kit/react-components` 패키지가 업데이트되면서 IdAsyncSelect API 변경되었으나, scaffolding 생성 코드(`scaffolding/react-components.ts`) API 기준으로 코드를 생성합니다.
314
+ When the `@sonamu-kit/react-components` package was updated, the IdAsyncSelect API changed, but the scaffolding generation code (`scaffolding/react-components.ts`) still generates code based on the old API.
315
315
 
316
- 따라서 `pnpm sonamu scaffold` 실행 API 기반 래퍼 컴포넌트가 생성되며, 최신 패키지를 사용하는 프로젝트에서는 빌드 오류가 발생합니다.
316
+ Therefore, running `pnpm sonamu scaffold` generates wrapper components based on the old API, causing build errors in projects using the latest package.
317
317
 
318
- #### 구체적인 API 변경 사항
318
+ #### Specific API Changes
319
319
 
320
- **구 API (scaffolding이 생성하는 코드):**
320
+ **Old API (code generated by scaffolding):**
321
321
  ```typescript
322
322
  export function UserIdAsyncSelect<T extends UserSubsetKey>({
323
323
  subset,
324
324
  value,
325
325
  onValueChange,
326
- listParams, // ← API
327
- textField = "name", // ← API
328
- pageField, // ← API
326
+ listParams, // ← old API
327
+ textField = "name", // ← old API
328
+ pageField, // ← old API
329
329
  ...
330
330
  }: UserIdAsyncSelectProps<T>) {
331
- // 수동 상태 관리
331
+ // manual state management
332
332
  const [searchText, setSearchText] = useState("");
333
333
 
334
334
  const handleSearch = useCallback((text: string) => {
@@ -336,7 +336,7 @@ export function UserIdAsyncSelect<T extends UserSubsetKey>({
336
336
  }, []);
337
337
 
338
338
  return (
339
- <AsyncSelect // ← 컴포넌트
339
+ <AsyncSelect // ← old component
340
340
  config={UserAsyncIdConfig}
341
341
  subset={subset}
342
342
  listParams={{ ...listParams, [textField]: searchText }}
@@ -349,71 +349,71 @@ export function UserIdAsyncSelect<T extends UserSubsetKey>({
349
349
  }
350
350
  ```
351
351
 
352
- **신 API (실제 패키지 API):**
352
+ **New API (actual package API):**
353
353
  ```typescript
354
354
  export function UserIdAsyncSelect<T extends UserSubsetKey>({
355
355
  subset,
356
356
  value,
357
357
  onValueChange,
358
- baseListParams, // ← API
359
- displayField = "name", // ← API
360
- // pageField 없음 // ← 제거됨
358
+ baseListParams, // ← new API
359
+ displayField = "name", // ← new API
360
+ // pageField removed // ← removed
361
361
  ...
362
362
  }: UserIdAsyncSelectProps<T>) {
363
- // 상태 관리 없음 (내부에서 처리)
363
+ // no state management (handled internally)
364
364
 
365
365
  return (
366
- <IdAsyncSelect<number> // ← 컴포넌트 + 제네릭
366
+ <IdAsyncSelect<number> // ← new component + generic
367
367
  config={UserAsyncIdConfig}
368
368
  subset={subset}
369
369
  baseListParams={baseListParams}
370
370
  displayField={displayField}
371
- // 내부에서 검색 처리
371
+ // search handled internally
372
372
  ...
373
373
  />
374
374
  );
375
375
  }
376
376
  ```
377
377
 
378
- #### 주요 변경점
378
+ #### Key Changes
379
379
 
380
- 1. **컴포넌트명**: `AsyncSelect` → `IdAsyncSelect<T>` (제네릭 추가)
381
- 2. **Props 이름**:
380
+ 1. **Component name**: `AsyncSelect` → `IdAsyncSelect<T>` (generic added)
381
+ 2. **Prop names**:
382
382
  - `listParams` → `baseListParams`
383
383
  - `textField` → `displayField`
384
- - `pageField` 삭제
385
- 3. **검색 로직**: 외부 상태관리내부 처리 (useState, useCallback, onSearch 불필요)
386
- 4. **제네릭 타입**: PK 타입 명시 필요 (`<number>` 또는 `<string>`)
384
+ - `pageField` removed
385
+ 3. **Search logic**: external state management internal handling (useState, useCallback, onSearch no longer needed)
386
+ 4. **Generic type**: PK type must be specified explicitly (`<number>` or `<string>`)
387
387
 
388
- #### 수정이 필요한 파일들
388
+ #### Files That Need Updating
389
389
 
390
390
  ```
391
391
  src/components/
392
392
  ├── user/UserIdAsyncSelect.tsx
393
393
  ├── account/AccountIdAsyncSelect.tsx
394
394
  ├── announcement/AnnouncementIdAsyncSelect.tsx
395
- └── ... (모든 *IdAsyncSelect.tsx 파일)
395
+ └── ... (all *IdAsyncSelect.tsx files)
396
396
  ```
397
397
 
398
- #### 마이그레이션 체크리스트
398
+ #### Migration Checklist
399
399
 
400
- - [ ] 컴포넌트 import 변경: `AsyncSelect` → `IdAsyncSelect`
401
- - [ ] 제네릭 타입 파라미터 추가: `<number>` 또는 `<string>` (PK 타입에 따라)
402
- - [ ] Props 타입 정의 업데이트:
400
+ - [ ] Change component import: `AsyncSelect` → `IdAsyncSelect`
401
+ - [ ] Add generic type parameter: `<number>` or `<string>` (depending on PK type)
402
+ - [ ] Update Props type definitions:
403
403
  - [ ] `listParams` → `baseListParams`
404
404
  - [ ] `textField` → `displayField`
405
- - [ ] `pageField` 제거
406
- - [ ] 수동 상태 관리 제거:
407
- - [ ] `useState`, `useCallback` 제거
408
- - [ ] `onSearch` 핸들러 제거
409
- - [ ] JSX props 이름 변경:
405
+ - [ ] Remove `pageField`
406
+ - [ ] Remove manual state management:
407
+ - [ ] Remove `useState`, `useCallback`
408
+ - [ ] Remove `onSearch` handler
409
+ - [ ] Update prop names in JSX:
410
410
  - [ ] `listParams={...}` → `baseListParams={...}`
411
411
  - [ ] `textField={...}` → `displayField={...}`
412
- - [ ] `pageField` 제거
413
- - [ ] `onSearch` 제거
412
+ - [ ] Remove `pageField`
413
+ - [ ] Remove `onSearch`
414
414
 
415
- #### 이런 일이 발생하나?
415
+ #### Why does this happen?
416
416
 
417
- Sonamu의 scaffolding 생성 코드가 최신 패키지 API 반영하지 못한 상태에서, 사용자가 로컬의 Sonamu 소스를 수정하면서 패키지는 업데이트되었지만 scaffolding 템플릿은 그대로인 상황에서 발생합니다.
417
+ This occurs when the scaffolding generation code in Sonamu has not been updated to reflect the latest package API, while the user has modified the local Sonamu source and the package has been updated but the scaffolding template has not.
418
418
 
419
- **해결책**: 생성된 컴포넌트를 체크리스트에 따라 수동으로 수정하거나, Sonamu 코어의 scaffolding 템플릿을 최신 API로 업데이트해야 합니다.
419
+ **Fix**: Manually update the generated components according to the checklist above, or update the scaffolding template in the Sonamu core to use the latest API.