api-switch-cc 0.2.7 → 0.3.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/api-switch.js +103 -0
- package/install.js +36 -13
- package/package.json +2 -6
package/api-switch.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* API-Switch — lazy-install launcher
|
|
5
|
+
*
|
|
6
|
+
* On first run, installs the api-switch binary (via go/gitee/github),
|
|
7
|
+
* then execs it with the original arguments.
|
|
8
|
+
* Subsequent runs use the cached binary directly.
|
|
9
|
+
*
|
|
10
|
+
* Usage: api-switch <args...>
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
"use strict";
|
|
14
|
+
|
|
15
|
+
const { existsSync, mkdirSync, chmodSync, unlinkSync, copyFileSync } = require("fs");
|
|
16
|
+
const { join } = require("path");
|
|
17
|
+
const { execSync, spawnSync } = require("child_process");
|
|
18
|
+
|
|
19
|
+
const VERSION = "v0.2.1";
|
|
20
|
+
const BIN_DIR = join(__dirname, ".bin");
|
|
21
|
+
const BIN_NAME = process.platform === "win32" ? "api-switch.exe" : "api-switch";
|
|
22
|
+
const BIN_PATH = join(BIN_DIR, BIN_NAME);
|
|
23
|
+
|
|
24
|
+
const GITEE_REPO = "https://gitee.com/776311606/API-Switch.git";
|
|
25
|
+
const GH_RELEASE = `https://github.com/hxz0727/API-Switch/releases/download/${VERSION}`;
|
|
26
|
+
|
|
27
|
+
function platform() {
|
|
28
|
+
const map = {
|
|
29
|
+
"darwin-x64": "darwin-amd64", "darwin-arm64": "darwin-arm64",
|
|
30
|
+
"linux-x64": "linux-amd64", "linux-arm64": "linux-arm64",
|
|
31
|
+
"win32-x64": "windows-amd64",
|
|
32
|
+
};
|
|
33
|
+
return map[`${process.platform}-${process.arch}`];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ── Install binary (lazy, on first use) ──
|
|
37
|
+
function ensureInstalled() {
|
|
38
|
+
if (existsSync(BIN_PATH)) return;
|
|
39
|
+
|
|
40
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
41
|
+
console.log("First run — installing api-switch...");
|
|
42
|
+
|
|
43
|
+
// 1. go install via goproxy.cn
|
|
44
|
+
try {
|
|
45
|
+
const gopath = (execSync("go env GOPATH", { encoding: "utf8", stdio: "pipe" }) || "~/go").trim();
|
|
46
|
+
const goBin = join(gopath, "bin", BIN_NAME);
|
|
47
|
+
execSync(`GOPROXY=https://goproxy.cn,direct GOTOOLCHAIN=local go install github.com/hxz0727/API-Switch/cmd/api-switch@${VERSION}`, { stdio: "pipe", timeout: 120000 });
|
|
48
|
+
if (existsSync(goBin)) {
|
|
49
|
+
copyFileSync(goBin, BIN_PATH);
|
|
50
|
+
chmodSync(BIN_PATH, 0o755);
|
|
51
|
+
console.log("Installed via go install.");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
} catch (_) {}
|
|
55
|
+
|
|
56
|
+
// 2. Clone from Gitee + build
|
|
57
|
+
try {
|
|
58
|
+
console.log("Trying Gitee mirror...");
|
|
59
|
+
const tmp = join(__dirname, ".gitee-build");
|
|
60
|
+
execSync(`rm -rf ${tmp} && git clone --depth=1 ${GITEE_REPO} ${tmp}`, { stdio: "pipe", timeout: 60000 });
|
|
61
|
+
execSync(`cd ${tmp} && GOTOOLCHAIN=local GOPROXY=https://goproxy.cn,direct go build -ldflags="-s -w -X main.Version=${VERSION}" -o "${BIN_PATH}" ./cmd/api-switch/`, { stdio: "pipe", timeout: 120000 });
|
|
62
|
+
execSync(`rm -rf ${tmp}`, { stdio: "pipe" });
|
|
63
|
+
chmodSync(BIN_PATH, 0o755);
|
|
64
|
+
console.log("Installed via Gitee mirror.");
|
|
65
|
+
return;
|
|
66
|
+
} catch (_) {}
|
|
67
|
+
|
|
68
|
+
// 3. GitHub release download
|
|
69
|
+
const plat = platform();
|
|
70
|
+
if (plat) {
|
|
71
|
+
try {
|
|
72
|
+
console.log("Trying GitHub release...");
|
|
73
|
+
const isWin = process.platform === "win32";
|
|
74
|
+
const archive = `api-switch-${plat}${isWin ? ".zip" : ".tar.gz"}`;
|
|
75
|
+
const url = `${GH_RELEASE}/${archive}`;
|
|
76
|
+
const tmp = join(__dirname, ".gh-download");
|
|
77
|
+
execSync(`curl -sSL --connect-timeout 10 --max-time 120 "${url}" -o "${tmp}"`, { stdio: "pipe", timeout: 150000 });
|
|
78
|
+
if (isWin) {
|
|
79
|
+
execSync(`unzip -o "${tmp}" "api-switch-${plat}.exe"`, { stdio: "pipe" });
|
|
80
|
+
renameSync(`api-switch-${plat}.exe`, BIN_PATH);
|
|
81
|
+
} else {
|
|
82
|
+
execSync(`tar xzf "${tmp}" -C "${BIN_DIR}" "api-switch-${plat}"`, { stdio: "pipe" });
|
|
83
|
+
execSync(`mv "${join(BIN_DIR, 'api-switch-' + plat)}" "${BIN_PATH}"`, { stdio: "pipe" });
|
|
84
|
+
}
|
|
85
|
+
unlinkSync(tmp);
|
|
86
|
+
chmodSync(BIN_PATH, 0o755);
|
|
87
|
+
console.log("Installed via GitHub.");
|
|
88
|
+
return;
|
|
89
|
+
} catch (_) {}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.error();
|
|
93
|
+
console.error("Installation failed. Run manually:");
|
|
94
|
+
console.error(` git clone --depth=1 ${GITEE_REPO}`);
|
|
95
|
+
console.error(" cd API-Switch && GOTOOLCHAIN=local GOPROXY=https://goproxy.cn,direct go build -o api-switch ./cmd/api-switch/");
|
|
96
|
+
console.error(" cp api-switch /usr/local/bin/");
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ── Entry ──
|
|
101
|
+
ensureInstalled();
|
|
102
|
+
const r = spawnSync(BIN_PATH, process.argv.slice(2), { stdio: "inherit" });
|
|
103
|
+
process.exit(r.status ?? 1);
|
package/install.js
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*
|
|
6
6
|
* On postinstall, installs the api-switch binary.
|
|
7
7
|
* Tries multiple methods in order:
|
|
8
|
-
* 1. go install (works behind GFW
|
|
9
|
-
* 2.
|
|
8
|
+
* 1. go install (via goproxy.cn, works behind GFW)
|
|
9
|
+
* 2. Build from Gitee mirror (fast in China)
|
|
10
|
+
* 3. Download from GitHub Releases
|
|
10
11
|
*
|
|
11
12
|
* Usage: npx api-switch-cc <command>
|
|
12
13
|
* npm install -g api-switch-cc && api-switch serve
|
|
@@ -21,6 +22,7 @@ const { execSync } = require("child_process");
|
|
|
21
22
|
const PKG = require("./package.json");
|
|
22
23
|
const DOWNLOAD_VERSION = "v0.2.1";
|
|
23
24
|
const GH_RELEASE = `https://github.com/hxz0727/API-Switch/releases/download/${DOWNLOAD_VERSION}`;
|
|
25
|
+
const GITEE_REPO = "https://gitee.com/776311606/API-Switch.git";
|
|
24
26
|
const BIN_DIR = join(__dirname, "bin");
|
|
25
27
|
|
|
26
28
|
function platform() {
|
|
@@ -54,7 +56,10 @@ function install() {
|
|
|
54
56
|
// ── Method 1: go install via goproxy.cn (works in China) ──
|
|
55
57
|
if (tryGoInstall(binPath, name)) return;
|
|
56
58
|
|
|
57
|
-
// ── Method 2:
|
|
59
|
+
// ── Method 2: Clone from Gitee + build (fast for Chinese users) ──
|
|
60
|
+
if (tryGiteeBuild(binPath)) return;
|
|
61
|
+
|
|
62
|
+
// ── Method 3: Download from GitHub Releases ──
|
|
58
63
|
if (tryGitHubDownload(binPath, name)) return;
|
|
59
64
|
|
|
60
65
|
// ── All methods failed ──
|
|
@@ -65,28 +70,27 @@ function install() {
|
|
|
65
70
|
console.error(" GOPROXY=https://goproxy.cn,direct go install github.com/hxz0727/API-Switch/cmd/api-switch@v0.2.1");
|
|
66
71
|
console.error(" sudo cp ~/go/bin/api-switch /usr/local/bin/");
|
|
67
72
|
console.error();
|
|
68
|
-
console.error(" # Option B:
|
|
73
|
+
console.error(" # Option B: Clone from Gitee and build");
|
|
74
|
+
console.error(` git clone --depth=1 ${GITEE_REPO}`);
|
|
75
|
+
console.error(" cd API-Switch && GOTOOLCHAIN=local GOPROXY=https://goproxy.cn,direct go build -o api-switch ./cmd/api-switch/");
|
|
76
|
+
console.error(" sudo cp api-switch /usr/local/bin/");
|
|
77
|
+
console.error();
|
|
78
|
+
console.error(" # Option C: Download from GitHub");
|
|
69
79
|
const plat = platform();
|
|
70
80
|
const isWin = process.platform === "win32";
|
|
71
81
|
const archive = `api-switch-${plat}${isWin ? ".zip" : ".tar.gz"}`;
|
|
72
82
|
console.error(` curl -sSL "${GH_RELEASE}/${archive}" | tar xz`);
|
|
73
83
|
console.error(` sudo cp api-switch-${plat} /usr/local/bin/api-switch`);
|
|
74
|
-
console.error();
|
|
75
|
-
console.error(" # Option C: Build from source");
|
|
76
|
-
console.error(" git clone https://github.com/hxz0727/API-Switch.git");
|
|
77
|
-
console.error(" cd API-Switch && make build && sudo make install");
|
|
78
84
|
process.exit(1);
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
function tryGoInstall(binPath, name) {
|
|
82
88
|
try {
|
|
83
89
|
console.log("Trying go install (works behind GFW)...");
|
|
84
|
-
// Use goproxy.cn for Chinese users who can't reach proxy.golang.org
|
|
85
90
|
execSync(
|
|
86
91
|
`GOPROXY=https://goproxy.cn,direct GOTOOLCHAIN=local go install github.com/hxz0727/API-Switch/cmd/api-switch@${DOWNLOAD_VERSION}`,
|
|
87
92
|
{ stdio: "pipe", timeout: 120000 }
|
|
88
93
|
);
|
|
89
|
-
// go install puts binary in GOPATH/bin or ~/go/bin
|
|
90
94
|
const goPath = (execSync("go env GOPATH", { encoding: "utf8" }) || "~/go").trim();
|
|
91
95
|
const goBin = join(goPath, "bin", name);
|
|
92
96
|
if (existsSync(goBin)) {
|
|
@@ -95,9 +99,28 @@ function tryGoInstall(binPath, name) {
|
|
|
95
99
|
console.log(`Installed to ${binPath}`);
|
|
96
100
|
return true;
|
|
97
101
|
}
|
|
98
|
-
} catch (_) {
|
|
99
|
-
|
|
100
|
-
|
|
102
|
+
} catch (_) {}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function tryGiteeBuild(binPath) {
|
|
107
|
+
try {
|
|
108
|
+
console.log("Trying Gitee mirror build...");
|
|
109
|
+
const tmpDir = join(__dirname, "_build");
|
|
110
|
+
execSync("rm -rf " + tmpDir, { stdio: "pipe" });
|
|
111
|
+
execSync(
|
|
112
|
+
`git clone --depth=1 ${GITEE_REPO} ${tmpDir}`,
|
|
113
|
+
{ stdio: "pipe", timeout: 60000 }
|
|
114
|
+
);
|
|
115
|
+
execSync(
|
|
116
|
+
`cd ${tmpDir} && GOTOOLCHAIN=local GOPROXY=https://goproxy.cn,direct go build -ldflags="-s -w -X main.Version=v0.2.1" -o "${binPath}" ./cmd/api-switch/`,
|
|
117
|
+
{ stdio: "pipe", timeout: 120000 }
|
|
118
|
+
);
|
|
119
|
+
execSync("rm -rf " + tmpDir, { stdio: "pipe" });
|
|
120
|
+
chmodSync(binPath, 0o755);
|
|
121
|
+
console.log(`Installed to ${binPath}`);
|
|
122
|
+
return true;
|
|
123
|
+
} catch (_) {}
|
|
101
124
|
return false;
|
|
102
125
|
}
|
|
103
126
|
|
package/package.json
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "api-switch-cc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Claude Code 多模型代理 — 一键切换 DeepSeek、Qwen、GLM、Moonshot 等国产大模型,协议自动转换,零配置即用。LLM API proxy for Claude Code with DeepSeek, Qwen, Anthropic, OpenAI support.",
|
|
5
5
|
"bin": {
|
|
6
|
-
"api-switch": "
|
|
7
|
-
},
|
|
8
|
-
"scripts": {
|
|
9
|
-
"postinstall": "node install.js",
|
|
10
|
-
"postupdate": "node install.js"
|
|
6
|
+
"api-switch": "api-switch.js"
|
|
11
7
|
},
|
|
12
8
|
"repository": {
|
|
13
9
|
"type": "git",
|