- 六协议调试:HTTP/GraphQL/WebSocket/SSE/Socket.IO/MQTT
- 集合树/多标签/多环境变量/历史记录,localStorage 持久化
- 导入:OpenAPI 2/3/3.1、Postman、Apifox、Apipost、cURL、HAR、
Insomnia、Hoppscotch、Markdown(自动识别,21 个单测覆盖)
- 导出:OpenAPI 3.0 JSON/YAML、Postman v2.1、Markdown 文档、
全量备份;单请求生成 cURL/fetch/Python/Go 代码
- Gin 服务:HTTP 代理、NDJSON 流式代理(SSE 透传)、
WebSocket 隧道(浏览器自定义握手 Header)
- 内置产品官网 /home 与用户文档站 /docs(SSR,随二进制交付)
- lucide 图标体系 + 品牌标识(Logo/favicon),明暗双主题
- 环境变量:彩色徽标切换器、管理弹窗、{{ 自动补全
251 lines
5.2 KiB
TypeScript
251 lines
5.2 KiB
TypeScript
/**
|
||
* OpsxAPI 集合数据模型 —— UI / 导入导出 / 持久化共用的唯一事实源。
|
||
*/
|
||
|
||
export type RequestMethod =
|
||
| "GET"
|
||
| "POST"
|
||
| "PUT"
|
||
| "PATCH"
|
||
| "DELETE"
|
||
| "HEAD"
|
||
| "OPTIONS";
|
||
|
||
export const REQUEST_METHODS: RequestMethod[] = [
|
||
"GET",
|
||
"POST",
|
||
"PUT",
|
||
"PATCH",
|
||
"DELETE",
|
||
"HEAD",
|
||
"OPTIONS",
|
||
];
|
||
|
||
export type RequestKind = "http" | "graphql" | "websocket" | "sse" | "socketio" | "mqtt";
|
||
|
||
export const REQUEST_KINDS: RequestKind[] = [
|
||
"http",
|
||
"graphql",
|
||
"websocket",
|
||
"sse",
|
||
"socketio",
|
||
"mqtt",
|
||
];
|
||
|
||
export const KIND_LABELS: Record<RequestKind, string> = {
|
||
http: "HTTP",
|
||
graphql: "GraphQL",
|
||
websocket: "WebSocket",
|
||
sse: "SSE",
|
||
socketio: "Socket.IO",
|
||
mqtt: "MQTT",
|
||
};
|
||
|
||
/** 键值行:Params / Headers / Cookies / 表单 / 环境变量共用 */
|
||
export type KVRow = {
|
||
id: string;
|
||
key: string;
|
||
value: string;
|
||
enabled: boolean;
|
||
description?: string;
|
||
};
|
||
|
||
export type BodyMode =
|
||
| "none"
|
||
| "json"
|
||
| "xml"
|
||
| "text"
|
||
| "html"
|
||
| "urlencoded"
|
||
| "form-data";
|
||
|
||
export const BODY_MODE_LABELS: Record<BodyMode, string> = {
|
||
none: "none",
|
||
json: "JSON",
|
||
xml: "XML",
|
||
text: "Text",
|
||
html: "HTML",
|
||
urlencoded: "x-www-form-urlencoded",
|
||
"form-data": "form-data",
|
||
};
|
||
|
||
export const RAW_BODY_MODES: BodyMode[] = ["json", "xml", "text", "html"];
|
||
|
||
export type AuthMode = "none" | "bearer" | "basic" | "apikey";
|
||
|
||
export type AuthConfig = {
|
||
mode: AuthMode;
|
||
bearer?: string;
|
||
basicUser?: string;
|
||
basicPass?: string;
|
||
apiKeyName?: string;
|
||
apiKeyValue?: string;
|
||
apiKeyIn?: "header" | "query";
|
||
};
|
||
|
||
export type HttpRequestData = {
|
||
kind: "http";
|
||
method: RequestMethod;
|
||
url: string;
|
||
query: KVRow[];
|
||
headers: KVRow[];
|
||
cookies: KVRow[];
|
||
auth: AuthConfig;
|
||
bodyMode: BodyMode;
|
||
bodyRaw: string;
|
||
bodyForm: KVRow[];
|
||
};
|
||
|
||
export type GraphqlRequestData = {
|
||
kind: "graphql";
|
||
url: string;
|
||
headers: KVRow[];
|
||
auth: AuthConfig;
|
||
query: string;
|
||
variables: string;
|
||
};
|
||
|
||
export type WebsocketRequestData = {
|
||
kind: "websocket";
|
||
url: string;
|
||
headers: KVRow[];
|
||
protocols: string;
|
||
};
|
||
|
||
export type SseRequestData = {
|
||
kind: "sse";
|
||
url: string;
|
||
headers: KVRow[];
|
||
query: KVRow[];
|
||
auth: AuthConfig;
|
||
lastEventId: string;
|
||
/** 仅解析 data: 行为 JSON */
|
||
dataOnly: boolean;
|
||
};
|
||
|
||
export type SocketIoRequestData = {
|
||
kind: "socketio";
|
||
url: string;
|
||
/** 额外连接参数(JSON:auth / transports / path …) */
|
||
options: string;
|
||
/** 监听的服务端事件名 */
|
||
listenEvents: string[];
|
||
sendEvent: string;
|
||
sendArgs: string;
|
||
};
|
||
|
||
export type MqttRequestData = {
|
||
kind: "mqtt";
|
||
brokerUrl: string;
|
||
username: string;
|
||
password: string;
|
||
clientId: string;
|
||
/** 订阅主题,逗号分隔 */
|
||
subscribeTopics: string;
|
||
publishTopic: string;
|
||
publishPayload: string;
|
||
qos: 0 | 1 | 2;
|
||
};
|
||
|
||
export type RequestData =
|
||
| HttpRequestData
|
||
| GraphqlRequestData
|
||
| WebsocketRequestData
|
||
| SseRequestData
|
||
| SocketIoRequestData
|
||
| MqttRequestData;
|
||
|
||
export type RequestDataOf<K extends RequestKind> = Extract<RequestData, { kind: K }>;
|
||
|
||
export type RequestNodeBase = {
|
||
id: string;
|
||
type: "request";
|
||
name: string;
|
||
description?: string;
|
||
createdAt: number;
|
||
updatedAt: number;
|
||
};
|
||
|
||
export type HttpApiNode = RequestNodeBase & { kind: "http"; data: HttpRequestData };
|
||
export type GraphqlApiNode = RequestNodeBase & { kind: "graphql"; data: GraphqlRequestData };
|
||
export type WebsocketApiNode = RequestNodeBase & { kind: "websocket"; data: WebsocketRequestData };
|
||
export type SseApiNode = RequestNodeBase & { kind: "sse"; data: SseRequestData };
|
||
export type SocketIoApiNode = RequestNodeBase & { kind: "socketio"; data: SocketIoRequestData };
|
||
export type MqttApiNode = RequestNodeBase & { kind: "mqtt"; data: MqttRequestData };
|
||
|
||
/** 判别联合:`node.kind === "http"` 时自动收窄 data 类型 */
|
||
export type RequestNode =
|
||
| HttpApiNode
|
||
| GraphqlApiNode
|
||
| WebsocketApiNode
|
||
| SseApiNode
|
||
| SocketIoApiNode
|
||
| MqttApiNode;
|
||
|
||
export type FolderNode = {
|
||
id: string;
|
||
type: "folder";
|
||
name: string;
|
||
description?: string;
|
||
children: CollectionNode[];
|
||
createdAt: number;
|
||
updatedAt: number;
|
||
};
|
||
|
||
export type CollectionNode = RequestNode | FolderNode;
|
||
|
||
/** 一个集合(项目),本身是一个顶层目录 */
|
||
export type Collection = {
|
||
id: string;
|
||
type: "collection";
|
||
name: string;
|
||
description?: string;
|
||
children: CollectionNode[];
|
||
createdAt: number;
|
||
updatedAt: number;
|
||
};
|
||
|
||
export type Environment = {
|
||
id: string;
|
||
name: string;
|
||
variables: KVRow[];
|
||
};
|
||
|
||
export type HistoryEntry = {
|
||
id: string;
|
||
at: number;
|
||
kind: RequestKind;
|
||
label: string;
|
||
method?: RequestMethod;
|
||
url: string;
|
||
status?: number;
|
||
durationMs?: number;
|
||
ok: boolean;
|
||
/** 关联的请求节点 id(可回跳) */
|
||
nodeId?: string;
|
||
};
|
||
|
||
export type ThemeMode = "dark" | "light";
|
||
|
||
export type WorkspaceSettings = {
|
||
theme: ThemeMode;
|
||
/** 请求超时(毫秒) */
|
||
timeoutMs: number;
|
||
};
|
||
|
||
export type WorkspaceData = {
|
||
version: 2;
|
||
collections: Collection[];
|
||
environments: Environment[];
|
||
activeEnvironmentId: string | null;
|
||
history: HistoryEntry[];
|
||
settings: WorkspaceSettings;
|
||
};
|
||
|
||
/** 导入结果:集合 + 建议写入环境的前缀变量(如 baseUrl) */
|
||
export type ImportResult = {
|
||
collections: Collection[];
|
||
environmentVariables: { key: string; value: string }[];
|
||
warnings: string[];
|
||
};
|