tylersong 1.0.8 → 1.0.10

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.
@@ -0,0 +1,158 @@
1
+ <!-- 8c733d2f-63d8-4158-aa6e-255c23deedca 77c7f805-6518-4181-90b0-4dff17016b38 -->
2
+ # 프로젝트 품질 개선 계획
3
+
4
+ ## 📊 현재 프로젝트 분석
5
+
6
+ ### ✅ 장점
7
+
8
+ 1. **깔끔한 코드 구조**: TypeScript 기반의 명확한 단일 파일 구조
9
+ 2. **타입 안정성**: TypeScript 사용으로 인터페이스 정의 및 strict 모드 활성화
10
+ 3. **Bun 지원**: 최신 런타임 지원으로 성능 최적화 가능
11
+ 4. **풍부한 문서화**: docs 폴더에 배포, 사용법 등 상세 문서 작성됨
12
+ 5. **사용자 친화적**: Commander.js, Inquirer.js로 직관적인 CLI 경험 제공
13
+ 6. **크로스 플랫폼**: Windows, macOS, Linux 모두 지원하는 URL 열기 기능
14
+
15
+ ### ❌ 단점 및 개선 필요 사항
16
+
17
+ #### 1. **테스트 코드 부재** (Critical)
18
+
19
+ - 현재 `package.json`에 "No test specified"로 테스트 미구현
20
+ - 사용자 규칙에 따라 Vitest 사용 필요
21
+
22
+ #### 2. **에러 처리 부족** (High)
23
+
24
+ - `exec()` 함수의 에러 핸들링 없음
25
+ - URL 열기 실패 시 사용자 피드백 없음
26
+ - 프로미스 거부(rejection) 처리가 `.catch(console.error)`로만 처리
27
+
28
+ #### 3. **린팅/포맷팅 설정 없음** (Medium)
29
+
30
+ - ESLint, Prettier 등 코드 품질 도구 미설정
31
+ - 일관된 코드 스타일 관리 어려움
32
+
33
+ #### 4. **CI/CD 파이프라인 없음** (High)
34
+
35
+ - docs에 워크플로우 문서는 있으나 실제 `.github/workflows` 폴더 없음
36
+ - 자동 테스트, 빌드, 배포 검증 불가
37
+
38
+ #### 5. **버전 중복 관리** (Low)
39
+
40
+ - `package.json`과 `src/index.ts`에 버전이 각각 하드코딩됨
41
+ - 버전 업데이트 시 두 곳을 수정해야 함
42
+
43
+ #### 6. **Bun 우선 정책 미준수** (Medium)
44
+
45
+ - `prepublishOnly` 스크립트가 `npm run build` 사용
46
+ - 사용자 규칙에 따라 bun 사용 필요
47
+
48
+ #### 7. **Git 관리 개선 필요** (Low)
49
+
50
+ - `.gitignore`에 `dist/`, `*.log` 등 명시 필요
51
+ - `node_modules` 제외 확인 필요
52
+
53
+ #### 8. **보안 및 의존성 관리** (Medium)
54
+
55
+ - 의존성 취약점 자동 검사 없음
56
+ - 정기적인 업데이트 메커니즘 부재
57
+
58
+ #### 9. **환경별 설정 분리 없음** (Low)
59
+
60
+ - 개인정보(GitHub URL, 이메일)가 하드코딩됨
61
+ - 설정 파일로 분리하면 재사용성 향상
62
+
63
+ ## 🔧 개선 작업 항목
64
+
65
+ ### 1. 테스트 환경 구축 (`test/` 폴더)
66
+
67
+ - **파일**: `test/index.test.ts`
68
+ - Vitest 설치 및 설정
69
+ - 주요 함수(`openUrl`, `main`) 단위 테스트 작성
70
+ - CLI 옵션별 통합 테스트 작성
71
+
72
+ ### 2. 에러 처리 강화 (`src/index.ts`)
73
+
74
+ ```typescript
75
+ // openUrl 함수 개선
76
+ const openUrl = (url: string): void => {
77
+ exec(`${command} ${url}`, (error) => {
78
+ if (error) {
79
+ console.error(chalk.red('❌ 브라우저를 열 수 없습니다.'));
80
+ }
81
+ });
82
+ };
83
+ ```
84
+
85
+ ### 3. 린팅/포맷팅 설정
86
+
87
+ - **파일**: `.eslintrc.json`, `.prettierrc`, `.editorconfig`
88
+ - ESLint + TypeScript 플러그인 설치
89
+ - Prettier 설정
90
+ - pre-commit 훅 설정 (husky)
91
+
92
+ ### 4. CI/CD 파이프라인 구축
93
+
94
+ - **파일**: `.github/workflows/ci.yml`, `.github/workflows/publish.yml`
95
+ - Pull Request 시 자동 테스트/린트
96
+ - main 브랜치 머지 시 자동 빌드 검증
97
+ - 태그 푸시 시 NPM 자동 배포
98
+
99
+ ### 5. 버전 관리 개선
100
+
101
+ - `src/index.ts`에서 버전 하드코딩 제거
102
+ - `package.json` 버전을 동적으로 읽어오기
103
+
104
+ ### 6. 프로젝트 설정 개선
105
+
106
+ - **파일**: `.gitignore`, `vitest.config.ts`
107
+ - Bun 우선 스크립트 수정
108
+ - Git ignore 규칙 추가
109
+
110
+ ### 7. 문서 업데이트
111
+
112
+ - **파일**: `docs/testing.md`, `docs/development.md`
113
+ - 테스트 실행 방법 문서화
114
+ - 개발 환경 설정 가이드 추가
115
+ - 파이프라인 다이어그램 (Mermaid 그래프)
116
+
117
+ ## 📝 생성/수정될 파일 목록
118
+
119
+ ### 새로 생성
120
+
121
+ - `test/index.test.ts` - 테스트 코드
122
+ - `vitest.config.ts` - Vitest 설정
123
+ - `.eslintrc.json` - ESLint 설정
124
+ - `.prettierrc` - Prettier 설정
125
+ - `.gitignore` - Git ignore 규칙
126
+ - `.github/workflows/ci.yml` - CI 워크플로우
127
+ - `.github/workflows/publish.yml` - 배포 워크플로우
128
+ - `docs/testing.md` - 테스트 가이드
129
+ - `docs/pipeline.md` - CI/CD 파이프라인 설명 (Mermaid 그래프 포함)
130
+
131
+ ### 수정
132
+
133
+ - `src/index.ts` - 에러 처리 강화, 버전 동적 로딩
134
+ - `package.json` - 테스트 스크립트 추가, bun 우선 스크립트 수정
135
+ - `README.md` - 테스트, 린팅 배지 추가
136
+
137
+ ## 🎯 우선순위
138
+
139
+ 1. **테스트 환경 구축** (가장 중요)
140
+ 2. **에러 처리 강화**
141
+ 3. **CI/CD 파이프라인**
142
+ 4. **린팅/포맷팅 설정**
143
+ 5. **기타 개선 사항**
144
+
145
+ ### To-dos
146
+
147
+ - [ ] Vitest 설치 및 설정 파일 생성 (vitest.config.ts)
148
+ - [ ] test/index.test.ts 파일 작성 (주요 기능 테스트)
149
+ - [ ] src/index.ts의 에러 처리 강화 (openUrl, main 함수)
150
+ - [ ] ESLint, Prettier 설정 파일 생성
151
+ - [ ] .github/workflows/ci.yml 생성 (테스트, 린트 자동화)
152
+ - [ ] .github/workflows/publish.yml 생성 (NPM 자동 배포)
153
+ - [ ] src/index.ts에서 버전을 package.json에서 동적으로 읽어오기
154
+ - [ ] .gitignore 파일 생성 또는 개선
155
+ - [ ] package.json의 테스트/린트 스크립트 추가, bun 우선 수정
156
+ - [ ] docs/testing.md 문서 작성
157
+ - [ ] docs/pipeline.md 작성 (Mermaid 그래프 포함)
158
+ - [ ] README.md에 테스트, 린팅 배지 및 정보 추가
package/.editorconfig ADDED
@@ -0,0 +1,15 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ trim_trailing_whitespace = true
8
+
9
+ [*.{ts,js,json}]
10
+ indent_style = space
11
+ indent_size = 2
12
+
13
+ [*.md]
14
+ trim_trailing_whitespace = false
15
+
package/.eslintrc.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "env": {
3
+ "node": true,
4
+ "es2021": true
5
+ },
6
+ "extends": [
7
+ "eslint:recommended",
8
+ "plugin:@typescript-eslint/recommended",
9
+ "plugin:@typescript-eslint/recommended-requiring-type-checking"
10
+ ],
11
+ "parser": "@typescript-eslint/parser",
12
+ "parserOptions": {
13
+ "ecmaVersion": "latest",
14
+ "sourceType": "module",
15
+ "project": "./tsconfig.eslint.json"
16
+ },
17
+ "plugins": ["@typescript-eslint"],
18
+ "rules": {
19
+ "@typescript-eslint/no-unused-vars": [
20
+ "error",
21
+ {
22
+ "argsIgnorePattern": "^_",
23
+ "varsIgnorePattern": "^_"
24
+ }
25
+ ],
26
+ "@typescript-eslint/explicit-function-return-type": "warn",
27
+ "@typescript-eslint/no-explicit-any": "warn",
28
+ "@typescript-eslint/no-floating-promises": "error",
29
+ "no-console": "off"
30
+ },
31
+ "ignorePatterns": ["dist", "node_modules", "*.config.ts", "*.config.js", "**/*.d.ts"]
32
+ }
33
+
@@ -1,4 +1,4 @@
1
- name: Continuous Integration
1
+ name: CI
2
2
 
3
3
  on:
4
4
  push:
@@ -8,169 +8,72 @@ on:
8
8
 
9
9
  jobs:
10
10
  test:
11
- name: Test
11
+ name: Test & Lint
12
12
  runs-on: ubuntu-latest
13
13
 
14
14
  strategy:
15
15
  matrix:
16
- runtime: [node, bun]
16
+ node-version: [18.x, 20.x]
17
17
 
18
18
  steps:
19
- - name: Checkout code
19
+ - name: 코드 체크아웃
20
20
  uses: actions/checkout@v4
21
21
 
22
- - name: Setup runtime environment
23
- uses: ./.github/actions/setup-runtime
22
+ - name: Bun 설치
23
+ uses: oven-sh/setup-bun@v1
24
24
  with:
25
- runtime: ${{ matrix.runtime }}
26
-
27
- - name: Run tests (Node.js)
28
- if: matrix.runtime == 'node'
29
- run: npm test
30
-
31
- - name: Run tests (Bun)
32
- if: matrix.runtime == 'bun'
33
- run: bun test || echo "No bun tests specified"
34
-
35
- - name: Test CLI functionality (Node.js)
36
- if: matrix.runtime == 'node'
37
- run: |
38
- npm run build
39
- node dist/index.js --version
40
- node dist/index.js --help
41
-
42
- - name: Test CLI functionality (Bun)
43
- if: matrix.runtime == 'bun'
44
- run: |
45
- bun run build:bun
46
- bun run dist/index.js --version
47
- bun run dist/index.js --help
25
+ bun-version: latest
48
26
 
49
- build:
50
- name: Build & Upload Artifacts
51
- runs-on: ubuntu-latest
52
- needs: test
27
+ - name: 의존성 캐시
28
+ uses: actions/cache@v3
29
+ with:
30
+ path: ~/.bun/install/cache
31
+ key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
32
+ restore-keys: |
33
+ ${{ runner.os }}-bun-
53
34
 
54
- steps:
55
- - name: Checkout code
56
- uses: actions/checkout@v4
35
+ - name: 의존성 설치
36
+ run: bun install
57
37
 
58
- - name: Setup Node.js environment
59
- uses: ./.github/actions/setup-runtime
60
- with:
61
- runtime: node
38
+ - name: 타입 체크
39
+ run: bun run build
62
40
 
63
- - name: Build TypeScript
64
- run: npm run build
41
+ - name: 린트 실행
42
+ run: bun run lint
65
43
 
66
- - name: Upload build artifacts
67
- uses: actions/upload-artifact@v4
68
- with:
69
- name: dist-files-${{ github.sha }}
70
- path: dist/
71
- retention-days: 30
44
+ - name: 테스트 실행
45
+ run: bun run test
72
46
 
73
- - name: Upload type definitions
74
- uses: actions/upload-artifact@v4
47
+ - name: 테스트 커버리지 업로드
48
+ if: matrix.node-version == '20.x'
49
+ uses: codecov/codecov-action@v3
75
50
  with:
76
- name: types-${{ github.sha }}
77
- path: |
78
- dist/*.d.ts
79
- dist/*.d.ts.map
80
- retention-days: 30
81
-
82
- lint:
83
- name: Code Quality
51
+ files: ./coverage/coverage-final.json
52
+ flags: unittests
53
+ name: codecov-umbrella
54
+
55
+ build:
56
+ name: Build
84
57
  runs-on: ubuntu-latest
58
+ needs: test
85
59
 
86
60
  steps:
87
- - name: Checkout code
61
+ - name: 코드 체크아웃
88
62
  uses: actions/checkout@v4
89
63
 
90
- - name: Setup Node.js environment
91
- uses: ./.github/actions/setup-runtime
64
+ - name: Bun 설치
65
+ uses: oven-sh/setup-bun@v1
92
66
  with:
93
- runtime: node
94
-
95
- - name: Check TypeScript compilation
96
- run: npx tsc --noEmit
67
+ bun-version: latest
97
68
 
98
- - name: Check code formatting (if prettier is added)
99
- run: echo "Add prettier check here if needed"
69
+ - name: 의존성 설치
70
+ run: bun install
100
71
 
101
- - name: Security audit
102
- run: npm audit --audit-level=moderate
103
-
104
- notify:
105
- name: Notify Results
106
- runs-on: ubuntu-latest
107
- needs: [test, build, lint]
108
- if: always()
72
+ - name: Bun으로 빌드
73
+ run: bun run build:bun
109
74
 
110
- steps:
111
- - name: Checkout code
112
- uses: actions/checkout@v4
113
-
114
- - name: Determine overall status
115
- id: status
116
- run: |
117
- if [ "${{ needs.test.result }}" == "success" ] && [ "${{ needs.build.result }}" == "success" ] && [ "${{ needs.lint.result }}" == "success" ]; then
118
- echo "status=success" >> $GITHUB_OUTPUT
119
- echo "title=CI 성공 🎉" >> $GITHUB_OUTPUT
120
- echo "description=모든 테스트, 빌드, 린팅이 성공적으로 완료되었습니다." >> $GITHUB_OUTPUT
121
- else
122
- echo "status=failure" >> $GITHUB_OUTPUT
123
- echo "title=CI 실패 💥" >> $GITHUB_OUTPUT
124
- echo "description=CI 파이프라인에서 오류가 발생했습니다. 로그를 확인해주세요." >> $GITHUB_OUTPUT
125
- fi
126
-
127
- - name: Create fields JSON
128
- id: fields
129
- run: |
130
- FIELDS=$(cat << EOF
131
- [
132
- {
133
- "name": "브랜치",
134
- "value": "${{ github.ref_name }}",
135
- "inline": true
136
- },
137
- {
138
- "name": "커밋",
139
- "value": "[\`${GITHUB_SHA:0:7}\`](https://github.com/${{ github.repository }}/commit/${{ github.sha }})",
140
- "inline": true
141
- },
142
- {
143
- "name": "테스트",
144
- "value": "${{ needs.test.result == 'success' && '✅ 성공' || '❌ 실패' }}",
145
- "inline": true
146
- },
147
- {
148
- "name": "빌드",
149
- "value": "${{ needs.build.result == 'success' && '✅ 성공' || '❌ 실패' }}",
150
- "inline": true
151
- },
152
- {
153
- "name": "린팅",
154
- "value": "${{ needs.lint.result == 'success' && '✅ 성공' || '❌ 실패' }}",
155
- "inline": true
156
- },
157
- {
158
- "name": "작업자",
159
- "value": "${{ github.actor }}",
160
- "inline": true
161
- }
162
- ]
163
- EOF
164
- )
165
- echo "fields<<EOF" >> $GITHUB_OUTPUT
166
- echo "$FIELDS" >> $GITHUB_OUTPUT
167
- echo "EOF" >> $GITHUB_OUTPUT
168
-
169
- - name: Send Discord notification
170
- uses: ./.github/actions/discord-notify
75
+ - name: 빌드 결과물 업로드
76
+ uses: actions/upload-artifact@v3
171
77
  with:
172
- webhook-url: ${{ secrets.DISCORD_WEBHOOK_URL }}
173
- status: ${{ steps.status.outputs.status }}
174
- title: ${{ steps.status.outputs.title }}
175
- description: ${{ steps.status.outputs.description }}
176
- fields: ${{ steps.fields.outputs.fields }}
78
+ name: dist
79
+ path: dist/
@@ -0,0 +1,164 @@
1
+ name: Deploy to NPM
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ tags: ["v*"]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ permissions:
11
+ contents: write
12
+ packages: write
13
+
14
+ jobs:
15
+ # 통합된 CI + 배포 작업
16
+ deploy:
17
+ name: CI & Deploy
18
+ runs-on: ubuntu-latest
19
+
20
+ steps:
21
+ # === 기본 Setup ===
22
+ - name: Checkout
23
+ uses: actions/checkout@v4
24
+ with:
25
+ token: ${{ secrets.GITHUB_TOKEN }}
26
+ fetch-depth: 0
27
+
28
+ - name: Setup Node.js
29
+ uses: actions/setup-node@v4
30
+ with:
31
+ node-version: "20.x"
32
+ registry-url: "https://registry.npmjs.org/"
33
+ cache: "npm"
34
+
35
+ - name: Install dependencies
36
+ run: npm ci
37
+
38
+ # === CI 단계 ===
39
+ - name: Type check
40
+ run: npx tsc --noEmit
41
+
42
+ - name: Build
43
+ run: npm run build
44
+
45
+ - name: Test CLI
46
+ run: |
47
+ node dist/index.js --version
48
+ node dist/index.js --help
49
+
50
+ - name: Security audit
51
+ run: npm audit --audit-level=moderate || true
52
+
53
+ # === 버전 관리 (main 브랜치만) ===
54
+ - name: Auto version update
55
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
56
+ run: |
57
+ # Git 설정
58
+ git config user.name "github-actions[bot]"
59
+ git config user.email "github-actions[bot]@users.noreply.github.com"
60
+
61
+ CURRENT_VERSION=$(node -p "require('./package.json').version")
62
+ PUBLISHED_VERSION=$(npm view tylersong version 2>/dev/null || echo "0.0.0")
63
+
64
+ echo "📦 Current: $CURRENT_VERSION | Published: $PUBLISHED_VERSION"
65
+
66
+ # 같은 버전이면 자동 업데이트
67
+ if [ "$CURRENT_VERSION" == "$PUBLISHED_VERSION" ]; then
68
+ echo "🔄 Auto-updating version..."
69
+
70
+ # 커밋 메시지로 버전 타입 결정
71
+ COMMIT_MSG=$(git log -1 --pretty=%B)
72
+ if echo "$COMMIT_MSG" | grep -qE "BREAKING CHANGE|feat!|fix!"; then
73
+ VERSION_TYPE="major"
74
+ elif echo "$COMMIT_MSG" | grep -qE "^feat(\(.+\))?:"; then
75
+ VERSION_TYPE="minor"
76
+ else
77
+ VERSION_TYPE="patch"
78
+ fi
79
+
80
+ echo "📈 Version type: $VERSION_TYPE"
81
+
82
+ # 버전 업데이트
83
+ npm version $VERSION_TYPE --no-git-tag-version
84
+ NEW_VERSION=$(node -p "require('./package.json').version")
85
+
86
+ echo "✅ Updated to v$NEW_VERSION"
87
+ echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV
88
+
89
+ # 재빌드 (버전 반영)
90
+ npm run build
91
+
92
+ # 커밋 & 푸시
93
+ git add package.json package-lock.json
94
+ git commit -m "chore: bump version to v$NEW_VERSION [skip ci]"
95
+ git push origin main
96
+
97
+ echo "SHOULD_PUBLISH=true" >> $GITHUB_ENV
98
+ else
99
+ echo "✅ Version already updated"
100
+ echo "NEW_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV
101
+ echo "SHOULD_PUBLISH=true" >> $GITHUB_ENV
102
+ fi
103
+
104
+ # === 태그 기반 배포 ===
105
+ - name: Tag deployment check
106
+ if: startsWith(github.ref, 'refs/tags/v')
107
+ run: |
108
+ VERSION=$(node -p "require('./package.json').version")
109
+ echo "🏷️ Tag deployment for v$VERSION"
110
+ echo "NEW_VERSION=$VERSION" >> $GITHUB_ENV
111
+ echo "SHOULD_PUBLISH=true" >> $GITHUB_ENV
112
+
113
+ # === NPM 배포 ===
114
+ - name: Publish to NPM
115
+ if: |
116
+ env.SHOULD_PUBLISH == 'true' &&
117
+ github.event_name != 'pull_request'
118
+ run: npm publish
119
+ env:
120
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
121
+
122
+ # === GitHub Release (태그만) ===
123
+ - name: Create GitHub Release
124
+ if: startsWith(github.ref, 'refs/tags/v')
125
+ uses: actions/github-script@v7
126
+ with:
127
+ github-token: ${{ secrets.GITHUB_TOKEN }}
128
+ script: |
129
+ const version = process.env.NEW_VERSION;
130
+ const tagName = context.ref.replace('refs/tags/', '');
131
+
132
+ await github.rest.repos.createRelease({
133
+ owner: context.repo.owner,
134
+ repo: context.repo.repo,
135
+ tag_name: tagName,
136
+ name: `Release v${version}`,
137
+ body: `🚀 **tylersong CLI v${version}**
138
+
139
+ ### 설치
140
+ \`\`\`bash
141
+ npx tylersong
142
+ \`\`\`
143
+
144
+ ### 변경사항
145
+ 전체 변경사항은 [커밋 히스토리](https://github.com/${context.repo.owner}/${context.repo.repo}/commits/v${version})를 확인해주세요.`,
146
+ draft: false,
147
+ prerelease: false
148
+ });
149
+
150
+ # === 성공 알림 ===
151
+ - name: Success notification
152
+ if: success() && env.SHOULD_PUBLISH == 'true'
153
+ run: |
154
+ echo "🎉 Successfully deployed tylersong v${{ env.NEW_VERSION }}"
155
+ echo "📦 NPM: https://www.npmjs.com/package/tylersong"
156
+ echo "🚀 Install: npx tylersong"
157
+
158
+ # === 실패 알림 ===
159
+ - name: Failure notification
160
+ if: failure()
161
+ run: |
162
+ echo "❌ Deployment failed!"
163
+ echo "📋 Check the logs above for details"
164
+ exit 1