@factadev/cli 0.2.13 → 0.2.14
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/bin/ensure-platform.cjs +41 -0
- package/bin/nest.cjs +55 -106
- package/package.json +13 -7
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Postinstall: ensure platform optional dependency is installed so
|
|
4
|
+
* optionalDependencies auto-link works. If the binary is missing, install it
|
|
5
|
+
* into this package's node_modules (npm sometimes skips optional deps).
|
|
6
|
+
*/
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const arch = process.arch;
|
|
13
|
+
const platformKey = `${platform}-${arch}`;
|
|
14
|
+
const pkgName = `@factadev/cli-${platformKey}`;
|
|
15
|
+
const binName = platform === 'win32' ? 'nest.exe' : 'nest';
|
|
16
|
+
|
|
17
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
18
|
+
const binaryPath = path.join(packageRoot, 'node_modules', pkgName, 'bin', binName);
|
|
19
|
+
|
|
20
|
+
if (fs.existsSync(binaryPath)) {
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let version;
|
|
25
|
+
try {
|
|
26
|
+
const pkgPath = path.join(packageRoot, 'package.json');
|
|
27
|
+
version = require(pkgPath).version;
|
|
28
|
+
} catch (e) {
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (!version) process.exit(0);
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
execSync(`npm install ${pkgName}@${version} --no-save --prefer-offline --no-audit`, {
|
|
36
|
+
cwd: packageRoot,
|
|
37
|
+
stdio: 'inherit',
|
|
38
|
+
});
|
|
39
|
+
} catch (e) {
|
|
40
|
+
// Non-fatal: launcher will prompt or install on first run
|
|
41
|
+
}
|
package/bin/nest.cjs
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* NEST CLI launcher. Resolves platform binary from optionalDependency
|
|
4
|
+
* (npm may install it in main package node_modules or as global sibling).
|
|
5
|
+
*/
|
|
3
6
|
const { execFileSync, execSync } = require('child_process');
|
|
4
7
|
const path = require('path');
|
|
5
8
|
const fs = require('fs');
|
|
@@ -7,132 +10,78 @@ const fs = require('fs');
|
|
|
7
10
|
const platform = process.platform;
|
|
8
11
|
const arch = process.arch;
|
|
9
12
|
const RELEASE_URL = 'https://github.com/Facta-Dev/ctx0_nest/releases';
|
|
10
|
-
const SUPPORTED_PLATFORMS = [
|
|
11
|
-
{ key: 'darwin-arm64', label: 'darwin-arm64 (macOS Apple Silicon)' },
|
|
12
|
-
{ key: 'darwin-x64', label: 'darwin-x64 (macOS Intel)' },
|
|
13
|
-
{ key: 'linux-arm64', label: 'linux-arm64' },
|
|
14
|
-
{ key: 'linux-x64', label: 'linux-x64' },
|
|
15
|
-
{ key: 'win32-x64', label: 'win32-x64' },
|
|
16
|
-
];
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
14
|
+
// Node: darwin|linux|win32, x64|arm64 -> matches our package suffix
|
|
15
|
+
const platformKey = `${platform}-${arch}`;
|
|
16
|
+
const pkgName = `@factadev/cli-${platformKey}`;
|
|
17
|
+
const binName = platform === 'win32' ? 'nest.exe' : 'nest';
|
|
21
18
|
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
}
|
|
19
|
+
function getBinaryPath() {
|
|
20
|
+
const mainRoot = path.resolve(__dirname, '..');
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
22
|
+
const candidates = [
|
|
23
|
+
// 1. Optional dep inside main package (npm install -g @factadev/cli)
|
|
24
|
+
path.join(mainRoot, 'node_modules', pkgName, 'bin', binName),
|
|
25
|
+
// 2. Sibling under same scope (global: .../node_modules/@factadev/cli-*)
|
|
26
|
+
path.join(mainRoot, '..', `cli-${platformKey}`, 'bin', binName),
|
|
27
|
+
// 3. Global Unix
|
|
28
|
+
path.join(
|
|
29
|
+
process.env.npm_config_prefix || process.env.PREFIX || '/usr/local',
|
|
30
|
+
'lib',
|
|
31
|
+
'node_modules',
|
|
32
|
+
pkgName,
|
|
33
|
+
'bin',
|
|
34
|
+
binName
|
|
35
|
+
),
|
|
36
|
+
// 4. Global Windows
|
|
37
|
+
path.join(
|
|
38
|
+
process.env.npm_config_prefix ||
|
|
39
|
+
(process.env.APPDATA ? path.join(process.env.APPDATA, 'npm') : ''),
|
|
40
|
+
'node_modules',
|
|
41
|
+
pkgName,
|
|
42
|
+
'bin',
|
|
43
|
+
binName
|
|
44
|
+
),
|
|
45
|
+
// 5. nvm-style global
|
|
46
|
+
path.join(
|
|
47
|
+
process.env.HOME || '',
|
|
48
|
+
'.nvm', 'versions', 'node',
|
|
49
|
+
'v' + process.version.split('.')[0].slice(1),
|
|
50
|
+
'lib', 'node_modules',
|
|
51
|
+
pkgName, 'bin', binName
|
|
52
|
+
),
|
|
53
|
+
].filter(Boolean);
|
|
48
54
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
console.log(`Installing ${pkgName}...`);
|
|
52
|
-
try {
|
|
53
|
-
execSync(`npm install -g ${pkgName}`, { stdio: 'inherit' });
|
|
54
|
-
return true;
|
|
55
|
-
} catch (e) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function getInstalledVersion(platformName = platform, archName = arch) {
|
|
61
|
-
const binPath = getBinaryPath(platformName, archName);
|
|
62
|
-
if (binPath) {
|
|
63
|
-
return 'installed';
|
|
55
|
+
for (const binPath of candidates) {
|
|
56
|
+
if (fs.existsSync(binPath)) return binPath;
|
|
64
57
|
}
|
|
65
58
|
return null;
|
|
66
59
|
}
|
|
67
60
|
|
|
68
|
-
function getLatestVersion(platformName = platform, archName = arch) {
|
|
69
|
-
const pkgName = `@factadev/cli-${platformName}-${archName}`;
|
|
70
|
-
try {
|
|
71
|
-
const result = execSync(`npm view ${pkgName} version`, { encoding: 'utf8' });
|
|
72
|
-
return result.trim();
|
|
73
|
-
} catch (e) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function getBunPath() {
|
|
79
|
-
const bunPaths = [
|
|
80
|
-
path.join(__dirname, '..', 'node_modules', '.bin', 'bun'),
|
|
81
|
-
path.join(process.env.HOME || '', '.bun', 'bin', 'bun'),
|
|
82
|
-
path.join(process.env.APPDATA || '', 'bun', 'bin', 'bun.exe'),
|
|
83
|
-
'/usr/local/bin/bun',
|
|
84
|
-
'/opt/homebrew/bin/bun',
|
|
85
|
-
];
|
|
86
|
-
for (const p of bunPaths) {
|
|
87
|
-
try { fs.accessSync(p, fs.constants.X_OK); return p; } catch {}
|
|
88
|
-
}
|
|
89
|
-
return 'bun';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
61
|
function main() {
|
|
93
|
-
if (!isSupportedPlatform()) {
|
|
94
|
-
console.error(`Unsupported platform: ${platform}-${arch}`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const platformKey = getPlatformKey();
|
|
99
62
|
let binPath = getBinaryPath();
|
|
100
63
|
|
|
101
|
-
// Check if platform package needs update or install
|
|
102
64
|
if (!binPath) {
|
|
103
|
-
console.log('
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
} else {
|
|
107
|
-
// Check version and update if needed (optional)
|
|
108
|
-
const currentVer = getInstalledVersion();
|
|
109
|
-
const latestVer = getLatestVersion();
|
|
110
|
-
if (currentVer && latestVer && currentVer !== latestVer) {
|
|
111
|
-
console.log(`Updating to v${latestVer}...`);
|
|
112
|
-
installPlatformPackage();
|
|
65
|
+
console.log('Platform binary not found. Installing @factadev/cli-' + platformKey + '...');
|
|
66
|
+
try {
|
|
67
|
+
execSync(`npm install -g @factadev/cli-${platformKey}@latest --force`, { stdio: 'inherit' });
|
|
113
68
|
binPath = getBinaryPath();
|
|
69
|
+
} catch (e) {
|
|
70
|
+
console.error('Install failed. Try: npm install -g @factadev/cli @factadev/cli-' + platformKey + ' --force');
|
|
71
|
+
console.error('Or download from:', RELEASE_URL);
|
|
72
|
+
process.exit(1);
|
|
114
73
|
}
|
|
115
74
|
}
|
|
116
75
|
|
|
117
|
-
// Fallback to bun if no binary
|
|
118
76
|
if (!binPath) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
console.log('No pre-built binary. Using bun...\n');
|
|
122
|
-
try {
|
|
123
|
-
execFileSync(bunPath, [cliPath, ...process.argv.slice(2)], { stdio: 'inherit' });
|
|
124
|
-
return;
|
|
125
|
-
} catch (error) {
|
|
126
|
-
console.error(`Failed to run with bun: ${error.message}`);
|
|
127
|
-
process.exit(1);
|
|
128
|
-
}
|
|
77
|
+
console.error('Binary still missing. Run: npm install -g @factadev/cli @factadev/cli-' + platformKey + ' --force');
|
|
78
|
+
process.exit(1);
|
|
129
79
|
}
|
|
130
80
|
|
|
131
|
-
// Run the binary
|
|
132
81
|
try {
|
|
133
82
|
execFileSync(binPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
134
|
-
} catch (
|
|
135
|
-
process.exit(
|
|
83
|
+
} catch (e) {
|
|
84
|
+
process.exit(typeof e.status === 'number' ? e.status : 1);
|
|
136
85
|
}
|
|
137
86
|
}
|
|
138
87
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@factadev/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"description": "NEST CLI - Enterprise AI coding agent control center. Run Claude Code, Codex, Cursor, Gemini, OpenCode locally and control remotely via web.",
|
|
5
5
|
"author": "Carlos Matias Baglieri",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
@@ -15,15 +15,21 @@
|
|
|
15
15
|
"bin": {
|
|
16
16
|
"nest": "bin/nest.cjs"
|
|
17
17
|
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"postinstall": "node -e \"try{require('fs').chmodSync(require('path').join(__dirname,'bin','nest.cjs'),0o755)}catch(e){}\" && node bin/ensure-platform.cjs"
|
|
20
|
+
},
|
|
18
21
|
"files": [
|
|
19
22
|
"bin/nest.cjs",
|
|
20
|
-
"
|
|
23
|
+
"bin/ensure-platform.cjs",
|
|
24
|
+
"NOTICE",
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"README.md"
|
|
21
27
|
],
|
|
22
28
|
"optionalDependencies": {
|
|
23
|
-
"@factadev/cli-darwin-arm64": "0.2.
|
|
24
|
-
"@factadev/cli-darwin-x64": "0.2.
|
|
25
|
-
"@factadev/cli-linux-arm64": "0.2.
|
|
26
|
-
"@factadev/cli-linux-x64": "0.2.
|
|
27
|
-
"@factadev/cli-win32-x64": "0.2.
|
|
29
|
+
"@factadev/cli-darwin-arm64": "0.2.14",
|
|
30
|
+
"@factadev/cli-darwin-x64": "0.2.14",
|
|
31
|
+
"@factadev/cli-linux-arm64": "0.2.14",
|
|
32
|
+
"@factadev/cli-linux-x64": "0.2.14",
|
|
33
|
+
"@factadev/cli-win32-x64": "0.2.14"
|
|
28
34
|
}
|
|
29
35
|
}
|