sonamu 0.10.5 → 0.10.7

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 (99) hide show
  1. package/dist/api/base-frame.d.ts +2 -0
  2. package/dist/api/base-frame.d.ts.map +1 -1
  3. package/dist/api/base-frame.js +8 -1
  4. package/dist/api/decorators.js +1 -1
  5. package/dist/api/sonamu.js +1 -1
  6. package/dist/bin/cli.js +195 -187
  7. package/dist/cone/cone-generator.js +3 -9
  8. package/dist/database/base-model.js +2 -2
  9. package/dist/database/knex.d.ts.map +1 -1
  10. package/dist/database/knex.js +2 -2
  11. package/dist/database/puri.d.ts +17 -0
  12. package/dist/database/puri.d.ts.map +1 -1
  13. package/dist/database/puri.js +102 -3
  14. package/dist/entity/entity-manager.js +1 -1
  15. package/dist/index.js +3 -3
  16. package/dist/migration/code-generation.js +6 -6
  17. package/dist/migration/migrator.d.ts.map +1 -1
  18. package/dist/migration/migrator.js +52 -7
  19. package/dist/migration/slack-confirm.js +1 -1
  20. package/dist/naite/naite-reporter.js +1 -1
  21. package/dist/syncer/checksum.js +1 -1
  22. package/dist/syncer/code-generator.js +1 -1
  23. package/dist/syncer/entity-operations.js +1 -1
  24. package/dist/syncer/syncer-actions.js +1 -1
  25. package/dist/syncer/syncer.js +1 -1
  26. package/dist/ui-web/assets/{index-BLX4zN8c.js → index-D0MHYbxl.js} +1 -1
  27. package/dist/ui-web/assets/index-Dx_JX4aQ.css +1 -0
  28. package/dist/ui-web/index.html +2 -2
  29. package/dist/utils/formatter.js +1 -1
  30. package/package.json +3 -3
  31. package/src/api/base-frame.ts +14 -1
  32. package/src/bin/cli.ts +268 -280
  33. package/src/cone/cone-generator.ts +2 -18
  34. package/src/database/__tests__/puri.test.ts +183 -0
  35. package/src/database/knex.ts +4 -1
  36. package/src/database/puri.ts +229 -2
  37. package/src/database/puri.types.test-d.ts +56 -0
  38. package/src/migration/code-generation.ts +5 -5
  39. package/src/migration/migrator.ts +81 -7
  40. package/src/skills/AGENTS.md +76 -50
  41. package/src/skills/sonamu/SKILL.md +46 -227
  42. package/src/skills/{sonamu/ai-agents.md → sonamu-ai-agents/SKILL.md} +3 -3
  43. package/src/skills/{sonamu/api.md → sonamu-api/SKILL.md} +3 -2
  44. package/src/skills/{sonamu/auth.md → sonamu-auth/SKILL.md} +9 -4
  45. package/src/skills/{sonamu/auth-plugins.md → sonamu-auth/references/plugins.md} +2 -7
  46. package/src/skills/sonamu-auth/references/user-id-migration-followups.md +192 -0
  47. package/src/skills/{sonamu/auth-migration.md → sonamu-auth/references/user-id-migration.md} +1 -195
  48. package/src/skills/sonamu-config/SKILL.md +203 -0
  49. package/src/skills/{sonamu → sonamu-config/references}/database.md +3 -8
  50. package/src/skills/sonamu-config/references/environments.md +178 -0
  51. package/src/skills/sonamu-config/references/server-options.md +400 -0
  52. package/src/skills/sonamu-entity/SKILL.md +180 -0
  53. package/src/skills/{sonamu/entity-validation-checklist.md → sonamu-entity/references/creation-workflow.md} +117 -8
  54. package/src/skills/sonamu-entity/references/design-guides.md +243 -0
  55. package/src/skills/sonamu-entity/references/field-types.md +170 -0
  56. package/src/skills/sonamu-entity/references/relations-detail.md +245 -0
  57. package/src/skills/{sonamu/entity-relations.md → sonamu-entity/references/relations.md} +1 -258
  58. package/src/skills/{sonamu → sonamu-entity/references}/subset.md +1 -11
  59. package/src/skills/sonamu-fixture/SKILL.md +180 -0
  60. package/src/skills/{sonamu/fixture-cli.md → sonamu-fixture/references/cli-usage.md} +5 -176
  61. package/src/skills/{sonamu → sonamu-fixture/references}/cone.md +4 -14
  62. package/src/skills/sonamu-frontend/SKILL.md +142 -0
  63. package/src/skills/sonamu-frontend/references/components.md +323 -0
  64. package/src/skills/sonamu-frontend/references/examples.md +64 -0
  65. package/src/skills/sonamu-frontend/references/hooks.md +273 -0
  66. package/src/skills/sonamu-frontend/references/runtime.md +165 -0
  67. package/src/skills/{sonamu → sonamu-frontend/references}/scaffolding.md +3 -8
  68. package/src/skills/{sonamu/i18n.md → sonamu-i18n/SKILL.md} +2 -2
  69. package/src/skills/{sonamu/migration.md → sonamu-migration/SKILL.md} +1 -1
  70. package/src/skills/{sonamu/naite.md → sonamu-naite/SKILL.md} +5 -5
  71. package/src/skills/sonamu-query/SKILL.md +48 -0
  72. package/src/skills/sonamu-query/references/model-patterns.md +390 -0
  73. package/src/skills/{sonamu → sonamu-query/references}/model.md +1 -401
  74. package/src/skills/{sonamu → sonamu-query/references}/puri.md +31 -243
  75. package/src/skills/sonamu-query/references/search.md +238 -0
  76. package/src/skills/{sonamu → sonamu-query/references}/upsert.md +1 -6
  77. package/src/skills/{sonamu/tasks.md → sonamu-tasks/SKILL.md} +1 -1
  78. package/src/skills/sonamu-testing/SKILL.md +251 -0
  79. package/src/skills/{sonamu/testing-devrunner.md → sonamu-testing/references/devrunner.md} +4 -9
  80. package/src/skills/sonamu-testing/references/helpers.md +185 -0
  81. package/src/skills/sonamu-testing/references/patterns.md +263 -0
  82. package/src/skills/sonamu-testing/references/pitfalls.md +588 -0
  83. package/src/skills/sonamu-testing/references/quick-start.md +285 -0
  84. package/src/skills/sonamu-testing/references/type-safety.md +172 -0
  85. package/src/skills/sonamu-testing/references/writing-plan.md +375 -0
  86. package/src/skills/{sonamu/vector.md → sonamu-vector/SKILL.md} +1 -1
  87. package/dist/ui-web/assets/index-Dx4ap5i4.css +0 -1
  88. package/src/skills/commands/sonamu-skills.md +0 -20
  89. package/src/skills/project/README.md +0 -19
  90. package/src/skills/project/architecture.md +0 -373
  91. package/src/skills/sonamu/cdd.md +0 -129
  92. package/src/skills/sonamu/config.md +0 -772
  93. package/src/skills/sonamu/create-sonamu.md +0 -208
  94. package/src/skills/sonamu/entity-basic.md +0 -678
  95. package/src/skills/sonamu/framework-change.md +0 -96
  96. package/src/skills/sonamu/frontend.md +0 -915
  97. package/src/skills/sonamu/project-init.md +0 -477
  98. package/src/skills/sonamu/skill-contribution.md +0 -247
  99. package/src/skills/sonamu/testing.md +0 -2163
@@ -1,772 +0,0 @@
1
- ---
2
- name: sonamu-config
3
- description: Sonamu project configuration. .env environment variables, sonamu.config.ts settings. Use when configuring a new Sonamu project.
4
- ---
5
-
6
- # Sonamu Project Configuration
7
-
8
- A guide for setting up `.env` and `sonamu.config.ts` after project creation.
9
-
10
- ## .env File
11
-
12
- Location: `packages/api/.env`
13
-
14
- ### Default Environment Variables (generated by create-sonamu)
15
-
16
- ```env
17
- # Database Configuration
18
- DB_HOST=0.0.0.0
19
- DB_PORT=5432
20
- DB_USER=postgres
21
- DB_PASSWORD=1234
22
- CONTAINER_NAME=myproject-container
23
- DATABASE_NAME=myproject
24
- PROJECT_NAME=myproject
25
- ```
26
-
27
- ### Additional Environment Variables (as needed)
28
-
29
- ```env
30
- # Session (must be changed in production)
31
- SESSION_SECRET=your-secret-key-change-in-production
32
- SESSION_SALT=random-16-char-salt
33
-
34
- # AWS S3 (for file uploads)
35
- AWS_ACCESS_KEY_ID=your-access-key
36
- AWS_SECRET_ACCESS_KEY=your-secret-key
37
- S3_REGION=ap-northeast-2
38
- S3_BUCKET=your-bucket-name
39
-
40
- # Slack notifications (for migration confirmation)
41
- SLACK_BOT_TOKEN=xoxb-your-token
42
- SLACK_CHANNEL_ID=C0123456789
43
- ```
44
-
45
- ### Environment Variable Reference
46
-
47
- | Variable | Required | Description |
48
- | ----------------------- | -------- | --------------------------------------------------------- |
49
- | `DB_HOST` | ✓ | DB host (Docker: `0.0.0.0`, external DB: the relevant IP) |
50
- | `DB_PORT` | ✓ | DB port (default: `5432`) |
51
- | `DB_USER` | ✓ | DB username (default: `postgres`) |
52
- | `DB_PASSWORD` | ✓ | DB password |
53
- | `DATABASE_NAME` | ✓ | Database name |
54
- | `PROJECT_NAME` | ✓ | Project name (used in Docker, config) |
55
- | `CONTAINER_NAME` | | Docker container name |
56
- | `SESSION_SECRET` | | Session encryption key (required in production) |
57
- | `SESSION_SALT` | | Session salt (16 characters) |
58
- | `AWS_ACCESS_KEY_ID` | | Required when using S3 |
59
- | `AWS_SECRET_ACCESS_KEY` | | Required when using S3 |
60
- | `S3_REGION` | | S3 region (default: `ap-northeast-2`) |
61
- | `S3_BUCKET` | | S3 bucket name |
62
-
63
- ---
64
-
65
- ## sonamu.config.ts
66
-
67
- Location: `packages/api/src/sonamu.config.ts`
68
-
69
- ### Full Structure
70
-
71
- ```typescript
72
- import path from "node:path";
73
- import { CachePresets, defineConfig } from "sonamu";
74
- import { drivers as cacheDrivers, store } from "sonamu/cache";
75
- import { drivers } from "sonamu/storage";
76
-
77
- const host = "localhost";
78
- const port = 34900;
79
-
80
- export default defineConfig({
81
- projectName: process.env.PROJECT_NAME ?? "MyProject",
82
- api: {
83
- /* API settings */
84
- },
85
- i18n: {
86
- /* i18n settings */
87
- },
88
- sync: {
89
- /* sync settings */
90
- },
91
- database: {
92
- /* DB settings */
93
- },
94
- logging: {
95
- /* logging settings (disable with false) */
96
- },
97
- test: {
98
- /* test settings */
99
- },
100
- server: {
101
- /* server settings */
102
- },
103
- slackConfirm: {
104
- /* Production migration Slack approval */
105
- },
106
- });
107
- ```
108
-
109
- ### Key Section Settings
110
-
111
- #### projectName
112
-
113
- ```typescript
114
- projectName: process.env.PROJECT_NAME ?? "MyProject",
115
- ```
116
-
117
- #### api
118
-
119
- ```typescript
120
- api: {
121
- dir: "api", // API directory name
122
- timezone: "Asia/Seoul", // timezone
123
- route: {
124
- prefix: "/api", // API route prefix
125
- },
126
- },
127
- ```
128
-
129
- #### i18n
130
-
131
- ```typescript
132
- i18n: {
133
- defaultLocale: "ko",
134
- supportedLocales: ["ko", "en"],
135
- },
136
- ```
137
-
138
- See `i18n.md` for details.
139
-
140
- #### sync
141
-
142
- ```typescript
143
- sync: {
144
- targets: ["web"], // target packages for type sync
145
- },
146
- ```
147
-
148
- #### database
149
-
150
- ```typescript
151
- database: {
152
- database: "pg", // PostgreSQL
153
- name: process.env.DATABASE_NAME ?? "database_name",
154
- defaultOptions: {
155
- connection: {
156
- host: process.env.DB_HOST || "0.0.0.0",
157
- port: Number(process.env.DB_PORT) || 5432,
158
- user: process.env.DB_USER || "postgres",
159
- password: process.env.DB_PASSWORD,
160
- },
161
- },
162
- },
163
- ```
164
-
165
- See `database.md` for details.
166
-
167
- #### test
168
-
169
- ```typescript
170
- test: {
171
- parallel: true, // enable parallel testing
172
- maxWorkers: 4, // number of workers
173
- devRunner: { // Vitest resident instance inside Dev server
174
- enabled: true,
175
- watch: true,
176
- },
177
- },
178
- ```
179
-
180
- See `testing.md`, `testing-devrunner.md` for details.
181
-
182
- #### server
183
-
184
- ```typescript
185
- server: {
186
- listen: { port: 34900, host: "localhost" },
187
- plugins: { /* plugin settings */ },
188
- auth: true,
189
- apiConfig: { /* API settings */ },
190
- storage: { /* storage settings */ },
191
- cache: { /* cache settings */ },
192
- lifecycle: { /* lifecycle hooks */ },
193
- },
194
- ```
195
-
196
- ---
197
-
198
- ## server.auth Details (better-auth Authentication)
199
-
200
- Sonamu provides an authentication system using **better-auth**.
201
-
202
- ### 1. Auto-generate Entities
203
-
204
- ```bash
205
- pnpm sonamu auth generate
206
- ```
207
-
208
- Generated entities:
209
-
210
- - **User** - user (id, name, email, email_verified, image)
211
- - **Session** - session (token, expires_at, user_id)
212
- - **Account** - account (provider_id, access_token, etc.)
213
- - **Verification** - email verification
214
-
215
- ### 2. server.auth Configuration
216
-
217
- ```typescript
218
- server: {
219
- // Basic configuration (emailAndPassword enabled)
220
- auth: {
221
- emailAndPassword: { enabled: true },
222
- },
223
-
224
- // Add social login
225
- // auth: {
226
- // emailAndPassword: { enabled: true },
227
- // socialProviders: {
228
- // google: {
229
- // clientId: process.env.GOOGLE_CLIENT_ID!,
230
- // clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
231
- // },
232
- // },
233
- // },
234
- }
235
- ```
236
-
237
- ### 3. Authentication API Endpoints
238
-
239
- Automatically registered under the `/api/auth/*` path:
240
-
241
- | Endpoint | Method | Description |
242
- | ------------------------- | ------ | ----------- |
243
- | `/api/auth/sign-up/email` | POST | Sign up |
244
- | `/api/auth/sign-in/email` | POST | Sign in |
245
- | `/api/auth/sign-out` | POST | Sign out |
246
- | `/api/auth/get-session` | GET | Get session |
247
-
248
- ### 4. Accessing user/session from Context
249
-
250
- ```typescript
251
- @api({ httpMethod: "GET", guards: ["user"] })
252
- async me(): Promise<UserSubsetA | null> {
253
- const { user, session } = Sonamu.getContext();
254
- if (!user) return null;
255
- return this.findById("A", user.id);
256
- }
257
- ```
258
-
259
- ### 5. Field Mapping (camelCase → snake_case)
260
-
261
- better-auth uses camelCase, Sonamu uses snake_case. Automatic mapping is applied:
262
-
263
- | better-auth | Sonamu |
264
- | --------------- | ---------------- |
265
- | `emailVerified` | `email_verified` |
266
- | `createdAt` | `created_at` |
267
- | `userId` | `user_id` |
268
- | `expiresAt` | `expires_at` |
269
-
270
- ---
271
-
272
- ## Guards System (Access Control)
273
-
274
- The Sonamu permission system consists of 2 components:
275
-
276
- 1. **GuardKeys** - permission key definitions
277
- 2. **guardHandler** - permission check logic
278
-
279
- ### 1. Extending GuardKeys (Custom Permissions)
280
-
281
- **Source code:** `modules/sonamu/src/api/decorators.ts` (GuardKeys interface)
282
-
283
- Provided by default: `query`, `admin`, `user`
284
-
285
- To add custom permissions, extend in `src/typings/sonamu.d.ts`:
286
-
287
- **File location:** `src/typings/sonamu.d.ts`
288
-
289
- ```typescript
290
- import {} from "sonamu";
291
-
292
- declare module "sonamu" {
293
- export interface GuardKeys {
294
- query: true;
295
- admin: true;
296
- user: true;
297
- manager: true; // added
298
- superadmin: true; // added
299
- }
300
- }
301
- ```
302
-
303
- ### 2. Using guards in the @api Decorator
304
-
305
- ```typescript
306
- // user.model.ts
307
- import { api } from "sonamu";
308
-
309
- class UserModelClass extends BaseModelClass {
310
- @api({ httpMethod: "GET", guards: ["user"] })
311
- async me(): Promise<UserSubsetA | null> {
312
- // only logged-in users can access
313
- }
314
-
315
- @api({ httpMethod: "DELETE", guards: ["admin"] })
316
- async del(ids: number[]): Promise<number> {
317
- // only admins can access
318
- }
319
-
320
- @api({ httpMethod: "GET", guards: ["admin", "manager"] })
321
- async adminList(): Promise<UserSubsetA[]> {
322
- // admin or manager permission
323
- }
324
- }
325
- ```
326
-
327
- ### 3. Implementing guardHandler
328
-
329
- ```typescript
330
- import { Sonamu } from "sonamu";
331
-
332
- // sonamu.config.ts
333
- apiConfig: {
334
- guardHandler: (guard, request, api) => {
335
- // Access user from better-auth Context
336
- const { user } = Sonamu.getContext();
337
-
338
- switch (guard) {
339
- case "user":
340
- // login required
341
- if (!user) {
342
- throw new Error("Login is required");
343
- }
344
- break;
345
-
346
- case "admin":
347
- // admin permission (requires adding role field to User entity)
348
- if (!user || (user as any).role !== "admin") {
349
- throw new Error("Only admins can access");
350
- }
351
- break;
352
-
353
- case "manager":
354
- // manager permission (custom Guard example)
355
- if (!user || !["admin", "manager"].includes((user as any).role)) {
356
- throw new Error("Manager permission is required");
357
- }
358
- break;
359
-
360
- case "query":
361
- // allow all users (including unauthenticated)
362
- break;
363
- }
364
- },
365
- },
366
- ```
367
-
368
- **NOTE:** better-auth's default User entity does not have a `role` field. If role-based authentication is needed, add a `role` field to the User entity or create a separate Role entity.
369
-
370
- ### Menu/Screen Access Control by Permission
371
-
372
- UI access control by permission is handled **on the frontend**:
373
-
374
- ```typescript
375
- // web/src/lib/auth.ts
376
- export const menuPermissions = {
377
- dashboard: ["user", "admin", "manager"],
378
- userManagement: ["admin"],
379
- settings: ["admin", "manager"],
380
- reports: ["admin", "manager"],
381
- };
382
-
383
- export function canAccess(userRole: string, menu: keyof typeof menuPermissions) {
384
- return menuPermissions[menu].includes(userRole);
385
- }
386
- ```
387
-
388
- ```tsx
389
- // web/src/components/Sidebar.tsx
390
- {
391
- canAccess(user.role, "userManagement") && (
392
- <MenuItem href="/admin/users">User Management</MenuItem>
393
- );
394
- }
395
- ```
396
-
397
- ---
398
-
399
- ## server.plugins Details
400
-
401
- ### session (Session Management)
402
-
403
- ```typescript
404
- session: {
405
- secret: process.env.SESSION_SECRET || "change-this-in-production",
406
- salt: process.env.SESSION_SALT || "mq9hDxBCDbsQDR6N",
407
- cookie: {
408
- domain: "localhost", // change to actual domain in production
409
- path: "/",
410
- maxAge: 60 * 60 * 24 * 365 * 10, // 10 years
411
- },
412
- },
413
- ```
414
-
415
- **Production checklist:**
416
-
417
- - `SESSION_SECRET`: must be changed to a strong random string
418
- - `SESSION_SALT`: change to a 16-character random string
419
- - `cookie.domain`: change to the actual domain
420
-
421
- ### static (Static Files)
422
-
423
- ```typescript
424
- static: {
425
- root: path.join(import.meta.dirname, "/../", "public"),
426
- prefix: "/api/public",
427
- },
428
- ```
429
-
430
- ### multipart (File Upload)
431
-
432
- ```typescript
433
- multipart: {
434
- limits: {
435
- fileSize: 1024 * 1024 * 30, // 30MB
436
- },
437
- },
438
- ```
439
-
440
- ---
441
-
442
- ## server.storage Details
443
-
444
- ### Local File System
445
-
446
- ```typescript
447
- storage: {
448
- drivers: {
449
- fs: drivers.fs({
450
- location: path.join(import.meta.dirname, "/../public/uploaded"),
451
- visibility: "public",
452
- urlBuilder: {
453
- async generateURL(key) {
454
- return `/api/public/uploaded/${key}`;
455
- },
456
- async generateSignedURL(key) {
457
- return `/api/public/uploaded/${key}`;
458
- },
459
- },
460
- }),
461
- },
462
- },
463
- ```
464
-
465
- ### AWS S3
466
-
467
- ```typescript
468
- storage: {
469
- drivers: {
470
- s3: drivers.s3({
471
- credentials: {
472
- accessKeyId: process.env.AWS_ACCESS_KEY_ID ?? "",
473
- secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY ?? "",
474
- },
475
- region: process.env.S3_REGION ?? "ap-northeast-2",
476
- bucket: process.env.S3_BUCKET ?? "my-bucket",
477
- visibility: "private",
478
- }),
479
- },
480
- },
481
- ```
482
-
483
- ---
484
-
485
- ## server.cache Details
486
-
487
- Sonamu uses **BentoCache**.
488
-
489
- ```typescript
490
- import { drivers as cacheDrivers, store } from "sonamu/cache";
491
-
492
- cache: {
493
- default: "main",
494
- stores: {
495
- main: store().useL1Layer(cacheDrivers.memory({ maxSize: "50mb" })),
496
- },
497
- ttl: "5m",
498
- prefix: "",
499
- },
500
- ```
501
-
502
- **Available drivers:**
503
-
504
- - `memory` - in-memory cache (default)
505
- - `file` - file-based cache
506
- - `redis` - Redis cache
507
- - `knex` - DB-based cache
508
-
509
- For other drivers, refer to the [BentoCache documentation](https://bentocache.dev/).
510
-
511
- ---
512
-
513
- ## server.apiConfig Details
514
-
515
- ### contextProvider
516
-
517
- Inject additional information into Context per request:
518
-
519
- ```typescript
520
- contextProvider: (defaultContext, request) => {
521
- return {
522
- ...defaultContext,
523
- ip: request.ip,
524
- session: request.session,
525
- body: request.body,
526
- // custom fields can be added
527
- };
528
- },
529
- ```
530
-
531
- ### guardHandler
532
-
533
- Handle API guard processing:
534
-
535
- ```typescript
536
- guardHandler: (guard, request, api) => {
537
- // access control based on guard value
538
- if (guard === "admin" && request.user?.role !== "admin") {
539
- throw new Error("Only admins can access");
540
- }
541
- },
542
- ```
543
-
544
- ### cacheControlHandler
545
-
546
- Set HTTP cache headers:
547
-
548
- ```typescript
549
- cacheControlHandler: (req) => {
550
- switch (req.type) {
551
- case "assets":
552
- if (req.path.match(/-[a-f0-9]+\./)) {
553
- return CachePresets.immutable; // files with hash
554
- }
555
- return CachePresets.longLived;
556
-
557
- case "api":
558
- if (req.method === "GET") {
559
- return CachePresets.shortLived;
560
- }
561
- return CachePresets.noCache;
562
-
563
- case "ssr":
564
- return CachePresets.ssr;
565
-
566
- case "csr":
567
- return CachePresets.shortLived;
568
- }
569
- },
570
- ```
571
-
572
- ---
573
-
574
- ## server.lifecycle Details
575
-
576
- ```typescript
577
- lifecycle: {
578
- onStart: () => {
579
- console.log(`🌲 Server listening on http://${host}:${port}`);
580
- },
581
- onShutdown: () => {
582
- console.log("graceful shutdown");
583
- // close DB connections, clean up resources, etc.
584
- },
585
- onError: (error, request, reply) => {
586
- console.error(error);
587
- reply.status(500).send({
588
- name: error.name,
589
- message: error.message,
590
- });
591
- },
592
- },
593
- ```
594
-
595
- ---
596
-
597
- ## Sonamu Local Development Environment Setup
598
-
599
- **When is this needed:**
600
-
601
- - When modifying the Sonamu framework source code during development
602
- - When linking a local Sonamu repository to a project for development
603
-
604
- **Problem:**
605
-
606
- When linking Sonamu with pnpm link, type errors occur at build time:
607
-
608
- ```
609
- error TS2345: Argument of type 'ZodNumber' is not assignable to parameter...
610
- Type '2' is not assignable to type '3'.
611
- ```
612
-
613
- **Cause:**
614
-
615
- - The linked Sonamu and the project each maintain their own `node_modules`
616
- - TypeScript type mismatches occur due to different versions of shared dependencies (e.g. zod)
617
- - TypeScript simultaneously references two different type definitions, causing errors
618
-
619
- **Solution:**
620
-
621
- ### 1. Add override to pnpm-workspace.yaml
622
-
623
- In the project root's `pnpm-workspace.yaml`:
624
-
625
- ```yaml
626
- overrides:
627
- sonamu: link:../../sonamu/modules/sonamu
628
- ```
629
-
630
- ### 2. Specify published version in packages/api/package.json
631
-
632
- ```json
633
- {
634
- "dependencies": {
635
- "sonamu": "^0.7.45" // specify the latest published version
636
- }
637
- }
638
- ```
639
-
640
- ### 3. Run install
641
-
642
- ```bash
643
- pnpm install
644
- ```
645
-
646
- ### 4. Verify build
647
-
648
- ```bash
649
- cd packages/api
650
- pnpm build
651
- ```
652
-
653
- **How it works:**
654
-
655
- - **TypeScript type check**: references type definitions from the npm registry based on the published version in `package.json`
656
- - **Actual runtime**: `pnpm overrides` local link takes priority and runs local source code
657
- - Separates type checking and runtime to resolve version mismatch issues
658
-
659
- **Notes:**
660
-
661
- - Changes to Sonamu source code are immediately reflected in the project
662
- - Restarting the project is required after building Sonamu
663
- - For general project development, using the npm version is recommended
664
-
665
- ---
666
-
667
- ## Environment-Specific Configuration
668
-
669
- ### Development Environment
670
-
671
- ```env
672
- # packages/api/.env
673
- DB_HOST=0.0.0.0
674
- DB_PORT=5432
675
- DB_USER=postgres
676
- DB_PASSWORD=1234
677
- DATABASE_NAME=myproject
678
- PROJECT_NAME=myproject
679
- ```
680
-
681
- ### Production Environment
682
-
683
- ```env
684
- # packages/api/.env.production
685
- DB_HOST=your-rds-endpoint.amazonaws.com
686
- DB_PORT=5432
687
- DB_USER=produser
688
- DB_PASSWORD=strong-password-here
689
- DATABASE_NAME=myproject_prod
690
- PROJECT_NAME=myproject
691
-
692
- SESSION_SECRET=very-long-random-string-at-least-32-chars
693
- SESSION_SALT=random16charstr!
694
-
695
- AWS_ACCESS_KEY_ID=AKIA...
696
- AWS_SECRET_ACCESS_KEY=...
697
- S3_REGION=ap-northeast-2
698
- S3_BUCKET=myproject-prod-bucket
699
- ```
700
-
701
- ---
702
-
703
- ## server Additional Options
704
-
705
- ### baseUrl
706
-
707
- ```typescript
708
- server: {
709
- baseUrl: "https://api.example.com", // external access URL (default: host:port)
710
- }
711
- ```
712
-
713
- ### fastify
714
-
715
- Pass Fastify server options directly (excluding `logger`).
716
-
717
- ### Full Plugin List
718
-
719
- | Plugin | Type | Description |
720
- | ----------- | ------------------------------------ | ---------------------------------------- |
721
- | `compress` | `boolean \| FastifyCompressOptions` | Response compression (@fastify/compress) |
722
- | `cors` | `boolean \| FastifyCorsOptions` | CORS configuration |
723
- | `formbody` | `boolean \| FastifyFormbodyOptions` | x-www-form-urlencoded parsing |
724
- | `multipart` | `boolean \| FastifyMultipartOptions` | File upload |
725
- | `qs` | `boolean \| QsPluginOptions` | Query string parsing |
726
- | `session` | session config | Session management |
727
- | `sse` | `boolean \| SsePluginOptions` | Server-Sent Events |
728
- | `static` | `boolean \| FastifyStaticOptions` | Static file serving |
729
- | `custom` | `(server: FastifyInstance) => void` | Custom plugin registration function |
730
-
731
- ## logging
732
-
733
- Define logging configuration. Set to `false` to completely disable logging.
734
-
735
- ```typescript
736
- logging: false, // disable logging
737
- // or
738
- logging: {
739
- sinks: { /* define log output targets */ },
740
- filters: { /* define filters */ },
741
- },
742
- ```
743
-
744
- ## slackConfirm
745
-
746
- Activates a Slack-based approval process for production DB migrations.
747
-
748
- ```typescript
749
- slackConfirm: {
750
- targets: ["production"], // list of DB keys requiring approval
751
- botToken: process.env.SLACK_BOT_TOKEN ?? "", // Slack Bot Token (xoxb-...)
752
- channelId: process.env.SLACK_CHANNEL_ID ?? "", // Slack Channel ID (C...)
753
- },
754
- ```
755
-
756
- ---
757
-
758
- ## Post-Configuration Checklist
759
-
760
- 1. Confirm `.env` file is created
761
- 2. Start Docker: `pnpm docker:up`
762
- 3. Verify build: `pnpm build`
763
- 4. Start server: `pnpm dev`
764
- 5. Access Sonamu UI: http://localhost:34900/sonamu-ui
765
-
766
- Before production deployment:
767
-
768
- - [ ] Change `SESSION_SECRET`
769
- - [ ] Change `SESSION_SALT`
770
- - [ ] Change `cookie.domain` to the actual domain
771
- - [ ] Configure S3 (if needed)
772
- - [ ] Add error handling logic