craftdesk 0.3.0 → 0.4.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.
Files changed (175) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +943 -46
  3. package/dist/commands/add.d.ts +5 -0
  4. package/dist/commands/add.d.ts.map +1 -1
  5. package/dist/commands/add.js +302 -6
  6. package/dist/commands/add.js.map +1 -1
  7. package/dist/commands/convert.d.ts +8 -0
  8. package/dist/commands/convert.d.ts.map +1 -0
  9. package/dist/commands/convert.js +146 -0
  10. package/dist/commands/convert.js.map +1 -0
  11. package/dist/commands/info.d.ts +8 -0
  12. package/dist/commands/info.d.ts.map +1 -0
  13. package/dist/commands/info.js +66 -0
  14. package/dist/commands/info.js.map +1 -0
  15. package/dist/commands/init.d.ts +5 -0
  16. package/dist/commands/init.d.ts.map +1 -1
  17. package/dist/commands/init.js +8 -2
  18. package/dist/commands/init.js.map +1 -1
  19. package/dist/commands/install.d.ts +5 -0
  20. package/dist/commands/install.d.ts.map +1 -1
  21. package/dist/commands/install.js +24 -4
  22. package/dist/commands/install.js.map +1 -1
  23. package/dist/commands/list.d.ts +5 -0
  24. package/dist/commands/list.d.ts.map +1 -1
  25. package/dist/commands/list.js +72 -7
  26. package/dist/commands/list.js.map +1 -1
  27. package/dist/commands/login.d.ts +8 -0
  28. package/dist/commands/login.d.ts.map +1 -0
  29. package/dist/commands/login.js +158 -0
  30. package/dist/commands/login.js.map +1 -0
  31. package/dist/commands/logout.d.ts +8 -0
  32. package/dist/commands/logout.d.ts.map +1 -0
  33. package/dist/commands/logout.js +51 -0
  34. package/dist/commands/logout.js.map +1 -0
  35. package/dist/commands/outdated.d.ts +23 -0
  36. package/dist/commands/outdated.d.ts.map +1 -0
  37. package/dist/commands/outdated.js +268 -0
  38. package/dist/commands/outdated.js.map +1 -0
  39. package/dist/commands/publish.d.ts +8 -0
  40. package/dist/commands/publish.d.ts.map +1 -0
  41. package/dist/commands/publish.js +198 -0
  42. package/dist/commands/publish.js.map +1 -0
  43. package/dist/commands/remove.d.ts +5 -0
  44. package/dist/commands/remove.d.ts.map +1 -1
  45. package/dist/commands/remove.js +51 -10
  46. package/dist/commands/remove.js.map +1 -1
  47. package/dist/commands/search.d.ts +8 -0
  48. package/dist/commands/search.d.ts.map +1 -0
  49. package/dist/commands/search.js +60 -0
  50. package/dist/commands/search.js.map +1 -0
  51. package/dist/commands/update.d.ts +8 -0
  52. package/dist/commands/update.d.ts.map +1 -0
  53. package/dist/commands/update.js +369 -0
  54. package/dist/commands/update.js.map +1 -0
  55. package/dist/commands/whoami.d.ts +8 -0
  56. package/dist/commands/whoami.d.ts.map +1 -0
  57. package/dist/commands/whoami.js +58 -0
  58. package/dist/commands/whoami.js.map +1 -0
  59. package/dist/converters/base-converter.d.ts +89 -0
  60. package/dist/converters/base-converter.d.ts.map +1 -0
  61. package/dist/converters/base-converter.js +249 -0
  62. package/dist/converters/base-converter.js.map +1 -0
  63. package/dist/converters/continue-converter.d.ts +53 -0
  64. package/dist/converters/continue-converter.d.ts.map +1 -0
  65. package/dist/converters/continue-converter.js +243 -0
  66. package/dist/converters/continue-converter.js.map +1 -0
  67. package/dist/converters/cursor-converter.d.ts +70 -0
  68. package/dist/converters/cursor-converter.d.ts.map +1 -0
  69. package/dist/converters/cursor-converter.js +272 -0
  70. package/dist/converters/cursor-converter.js.map +1 -0
  71. package/dist/index.js +34 -3
  72. package/dist/index.js.map +1 -1
  73. package/dist/services/config-manager.d.ts +128 -10
  74. package/dist/services/config-manager.d.ts.map +1 -1
  75. package/dist/services/config-manager.js +189 -18
  76. package/dist/services/config-manager.js.map +1 -1
  77. package/dist/services/converter.d.ts +53 -0
  78. package/dist/services/converter.d.ts.map +1 -0
  79. package/dist/services/converter.js +185 -0
  80. package/dist/services/converter.js.map +1 -0
  81. package/dist/services/craft-wrapper.d.ts +108 -0
  82. package/dist/services/craft-wrapper.d.ts.map +1 -0
  83. package/dist/services/craft-wrapper.js +268 -0
  84. package/dist/services/craft-wrapper.js.map +1 -0
  85. package/dist/services/git-resolver.d.ts +9 -3
  86. package/dist/services/git-resolver.d.ts.map +1 -1
  87. package/dist/services/git-resolver.js +29 -10
  88. package/dist/services/git-resolver.js.map +1 -1
  89. package/dist/services/installer.d.ts +51 -1
  90. package/dist/services/installer.d.ts.map +1 -1
  91. package/dist/services/installer.js +245 -14
  92. package/dist/services/installer.js.map +1 -1
  93. package/dist/services/plugin-resolver.d.ts +80 -0
  94. package/dist/services/plugin-resolver.d.ts.map +1 -0
  95. package/dist/services/plugin-resolver.js +182 -0
  96. package/dist/services/plugin-resolver.js.map +1 -0
  97. package/dist/services/registry-client.d.ts +132 -5
  98. package/dist/services/registry-client.d.ts.map +1 -1
  99. package/dist/services/registry-client.js +239 -34
  100. package/dist/services/registry-client.js.map +1 -1
  101. package/dist/services/settings-manager.d.ts +151 -0
  102. package/dist/services/settings-manager.d.ts.map +1 -0
  103. package/dist/services/settings-manager.js +333 -0
  104. package/dist/services/settings-manager.js.map +1 -0
  105. package/dist/types/claude-settings.d.ts +155 -0
  106. package/dist/types/claude-settings.d.ts.map +1 -0
  107. package/dist/types/claude-settings.js +20 -0
  108. package/dist/types/claude-settings.js.map +1 -0
  109. package/dist/types/converter.d.ts +98 -0
  110. package/dist/types/converter.d.ts.map +1 -0
  111. package/dist/types/converter.js +6 -0
  112. package/dist/types/converter.js.map +1 -0
  113. package/dist/types/craftdesk-json.d.ts +63 -3
  114. package/dist/types/craftdesk-json.d.ts.map +1 -1
  115. package/dist/types/craftdesk-lock.d.ts +62 -1
  116. package/dist/types/craftdesk-lock.d.ts.map +1 -1
  117. package/dist/utils/crypto.d.ts +23 -0
  118. package/dist/utils/crypto.d.ts.map +1 -0
  119. package/dist/utils/crypto.js +52 -0
  120. package/dist/utils/crypto.js.map +1 -0
  121. package/dist/utils/file-system.d.ts +43 -0
  122. package/dist/utils/file-system.d.ts.map +1 -1
  123. package/dist/utils/file-system.js +45 -2
  124. package/dist/utils/file-system.js.map +1 -1
  125. package/dist/utils/logger.d.ts +75 -0
  126. package/dist/utils/logger.d.ts.map +1 -1
  127. package/dist/utils/logger.js +76 -1
  128. package/dist/utils/logger.js.map +1 -1
  129. package/dist/utils/version-utils.d.ts +63 -0
  130. package/dist/utils/version-utils.d.ts.map +1 -0
  131. package/dist/utils/version-utils.js +130 -0
  132. package/dist/utils/version-utils.js.map +1 -0
  133. package/package.json +36 -9
  134. package/.claude/settings.local.json +0 -19
  135. package/.github/workflows/ci.yml +0 -94
  136. package/API.md +0 -414
  137. package/TESTING.md +0 -263
  138. package/dist/commands/config.d.ts +0 -3
  139. package/dist/commands/config.d.ts.map +0 -1
  140. package/dist/commands/config.js +0 -56
  141. package/dist/commands/config.js.map +0 -1
  142. package/dist/types/config.d.ts +0 -17
  143. package/dist/types/config.d.ts.map +0 -1
  144. package/dist/types/config.js +0 -3
  145. package/dist/types/config.js.map +0 -1
  146. package/docs/DEPENDENCY_RESOLUTION.md +0 -237
  147. package/examples/craftdesk-all-sources.json +0 -79
  148. package/examples/craftdesk-git-monorepo.json +0 -41
  149. package/examples/craftdesk-multi-registry.json +0 -40
  150. package/examples/craftdesk-with-registries.json +0 -49
  151. package/examples/simple-craftdesk.json +0 -10
  152. package/src/commands/add.ts +0 -314
  153. package/src/commands/init.ts +0 -55
  154. package/src/commands/install.ts +0 -126
  155. package/src/commands/list.ts +0 -126
  156. package/src/commands/remove.ts +0 -82
  157. package/src/index.ts +0 -56
  158. package/src/services/config-manager.ts +0 -150
  159. package/src/services/git-resolver.ts +0 -373
  160. package/src/services/installer.ts +0 -314
  161. package/src/services/registry-client.ts +0 -163
  162. package/src/types/craftdesk-json.ts +0 -53
  163. package/src/types/craftdesk-lock.ts +0 -38
  164. package/src/utils/file-system.ts +0 -55
  165. package/src/utils/logger.ts +0 -82
  166. package/tests/fixtures/craftdesk-git.json +0 -17
  167. package/tests/fixtures/craftdesk.json +0 -15
  168. package/tests/helpers/test-utils.ts +0 -60
  169. package/tests/integration/init-command.test.ts +0 -70
  170. package/tests/integration/list-command.test.ts +0 -77
  171. package/tests/unit/config-manager.test.ts +0 -228
  172. package/tests/unit/git-resolver.test.ts +0 -303
  173. package/tests/unit/installer.test.ts +0 -105
  174. package/tsconfig.json +0 -20
  175. package/vitest.config.ts +0 -29
package/API.md DELETED
@@ -1,414 +0,0 @@
1
- # CraftDesk CLI API Documentation
2
-
3
- ## Overview
4
-
5
- This document describes the internal API for the CraftDesk CLI, useful for contributors and developers extending the functionality.
6
-
7
- ## Core Services
8
-
9
- ### ConfigManager
10
-
11
- Manages configuration and registry resolution.
12
-
13
- ```typescript
14
- import { configManager } from './services/config-manager';
15
- ```
16
-
17
- #### Methods
18
-
19
- ##### `getRegistryForPackage(packageName: string): Promise<string>`
20
-
21
- Returns the appropriate registry URL for a given package.
22
-
23
- **Parameters:**
24
- - `packageName` - Package name (may be scoped like `@company/package`)
25
-
26
- **Returns:** Registry URL
27
-
28
- **Example:**
29
- ```typescript
30
- const registry = await configManager.getRegistryForPackage('@company/auth');
31
- // Returns: 'https://company.internal' (if configured)
32
- ```
33
-
34
- ##### `getAuthToken(registryName: string): Promise<string | null>`
35
-
36
- Gets authentication token from environment variables.
37
-
38
- **Parameters:**
39
- - `registryName` - Registry name from craftdesk.json
40
-
41
- **Returns:** Auth token or null
42
-
43
- **Environment Variable Format:** `CRAFTDESK_AUTH_{REGISTRY_NAME_UPPERCASE}`
44
-
45
- **Example:**
46
- ```typescript
47
- // Looks for CRAFTDESK_AUTH_COMPANY_PRIVATE
48
- const token = await configManager.getAuthToken('company-private');
49
- ```
50
-
51
- ##### `getInstallPath(): string`
52
-
53
- Returns the installation directory path.
54
-
55
- **Returns:** `.claude` (relative path)
56
-
57
- ##### `getCraftDeskJson(): Promise<CraftDeskJson | null>`
58
-
59
- Reads and caches the craftdesk.json file.
60
-
61
- **Returns:** Parsed craftdesk.json or null if not found
62
-
63
- ---
64
-
65
- ### GitResolver
66
-
67
- Resolves git dependencies and extracts metadata.
68
-
69
- ```typescript
70
- import { GitResolver } from './services/git-resolver';
71
-
72
- const resolver = new GitResolver();
73
- ```
74
-
75
- #### Methods
76
-
77
- ##### `resolveGitDependency(gitInfo: GitDependencyInfo): Promise<GitDependencyInfo>`
78
-
79
- Resolves a git dependency by cloning and reading metadata.
80
-
81
- **Parameters:**
82
- ```typescript
83
- interface GitDependencyInfo {
84
- url: string;
85
- branch?: string;
86
- tag?: string;
87
- commit?: string;
88
- path?: string;
89
- craftDeskJson?: CraftDeskJson;
90
- resolvedCommit?: string;
91
- }
92
- ```
93
-
94
- **Returns:** Enhanced GitDependencyInfo with craftdesk.json and resolved commit
95
-
96
- **Example:**
97
- ```typescript
98
- const info = await resolver.resolveGitDependency({
99
- url: 'https://github.com/company/auth.git',
100
- branch: 'main',
101
- path: 'packages/auth'
102
- });
103
-
104
- console.log(info.craftDeskJson.name); // 'auth-skill'
105
- console.log(info.resolvedCommit); // Full commit hash
106
- ```
107
-
108
- ##### `resolveAllDependencies(dependencies: Record<string, string | DependencyConfig>): Promise<{resolved, lockfile}>`
109
-
110
- Resolves all dependencies including transitive dependencies.
111
-
112
- **Parameters:**
113
- - `dependencies` - Map of dependency names to version strings or config objects
114
-
115
- **Returns:**
116
- ```typescript
117
- {
118
- resolved: Record<string, any>; // All resolved dependencies
119
- lockfile: { // Generated lockfile structure
120
- version: string;
121
- lockfileVersion: number;
122
- crafts: Record<string, any>;
123
- }
124
- }
125
- ```
126
-
127
- **Example:**
128
- ```typescript
129
- const result = await resolver.resolveAllDependencies({
130
- 'ruby-on-rails': '^7.0.0',
131
- 'custom-auth': {
132
- git: 'https://github.com/company/auth.git',
133
- branch: 'main'
134
- }
135
- });
136
- ```
137
-
138
- ---
139
-
140
- ### Installer
141
-
142
- Handles installation of crafts from various sources.
143
-
144
- ```typescript
145
- import { Installer } from './services/installer';
146
-
147
- const installer = new Installer();
148
- ```
149
-
150
- #### Methods
151
-
152
- ##### `installFromLockfile(lockfile: CraftDeskLock): Promise<void>`
153
-
154
- Installs all crafts defined in a lockfile.
155
-
156
- **Parameters:**
157
- ```typescript
158
- interface CraftDeskLock {
159
- version: string;
160
- lockfileVersion: number;
161
- crafts: Record<string, LockEntry>;
162
- }
163
- ```
164
-
165
- **Throws:** Error if any craft fails to install
166
-
167
- **Example:**
168
- ```typescript
169
- const lockfile = await readLockfile();
170
- await installer.installFromLockfile(lockfile);
171
- ```
172
-
173
- ##### `installCraft(name: string, entry: LockEntry): Promise<void>`
174
-
175
- Installs a single craft.
176
-
177
- **Parameters:**
178
- - `name` - Craft name
179
- - `entry` - Lockfile entry with installation details
180
-
181
- **Example:**
182
- ```typescript
183
- await installer.installCraft('ruby-on-rails', {
184
- version: '7.1.0',
185
- resolved: 'https://craftdesk.ai/download/...',
186
- type: 'skill',
187
- dependencies: {}
188
- });
189
- ```
190
-
191
- ---
192
-
193
- ### RegistryClient
194
-
195
- Communicates with CraftDesk registries.
196
-
197
- ```typescript
198
- import { registryClient } from './services/registry-client';
199
- ```
200
-
201
- #### Methods
202
-
203
- ##### `getCraftInfo(name: string, version?: string, registry?: string): Promise<CraftInfo | null>`
204
-
205
- Fetches craft information from registry.
206
-
207
- **Parameters:**
208
- - `name` - Craft name
209
- - `version` - Optional version constraint
210
- - `registry` - Optional registry URL override
211
-
212
- **Returns:** Craft metadata or null if not found
213
-
214
- **Example:**
215
- ```typescript
216
- const info = await registryClient.getCraftInfo('ruby-on-rails', '^7.0.0');
217
- console.log(info.version); // '7.1.0'
218
- ```
219
-
220
- ---
221
-
222
- ## Type Definitions
223
-
224
- ### CraftDeskJson
225
-
226
- ```typescript
227
- interface CraftDeskJson {
228
- name: string;
229
- version: string;
230
- type: 'skill' | 'agent' | 'command' | 'hook';
231
- description?: string;
232
- author?: string;
233
- dependencies?: Record<string, string | DependencyConfig>;
234
- devDependencies?: Record<string, string | DependencyConfig>;
235
- registries?: Record<string, RegistryConfig>;
236
- }
237
- ```
238
-
239
- ### DependencyConfig
240
-
241
- ```typescript
242
- interface DependencyConfig {
243
- version?: string; // For registry deps
244
- registry?: string; // Custom registry URL
245
- git?: string; // Git repository URL
246
- branch?: string; // Git branch
247
- tag?: string; // Git tag
248
- commit?: string; // Git commit hash
249
- path?: string; // Subdirectory path for monorepos
250
- }
251
- ```
252
-
253
- ### RegistryConfig
254
-
255
- ```typescript
256
- interface RegistryConfig {
257
- url: string;
258
- scope?: string; // Scope for scoped packages (@company)
259
- auth?: string; // DEPRECATED: Use environment variables
260
- }
261
- ```
262
-
263
- ### LockEntry
264
-
265
- ```typescript
266
- interface LockEntry {
267
- version: string;
268
- resolved: string; // Download URL or git URL
269
- integrity: string; // SHA-256 hash or commit hash
270
- type: 'skill' | 'agent' | 'command' | 'hook';
271
- author?: string;
272
- dependencies: Record<string, string>;
273
-
274
- // Git-specific fields
275
- git?: string;
276
- branch?: string;
277
- tag?: string;
278
- commit?: string;
279
- path?: string;
280
-
281
- // Registry-specific fields
282
- registry?: string;
283
- }
284
- ```
285
-
286
- ---
287
-
288
- ## Utility Functions
289
-
290
- ### File System Utilities
291
-
292
- ```typescript
293
- import { readCraftDeskJson, writeCraftDeskJson, ensureDir } from './utils/file-system';
294
- ```
295
-
296
- #### `readCraftDeskJson(): Promise<CraftDeskJson | null>`
297
-
298
- Reads craftdesk.json from current directory.
299
-
300
- #### `writeCraftDeskJson(data: CraftDeskJson): Promise<void>`
301
-
302
- Writes craftdesk.json to current directory.
303
-
304
- #### `ensureDir(dirPath: string): Promise<void>`
305
-
306
- Creates directory if it doesn't exist.
307
-
308
- ### Logger
309
-
310
- ```typescript
311
- import { logger } from './utils/logger';
312
- ```
313
-
314
- #### Methods
315
-
316
- - `info(message: string)` - Info message
317
- - `success(message: string)` - Success message (green)
318
- - `error(message: string)` - Error message (red)
319
- - `warn(message: string)` - Warning message (yellow)
320
- - `debug(message: string)` - Debug message (if verbose)
321
- - `startSpinner(message: string)` - Start loading spinner
322
- - `updateSpinner(message: string)` - Update spinner message
323
- - `succeedSpinner(message?: string)` - Stop spinner with success
324
- - `failSpinner(message?: string)` - Stop spinner with failure
325
-
326
- ---
327
-
328
- ## Extension Points
329
-
330
- ### Adding New Craft Types
331
-
332
- 1. Update type definition in `src/types/craftdesk-json.ts`:
333
-
334
- ```typescript
335
- export type CraftType = 'skill' | 'agent' | 'command' | 'hook' | 'your-new-type';
336
- ```
337
-
338
- 2. Update installer's `getTypeDirectory()` method:
339
-
340
- ```typescript
341
- private getTypeDirectory(type: CraftType): string {
342
- switch (type) {
343
- case 'your-new-type':
344
- return 'your-types';
345
- // ...
346
- }
347
- }
348
- ```
349
-
350
- 3. Update git-resolver's `inferCraftType()` method:
351
-
352
- ```typescript
353
- if (files.includes('YOUR_TYPE.md')) return 'your-new-type';
354
- ```
355
-
356
- ### Adding New Commands
357
-
358
- 1. Create command file in `src/commands/`:
359
-
360
- ```typescript
361
- import { Command } from 'commander';
362
-
363
- export function createYourCommand(): Command {
364
- return new Command('your-command')
365
- .description('Your command description')
366
- .action(async () => {
367
- // Implementation
368
- });
369
- }
370
- ```
371
-
372
- 2. Register in `src/index.ts`:
373
-
374
- ```typescript
375
- import { createYourCommand } from './commands/your-command';
376
-
377
- program.addCommand(createYourCommand());
378
- ```
379
-
380
- ### Adding New Dependency Sources
381
-
382
- 1. Update `DependencyConfig` interface
383
- 2. Modify `GitResolver.resolveAllDependencies()` to handle new source type
384
- 3. Update `Installer.installCraft()` to support new installation method
385
-
386
- ---
387
-
388
- ## Error Handling
389
-
390
- All service methods may throw errors. Wrap calls in try-catch:
391
-
392
- ```typescript
393
- try {
394
- await installer.installCraft(name, entry);
395
- } catch (error) {
396
- logger.error(`Installation failed: ${error.message}`);
397
- process.exit(1);
398
- }
399
- ```
400
-
401
- ## Testing
402
-
403
- See [TESTING.md](./TESTING.md) for testing guidelines and examples.
404
-
405
- ## Contributing
406
-
407
- When adding new functionality:
408
-
409
- 1. Add JSDoc comments to all public functions
410
- 2. Include usage examples in documentation
411
- 3. Add unit tests for new functions
412
- 4. Update integration tests if CLI behavior changes
413
- 5. Update type definitions
414
- 6. Add inline comments for complex algorithms
package/TESTING.md DELETED
@@ -1,263 +0,0 @@
1
- # Testing Guide
2
-
3
- ## Overview
4
-
5
- The CraftDesk CLI uses **Vitest** as its testing framework, providing fast and modern testing capabilities with TypeScript support.
6
-
7
- ## Test Structure
8
-
9
- ```
10
- tests/
11
- ├── unit/ # Unit tests for individual modules
12
- │ ├── config-manager.test.ts
13
- │ ├── git-resolver.test.ts
14
- │ └── installer.test.ts
15
- ├── integration/ # Integration tests for CLI commands
16
- │ ├── init-command.test.ts
17
- │ └── list-command.test.ts
18
- ├── fixtures/ # Test fixtures and mock data
19
- │ ├── craftdesk.json
20
- │ └── craftdesk-git.json
21
- └── helpers/ # Test utilities
22
- └── test-utils.ts
23
- ```
24
-
25
- ## Running Tests
26
-
27
- ### Run all tests
28
- ```bash
29
- npm test
30
- ```
31
-
32
- ### Run tests in watch mode
33
- ```bash
34
- npm run test:watch
35
- ```
36
-
37
- ### Run tests with coverage
38
- ```bash
39
- npm run test:coverage
40
- ```
41
-
42
- ### Run tests with UI
43
- ```bash
44
- npm run test:ui
45
- ```
46
-
47
- ## Test Coverage
48
-
49
- Coverage reports are generated using Vitest's built-in coverage tool (v8 provider).
50
-
51
- ### Viewing Coverage
52
-
53
- After running `npm run test:coverage`, view the report:
54
-
55
- ```bash
56
- # Terminal summary is displayed automatically
57
-
58
- # Open HTML report in browser
59
- open coverage/index.html
60
- ```
61
-
62
- ### Coverage Thresholds
63
-
64
- Current coverage configuration in `vitest.config.ts`:
65
- - Excludes: `node_modules/`, `dist/`, `bin/`, test files
66
-
67
- ## Writing Tests
68
-
69
- ### Unit Tests
70
-
71
- Unit tests focus on testing individual functions and classes in isolation.
72
-
73
- **Example: Testing ConfigManager**
74
-
75
- ```typescript
76
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
77
- import { ConfigManager } from '../../src/services/config-manager';
78
- import { createTempDir, cleanupTempDir } from '../helpers/test-utils';
79
-
80
- describe('ConfigManager', () => {
81
- let configManager: ConfigManager;
82
- let tempDir: string;
83
-
84
- beforeEach(async () => {
85
- configManager = new ConfigManager();
86
- tempDir = await createTempDir('config-test-');
87
- process.chdir(tempDir);
88
- });
89
-
90
- afterEach(async () => {
91
- await cleanupTempDir(tempDir);
92
- });
93
-
94
- it('should return default registry when no craftdesk.json exists', async () => {
95
- const registry = await configManager.getRegistryForPackage('test-package');
96
- expect(registry).toBe('https://craftdesk.ai');
97
- });
98
- });
99
- ```
100
-
101
- ### Integration Tests
102
-
103
- Integration tests verify that CLI commands work correctly end-to-end.
104
-
105
- **Example: Testing CLI Commands**
106
-
107
- ```typescript
108
- import { execSync } from 'child_process';
109
- import path from 'path';
110
-
111
- describe('craftdesk init command', () => {
112
- const cliPath = path.join(__dirname, '../../dist/index.js');
113
-
114
- it('should create a new craftdesk.json file', () => {
115
- execSync(`node ${cliPath} init --name test --version 1.0.0 --type skill`);
116
-
117
- const exists = await fs.pathExists('craftdesk.json');
118
- expect(exists).toBe(true);
119
- });
120
- });
121
- ```
122
-
123
- ### Test Utilities
124
-
125
- The `tests/helpers/test-utils.ts` file provides helper functions:
126
-
127
- - `createTempDir(prefix)` - Creates a temporary test directory
128
- - `cleanupTempDir(dirPath)` - Removes a temporary directory
129
- - `copyFixture(name, targetDir)` - Copies a fixture file
130
- - `readJsonFile(path)` - Reads and parses JSON file
131
- - `writeJsonFile(path, data)` - Writes JSON to file
132
- - `createMockCraftInfo(name, version)` - Creates mock craft metadata
133
-
134
- ### Mocking
135
-
136
- Use Vitest's built-in mocking for external dependencies:
137
-
138
- ```typescript
139
- import { vi } from 'vitest';
140
- import { execSync } from 'child_process';
141
-
142
- vi.mock('child_process', () => ({
143
- execSync: vi.fn()
144
- }));
145
-
146
- // In your test
147
- const mockExecSync = vi.mocked(execSync);
148
- mockExecSync.mockReturnValue(Buffer.from('output'));
149
- ```
150
-
151
- ## CI/CD Integration
152
-
153
- ### GitHub Actions
154
-
155
- The `.github/workflows/ci.yml` file runs tests automatically on:
156
- - Push to main/master/develop branches
157
- - Pull requests to main/master/develop branches
158
-
159
- The workflow:
160
- 1. Tests on Node.js 16.x, 18.x, and 20.x
161
- 2. Generates coverage report (Node 20.x only)
162
- 3. Uploads coverage to Codecov
163
- 4. Verifies TypeScript compilation
164
- 5. Builds the project
165
-
166
- ### Local CI Simulation
167
-
168
- Run the same checks locally before pushing:
169
-
170
- ```bash
171
- # Run tests
172
- npm test
173
-
174
- # Generate coverage
175
- npm run test:coverage
176
-
177
- # Type check
178
- npx tsc --noEmit
179
-
180
- # Build
181
- npm run build
182
- ```
183
-
184
- ## Test Best Practices
185
-
186
- ### 1. Isolation
187
- - Each test should be independent
188
- - Use `beforeEach` and `afterEach` for setup/teardown
189
- - Clean up temporary files and directories
190
-
191
- ### 2. Descriptive Names
192
- ```typescript
193
- // Good
194
- it('should return scoped registry for scoped package')
195
-
196
- // Bad
197
- it('test1')
198
- ```
199
-
200
- ### 3. Arrange-Act-Assert Pattern
201
- ```typescript
202
- it('should parse git URL with branch', () => {
203
- // Arrange
204
- const url = 'https://github.com/user/repo.git#main';
205
-
206
- // Act
207
- const result = parseGitUrl(url);
208
-
209
- // Assert
210
- expect(result.branch).toBe('main');
211
- expect(result.url).toBe('https://github.com/user/repo.git');
212
- });
213
- ```
214
-
215
- ### 4. Test Edge Cases
216
- - Empty inputs
217
- - Invalid data
218
- - Error conditions
219
- - Boundary values
220
-
221
- ### 5. Mock External Dependencies
222
- - File system operations (when appropriate)
223
- - Network requests
224
- - Child processes
225
- - Environment variables
226
-
227
- ## Debugging Tests
228
-
229
- ### Run specific test file
230
- ```bash
231
- npm test tests/unit/config-manager.test.ts
232
- ```
233
-
234
- ### Run tests matching pattern
235
- ```bash
236
- npm test -- --grep "git dependency"
237
- ```
238
-
239
- ### Debug with breakpoints
240
- ```bash
241
- node --inspect-brk ./node_modules/.bin/vitest run
242
- ```
243
-
244
- Then attach your debugger (VS Code, Chrome DevTools, etc.)
245
-
246
- ## Continuous Improvement
247
-
248
- ### Coverage Goals
249
- - Maintain >80% code coverage
250
- - Focus on critical paths first
251
- - Add tests when fixing bugs
252
-
253
- ### Test Maintenance
254
- - Update tests when changing functionality
255
- - Remove obsolete tests
256
- - Keep test data fixtures up to date
257
- - Review test failures in CI promptly
258
-
259
- ## Resources
260
-
261
- - [Vitest Documentation](https://vitest.dev/)
262
- - [Testing Library Best Practices](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)
263
- - [Effective Testing Strategies](https://martinfowler.com/articles/practical-test-pyramid.html)
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createConfigCommand(): Command;
3
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,mBAAmB,IAAI,OAAO,CAiD7C"}