Files
fox-cli/src/config.ts
T
chenyunda218 80b784a9f3 feat(cli): 實作 CLI 各指令與 help(M1+M2,issue #13)
- 加入 pnpm workspace;Node.js ≥22 + TypeScript 實作
- 指令:auth status、tokens verify/create/list/revoke、novels get
- 非互動、stdout 僅輸出單一 JSON;exit code 0/1/2
- 設定優先順序:--token/--api-url > FOX_API_TOKEN/FOX_API_URL > ~/.config/fox/cli.json
- novels list/create/update 待後端接受 Bearer token 後補齊(README 授權缺口)
- 已對模擬後端完成端到端驗證(含 401/404/網路錯誤、冪等 revoke)
2026-09-04 20:26:11 +08:00

54 lines
1.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { readFile } from "node:fs/promises";
import { homedir } from "node:os";
import { join } from "node:path";
import { ApiError } from "./errors.js";
/** CLI 設定:API 位址與 access token。 */
export interface FoxConfig {
apiUrl: string;
token: string | null;
}
const DEFAULT_API_URL = "http://localhost:3000";
/**
* 讀取設定。優先順序(高 → 低):
* 1. 環境變數 FOX_API_URL / FOX_API_TOKEN
* 2. --api-url / --token 參數(由 caller 傳入)
* 3. 本機設定檔 ~/.config/fox/cli.json({"apiUrl": "...", "token": "..."})
*
* apiUrl 預設 http://localhost:3000;token 找不到時為 null,
* 需要 token 的命令由 caller 檢查並報錯。
*/
export async function loadConfig(flags: { apiUrl?: string; token?: string }): Promise<FoxConfig> {
const configPath = join(homedir(), ".config", "fox", "cli.json");
let fileApiUrl: string | undefined;
let fileToken: string | undefined;
try {
const raw = await readFile(configPath, "utf-8");
const parsed: unknown = JSON.parse(raw);
if (parsed && typeof parsed === "object") {
const obj = parsed as Record<string, unknown>;
if (typeof obj.apiUrl === "string") fileApiUrl = obj.apiUrl;
if (typeof obj.token === "string") fileToken = obj.token;
}
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
if (code !== "ENOENT") {
// 設定檔存在但壞掉:明確報錯,而不是靜默忽略。
throw new ApiError(`設定檔 ${configPath} 無法解析:${(err as Error).message}`);
}
}
const envApiUrl = process.env.FOX_API_URL?.trim() || undefined;
const envToken = process.env.FOX_API_TOKEN?.trim() || undefined;
const apiUrl =
flags.apiUrl ??
envApiUrl ??
fileApiUrl ??
DEFAULT_API_URL;
const token = flags.token ?? envToken ?? fileToken ?? null;
return { apiUrl: apiUrl.replace(/\/+$/, ""), token };
}