craftdesk 0.1.0 → 0.2.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 (103) hide show
  1. package/.claude/settings.local.json +17 -0
  2. package/.github/workflows/ci.yml +94 -0
  3. package/API.md +414 -0
  4. package/README.md +799 -0
  5. package/TESTING.md +263 -0
  6. package/bin/craftdesk.js +4 -0
  7. package/dist/commands/add.d.ts +3 -0
  8. package/dist/commands/add.d.ts.map +1 -0
  9. package/dist/commands/add.js +284 -0
  10. package/dist/commands/add.js.map +1 -0
  11. package/dist/commands/config.d.ts +3 -0
  12. package/dist/commands/config.d.ts.map +1 -0
  13. package/dist/commands/config.js +56 -0
  14. package/dist/commands/config.js.map +1 -0
  15. package/dist/commands/init.d.ts +3 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +57 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/install.d.ts +3 -0
  20. package/dist/commands/install.d.ts.map +1 -0
  21. package/dist/commands/install.js +109 -0
  22. package/dist/commands/install.js.map +1 -0
  23. package/dist/commands/list.d.ts +3 -0
  24. package/dist/commands/list.d.ts.map +1 -0
  25. package/dist/commands/list.js +117 -0
  26. package/dist/commands/list.js.map +1 -0
  27. package/dist/commands/remove.d.ts +3 -0
  28. package/dist/commands/remove.d.ts.map +1 -0
  29. package/dist/commands/remove.js +74 -0
  30. package/dist/commands/remove.js.map +1 -0
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +51 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/services/config-manager.d.ts +88 -0
  36. package/dist/services/config-manager.d.ts.map +1 -0
  37. package/dist/services/config-manager.js +143 -0
  38. package/dist/services/config-manager.js.map +1 -0
  39. package/dist/services/git-resolver.d.ts +139 -0
  40. package/dist/services/git-resolver.d.ts.map +1 -0
  41. package/dist/services/git-resolver.js +334 -0
  42. package/dist/services/git-resolver.js.map +1 -0
  43. package/dist/services/installer.d.ts +98 -0
  44. package/dist/services/installer.d.ts.map +1 -0
  45. package/dist/services/installer.js +274 -0
  46. package/dist/services/installer.js.map +1 -0
  47. package/dist/services/registry-client.d.ts +27 -0
  48. package/dist/services/registry-client.d.ts.map +1 -0
  49. package/dist/services/registry-client.js +134 -0
  50. package/dist/services/registry-client.js.map +1 -0
  51. package/dist/types/config.d.ts +17 -0
  52. package/dist/types/config.d.ts.map +1 -0
  53. package/dist/types/config.js +3 -0
  54. package/dist/types/config.js.map +1 -0
  55. package/dist/types/craftdesk-json.d.ts +42 -0
  56. package/dist/types/craftdesk-json.d.ts.map +1 -0
  57. package/dist/types/craftdesk-json.js +3 -0
  58. package/dist/types/craftdesk-json.js.map +1 -0
  59. package/dist/types/craftdesk-lock.d.ts +34 -0
  60. package/dist/types/craftdesk-lock.d.ts.map +1 -0
  61. package/dist/types/craftdesk-lock.js +3 -0
  62. package/dist/types/craftdesk-lock.js.map +1 -0
  63. package/dist/utils/file-system.d.ts +10 -0
  64. package/dist/utils/file-system.d.ts.map +1 -0
  65. package/dist/utils/file-system.js +60 -0
  66. package/dist/utils/file-system.js.map +1 -0
  67. package/dist/utils/logger.d.ts +18 -0
  68. package/dist/utils/logger.d.ts.map +1 -0
  69. package/dist/utils/logger.js +72 -0
  70. package/dist/utils/logger.js.map +1 -0
  71. package/docs/DEPENDENCY_RESOLUTION.md +237 -0
  72. package/examples/craftdesk-all-sources.json +79 -0
  73. package/examples/craftdesk-git-monorepo.json +41 -0
  74. package/examples/craftdesk-multi-registry.json +40 -0
  75. package/examples/craftdesk-with-registries.json +49 -0
  76. package/examples/simple-craftdesk.json +10 -0
  77. package/package.json +32 -25
  78. package/src/commands/add.ts +314 -0
  79. package/src/commands/init.ts +55 -0
  80. package/src/commands/install.ts +126 -0
  81. package/src/commands/list.ts +126 -0
  82. package/src/commands/remove.ts +82 -0
  83. package/src/index.ts +56 -0
  84. package/src/services/config-manager.ts +150 -0
  85. package/src/services/git-resolver.ts +370 -0
  86. package/src/services/installer.ts +314 -0
  87. package/src/services/registry-client.ts +163 -0
  88. package/src/types/craftdesk-json.ts +53 -0
  89. package/src/types/craftdesk-lock.ts +38 -0
  90. package/src/utils/file-system.ts +55 -0
  91. package/src/utils/logger.ts +82 -0
  92. package/tests/fixtures/craftdesk-git.json +17 -0
  93. package/tests/fixtures/craftdesk.json +15 -0
  94. package/tests/helpers/test-utils.ts +60 -0
  95. package/tests/integration/init-command.test.ts +70 -0
  96. package/tests/integration/list-command.test.ts +77 -0
  97. package/tests/unit/config-manager.test.ts +228 -0
  98. package/tests/unit/git-resolver.test.ts +303 -0
  99. package/tests/unit/installer.test.ts +105 -0
  100. package/tsconfig.json +20 -0
  101. package/vitest.config.ts +29 -0
  102. package/LICENSE +0 -21
  103. package/index.js +0 -4
@@ -0,0 +1,17 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npm run build:*)",
5
+ "Bash(cat:*)",
6
+ "Bash(git init:*)",
7
+ "Bash(git remote add:*)",
8
+ "Bash(git add:*)",
9
+ "Bash(git commit:*)",
10
+ "Bash(git push:*)",
11
+ "Bash(npm test)",
12
+ "Bash(node /home/mencio/Software/CraftDesk/CraftDesk/cli/dist/index.js:*)"
13
+ ],
14
+ "deny": [],
15
+ "ask": []
16
+ }
17
+ }
@@ -0,0 +1,94 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master, develop]
6
+ pull_request:
7
+ branches: [main, master, develop]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test on Node.js ${{ matrix.node-version }}
12
+ runs-on: ubuntu-latest
13
+
14
+ strategy:
15
+ matrix:
16
+ node-version: [18.x, 20.x, 22.x]
17
+
18
+ steps:
19
+ - name: Checkout code
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Setup Node.js ${{ matrix.node-version }}
23
+ uses: actions/setup-node@v4
24
+ with:
25
+ node-version: ${{ matrix.node-version }}
26
+ cache: 'npm'
27
+
28
+ - name: Install dependencies
29
+ run: npm ci
30
+
31
+ - name: Run linter (if configured)
32
+ run: npm run lint --if-present
33
+
34
+ - name: Run tests
35
+ run: npm test
36
+
37
+ - name: Generate coverage report
38
+ run: npm run test:coverage
39
+ if: matrix.node-version == '20.x'
40
+
41
+ - name: Upload coverage to Codecov
42
+ uses: codecov/codecov-action@v3
43
+ if: matrix.node-version == '20.x'
44
+ with:
45
+ files: ./coverage/coverage-final.json
46
+ flags: unittests
47
+ name: codecov-umbrella
48
+ fail_ci_if_error: false
49
+
50
+ build:
51
+ name: Build
52
+ runs-on: ubuntu-latest
53
+ needs: test
54
+
55
+ steps:
56
+ - name: Checkout code
57
+ uses: actions/checkout@v4
58
+
59
+ - name: Setup Node.js
60
+ uses: actions/setup-node@v4
61
+ with:
62
+ node-version: '20.x'
63
+ cache: 'npm'
64
+
65
+ - name: Install dependencies
66
+ run: npm ci
67
+
68
+ - name: Build TypeScript
69
+ run: npm run build
70
+
71
+ - name: Verify build artifacts
72
+ run: |
73
+ test -f dist/index.js || exit 1
74
+ echo "Build successful!"
75
+
76
+ type-check:
77
+ name: Type Check
78
+ runs-on: ubuntu-latest
79
+
80
+ steps:
81
+ - name: Checkout code
82
+ uses: actions/checkout@v4
83
+
84
+ - name: Setup Node.js
85
+ uses: actions/setup-node@v4
86
+ with:
87
+ node-version: '20.x'
88
+ cache: 'npm'
89
+
90
+ - name: Install dependencies
91
+ run: npm ci
92
+
93
+ - name: Run TypeScript compiler check
94
+ run: npx tsc --noEmit
package/API.md ADDED
@@ -0,0 +1,414 @@
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