@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 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
+ });