mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 20:00:47 +00:00
refactor(open-sse): usage.js dispatcher switch → USAGE_HANDLERS registry
Gộp switch 13 nhánh getUsageForProvider thành 1 registry object (provider → handler), mỗi handler giữ nguyên signature/args qua ctx. Behavior giữ nguyên (ollama vẫn chỉ nhận accessToken như cũ). Thêm tests/unit/usage-dispatch.test.js guard dispatch. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+22
-32
@@ -63,6 +63,25 @@ const CLAUDE_CONFIG = {
|
|||||||
* @param {Object} connection - Provider connection with accessToken
|
* @param {Object} connection - Provider connection with accessToken
|
||||||
* @returns {Object} Usage data with quotas
|
* @returns {Object} Usage data with quotas
|
||||||
*/
|
*/
|
||||||
|
// provider → usage handler (ctx carries every arg each handler needs)
|
||||||
|
const USAGE_HANDLERS = {
|
||||||
|
github: (c) => getGitHubUsage(c.accessToken, c.providerSpecificData, c.proxyOptions),
|
||||||
|
"gemini-cli": (c) => getGeminiUsage(c.accessToken, c.providerDataWithProjectId, c.proxyOptions),
|
||||||
|
antigravity: (c) => getAntigravityUsage(c.accessToken, c.providerSpecificData, c.proxyOptions),
|
||||||
|
claude: (c) => getClaudeUsage(c.accessToken, c.proxyOptions),
|
||||||
|
codex: (c) => getCodexUsage(c.accessToken, c.proxyOptions),
|
||||||
|
kiro: (c) => getKiroUsage(c.accessToken, c.providerSpecificData, c.proxyOptions),
|
||||||
|
qoder: (c) => getQoderUsage(c.accessToken, c.proxyOptions),
|
||||||
|
qwen: (c) => getQwenUsage(c.accessToken, c.providerSpecificData),
|
||||||
|
iflow: (c) => getIflowUsage(c.accessToken),
|
||||||
|
ollama: (c) => getOllamaUsage(c.accessToken),
|
||||||
|
glm: (c) => getGlmUsage(c.apiKey, c.provider, c.proxyOptions),
|
||||||
|
"glm-cn": (c) => getGlmUsage(c.apiKey, c.provider, c.proxyOptions),
|
||||||
|
minimax: (c) => getMiniMaxUsage(c.apiKey, c.provider, c.proxyOptions),
|
||||||
|
"minimax-cn": (c) => getMiniMaxUsage(c.apiKey, c.provider, c.proxyOptions),
|
||||||
|
"vercel-ai-gateway": (c) => getVercelAiGatewayUsage(c.apiKey, c.proxyOptions),
|
||||||
|
};
|
||||||
|
|
||||||
export async function getUsageForProvider(connection, proxyOptions = null) {
|
export async function getUsageForProvider(connection, proxyOptions = null) {
|
||||||
const { provider, accessToken, apiKey, providerSpecificData, projectId } = connection;
|
const { provider, accessToken, apiKey, providerSpecificData, projectId } = connection;
|
||||||
const providerDataWithProjectId = {
|
const providerDataWithProjectId = {
|
||||||
@@ -70,38 +89,9 @@ export async function getUsageForProvider(connection, proxyOptions = null) {
|
|||||||
...(projectId ? { projectId } : {}),
|
...(projectId ? { projectId } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (provider) {
|
const handler = USAGE_HANDLERS[provider];
|
||||||
case "github":
|
if (!handler) return { message: `Usage API not implemented for ${provider}` };
|
||||||
return await getGitHubUsage(accessToken, providerSpecificData, proxyOptions);
|
return await handler({ provider, accessToken, apiKey, providerSpecificData, providerDataWithProjectId, proxyOptions });
|
||||||
case "gemini-cli":
|
|
||||||
return await getGeminiUsage(accessToken, providerDataWithProjectId, proxyOptions);
|
|
||||||
case "antigravity":
|
|
||||||
return await getAntigravityUsage(accessToken, providerSpecificData, proxyOptions);
|
|
||||||
case "claude":
|
|
||||||
return await getClaudeUsage(accessToken, proxyOptions);
|
|
||||||
case "codex":
|
|
||||||
return await getCodexUsage(accessToken, proxyOptions);
|
|
||||||
case "kiro":
|
|
||||||
return await getKiroUsage(accessToken, providerSpecificData, proxyOptions);
|
|
||||||
case "qoder":
|
|
||||||
return await getQoderUsage(accessToken, proxyOptions);
|
|
||||||
case "qwen":
|
|
||||||
return await getQwenUsage(accessToken, providerSpecificData);
|
|
||||||
case "iflow":
|
|
||||||
return await getIflowUsage(accessToken);
|
|
||||||
case "ollama":
|
|
||||||
return await getOllamaUsage(accessToken);
|
|
||||||
case "glm":
|
|
||||||
case "glm-cn":
|
|
||||||
return await getGlmUsage(apiKey, provider, proxyOptions);
|
|
||||||
case "minimax":
|
|
||||||
case "minimax-cn":
|
|
||||||
return await getMiniMaxUsage(apiKey, provider, proxyOptions);
|
|
||||||
case "vercel-ai-gateway":
|
|
||||||
return await getVercelAiGatewayUsage(apiKey, proxyOptions);
|
|
||||||
default:
|
|
||||||
return { message: `Usage API not implemented for ${provider}` };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Guards the refactored USAGE_HANDLERS dispatch: unsupported → message, supported → routed.
|
||||||
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||||
|
|
||||||
|
// Stub network so handlers don't hit real APIs; each call resolves an empty 200.
|
||||||
|
vi.mock("../../open-sse/utils/proxyFetch.js", () => ({
|
||||||
|
proxyAwareFetch: vi.fn(async () => ({
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
json: async () => ({}),
|
||||||
|
text: async () => "{}",
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const load = () => import("../../open-sse/services/usage.js");
|
||||||
|
const SUPPORTED = [
|
||||||
|
"github", "gemini-cli", "antigravity", "claude", "codex", "kiro",
|
||||||
|
"qoder", "qwen", "iflow", "ollama", "glm", "glm-cn",
|
||||||
|
"minimax", "minimax-cn", "vercel-ai-gateway",
|
||||||
|
];
|
||||||
|
|
||||||
|
describe("usage dispatch", () => {
|
||||||
|
beforeEach(() => vi.clearAllMocks());
|
||||||
|
|
||||||
|
it("unsupported provider → not-implemented message", async () => {
|
||||||
|
const { getUsageForProvider } = await load();
|
||||||
|
const res = await getUsageForProvider({ provider: "totally-unknown" });
|
||||||
|
expect(res).toEqual({ message: "Usage API not implemented for totally-unknown" });
|
||||||
|
});
|
||||||
|
|
||||||
|
it("every supported provider routes to its handler (no fallback message)", async () => {
|
||||||
|
const { getUsageForProvider } = await load();
|
||||||
|
for (const provider of SUPPORTED) {
|
||||||
|
const res = await getUsageForProvider({ provider, accessToken: "t", apiKey: "k" });
|
||||||
|
// Routed handler must return an object and never the unsupported fallback
|
||||||
|
expect(res, `${provider} routed`).toBeTypeOf("object");
|
||||||
|
expect(res?.message).not.toBe(`Usage API not implemented for ${provider}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user