refactor(types): rename AppType to AppId for semantic clarity

Rename `AppType` to `AppId` across the entire frontend codebase to better
reflect its purpose as an application identifier rather than a type category.
This aligns frontend naming with backend command parameter conventions.

Changes:
- Rename type `AppType` to `AppId` in src/lib/api/types.ts
- Remove `AppType` export from src/lib/api/index.ts
- Update all component props from `appType` to `appId` (43 files)
- Update all variable names from `appType` to `appId`
- Synchronize documentation (CHANGELOG, refactoring plans)
- Update test files and MSW mocks

BREAKING CHANGE: `AppType` type is no longer exported. Use `AppId` instead.
All component props have been renamed from `appType` to `appId`.
This commit is contained in:
Jason
2025-10-30 14:59:15 +08:00
parent 80dd6e9381
commit 8e4a0a1bbb
43 changed files with 327 additions and 347 deletions

View File

@@ -61,7 +61,7 @@ describe("AddProviderDialog", () => {
<AddProviderDialog
open
onOpenChange={handleOpenChange}
appType="claude"
appId="claude"
onSubmit={handleSubmit}
/>,
);
@@ -97,7 +97,7 @@ describe("AddProviderDialog", () => {
<AddProviderDialog
open
onOpenChange={vi.fn()}
appType="claude"
appId="claude"
onSubmit={handleSubmit}
/>,
);

View File

@@ -114,7 +114,7 @@ const renderForm = (props?: Partial<React.ComponentProps<typeof McpFormModal>>)
const onClose = overrideOnClose ?? vi.fn();
render(
<McpFormModal
appType="claude"
appId="claude"
onSave={onSave}
onClose={onClose}
existingIds={[]}
@@ -260,7 +260,7 @@ const renderForm = (props?: Partial<React.ComponentProps<typeof McpFormModal>>)
});
it("TOML 模式下自动提取 ID 并成功保存", async () => {
const { onSave } = renderForm({ appType: "codex" });
const { onSave } = renderForm({ appId: "codex" });
const configTextarea = screen.getByPlaceholderText(
"mcp.form.tomlPlaceholder",
@@ -288,7 +288,7 @@ command = "run"
});
it("TOML 模式下缺少命令时展示错误提示并阻止提交", async () => {
const { onSave } = renderForm({ appType: "codex" });
const { onSave } = renderForm({ appId: "codex" });
const configTextarea = screen.getByPlaceholderText(
"mcp.form.tomlPlaceholder",
@@ -319,7 +319,7 @@ type = "stdio"
} as McpServer;
const { onSave } = renderForm({
appType: "claude",
appId: "claude",
editingId: "existing",
initialData,
});

View File

@@ -122,7 +122,7 @@ describe("ProviderList Component", () => {
<ProviderList
providers={{}}
currentProviderId=""
appType="claude"
appId="claude"
onSwitch={vi.fn()}
onEdit={vi.fn()}
onDelete={vi.fn()}
@@ -150,7 +150,7 @@ describe("ProviderList Component", () => {
<ProviderList
providers={{}}
currentProviderId=""
appType="claude"
appId="claude"
onSwitch={vi.fn()}
onEdit={vi.fn()}
onDelete={vi.fn()}
@@ -189,7 +189,7 @@ describe("ProviderList Component", () => {
<ProviderList
providers={{ a: providerA, b: providerB }}
currentProviderId="b"
appType="claude"
appId="claude"
isEditMode
onSwitch={handleSwitch}
onEdit={handleEdit}

View File

@@ -41,13 +41,13 @@ vi.mock("@/components/providers/ProviderList", () => ({
}));
vi.mock("@/components/providers/AddProviderDialog", () => ({
AddProviderDialog: ({ open, onOpenChange, onSubmit, appType }: any) =>
AddProviderDialog: ({ open, onOpenChange, onSubmit, appId }: any) =>
open ? (
<div data-testid="add-provider-dialog">
<button
onClick={() =>
onSubmit({
name: `New ${appType} Provider`,
name: `New ${appId} Provider`,
settingsConfig: {},
category: "custom",
sortIndex: 99,

View File

@@ -139,7 +139,7 @@ const renderPanel = (props?: Partial<React.ComponentProps<typeof McpPanel>>) =>
const client = createTestQueryClient();
return render(
<QueryClientProvider client={client}>
<McpPanel open onOpenChange={() => {}} appType="claude" {...props} />
<McpPanel open onOpenChange={() => {}} appId="claude" {...props} />
</QueryClientProvider>,
);
};
@@ -229,4 +229,3 @@ describe("McpPanel integration", () => {
await waitFor(() => expect(deleteServerMock).toHaveBeenCalledWith("sample"));
});
});

View File

@@ -1,5 +1,5 @@
import { http, HttpResponse } from "msw";
import type { AppType } from "@/lib/api/types";
import type { AppId } from "@/lib/api/types";
import type { McpServer, Provider, Settings } from "@/types";
import {
addProvider,
@@ -37,19 +37,19 @@ const success = <T>(payload: T) => HttpResponse.json(payload as any);
export const handlers = [
http.post(`${TAURI_ENDPOINT}/get_providers`, async ({ request }) => {
const { app } = await withJson<{ app: AppType }>(request);
const { app } = await withJson<{ app: AppId }>(request);
return success(getProviders(app));
}),
http.post(`${TAURI_ENDPOINT}/get_current_provider`, async ({ request }) => {
const { app } = await withJson<{ app: AppType }>(request);
const { app } = await withJson<{ app: AppId }>(request);
return success(getCurrentProviderId(app));
}),
http.post(`${TAURI_ENDPOINT}/update_providers_sort_order`, async ({ request }) => {
const { updates = [], app } = await withJson<{
updates: { id: string; sortIndex: number }[];
app: AppType;
app: AppId;
}>(request);
updateSortOrder(app, updates);
return success(true);
@@ -58,7 +58,7 @@ export const handlers = [
http.post(`${TAURI_ENDPOINT}/update_tray_menu`, () => success(true)),
http.post(`${TAURI_ENDPOINT}/switch_provider`, async ({ request }) => {
const { id, app } = await withJson<{ id: string; app: AppType }>(request);
const { id, app } = await withJson<{ id: string; app: AppId }>(request);
const providers = listProviders(app);
if (!providers[id]) {
return HttpResponse.json(false, { status: 404 });
@@ -70,7 +70,7 @@ export const handlers = [
http.post(`${TAURI_ENDPOINT}/add_provider`, async ({ request }) => {
const { provider, app } = await withJson<{
provider: Provider & { id?: string };
app: AppType;
app: AppId;
}>(request);
const newId = provider.id ?? `mock-${Date.now()}`;
@@ -81,14 +81,14 @@ export const handlers = [
http.post(`${TAURI_ENDPOINT}/update_provider`, async ({ request }) => {
const { provider, app } = await withJson<{
provider: Provider;
app: AppType;
app: AppId;
}>(request);
updateProvider(app, provider);
return success(true);
}),
http.post(`${TAURI_ENDPOINT}/delete_provider`, async ({ request }) => {
const { id, app } = await withJson<{ id: string; app: AppType }>(request);
const { id, app } = await withJson<{ id: string; app: AppId }>(request);
deleteProvider(app, id);
return success(true);
}),
@@ -102,7 +102,7 @@ export const handlers = [
// MCP APIs
http.post(`${TAURI_ENDPOINT}/get_mcp_config`, async ({ request }) => {
const { app } = await withJson<{ app: AppType }>(request);
const { app } = await withJson<{ app: AppId }>(request);
return success(getMcpConfig(app));
}),
@@ -111,7 +111,7 @@ export const handlers = [
http.post(`${TAURI_ENDPOINT}/set_mcp_enabled`, async ({ request }) => {
const { app, id, enabled } = await withJson<{
app: AppType;
app: AppId;
id: string;
enabled: boolean;
}>(request);
@@ -121,7 +121,7 @@ export const handlers = [
http.post(`${TAURI_ENDPOINT}/upsert_mcp_server_in_config`, async ({ request }) => {
const { app, id, spec } = await withJson<{
app: AppType;
app: AppId;
id: string;
spec: McpServer;
}>(request);
@@ -130,7 +130,7 @@ export const handlers = [
}),
http.post(`${TAURI_ENDPOINT}/delete_mcp_server_in_config`, async ({ request }) => {
const { app, id } = await withJson<{ app: AppType; id: string }>(request);
const { app, id } = await withJson<{ app: AppId; id: string }>(request);
deleteMcpServer(app, id);
return success(true);
}),
@@ -162,7 +162,7 @@ export const handlers = [
}),
http.post(`${TAURI_ENDPOINT}/get_config_dir`, async ({ request }) => {
const { app } = await withJson<{ app: AppType }>(request);
const { app } = await withJson<{ app: AppId }>(request);
return success(app === "claude" ? "/default/claude" : "/default/codex");
}),

View File

@@ -1,9 +1,9 @@
import type { AppType } from "@/lib/api/types";
import type { AppId } from "@/lib/api/types";
import type { McpServer, Provider, Settings } from "@/types";
type ProvidersByApp = Record<AppType, Record<string, Provider>>;
type CurrentProviderState = Record<AppType, string>;
type McpConfigState = Record<AppType, Record<string, McpServer>>;
type ProvidersByApp = Record<AppId, Record<string, Provider>>;
type CurrentProviderState = Record<AppId, string>;
type McpConfigState = Record<AppId, Record<string, McpServer>>;
const createDefaultProviders = (): ProvidersByApp => ({
claude: {
@@ -126,29 +126,29 @@ export const resetProviderState = () => {
};
};
export const getProviders = (appType: AppType) =>
export const getProviders = (appType: AppId) =>
cloneProviders(providers)[appType] ?? {};
export const getCurrentProviderId = (appType: AppType) => current[appType] ?? "";
export const getCurrentProviderId = (appType: AppId) => current[appType] ?? "";
export const setCurrentProviderId = (appType: AppType, providerId: string) => {
export const setCurrentProviderId = (appType: AppId, providerId: string) => {
current[appType] = providerId;
};
export const updateProviders = (appType: AppType, data: Record<string, Provider>) => {
export const updateProviders = (appType: AppId, data: Record<string, Provider>) => {
providers[appType] = cloneProviders({ [appType]: data } as ProvidersByApp)[appType];
};
export const setProviders = (appType: AppType, data: Record<string, Provider>) => {
export const setProviders = (appType: AppId, data: Record<string, Provider>) => {
providers[appType] = JSON.parse(JSON.stringify(data)) as Record<string, Provider>;
};
export const addProvider = (appType: AppType, provider: Provider) => {
export const addProvider = (appType: AppId, provider: Provider) => {
providers[appType] = providers[appType] ?? {};
providers[appType][provider.id] = provider;
};
export const updateProvider = (appType: AppType, provider: Provider) => {
export const updateProvider = (appType: AppId, provider: Provider) => {
if (!providers[appType]) return;
providers[appType][provider.id] = {
...providers[appType][provider.id],
@@ -156,7 +156,7 @@ export const updateProvider = (appType: AppType, provider: Provider) => {
};
};
export const deleteProvider = (appType: AppType, providerId: string) => {
export const deleteProvider = (appType: AppId, providerId: string) => {
if (!providers[appType]) return;
delete providers[appType][providerId];
if (current[appType] === providerId) {
@@ -166,7 +166,7 @@ export const deleteProvider = (appType: AppType, providerId: string) => {
};
export const updateSortOrder = (
appType: AppType,
appType: AppId,
updates: { id: string; sortIndex: number }[],
) => {
if (!providers[appType]) return;
@@ -178,7 +178,7 @@ export const updateSortOrder = (
});
};
export const listProviders = (appType: AppType) =>
export const listProviders = (appType: AppId) =>
JSON.parse(JSON.stringify(providers[appType] ?? {})) as Record<string, Provider>;
export const getSettings = () => JSON.parse(JSON.stringify(settingsState)) as Settings;
@@ -193,7 +193,7 @@ export const setAppConfigDirOverrideState = (value: string | null) => {
appConfigDirOverride = value;
};
export const getMcpConfig = (appType: AppType) => {
export const getMcpConfig = (appType: AppId) => {
const servers = JSON.parse(
JSON.stringify(mcpConfigs[appType] ?? {}),
) as Record<string, McpServer>;
@@ -203,12 +203,12 @@ export const getMcpConfig = (appType: AppType) => {
};
};
export const setMcpConfig = (appType: AppType, value: Record<string, McpServer>) => {
export const setMcpConfig = (appType: AppId, value: Record<string, McpServer>) => {
mcpConfigs[appType] = JSON.parse(JSON.stringify(value)) as Record<string, McpServer>;
};
export const setMcpServerEnabled = (
appType: AppType,
appType: AppId,
id: string,
enabled: boolean,
) => {
@@ -220,7 +220,7 @@ export const setMcpServerEnabled = (
};
export const upsertMcpServer = (
appType: AppType,
appType: AppId,
id: string,
server: McpServer,
) => {
@@ -230,7 +230,7 @@ export const upsertMcpServer = (
mcpConfigs[appType][id] = JSON.parse(JSON.stringify(server)) as McpServer;
};
export const deleteMcpServer = (appType: AppType, id: string) => {
export const deleteMcpServer = (appType: AppId, id: string) => {
if (!mcpConfigs[appType]) return;
delete mcpConfigs[appType][id];
};