@kandiforge/spectacle 0.2.1
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/kandi-gpt +25 -0
- package/bin/kandi-plan +25 -0
- package/bin/spectacle +25 -0
- package/bin/spectacle-bin +0 -0
- package/package.json +41 -0
- package/scripts/install.js +147 -0
package/bin/kandi-gpt
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Determine binary name based on platform
|
|
7
|
+
const binaryName = process.platform === 'win32' ? 'kandi-gpt-bin.exe' : 'kandi-gpt-bin';
|
|
8
|
+
const binaryPath = path.join(__dirname, binaryName);
|
|
9
|
+
|
|
10
|
+
// Spawn the binary with all arguments
|
|
11
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
12
|
+
stdio: 'inherit',
|
|
13
|
+
env: process.env
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Forward exit code
|
|
17
|
+
child.on('exit', (code) => {
|
|
18
|
+
process.exit(code || 0);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Handle errors
|
|
22
|
+
child.on('error', (err) => {
|
|
23
|
+
console.error('Failed to start kandi-gpt binary:', err.message);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
package/bin/kandi-plan
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Determine binary name based on platform
|
|
7
|
+
const binaryName = process.platform === 'win32' ? 'kandi-plan-bin.exe' : 'kandi-plan-bin';
|
|
8
|
+
const binaryPath = path.join(__dirname, binaryName);
|
|
9
|
+
|
|
10
|
+
// Spawn the binary with all arguments
|
|
11
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
12
|
+
stdio: 'inherit',
|
|
13
|
+
env: process.env
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Forward exit code
|
|
17
|
+
child.on('exit', (code) => {
|
|
18
|
+
process.exit(code || 0);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Handle errors
|
|
22
|
+
child.on('error', (err) => {
|
|
23
|
+
console.error('Failed to start kandi-plan binary:', err.message);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
package/bin/spectacle
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Determine binary name based on platform
|
|
7
|
+
const binaryName = process.platform === 'win32' ? 'spectacle-bin.exe' : 'spectacle-bin';
|
|
8
|
+
const binaryPath = path.join(__dirname, binaryName);
|
|
9
|
+
|
|
10
|
+
// Spawn the binary with all arguments
|
|
11
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
12
|
+
stdio: 'inherit',
|
|
13
|
+
env: process.env
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// Forward exit code
|
|
17
|
+
child.on('exit', (code) => {
|
|
18
|
+
process.exit(code || 0);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Handle errors
|
|
22
|
+
child.on('error', (err) => {
|
|
23
|
+
console.error('Failed to start spectacle binary:', err.message);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kandiforge/spectacle",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Spectacle server and CLI tools for KandiForge ecosystem",
|
|
5
|
+
"author": "Abstract Class Consulting Inc.",
|
|
6
|
+
"license": "PROPRIETARY",
|
|
7
|
+
"homepage": "https://github.com/KandiForge/apps",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/KandiForge/apps.git",
|
|
11
|
+
"directory": "spectacle"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/KandiForge/apps/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"spectacle",
|
|
18
|
+
"server",
|
|
19
|
+
"cli",
|
|
20
|
+
"kandiforge",
|
|
21
|
+
"development"
|
|
22
|
+
],
|
|
23
|
+
"bin": {
|
|
24
|
+
"spectacle": "./bin/spectacle",
|
|
25
|
+
"kandi-plan": "./bin/kandi-plan",
|
|
26
|
+
"kandi-gpt": "./bin/kandi-gpt"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"postinstall": "node scripts/install.js",
|
|
30
|
+
"test": "echo \"No tests configured\""
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"bin/",
|
|
34
|
+
"scripts/",
|
|
35
|
+
"README.md",
|
|
36
|
+
"LICENSE"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=14.0.0"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const https = require('https');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
// This version MUST match package.json
|
|
9
|
+
const RELEASE_VERSION = '0.2.1';
|
|
10
|
+
const GITHUB_REPO = 'KandiForge/distribution';
|
|
11
|
+
|
|
12
|
+
function downloadFile(url, destPath) {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
console.log(`Downloading from: ${url}`);
|
|
15
|
+
|
|
16
|
+
https.get(url, (response) => {
|
|
17
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
18
|
+
// Follow redirect
|
|
19
|
+
return downloadFile(response.headers.location, destPath)
|
|
20
|
+
.then(resolve)
|
|
21
|
+
.catch(reject);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (response.statusCode !== 200) {
|
|
25
|
+
reject(new Error(`Failed to download: ${response.statusCode} ${response.statusMessage}`));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const file = fs.createWriteStream(destPath);
|
|
30
|
+
response.pipe(file);
|
|
31
|
+
|
|
32
|
+
file.on('finish', () => {
|
|
33
|
+
file.close();
|
|
34
|
+
resolve();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
file.on('error', (err) => {
|
|
38
|
+
fs.unlink(destPath, () => {});
|
|
39
|
+
reject(err);
|
|
40
|
+
});
|
|
41
|
+
}).on('error', reject);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function install() {
|
|
46
|
+
try {
|
|
47
|
+
const platform = process.platform;
|
|
48
|
+
const arch = process.arch;
|
|
49
|
+
|
|
50
|
+
// Determine file name based on platform
|
|
51
|
+
let fileName, extractCmd;
|
|
52
|
+
const binaries = platform === 'win32'
|
|
53
|
+
? ['spectacle.exe', 'kandi-plan.exe', 'kandi-gpt.exe']
|
|
54
|
+
: ['spectacle', 'kandi-plan', 'kandi-gpt'];
|
|
55
|
+
|
|
56
|
+
if (platform === 'darwin') {
|
|
57
|
+
fileName = `spectacle-v${RELEASE_VERSION}-macos-universal.tar.gz`;
|
|
58
|
+
extractCmd = `tar -xzf`;
|
|
59
|
+
} else if (platform === 'linux') {
|
|
60
|
+
fileName = `spectacle-v${RELEASE_VERSION}-linux-x64.tar.gz`;
|
|
61
|
+
extractCmd = `tar -xzf`;
|
|
62
|
+
} else if (platform === 'win32') {
|
|
63
|
+
fileName = `spectacle-v${RELEASE_VERSION}-windows-x64.zip`;
|
|
64
|
+
extractCmd = `unzip -o`;
|
|
65
|
+
} else {
|
|
66
|
+
throw new Error(`Platform ${platform} is not supported. Supported: macOS, Linux, Windows`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Download URL from GitHub release assets (public even for private repos)
|
|
70
|
+
const downloadUrl = `https://github.com/${GITHUB_REPO}/releases/download/spectacle-v${RELEASE_VERSION}/${fileName}`;
|
|
71
|
+
|
|
72
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
73
|
+
const tempFile = path.join(binDir, fileName);
|
|
74
|
+
|
|
75
|
+
// Create bin directory if it doesn't exist
|
|
76
|
+
if (!fs.existsSync(binDir)) {
|
|
77
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Download the release archive
|
|
81
|
+
console.log(`Installing Spectacle v${RELEASE_VERSION} for ${platform} ${arch}...`);
|
|
82
|
+
await downloadFile(downloadUrl, tempFile);
|
|
83
|
+
|
|
84
|
+
// Extract the binary
|
|
85
|
+
console.log('Extracting binary...');
|
|
86
|
+
// Use appropriate flag based on archive type: -C for tar, -d for unzip
|
|
87
|
+
const destFlag = platform === 'win32' ? '-d' : '-C';
|
|
88
|
+
execSync(`${extractCmd} "${tempFile}" ${destFlag} "${binDir}"`, { stdio: 'inherit' });
|
|
89
|
+
|
|
90
|
+
// Clean up archive
|
|
91
|
+
fs.unlinkSync(tempFile);
|
|
92
|
+
|
|
93
|
+
// The archive extracts to spectacle-v{version}/[spectacle, kandi-plan, kandi-gpt][.exe]
|
|
94
|
+
const extractedDir = path.join(binDir, `spectacle-v${RELEASE_VERSION}`);
|
|
95
|
+
|
|
96
|
+
// Move all binaries to the correct location
|
|
97
|
+
const installedBinaries = [];
|
|
98
|
+
for (const binaryName of binaries) {
|
|
99
|
+
const extractedPath = path.join(extractedDir, binaryName);
|
|
100
|
+
|
|
101
|
+
// Determine destination name: spectacle -> spectacle-bin, kandi-plan -> kandi-plan-bin, kandi-gpt -> kandi-gpt-bin
|
|
102
|
+
const baseName = binaryName.replace('.exe', '');
|
|
103
|
+
const destName = `${baseName}-bin${platform === 'win32' ? '.exe' : ''}`;
|
|
104
|
+
const binaryPath = path.join(binDir, destName);
|
|
105
|
+
|
|
106
|
+
if (fs.existsSync(extractedPath)) {
|
|
107
|
+
fs.renameSync(extractedPath, binaryPath);
|
|
108
|
+
|
|
109
|
+
// Make binary executable (Unix only)
|
|
110
|
+
if (platform !== 'win32') {
|
|
111
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
installedBinaries.push({ name: baseName, path: binaryPath });
|
|
115
|
+
} else {
|
|
116
|
+
console.warn(`⚠️ Warning: ${binaryName} not found in archive at ${extractedPath}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Clean up the extracted directory
|
|
121
|
+
if (fs.existsSync(extractedDir)) {
|
|
122
|
+
fs.rmdirSync(extractedDir, { recursive: true });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (installedBinaries.length === 0) {
|
|
126
|
+
throw new Error('No binaries were found in the archive');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log('✅ Spectacle installed successfully!');
|
|
130
|
+
console.log('\nInstalled binaries:');
|
|
131
|
+
for (const binary of installedBinaries) {
|
|
132
|
+
console.log(` - ${binary.name}: ${binary.path}`);
|
|
133
|
+
}
|
|
134
|
+
console.log('\nTo get started, run:');
|
|
135
|
+
console.log(' spectacle --help');
|
|
136
|
+
console.log(' kandi-plan --help');
|
|
137
|
+
console.log(' kandi-gpt --help');
|
|
138
|
+
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error('❌ Installation failed:', error.message);
|
|
141
|
+
console.error('\nPlease report this issue at: https://github.com/KandiForge/apps/issues');
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Run installation
|
|
147
|
+
install();
|