@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.
@@ -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
- function getPlatformKey(p = platform, a = arch) {
19
- return `${p}-${a}`;
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 isSupportedPlatform(p = platform, a = arch) {
23
- return SUPPORTED_PLATFORMS.some(item => item.key === getPlatformKey(p, a));
24
- }
19
+ function getBinaryPath() {
20
+ const mainRoot = path.resolve(__dirname, '..');
25
21
 
26
- function getBinaryPath(platformName = platform, archName = arch) {
27
- const pkgName = `@factadev/cli-${platformName}-${archName}`;
28
- const binName = platformName === 'win32' ? 'nest.exe' : 'nest';
29
-
30
- // Try multiple locations where the package might be installed
31
- const possiblePaths = [
32
- // 1. Top-level node_modules (if installed separately)
33
- path.join(__dirname, '..', '..', pkgName, 'bin', binName),
34
- // 2. Inside @factadev/cli/node_modules (if installed as optional dep)
35
- path.join(__dirname, '..', 'node_modules', pkgName, 'bin', binName),
36
- // 3. Global node_modules
37
- path.join(process.env.PREFIX || '/usr/local', 'lib', 'node_modules', pkgName, 'bin', binName),
38
- ];
39
-
40
- for (const binPath of possiblePaths) {
41
- if (fs.existsSync(binPath)) {
42
- return binPath;
43
- }
44
- }
45
-
46
- return null;
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
- function installPlatformPackage(platformName = platform, archName = arch) {
50
- const pkgName = `@factadev/cli-${platformName}-${archName}`;
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('No platform binary found. Installing...');
104
- installPlatformPackage();
105
- binPath = getBinaryPath();
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
- const bunPath = getBunPath();
120
- const cliPath = path.join(__dirname, '..', 'src', 'index.ts');
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 (error) {
135
- process.exit(error.status || 1);
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.13",
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
- "NOTICE"
23
+ "bin/ensure-platform.cjs",
24
+ "NOTICE",
25
+ "LICENSE",
26
+ "README.md"
21
27
  ],
22
28
  "optionalDependencies": {
23
- "@factadev/cli-darwin-arm64": "0.2.10",
24
- "@factadev/cli-darwin-x64": "0.2.10",
25
- "@factadev/cli-linux-arm64": "0.2.10",
26
- "@factadev/cli-linux-x64": "0.2.10",
27
- "@factadev/cli-win32-x64": "0.2.10"
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
  }