vibe-weaver 1.0.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.
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Shell execution tool for Vibe-Weaver CLI
3
+ * Runs real shell commands and streams output
4
+ */
5
+
6
+ import { execa, execaCommand } from 'execa';
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+
10
+ export interface CommandResult {
11
+ success: boolean;
12
+ command: string;
13
+ exitCode: number;
14
+ stdout: string;
15
+ stderr: string;
16
+ timedOut?: boolean;
17
+ duration?: number;
18
+ }
19
+
20
+ /**
21
+ * Run a shell command and capture output
22
+ */
23
+ export async function runShell(
24
+ command: string,
25
+ options: {
26
+ cwd?: string;
27
+ env?: Record<string, string>;
28
+ timeout?: number;
29
+ shell?: boolean;
30
+ dryRun?: boolean;
31
+ } = {}
32
+ ): Promise<CommandResult> {
33
+ const startTime = Date.now();
34
+
35
+ if (options.dryRun) {
36
+ console.log(chalk.grey(`[DRY-RUN] Would execute: ${command}`));
37
+ return {
38
+ success: true,
39
+ command,
40
+ exitCode: 0,
41
+ stdout: '',
42
+ stderr: '',
43
+ duration: 0
44
+ };
45
+ }
46
+
47
+ try {
48
+ const result = await execaCommand(command, {
49
+ cwd: options.cwd || process.cwd(),
50
+ env: { ...process.env, ...options.env },
51
+ timeout: options.timeout || 120000, // 2 minute default timeout
52
+ shell: options.shell || true,
53
+ reject: false,
54
+ cleanup: true
55
+ });
56
+
57
+ const duration = Date.now() - startTime;
58
+
59
+ return {
60
+ success: result.exitCode === 0,
61
+ command,
62
+ exitCode: result.exitCode || 0,
63
+ stdout: result.stdout || '',
64
+ stderr: result.stderr || '',
65
+ duration
66
+ };
67
+ } catch (error) {
68
+ const duration = Date.now() - startTime;
69
+
70
+ return {
71
+ success: false,
72
+ command,
73
+ exitCode: 1,
74
+ stdout: '',
75
+ stderr: error instanceof Error ? error.message : String(error),
76
+ timedOut: error instanceof Error && error.message.includes('timeout'),
77
+ duration
78
+ };
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Run a shell command with streaming output (live display)
84
+ */
85
+ export async function runShellStream(
86
+ command: string,
87
+ options: {
88
+ cwd?: string;
89
+ env?: Record<string, string>;
90
+ timeout?: number;
91
+ onStdout?: (data: string) => void;
92
+ onStderr?: (data: string) => void;
93
+ } = {}
94
+ ): Promise<CommandResult> {
95
+ const startTime = Date.now();
96
+
97
+ try {
98
+ const childProcess = execa(command, {
99
+ cwd: options.cwd || process.cwd(),
100
+ env: { ...process.env, ...options.env },
101
+ shell: true,
102
+ cleanup: true
103
+ });
104
+
105
+ let stdout = '';
106
+ let stderr = '';
107
+
108
+ childProcess.stdout?.on('data', (data: Buffer) => {
109
+ const text = data.toString();
110
+ stdout += text;
111
+ if (options.onStdout) {
112
+ options.onStdout(text);
113
+ } else {
114
+ process.stdout.write(text);
115
+ }
116
+ });
117
+
118
+ childProcess.stderr?.on('data', (data: Buffer) => {
119
+ const text = data.toString();
120
+ stderr += text;
121
+ if (options.onStderr) {
122
+ options.onStderr(text);
123
+ } else {
124
+ process.stderr.write(text);
125
+ }
126
+ });
127
+
128
+ const result = await childProcess;
129
+ const duration = Date.now() - startTime;
130
+
131
+ return {
132
+ success: result.exitCode === 0,
133
+ command,
134
+ exitCode: result.exitCode || 0,
135
+ stdout,
136
+ stderr,
137
+ duration
138
+ };
139
+ } catch (error) {
140
+ const duration = Date.now() - startTime;
141
+
142
+ return {
143
+ success: false,
144
+ command,
145
+ exitCode: 1,
146
+ stdout: '',
147
+ stderr: error instanceof Error ? error.message : String(error),
148
+ duration
149
+ };
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Run a command with a spinner
155
+ */
156
+ export async function runWithSpinner(
157
+ command: string,
158
+ options: {
159
+ cwd?: string;
160
+ env?: Record<string, string>;
161
+ timeout?: number;
162
+ message?: string;
163
+ } = {}
164
+ ): Promise<CommandResult> {
165
+ const spinner = ora(options.message || 'Running command...').start();
166
+
167
+ try {
168
+ const result = await runShell(command, options);
169
+
170
+ if (result.success) {
171
+ spinner.succeed(chalk.green('Command completed successfully'));
172
+ } else {
173
+ spinner.fail(chalk.red(`Command failed with exit code ${result.exitCode}`));
174
+ }
175
+
176
+ return result;
177
+ } catch (error) {
178
+ spinner.fail(chalk.red('Command failed'));
179
+ throw error;
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Common build commands
185
+ */
186
+ export const buildCommands = {
187
+ npmInstall: 'npm install',
188
+ npmBuild: 'npm run build',
189
+ npmTest: 'npm test',
190
+ npmLint: 'npm run lint',
191
+ npmTypecheck: 'npm run typecheck' || 'npx tsc --noEmit',
192
+ pnpmInstall: 'pnpm install',
193
+ pnpmBuild: 'pnpm run build',
194
+ bunInstall: 'bun install',
195
+ bunBuild: 'bun run build',
196
+ yarnInstall: 'yarn install',
197
+ yarnBuild: 'yarn run build'
198
+ };
199
+
200
+ /**
201
+ * Detect package manager from lock files
202
+ */
203
+ export function detectPackageManager(cwd: string = process.cwd()): 'npm' | 'pnpm' | 'yarn' | 'bun' {
204
+ const fs = require('fs');
205
+
206
+ if (fs.existsSync(`${cwd}/pnpm-lock.yaml`)) return 'pnpm';
207
+ if (fs.existsSync(`${cwd}/yarn.lock`)) return 'yarn';
208
+ if (fs.existsSync(`${cwd}/bun.lockb`)) return 'bun';
209
+ return 'npm';
210
+ }
211
+
212
+ /**
213
+ * Get the appropriate install command
214
+ */
215
+ export function getInstallCommand(cwd: string = process.cwd()): string {
216
+ const pm = detectPackageManager(cwd);
217
+
218
+ switch (pm) {
219
+ case 'pnpm': return buildCommands.pnpmInstall;
220
+ case 'yarn': return buildCommands.yarnInstall;
221
+ case 'bun': return buildCommands.bunInstall;
222
+ default: return buildCommands.npmInstall;
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Get the appropriate build command
228
+ */
229
+ export function getBuildCommand(cwd: string = process.cwd()): string {
230
+ const pm = detectPackageManager(cwd);
231
+
232
+ switch (pm) {
233
+ case 'pnpm': return buildCommands.pnpmBuild;
234
+ case 'yarn': return buildCommands.yarnBuild;
235
+ case 'bun': return buildCommands.bunBuild;
236
+ default: return buildCommands.npmBuild;
237
+ }
238
+ }
239
+
240
+ export default {
241
+ runShell,
242
+ runShellStream,
243
+ runWithSpinner,
244
+ buildCommands,
245
+ detectPackageManager,
246
+ getInstallCommand,
247
+ getBuildCommand
248
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022"],
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "resolveJsonModule": true,
17
+ "allowSyntheticDefaultImports": true,
18
+ "noUnusedLocals": false,
19
+ "noUnusedParameters": false,
20
+ "noImplicitReturns": true,
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": ["src/**/*"],
24
+ "exclude": ["node_modules", "dist", "tests"]
25
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,34 @@
1
+ import { defineConfig } from 'tsup';
2
+ import { copyFileSync, mkdirSync, existsSync } from 'fs';
3
+ import { join, dirname } from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url));
7
+
8
+ export default defineConfig({
9
+ entry: ['src/index.ts'],
10
+ format: ['esm'],
11
+ platform: 'node',
12
+ target: 'node18',
13
+ outDir: 'dist',
14
+ splitting: false,
15
+ sourcemap: true,
16
+ dts: true,
17
+ clean: true,
18
+ treeshake: true,
19
+ minify: false,
20
+ shims: false,
21
+ noExternal: [],
22
+ onSuccess: () => {
23
+ // Ensure bin directory exists in dist
24
+ const distBinDir = join(__dirname, 'dist', 'bin');
25
+ if (!existsSync(distBinDir)) {
26
+ mkdirSync(distBinDir, { recursive: true });
27
+ }
28
+ // Copy the bin file
29
+ copyFileSync(
30
+ join(__dirname, 'bin', 'vibe-weaver.js'),
31
+ join(distBinDir, 'vibe-weaver.js')
32
+ );
33
+ }
34
+ });
Binary file