@avantmedia/af 0.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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +539 -0
  3. package/af +2 -0
  4. package/bun-upgrade.ts +130 -0
  5. package/commands/bun.ts +55 -0
  6. package/commands/changes.ts +35 -0
  7. package/commands/e2e.ts +12 -0
  8. package/commands/help.ts +236 -0
  9. package/commands/install-extension.ts +133 -0
  10. package/commands/jira.ts +577 -0
  11. package/commands/licenses.ts +32 -0
  12. package/commands/npm.ts +55 -0
  13. package/commands/scaffold.ts +105 -0
  14. package/commands/setup.tsx +156 -0
  15. package/commands/spec.ts +405 -0
  16. package/commands/stop-hook.ts +90 -0
  17. package/commands/todo.ts +208 -0
  18. package/commands/versions.ts +150 -0
  19. package/commands/watch.ts +344 -0
  20. package/commands/worktree.ts +424 -0
  21. package/components/change-select.tsx +71 -0
  22. package/components/confirm.tsx +41 -0
  23. package/components/file-conflict.tsx +52 -0
  24. package/components/input.tsx +53 -0
  25. package/components/layout.tsx +70 -0
  26. package/components/messages.tsx +48 -0
  27. package/components/progress.tsx +71 -0
  28. package/components/select.tsx +90 -0
  29. package/components/status-display.tsx +74 -0
  30. package/components/table.tsx +79 -0
  31. package/generated/setup-manifest.ts +67 -0
  32. package/git-worktree.ts +184 -0
  33. package/main.ts +12 -0
  34. package/npm-upgrade.ts +117 -0
  35. package/package.json +83 -0
  36. package/resources/copy-prompt-reporter.ts +443 -0
  37. package/router.ts +220 -0
  38. package/setup/.claude/commands/commit-work.md +47 -0
  39. package/setup/.claude/commands/complete-work.md +34 -0
  40. package/setup/.claude/commands/e2e.md +29 -0
  41. package/setup/.claude/commands/start-work.md +51 -0
  42. package/setup/.claude/skills/pm/SKILL.md +294 -0
  43. package/setup/.claude/skills/pm/templates/api-endpoint.md +69 -0
  44. package/setup/.claude/skills/pm/templates/bug-fix.md +77 -0
  45. package/setup/.claude/skills/pm/templates/feature.md +87 -0
  46. package/setup/.claude/skills/pm/templates/ui-component.md +78 -0
  47. package/utils/change-select-render.tsx +44 -0
  48. package/utils/claude.ts +9 -0
  49. package/utils/config.ts +58 -0
  50. package/utils/env.ts +53 -0
  51. package/utils/git.ts +120 -0
  52. package/utils/ink-render.tsx +50 -0
  53. package/utils/openspec.ts +54 -0
  54. package/utils/output.ts +104 -0
  55. package/utils/proposal.ts +160 -0
  56. package/utils/resources.ts +64 -0
  57. package/utils/setup-files.ts +230 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Avant Media LTD
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,539 @@
1
+ # Artifex
2
+
3
+ A lightweight CLI development utility that helps you automate common development tasks.
4
+
5
+ > **Note:** Artifex is in early-stage development. Features and APIs may change as the project evolves.
6
+
7
+ ## What is Artifex?
8
+
9
+ Artifex is a command-line tool designed to streamline your development workflow by automating repetitive tasks. Currently, it helps you keep your project dependencies up to date with a single command, and it's built to be fast and easy to use.
10
+
11
+ ### Why Artifex?
12
+
13
+ - **Simple**: One command to upgrade all your npm dependencies
14
+ - **Fast**: Built with performance in mind, runs TypeScript directly without build steps
15
+ - **Developer-friendly**: Clear output and sensible defaults
16
+ - **Lightweight**: Minimal dependencies, maximum efficiency
17
+
18
+ ## Installation
19
+
20
+ ### Prerequisites
21
+
22
+ - [Bun](https://bun.sh) runtime
23
+
24
+ ### Install from NPM
25
+
26
+ ```bash
27
+ npm install -g @avantmedia/af
28
+ ```
29
+
30
+ After installation, the `af` command will be available globally.
31
+
32
+ ### Install from Source
33
+
34
+ ```bash
35
+ git clone https://github.com/avantmedialtd/artifex.git
36
+ cd artifex
37
+ bun install
38
+ bun link
39
+ ```
40
+
41
+ ### Platform Support
42
+
43
+ af works on:
44
+
45
+ - macOS
46
+ - Linux
47
+ - Windows
48
+
49
+ ## Usage
50
+
51
+ ### Upgrade NPM Dependencies
52
+
53
+ Upgrade all dependencies in your project to their latest versions:
54
+
55
+ ```bash
56
+ af npm upgrade
57
+ ```
58
+
59
+ This command will:
60
+
61
+ 1. Read your `package.json` file
62
+ 2. Check the npm registry for the latest version of each dependency
63
+ 3. Update both `dependencies` and `devDependencies` to the latest versions
64
+ 4. Preserve your existing version range symbols (^, ~, etc.)
65
+ 5. Automatically run `npm install` to apply the changes
66
+
67
+ **Example:**
68
+
69
+ ```bash
70
+ cd my-project
71
+ af npm upgrade
72
+ ```
73
+
74
+ **Output:**
75
+
76
+ ```
77
+ Upgrading dependencies in package.json...
78
+ express: ^4.18.0 → ^4.19.2
79
+ typescript: ^5.0.0 → ^5.4.5
80
+ Running npm install...
81
+ Done! All dependencies upgraded.
82
+ ```
83
+
84
+ ### Upgrade Bun Dependencies
85
+
86
+ Upgrade all dependencies in your project to their latest versions using Bun:
87
+
88
+ ```bash
89
+ af bun upgrade
90
+ ```
91
+
92
+ This command will:
93
+
94
+ 1. Run `bun outdated` to detect outdated packages
95
+ 2. Upgrade each package using `bun add <package>@latest`
96
+ 3. Display a summary of upgraded packages
97
+
98
+ **Example:**
99
+
100
+ ```bash
101
+ cd my-project
102
+ af bun upgrade
103
+ ```
104
+
105
+ **Output:**
106
+
107
+ ```
108
+ Checking for outdated packages...
109
+
110
+ Found 2 package(s) to upgrade:
111
+ • lodash
112
+ • typescript
113
+
114
+ Upgrading lodash...
115
+ Upgrading typescript...
116
+
117
+ Upgrade Summary
118
+ ==================================================
119
+ Successfully upgraded: 2 package(s)
120
+ ✓ lodash
121
+ ✓ typescript
122
+
123
+ All packages upgraded successfully!
124
+ ```
125
+
126
+ ### Propose OpenSpec Changes
127
+
128
+ Create a new OpenSpec change proposal using Claude Code:
129
+
130
+ ```bash
131
+ af spec propose <proposal-text>
132
+ ```
133
+
134
+ This command provides a convenient wrapper for initiating an OpenSpec proposal workflow. It automatically executes `claude --permission-mode acceptEdits "/openspec:proposal <proposal-text>"` for you.
135
+
136
+ **Prerequisites:**
137
+
138
+ - [Claude Code CLI](https://claude.com/claude-code) must be installed and available in your PATH
139
+ - Your project must have OpenSpec configured
140
+
141
+ **Examples:**
142
+
143
+ ```bash
144
+ # Create a proposal with single-word text
145
+ af spec propose "Add user authentication"
146
+
147
+ # Create a proposal with multi-word text (quotes optional)
148
+ af spec propose Add new API endpoints for user management
149
+ ```
150
+
151
+ This will:
152
+
153
+ 1. Check if Claude Code CLI is available
154
+ 2. Invoke the OpenSpec proposal workflow
155
+ 3. Create a new change proposal with AI assistance
156
+ 4. Automatically commit the proposal files with message format: "Propose: <Title>"
157
+
158
+ ### Archive OpenSpec Changes
159
+
160
+ Archive a deployed OpenSpec change using Claude Code:
161
+
162
+ ```bash
163
+ af spec archive <spec-id>
164
+ ```
165
+
166
+ This command provides a convenient wrapper for invoking Claude Code's OpenSpec archive workflow. It automatically executes `claude --permission-mode acceptEdits "/openspec:archive <spec-id>"` for you.
167
+
168
+ **Prerequisites:**
169
+
170
+ - [Claude Code CLI](https://claude.com/claude-code) must be installed and available in your PATH
171
+ - The OpenSpec change must exist in your project's `openspec/changes` directory
172
+
173
+ **Example:**
174
+
175
+ ```bash
176
+ # Archive a completed OpenSpec change
177
+ af spec archive add-user-authentication
178
+ ```
179
+
180
+ This will:
181
+
182
+ 1. Check if Claude Code CLI is available
183
+ 2. Invoke the OpenSpec archive workflow
184
+ 3. Archive the change and update related specifications
185
+
186
+ ### Apply OpenSpec Changes
187
+
188
+ Apply an approved OpenSpec change using Claude Code:
189
+
190
+ ```bash
191
+ af spec apply [change-id]
192
+ ```
193
+
194
+ This command provides a convenient wrapper for invoking Claude Code's OpenSpec apply workflow. It automatically executes `claude --permission-mode acceptEdits "/openspec:apply [change-id]"` for you.
195
+
196
+ **Prerequisites:**
197
+
198
+ - [Claude Code CLI](https://claude.com/claude-code) must be installed and available in your PATH
199
+ - The OpenSpec change must exist in your project's `openspec/changes` directory
200
+
201
+ **Example:**
202
+
203
+ ```bash
204
+ # Apply a specific change
205
+ af spec apply add-user-authentication
206
+
207
+ # Let Claude prompt for which change to apply
208
+ af spec apply
209
+ ```
210
+
211
+ ### View TODO Items
212
+
213
+ Display all TODO items from active OpenSpec changes:
214
+
215
+ ```bash
216
+ af todo
217
+ ```
218
+
219
+ This command scans all active changes in `openspec/changes/` and displays their tasks from `tasks.md` files with progress indicators.
220
+
221
+ **Example:**
222
+
223
+ ```bash
224
+ af todo
225
+ ```
226
+
227
+ **Output:**
228
+
229
+ ```
230
+ 📋 TODO Items
231
+
232
+ ┌─ add-user-authentication (2/5 tasks completed)
233
+
234
+ │ Implementation
235
+ │ ☑ 1.1 Create database schema
236
+ │ ☑ 1.2 Implement API endpoint
237
+ │ ☐ 1.3 Add frontend component
238
+ │ ☐ 1.4 Write tests
239
+ │ ☐ 1.5 Update documentation
240
+
241
+ └────────────────────────────────────────
242
+ ```
243
+
244
+ ### Watch TODO Items
245
+
246
+ Continuously monitor and display TODO items with real-time updates:
247
+
248
+ ```bash
249
+ af watch
250
+ ```
251
+
252
+ This command starts watch mode, which automatically refreshes the TODO display whenever task files are modified. Perfect for tracking progress during active development.
253
+
254
+ **Example:**
255
+
256
+ ```bash
257
+ af watch
258
+ ```
259
+
260
+ **Features:**
261
+
262
+ - Real-time display updates when `tasks.md` files change
263
+ - Debounced refreshes (100ms) to batch rapid changes
264
+ - Clear screen with timestamp on each update
265
+ - Press Ctrl+C to exit gracefully
266
+
267
+ **Use case:** Keep `af watch` running in a terminal window while working through implementation tasks to see your progress update automatically.
268
+
269
+ ## VSCode Extension
270
+
271
+ For VSCode users, Artifex includes a dedicated extension that displays OpenSpec tasks directly in a panel (similar to the Problems panel).
272
+
273
+ ### Features
274
+
275
+ - **Native Panel Integration**: View all active OpenSpec changes and tasks in a dedicated panel
276
+ - **Progress Tracking**: See completion counts for each change at a glance
277
+ - **Badge Notifications**: Panel badge shows completion percentage across all active changes (e.g., "75%" with tooltip showing "3 active changes, 75% complete (15/20 tasks)")
278
+ - **Real-time Updates**: Automatically refreshes when `tasks.md` files change
279
+ - **Hierarchical Display**: Tasks organized by change → section → individual task
280
+
281
+ ### Installation
282
+
283
+ 1. Navigate to the extension directory:
284
+
285
+ ```bash
286
+ cd vscode-extension
287
+ ```
288
+
289
+ 2. Install dependencies and compile:
290
+
291
+ ```bash
292
+ npm install
293
+ npm run compile
294
+ ```
295
+
296
+ 3. Install the extension:
297
+ - Press `F5` in VSCode to open an Extension Development Host, or
298
+ - Package and install: `vsce package` then install the `.vsix` file
299
+
300
+ ### Usage
301
+
302
+ Once installed, the "OpenSpec Tasks" panel appears automatically when you open a workspace containing an `openspec/changes/` directory. The panel shows all active changes with their task completion status.
303
+
304
+ For detailed documentation, see [vscode-extension/README.md](vscode-extension/README.md).
305
+
306
+ ## Configuration
307
+
308
+ ### ARTIFEX_AGENT Environment Variable
309
+
310
+ By default, Artifex uses the `claude` command when invoking AI agents for OpenSpec operations. You can customize this behavior by setting the `ARTIFEX_AGENT` environment variable.
311
+
312
+ **Use cases:**
313
+
314
+ - Testing with alternative agent implementations
315
+ - Using custom CLI wrappers
316
+ - Running with agent commands installed at non-standard paths
317
+
318
+ **Examples:**
319
+
320
+ ```bash
321
+ # Use default claude command
322
+ af spec propose "add feature X"
323
+
324
+ # Use a custom agent command
325
+ ARTIFEX_AGENT=my-agent af spec propose "add feature X"
326
+
327
+ # Use an absolute path to the agent
328
+ ARTIFEX_AGENT=/usr/local/bin/custom-claude af spec apply
329
+
330
+ # Set for your entire session
331
+ export ARTIFEX_AGENT=my-custom-agent
332
+ af spec propose "add feature Y"
333
+ ```
334
+
335
+ When `ARTIFEX_AGENT` is set, Artifex will use that command name for:
336
+
337
+ - Checking agent availability
338
+ - Executing `spec propose` commands
339
+ - Executing `spec archive` commands
340
+ - Executing `spec apply` commands
341
+
342
+ **Note:** The custom agent command must support the same CLI interface as Claude Code (e.g., `--permission-mode acceptEdits` and slash command syntax).
343
+
344
+ ### Version Worktree Management
345
+
346
+ af provides commands to manage git worktrees for version branches (branches matching the pattern `v1`, `v2`, `v10`, etc.).
347
+
348
+ #### Reset Version Worktrees
349
+
350
+ Reset all version worktrees to the current branch HEAD:
351
+
352
+ ```bash
353
+ af versions reset
354
+ ```
355
+
356
+ This command will:
357
+
358
+ 1. Find all git worktrees with branch names matching `/v\d+/` (e.g., `v1`, `v2`, `v10`)
359
+ 2. Check each worktree for uncommitted changes
360
+ 3. If all worktrees are clean, reset each to the current branch's HEAD commit
361
+ 4. Display a success summary showing all reset worktrees
362
+
363
+ **Example:**
364
+
365
+ ```bash
366
+ # On the master branch at commit abc123
367
+ af versions reset
368
+ # Output: Successfully reset 3 worktree(s): v1, v2, v3
369
+ ```
370
+
371
+ **Requirements:**
372
+
373
+ - Must be run from within a git repository
374
+ - All matching worktrees must have no uncommitted changes
375
+
376
+ #### Push Version Worktrees
377
+
378
+ Force-push all version worktrees to their remote repositories:
379
+
380
+ ```bash
381
+ af versions push
382
+ ```
383
+
384
+ This command will:
385
+
386
+ 1. Find all git worktrees with branch names matching `/v\d+/` (e.g., `v1`, `v2`, `v10`)
387
+ 2. Force-push each worktree to its remote repository
388
+ 3. Stop on first failure with clear error reporting
389
+ 4. Display a success summary showing all pushed worktrees
390
+
391
+ **Example:**
392
+
393
+ ```bash
394
+ # After resetting version worktrees
395
+ af versions push
396
+ # Output: Successfully pushed 3 worktree(s): v1, v2, v3
397
+ ```
398
+
399
+ **Requirements:**
400
+
401
+ - Must be run from within a git repository
402
+ - Each worktree must have an upstream branch configured
403
+
404
+ **Note:** This command uses `--force` push. It's designed to work in conjunction with `versions reset` to synchronize version branches after updates.
405
+
406
+ ## Development
407
+
408
+ Want to contribute or work on Artifex? Here's how to get started.
409
+
410
+ ### Setup
411
+
412
+ ```bash
413
+ # Clone the repository
414
+ git clone https://github.com/avantmedialtd/artifex.git
415
+ cd artifex
416
+
417
+ # Install dependencies
418
+ bun install
419
+
420
+ # Link for local testing
421
+ bun link
422
+ ```
423
+
424
+ ### Running Tests
425
+
426
+ ```bash
427
+ # Run tests once
428
+ bun test
429
+
430
+ # Run tests in watch mode
431
+ bun run test:watch
432
+
433
+ # Run tests with coverage
434
+ bun run test:coverage
435
+ ```
436
+
437
+ ### Code Formatting
438
+
439
+ ```bash
440
+ # Format all files
441
+ bun run format
442
+
443
+ # Check formatting without making changes
444
+ bun run format:check
445
+ ```
446
+
447
+ ### Linting
448
+
449
+ ```bash
450
+ # Check for linting errors
451
+ bun run lint
452
+
453
+ # Fix linting errors automatically
454
+ bun run lint:fix
455
+ ```
456
+
457
+ ### Git Hooks
458
+
459
+ Set up a pre-push hook to run both linting and formatting checks before pushing:
460
+
461
+ ```bash
462
+ printf '#!/bin/sh\nbun run lint && bun run spell:check && bun run format:check\n' > .git/hooks/pre-push && chmod +x .git/hooks/pre-push
463
+ ```
464
+
465
+ This ensures code is linted and properly formatted before it gets pushed to the repository.
466
+
467
+ ### Making Changes
468
+
469
+ 1. Make your changes to the code
470
+ 2. Format your code: `bun run format`
471
+ 3. Run tests to ensure everything works: `bun test`
472
+ 4. Run the linter: `bun run lint`
473
+ 5. Test your changes locally using the linked `af` command
474
+ 6. Commit your changes and submit a pull request
475
+
476
+ ### Publishing to NPM
477
+
478
+ The package is published as `@avantmedia/af` on the public NPM registry. It ships TypeScript source directly — Bun executes it natively without a build step.
479
+
480
+ ```bash
481
+ # Verify what will be published
482
+ npm pack --dry-run
483
+
484
+ # Publish (requires npm login and @avantmedia org access)
485
+ npm publish --access public
486
+ ```
487
+
488
+ The `files` field in `package.json` controls what gets included. Test files, OpenSpec artifacts, the VSCode extension, and build outputs are excluded.
489
+
490
+ ### Project Structure
491
+
492
+ - `main.ts` - Entry point for the CLI
493
+ - `router.ts` - Command routing logic
494
+ - `commands/` - Command handler modules
495
+ - `components/` - Ink React UI components
496
+ - `utils/` - Shared utility modules
497
+ - `af` - Primary executable file that invokes the CLI
498
+ - Tests are colocated with source files (e.g., `*.test.ts`)
499
+
500
+ For more detailed contributor guidelines, see [CLAUDE.md](CLAUDE.md).
501
+
502
+ ## Bug Reports and Feature Requests
503
+
504
+ Found a bug or have an idea for a new feature?
505
+
506
+ - **Report bugs**: [GitHub Issues](https://github.com/avantmedialtd/artifex/issues)
507
+ - **Request features**: [GitHub Issues](https://github.com/avantmedialtd/artifex/issues)
508
+
509
+ When reporting a bug, please include:
510
+
511
+ - Your operating system and Node.js version
512
+ - Steps to reproduce the issue
513
+ - Expected vs actual behavior
514
+ - Any error messages or logs
515
+
516
+ ## Contributing
517
+
518
+ Contributions are welcome! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.
519
+
520
+ 1. Check existing [issues](https://github.com/avantmedialtd/artifex/issues) or create a new one
521
+ 2. Fork the repository
522
+ 3. Create a feature branch (`git checkout -b feature/amazing-feature`)
523
+ 4. Make your changes and add tests
524
+ 5. Ensure tests and linting pass
525
+ 6. Commit your changes
526
+ 7. Push to your fork and submit a pull request
527
+
528
+ ## License
529
+
530
+ MIT License. See [LICENSE](LICENSE) for details.
531
+
532
+ ## Author
533
+
534
+ István Antal <istvan@antal.xyz>
535
+
536
+ ## Links
537
+
538
+ - [GitHub Repository](https://github.com/avantmedialtd/artifex)
539
+ - [Issue Tracker](https://github.com/avantmedialtd/artifex/issues)
package/af ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ import './main.ts';
package/bun-upgrade.ts ADDED
@@ -0,0 +1,130 @@
1
+ import { spawn } from 'child_process';
2
+
3
+ export interface UpgradeResult {
4
+ package: string;
5
+ success: boolean;
6
+ error?: string;
7
+ }
8
+
9
+ /**
10
+ * Parse bun outdated text output to extract package names.
11
+ * Bun outputs a table format like:
12
+ * ┌─────────┬─────────┬────────┬────────┐
13
+ * │ Package │ Current │ Update │ Latest │
14
+ * ├─────────┼─────────┼────────┼────────┤
15
+ * │ lodash │ 4.17.0 │ 4.17.21│ 4.17.21│
16
+ * └─────────┴─────────┴────────┴────────┘
17
+ */
18
+ export function parseBunOutdatedOutput(output: string): string[] {
19
+ const lines = output.split('\n');
20
+ const packages: string[] = [];
21
+
22
+ for (const line of lines) {
23
+ // Skip header row, separator rows, and empty lines
24
+ if (!line.trim()) continue;
25
+ if (line.includes('Package') && line.includes('Current')) continue;
26
+ if (/^[┌├└─┬┼┴┐│┘]+$/.test(line.replace(/\s/g, ''))) continue;
27
+
28
+ // Parse table data rows that start with │
29
+ if (line.startsWith('│')) {
30
+ const cells = line
31
+ .split('│')
32
+ .map(cell => cell.trim())
33
+ .filter(cell => cell.length > 0);
34
+
35
+ // First cell is the package name
36
+ if (cells.length > 0 && cells[0] && !cells[0].includes('Package')) {
37
+ packages.push(cells[0]);
38
+ }
39
+ }
40
+ }
41
+
42
+ return packages;
43
+ }
44
+
45
+ /**
46
+ * Execute bun outdated and return list of packages that need updating
47
+ */
48
+ export async function getBunOutdatedPackages(): Promise<string[]> {
49
+ return new Promise((resolve, reject) => {
50
+ const bunProcess = spawn('bun', ['outdated'], {
51
+ stdio: ['ignore', 'pipe', 'pipe'],
52
+ shell: true,
53
+ });
54
+
55
+ let stdout = '';
56
+ let stderr = '';
57
+
58
+ bunProcess.stdout.on('data', (data: Buffer) => {
59
+ stdout += data.toString();
60
+ });
61
+
62
+ bunProcess.stderr.on('data', (data: Buffer) => {
63
+ stderr += data.toString();
64
+ });
65
+
66
+ bunProcess.on('close', (code: number | null) => {
67
+ // bun outdated returns 0 for success (regardless of whether packages are outdated)
68
+ if (code !== 0) {
69
+ reject(new Error(`bun outdated failed with code ${code}: ${stderr}`));
70
+ return;
71
+ }
72
+
73
+ // Parse the table output
74
+ const packages = parseBunOutdatedOutput(stdout);
75
+ resolve(packages);
76
+ });
77
+
78
+ bunProcess.on('error', (error: Error) => {
79
+ reject(new Error(`Failed to execute bun outdated: ${error.message}`));
80
+ });
81
+ });
82
+ }
83
+
84
+ /**
85
+ * Upgrade a single package to its latest version using bun
86
+ */
87
+ export async function bunUpgradePackage(packageName: string): Promise<UpgradeResult> {
88
+ return new Promise(resolve => {
89
+ console.log(`\nUpgrading ${packageName}...`);
90
+
91
+ const bunProcess = spawn('bun', ['add', `${packageName}@latest`], {
92
+ stdio: ['ignore', 'inherit', 'inherit'],
93
+ shell: true,
94
+ });
95
+
96
+ bunProcess.on('close', (code: number | null) => {
97
+ if (code === 0) {
98
+ resolve({ package: packageName, success: true });
99
+ } else {
100
+ resolve({
101
+ package: packageName,
102
+ success: false,
103
+ error: `bun add failed with exit code ${code}`,
104
+ });
105
+ }
106
+ });
107
+
108
+ bunProcess.on('error', (error: Error) => {
109
+ resolve({
110
+ package: packageName,
111
+ success: false,
112
+ error: error.message,
113
+ });
114
+ });
115
+ });
116
+ }
117
+
118
+ /**
119
+ * Upgrade all outdated packages sequentially using bun
120
+ */
121
+ export async function bunUpgradeAllPackages(packages: string[]): Promise<UpgradeResult[]> {
122
+ const results: UpgradeResult[] = [];
123
+
124
+ for (const packageName of packages) {
125
+ const result = await bunUpgradePackage(packageName);
126
+ results.push(result);
127
+ }
128
+
129
+ return results;
130
+ }