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),明暗双主题
- 环境变量:彩色徽标切换器、管理弹窗、{{ 自动补全
This commit is contained in:
commit
dec66db5aa
182 files changed
+23377
No files matched your search
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 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[];
|
||||
};
|
||||
Reference in new issue
Block a user