@zibby/cli 0.1.16 → 0.1.19
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/package.json +4 -6
- package/src/commands/init.js +146 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "Zibby CLI - Test automation generator and runner",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,8 +32,9 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@aws-sdk/client-sqs": "^3.1000.0",
|
|
35
|
-
"@zibby/skills": "^0.1.
|
|
36
|
-
"@zibby/core": "^0.1.
|
|
35
|
+
"@zibby/skills": "^0.1.3",
|
|
36
|
+
"@zibby/core": "^0.1.15",
|
|
37
|
+
"@zibby/memory": "^0.1.3",
|
|
37
38
|
"chalk": "^5.3.0",
|
|
38
39
|
"commander": "^12.0.0",
|
|
39
40
|
"dotenv": "^17.2.3",
|
|
@@ -55,9 +56,6 @@
|
|
|
55
56
|
"engines": {
|
|
56
57
|
"node": ">=18.0.0"
|
|
57
58
|
},
|
|
58
|
-
"optionalDependencies": {
|
|
59
|
-
"@zibby/memory": "*"
|
|
60
|
-
},
|
|
61
59
|
"devDependencies": {
|
|
62
60
|
"vitest": "^4.0.18"
|
|
63
61
|
}
|
package/src/commands/init.js
CHANGED
|
@@ -1,18 +1,120 @@
|
|
|
1
1
|
import { mkdir, writeFile, readFile } from 'fs/promises';
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { join, resolve, dirname } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
4
5
|
import inquirer from 'inquirer';
|
|
5
6
|
import chalk from 'chalk';
|
|
6
7
|
import ora from 'ora';
|
|
7
|
-
import { spawn } from 'child_process';
|
|
8
|
+
import { spawn, execSync } from 'child_process';
|
|
8
9
|
import { fileURLToPath } from 'url';
|
|
9
10
|
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = dirname(__filename);
|
|
12
13
|
|
|
14
|
+
async function checkNpmGlobalBinInPath() {
|
|
15
|
+
try {
|
|
16
|
+
const isWindows = process.platform === 'win32';
|
|
17
|
+
|
|
18
|
+
// Get npm global bin directory
|
|
19
|
+
const npmPrefix = execSync('npm config get prefix', { encoding: 'utf-8' }).trim();
|
|
20
|
+
const npmGlobalBin = isWindows ? npmPrefix : `${npmPrefix}/bin`;
|
|
21
|
+
const npmGlobalBinExpanded = npmGlobalBin.replace(/^~/, homedir());
|
|
22
|
+
|
|
23
|
+
// Check if it's in PATH
|
|
24
|
+
const pathSeparator = isWindows ? ';' : ':';
|
|
25
|
+
const pathDirs = process.env.PATH.split(pathSeparator);
|
|
26
|
+
const isInPath = pathDirs.some(dir => {
|
|
27
|
+
const normalizedDir = dir.replace(/^~/, homedir());
|
|
28
|
+
return normalizedDir === npmGlobalBinExpanded || normalizedDir === npmGlobalBin;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (isInPath) {
|
|
32
|
+
return; // Already configured
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Not in PATH - offer to add it
|
|
36
|
+
console.log(chalk.yellow('⚠️ npm global bin not in PATH'));
|
|
37
|
+
console.log(chalk.gray(` Location: ${npmGlobalBinExpanded}`));
|
|
38
|
+
console.log();
|
|
39
|
+
|
|
40
|
+
const { shouldAddPath } = await inquirer.prompt([{
|
|
41
|
+
type: 'confirm',
|
|
42
|
+
name: 'shouldAddPath',
|
|
43
|
+
message: 'Add npm global bin to your shell PATH automatically?',
|
|
44
|
+
default: true
|
|
45
|
+
}]);
|
|
46
|
+
|
|
47
|
+
if (!shouldAddPath) {
|
|
48
|
+
if (isWindows) {
|
|
49
|
+
console.log(chalk.gray('\n💡 To add manually on Windows:'));
|
|
50
|
+
console.log(chalk.gray(' 1. Search "Environment Variables" in Start menu'));
|
|
51
|
+
console.log(chalk.gray(' 2. Edit "Path" in User variables'));
|
|
52
|
+
console.log(chalk.gray(` 3. Add: ${npmGlobalBinExpanded}\n`));
|
|
53
|
+
} else {
|
|
54
|
+
console.log(chalk.gray('\n💡 To add manually, run:'));
|
|
55
|
+
console.log(chalk.gray(` echo 'export PATH="${npmGlobalBinExpanded}:$PATH"' >> ~/.zshrc`));
|
|
56
|
+
console.log(chalk.gray(` source ~/.zshrc\n`));
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Windows: Can't auto-add to PATH (requires registry changes)
|
|
62
|
+
if (isWindows) {
|
|
63
|
+
console.log(chalk.yellow('⚠️ Cannot auto-add PATH on Windows'));
|
|
64
|
+
console.log(chalk.gray(' Please add manually:'));
|
|
65
|
+
console.log(chalk.gray(' 1. Search "Environment Variables" in Start menu'));
|
|
66
|
+
console.log(chalk.gray(' 2. Edit "Path" in User variables'));
|
|
67
|
+
console.log(chalk.gray(` 3. Add: ${npmGlobalBinExpanded}\n`));
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Unix/Linux: Auto-add to shell config
|
|
72
|
+
const shell = process.env.SHELL || '';
|
|
73
|
+
let shellRc = '';
|
|
74
|
+
|
|
75
|
+
if (shell.includes('zsh')) {
|
|
76
|
+
shellRc = join(homedir(), '.zshrc');
|
|
77
|
+
} else if (shell.includes('bash')) {
|
|
78
|
+
// Linux often uses .bashrc, macOS uses .bash_profile
|
|
79
|
+
shellRc = existsSync(join(homedir(), '.bashrc'))
|
|
80
|
+
? join(homedir(), '.bashrc')
|
|
81
|
+
: join(homedir(), '.bash_profile');
|
|
82
|
+
} else {
|
|
83
|
+
console.log(chalk.yellow(`⚠️ Unknown shell: ${shell}`));
|
|
84
|
+
console.log(chalk.gray(' Please add manually:'));
|
|
85
|
+
console.log(chalk.gray(` export PATH="${npmGlobalBinExpanded}:$PATH"`));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check if already in shell config
|
|
90
|
+
if (existsSync(shellRc)) {
|
|
91
|
+
const rcContent = await readFile(shellRc, 'utf-8');
|
|
92
|
+
if (rcContent.includes(npmGlobalBinExpanded) || (rcContent.includes('npm') && rcContent.includes('global') && rcContent.includes('bin'))) {
|
|
93
|
+
console.log(chalk.yellow(`⚠️ PATH entry found in ${shellRc} but not active`));
|
|
94
|
+
console.log(chalk.gray(` Run: source ${shellRc}\n`));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Add to shell config
|
|
100
|
+
const pathEntry = `\n# npm global bin (added by zibby)\nexport PATH="${npmGlobalBinExpanded}:$PATH"\n`;
|
|
101
|
+
await writeFile(shellRc, (existsSync(shellRc) ? await readFile(shellRc, 'utf-8') : '') + pathEntry);
|
|
102
|
+
|
|
103
|
+
console.log(chalk.green(`✅ Added to ${shellRc}`));
|
|
104
|
+
console.log(chalk.yellow('\n💡 Run this to activate in current session:'));
|
|
105
|
+
console.log(chalk.gray(` source ${shellRc}\n`));
|
|
106
|
+
|
|
107
|
+
} catch {
|
|
108
|
+
// Silently fail - don't block init if this check fails
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
13
112
|
export async function initCommand(projectName, options) {
|
|
14
113
|
console.log(chalk.bold.cyan('\n🎭 Welcome to Zibby Test Automation!\n'));
|
|
15
114
|
|
|
115
|
+
// Check if npm global bin is in PATH
|
|
116
|
+
await checkNpmGlobalBinInPath();
|
|
117
|
+
|
|
16
118
|
const targetDir = projectName ? resolve(process.cwd(), projectName) : process.cwd();
|
|
17
119
|
const projectNameActual = projectName || 'zibby-tests';
|
|
18
120
|
const isNewProject = !!projectName;
|
|
@@ -188,9 +290,25 @@ export async function initCommand(projectName, options) {
|
|
|
188
290
|
const envContent = generateEnvFile(answers, options);
|
|
189
291
|
await writeFile(join(targetDir, '.env.example'), envContent);
|
|
190
292
|
|
|
191
|
-
// Create/update .env file
|
|
293
|
+
// Create/update .env file
|
|
294
|
+
const envPath = join(targetDir, '.env');
|
|
192
295
|
if (answers.apiKey && answers.apiKey.trim()) {
|
|
193
296
|
await createOrUpdateEnvFile(targetDir, answers.apiKey.trim(), answers, options);
|
|
297
|
+
} else if (!existsSync(envPath)) {
|
|
298
|
+
// Create .env from .env.example if it doesn't exist
|
|
299
|
+
await writeFile(envPath, envContent);
|
|
300
|
+
} else if (options.force) {
|
|
301
|
+
// On force reinit, merge memory vars into existing .env if using --mem
|
|
302
|
+
if (options.mem) {
|
|
303
|
+
let existingEnv = await readFile(envPath, 'utf-8');
|
|
304
|
+
if (!existingEnv.includes('ZIBBY_MEMORY_MAX_RUNS')) {
|
|
305
|
+
existingEnv += `\n# Test Memory (Dolt DB) - Auto-compaction settings\n`;
|
|
306
|
+
existingEnv += `# ZIBBY_MEMORY_MAX_RUNS=3000 # Max test runs to keep per spec\n`;
|
|
307
|
+
existingEnv += `# ZIBBY_MEMORY_MAX_AGE=1095 # Max age in days for stale data (~3 years)\n`;
|
|
308
|
+
existingEnv += `# ZIBBY_MEMORY_COMPACT_EVERY=1500 # Auto-compact every N runs (0 to disable)\n`;
|
|
309
|
+
await writeFile(envPath, existingEnv);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
194
312
|
}
|
|
195
313
|
|
|
196
314
|
|
|
@@ -435,8 +553,8 @@ function generateConfig(answers, _options = {}) {
|
|
|
435
553
|
`;
|
|
436
554
|
}
|
|
437
555
|
|
|
438
|
-
function generateEnvFile(answers,
|
|
439
|
-
|
|
556
|
+
function generateEnvFile(answers, options = {}) {
|
|
557
|
+
let content = `# Zibby Test Automation - Environment Variables
|
|
440
558
|
|
|
441
559
|
# AI Provider Keys
|
|
442
560
|
${answers.agent === 'claude' ? '# Claude (Anthropic) - Direct API\nANTHROPIC_API_KEY=sk-ant-your_key_here\n' : '# ANTHROPIC_API_KEY=sk-ant-your_key_here\n'}
|
|
@@ -450,6 +568,16 @@ ${answers.agent === 'cursor' ? '# Cursor Agent (uses cursor-agent CLI)\n# No API
|
|
|
450
568
|
# SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
|
|
451
569
|
`;
|
|
452
570
|
|
|
571
|
+
// Add memory configuration if --mem flag is used
|
|
572
|
+
if (options.mem) {
|
|
573
|
+
content += `
|
|
574
|
+
# Test Memory (Dolt DB) - Auto-compaction settings
|
|
575
|
+
# ZIBBY_MEMORY_MAX_RUNS=3000 # Max test runs to keep per spec
|
|
576
|
+
# ZIBBY_MEMORY_MAX_AGE=1095 # Max age in days for stale data (~3 years)
|
|
577
|
+
# ZIBBY_MEMORY_COMPACT_EVERY=1500 # Auto-compact every N runs (0 to disable)
|
|
578
|
+
`;
|
|
579
|
+
}
|
|
580
|
+
|
|
453
581
|
return content;
|
|
454
582
|
}
|
|
455
583
|
|
|
@@ -481,8 +609,8 @@ async function createOrUpdateEnvFile(targetDir, apiKey, answers, options = {}) {
|
|
|
481
609
|
await writeFile(envPath, envContent);
|
|
482
610
|
}
|
|
483
611
|
|
|
484
|
-
function generateEnvFileWithKey(answers, apiKey,
|
|
485
|
-
|
|
612
|
+
function generateEnvFileWithKey(answers, apiKey, options = {}) {
|
|
613
|
+
let content = `# Zibby Test Automation - Environment Variables
|
|
486
614
|
|
|
487
615
|
# AI Provider Keys
|
|
488
616
|
${answers.agent === 'claude' ? 'ANTHROPIC_API_KEY=sk-ant-your_key_here\n' : '# ANTHROPIC_API_KEY=sk-ant-your_key_here\n'}
|
|
@@ -494,6 +622,16 @@ ZIBBY_API_KEY=${apiKey}
|
|
|
494
622
|
# SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
|
|
495
623
|
`;
|
|
496
624
|
|
|
625
|
+
// Add memory configuration if --mem flag is used
|
|
626
|
+
if (options.mem) {
|
|
627
|
+
content += `
|
|
628
|
+
# Test Memory (Dolt DB) - Auto-compaction settings
|
|
629
|
+
# ZIBBY_MEMORY_MAX_RUNS=3000 # Max test runs to keep per spec
|
|
630
|
+
# ZIBBY_MEMORY_MAX_AGE=1095 # Max age in days for stale data (~3 years)
|
|
631
|
+
# ZIBBY_MEMORY_COMPACT_EVERY=1500 # Auto-compact every N runs (0 to disable)
|
|
632
|
+
`;
|
|
633
|
+
}
|
|
634
|
+
|
|
497
635
|
return content;
|
|
498
636
|
}
|
|
499
637
|
|
|
@@ -509,8 +647,8 @@ function generatePackageJson(projectName, _answers) {
|
|
|
509
647
|
'test:headed': 'playwright test --headed'
|
|
510
648
|
},
|
|
511
649
|
dependencies: {
|
|
512
|
-
'@zibby/cli': '^0.1.
|
|
513
|
-
'@zibby/core': '^0.1.
|
|
650
|
+
'@zibby/cli': '^0.1.19',
|
|
651
|
+
'@zibby/core': '^0.1.15'
|
|
514
652
|
},
|
|
515
653
|
devDependencies: {
|
|
516
654
|
'@playwright/test': '^1.49.0',
|