@altairalabs/packc 1.1.6 → 1.1.7
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/lib/installer.js +110 -0
- package/lib/installer.test.js +121 -0
- package/package.json +10 -2
- package/postinstall.js +13 -125
package/lib/installer.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import https from 'node:https';
|
|
2
|
+
import http from 'node:http';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { execSync } from 'node:child_process';
|
|
6
|
+
import { pipeline } from 'node:stream';
|
|
7
|
+
import { promisify } from 'node:util';
|
|
8
|
+
|
|
9
|
+
const streamPipeline = promisify(pipeline);
|
|
10
|
+
|
|
11
|
+
// Platform mapping to match GoReleaser output
|
|
12
|
+
export const PLATFORM_MAP = {
|
|
13
|
+
darwin: 'Darwin',
|
|
14
|
+
linux: 'Linux',
|
|
15
|
+
win32: 'Windows'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const ARCH_MAP = {
|
|
19
|
+
x64: 'x86_64',
|
|
20
|
+
arm64: 'arm64'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export function getPlatformInfo(platform = process.platform, arch = process.arch) {
|
|
24
|
+
const mappedPlatform = PLATFORM_MAP[platform];
|
|
25
|
+
const mappedArch = ARCH_MAP[arch];
|
|
26
|
+
|
|
27
|
+
if (!mappedPlatform || !mappedArch) {
|
|
28
|
+
throw new Error(`Unsupported platform: ${platform}-${arch}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return { platform: mappedPlatform, arch: mappedArch };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function getDownloadUrl(version, platform, arch, repo = 'AltairaLabs/PromptKit') {
|
|
35
|
+
const archiveExt = platform === 'Windows' ? 'zip' : 'tar.gz';
|
|
36
|
+
const archiveName = `PromptKit_${version}_${platform}_${arch}.${archiveExt}`;
|
|
37
|
+
return `https://github.com/${repo}/releases/download/v${version}/${archiveName}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function downloadFile(url, destPath) {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const client = url.startsWith('https:') ? https : http;
|
|
43
|
+
|
|
44
|
+
client.get(url, (response) => {
|
|
45
|
+
// Follow redirects
|
|
46
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
47
|
+
downloadFile(response.headers.location, destPath)
|
|
48
|
+
.then(resolve)
|
|
49
|
+
.catch(reject);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (response.statusCode !== 200) {
|
|
54
|
+
reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
59
|
+
streamPipeline(response, fileStream)
|
|
60
|
+
.then(resolve)
|
|
61
|
+
.catch(reject);
|
|
62
|
+
}).on('error', reject);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function extractBinary(archivePath, platform, binaryName, destDir) {
|
|
67
|
+
const binaryWithExt = platform === 'Windows' ? `${binaryName}.exe` : binaryName;
|
|
68
|
+
const destPath = path.join(destDir, binaryWithExt);
|
|
69
|
+
|
|
70
|
+
if (platform === 'Windows') {
|
|
71
|
+
execSync(`unzip -j "${archivePath}" "${binaryWithExt}" -d "${destDir}"`, {
|
|
72
|
+
stdio: 'inherit'
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
execSync(`tar -xzf "${archivePath}" -C "${destDir}" "${binaryWithExt}"`, {
|
|
76
|
+
stdio: 'inherit'
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Make executable on Unix-like systems
|
|
81
|
+
if (platform !== 'Windows') {
|
|
82
|
+
fs.chmodSync(destPath, 0o755);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return destPath;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function install(binaryName, version, baseDir) {
|
|
89
|
+
console.log(`Installing ${binaryName} v${version}...`);
|
|
90
|
+
|
|
91
|
+
const { platform, arch } = getPlatformInfo();
|
|
92
|
+
console.log(`Platform: ${platform} ${arch}`);
|
|
93
|
+
|
|
94
|
+
const url = getDownloadUrl(version, platform, arch);
|
|
95
|
+
const archiveExt = platform === 'Windows' ? 'zip' : 'tar.gz';
|
|
96
|
+
const archivePath = path.join(baseDir, `archive.${archiveExt}`);
|
|
97
|
+
|
|
98
|
+
console.log('Downloading binary from GitHub Releases...');
|
|
99
|
+
await downloadFile(url, archivePath);
|
|
100
|
+
console.log('✓ Download complete');
|
|
101
|
+
|
|
102
|
+
console.log('Extracting binary...');
|
|
103
|
+
extractBinary(archivePath, platform, binaryName, baseDir);
|
|
104
|
+
console.log(`✓ Extracted ${binaryName}`);
|
|
105
|
+
|
|
106
|
+
// Clean up archive
|
|
107
|
+
fs.unlinkSync(archivePath);
|
|
108
|
+
|
|
109
|
+
console.log(`✓ ${binaryName} installed successfully!`);
|
|
110
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getPlatformInfo,
|
|
3
|
+
getDownloadUrl,
|
|
4
|
+
PLATFORM_MAP,
|
|
5
|
+
ARCH_MAP
|
|
6
|
+
} from './installer.js';
|
|
7
|
+
|
|
8
|
+
describe('installer', () => {
|
|
9
|
+
describe('PLATFORM_MAP', () => {
|
|
10
|
+
it('should map darwin to Darwin', () => {
|
|
11
|
+
expect(PLATFORM_MAP.darwin).toBe('Darwin');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should map linux to Linux', () => {
|
|
15
|
+
expect(PLATFORM_MAP.linux).toBe('Linux');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should map win32 to Windows', () => {
|
|
19
|
+
expect(PLATFORM_MAP.win32).toBe('Windows');
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('ARCH_MAP', () => {
|
|
24
|
+
it('should map x64 to x86_64', () => {
|
|
25
|
+
expect(ARCH_MAP.x64).toBe('x86_64');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should map arm64 to arm64', () => {
|
|
29
|
+
expect(ARCH_MAP.arm64).toBe('arm64');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('getPlatformInfo', () => {
|
|
34
|
+
it('should return mapped platform and arch for darwin x64', () => {
|
|
35
|
+
const result = getPlatformInfo('darwin', 'x64');
|
|
36
|
+
expect(result).toEqual({ platform: 'Darwin', arch: 'x86_64' });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should return mapped platform and arch for darwin arm64', () => {
|
|
40
|
+
const result = getPlatformInfo('darwin', 'arm64');
|
|
41
|
+
expect(result).toEqual({ platform: 'Darwin', arch: 'arm64' });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should return mapped platform and arch for linux x64', () => {
|
|
45
|
+
const result = getPlatformInfo('linux', 'x64');
|
|
46
|
+
expect(result).toEqual({ platform: 'Linux', arch: 'x86_64' });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should return mapped platform and arch for linux arm64', () => {
|
|
50
|
+
const result = getPlatformInfo('linux', 'arm64');
|
|
51
|
+
expect(result).toEqual({ platform: 'Linux', arch: 'arm64' });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should return mapped platform and arch for win32 x64', () => {
|
|
55
|
+
const result = getPlatformInfo('win32', 'x64');
|
|
56
|
+
expect(result).toEqual({ platform: 'Windows', arch: 'x86_64' });
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should throw error for unsupported platform', () => {
|
|
60
|
+
expect(() => getPlatformInfo('freebsd', 'x64')).toThrow(
|
|
61
|
+
'Unsupported platform: freebsd-x64'
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should throw error for unsupported arch', () => {
|
|
66
|
+
expect(() => getPlatformInfo('darwin', 'ia32')).toThrow(
|
|
67
|
+
'Unsupported platform: darwin-ia32'
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should throw error for unsupported platform and arch', () => {
|
|
72
|
+
expect(() => getPlatformInfo('aix', 'ppc64')).toThrow(
|
|
73
|
+
'Unsupported platform: aix-ppc64'
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('getDownloadUrl', () => {
|
|
79
|
+
it('should generate correct URL for Darwin x86_64', () => {
|
|
80
|
+
const url = getDownloadUrl('1.0.0', 'Darwin', 'x86_64');
|
|
81
|
+
expect(url).toBe(
|
|
82
|
+
'https://github.com/AltairaLabs/PromptKit/releases/download/v1.0.0/PromptKit_1.0.0_Darwin_x86_64.tar.gz'
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should generate correct URL for Darwin arm64', () => {
|
|
87
|
+
const url = getDownloadUrl('1.0.0', 'Darwin', 'arm64');
|
|
88
|
+
expect(url).toBe(
|
|
89
|
+
'https://github.com/AltairaLabs/PromptKit/releases/download/v1.0.0/PromptKit_1.0.0_Darwin_arm64.tar.gz'
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('should generate correct URL for Linux x86_64', () => {
|
|
94
|
+
const url = getDownloadUrl('2.1.0', 'Linux', 'x86_64');
|
|
95
|
+
expect(url).toBe(
|
|
96
|
+
'https://github.com/AltairaLabs/PromptKit/releases/download/v2.1.0/PromptKit_2.1.0_Linux_x86_64.tar.gz'
|
|
97
|
+
);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('should generate correct URL for Windows (zip extension)', () => {
|
|
101
|
+
const url = getDownloadUrl('1.0.0', 'Windows', 'x86_64');
|
|
102
|
+
expect(url).toBe(
|
|
103
|
+
'https://github.com/AltairaLabs/PromptKit/releases/download/v1.0.0/PromptKit_1.0.0_Windows_x86_64.zip'
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should use custom repository when provided', () => {
|
|
108
|
+
const url = getDownloadUrl('1.0.0', 'Darwin', 'x86_64', 'MyOrg/MyRepo');
|
|
109
|
+
expect(url).toBe(
|
|
110
|
+
'https://github.com/MyOrg/MyRepo/releases/download/v1.0.0/PromptKit_1.0.0_Darwin_x86_64.tar.gz'
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should handle prerelease versions', () => {
|
|
115
|
+
const url = getDownloadUrl('1.0.0-beta.1', 'Linux', 'arm64');
|
|
116
|
+
expect(url).toBe(
|
|
117
|
+
'https://github.com/AltairaLabs/PromptKit/releases/download/v1.0.0-beta.1/PromptKit_1.0.0-beta.1_Linux_arm64.tar.gz'
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@altairalabs/packc",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "PromptKit Pack Compiler - Compile and validate prompt packs for LLM applications",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,14 @@
|
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"postinstall": "node postinstall.js",
|
|
11
|
-
"test": "node bin/
|
|
11
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage",
|
|
12
|
+
"test:ci": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage --ci",
|
|
13
|
+
"test:binary": "node bin/packc.js version",
|
|
14
|
+
"lint": "eslint *.js bin/*.js lib/*.js"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"eslint": "^8.55.0",
|
|
18
|
+
"jest": "^29.7.0"
|
|
12
19
|
},
|
|
13
20
|
"keywords": [
|
|
14
21
|
"llm",
|
|
@@ -47,6 +54,7 @@
|
|
|
47
54
|
],
|
|
48
55
|
"files": [
|
|
49
56
|
"bin/",
|
|
57
|
+
"lib/",
|
|
50
58
|
"postinstall.js",
|
|
51
59
|
"README.md"
|
|
52
60
|
]
|
package/postinstall.js
CHANGED
|
@@ -1,140 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import https from 'node:https';
|
|
4
|
-
import http from 'node:http';
|
|
5
|
-
import fs from 'node:fs';
|
|
6
3
|
import path from 'node:path';
|
|
7
|
-
import { execSync } from 'node:child_process';
|
|
8
|
-
import { pipeline } from 'node:stream';
|
|
9
|
-
import { promisify } from 'node:util';
|
|
10
4
|
import { fileURLToPath } from 'node:url';
|
|
11
5
|
import { createRequire } from 'node:module';
|
|
6
|
+
import { install, getDownloadUrl, getPlatformInfo } from './lib/installer.js';
|
|
12
7
|
|
|
13
8
|
const require = createRequire(import.meta.url);
|
|
14
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
10
|
const __dirname = path.dirname(__filename);
|
|
16
11
|
|
|
17
|
-
const streamPipeline = promisify(pipeline);
|
|
18
|
-
|
|
19
12
|
const BINARY_NAME = 'packc';
|
|
20
|
-
const GITHUB_REPO = 'AltairaLabs/PromptKit';
|
|
21
13
|
const VERSION = require('./package.json').version;
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
linux: 'Linux',
|
|
27
|
-
win32: 'Windows'
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const ARCH_MAP = {
|
|
31
|
-
x64: 'x86_64',
|
|
32
|
-
arm64: 'arm64'
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
function getPlatformInfo() {
|
|
36
|
-
const platform = PLATFORM_MAP[process.platform];
|
|
37
|
-
const arch = ARCH_MAP[process.arch];
|
|
38
|
-
|
|
39
|
-
if (!platform || !arch) {
|
|
40
|
-
throw new Error(`Unsupported platform: ${process.platform}-${process.arch}`);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return { platform, arch };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function getDownloadUrl(platform, arch) {
|
|
47
|
-
const archiveExt = platform === 'Windows' ? 'zip' : 'tar.gz';
|
|
48
|
-
const archiveName = `PromptKit_${VERSION}_${platform}_${arch}.${archiveExt}`;
|
|
49
|
-
return `https://github.com/${GITHUB_REPO}/releases/download/v${VERSION}/${archiveName}`;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async function downloadFile(url, destPath) {
|
|
53
|
-
return new Promise((resolve, reject) => {
|
|
54
|
-
const client = url.startsWith('https:') ? https : http;
|
|
55
|
-
|
|
56
|
-
client.get(url, (response) => {
|
|
57
|
-
// Follow redirects
|
|
58
|
-
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
59
|
-
downloadFile(response.headers.location, destPath)
|
|
60
|
-
.then(resolve)
|
|
61
|
-
.catch(reject);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (response.statusCode !== 200) {
|
|
66
|
-
reject(new Error(`Failed to download: HTTP ${response.statusCode}`));
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const fileStream = fs.createWriteStream(destPath);
|
|
71
|
-
streamPipeline(response, fileStream)
|
|
72
|
-
.then(resolve)
|
|
73
|
-
.catch(reject);
|
|
74
|
-
}).on('error', reject);
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function extractBinary(archivePath, platform, binaryName) {
|
|
79
|
-
const binaryWithExt = platform === 'Windows' ? `${binaryName}.exe` : binaryName;
|
|
80
|
-
const destPath = path.join(__dirname, binaryWithExt);
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
if (platform === 'Windows') {
|
|
84
|
-
// Extract from zip - the binary should be in the archive root
|
|
85
|
-
execSync(`unzip -j "${archivePath}" "${binaryWithExt}" -d "${__dirname}"`, {
|
|
86
|
-
stdio: 'inherit'
|
|
87
|
-
});
|
|
88
|
-
} else {
|
|
89
|
-
// Extract from tar.gz - the binary should be in the archive root
|
|
90
|
-
execSync(`tar -xzf "${archivePath}" -C "${__dirname}" "${binaryWithExt}"`, {
|
|
91
|
-
stdio: 'inherit'
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Make executable on Unix-like systems
|
|
96
|
-
if (platform !== 'Windows') {
|
|
97
|
-
fs.chmodSync(destPath, 0o755);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
console.log(`✓ Extracted ${binaryWithExt}`);
|
|
101
|
-
return destPath;
|
|
102
|
-
} catch (error) {
|
|
103
|
-
throw new Error(`Failed to extract binary: ${error.message}`);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function install() {
|
|
108
|
-
console.log(`Installing ${BINARY_NAME} v${VERSION}...`);
|
|
109
|
-
|
|
15
|
+
try {
|
|
16
|
+
await install(BINARY_NAME, VERSION, __dirname);
|
|
17
|
+
} catch (error) {
|
|
110
18
|
const { platform, arch } = getPlatformInfo();
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
console.log('✓ Download complete');
|
|
121
|
-
|
|
122
|
-
console.log('Extracting binary...');
|
|
123
|
-
extractBinary(archivePath, platform, BINARY_NAME);
|
|
124
|
-
|
|
125
|
-
// Clean up archive
|
|
126
|
-
fs.unlinkSync(archivePath);
|
|
127
|
-
|
|
128
|
-
console.log(`✓ ${BINARY_NAME} installed successfully!`);
|
|
129
|
-
} catch (error) {
|
|
130
|
-
console.error(`\n❌ Installation failed: ${error.message}`);
|
|
131
|
-
console.error('\nTroubleshooting:');
|
|
132
|
-
console.error('1. Verify version exists: https://github.com/AltairaLabs/PromptKit/releases');
|
|
133
|
-
console.error('2. Check your internet connection');
|
|
134
|
-
console.error('3. Try downloading manually from GitHub Releases');
|
|
135
|
-
console.error(` URL: ${url}`);
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
19
|
+
const url = getDownloadUrl(VERSION, platform, arch);
|
|
20
|
+
|
|
21
|
+
console.error(`\n❌ Installation failed: ${error.message}`);
|
|
22
|
+
console.error('\nTroubleshooting:');
|
|
23
|
+
console.error('1. Verify version exists: https://github.com/AltairaLabs/PromptKit/releases');
|
|
24
|
+
console.error('2. Check your internet connection');
|
|
25
|
+
console.error('3. Try downloading manually from GitHub Releases');
|
|
26
|
+
console.error(` URL: ${url}`);
|
|
27
|
+
process.exit(1);
|
|
138
28
|
}
|
|
139
|
-
|
|
140
|
-
await install();
|