cli4ai 1.2.2 → 1.2.3
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/dist/commands/add.js +11 -9
- package/dist/commands/browse.js +3 -3
- package/dist/commands/info.js +5 -4
- package/dist/commands/search.js +8 -6
- package/package.json +1 -1
package/dist/commands/add.js
CHANGED
|
@@ -6,10 +6,9 @@ import { resolve, dirname, join, normalize } from 'path';
|
|
|
6
6
|
import { createInterface } from 'readline';
|
|
7
7
|
import { tmpdir, platform } from 'os';
|
|
8
8
|
import { spawnSync } from 'child_process';
|
|
9
|
-
// Windows
|
|
9
|
+
// Windows compatibility: use shell: true on Windows to handle .cmd wrappers
|
|
10
|
+
// This is safe because package names are validated with strict regex patterns
|
|
10
11
|
const isWindows = platform() === 'win32';
|
|
11
|
-
const npmCmd = isWindows ? 'npm.cmd' : 'npm';
|
|
12
|
-
const tarCmd = 'tar'; // Windows 10+ has tar built-in
|
|
13
12
|
import { output, outputError, log } from '../lib/cli.js';
|
|
14
13
|
import { loadManifest, tryLoadManifest } from '../core/manifest.js';
|
|
15
14
|
import { ensureCli4aiHome, ensureLocalDir, PACKAGES_DIR, LOCAL_PACKAGES_DIR, loadConfig } from '../core/config.js';
|
|
@@ -102,10 +101,11 @@ async function downloadFromNpm(packageName, targetDir) {
|
|
|
102
101
|
try {
|
|
103
102
|
// Use npm pack to download the tarball - using spawnSync to prevent command injection
|
|
104
103
|
log(`Downloading ${packageName} from npm...`);
|
|
105
|
-
const packResult = spawnSync(
|
|
104
|
+
const packResult = spawnSync('npm', ['pack', packageName, `--pack-destination=${tmpDir}`], {
|
|
106
105
|
stdio: 'pipe',
|
|
107
106
|
cwd: tmpDir,
|
|
108
|
-
encoding: 'utf-8'
|
|
107
|
+
encoding: 'utf-8',
|
|
108
|
+
shell: isWindows // Required on Windows to find npm.cmd
|
|
109
109
|
});
|
|
110
110
|
if (packResult.error) {
|
|
111
111
|
throw new Error(`npm not found or failed to execute: ${packResult.error.message}`);
|
|
@@ -122,9 +122,10 @@ async function downloadFromNpm(packageName, targetDir) {
|
|
|
122
122
|
// Extract the tarball using spawnSync to prevent command injection
|
|
123
123
|
// Use --strip-components=1 equivalent by extracting to a subdir
|
|
124
124
|
const tarPath = join(tmpDir, tarball);
|
|
125
|
-
const extractResult = spawnSync(
|
|
125
|
+
const extractResult = spawnSync('tar', ['-xzf', tarPath, '-C', tmpDir], {
|
|
126
126
|
stdio: 'pipe',
|
|
127
|
-
encoding: 'utf-8'
|
|
127
|
+
encoding: 'utf-8',
|
|
128
|
+
shell: isWindows // Required on Windows
|
|
128
129
|
});
|
|
129
130
|
if (extractResult.status !== 0) {
|
|
130
131
|
throw new Error(`Failed to extract package: ${extractResult.stderr || 'tar extraction failed'}`);
|
|
@@ -181,9 +182,10 @@ async function installNpmDependencies(pkgPath, dependencies) {
|
|
|
181
182
|
if (deps.length === 0)
|
|
182
183
|
return;
|
|
183
184
|
log(`Installing npm dependencies: ${deps.join(', ')}`);
|
|
184
|
-
const result = spawnSync(
|
|
185
|
+
const result = spawnSync('npm', ['install', ...deps], {
|
|
185
186
|
cwd: pkgPath,
|
|
186
|
-
stdio: 'inherit'
|
|
187
|
+
stdio: 'inherit',
|
|
188
|
+
shell: isWindows // Required on Windows to find npm.cmd
|
|
187
189
|
});
|
|
188
190
|
if (result.status !== 0) {
|
|
189
191
|
throw new Error(`Failed to install dependencies (exit code: ${result.status})`);
|
package/dist/commands/browse.js
CHANGED
|
@@ -5,8 +5,8 @@ import { spawnSync } from 'child_process';
|
|
|
5
5
|
import { platform } from 'os';
|
|
6
6
|
import { log, outputError } from '../lib/cli.js';
|
|
7
7
|
import { getNpmGlobalPackages, getGlobalPackages, getLocalPackages } from '../core/config.js';
|
|
8
|
-
// Windows
|
|
9
|
-
const
|
|
8
|
+
// Windows compatibility
|
|
9
|
+
const isWindows = platform() === 'win32';
|
|
10
10
|
// ANSI codes
|
|
11
11
|
const RESET = '\x1B[0m';
|
|
12
12
|
const BOLD = '\x1B[1m';
|
|
@@ -331,7 +331,7 @@ async function installPackages(packages, scope) {
|
|
|
331
331
|
if (scopeFlag)
|
|
332
332
|
addArgs.push(scopeFlag);
|
|
333
333
|
addArgs.push('-y');
|
|
334
|
-
const result = spawnSync(
|
|
334
|
+
const result = spawnSync('cli4ai', addArgs, { stdio: 'pipe', shell: isWindows });
|
|
335
335
|
clearInterval(spinner);
|
|
336
336
|
if (result.status === 0) {
|
|
337
337
|
process.stderr.write(`\r ${GREEN}✓${RESET} ${BOLD}${shortName}${RESET} installed \n`);
|
package/dist/commands/info.js
CHANGED
|
@@ -5,8 +5,8 @@ import { resolve } from 'path';
|
|
|
5
5
|
import { spawnSync } from 'child_process';
|
|
6
6
|
import { platform } from 'os';
|
|
7
7
|
import { output, outputError, log } from '../lib/cli.js';
|
|
8
|
-
// Windows
|
|
9
|
-
const
|
|
8
|
+
// Windows compatibility
|
|
9
|
+
const isWindows = platform() === 'win32';
|
|
10
10
|
import { findPackage, loadConfig } from '../core/config.js';
|
|
11
11
|
import { loadManifest, tryLoadManifest } from '../core/manifest.js';
|
|
12
12
|
import { remotePackageInfo, RemoteConnectionError, RemoteApiError } from '../core/remote-client.js';
|
|
@@ -65,10 +65,11 @@ export async function infoCommand(packageName, options) {
|
|
|
65
65
|
try {
|
|
66
66
|
log(`Fetching ${scopedName} from npm...`);
|
|
67
67
|
// Use spawnSync with argument array to prevent command injection
|
|
68
|
-
const result = spawnSync(
|
|
68
|
+
const result = spawnSync('npm', ['view', scopedName, '--json'], {
|
|
69
69
|
encoding: 'utf-8',
|
|
70
70
|
timeout: 10000,
|
|
71
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
71
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
72
|
+
shell: isWindows // Required on Windows to find npm.cmd
|
|
72
73
|
});
|
|
73
74
|
if (result.status === 0 && result.stdout) {
|
|
74
75
|
const pkg = JSON.parse(result.stdout);
|
package/dist/commands/search.js
CHANGED
|
@@ -6,8 +6,8 @@ import { resolve } from 'path';
|
|
|
6
6
|
import { spawnSync } from 'child_process';
|
|
7
7
|
import { platform } from 'os';
|
|
8
8
|
import { output, outputError, log } from '../lib/cli.js';
|
|
9
|
-
// Windows
|
|
10
|
-
const
|
|
9
|
+
// Windows compatibility
|
|
10
|
+
const isWindows = platform() === 'win32';
|
|
11
11
|
import { loadConfig, getGlobalPackages, getLocalPackages } from '../core/config.js';
|
|
12
12
|
import { tryLoadManifest } from '../core/manifest.js';
|
|
13
13
|
import { remoteListPackages, RemoteConnectionError, RemoteApiError } from '../core/remote-client.js';
|
|
@@ -97,18 +97,20 @@ export async function searchCommand(query, options) {
|
|
|
97
97
|
try {
|
|
98
98
|
log(`Searching npm for @cli4ai packages...`);
|
|
99
99
|
// Use spawnSync with argument array to prevent command injection
|
|
100
|
-
const searchResult = spawnSync(
|
|
100
|
+
const searchResult = spawnSync('npm', ['search', `@cli4ai/${query}`, '--json'], {
|
|
101
101
|
encoding: 'utf-8',
|
|
102
102
|
timeout: 10000,
|
|
103
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
103
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
104
|
+
shell: isWindows // Required on Windows to find npm.cmd
|
|
104
105
|
});
|
|
105
106
|
let npmResults = searchResult.stdout || '';
|
|
106
107
|
// Fallback to searching @cli4ai if specific query fails
|
|
107
108
|
if (!npmResults || npmResults === '[]') {
|
|
108
|
-
const fallbackResult = spawnSync(
|
|
109
|
+
const fallbackResult = spawnSync('npm', ['search', '@cli4ai', '--json'], {
|
|
109
110
|
encoding: 'utf-8',
|
|
110
111
|
timeout: 10000,
|
|
111
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
112
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
113
|
+
shell: isWindows // Required on Windows to find npm.cmd
|
|
112
114
|
});
|
|
113
115
|
npmResults = fallbackResult.stdout || '[]';
|
|
114
116
|
}
|