byuckchon-frontend-cli 1.10.1 → 2.0.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/bin/index.js +8 -1
- package/package.json +1 -1
- package/src/generators/createApp.js +6 -5
- package/src/generators/createBaseFiles.js +155 -5
- package/src/generators/createFolders.js +8 -6
- package/src/generators/createMonorepo.js +5 -0
- package/templates/review-automation/github/pull_request_template.md +14 -17
- package/templates/review-automation/github/workflows/pr-description.yml +2 -2
package/bin/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
|
|
2
4
|
import { config as loadDotenv } from 'dotenv';
|
|
3
5
|
import { Command } from 'commander';
|
|
4
6
|
import chalk from 'chalk';
|
|
@@ -24,12 +26,17 @@ import {
|
|
|
24
26
|
// 프로젝트 .env 가 있으면 자동 로드 (ANTHROPIC_API_KEY, OPENAI_API_KEY 등).
|
|
25
27
|
loadDotenv({ quiet: true });
|
|
26
28
|
|
|
29
|
+
// 버전은 package.json 에서 읽는다. 여기에 직접 적으면 changesets 가 올린 버전과
|
|
30
|
+
// 어긋나서, 실제로는 최신인데 옛 버전이라고 표시되는 일이 생긴다.
|
|
31
|
+
const require = createRequire(import.meta.url);
|
|
32
|
+
const { version } = require('../package.json');
|
|
33
|
+
|
|
27
34
|
const program = new Command();
|
|
28
35
|
|
|
29
36
|
program
|
|
30
37
|
.name('bc')
|
|
31
38
|
.description('Byuckchon Frontend Workbench — 프로젝트 스타터 + AI 어시스턴트')
|
|
32
|
-
.version(
|
|
39
|
+
.version(version);
|
|
33
40
|
|
|
34
41
|
program
|
|
35
42
|
.command('init')
|
package/package.json
CHANGED
|
@@ -163,11 +163,12 @@ async function applyMonorepoConventions(appDir, config, scope) {
|
|
|
163
163
|
compilerOptions: {
|
|
164
164
|
// 공통 옵션은 config-typescript → settings 프리셋에 있다.
|
|
165
165
|
tsBuildInfoFile: './node_modules/.tmp/tsconfig.tsbuildinfo',
|
|
166
|
-
baseUrl
|
|
166
|
+
// baseUrl 은 TypeScript 7 에서 제거 대상이다.
|
|
167
|
+
// 생략하면 paths 가 이 tsconfig 파일 위치 기준으로 해석되므로 ./ 을 붙인다.
|
|
167
168
|
paths: {
|
|
168
|
-
'@/*': ['src/*'],
|
|
169
|
-
'@icons/*': ['src/assets/icons/*'],
|
|
170
|
-
'@images/*': ['src/assets/images/*'],
|
|
169
|
+
'@/*': ['./src/*'],
|
|
170
|
+
'@icons/*': ['./src/assets/icons/*'],
|
|
171
|
+
'@images/*': ['./src/assets/images/*'],
|
|
171
172
|
},
|
|
172
173
|
},
|
|
173
174
|
include: ['src', 'vite.config.ts'],
|
|
@@ -183,7 +184,7 @@ async function applyMonorepoConventions(appDir, config, scope) {
|
|
|
183
184
|
{
|
|
184
185
|
extends: `@${scope}/config-typescript/next.json`,
|
|
185
186
|
compilerOptions: {
|
|
186
|
-
baseUrl
|
|
187
|
+
// baseUrl 없이 paths 만 쓴다. (TypeScript 7 에서 baseUrl 제거)
|
|
187
188
|
paths: { '@/*': ['./src/*'] },
|
|
188
189
|
},
|
|
189
190
|
include: [
|
|
@@ -26,6 +26,151 @@ import { defineTokenConfig } from "@byuckchon-frontend/settings/tokens";
|
|
|
26
26
|
export default defineTokenConfig();
|
|
27
27
|
`;
|
|
28
28
|
|
|
29
|
+
// ─── AI 에이전트 가이드 ────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* AGENTS.md 를 만든다. Codex 와 bc chat 이 이 이름을 기본으로 찾고,
|
|
33
|
+
* CLAUDE.md 는 이 파일을 import 하는 한 줄짜리로 둬서 문서를 하나만 관리한다.
|
|
34
|
+
*
|
|
35
|
+
* 매 세션 컨텍스트에 실리므로 짧게 유지한다. 상세 API 는 각 패키지 README 로 넘긴다.
|
|
36
|
+
*/
|
|
37
|
+
export function agentsDoc(framework) {
|
|
38
|
+
const isReact = framework === "react";
|
|
39
|
+
|
|
40
|
+
return `# 작업 규칙
|
|
41
|
+
|
|
42
|
+
이 프로젝트에서 코드를 작성할 때 지켜야 할 것들입니다.
|
|
43
|
+
|
|
44
|
+
## 1. 사내 패키지를 먼저 쓴다
|
|
45
|
+
|
|
46
|
+
직접 구현하기 전에 아래 패키지에 이미 있는지 **반드시 먼저 확인하세요.**
|
|
47
|
+
같은 기능을 새로 만들면 유지보수 비용이 프로젝트 수만큼 늘어납니다.
|
|
48
|
+
|
|
49
|
+
| 패키지 | 무엇이 있나 |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| \`@byuckchon-frontend/hooks\` | useDebounce, useThrottle, useTimer, useInfiniteScroll, useIntersectionObserver, useDetectClose, useAutoFocus, useFileUpload, usePagination, usePullToRefresh, useScrollTop, useCheckList, useMonthCalendar, useVisibilityEvent, usePasswordVisibility, useImpressionRef, useInstallPWA, useScrollToSelectedItem |
|
|
52
|
+
| \`@byuckchon-frontend/utils\` | 포맷(formatData), 검증(validate), 에러 처리(handleError), 쿼리 파라미터(filterParams), userAgent, sanitizeHtml, dateUtils, editorUtils |
|
|
53
|
+
| \`@byuckchon-frontend/core\` | Overlay, ErrorBoundary, SanitizeHtmlRender |
|
|
54
|
+
| \`@byuckchon-frontend/basic-ui\` | ⚠️ **먼저 쓰지 않는다** — 아래 설명 참고 |
|
|
55
|
+
| \`@byuckchon-frontend/settings\` | ESLint / Prettier / tsconfig 프리셋, 모션 토큰, 디자인 토큰 변환 |
|
|
56
|
+
|
|
57
|
+
**작업 순서**
|
|
58
|
+
|
|
59
|
+
1. 위 표에서 찾아본다
|
|
60
|
+
2. 애매하면 실제 export 를 확인한다 — 위 목록은 스냅샷이라 최신이 아닐 수 있다
|
|
61
|
+
\`\`\`bash
|
|
62
|
+
cat node_modules/@byuckchon-frontend/hooks/dist/index.d.ts
|
|
63
|
+
\`\`\`
|
|
64
|
+
3. 없으면 그때 직접 구현한다
|
|
65
|
+
|
|
66
|
+
없는 걸 억지로 끼워 맞추지는 마세요. 쓰임이 다르면 직접 만드는 게 맞습니다.
|
|
67
|
+
|
|
68
|
+
### basic-ui 는 예외입니다
|
|
69
|
+
|
|
70
|
+
\`@byuckchon-frontend/basic-ui\` 는 **사용자가 명시적으로 요청했을 때만** 씁니다.
|
|
71
|
+
프로젝트마다 디자인이 달라서 기본 UI 컴포넌트를 그대로 쓰면 오히려 덜어내는 작업이 늘어납니다.
|
|
72
|
+
|
|
73
|
+
UI 컴포넌트는 이 프로젝트의 디자인에 맞춰 직접 만드세요.
|
|
74
|
+
(Accordion, Input, Modal, Table 등이 필요하면 basic-ui 에 있으니 참고만 하세요)
|
|
75
|
+
|
|
76
|
+
### 모션은 settings 의 클래스를 씁니다
|
|
77
|
+
|
|
78
|
+
전환 효과가 필요하면 \`duration-200\` 같은 Tailwind 기본 클래스를 직접 쓰지 말고,
|
|
79
|
+
\`@byuckchon-frontend/settings\` 의 모션 유틸리티를 쓰세요. 팀 전체가 같은 속도·곡선을 공유합니다.
|
|
80
|
+
|
|
81
|
+
| 상황 | 클래스 |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| hover 확대 / 클릭 눌림 | \`motion-hover-scale\` \`motion-press\` |
|
|
84
|
+
| 펼침·접힘 / 화살표 회전 | \`motion-collapse\` \`motion-rotate\` |
|
|
85
|
+
| 팝업·드롭다운 진입 | \`motion-scale-in\` |
|
|
86
|
+
| 배경 딤 | \`motion-backdrop\` |
|
|
87
|
+
| 바텀시트 / 드로어 | \`motion-sheet\` \`motion-slide-x-left\` \`motion-slide-x-right\` |
|
|
88
|
+
| 토스트 / 툴팁 | \`motion-toast\` \`motion-tooltip\` |
|
|
89
|
+
| 토글 / 체크 / 라벨 | \`motion-toggle-knob\` \`motion-check-pop\` \`motion-label-float\` |
|
|
90
|
+
| 탭 인디케이터 | \`motion-tab-indicator\` |
|
|
91
|
+
|
|
92
|
+
\`data-open\` 이 필요한 클래스가 있습니다. 열림 상태를 \`data-open={isOpen}\` 으로 내려주세요.
|
|
93
|
+
|
|
94
|
+
\`\`\`tsx
|
|
95
|
+
<div data-open={isOpen} className="motion-collapse"><div>{content}</div></div>
|
|
96
|
+
\`\`\`
|
|
97
|
+
|
|
98
|
+
### 클래스 병합은 cn 을 씁니다
|
|
99
|
+
|
|
100
|
+
\`src/lib/utils/cn.ts\` 의 \`cn\` 을 쓰세요. \`twMerge\` 를 직접 쓰면
|
|
101
|
+
타이포그래피 유틸(\`text-body-sm-regular\`)이 글자 색으로 분류되어 조용히 사라집니다.
|
|
102
|
+
|
|
103
|
+
## 2. 설정 파일은 직접 고치지 않는다
|
|
104
|
+
|
|
105
|
+
\`eslint.config.js\`, \`prettier.config.js\`, \`tsconfig.*.json\`, \`token.config.js\` 는
|
|
106
|
+
\`@byuckchon-frontend/settings\` 를 참조만 합니다. 규칙 본체는 node_modules 안에 있습니다.
|
|
107
|
+
|
|
108
|
+
예외가 필요하면 **덮어쓰지 말고 뒤에 이어붙이세요.**
|
|
109
|
+
|
|
110
|
+
\`\`\`js
|
|
111
|
+
// eslint.config.js — 배열 뒤쪽이 이깁니다
|
|
112
|
+
import byuckchon from '@byuckchon-frontend/settings/eslint/react';
|
|
113
|
+
|
|
114
|
+
export default [
|
|
115
|
+
...byuckchon,
|
|
116
|
+
{ rules: { '@typescript-eslint/no-explicit-any': 'warn' } },
|
|
117
|
+
];
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
\`.vscode/settings.json\`, \`.nvmrc\`${isReact ? "" : ""} 같은 파일은 \`npx byuckchon-settings-sync\` 로 갱신합니다.
|
|
121
|
+
|
|
122
|
+
## 3. 커밋 메시지
|
|
123
|
+
|
|
124
|
+
\`\`\`
|
|
125
|
+
<type>: <요약>
|
|
126
|
+
\`\`\`
|
|
127
|
+
|
|
128
|
+
\`feat\` \`fix\` \`refactor\` \`perf\` \`style\` \`docs\` \`test\` \`chore\`
|
|
129
|
+
|
|
130
|
+
**리뷰어가 확인해야 할 것은 커밋 본문에 남깁니다.** PR 본문의 "리뷰 포인트"로 자동 수집됩니다.
|
|
131
|
+
|
|
132
|
+
\`\`\`
|
|
133
|
+
feat: 주문 목록 API 연동
|
|
134
|
+
|
|
135
|
+
NOTE: 응답 스키마가 미확정이라 types/order.ts 에 any 가 남아 있습니다
|
|
136
|
+
TODO: 에러 처리 미구현 — 백엔드 에러 코드 확정 후 작업 예정
|
|
137
|
+
\`\`\`
|
|
138
|
+
|
|
139
|
+
확신이 없거나, 임시로 둔 코드가 있거나, 리뷰어의 판단이 필요하면 **반드시 남기세요.**
|
|
140
|
+
말없이 넘어가면 리뷰에서 놓칩니다.
|
|
141
|
+
|
|
142
|
+
## 4. 브랜치 이름
|
|
143
|
+
|
|
144
|
+
\`\`\`
|
|
145
|
+
<type>/<작업 요약>/<작업자>
|
|
146
|
+
feature/update-mypage-style/hyuk
|
|
147
|
+
\`\`\`
|
|
148
|
+
|
|
149
|
+
PR 제목은 첫 토막이 대괄호로 자동으로 붙습니다. → \`[feature] 마이페이지 디자인 적용\`
|
|
150
|
+
|
|
151
|
+
## 5. 폴더 구조
|
|
152
|
+
|
|
153
|
+
${
|
|
154
|
+
isReact
|
|
155
|
+
? `\`\`\`
|
|
156
|
+
src/lib 공용 로직·유틸 src/store 전역 상태
|
|
157
|
+
src/api API 호출 src/hooks 커스텀 훅
|
|
158
|
+
src/context Context src/components 컴포넌트
|
|
159
|
+
src/layouts 레이아웃 src/pages 페이지
|
|
160
|
+
src/assets 이미지·아이콘
|
|
161
|
+
\`\`\``
|
|
162
|
+
: `\`\`\`
|
|
163
|
+
src/app App Router src/components 컴포넌트
|
|
164
|
+
src/lib 공용 로직·유틸 src/hooks 커스텀 훅
|
|
165
|
+
src/providers Provider src/constant 상수
|
|
166
|
+
src/assets 이미지·아이콘
|
|
167
|
+
\`\`\``
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
경로 별칭은 \`@/\` 를 씁니다. (\`@/lib/utils/cn\`)
|
|
171
|
+
`;
|
|
172
|
+
}
|
|
173
|
+
|
|
29
174
|
// ─── 공통 설정 파일 ────────────────────────────────────────────────────────────
|
|
30
175
|
|
|
31
176
|
async function createPrettierConfig(rootDir) {
|
|
@@ -213,11 +358,12 @@ export default defineConfig({
|
|
|
213
358
|
extends: "@byuckchon-frontend/settings/tsconfig/react.json",
|
|
214
359
|
compilerOptions: {
|
|
215
360
|
tsBuildInfoFile: "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
216
|
-
baseUrl
|
|
361
|
+
// baseUrl 은 TypeScript 7 에서 제거 대상이다.
|
|
362
|
+
// 생략하면 paths 가 이 tsconfig 파일 위치 기준으로 해석되므로 ./ 을 붙인다.
|
|
217
363
|
paths: {
|
|
218
|
-
"@/*": ["src/*"],
|
|
219
|
-
"@icons/*": ["src/assets/icons/*"],
|
|
220
|
-
"@images/*": ["src/assets/images/*"],
|
|
364
|
+
"@/*": ["./src/*"],
|
|
365
|
+
"@icons/*": ["./src/assets/icons/*"],
|
|
366
|
+
"@images/*": ["./src/assets/images/*"],
|
|
221
367
|
},
|
|
222
368
|
},
|
|
223
369
|
include: ["src"],
|
|
@@ -245,6 +391,8 @@ export default defineConfig({
|
|
|
245
391
|
);
|
|
246
392
|
|
|
247
393
|
await write(path.join(rootDir, ".nvmrc"), await readSettingsAsset("project/nvmrc"));
|
|
394
|
+
await write(path.join(rootDir, "AGENTS.md"), agentsDoc("react"));
|
|
395
|
+
await write(path.join(rootDir, "CLAUDE.md"), "@AGENTS.md\n");
|
|
248
396
|
|
|
249
397
|
await createPrettierConfig(rootDir);
|
|
250
398
|
await createEslintConfig(rootDir);
|
|
@@ -360,7 +508,7 @@ export default nextConfig;
|
|
|
360
508
|
{
|
|
361
509
|
extends: "@byuckchon-frontend/settings/tsconfig/next.json",
|
|
362
510
|
compilerOptions: {
|
|
363
|
-
baseUrl
|
|
511
|
+
// baseUrl 없이 paths 만 쓴다. (TypeScript 7 에서 baseUrl 제거)
|
|
364
512
|
paths: { "@/*": ["./src/*"] },
|
|
365
513
|
},
|
|
366
514
|
include: ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
@@ -372,6 +520,8 @@ export default nextConfig;
|
|
|
372
520
|
);
|
|
373
521
|
|
|
374
522
|
await write(path.join(rootDir, ".nvmrc"), await readSettingsAsset("project/nvmrc"));
|
|
523
|
+
await write(path.join(rootDir, "AGENTS.md"), agentsDoc("next"));
|
|
524
|
+
await write(path.join(rootDir, "CLAUDE.md"), "@AGENTS.md\n");
|
|
375
525
|
|
|
376
526
|
await createPrettierConfig(rootDir);
|
|
377
527
|
await createNextEslintConfig(rootDir);
|
|
@@ -54,12 +54,14 @@ export async function createFolders(rootDir, config) {
|
|
|
54
54
|
// 각 레이어에 placeholder 파일 생성
|
|
55
55
|
await writeFile(
|
|
56
56
|
path.join(rootDir, 'src/lib/utils/cn.ts'),
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
57
|
+
`// 클래스 병합은 @byuckchon-frontend/utils 가 관리합니다.
|
|
58
|
+
// twMerge 기본 설정은 타이포그래피 유틸(text-body-sm-regular 등)을 글자 색으로 분류해서
|
|
59
|
+
// 색과 함께 쓰면 타이포가 조용히 사라집니다. utils 의 cn 은 그 부분을 고쳐둔 것입니다.
|
|
60
|
+
//
|
|
61
|
+
// 토큰 이름 체계가 기본 패턴과 다르면 createCn 으로 직접 지정하세요.
|
|
62
|
+
// import { createCn } from '@byuckchon-frontend/utils';
|
|
63
|
+
// export const cn = createCn({ typography: ['tab-bar', 'subtitle'] });
|
|
64
|
+
export { cn } from '@byuckchon-frontend/utils';
|
|
63
65
|
`,
|
|
64
66
|
);
|
|
65
67
|
await writeFile(
|
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
|
|
4
4
|
import { versions } from '../constants/versions.js';
|
|
5
5
|
import { readSettingsAsset } from '../utils/settingsAssets.js';
|
|
6
|
+
import { agentsDoc } from './createBaseFiles.js';
|
|
6
7
|
import { createApp } from './createApp.js';
|
|
7
8
|
import { scaffoldReviewAutomation } from './scaffoldReviewAutomation.js';
|
|
8
9
|
|
|
@@ -134,6 +135,10 @@ packages:
|
|
|
134
135
|
|
|
135
136
|
await write(path.join(root, '.nvmrc'), await readSettingsAsset('project/nvmrc'));
|
|
136
137
|
|
|
138
|
+
// AI 에이전트 가이드 — 루트에 두면 모든 앱에서 공통으로 읽힌다.
|
|
139
|
+
await write(path.join(root, 'AGENTS.md'), agentsDoc(config.framework));
|
|
140
|
+
await write(path.join(root, 'CLAUDE.md'), '@AGENTS.md\n');
|
|
141
|
+
|
|
137
142
|
await write(
|
|
138
143
|
path.join(root, 'prettier.config.mjs'),
|
|
139
144
|
`// 포맷 규칙은 @byuckchon-frontend/settings 가 관리합니다.
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
## 작업 내용
|
|
2
2
|
|
|
3
|
-
<!--
|
|
3
|
+
<!--
|
|
4
|
+
아래 마커 사이는 커밋 내역으로 자동 채워집니다. 직접 수정하지 마세요.
|
|
5
|
+
덧붙일 설명이 있으면 이 주석 위·아래에 자유롭게 적으면 됩니다.
|
|
6
|
+
-->
|
|
7
|
+
<!-- byuckchon:commits:start -->
|
|
8
|
+
<!-- byuckchon:commits:end -->
|
|
4
9
|
|
|
5
10
|
## 확인 사항
|
|
6
11
|
|
|
7
|
-
<!-- 리뷰어가 중점적으로 봐야 할 부분이 있다면 적어주세요. -->
|
|
8
|
-
|
|
9
|
-
## 테스트
|
|
10
|
-
|
|
11
|
-
- [ ] 로컬에서 동작 확인
|
|
12
|
-
- [ ] `lint` / `typecheck` / `build` 통과
|
|
13
|
-
|
|
14
12
|
<!--
|
|
15
|
-
아래 마커 사이는
|
|
16
|
-
|
|
17
|
-
- 커밋 내역: 커밋 메시지 첫 줄을 타입별로 묶습니다. (feat / fix / docs ...)
|
|
18
|
-
- 리뷰 포인트: 커밋 본문에 NOTE: 또는 TODO: 로 적은 줄을 모읍니다.
|
|
13
|
+
아래 마커 사이는 커밋 본문의 NOTE: / TODO: 로 자동 채워집니다.
|
|
19
14
|
|
|
20
15
|
feat: 주문 목록 API 연동
|
|
21
16
|
|
|
22
17
|
NOTE: 응답 스키마가 미확정이라 any 가 남아 있습니다
|
|
23
18
|
TODO: 에러 처리 미구현
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
feature/update-mypage-style/hyuk + "마이페이지 디자인 적용"
|
|
27
|
-
→ "[feature] 마이페이지 디자인 적용"
|
|
20
|
+
리뷰어가 봐야 할 다른 내용은 이 주석 아래에 적어주세요.
|
|
28
21
|
-->
|
|
29
|
-
<!-- byuckchon:
|
|
30
|
-
<!-- byuckchon:
|
|
22
|
+
<!-- byuckchon:notes:start -->
|
|
23
|
+
<!-- byuckchon:notes:end -->
|
|
24
|
+
|
|
25
|
+
## 기타
|
|
26
|
+
|
|
27
|
+
<!-- 참고 링크, 스크린샷, 남은 작업 등 자유롭게 적어주세요. -->
|
|
@@ -22,8 +22,8 @@ name: PR Description
|
|
|
22
22
|
on:
|
|
23
23
|
pull_request:
|
|
24
24
|
types: [opened, synchronize, reopened]
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
# 대상 브랜치를 제한하지 않습니다. PR 본문을 채우는 일이라
|
|
26
|
+
# dev 든 main 이든 동작하는 편이 낫습니다.
|
|
27
27
|
|
|
28
28
|
concurrency:
|
|
29
29
|
group: pr-description-${{ github.event.pull_request.number }}
|