@baizor/cc-switch 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/LICENSE +21 -0
- package/README.md +76 -0
- package/assets/readme-header.svg +236 -0
- package/dist/config.d.ts +7 -0
- package/dist/config.js +180 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +137 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.js +24 -0
- package/dist/logger.js.map +1 -0
- package/dist/monitor.d.ts +1 -0
- package/dist/monitor.js +25 -0
- package/dist/monitor.js.map +1 -0
- package/dist/paths.d.ts +8 -0
- package/dist/paths.js +27 -0
- package/dist/paths.js.map +1 -0
- package/dist/service.d.ts +13 -0
- package/dist/service.js +227 -0
- package/dist/service.js.map +1 -0
- package/dist/state.d.ts +7 -0
- package/dist/state.js +51 -0
- package/dist/state.js.map +1 -0
- package/dist/statusLine.d.ts +6 -0
- package/dist/statusLine.js +83 -0
- package/dist/statusLine.js.map +1 -0
- package/dist/switcher.d.ts +11 -0
- package/dist/switcher.js +137 -0
- package/dist/switcher.js.map +1 -0
- package/dist/telemetry.d.ts +2 -0
- package/dist/telemetry.js +43 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tui.d.ts +7 -0
- package/dist/tui.js +300 -0
- package/dist/tui.js.map +1 -0
- package/dist/types.d.ts +61 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/util.d.ts +8 -0
- package/dist/util.js +67 -0
- package/dist/util.js.map +1 -0
- package/package.json +52 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type SwitchMode = "env" | "credentials-file";
|
|
2
|
+
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
3
|
+
export interface AppConfig {
|
|
4
|
+
tokens: string[];
|
|
5
|
+
tokenLabels: string[];
|
|
6
|
+
pollSeconds: number;
|
|
7
|
+
fiveHourMinLeftPercent: number;
|
|
8
|
+
weeklyMinLeftPercent: number;
|
|
9
|
+
switchingMode: SwitchMode;
|
|
10
|
+
logLevel: LogLevel;
|
|
11
|
+
serviceAutostart: boolean;
|
|
12
|
+
configPath: string;
|
|
13
|
+
statePath: string;
|
|
14
|
+
credentialsPath?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface RateLimitWindow {
|
|
17
|
+
usedPercentage?: number;
|
|
18
|
+
resetsAt?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface QuotaSnapshot {
|
|
21
|
+
tokenFingerprint: string;
|
|
22
|
+
fiveHour?: RateLimitWindow;
|
|
23
|
+
weekly?: RateLimitWindow;
|
|
24
|
+
capturedAt: string;
|
|
25
|
+
}
|
|
26
|
+
export interface SwitchHistoryEntry {
|
|
27
|
+
fromIndex: number | null;
|
|
28
|
+
toIndex: number;
|
|
29
|
+
reason: string;
|
|
30
|
+
switchedAt: string;
|
|
31
|
+
}
|
|
32
|
+
export interface ServiceStatusCache {
|
|
33
|
+
installed: boolean;
|
|
34
|
+
running: boolean;
|
|
35
|
+
detail?: string;
|
|
36
|
+
checkedAt: string;
|
|
37
|
+
}
|
|
38
|
+
export interface StatusLineMetadata {
|
|
39
|
+
installed: boolean;
|
|
40
|
+
settingsPath?: string;
|
|
41
|
+
previousStatusLine?: unknown;
|
|
42
|
+
installedAt?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface AppState {
|
|
45
|
+
activeTokenIndex: number | null;
|
|
46
|
+
snapshots: Record<string, QuotaSnapshot>;
|
|
47
|
+
switchHistory: SwitchHistoryEntry[];
|
|
48
|
+
serviceStatusCache?: ServiceStatusCache;
|
|
49
|
+
statusLine: StatusLineMetadata;
|
|
50
|
+
}
|
|
51
|
+
export interface TokenView {
|
|
52
|
+
index: number;
|
|
53
|
+
label: string;
|
|
54
|
+
fingerprint: string;
|
|
55
|
+
active: boolean;
|
|
56
|
+
fiveHourUsed: string;
|
|
57
|
+
weeklyUsed: string;
|
|
58
|
+
resetEta: string;
|
|
59
|
+
health: "ok" | "low" | "unknown";
|
|
60
|
+
lastTelemetry: string;
|
|
61
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function tokenFingerprint(token: string): string;
|
|
2
|
+
export declare function maskToken(token: string): string;
|
|
3
|
+
export declare function parseBoolean(value: string | undefined, fallback: boolean): boolean;
|
|
4
|
+
export declare function parseJsonArrayOrCsv(value: string | undefined): string[];
|
|
5
|
+
export declare function etaFromNow(iso: string | undefined, now?: Date): string;
|
|
6
|
+
export declare function percentUsed(value: number | undefined): string;
|
|
7
|
+
export declare function clampIndex(index: number, length: number): boolean;
|
|
8
|
+
export declare function shellQuote(value: string): string;
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
export function tokenFingerprint(token) {
|
|
3
|
+
return crypto.createHash("sha256").update(token).digest("hex").slice(0, 10);
|
|
4
|
+
}
|
|
5
|
+
export function maskToken(token) {
|
|
6
|
+
if (!token)
|
|
7
|
+
return "<empty>";
|
|
8
|
+
const fp = tokenFingerprint(token);
|
|
9
|
+
if (token.length <= 8)
|
|
10
|
+
return `${token.slice(0, 2)}...${fp}`;
|
|
11
|
+
return `${token.slice(0, 4)}...${token.slice(-4)} (${fp})`;
|
|
12
|
+
}
|
|
13
|
+
export function parseBoolean(value, fallback) {
|
|
14
|
+
if (value == null || value === "")
|
|
15
|
+
return fallback;
|
|
16
|
+
return ["1", "true", "yes", "on"].includes(value.toLowerCase());
|
|
17
|
+
}
|
|
18
|
+
export function parseJsonArrayOrCsv(value) {
|
|
19
|
+
if (!value)
|
|
20
|
+
return [];
|
|
21
|
+
const trimmed = value.trim();
|
|
22
|
+
if (!trimmed)
|
|
23
|
+
return [];
|
|
24
|
+
if (trimmed.startsWith("[")) {
|
|
25
|
+
const parsed = JSON.parse(trimmed);
|
|
26
|
+
if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "string")) {
|
|
27
|
+
throw new Error("Expected a JSON string array");
|
|
28
|
+
}
|
|
29
|
+
return parsed;
|
|
30
|
+
}
|
|
31
|
+
return trimmed
|
|
32
|
+
.split(",")
|
|
33
|
+
.map((item) => item.trim())
|
|
34
|
+
.filter(Boolean);
|
|
35
|
+
}
|
|
36
|
+
export function etaFromNow(iso, now = new Date()) {
|
|
37
|
+
if (!iso)
|
|
38
|
+
return "unknown";
|
|
39
|
+
const at = new Date(iso);
|
|
40
|
+
if (Number.isNaN(at.getTime()))
|
|
41
|
+
return "unknown";
|
|
42
|
+
const ms = at.getTime() - now.getTime();
|
|
43
|
+
if (ms <= 0)
|
|
44
|
+
return "now";
|
|
45
|
+
const mins = Math.round(ms / 60000);
|
|
46
|
+
if (mins < 60)
|
|
47
|
+
return `${mins}m`;
|
|
48
|
+
const hours = Math.floor(mins / 60);
|
|
49
|
+
const rem = mins % 60;
|
|
50
|
+
if (hours < 24)
|
|
51
|
+
return rem ? `${hours}h ${rem}m` : `${hours}h`;
|
|
52
|
+
const days = Math.floor(hours / 24);
|
|
53
|
+
const remHours = hours % 24;
|
|
54
|
+
return remHours ? `${days}d ${remHours}h` : `${days}d`;
|
|
55
|
+
}
|
|
56
|
+
export function percentUsed(value) {
|
|
57
|
+
return typeof value === "number" && Number.isFinite(value) ? `${Math.round(value)}%` : "unknown";
|
|
58
|
+
}
|
|
59
|
+
export function clampIndex(index, length) {
|
|
60
|
+
return Number.isInteger(index) && index >= 0 && index < length;
|
|
61
|
+
}
|
|
62
|
+
export function shellQuote(value) {
|
|
63
|
+
if (/^[A-Za-z0-9_/:=.,@%+-]+$/.test(value))
|
|
64
|
+
return value;
|
|
65
|
+
return `'${value.replace(/'/g, "'\"'\"'")}'`;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@baizor/cc-switch",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Manage multiple Claude Code subscription OAuth tokens from a TypeScript CLI.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/IvanMurzak/Claude-Subscription-Switcher.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/IvanMurzak/Claude-Subscription-Switcher#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/IvanMurzak/Claude-Subscription-Switcher/issues"
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"cc-switch": "dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"assets",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE"
|
|
22
|
+
],
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
28
|
+
"build": "npm run clean && tsc -p tsconfig.json",
|
|
29
|
+
"test": "vitest run",
|
|
30
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
31
|
+
},
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=20"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@inquirer/prompts": "^7.3.2",
|
|
37
|
+
"chalk": "^5.4.1",
|
|
38
|
+
"commander": "^12.1.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^22.10.7",
|
|
42
|
+
"typescript": "^5.7.3",
|
|
43
|
+
"vitest": "^4.1.10"
|
|
44
|
+
},
|
|
45
|
+
"keywords": [
|
|
46
|
+
"claude-code",
|
|
47
|
+
"cli",
|
|
48
|
+
"oauth",
|
|
49
|
+
"subscription"
|
|
50
|
+
],
|
|
51
|
+
"license": "MIT"
|
|
52
|
+
}
|