nuwax-codex 0.16.15 → 0.17.2-beta.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/nuwax-codex.js +8 -2
- package/bin/postinstall.js +190 -0
- package/package.json +1 -1
package/bin/nuwax-codex.js
CHANGED
|
@@ -143,9 +143,15 @@ async function extractTarGz(archivePath, destDir) {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
async function extractZip(archivePath, destDir) {
|
|
146
|
-
//
|
|
146
|
+
// extractZip 仅在 Windows 上触发(getArchiveExt 对 win32 返回 zip)。
|
|
147
|
+
// Windows 没有内置 `unzip` 命令,改用 PowerShell 的 Expand-Archive 解压。
|
|
147
148
|
const { execSync } = await import("node:child_process");
|
|
148
|
-
|
|
149
|
+
const psArchive = archivePath.replace(/'/g, "''");
|
|
150
|
+
const psDest = destDir.replace(/'/g, "''");
|
|
151
|
+
execSync(
|
|
152
|
+
`powershell -NoProfile -NonInteractive -Command "Expand-Archive -LiteralPath '${psArchive}' -DestinationPath '${psDest}' -Force"`,
|
|
153
|
+
{ stdio: "inherit" },
|
|
154
|
+
);
|
|
149
155
|
}
|
|
150
156
|
|
|
151
157
|
// -- main -------------------------------------------------------------------
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Postinstall script: pre-downloads the native `nuwax-codex` binary from
|
|
3
|
+
// Alibaba Cloud OSS so the first CLI invocation is instant.
|
|
4
|
+
|
|
5
|
+
import { createWriteStream, existsSync, mkdirSync, chmodSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { homedir } from "node:os";
|
|
7
|
+
import { join, dirname } from "node:path";
|
|
8
|
+
import { createGunzip } from "node:zlib";
|
|
9
|
+
import { pipeline } from "node:stream/promises";
|
|
10
|
+
import { Transform } from "node:stream";
|
|
11
|
+
import { createReadStream } from "node:fs";
|
|
12
|
+
import { createRequire } from "node:module";
|
|
13
|
+
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const VERSION = require("../package.json").version;
|
|
16
|
+
const OSS_CDN_BASE = "https://nuwa-packages.oss-rg-china-mainland.aliyuncs.com/nuwax-codex";
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Platform helpers
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
function getTargetTriple() {
|
|
23
|
+
const p = process.platform;
|
|
24
|
+
const a = process.arch;
|
|
25
|
+
if (p === "darwin") {
|
|
26
|
+
return a === "arm64" ? "aarch64-apple-darwin" : "x86_64-apple-darwin";
|
|
27
|
+
}
|
|
28
|
+
if (p === "linux") {
|
|
29
|
+
if (a !== "x64") throw new Error(`Unsupported Linux arch: ${a}`);
|
|
30
|
+
const { familySync } = require("detect-libc");
|
|
31
|
+
return familySync() === "musl"
|
|
32
|
+
? "x86_64-unknown-linux-musl"
|
|
33
|
+
: "x86_64-unknown-linux-gnu";
|
|
34
|
+
}
|
|
35
|
+
if (p === "win32") {
|
|
36
|
+
return a === "arm64" ? "aarch64-pc-windows-msvc" : "x86_64-pc-windows-msvc";
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`Unsupported platform: ${p}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getArchiveExt() {
|
|
42
|
+
return process.platform === "win32" ? "zip" : "tar.gz";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getBinaryName() {
|
|
46
|
+
return process.platform === "win32" ? "nuwax-codex.exe" : "nuwax-codex";
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function cacheDir() {
|
|
50
|
+
return join(homedir(), ".nuwax-codex-cache", VERSION);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function cachedBinaryPath() {
|
|
54
|
+
return join(cacheDir(), getBinaryName());
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Download
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
async function downloadBinary(url, outPath) {
|
|
62
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
63
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
64
|
+
if (!res.ok) {
|
|
65
|
+
throw new Error(
|
|
66
|
+
`Failed to download binary: HTTP ${res.status} ${res.statusText}\nURL: ${url}`,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
const total = parseInt(res.headers.get("content-length") || "0", 10);
|
|
70
|
+
let downloaded = 0;
|
|
71
|
+
const reader = res.body.getReader();
|
|
72
|
+
const ws = createWriteStream(outPath);
|
|
73
|
+
const logInterval = setInterval(() => {
|
|
74
|
+
if (total > 0) {
|
|
75
|
+
process.stderr.write(
|
|
76
|
+
`\r Downloading nuwax-codex ${VERSION} … ${((downloaded / total) * 100).toFixed(0)}%`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}, 500);
|
|
80
|
+
try {
|
|
81
|
+
while (true) {
|
|
82
|
+
const { done, value } = await reader.read();
|
|
83
|
+
if (done) break;
|
|
84
|
+
ws.write(value);
|
|
85
|
+
downloaded += value.length;
|
|
86
|
+
}
|
|
87
|
+
} finally {
|
|
88
|
+
clearInterval(logInterval);
|
|
89
|
+
ws.end();
|
|
90
|
+
}
|
|
91
|
+
process.stderr.write("\n");
|
|
92
|
+
if (process.platform !== "win32") {
|
|
93
|
+
chmodSync(outPath, 0o755);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
// Extraction
|
|
99
|
+
// ---------------------------------------------------------------------------
|
|
100
|
+
|
|
101
|
+
async function extractTarGz(archivePath, destDir) {
|
|
102
|
+
const gunzip = createGunzip();
|
|
103
|
+
const rs = createReadStream(archivePath);
|
|
104
|
+
let buffer = Buffer.alloc(0);
|
|
105
|
+
|
|
106
|
+
await pipeline(
|
|
107
|
+
rs,
|
|
108
|
+
gunzip,
|
|
109
|
+
new Transform({
|
|
110
|
+
transform(chunk, _enc, cb) {
|
|
111
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
112
|
+
while (buffer.length >= 512) {
|
|
113
|
+
const name = buffer.toString("utf8", 0, 100).replace(/\0.*$/, "");
|
|
114
|
+
const sizeStr = buffer.toString("utf8", 124, 136).replace(/\0.*$/, "");
|
|
115
|
+
const size = parseInt(sizeStr, 8);
|
|
116
|
+
if (isNaN(size) || size < 0) break;
|
|
117
|
+
const totalSize = Math.ceil((512 + size) / 512) * 512;
|
|
118
|
+
if (buffer.length < totalSize) break;
|
|
119
|
+
if (name && !name.endsWith("/") && size > 0) {
|
|
120
|
+
const fileData = buffer.subarray(512, 512 + size);
|
|
121
|
+
const outPath = join(destDir, name);
|
|
122
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
123
|
+
writeFileSync(outPath, fileData);
|
|
124
|
+
if (process.platform !== "win32") {
|
|
125
|
+
chmodSync(outPath, 0o755);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
buffer = buffer.subarray(totalSize);
|
|
129
|
+
}
|
|
130
|
+
cb();
|
|
131
|
+
},
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function extractZip(archivePath, destDir) {
|
|
137
|
+
// extractZip 仅在 Windows 上触发(getArchiveExt 对 win32 返回 zip)。
|
|
138
|
+
// Windows 没有内置 `unzip` 命令,改用 PowerShell 的 Expand-Archive 解压,
|
|
139
|
+
// 否则 Windows 用户安装后预下载会被静默吞掉、首次运行 CLI 直接报错退出。
|
|
140
|
+
const { execSync } = await import("node:child_process");
|
|
141
|
+
const psArchive = archivePath.replace(/'/g, "''");
|
|
142
|
+
const psDest = destDir.replace(/'/g, "''");
|
|
143
|
+
execSync(
|
|
144
|
+
`powershell -NoProfile -NonInteractive -Command "Expand-Archive -LiteralPath '${psArchive}' -DestinationPath '${psDest}' -Force"`,
|
|
145
|
+
{ stdio: "inherit" },
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ---------------------------------------------------------------------------
|
|
150
|
+
// Main
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
async function main() {
|
|
154
|
+
const cached = cachedBinaryPath();
|
|
155
|
+
if (existsSync(cached)) {
|
|
156
|
+
process.stderr.write(`nuwax-codex ${VERSION} binary already cached, skipping download.\n`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const target = getTargetTriple();
|
|
161
|
+
const ext = getArchiveExt();
|
|
162
|
+
const url = `${OSS_CDN_BASE}/v${VERSION}/nuwax-codex-${VERSION}-${target}.${ext}`;
|
|
163
|
+
|
|
164
|
+
process.stderr.write(`Pre-downloading nuwax-codex ${VERSION} for ${target} …\n`);
|
|
165
|
+
process.stderr.write(` ${url}\n`);
|
|
166
|
+
|
|
167
|
+
const dir = cacheDir();
|
|
168
|
+
mkdirSync(dir, { recursive: true });
|
|
169
|
+
const archivePath = join(dir, `nuwax-codex.${ext}`);
|
|
170
|
+
|
|
171
|
+
await downloadBinary(url, archivePath);
|
|
172
|
+
|
|
173
|
+
process.stderr.write(" Extracting …\n");
|
|
174
|
+
if (ext === "tar.gz") {
|
|
175
|
+
await extractTarGz(archivePath, dir);
|
|
176
|
+
} else {
|
|
177
|
+
await extractZip(archivePath, dir);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (existsSync(cached)) {
|
|
181
|
+
process.stderr.write(`✓ nuwax-codex ${VERSION} ready at ${cached}\n`);
|
|
182
|
+
} else {
|
|
183
|
+
process.stderr.write(`⚠ nuwax-codex ${VERSION} download completed but binary not found at ${cached}\n`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
main().catch((err) => {
|
|
188
|
+
process.stderr.write(`nuwax-codex postinstall: ${err.message}\n`);
|
|
189
|
+
// Never fail the install — binary will be downloaded on first run instead
|
|
190
|
+
});
|