byuckchon-frontend-cli 1.9.7 → 1.10.1
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/README.md +59 -5
- package/package.json +8 -2
- package/src/commands/adopt.js +12 -3
- package/src/constants/versions.js +12 -46
- package/src/generators/createApp.js +13 -29
- package/src/generators/createBaseFiles.js +79 -311
- package/src/generators/createFolders.js +17 -1
- package/src/generators/createMonorepo.js +49 -236
- package/src/generators/createPackageJson.js +10 -11
- package/src/generators/scaffoldReviewAutomation.js +51 -30
- package/src/utils/ensureRequiredDependencies.js +35 -9
- package/src/utils/settingsAssets.js +27 -0
- package/templates/review-automation/github/pull_request_template.md +30 -0
- package/templates/review-automation/github/workflows/eslint-convention-review.monorepo.yml +8 -6
- package/templates/review-automation/github/workflows/eslint-convention-review.single.yml +6 -6
- package/templates/review-automation/github/workflows/pr-check.monorepo.yml +51 -0
- package/templates/review-automation/github/workflows/pr-check.single.yml +47 -0
- package/templates/review-automation/github/workflows/pr-description.yml +58 -0
- package/templates/review-automation/tools/review.config.mjs +9 -0
- package/templates/review-automation/tools/eslint-rules/internal-blocking-conventions.js +0 -1242
- package/templates/review-automation/tools/eslint-rules/internal-plugin.cjs +0 -8
- package/templates/review-automation/tools/eslint-rules/internal-rdjson-formatter.js +0 -60
- package/templates/review-automation/tools/eslint-rules/internal-warning-conventions.js +0 -57
- package/templates/review-automation/tools/eslint-rules/package.json +0 -3
- package/templates/review-automation/tools/eslint-rules/review.config.mjs +0 -22
- package/templates/review-automation/tools/post-eslint-review-comments.cjs +0 -309
package/README.md
CHANGED
|
@@ -225,25 +225,78 @@ https://www.figma.com/design/.../?node-id=12-34
|
|
|
225
225
|
| **Components** 화 (♦ 마름모 아이콘) | 반복 UI 가 component 면 모델이 "이거 디자인 시스템 컴포넌트구나" 인식 → 코드에서도 재사용 컴포넌트를 만듭니다. |
|
|
226
226
|
| frame 별로 **"Copy link to selection"** | 일반 share link 는 파일 전체. 특정 frame URL 을 받아야 AI 가 그것만 정확히 가져옵니다. |
|
|
227
227
|
|
|
228
|
+
### 디자인 토큰 빌드
|
|
229
|
+
|
|
230
|
+
`bc init`으로 생성한 프로젝트에는 토큰 변환 설정이 함께 들어갑니다.
|
|
231
|
+
|
|
232
|
+
```text
|
|
233
|
+
token.config.js # @byuckchon-frontend/settings/tokens 프리셋을 사용
|
|
234
|
+
src/tokens.json # 디자이너가 Figma(Tokens Studio)에서 export 한 파일을 여기에 덮어씀
|
|
235
|
+
src/tokens.css # 아래 명령으로 자동 생성 (직접 수정하지 않음)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
npm run tokens:build
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
color는 `@theme`의 `--color-*`로, typography는 `@utility text-*`로, motion 등 나머지 토큰은
|
|
243
|
+
`:root` 변수로 출력됩니다. duration 값이 단위 없는 숫자면 `ms`가 자동으로 붙고, settings에 없는
|
|
244
|
+
`--motion-*` 이름이 있으면 경고가 나옵니다. 변환 규칙은 `@byuckchon-frontend/settings`가
|
|
245
|
+
관리하므로, 규칙이 바뀌면 패키지 버전만 올리면 기존 프로젝트에도 그대로 반영됩니다.
|
|
246
|
+
|
|
228
247
|
### ESLint Convention Review
|
|
229
248
|
|
|
230
249
|
`bc init`과 `bc adopt`는 프로젝트 루트에 아래 파일을 준비합니다.
|
|
231
250
|
|
|
232
251
|
```text
|
|
233
|
-
.github/workflows/eslint-convention-review.yml
|
|
234
|
-
|
|
235
|
-
|
|
252
|
+
.github/workflows/eslint-convention-review.yml # 컨벤션 인라인 댓글
|
|
253
|
+
.github/workflows/pr-check.yml # lint / typecheck / build 통과 여부 (bc init 전용)
|
|
254
|
+
.github/workflows/pr-description.yml # 커밋 내역을 PR 본문에 반영
|
|
255
|
+
.github/pull_request_template.md
|
|
256
|
+
tools/review.config.mjs
|
|
236
257
|
```
|
|
237
258
|
|
|
259
|
+
`pr-check.yml` 은 `bc init` 으로 생성한 프로젝트에만 추가됩니다.
|
|
260
|
+
스크립트 이름·대상 브랜치·패키지 매니저를 전제하기 때문에, 기존 프로젝트에
|
|
261
|
+
`bc adopt` 할 때는 추가하지 않습니다. 필요하면 위 파일을 참고해 직접 만드세요.
|
|
262
|
+
|
|
263
|
+
워크플로 템플릿은 프로젝트 유형에 맞는 것만 복사됩니다.
|
|
264
|
+
(`<이름>.single.yml` / `<이름>.monorepo.yml` → `<이름>.yml`)
|
|
265
|
+
단일 프로젝트는 npm, 모노레포는 pnpm + turbo 기준으로 만들어집니다.
|
|
266
|
+
|
|
267
|
+
복사된 파일이므로 **프로젝트 소유**입니다. 대상 브랜치나 단계를 자유롭게 고치세요.
|
|
268
|
+
settings 를 올려도 이 파일은 바뀌지 않습니다.
|
|
269
|
+
|
|
238
270
|
PR이 `dev` 브랜치를 대상으로 할 때, workflow가 기계적으로 판별 가능한 규칙을 검사하고
|
|
239
271
|
변경 줄에 댓글을 게시합니다.
|
|
240
272
|
|
|
273
|
+
컨벤션 규칙과 댓글 게시 스크립트는 `@byuckchon-frontend/settings`가 제공합니다.
|
|
274
|
+
프로젝트에 규칙 사본을 두지 않으므로, 규칙이 바뀌면 settings 버전만 올리면 됩니다.
|
|
275
|
+
|
|
241
276
|
| 구분 | 담당 | 결과 |
|
|
242
277
|
| --- | --- | --- |
|
|
243
278
|
| 일반 lint | 기존 ESLint 규칙 | Actions annotation |
|
|
244
279
|
| Convention Review | 파일명, export 방식, boolean 변수명 등 | PR 인라인 `BLOCKING` 또는 `WARNING` 댓글 |
|
|
245
280
|
| AI 리뷰 | 설계·예외 처리·비즈니스 판단 | 별도 AI 리뷰 workflow에서 구성 |
|
|
246
281
|
|
|
282
|
+
### PR 본문 자동 작성
|
|
283
|
+
|
|
284
|
+
`pr-description.yml` 이 PR 의 커밋을 타입별로 묶어 description 에 채워 넣습니다.
|
|
285
|
+
|
|
286
|
+
```markdown
|
|
287
|
+
### ✨ 기능
|
|
288
|
+
- **settings** — tsconfig 프리셋 추가 (a1b2c3d)
|
|
289
|
+
|
|
290
|
+
### 🐛 수정
|
|
291
|
+
- letterSpacing % → em 변환 (b2c3d4e)
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
사람이 쓴 내용은 건드리지 않고 `<!-- byuckchon:commits:start -->` 마커 사이만 갱신하며,
|
|
295
|
+
커밋을 추가로 푸시하면 목록도 따라 갱신됩니다. 머지 커밋은 제외하고, 컨벤션을 안 지킨
|
|
296
|
+
커밋은 버리지 않고 "분류 없음"으로 모읍니다.
|
|
297
|
+
|
|
298
|
+
생성되는 `.github/pull_request_template.md` 에 마커가 미리 들어 있습니다.
|
|
299
|
+
|
|
247
300
|
같은 지적은 숨김 marker를 기준으로 중복 게시하지 않고, 메시지가 바뀌면 기존 댓글을 갱신합니다.
|
|
248
301
|
모노레포에서는 workflow와 `tools/`가 루트에 한 번만 존재하며, PR에서 변경된 TypeScript 파일을
|
|
249
302
|
대상으로 검사합니다.
|
|
@@ -317,8 +370,9 @@ bc chat --resume <session-id>
|
|
|
317
370
|
- 기존 모노레포에 `bc adopt`를 적용할 때, 모노레포용 `review.config.mjs`는
|
|
318
371
|
`packages/config-eslint/react.js` 구조를 전제로 합니다. ESLint 설정 구조가 다르면 해당 import를
|
|
319
372
|
프로젝트에 맞게 조정해야 합니다.
|
|
320
|
-
- AI Code Review
|
|
321
|
-
|
|
373
|
+
- AI Code Review workflow는 자동 생성 대상이 아닙니다. 팀의 AI 제공자에 맞춰 별도로 추가해야 합니다.
|
|
374
|
+
- PR Check workflow는 lint · typecheck · build 만 실행합니다. 테스트는 팀의 전략에 맞춰
|
|
375
|
+
생성된 `pr-check.yml` 에 단계를 추가하세요.
|
|
322
376
|
|
|
323
377
|
## 제품 로드맵
|
|
324
378
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "byuckchon-frontend-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.1",
|
|
4
4
|
"description": "Byuckchon Frontend Workbench — project starter + AI chat + codebase RAG + OpenAPI codegen",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -14,9 +14,12 @@
|
|
|
14
14
|
"start": "node bin/index.js",
|
|
15
15
|
"chat": "node bin/index.js chat",
|
|
16
16
|
"init": "node bin/index.js init",
|
|
17
|
-
"config": "node bin/index.js config show"
|
|
17
|
+
"config": "node bin/index.js config show",
|
|
18
|
+
"release": "changeset publish",
|
|
19
|
+
"version-packages": "changeset version"
|
|
18
20
|
},
|
|
19
21
|
"dependencies": {
|
|
22
|
+
"@byuckchon-frontend/settings": "^1.6.0",
|
|
20
23
|
"@ai-sdk/anthropic": "^3.0.85",
|
|
21
24
|
"@ai-sdk/openai": "^3.0.73",
|
|
22
25
|
"ai": "^6.0.208",
|
|
@@ -65,5 +68,8 @@
|
|
|
65
68
|
"repository": {
|
|
66
69
|
"type": "git",
|
|
67
70
|
"url": "git+https://github.com/RevolutionaryWarrior/byuckchon-frontend-cli.git"
|
|
71
|
+
},
|
|
72
|
+
"devDependencies": {
|
|
73
|
+
"@changesets/cli": "^2.29.8"
|
|
68
74
|
}
|
|
69
75
|
}
|
package/src/commands/adopt.js
CHANGED
|
@@ -188,25 +188,34 @@ export async function adoptCommand(opts = {}) {
|
|
|
188
188
|
projectRoot: reviewProjectRoot,
|
|
189
189
|
projectType,
|
|
190
190
|
overwrite: false,
|
|
191
|
+
// PR Check 는 스크립트 이름·브랜치·패키지 매니저를 전제하므로
|
|
192
|
+
// 기존 프로젝트에 말없이 깔면 CI 가 곧바로 실패한다. bc init 전용으로 둔다.
|
|
193
|
+
exclude: ['pr-check'],
|
|
191
194
|
});
|
|
192
195
|
|
|
193
196
|
if (reviewAutomation.workflows.length) {
|
|
194
197
|
console.log(
|
|
195
198
|
chalk.green(
|
|
196
|
-
` ✓
|
|
199
|
+
` ✓ PR 워크플로 추가: ${path.join(reviewProjectRoot, '.github', 'workflows')}`,
|
|
200
|
+
),
|
|
201
|
+
);
|
|
202
|
+
console.log(chalk.dim(` ${reviewAutomation.workflows.join(', ')}`));
|
|
203
|
+
console.log(
|
|
204
|
+
chalk.dim(
|
|
205
|
+
' (PR Check 워크플로는 기존 프로젝트의 스크립트·브랜치 설정을 전제하므로 추가하지 않습니다)',
|
|
197
206
|
),
|
|
198
207
|
);
|
|
199
208
|
} else {
|
|
200
209
|
console.log(
|
|
201
210
|
chalk.dim(
|
|
202
|
-
`
|
|
211
|
+
` PR 워크플로 유지: ${path.join(reviewProjectRoot, '.github', 'workflows')} (이미 존재)`,
|
|
203
212
|
),
|
|
204
213
|
);
|
|
205
214
|
}
|
|
206
215
|
} catch (error) {
|
|
207
216
|
console.log(
|
|
208
217
|
chalk.yellow(
|
|
209
|
-
` ⚠
|
|
218
|
+
` ⚠ PR 워크플로를 추가하지 못했습니다: ${error.message}`,
|
|
210
219
|
),
|
|
211
220
|
);
|
|
212
221
|
}
|
|
@@ -1,50 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// Build tool (React only)
|
|
10
|
-
vite: '^6.0.0',
|
|
11
|
-
'@vitejs/plugin-react': '^4.3.0',
|
|
12
|
-
'vite-plugin-svgr': '^4.3.0',
|
|
13
|
-
'@svgr/webpack': '^8.1.0',
|
|
14
|
-
|
|
15
|
-
// TypeScript
|
|
16
|
-
typescript: '^5.7.0',
|
|
17
|
-
'@types/react': '^18.3.3',
|
|
18
|
-
'@types/react-dom': '^18.3.0',
|
|
19
|
-
'@types/node': '^22.0.0',
|
|
1
|
+
/**
|
|
2
|
+
* 검증된 스택 버전 매트릭스.
|
|
3
|
+
*
|
|
4
|
+
* 본체는 @byuckchon-frontend/settings 가 관리한다.
|
|
5
|
+
* 여기서는 settings 자신의 버전만 얹는다 — 자기 자신의 버전을 자기가 들고 있으면
|
|
6
|
+
* 어긋나기 때문에, CLI 와 함께 설치된 settings 의 실제 버전을 읽어서 쓴다.
|
|
7
|
+
*/
|
|
20
8
|
|
|
21
|
-
|
|
22
|
-
zustand: '^5.0.3',
|
|
23
|
-
axios: '^1.8.4',
|
|
24
|
-
'react-router-dom': '^7.5.0',
|
|
25
|
-
'@tanstack/react-query': '^5.74.4',
|
|
9
|
+
import { versions as shared } from '@byuckchon-frontend/settings/versions';
|
|
26
10
|
|
|
27
|
-
|
|
28
|
-
tailwindcss: '^4.1.4',
|
|
29
|
-
'@tailwindcss/vite': '^4.1.4',
|
|
30
|
-
'@tailwindcss/postcss': '^4',
|
|
11
|
+
import { settingsVersion } from '../utils/settingsAssets.js';
|
|
31
12
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
'
|
|
35
|
-
'eslint-config-next': '^15.0.0',
|
|
36
|
-
'eslint-import-resolver-typescript': '^3.6.0',
|
|
37
|
-
'eslint-plugin-import': '^2.29.0',
|
|
38
|
-
'eslint-plugin-react': '^7.34.0',
|
|
39
|
-
'eslint-plugin-react-hooks': '^4.6.0',
|
|
40
|
-
'@typescript-eslint/eslint-plugin': '^7.0.0',
|
|
41
|
-
'@typescript-eslint/parser': '^7.0.0',
|
|
42
|
-
|
|
43
|
-
// Formatting
|
|
44
|
-
prettier: '^3.3.0',
|
|
45
|
-
'prettier-plugin-tailwindcss': '^0.6.11',
|
|
46
|
-
'style-dictionary': '^5.4.0',
|
|
47
|
-
zod: '^3.24.3',
|
|
48
|
-
'@trivago/prettier-plugin-sort-imports': '^5.2.2',
|
|
49
|
-
'eslint-plugin-unused-imports': '^4.1.4',
|
|
13
|
+
export const versions = {
|
|
14
|
+
...shared,
|
|
15
|
+
'@byuckchon-frontend/settings': `^${settingsVersion()}`,
|
|
50
16
|
};
|
|
@@ -92,17 +92,18 @@ async function createAppPackageJson(appDir, config, scope) {
|
|
|
92
92
|
}
|
|
93
93
|
: {}),
|
|
94
94
|
zod: versions.zod,
|
|
95
|
+
clsx: versions.clsx,
|
|
96
|
+
'tailwind-merge': versions['tailwind-merge'],
|
|
95
97
|
},
|
|
96
98
|
devDependencies: {
|
|
97
99
|
[`@${scope}/config-eslint`]: 'workspace:*',
|
|
98
100
|
[`@${scope}/config-typescript`]: 'workspace:*',
|
|
101
|
+
// global.d.ts, App.css(motion), token.config.js 가 직접 참조한다.
|
|
102
|
+
'@byuckchon-frontend/settings': versions['@byuckchon-frontend/settings'],
|
|
99
103
|
'@types/react': versions['@types/react'],
|
|
100
104
|
'@types/react-dom': versions['@types/react-dom'],
|
|
101
105
|
'@types/node': versions['@types/node'],
|
|
102
|
-
|
|
103
|
-
// (단일 프로젝트의 eslintrc + eslint 8 과 별개)
|
|
104
|
-
eslint: '^9.18.0',
|
|
105
|
-
'eslint-plugin-unused-imports': versions['eslint-plugin-unused-imports'],
|
|
106
|
+
eslint: versions.eslint,
|
|
106
107
|
prettier: versions.prettier,
|
|
107
108
|
'prettier-plugin-tailwindcss': versions['prettier-plugin-tailwindcss'],
|
|
108
109
|
'style-dictionary': versions['style-dictionary'],
|
|
@@ -135,32 +136,18 @@ async function applyMonorepoConventions(appDir, config, scope) {
|
|
|
135
136
|
const isReact = config.framework === 'react';
|
|
136
137
|
|
|
137
138
|
// 루트에서 관리하는 설정들은 앱 레벨에서 제거.
|
|
138
|
-
await rm(path.join(appDir, '.
|
|
139
|
-
await rm(path.join(appDir, '.
|
|
139
|
+
await rm(path.join(appDir, 'eslint.config.js'));
|
|
140
|
+
await rm(path.join(appDir, 'eslint.config.mjs'));
|
|
141
|
+
await rm(path.join(appDir, 'prettier.config.js'));
|
|
140
142
|
await rm(path.join(appDir, '.gitignore'));
|
|
141
143
|
await rm(path.join(appDir, '.vscode'));
|
|
142
144
|
|
|
143
|
-
// 공유 ESLint 프리셋을
|
|
145
|
+
// 공유 ESLint 프리셋을 그대로 쓴다.
|
|
146
|
+
// 규칙 본체는 @byuckchon-frontend/settings 가 관리하고,
|
|
147
|
+
// 이 모노레포 전용 예외는 packages/config-eslint 에서 얹는다.
|
|
144
148
|
await write(
|
|
145
149
|
path.join(appDir, 'eslint.config.mjs'),
|
|
146
|
-
`
|
|
147
|
-
import unusedImports from 'eslint-plugin-unused-imports';
|
|
148
|
-
|
|
149
|
-
export default [
|
|
150
|
-
...reactConfig,
|
|
151
|
-
{
|
|
152
|
-
plugins: { 'unused-imports': unusedImports },
|
|
153
|
-
rules: {
|
|
154
|
-
'no-unused-vars': 'off',
|
|
155
|
-
'@typescript-eslint/no-unused-vars': 'off',
|
|
156
|
-
'unused-imports/no-unused-imports': 'error',
|
|
157
|
-
'unused-imports/no-unused-vars': [
|
|
158
|
-
'warn',
|
|
159
|
-
{ vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' },
|
|
160
|
-
],
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
];
|
|
150
|
+
`export { default } from '@${scope}/config-eslint/${isReact ? 'react' : 'next'}';
|
|
164
151
|
`
|
|
165
152
|
);
|
|
166
153
|
|
|
@@ -174,11 +161,8 @@ export default [
|
|
|
174
161
|
{
|
|
175
162
|
extends: `@${scope}/config-typescript/react.json`,
|
|
176
163
|
compilerOptions: {
|
|
164
|
+
// 공통 옵션은 config-typescript → settings 프리셋에 있다.
|
|
177
165
|
tsBuildInfoFile: './node_modules/.tmp/tsconfig.tsbuildinfo',
|
|
178
|
-
noUnusedLocals: true,
|
|
179
|
-
noUnusedParameters: true,
|
|
180
|
-
noUncheckedSideEffectImports: true,
|
|
181
|
-
moduleDetection: 'force',
|
|
182
166
|
baseUrl: '.',
|
|
183
167
|
paths: {
|
|
184
168
|
'@/*': ['src/*'],
|