@kairainy/ck 0.1.0
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/README.md +30 -0
- package/bin/ck.js +33 -0
- package/package.json +31 -0
- package/scripts/postinstall.js +162 -0
package/README.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# `@kairainy/ck`
|
|
2
|
+
|
|
3
|
+
npm wrapper cho binary **`ck`** (Code Knowledge Graph CLI).
|
|
4
|
+
Scope npm: org **`kairainy`** (không phải `@codeknowledge` — org đó chưa có trên npm).
|
|
5
|
+
|
|
6
|
+
## Cài đặt
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm i -g @kairainy/ck
|
|
10
|
+
ck --help
|
|
11
|
+
ck --version
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Khi chưa có release trên host:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# từ Individual/code-knowledge
|
|
18
|
+
cargo build -p code-knowledge --release
|
|
19
|
+
CK_CLI_USE_LOCAL=1 npm i -g ./packaging/npm/@codeknowledge/cli
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Env
|
|
23
|
+
|
|
24
|
+
| Biến | Mô tả |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `CK_CLI_USE_LOCAL=1` | Copy `target/release/ck(.exe)` từ monorepo |
|
|
27
|
+
| `CK_RELEASE_BASE` | Base URL kiểu `…/releases` |
|
|
28
|
+
| `CK_CLI_BINARY_URL` | URL archive đầy đủ |
|
|
29
|
+
|
|
30
|
+
Chi tiết: [docs/install/cli.md](../../../../docs/install/cli.md).
|
package/bin/ck.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Thin launcher: runs platform binary next to this file (installed by postinstall).
|
|
6
|
+
*/
|
|
7
|
+
const { spawn } = require("node:child_process");
|
|
8
|
+
const fs = require("node:fs");
|
|
9
|
+
const path = require("node:path");
|
|
10
|
+
|
|
11
|
+
const isWin = process.platform === "win32";
|
|
12
|
+
const binName = isWin ? "ck.exe" : "ck";
|
|
13
|
+
const binPath = path.join(__dirname, binName);
|
|
14
|
+
|
|
15
|
+
if (!fs.existsSync(binPath)) {
|
|
16
|
+
console.error(
|
|
17
|
+
`[ck] Binary missing at ${binPath}. Re-run: npm i -g @kairainy/ck\n` +
|
|
18
|
+
`Or for local dev: CK_CLI_USE_LOCAL=1 npm i -g ./packaging/npm/@codeknowledge/cli`
|
|
19
|
+
);
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const child = spawn(binPath, process.argv.slice(2), {
|
|
24
|
+
stdio: "inherit",
|
|
25
|
+
windowsHide: true,
|
|
26
|
+
});
|
|
27
|
+
child.on("exit", (code, signal) => {
|
|
28
|
+
if (signal) {
|
|
29
|
+
process.kill(process.pid, signal);
|
|
30
|
+
} else {
|
|
31
|
+
process.exit(code ?? 1);
|
|
32
|
+
}
|
|
33
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kairainy/ck",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "npm wrapper for the Code Knowledge Graph CLI (ck)",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ck": "bin/ck.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"scripts/",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"postinstall": "node scripts/postinstall.js"
|
|
16
|
+
},
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=18"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://codeknowledge.io.vn"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"code-knowledge",
|
|
26
|
+
"ck",
|
|
27
|
+
"cli",
|
|
28
|
+
"mcp",
|
|
29
|
+
"kairainy"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Download (or copy local) `ck` binary for this platform into bin/.
|
|
5
|
+
*
|
|
6
|
+
* Env:
|
|
7
|
+
* CK_CLI_USE_LOCAL=1 — copy from repo target/release (dev)
|
|
8
|
+
* CK_RELEASE_BASE — release base URL (GitHub-style .../releases)
|
|
9
|
+
* CK_CLI_BINARY_URL — full URL override for the archive
|
|
10
|
+
*/
|
|
11
|
+
const fs = require("node:fs");
|
|
12
|
+
const path = require("node:path");
|
|
13
|
+
const https = require("node:https");
|
|
14
|
+
const http = require("node:http");
|
|
15
|
+
const { execFileSync } = require("node:child_process");
|
|
16
|
+
const { createWriteStream } = require("node:fs");
|
|
17
|
+
const { pipeline } = require("node:stream/promises");
|
|
18
|
+
|
|
19
|
+
const pkg = require("../package.json");
|
|
20
|
+
const version = pkg.version;
|
|
21
|
+
const binDir = path.join(__dirname, "..", "bin");
|
|
22
|
+
const isWin = process.platform === "win32";
|
|
23
|
+
const binName = isWin ? "ck.exe" : "ck";
|
|
24
|
+
const dest = path.join(binDir, binName);
|
|
25
|
+
|
|
26
|
+
function rustTarget() {
|
|
27
|
+
const plat = process.platform;
|
|
28
|
+
const arch = process.arch;
|
|
29
|
+
let rustArch;
|
|
30
|
+
if (arch === "x64") rustArch = "x86_64";
|
|
31
|
+
else if (arch === "arm64") rustArch = "aarch64";
|
|
32
|
+
else throw new Error(`Unsupported arch: ${arch}`);
|
|
33
|
+
|
|
34
|
+
if (plat === "win32") return `${rustArch}-pc-windows-msvc`;
|
|
35
|
+
if (plat === "darwin") return `${rustArch}-apple-darwin`;
|
|
36
|
+
if (plat === "linux") return `${rustArch}-unknown-linux-gnu`;
|
|
37
|
+
throw new Error(`Unsupported platform: ${plat}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function findRepoRoot() {
|
|
41
|
+
// packaging/npm/@codeknowledge/cli/scripts → repo root = 5 levels up
|
|
42
|
+
return path.resolve(__dirname, "..", "..", "..", "..", "..");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function copyLocal() {
|
|
46
|
+
const root = findRepoRoot();
|
|
47
|
+
const local = path.join(root, "target", "release", binName);
|
|
48
|
+
if (!fs.existsSync(local)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`CK_CLI_USE_LOCAL=1 but missing ${local}. Run: cargo build -p code-knowledge --release`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
54
|
+
fs.copyFileSync(local, dest);
|
|
55
|
+
if (!isWin) fs.chmodSync(dest, 0o755);
|
|
56
|
+
console.log(`[ck] Installed local binary → ${dest}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function download(url, outFile) {
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const mod = url.startsWith("https") ? https : http;
|
|
62
|
+
const req = mod.get(url, (res) => {
|
|
63
|
+
if (
|
|
64
|
+
res.statusCode >= 300 &&
|
|
65
|
+
res.statusCode < 400 &&
|
|
66
|
+
res.headers.location
|
|
67
|
+
) {
|
|
68
|
+
res.resume();
|
|
69
|
+
download(res.headers.location, outFile).then(resolve, reject);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (res.statusCode !== 200) {
|
|
73
|
+
reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
74
|
+
res.resume();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const file = createWriteStream(outFile);
|
|
78
|
+
pipeline(res, file).then(resolve, reject);
|
|
79
|
+
});
|
|
80
|
+
req.on("error", reject);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async function downloadRelease() {
|
|
85
|
+
const target = rustTarget();
|
|
86
|
+
const base =
|
|
87
|
+
process.env.CK_RELEASE_BASE ||
|
|
88
|
+
"https://github.com/kai-rainy/code-knowledge/releases";
|
|
89
|
+
const archive = isWin
|
|
90
|
+
? `ck-${target}.zip`
|
|
91
|
+
: `ck-${target}.tar.gz`;
|
|
92
|
+
const url =
|
|
93
|
+
process.env.CK_CLI_BINARY_URL ||
|
|
94
|
+
`${base}/download/v${version}/${archive}`;
|
|
95
|
+
|
|
96
|
+
const tmpDir = fs.mkdtempSync(path.join(require("node:os").tmpdir(), "ck-npm-"));
|
|
97
|
+
const archivePath = path.join(tmpDir, archive);
|
|
98
|
+
|
|
99
|
+
console.log(`[ck] Downloading ${url}`);
|
|
100
|
+
try {
|
|
101
|
+
await download(url, archivePath);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
104
|
+
throw new Error(
|
|
105
|
+
`${e.message}\n` +
|
|
106
|
+
`No release asset yet? Use local: CK_CLI_USE_LOCAL=1 npm i -g ./packaging/npm/@codeknowledge/cli\n` +
|
|
107
|
+
`Or: cargo install --path apps/cli --force`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
112
|
+
try {
|
|
113
|
+
if (isWin) {
|
|
114
|
+
execFileSync(
|
|
115
|
+
"powershell.exe",
|
|
116
|
+
[
|
|
117
|
+
"-NoProfile",
|
|
118
|
+
"-Command",
|
|
119
|
+
`Expand-Archive -Path '${archivePath.replace(/'/g, "''")}' -DestinationPath '${tmpDir.replace(/'/g, "''")}' -Force`,
|
|
120
|
+
],
|
|
121
|
+
{ stdio: "inherit" }
|
|
122
|
+
);
|
|
123
|
+
} else {
|
|
124
|
+
execFileSync("tar", ["-xzf", archivePath, "-C", tmpDir], {
|
|
125
|
+
stdio: "inherit",
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
const found = walkFind(tmpDir, binName);
|
|
129
|
+
if (!found) throw new Error(`${binName} not found in archive`);
|
|
130
|
+
fs.copyFileSync(found, dest);
|
|
131
|
+
if (!isWin) fs.chmodSync(dest, 0o755);
|
|
132
|
+
console.log(`[ck] Installed → ${dest}`);
|
|
133
|
+
} finally {
|
|
134
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function walkFind(dir, name) {
|
|
139
|
+
for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
140
|
+
const p = path.join(dir, ent.name);
|
|
141
|
+
if (ent.isDirectory()) {
|
|
142
|
+
const hit = walkFind(p, name);
|
|
143
|
+
if (hit) return hit;
|
|
144
|
+
} else if (ent.name === name) {
|
|
145
|
+
return p;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function main() {
|
|
152
|
+
if (process.env.CK_CLI_USE_LOCAL === "1") {
|
|
153
|
+
copyLocal();
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
await downloadRelease();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
main().catch((err) => {
|
|
160
|
+
console.error(`[ck] postinstall failed: ${err.message}`);
|
|
161
|
+
process.exit(1);
|
|
162
|
+
});
|