@blastlabs/utils 1.16.0 β†’ 1.18.0

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 CHANGED
@@ -255,6 +255,89 @@ function App() {
255
255
  import type { FormDevToolsProps, ApiLogEntry } from '@blastlabs/utils/components/dev';
256
256
  ```
257
257
 
258
+ ## πŸš€ CLI 도ꡬ
259
+
260
+ 이 νŒ¨ν‚€μ§€λŠ” ν”„λ‘œμ νŠΈ 섀정을 μžλ™ν™”ν•˜λŠ” CLI 도ꡬλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.
261
+
262
+ ### FSD Entity Generator
263
+
264
+ Feature-Sliced Design μ•„ν‚€ν…μ²˜μš© μ—”ν‹°ν‹° μŠ€μΊν΄λ”©μ„ μžλ™μœΌλ‘œ μƒμ„±ν•©λ‹ˆλ‹€.
265
+
266
+ ```bash
267
+ # entities ν΄λ”λ‘œ 이동
268
+ cd src/entities
269
+
270
+ # μ—”ν‹°ν‹° 생성
271
+ npx blastlabs-generate-entity user
272
+ npx blastlabs-generate-entity my-new-entity
273
+ ```
274
+
275
+ **μƒμ„±λ˜λŠ” ꡬ쑰:**
276
+ ```
277
+ user/
278
+ β”œβ”€β”€ index.ts
279
+ β”œβ”€β”€ api/
280
+ β”‚ β”œβ”€β”€ get-user-list.ts
281
+ β”‚ β”œβ”€β”€ get-user-detail.ts
282
+ β”‚ β”œβ”€β”€ user-queries.ts
283
+ β”‚ β”œβ”€β”€ index.ts
284
+ β”‚ β”œβ”€β”€ mapper/
285
+ β”‚ β”‚ β”œβ”€β”€ map-user.ts
286
+ β”‚ β”‚ └── map-user-detail.ts
287
+ β”‚ └── query/
288
+ β”‚ └── user-list-query.ts
289
+ └── model/
290
+ β”œβ”€β”€ user.ts
291
+ └── user-detail.ts
292
+ ```
293
+
294
+ **νŠΉμ§•:**
295
+ - TanStack Query queryOptions νŒ¨ν„΄ 지원
296
+ - Zod μŠ€ν‚€λ§ˆ μžλ™ 생성
297
+ - API mapper νŒ¨ν„΄ 적용
298
+ - TypeScript νƒ€μž… μ•ˆμ •μ„± 보μž₯
299
+
300
+ ### AI Rules Installer
301
+
302
+ Cursor, Claude Code용 AI κ·œμΉ™μ„ ν”„λ‘œμ νŠΈμ— μ„€μΉ˜ν•©λ‹ˆλ‹€.
303
+
304
+ ```bash
305
+ # ν”„λ‘œμ νŠΈ λ£¨νŠΈμ—μ„œ μ‹€ν–‰
306
+ npx blastlabs-init-ai-rules [options]
307
+ ```
308
+
309
+ **μ˜΅μ…˜:**
310
+ - `--fsd` - FSD μ•„ν‚€ν…μ²˜ κ·œμΉ™ 포함
311
+ - `--all` - λͺ¨λ“  κ·œμΉ™ μ„€μΉ˜ (base + fsd)
312
+ - `--list, -l` - μ„€μΉ˜ κ°€λŠ₯ν•œ κ·œμΉ™ λͺ©λ‘ 보기
313
+ - `--help, -h` - 도움말 보기
314
+
315
+ **μ˜ˆμ‹œ:**
316
+ ```bash
317
+ # κΈ°λ³Έ κ·œμΉ™λ§Œ μ„€μΉ˜
318
+ npx blastlabs-init-ai-rules
319
+
320
+ # FSD μ•„ν‚€ν…μ²˜ κ·œμΉ™ 포함
321
+ npx blastlabs-init-ai-rules --fsd
322
+
323
+ # λͺ¨λ“  κ·œμΉ™ μ„€μΉ˜
324
+ npx blastlabs-init-ai-rules --all
325
+ ```
326
+
327
+ **μ„€μΉ˜λ˜λŠ” 파일:**
328
+ ```
329
+ .cursor/rules/*.mdc # Cursor용 κ·œμΉ™
330
+ .claude/rules/*.md # Claude Code용 κ·œμΉ™
331
+ ```
332
+
333
+ **ν¬ν•¨λœ κ·œμΉ™:**
334
+ - TypeScript ν‘œμ€€
335
+ - React Hooks κ°€μ΄λ“œλΌμΈ
336
+ - ν…ŒμŠ€νŠΈ μž‘μ„± κ°€μ΄λ“œ
337
+ - λ¬Έμ„œν™” κ°€μ΄λ“œλΌμΈ
338
+ - Git 컀밋 μ»¨λ²€μ…˜
339
+ - FSD μ•„ν‚€ν…μ²˜ (선택)
340
+
258
341
  ## μ£Όμ˜μ‚¬ν•­
259
342
 
260
343
  - **개발용 μ»΄ν¬λ„ŒνŠΈ(`components/dev`)λŠ” ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œ μ œμ™Έν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.**
@@ -11,6 +11,7 @@ const RULE_CATEGORIES = {
11
11
  "react-hooks.md",
12
12
  "testing.md",
13
13
  "documentation.md",
14
+ "changelog.md",
14
15
  "git-commit.md",
15
16
  ],
16
17
  // FSD μ•„ν‚€ν…μ²˜ κ·œμΉ™
@@ -94,10 +95,13 @@ function parseFrontmatter(content) {
94
95
  const body = match[2];
95
96
 
96
97
  const frontmatter = {};
98
+ let currentKey = null;
99
+
97
100
  for (const line of yamlBlock.split("\n")) {
101
+ // ν‚€-κ°’ 쌍 νŒŒμ‹±
98
102
  const kvMatch = line.match(/^(\w+):\s*(.*)$/);
99
103
  if (kvMatch) {
100
- const key = kvMatch[1];
104
+ currentKey = kvMatch[1];
101
105
  let value = kvMatch[2].trim();
102
106
 
103
107
  if (value === "true") value = true;
@@ -112,7 +116,18 @@ function parseFrontmatter(content) {
112
116
  }
113
117
 
114
118
  if (value !== undefined) {
115
- frontmatter[key] = value;
119
+ frontmatter[currentKey] = value;
120
+ }
121
+ } else if (line.startsWith(" -") && currentKey) {
122
+ // λ°°μ—΄ κ°’ 처리 (paths λ“±)
123
+ const arrayValueMatch = line.match(/^\s*-\s*"([^"]+)"\s*$/);
124
+ if (arrayValueMatch) {
125
+ const arrayValue = arrayValueMatch[1];
126
+ // ν˜„μž¬ ν‚€μ˜ 값이 배열이 μ•„λ‹ˆλ©΄ λ°°μ—΄λ‘œ μ΄ˆκΈ°ν™”
127
+ if (!Array.isArray(frontmatter[currentKey])) {
128
+ frontmatter[currentKey] = [];
129
+ }
130
+ frontmatter[currentKey].push(arrayValue);
116
131
  }
117
132
  }
118
133
  }
@@ -125,9 +140,14 @@ function serializeCursorFrontmatter(frontmatter) {
125
140
  if (frontmatter.description) {
126
141
  yaml += `description: ${frontmatter.description}\n`;
127
142
  }
128
- if (frontmatter.globs) {
129
- yaml += `globs: "${frontmatter.globs}"\n`;
143
+ // CursorλŠ” globs μ‚¬μš© (pathsλ₯Ό globs둜 λ³€ν™˜)
144
+ // 배열인 경우 μ‰Όν‘œλ‘œ κ΅¬λΆ„λœ ν•œ μ€„λ‘œ λ³€ν™˜
145
+ const globs = frontmatter.globs || frontmatter.paths;
146
+ if (globs) {
147
+ const globsStr = Array.isArray(globs) ? globs.join(",") : globs;
148
+ yaml += `globs: "${globsStr}"\n`;
130
149
  }
150
+ // alwaysApplyλŠ” Cursor μ „μš©
131
151
  if (frontmatter.alwaysApply !== undefined) {
132
152
  yaml += `alwaysApply: ${frontmatter.alwaysApply}\n`;
133
153
  }
@@ -140,9 +160,16 @@ function serializeClaudeFrontmatter(frontmatter) {
140
160
  if (frontmatter.description) {
141
161
  yaml += `description: "${frontmatter.description}"\n`;
142
162
  }
143
- // globsλŠ” alwaysApplyκ°€ trueκ°€ μ•„λ‹Œ κ²½μš°μ—λ§Œ 포함
144
- if (frontmatter.globs && frontmatter.alwaysApply !== true) {
145
- yaml += `globs: "${frontmatter.globs}"\n`;
163
+ // pathsλŠ” 항상 μ μš©λ˜μ§€ μ•ŠλŠ” κ²½μš°μ—λ§Œ 포함
164
+ if (frontmatter.paths && frontmatter.alwaysApply !== true) {
165
+ if (Array.isArray(frontmatter.paths)) {
166
+ yaml += "paths:\n";
167
+ for (const p of frontmatter.paths) {
168
+ yaml += ` - "${p}"\n`;
169
+ }
170
+ } else {
171
+ yaml += `paths:\n - "${frontmatter.paths}"\n`;
172
+ }
146
173
  }
147
174
  // alwaysApplyλŠ” Claudeμ—μ„œ μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ μƒλž΅
148
175
  yaml += "---\n";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blastlabs/utils",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,60 @@
1
+ ---
2
+ description: "Changelog μž‘μ„± κ·œμΉ™"
3
+ globs: "CHANGELOG.md"
4
+ alwaysApply: false
5
+ ---
6
+
7
+ # Changelog Rules
8
+
9
+ ## ν•„μˆ˜ κ·œμΉ™
10
+
11
+ - [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ν˜•μ‹ μ€€μˆ˜
12
+ - Semantic Versioning μ€€μˆ˜
13
+ - μ΅œμ‹  변경사항은 `[Unreleased]` μ„Ήμ…˜μ— μΆ”κ°€
14
+
15
+ ## μ„Ήμ…˜ ꡬ쑰
16
+
17
+ ```markdown
18
+ # Changelog
19
+
20
+ ## [Unreleased]
21
+
22
+ ### Added
23
+ - μƒˆλ‘œμš΄ κΈ°λŠ₯
24
+
25
+ ### Changed
26
+ - κΈ°μ‘΄ κΈ°λŠ₯의 λ³€κ²½
27
+
28
+ ### Deprecated
29
+ - κ³§ 제거될 κΈ°λŠ₯
30
+
31
+ ### Removed
32
+ - 제거된 κΈ°λŠ₯
33
+
34
+ ### Fixed
35
+ - 버그 μˆ˜μ •
36
+
37
+ ### Security
38
+ - λ³΄μ•ˆ 패치
39
+
40
+ ## [1.0.0] - 2024-01-01
41
+ ```
42
+
43
+ ## 버전 릴리즈 μ‹œ
44
+
45
+ 1. `[Unreleased]` λ‚΄μš©μ„ μƒˆ 버전 μ„Ήμ…˜μœΌλ‘œ 이동
46
+ 2. 릴리즈 λ‚ μ§œ μΆ”κ°€
47
+ 3. μƒˆλ‘œμš΄ `[Unreleased]` μ„Ήμ…˜ 생성
48
+
49
+ ```markdown
50
+ ## [Unreleased]
51
+
52
+ ## [1.1.0] - 2024-02-01
53
+ ### Added
54
+ - 이전에 Unreleased에 있던 λ‚΄μš©
55
+ ```
56
+
57
+ ## μ€‘μš”
58
+
59
+ - **Always** update CHANGELOG.md when making changes
60
+ - 배포 μ‹œ λ°˜λ“œμ‹œ changelog 확인
@@ -15,7 +15,16 @@ alwaysApply: false
15
15
 
16
16
  - κΈ°λŠ₯ μΆ”κ°€ μ‹œ README.md μ—…λ°μ΄νŠΈ
17
17
  - μƒˆ hooks μΆ”κ°€ μ‹œ κ΄€λ ¨ docs/*.md μ—…λ°μ΄νŠΈ
18
+ - 변경사항은 λ°˜λ“œμ‹œ CHANGELOG.md에 기둝
19
+
20
+ ## CHANGELOG μž‘μ„±
21
+
22
+ - [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ν˜•μ‹ μ€€μˆ˜
23
+ - μ΅œμ‹  변경사항은 `[Unreleased]` μ„Ήμ…˜μ— μΆ”κ°€
24
+ - μ„Ήμ…˜: Added, Changed, Deprecated, Removed, Fixed, Security
25
+ - 버전 릴리즈 μ‹œ `[Unreleased]`λ₯Ό ν•΄λ‹Ή λ²„μ „μœΌλ‘œ 이동
18
26
 
19
27
  ## ν•„μˆ˜ 사항
20
28
 
21
29
  - **Always** update documentation when adding features
30
+ - **Always** update CHANGELOG.md for any changes
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: "Entities λ ˆμ΄μ–΄ ꡬ쑰 및 API νŒ¨ν„΄"
3
- globs: "**/entities/**"
3
+ paths:
4
+ - "**/entities/**"
4
5
  ---
5
6
 
6
7
  # Entities Layer (μ—”ν‹°ν‹°)
@@ -1,7 +1,10 @@
1
1
  ---
2
2
  description: "React Hooks 개발 κ·œμΉ™ 및 SSR μ•ˆμ „μ„±"
3
- globs: "**/use*.ts,**/use*.tsx"
4
- alwaysApply: false
3
+ paths:
4
+ - "src/hooks/**/*.ts"
5
+ - "src/hooks/**/*.tsx"
6
+ - "**/use*.ts"
7
+ - "**/use*.tsx"
5
8
  ---
6
9
 
7
10
  # React Hooks Rules
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: "Shared λ ˆμ΄μ–΄ ꡬ쑰 및 lib vs utils ꡬ뢄"
3
- globs: "**/shared/**"
3
+ paths:
4
+ - "**/shared/**"
4
5
  ---
5
6
 
6
7
  # Shared Layer (곡유 λ ˆμ΄μ–΄)
package/rules/testing.md CHANGED
@@ -1,7 +1,9 @@
1
1
  ---
2
2
  description: "ν…ŒμŠ€νŠΈ μž‘μ„± κ°€μ΄λ“œλΌμΈ"
3
- globs: "**/*.test.ts,**/*.test.tsx,**/__tests__/**"
4
- alwaysApply: false
3
+ paths:
4
+ - "**/*.test.ts"
5
+ - "**/*.test.tsx"
6
+ - "**/__tests__/**"
5
7
  ---
6
8
 
7
9
  # Testing Guidelines
@@ -1,7 +1,8 @@
1
1
  ---
2
2
  description: "TypeScript μ½”λ”© ν‘œμ€€ 및 νƒ€μž… κ·œμΉ™"
3
- globs: "**/*.ts,**/*.tsx"
4
- alwaysApply: false
3
+ paths:
4
+ - "**/*.ts"
5
+ - "**/*.tsx"
5
6
  ---
6
7
 
7
8
  # TypeScript Standards
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  description: "Views λ ˆμ΄μ–΄ (νŽ˜μ΄μ§€) ꡬ쑰"
3
- globs: "**/views/**"
3
+ paths:
4
+ - "**/views/**"
4
5
  ---
5
6
 
6
7
  # Views Layer (νŽ˜μ΄μ§€ λ ˆμ΄μ–΄)