Files
opsxapi/packages/core/src/model.ts
T
logan dec66db5aa feat: OpsxAPI v1.0 全协议接口工作台
- 六协议调试: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),明暗双主题
- 环境变量:彩色徽标切换器、管理弹窗、{{ 自动补全
2026-09-18 00:16:59 +08:00

251 lines
5.2 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.
/**
* 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[];
};