kodu 3.0.1 → 3.0.2
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/kodu.js +28 -11
- package/package.json +3 -2
- package/scripts/install.js +68 -0
- package/scripts/postinstall.js +12 -59
package/bin/kodu.js
CHANGED
|
@@ -1,23 +1,40 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Thin launcher: runs the native kodu binary downloaded by postinstall.
|
|
3
|
+
// If the binary is missing (the package manager skipped the postinstall hook —
|
|
4
|
+
// bun does this by default, or `npm i --ignore-scripts` — or the download failed),
|
|
5
|
+
// it is fetched lazily from GitHub Releases on first run.
|
|
3
6
|
'use strict';
|
|
4
7
|
|
|
5
8
|
const path = require('node:path');
|
|
6
9
|
const fs = require('node:fs');
|
|
7
10
|
const { spawnSync } = require('node:child_process');
|
|
11
|
+
const { install, binNameFor, REPO } = require('../scripts/install');
|
|
8
12
|
|
|
9
|
-
const
|
|
10
|
-
const
|
|
13
|
+
const goos = process.platform === 'win32' ? 'windows' : process.platform;
|
|
14
|
+
const binName = binNameFor(goos);
|
|
15
|
+
const binDir = __dirname;
|
|
16
|
+
const binPath = path.join(binDir, binName);
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
function run() {
|
|
19
|
+
const res = spawnSync(binPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
20
|
+
if (res.error) {
|
|
21
|
+
console.error(`[kodu] ${res.error.message}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
process.exit(res.status ?? 0);
|
|
16
25
|
}
|
|
17
26
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
if (fs.existsSync(binPath)) {
|
|
28
|
+
run();
|
|
29
|
+
} else {
|
|
30
|
+
console.error('[kodu] Native binary not found, downloading it now…');
|
|
31
|
+
install(binDir)
|
|
32
|
+
.then(run)
|
|
33
|
+
.catch((err) => {
|
|
34
|
+
console.error(`[kodu] Failed to download the binary: ${err.message}`);
|
|
35
|
+
console.error('[kodu] Reinstall the package or build it from source:');
|
|
36
|
+
console.error('[kodu] go install github.com/uxname/kodu/cmd/kodu@latest');
|
|
37
|
+
console.error(`[kodu] https://github.com/${REPO}/releases`);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
});
|
|
22
40
|
}
|
|
23
|
-
process.exit(res.status ?? 0);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kodu",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "High-performance CLI to prepare a codebase for LLMs, automate reviews, and draft commits. Native Go binary.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"bin/kodu.js",
|
|
32
|
-
"scripts/postinstall.js"
|
|
32
|
+
"scripts/postinstall.js",
|
|
33
|
+
"scripts/install.js"
|
|
33
34
|
],
|
|
34
35
|
"scripts": {
|
|
35
36
|
"postinstall": "node scripts/postinstall.js"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Shared installer: downloads the native kodu binary for the current platform
|
|
2
|
+
// from GitHub Releases. Used by the postinstall hook AND by the launcher's
|
|
3
|
+
// lazy fallback (so the package works even when the package manager skipped
|
|
4
|
+
// postinstall — e.g. bun by default, or `npm i --ignore-scripts`).
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
const fs = require('node:fs');
|
|
8
|
+
const path = require('node:path');
|
|
9
|
+
const https = require('node:https');
|
|
10
|
+
const { execFileSync } = require('node:child_process');
|
|
11
|
+
|
|
12
|
+
const REPO = 'uxname/kodu';
|
|
13
|
+
const pkg = require('../package.json');
|
|
14
|
+
|
|
15
|
+
const PLATFORMS = { linux: 'linux', darwin: 'darwin', win32: 'windows' };
|
|
16
|
+
const ARCHES = { x64: 'amd64', arm64: 'arm64' };
|
|
17
|
+
|
|
18
|
+
function download(u, dest, redirects = 0) {
|
|
19
|
+
return new Promise((resolve, reject) => {
|
|
20
|
+
if (redirects > 5) return reject(new Error('too many redirects'));
|
|
21
|
+
https.get(u, (res) => {
|
|
22
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
23
|
+
res.resume();
|
|
24
|
+
return resolve(download(res.headers.location, dest, redirects + 1));
|
|
25
|
+
}
|
|
26
|
+
if (res.statusCode !== 200) {
|
|
27
|
+
res.resume();
|
|
28
|
+
return reject(new Error(`HTTP ${res.statusCode} for ${u}`));
|
|
29
|
+
}
|
|
30
|
+
const file = fs.createWriteStream(dest);
|
|
31
|
+
res.pipe(file);
|
|
32
|
+
file.on('finish', () => file.close(resolve));
|
|
33
|
+
file.on('error', reject);
|
|
34
|
+
}).on('error', reject);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Resolves the binary path for the running platform, or null if unsupported.
|
|
39
|
+
function binNameFor(goos) {
|
|
40
|
+
return goos === 'windows' ? 'kodu.exe' : 'kodu';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Downloads + extracts the native binary into binDir. Returns the absolute
|
|
44
|
+
// binary path on success; throws on any failure (caller decides how to log).
|
|
45
|
+
async function install(binDir) {
|
|
46
|
+
const goos = PLATFORMS[process.platform];
|
|
47
|
+
const goarch = ARCHES[process.arch];
|
|
48
|
+
if (!goos || !goarch) {
|
|
49
|
+
throw new Error(`Platform ${process.platform}/${process.arch} is not supported by a prebuilt binary.`);
|
|
50
|
+
}
|
|
51
|
+
const ext = goos === 'windows' ? 'zip' : 'tar.gz';
|
|
52
|
+
const binName = binNameFor(goos);
|
|
53
|
+
const asset = `kodu_v${pkg.version}_${goos}_${goarch}.${ext}`;
|
|
54
|
+
const url = `https://github.com/${REPO}/releases/download/v${pkg.version}/${asset}`;
|
|
55
|
+
|
|
56
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
57
|
+
const archivePath = path.join(binDir, asset);
|
|
58
|
+
await download(url, archivePath);
|
|
59
|
+
// bsdtar (tar) extracts both .tar.gz and .zip on Linux/macOS/Win10+.
|
|
60
|
+
execFileSync('tar', ['-xf', archivePath, '-C', binDir], { stdio: 'ignore' });
|
|
61
|
+
fs.rmSync(archivePath, { force: true });
|
|
62
|
+
const binPath = path.join(binDir, binName);
|
|
63
|
+
if (!fs.existsSync(binPath)) throw new Error('binary not found after extraction');
|
|
64
|
+
if (goos !== 'windows') fs.chmodSync(binPath, 0o755);
|
|
65
|
+
return { binPath, goos, goarch, version: pkg.version };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = { install, download, binNameFor, REPO, pkg };
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,69 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Downloads the native kodu binary for the current platform from GitHub Releases.
|
|
3
3
|
// On failure it does not break the install — it prints a hint (graceful degradation).
|
|
4
|
+
// The launcher (bin/kodu.js) will also download lazily on first run if this hook
|
|
5
|
+
// was skipped (bun) or failed, so a missing binary here is never fatal.
|
|
4
6
|
'use strict';
|
|
5
7
|
|
|
6
|
-
const fs = require('node:fs');
|
|
7
8
|
const path = require('node:path');
|
|
8
|
-
const
|
|
9
|
-
const { execFileSync } = require('node:child_process');
|
|
9
|
+
const { install, REPO } = require('./install');
|
|
10
10
|
|
|
11
|
-
const REPO = 'uxname/kodu';
|
|
12
|
-
const pkg = require('../package.json');
|
|
13
|
-
|
|
14
|
-
const PLATFORMS = { linux: 'linux', darwin: 'darwin', win32: 'windows' };
|
|
15
|
-
const ARCHES = { x64: 'amd64', arm64: 'arm64' };
|
|
16
|
-
|
|
17
|
-
function fail(msg) {
|
|
18
|
-
console.warn(`\n[kodu] ${msg}`);
|
|
19
|
-
console.warn('[kodu] Install manually: go install github.com/uxname/kodu/cmd/kodu@latest');
|
|
20
|
-
console.warn(`[kodu] or download the binary: https://github.com/${REPO}/releases\n`);
|
|
21
|
-
process.exit(0); // do not block npm install
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const goos = PLATFORMS[process.platform];
|
|
25
|
-
const goarch = ARCHES[process.arch];
|
|
26
|
-
if (!goos || !goarch) fail(`Platform ${process.platform}/${process.arch} is not supported by a prebuilt binary.`);
|
|
27
|
-
|
|
28
|
-
const ext = goos === 'windows' ? 'zip' : 'tar.gz';
|
|
29
|
-
const binName = goos === 'windows' ? 'kodu.exe' : 'kodu';
|
|
30
|
-
const asset = `kodu_v${pkg.version}_${goos}_${goarch}.${ext}`;
|
|
31
|
-
const url = `https://github.com/${REPO}/releases/download/v${pkg.version}/${asset}`;
|
|
32
11
|
const binDir = path.join(__dirname, '..', 'bin');
|
|
33
12
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
res.resume();
|
|
44
|
-
return reject(new Error(`HTTP ${res.statusCode} for ${u}`));
|
|
45
|
-
}
|
|
46
|
-
const file = fs.createWriteStream(dest);
|
|
47
|
-
res.pipe(file);
|
|
48
|
-
file.on('finish', () => file.close(resolve));
|
|
49
|
-
file.on('error', reject);
|
|
50
|
-
}).on('error', reject);
|
|
13
|
+
install(binDir)
|
|
14
|
+
.then(({ goos, goarch, version }) =>
|
|
15
|
+
console.log(`[kodu] Installed binary ${goos}/${goarch} v${version}`))
|
|
16
|
+
.catch((err) => {
|
|
17
|
+
console.warn(`\n[kodu] Failed to download the binary: ${err.message}`);
|
|
18
|
+
console.warn('[kodu] It will be downloaded automatically on first run, or install manually:');
|
|
19
|
+
console.warn('[kodu] go install github.com/uxname/kodu/cmd/kodu@latest');
|
|
20
|
+
console.warn(`[kodu] https://github.com/${REPO}/releases\n`);
|
|
21
|
+
process.exit(0); // do not block npm install
|
|
51
22
|
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
(async () => {
|
|
55
|
-
try {
|
|
56
|
-
fs.mkdirSync(binDir, { recursive: true });
|
|
57
|
-
const archivePath = path.join(binDir, asset);
|
|
58
|
-
await download(url, archivePath);
|
|
59
|
-
// bsdtar (tar) extracts both .tar.gz and .zip on Linux/macOS/Win10+.
|
|
60
|
-
execFileSync('tar', ['-xf', archivePath, '-C', binDir], { stdio: 'ignore' });
|
|
61
|
-
fs.rmSync(archivePath, { force: true });
|
|
62
|
-
const binPath = path.join(binDir, binName);
|
|
63
|
-
if (!fs.existsSync(binPath)) throw new Error('binary not found after extraction');
|
|
64
|
-
if (goos !== 'windows') fs.chmodSync(binPath, 0o755);
|
|
65
|
-
console.log(`[kodu] Installed binary ${goos}/${goarch} v${pkg.version}`);
|
|
66
|
-
} catch (err) {
|
|
67
|
-
fail(`Failed to download the binary: ${err.message}`);
|
|
68
|
-
}
|
|
69
|
-
})();
|