@gaonjs/cli 0.65.2 → 0.65.4
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.
|
@@ -123,7 +123,7 @@ import 하면 순환 참조가 생기므로, 실제 연결은 부팅 시 프레
|
|
|
123
123
|
| `t.enum([...] as const)` | `text + CHECK` | union type | E-4 (a) |
|
|
124
124
|
| `t.uuid()` | `uuid` | `string` | |
|
|
125
125
|
| `t.uuidPk()` | `uuid` | `string` | PK · `gen_random_uuid()` (E-4 (d)) |
|
|
126
|
-
| `t.json<T>()` / `t.jsonb<T>()` | `jsonb` | `T` (제네릭) | Postgres 권장 = jsonb |
|
|
126
|
+
| `t.json<T>()` / `t.jsonb<T>()` | `jsonb` | `T` (제네릭) | Postgres 권장 = jsonb · 값은 **`T` 를 그대로** 넘긴다 (결정 461) |
|
|
127
127
|
| `t.int()` | `integer` | `number` | 4바이트 정수 |
|
|
128
128
|
| `t.smallint()` | `smallint` | `number` | 2바이트 정수 |
|
|
129
129
|
| `t.float()` | `real` | `number` | 4바이트 부동소수 |
|
|
@@ -1219,6 +1219,14 @@ await Post.upsert({ id, title, body }) // onConflict 생략 = 기
|
|
|
1219
1219
|
- **벌크 3종은 행이 아니라 `{ count }` 를 준다** (결정 90) — 반환을 `Rec[]` 처럼
|
|
1220
1220
|
다루지 말 것. 삽입된 행이 필요하면 소량은 `create()`, 대량은 유니크 키 재조회.
|
|
1221
1221
|
`throw` 하던 옛 계약(비 RETURNING 방언)은 폐기 — MySQL 도 그냥 `count` 를 준다.
|
|
1222
|
+
- **jsonb 컬럼에는 `T` 를 그대로 넣는다 — JSON 문자열로 미리 인코딩하지 말 것** (결정 461).
|
|
1223
|
+
`t.jsonb<string[]>()` 에는 `['a','b']` 를, `t.jsonb<string>()` 에는 `'a@b.com'` 를 넘긴다.
|
|
1224
|
+
프레임웍이 방언 무관으로 직렬화하므로 `JSON.stringify` 를 손수 부르면 **이중 인코딩**돼
|
|
1225
|
+
읽을 때 문자열 안에 JSON 이 든 값이 나온다. 미리 인코딩한 텍스트를 꼭 넣어야 하면
|
|
1226
|
+
`Model.query()` 탈출구를 쓴다. (옛 판은 이 직렬화가 mysql 에서만 돌아
|
|
1227
|
+
`t.jsonb<string[]>()` 이 postgres 에서 **빈 배열을 `{}` 로 조용히 저장**하거나
|
|
1228
|
+
`invalid input syntax for type json` 으로 죽었다 — `jsonbValues.dialect.integration.test.ts` 가
|
|
1229
|
+
양 방언으로 고정한다.)
|
|
1222
1230
|
- **loop 안 관계 lazy 호출 = N+1** — doctor **n-plus-one** 검사가 잡는다.
|
|
1223
1231
|
목록은 `include()` 로.
|
|
1224
1232
|
- **스키마 파일명은 camelCase** — 테이블 `posts_tags` → 파일 `postsTags.ts`
|
|
@@ -1345,4 +1353,5 @@ await Post.upsert({ id, title, body }) // onConflict 생략 = 기
|
|
|
1345
1353
|
| 결정 336 | 중첩 hidden dot-path 실지원(290 대체) — 중첩 객체·type:{} 서브도큐먼트·서브도큐먼트 배열 · 직렬화 경계 상속 스레딩 · 지원 밖 위치는 fail-loud(§7.1) |
|
|
1346
1354
|
| E-4 | 컬럼 타입·수식어·체이닝 확장 · `Post.query()` 정정 · Serialized 명명 |
|
|
1347
1355
|
| **결정 456** | **수식어 × 빌더 매트릭스(§3.1) + `t.belongsTo(...).unique()` 신설** — "모든 타입에 적용" 이라 적고 조합표가 없어 `t.belongsTo('x').unique()` 가 migrate 를 죽였다(auction 실측). 1:1 FK 는 정당한 도메인 요구라 `unique` 는 **열고**, `default`·`check` 는 참조 무결성과 어긋나 **닫는다**(표에 이유까지 명기 · `type-tests/columnModifiers.test-d.ts` 가 매트릭스를 타입으로 고정) |
|
|
1356
|
+
| 결정 461 | `t.jsonb<T>()` 값 직렬화가 **방언 무관** — mysql 전용이던 탓에 pg 에서 배열이 PG 배열 리터럴로 나가 `[]`→`{}` 무신호 손상·`['a']`→throw 였다. 이제 `T` 를 그대로 넘긴다(문자열 포함 · §2·함정) |
|
|
1348
1357
|
| 결정 460 | unique·PK 컬럼의 `.index()` 는 DDL 이 건너뛴다(중복) — 조용한 no-op 을 `gaon doctor` `redundant-index` **경고**로 표면화(§3 `.index()`) · 빌더·타입은 무변경(체이닝 자유는 의도된 성질) |
|
|
@@ -51,9 +51,11 @@ const props = pageProps<'web:posts#index'>()
|
|
|
51
51
|
// 앱이 app.config sharedProps 로 등록한 키(locale·theme 등)도 같은 자리에서 읽힌다(결정 150).
|
|
52
52
|
```
|
|
53
53
|
**i18n 문구는 여기가 아니라 클라 `t()` 로 온다**(결정 454) — `import { t } from 'gaonjs/vue'`
|
|
54
|
-
로 `.vue` 에서 직접 부른다. 카탈로그는
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
로 `.vue` 에서 직접 부른다. 카탈로그는 **`apps/<앱>/locales/<로케일>/frontend.json`**
|
|
55
|
+
(앱마다 필수 · 결정 459) 하나이고 — **루트 공용 `locales/` 는 폐지됐다** — 서버 전용
|
|
56
|
+
문구(`apps/<앱>/locales/<로케일>/backend.json` · `domain/locales/<로케일>/backend.json`)를
|
|
57
|
+
클라에서 참조하면 컴파일 에러다(`agents/i18n.md`). 여러 앱이 함께 쓰는 문구는 앱마다
|
|
58
|
+
같은 키를 복제한다(doctor **i18n-app-scope**). 컨트롤러 render props·`sharedProps` 로 번역을
|
|
57
59
|
흘려보내던 옛 경로(결정 213)는 탈출구로만 남는다 — `sharedProps` 는 번역과 무관한 앱 공유
|
|
58
60
|
값(테마·플래그)에 쓴다.
|
|
59
61
|
`pageProps<K>()` 반환에도 교차되어 `props.csrf` 로도 읽히지만, 라우트 키가 필요 없는
|
|
@@ -340,7 +342,7 @@ import PageShell from '@shared/components/ui/PageShell.vue'
|
|
|
340
342
|
| 원자 (18) | Button · Input · Label · Badge · Card · CardHeader · CardTitle · CardDescription · CardContent · CardFooter · Alert · AlertTitle · AlertDescription · Form · FormField · FormMessage · Dialog · Sheet |
|
|
341
343
|
| 블록 (4 · 결정 106) | PageShell · PageHeader · EmptyState · Pagination |
|
|
342
344
|
|
|
343
|
-
**컴포넌트 사용법 — 킷
|
|
345
|
+
**컴포넌트 사용법 — 킷 22종 전수 (첫 시도용 · 소스 안 읽어도 되게 · O-2).** 카탈로그가
|
|
344
346
|
이름만이면 슬롯/prop 을 소스에서 찾아야 한다 — 표면 전부를 여기 못박는다. 아래 값은
|
|
345
347
|
`gaon g ui-kit` 이 심는 **템플릿 소스의 `defineProps`·`defineEmits`·`<slot>` 에서 확인한
|
|
346
348
|
것**이다(그래도 정본은 프로젝트에 복사된 여러분의 파일이다 — 고쳤다면 고친 쪽이 맞다).
|
|
@@ -713,6 +715,7 @@ async function runSearch(q: string) {
|
|
|
713
715
|
| 결정 206 | UI 킷 §8 슬롯·props 요약표(카탈로그가 이름만이라 소스 열람 유발 · O-2 해소) · named slot 비대칭 명시(PageHeader `#actions` 복수 vs EmptyState `#action` 단수) |
|
|
714
716
|
| 결정 213 | (구) i18n Vue 소비 = 서버 주도 render props/sharedProps 만 — **결정 454 로 부분 번복**(탈출구로 존속) |
|
|
715
717
|
| 결정 454 | 클라 `t()` 신설(`gaonjs/vue`) · 카탈로그 backend/frontend 분리 · 두 갈래 키 타입 · 앱별 카탈로그 청크(`agents/i18n.md`) |
|
|
718
|
+
| 결정 459 | locale 카탈로그 소유자 2개로 재편(454 부분 반전) — 루트 공용 `locales/` 폐지 · 화면 문구 = `apps/<앱>/locales/<로케일>/frontend.json`(앱마다 필수) · 공유 문구는 앱마다 키 복제(doctor i18n-app-scope · `agents/i18n.md`) |
|
|
716
719
|
| 결정 217 | doctor `shared-purity`(구 shared-composable-purity 개명) — `shared/` 의 .ts 컴포저블 + .vue 컴포넌트 순수성(pageProps/api 호출·domain 값 import 금지 · §4) |
|
|
717
720
|
| 결정 271 | W4 표면 정합 — `Head` 재수출(`gaonjs/vue` · `<Head title>` 제목 조합자 발화) 외 표면/최적화 4건(§12 결정 271) |
|
|
718
721
|
| 결정 299 | 타입 브리지 PropsOf 정정 — 유니온 분배(조건부 redirect 혼합 액션의 never 붕괴 봉합) + `this.json(data)` 언랩(`{json,status}` 래퍼 타입 거짓 봉합 · `JsonResult<T>` 제네릭) (§2) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gaonjs/cli",
|
|
3
|
-
"version": "0.65.
|
|
3
|
+
"version": "0.65.4",
|
|
4
4
|
"description": "Gaon CLI — 스캐폴딩·제너레이터·마이그레이션·dev/serve/work/hub·doctor·check (bin: gaon)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
33
|
"typescript": "^5.9.0",
|
|
34
34
|
"vite": "^7.0.0",
|
|
35
|
+
"@gaonjs/config": "0.26.2",
|
|
35
36
|
"@gaonjs/async": "0.22.0",
|
|
36
|
-
"@gaonjs/config": "0.26.1",
|
|
37
|
-
"@gaonjs/core": "0.3.0",
|
|
38
|
-
"@gaonjs/data": "0.26.3",
|
|
39
37
|
"@gaonjs/i18n": "0.5.0",
|
|
40
|
-
"@gaonjs/
|
|
41
|
-
"@gaonjs/mail": "0.5.4"
|
|
38
|
+
"@gaonjs/core": "0.3.0",
|
|
39
|
+
"@gaonjs/mail": "0.5.4",
|
|
40
|
+
"@gaonjs/data": "0.26.4",
|
|
41
|
+
"@gaonjs/web": "0.33.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "node ../../node_modules/typescript/bin/tsc -p tsconfig.json && node -e \"const fs=require('fs');fs.rmSync('dist/templates/project',{recursive:true,force:true});fs.cpSync('src/templates','dist/templates',{recursive:true,filter:(s)=>!s.endsWith('.ts')});fs.rmSync('dist/templates/index.ts',{force:true})\""
|