@i.un/api-client 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/chain.js ADDED
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/chain.ts
21
+ var chain_exports = {};
22
+ __export(chain_exports, {
23
+ executeRequestChain: () => executeRequestChain
24
+ });
25
+ module.exports = __toCommonJS(chain_exports);
26
+ async function executeChainRequest(spec, handlers = []) {
27
+ const method = spec.method.toUpperCase();
28
+ for (const handler of handlers) {
29
+ if (handler.shouldHandle(spec.url, method)) {
30
+ try {
31
+ const { adapter } = handler;
32
+ const headers = spec.headers;
33
+ switch (method) {
34
+ case "GET":
35
+ return await adapter.get(spec.url, spec.body, headers);
36
+ case "POST":
37
+ return await adapter.post(spec.url, spec.body, headers);
38
+ case "PUT":
39
+ if (!adapter.put)
40
+ throw new Error(`Adapter ${handler.name} missing PUT method`);
41
+ return await adapter.put(spec.url, spec.body, headers);
42
+ case "DELETE":
43
+ if (!adapter.delete)
44
+ throw new Error(`Adapter ${handler.name} missing DELETE method`);
45
+ return await adapter.delete(spec.url, spec.body, headers);
46
+ case "PATCH":
47
+ if (!adapter.patch)
48
+ throw new Error(`Adapter ${handler.name} missing PATCH method`);
49
+ return await adapter.patch(spec.url, spec.body, headers);
50
+ default:
51
+ throw new Error(`Unsupported method: ${method}`);
52
+ }
53
+ } catch (err) {
54
+ console.warn(
55
+ `Handler [${handler.name || "Anonymous"}] failed for ${spec.url}`,
56
+ err
57
+ );
58
+ return null;
59
+ }
60
+ }
61
+ }
62
+ if (spec.url.startsWith("http://") || spec.url.startsWith("https://")) {
63
+ return await executeFallbackFetch(spec);
64
+ }
65
+ console.warn(`No handler found for url: ${spec.url}`);
66
+ return null;
67
+ }
68
+ async function executeFallbackFetch(spec) {
69
+ try {
70
+ const response = await fetch(spec.url, {
71
+ method: spec.method,
72
+ headers: spec.headers,
73
+ body: spec.body ? JSON.stringify(spec.body) : void 0,
74
+ credentials: "include"
75
+ });
76
+ if (!response.ok) {
77
+ console.log(`External Request failed: ${response.status} ${spec.url}`);
78
+ return null;
79
+ }
80
+ return await response.json();
81
+ } catch (err) {
82
+ console.log("External Request error:", err);
83
+ return null;
84
+ }
85
+ }
86
+ function getByPath(obj, path) {
87
+ if (!path) return obj;
88
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
89
+ }
90
+ function substituteVariables(target, context) {
91
+ if (typeof target === "string") {
92
+ return target.replace(/\{\{([\w\.]+)\}\}/g, (_, path) => {
93
+ const val = getByPath(context, path);
94
+ return val !== void 0 ? String(val) : "";
95
+ });
96
+ }
97
+ if (Array.isArray(target)) {
98
+ return target.map((item) => substituteVariables(item, context));
99
+ }
100
+ if (target && typeof target === "object") {
101
+ const result = {};
102
+ for (const key in target) {
103
+ result[key] = substituteVariables(target[key], context);
104
+ }
105
+ return result;
106
+ }
107
+ return target;
108
+ }
109
+ async function executeRequestChain(requests, handlers = [], getChainRequests, initContext) {
110
+ const context = initContext || {};
111
+ let lastResult = null;
112
+ for (const rule of requests) {
113
+ try {
114
+ let contextData = {};
115
+ if (rule.pickContext) {
116
+ rule.pickContext.forEach((key) => {
117
+ if (key in context) contextData[key] = context[key];
118
+ });
119
+ } else if (rule.includeContext) {
120
+ contextData = context;
121
+ }
122
+ const hasContextData = Object.keys(contextData).length > 0;
123
+ let requestSpec = { ...rule.request };
124
+ if (hasContextData) {
125
+ requestSpec.body = {
126
+ ...contextData,
127
+ ...requestSpec.body || {}
128
+ };
129
+ }
130
+ requestSpec = substituteVariables(requestSpec, context);
131
+ let rawData = await executeChainRequest(requestSpec, handlers);
132
+ if (getChainRequests) {
133
+ const chainRequests = getChainRequests(rawData);
134
+ if (chainRequests && chainRequests.length > 0) {
135
+ rawData = await executeRequestChain(
136
+ chainRequests,
137
+ handlers,
138
+ getChainRequests,
139
+ JSON.parse(JSON.stringify(context))
140
+ );
141
+ }
142
+ }
143
+ lastResult = rawData;
144
+ if (rawData) {
145
+ if (rule.key) {
146
+ const data = rule.selector ? getByPath(rawData, rule.selector) : rawData;
147
+ context[rule.key] = data;
148
+ }
149
+ } else if (!rule.optional) {
150
+ throw new Error(
151
+ `Failed to fetch required data for key: ${rule.key || "unknown"}`
152
+ );
153
+ }
154
+ } catch (err) {
155
+ if (!rule.optional) {
156
+ throw err;
157
+ }
158
+ console.warn(`Optional request failed for rule:`, rule, err);
159
+ }
160
+ }
161
+ return lastResult;
162
+ }
163
+ // Annotate the CommonJS export names for ESM import in node:
164
+ 0 && (module.exports = {
165
+ executeRequestChain
166
+ });
167
+ //# sourceMappingURL=chain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/chain.ts"],"sourcesContent":["/**\n * Request Chain Runner\n * 负责解析和执行通用的 HTTP 请求链 (Chain Execution)\n * 适用于任何需要链式 HTTP 请求编排的场景\n */\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\n/** Supported HTTP Methods */\ntype HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n\n/** HTTP 请求参数 */\nexport interface HttpRequestSpec {\n method: HttpMethod;\n url: string;\n headers?: Record<string, string>;\n body?: any;\n}\n\n/**\n * 网络适配器接口\n * 定义实际发送请求的能力\n */\n/**\n * 网络适配器接口\n * 定义实际发送请求的能力\n */\nexport interface NetworkAdapter {\n get<T>(\n url: string,\n params?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n post<T>(\n url: string,\n body?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n put?<T>(\n url: string,\n body?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n delete?<T>(\n url: string,\n params?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n patch?<T>(\n url: string,\n body?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n}\n\n/**\n * 网络处理器接口 (Strategy Pattern)\n * 组合了\"匹配规则\"和\"执行能力\"\n */\nexport interface NetworkHandler {\n /** 处理器名称 (用于调试) */\n name?: string;\n\n /** 判断该 URL 是否由此适配器处理 */\n shouldHandle(url: string, method: HttpMethod): boolean;\n\n /** 具体的网络适配器 */\n adapter: NetworkAdapter;\n}\n\n/**\n * 请求链规则 (Chain Step)\n */\nexport interface ChainRequestRule {\n /**\n * 结果存储的键名 (Context Key)\n * Fetch 结果存储: context[key] = response\n */\n key?: string;\n\n /**\n * HTTP 请求详情\n */\n request: HttpRequestSpec;\n\n /**\n * 数据提取选择器\n * 用于从响应中提取特定数据, e.g., \"elements.0\"\n */\n selector?: string;\n\n /** 是否允许请求失败 (默认 false) */\n optional?: boolean;\n\n /**\n * 是否包含上下文\n * 如果为 true,请求 Body 将自动合并当前 Context 和 Payload\n */\n includeContext?: boolean;\n\n /**\n * 上下文筛选列表 (优先级高于 includeContext)\n * 指定需要合并到 Body 中的 Context Key 列表\n * e.g., [\"rawProfile\", \"rawCompany\"]\n */\n pickContext?: string[];\n}\n\n// ============================================================================\n// Internal Utilities\n// ============================================================================\n\n/**\n * 执行 HTTP 请求\n * 遍历 handlers 数组,找到第一个能处理该 URL 的适配器执行\n *\n * @param spec 请求详情\n * @param handlers 网络处理器链\n */\nasync function executeChainRequest<T>(\n spec: HttpRequestSpec,\n handlers: NetworkHandler[] = [],\n): Promise<T | null> {\n // Normalize method to upper case for robustness\n const method = spec.method.toUpperCase() as HttpMethod;\n\n // 1. 遍历处理器数组 (责任链)\n for (const handler of handlers) {\n if (handler.shouldHandle(spec.url, method)) {\n try {\n const { adapter } = handler;\n const headers = spec.headers;\n\n switch (method) {\n case \"GET\":\n return await adapter.get<T>(spec.url, spec.body, headers);\n case \"POST\":\n return await adapter.post<T>(spec.url, spec.body, headers);\n case \"PUT\":\n if (!adapter.put)\n throw new Error(`Adapter ${handler.name} missing PUT method`);\n return await adapter.put<T>(spec.url, spec.body, headers);\n case \"DELETE\":\n if (!adapter.delete)\n throw new Error(`Adapter ${handler.name} missing DELETE method`);\n return await adapter.delete<T>(spec.url, spec.body, headers);\n case \"PATCH\":\n if (!adapter.patch)\n throw new Error(`Adapter ${handler.name} missing PATCH method`);\n return await adapter.patch<T>(spec.url, spec.body, headers);\n default:\n throw new Error(`Unsupported method: ${method}`);\n }\n } catch (err) {\n console.warn(\n `Handler [${handler.name || \"Anonymous\"}] failed for ${spec.url}`,\n err,\n );\n // 如果需要继续尝试下一个 handler,可以在这里 continue,但通常由第一个匹配者全权负责\n return null;\n }\n }\n }\n\n // 2. 默认行为 (Fallback): 绝对路径自动走标准 fetch\n if (spec.url.startsWith(\"http://\") || spec.url.startsWith(\"https://\")) {\n return await executeFallbackFetch<T>(spec);\n }\n\n console.warn(`No handler found for url: ${spec.url}`);\n return null;\n}\n\n/**\n * 标准 Fetch 回退实现\n */\nasync function executeFallbackFetch<T>(\n spec: HttpRequestSpec,\n): Promise<T | null> {\n try {\n const response = await fetch(spec.url, {\n method: spec.method,\n headers: spec.headers,\n body: spec.body ? JSON.stringify(spec.body) : undefined,\n credentials: \"include\",\n });\n\n if (!response.ok) {\n console.log(`External Request failed: ${response.status} ${spec.url}`);\n return null;\n }\n\n return await response.json();\n } catch (err) {\n console.log(\"External Request error:\", err);\n return null;\n }\n}\n\n/**\n * 根据路径获取对象值\n */\nfunction getByPath(obj: any, path: string): any {\n if (!path) return obj;\n return path.split(\".\").reduce((acc, part) => acc && acc[part], obj);\n}\n\n/**\n * 变量替换 (Internal)\n * 支持字符串 {{key}} 和 {{key.prop}}\n */\nfunction substituteVariables(target: any, context: any): any {\n if (typeof target === \"string\") {\n return target.replace(/\\{\\{([\\w\\.]+)\\}\\}/g, (_, path) => {\n const val = getByPath(context, path);\n return val !== undefined ? String(val) : \"\";\n });\n }\n\n if (Array.isArray(target)) {\n return target.map((item) => substituteVariables(item, context));\n }\n\n if (target && typeof target === \"object\") {\n const result: any = {};\n for (const key in target) {\n result[key] = substituteVariables(target[key], context);\n }\n return result;\n }\n\n return target;\n}\n\n// ============================================================================\n// Main Runner\n// ============================================================================\n\n/**\n * 请求链执行器 (Request Chain Engine)\n * 支持链式请求、上下文累积、智能路由、变量替换\n *\n * @param requests 链式执行规则列表\n * @param handlers 网络适配器处理器列表 (按顺序匹配)\n */\nexport async function executeRequestChain<T>(\n requests: ChainRequestRule[],\n handlers: NetworkHandler[] = [],\n getChainRequests?: (\n context: Record<string, any>,\n ) => ChainRequestRule[] | null | undefined,\n initContext?: Record<string, any>,\n): Promise<T> {\n const context: Record<string, any> = initContext || {};\n let lastResult: any = null;\n\n for (const rule of requests) {\n try {\n // 1. 准备 Context Data (用于 Submit)\n let contextData: Record<string, any> = {};\n if (rule.pickContext) {\n rule.pickContext.forEach((key) => {\n if (key in context) contextData[key] = context[key];\n });\n } else if (rule.includeContext) {\n contextData = context;\n }\n const hasContextData = Object.keys(contextData).length > 0;\n\n // 2. 准备 Request Spec (合并 Context 到 Body)\n let requestSpec = { ...rule.request };\n if (hasContextData) {\n requestSpec.body = {\n ...contextData,\n ...(requestSpec.body || {}),\n };\n }\n\n // 3. 变量替换\n requestSpec = substituteVariables(requestSpec, context);\n\n // 4. 执行请求 (传入 handlers)\n let rawData = await executeChainRequest<any>(requestSpec, handlers);\n\n if (getChainRequests) {\n const chainRequests = getChainRequests(rawData);\n if (chainRequests && chainRequests.length > 0) {\n rawData = await executeRequestChain(\n chainRequests,\n handlers,\n getChainRequests,\n JSON.parse(JSON.stringify(context)),\n );\n }\n }\n\n lastResult = rawData;\n\n if (rawData) {\n // 5. 存储结果\n if (rule.key) {\n const data = rule.selector\n ? getByPath(rawData, rule.selector)\n : rawData;\n context[rule.key] = data;\n }\n } else if (!rule.optional) {\n throw new Error(\n `Failed to fetch required data for key: ${rule.key || \"unknown\"}`,\n );\n }\n } catch (err) {\n if (!rule.optional) {\n throw err;\n }\n console.warn(`Optional request failed for rule:`, rule, err);\n }\n }\n\n return lastResult as T;\n}\n"],"mappings":"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","names":[]}
package/dist/chain.mjs ADDED
@@ -0,0 +1,7 @@
1
+ import {
2
+ executeRequestChain
3
+ } from "./chunk-5CXSMOKF.mjs";
4
+ export {
5
+ executeRequestChain
6
+ };
7
+ //# sourceMappingURL=chain.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,143 @@
1
+ // src/chain.ts
2
+ async function executeChainRequest(spec, handlers = []) {
3
+ const method = spec.method.toUpperCase();
4
+ for (const handler of handlers) {
5
+ if (handler.shouldHandle(spec.url, method)) {
6
+ try {
7
+ const { adapter } = handler;
8
+ const headers = spec.headers;
9
+ switch (method) {
10
+ case "GET":
11
+ return await adapter.get(spec.url, spec.body, headers);
12
+ case "POST":
13
+ return await adapter.post(spec.url, spec.body, headers);
14
+ case "PUT":
15
+ if (!adapter.put)
16
+ throw new Error(`Adapter ${handler.name} missing PUT method`);
17
+ return await adapter.put(spec.url, spec.body, headers);
18
+ case "DELETE":
19
+ if (!adapter.delete)
20
+ throw new Error(`Adapter ${handler.name} missing DELETE method`);
21
+ return await adapter.delete(spec.url, spec.body, headers);
22
+ case "PATCH":
23
+ if (!adapter.patch)
24
+ throw new Error(`Adapter ${handler.name} missing PATCH method`);
25
+ return await adapter.patch(spec.url, spec.body, headers);
26
+ default:
27
+ throw new Error(`Unsupported method: ${method}`);
28
+ }
29
+ } catch (err) {
30
+ console.warn(
31
+ `Handler [${handler.name || "Anonymous"}] failed for ${spec.url}`,
32
+ err
33
+ );
34
+ return null;
35
+ }
36
+ }
37
+ }
38
+ if (spec.url.startsWith("http://") || spec.url.startsWith("https://")) {
39
+ return await executeFallbackFetch(spec);
40
+ }
41
+ console.warn(`No handler found for url: ${spec.url}`);
42
+ return null;
43
+ }
44
+ async function executeFallbackFetch(spec) {
45
+ try {
46
+ const response = await fetch(spec.url, {
47
+ method: spec.method,
48
+ headers: spec.headers,
49
+ body: spec.body ? JSON.stringify(spec.body) : void 0,
50
+ credentials: "include"
51
+ });
52
+ if (!response.ok) {
53
+ console.log(`External Request failed: ${response.status} ${spec.url}`);
54
+ return null;
55
+ }
56
+ return await response.json();
57
+ } catch (err) {
58
+ console.log("External Request error:", err);
59
+ return null;
60
+ }
61
+ }
62
+ function getByPath(obj, path) {
63
+ if (!path) return obj;
64
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
65
+ }
66
+ function substituteVariables(target, context) {
67
+ if (typeof target === "string") {
68
+ return target.replace(/\{\{([\w\.]+)\}\}/g, (_, path) => {
69
+ const val = getByPath(context, path);
70
+ return val !== void 0 ? String(val) : "";
71
+ });
72
+ }
73
+ if (Array.isArray(target)) {
74
+ return target.map((item) => substituteVariables(item, context));
75
+ }
76
+ if (target && typeof target === "object") {
77
+ const result = {};
78
+ for (const key in target) {
79
+ result[key] = substituteVariables(target[key], context);
80
+ }
81
+ return result;
82
+ }
83
+ return target;
84
+ }
85
+ async function executeRequestChain(requests, handlers = [], getChainRequests, initContext) {
86
+ const context = initContext || {};
87
+ let lastResult = null;
88
+ for (const rule of requests) {
89
+ try {
90
+ let contextData = {};
91
+ if (rule.pickContext) {
92
+ rule.pickContext.forEach((key) => {
93
+ if (key in context) contextData[key] = context[key];
94
+ });
95
+ } else if (rule.includeContext) {
96
+ contextData = context;
97
+ }
98
+ const hasContextData = Object.keys(contextData).length > 0;
99
+ let requestSpec = { ...rule.request };
100
+ if (hasContextData) {
101
+ requestSpec.body = {
102
+ ...contextData,
103
+ ...requestSpec.body || {}
104
+ };
105
+ }
106
+ requestSpec = substituteVariables(requestSpec, context);
107
+ let rawData = await executeChainRequest(requestSpec, handlers);
108
+ if (getChainRequests) {
109
+ const chainRequests = getChainRequests(rawData);
110
+ if (chainRequests && chainRequests.length > 0) {
111
+ rawData = await executeRequestChain(
112
+ chainRequests,
113
+ handlers,
114
+ getChainRequests,
115
+ JSON.parse(JSON.stringify(context))
116
+ );
117
+ }
118
+ }
119
+ lastResult = rawData;
120
+ if (rawData) {
121
+ if (rule.key) {
122
+ const data = rule.selector ? getByPath(rawData, rule.selector) : rawData;
123
+ context[rule.key] = data;
124
+ }
125
+ } else if (!rule.optional) {
126
+ throw new Error(
127
+ `Failed to fetch required data for key: ${rule.key || "unknown"}`
128
+ );
129
+ }
130
+ } catch (err) {
131
+ if (!rule.optional) {
132
+ throw err;
133
+ }
134
+ console.warn(`Optional request failed for rule:`, rule, err);
135
+ }
136
+ }
137
+ return lastResult;
138
+ }
139
+
140
+ export {
141
+ executeRequestChain
142
+ };
143
+ //# sourceMappingURL=chunk-5CXSMOKF.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/chain.ts"],"sourcesContent":["/**\n * Request Chain Runner\n * 负责解析和执行通用的 HTTP 请求链 (Chain Execution)\n * 适用于任何需要链式 HTTP 请求编排的场景\n */\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\n/** Supported HTTP Methods */\ntype HttpMethod = \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\n\n/** HTTP 请求参数 */\nexport interface HttpRequestSpec {\n method: HttpMethod;\n url: string;\n headers?: Record<string, string>;\n body?: any;\n}\n\n/**\n * 网络适配器接口\n * 定义实际发送请求的能力\n */\n/**\n * 网络适配器接口\n * 定义实际发送请求的能力\n */\nexport interface NetworkAdapter {\n get<T>(\n url: string,\n params?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n post<T>(\n url: string,\n body?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n put?<T>(\n url: string,\n body?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n delete?<T>(\n url: string,\n params?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n patch?<T>(\n url: string,\n body?: any,\n headers?: Record<string, string>,\n ): Promise<T>;\n}\n\n/**\n * 网络处理器接口 (Strategy Pattern)\n * 组合了\"匹配规则\"和\"执行能力\"\n */\nexport interface NetworkHandler {\n /** 处理器名称 (用于调试) */\n name?: string;\n\n /** 判断该 URL 是否由此适配器处理 */\n shouldHandle(url: string, method: HttpMethod): boolean;\n\n /** 具体的网络适配器 */\n adapter: NetworkAdapter;\n}\n\n/**\n * 请求链规则 (Chain Step)\n */\nexport interface ChainRequestRule {\n /**\n * 结果存储的键名 (Context Key)\n * Fetch 结果存储: context[key] = response\n */\n key?: string;\n\n /**\n * HTTP 请求详情\n */\n request: HttpRequestSpec;\n\n /**\n * 数据提取选择器\n * 用于从响应中提取特定数据, e.g., \"elements.0\"\n */\n selector?: string;\n\n /** 是否允许请求失败 (默认 false) */\n optional?: boolean;\n\n /**\n * 是否包含上下文\n * 如果为 true,请求 Body 将自动合并当前 Context 和 Payload\n */\n includeContext?: boolean;\n\n /**\n * 上下文筛选列表 (优先级高于 includeContext)\n * 指定需要合并到 Body 中的 Context Key 列表\n * e.g., [\"rawProfile\", \"rawCompany\"]\n */\n pickContext?: string[];\n}\n\n// ============================================================================\n// Internal Utilities\n// ============================================================================\n\n/**\n * 执行 HTTP 请求\n * 遍历 handlers 数组,找到第一个能处理该 URL 的适配器执行\n *\n * @param spec 请求详情\n * @param handlers 网络处理器链\n */\nasync function executeChainRequest<T>(\n spec: HttpRequestSpec,\n handlers: NetworkHandler[] = [],\n): Promise<T | null> {\n // Normalize method to upper case for robustness\n const method = spec.method.toUpperCase() as HttpMethod;\n\n // 1. 遍历处理器数组 (责任链)\n for (const handler of handlers) {\n if (handler.shouldHandle(spec.url, method)) {\n try {\n const { adapter } = handler;\n const headers = spec.headers;\n\n switch (method) {\n case \"GET\":\n return await adapter.get<T>(spec.url, spec.body, headers);\n case \"POST\":\n return await adapter.post<T>(spec.url, spec.body, headers);\n case \"PUT\":\n if (!adapter.put)\n throw new Error(`Adapter ${handler.name} missing PUT method`);\n return await adapter.put<T>(spec.url, spec.body, headers);\n case \"DELETE\":\n if (!adapter.delete)\n throw new Error(`Adapter ${handler.name} missing DELETE method`);\n return await adapter.delete<T>(spec.url, spec.body, headers);\n case \"PATCH\":\n if (!adapter.patch)\n throw new Error(`Adapter ${handler.name} missing PATCH method`);\n return await adapter.patch<T>(spec.url, spec.body, headers);\n default:\n throw new Error(`Unsupported method: ${method}`);\n }\n } catch (err) {\n console.warn(\n `Handler [${handler.name || \"Anonymous\"}] failed for ${spec.url}`,\n err,\n );\n // 如果需要继续尝试下一个 handler,可以在这里 continue,但通常由第一个匹配者全权负责\n return null;\n }\n }\n }\n\n // 2. 默认行为 (Fallback): 绝对路径自动走标准 fetch\n if (spec.url.startsWith(\"http://\") || spec.url.startsWith(\"https://\")) {\n return await executeFallbackFetch<T>(spec);\n }\n\n console.warn(`No handler found for url: ${spec.url}`);\n return null;\n}\n\n/**\n * 标准 Fetch 回退实现\n */\nasync function executeFallbackFetch<T>(\n spec: HttpRequestSpec,\n): Promise<T | null> {\n try {\n const response = await fetch(spec.url, {\n method: spec.method,\n headers: spec.headers,\n body: spec.body ? JSON.stringify(spec.body) : undefined,\n credentials: \"include\",\n });\n\n if (!response.ok) {\n console.log(`External Request failed: ${response.status} ${spec.url}`);\n return null;\n }\n\n return await response.json();\n } catch (err) {\n console.log(\"External Request error:\", err);\n return null;\n }\n}\n\n/**\n * 根据路径获取对象值\n */\nfunction getByPath(obj: any, path: string): any {\n if (!path) return obj;\n return path.split(\".\").reduce((acc, part) => acc && acc[part], obj);\n}\n\n/**\n * 变量替换 (Internal)\n * 支持字符串 {{key}} 和 {{key.prop}}\n */\nfunction substituteVariables(target: any, context: any): any {\n if (typeof target === \"string\") {\n return target.replace(/\\{\\{([\\w\\.]+)\\}\\}/g, (_, path) => {\n const val = getByPath(context, path);\n return val !== undefined ? String(val) : \"\";\n });\n }\n\n if (Array.isArray(target)) {\n return target.map((item) => substituteVariables(item, context));\n }\n\n if (target && typeof target === \"object\") {\n const result: any = {};\n for (const key in target) {\n result[key] = substituteVariables(target[key], context);\n }\n return result;\n }\n\n return target;\n}\n\n// ============================================================================\n// Main Runner\n// ============================================================================\n\n/**\n * 请求链执行器 (Request Chain Engine)\n * 支持链式请求、上下文累积、智能路由、变量替换\n *\n * @param requests 链式执行规则列表\n * @param handlers 网络适配器处理器列表 (按顺序匹配)\n */\nexport async function executeRequestChain<T>(\n requests: ChainRequestRule[],\n handlers: NetworkHandler[] = [],\n getChainRequests?: (\n context: Record<string, any>,\n ) => ChainRequestRule[] | null | undefined,\n initContext?: Record<string, any>,\n): Promise<T> {\n const context: Record<string, any> = initContext || {};\n let lastResult: any = null;\n\n for (const rule of requests) {\n try {\n // 1. 准备 Context Data (用于 Submit)\n let contextData: Record<string, any> = {};\n if (rule.pickContext) {\n rule.pickContext.forEach((key) => {\n if (key in context) contextData[key] = context[key];\n });\n } else if (rule.includeContext) {\n contextData = context;\n }\n const hasContextData = Object.keys(contextData).length > 0;\n\n // 2. 准备 Request Spec (合并 Context 到 Body)\n let requestSpec = { ...rule.request };\n if (hasContextData) {\n requestSpec.body = {\n ...contextData,\n ...(requestSpec.body || {}),\n };\n }\n\n // 3. 变量替换\n requestSpec = substituteVariables(requestSpec, context);\n\n // 4. 执行请求 (传入 handlers)\n let rawData = await executeChainRequest<any>(requestSpec, handlers);\n\n if (getChainRequests) {\n const chainRequests = getChainRequests(rawData);\n if (chainRequests && chainRequests.length > 0) {\n rawData = await executeRequestChain(\n chainRequests,\n handlers,\n getChainRequests,\n JSON.parse(JSON.stringify(context)),\n );\n }\n }\n\n lastResult = rawData;\n\n if (rawData) {\n // 5. 存储结果\n if (rule.key) {\n const data = rule.selector\n ? getByPath(rawData, rule.selector)\n : rawData;\n context[rule.key] = data;\n }\n } else if (!rule.optional) {\n throw new Error(\n `Failed to fetch required data for key: ${rule.key || \"unknown\"}`,\n );\n }\n } catch (err) {\n if (!rule.optional) {\n throw err;\n }\n console.warn(`Optional request failed for rule:`, rule, err);\n }\n }\n\n return lastResult as T;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,302 @@
1
+ // src/secure.js
2
+ import * as $protobuf from "protobufjs/minimal";
3
+ var $Reader = $protobuf.Reader;
4
+ var $Writer = $protobuf.Writer;
5
+ var $util = $protobuf.util;
6
+ var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
7
+ var secure = $root.secure = (() => {
8
+ const secure2 = {};
9
+ secure2.SecurePayload = (function() {
10
+ function SecurePayload(properties) {
11
+ if (properties) {
12
+ for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)
13
+ if (properties[keys[i]] != null)
14
+ this[keys[i]] = properties[keys[i]];
15
+ }
16
+ }
17
+ SecurePayload.prototype.ts = $util.Long ? $util.Long.fromBits(0, 0, false) : 0;
18
+ SecurePayload.prototype.data = $util.newBuffer([]);
19
+ SecurePayload.create = function create(properties) {
20
+ return new SecurePayload(properties);
21
+ };
22
+ SecurePayload.encode = function encode(message, writer) {
23
+ if (!writer)
24
+ writer = $Writer.create();
25
+ if (message.ts != null && Object.hasOwnProperty.call(message, "ts"))
26
+ writer.uint32(
27
+ /* id 1, wireType 0 =*/
28
+ 8
29
+ ).int64(message.ts);
30
+ if (message.data != null && Object.hasOwnProperty.call(message, "data"))
31
+ writer.uint32(
32
+ /* id 2, wireType 2 =*/
33
+ 18
34
+ ).bytes(message.data);
35
+ return writer;
36
+ };
37
+ SecurePayload.encodeDelimited = function encodeDelimited(message, writer) {
38
+ return this.encode(message, writer).ldelim();
39
+ };
40
+ SecurePayload.decode = function decode(reader, length, error) {
41
+ if (!(reader instanceof $Reader))
42
+ reader = $Reader.create(reader);
43
+ let end = length === void 0 ? reader.len : reader.pos + length, message = new $root.secure.SecurePayload();
44
+ while (reader.pos < end) {
45
+ let tag = reader.uint32();
46
+ if (tag === error)
47
+ break;
48
+ switch (tag >>> 3) {
49
+ case 1: {
50
+ message.ts = reader.int64();
51
+ break;
52
+ }
53
+ case 2: {
54
+ message.data = reader.bytes();
55
+ break;
56
+ }
57
+ default:
58
+ reader.skipType(tag & 7);
59
+ break;
60
+ }
61
+ }
62
+ return message;
63
+ };
64
+ SecurePayload.decodeDelimited = function decodeDelimited(reader) {
65
+ if (!(reader instanceof $Reader))
66
+ reader = new $Reader(reader);
67
+ return this.decode(reader, reader.uint32());
68
+ };
69
+ SecurePayload.verify = function verify(message) {
70
+ if (typeof message !== "object" || message === null)
71
+ return "object expected";
72
+ if (message.ts != null && message.hasOwnProperty("ts")) {
73
+ if (!$util.isInteger(message.ts) && !(message.ts && $util.isInteger(message.ts.low) && $util.isInteger(message.ts.high)))
74
+ return "ts: integer|Long expected";
75
+ }
76
+ if (message.data != null && message.hasOwnProperty("data")) {
77
+ if (!(message.data && typeof message.data.length === "number" || $util.isString(message.data)))
78
+ return "data: buffer expected";
79
+ }
80
+ return null;
81
+ };
82
+ SecurePayload.fromObject = function fromObject(object) {
83
+ if (object instanceof $root.secure.SecurePayload)
84
+ return object;
85
+ let message = new $root.secure.SecurePayload();
86
+ if (object.ts != null) {
87
+ if ($util.Long)
88
+ (message.ts = $util.Long.fromValue(object.ts)).unsigned = false;
89
+ else if (typeof object.ts === "string")
90
+ message.ts = parseInt(object.ts, 10);
91
+ else if (typeof object.ts === "number")
92
+ message.ts = object.ts;
93
+ else if (typeof object.ts === "object")
94
+ message.ts = new $util.LongBits(object.ts.low >>> 0, object.ts.high >>> 0).toNumber();
95
+ }
96
+ if (object.data != null) {
97
+ if (typeof object.data === "string")
98
+ $util.base64.decode(object.data, message.data = $util.newBuffer($util.base64.length(object.data)), 0);
99
+ else if (object.data.length >= 0)
100
+ message.data = object.data;
101
+ }
102
+ return message;
103
+ };
104
+ SecurePayload.toObject = function toObject(message, options) {
105
+ if (!options)
106
+ options = {};
107
+ let object = {};
108
+ if (options.defaults) {
109
+ if ($util.Long) {
110
+ let long = new $util.Long(0, 0, false);
111
+ object.ts = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long;
112
+ } else
113
+ object.ts = options.longs === String ? "0" : 0;
114
+ if (options.bytes === String)
115
+ object.data = "";
116
+ else {
117
+ object.data = [];
118
+ if (options.bytes !== Array)
119
+ object.data = $util.newBuffer(object.data);
120
+ }
121
+ }
122
+ if (message.ts != null && message.hasOwnProperty("ts"))
123
+ if (typeof message.ts === "number")
124
+ object.ts = options.longs === String ? String(message.ts) : message.ts;
125
+ else
126
+ object.ts = options.longs === String ? $util.Long.prototype.toString.call(message.ts) : options.longs === Number ? new $util.LongBits(message.ts.low >>> 0, message.ts.high >>> 0).toNumber() : message.ts;
127
+ if (message.data != null && message.hasOwnProperty("data"))
128
+ object.data = options.bytes === String ? $util.base64.encode(message.data, 0, message.data.length) : options.bytes === Array ? Array.prototype.slice.call(message.data) : message.data;
129
+ return object;
130
+ };
131
+ SecurePayload.prototype.toJSON = function toJSON() {
132
+ return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
133
+ };
134
+ SecurePayload.getTypeUrl = function getTypeUrl(typeUrlPrefix) {
135
+ if (typeUrlPrefix === void 0) {
136
+ typeUrlPrefix = "type.googleapis.com";
137
+ }
138
+ return typeUrlPrefix + "/secure.SecurePayload";
139
+ };
140
+ return SecurePayload;
141
+ })();
142
+ return secure2;
143
+ })();
144
+
145
+ // src/protobuf.ts
146
+ var PROTOBUF_CONTENT_TYPE = "application/x-protobuf";
147
+ function isProtobufContentType(contentType) {
148
+ return !!contentType?.toLowerCase().includes(PROTOBUF_CONTENT_TYPE);
149
+ }
150
+ function setProtobufRequestHeaders(existingHeaders, mode = "both") {
151
+ const headers = new Headers(existingHeaders);
152
+ if (mode === "send" || mode === "both") {
153
+ headers.set("Content-Type", PROTOBUF_CONTENT_TYPE);
154
+ }
155
+ if (mode === "receive" || mode === "both") {
156
+ headers.set("Accept", PROTOBUF_CONTENT_TYPE);
157
+ }
158
+ return headers;
159
+ }
160
+ var encoder = new TextEncoder();
161
+ var decoder = new TextDecoder();
162
+ function xorTransform(data, key) {
163
+ const keyBytes = typeof key === "string" ? encoder.encode(key) : key;
164
+ if (keyBytes.length === 0) return data;
165
+ for (let i = 0; i < data.length; i++) {
166
+ data[i] ^= keyBytes[i % keyBytes.length];
167
+ }
168
+ return data;
169
+ }
170
+ function createXorObfuscator(key) {
171
+ return {
172
+ encrypt: (data) => xorTransform(data, key),
173
+ decrypt: (data) => xorTransform(data, key)
174
+ };
175
+ }
176
+ function getInternalSecureType() {
177
+ return secure.SecurePayload;
178
+ }
179
+ async function encodeSecure(data, options = {}) {
180
+ const { obfuscator, protoType, transform, encode: customEncode } = options;
181
+ let buffer;
182
+ const processedData = transform?.beforeEncode ? transform.beforeEncode(data) : data;
183
+ if (customEncode) {
184
+ buffer = await customEncode(processedData);
185
+ } else {
186
+ const type = protoType || getInternalSecureType();
187
+ const payload = protoType ? processedData : {
188
+ // 默认容器模式:将预处理后的数据封装进信封
189
+ ts: Date.now(),
190
+ data: processedData instanceof Uint8Array ? processedData : encoder.encode(JSON.stringify(processedData))
191
+ };
192
+ const message = type.create(payload);
193
+ buffer = type.encode(message).finish();
194
+ }
195
+ if (obfuscator) {
196
+ return await obfuscator.encrypt(buffer);
197
+ }
198
+ return buffer;
199
+ }
200
+ async function decodeSecure(buffer, options = {}) {
201
+ const { obfuscator, protoType, transform, decode: customDecode } = options;
202
+ let uint8 = ArrayBuffer.isView(buffer) ? new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength) : new Uint8Array(buffer);
203
+ if (uint8.length === 0) {
204
+ return null;
205
+ }
206
+ if (uint8.length > 0 && obfuscator) {
207
+ uint8 = await obfuscator.decrypt(uint8);
208
+ }
209
+ if (customDecode) {
210
+ return await customDecode(uint8);
211
+ }
212
+ const type = protoType || getInternalSecureType();
213
+ const decoded = type.decode(uint8);
214
+ const plainObj = type.toObject(decoded, {
215
+ longs: String,
216
+ enums: String,
217
+ bytes: Uint8Array,
218
+ defaults: true
219
+ });
220
+ if (transform?.afterDecode) {
221
+ return transform.afterDecode(plainObj);
222
+ }
223
+ if (!protoType && plainObj.data) {
224
+ const jsonString = decoder.decode(plainObj.data);
225
+ try {
226
+ return JSON.parse(jsonString);
227
+ } catch {
228
+ return jsonString;
229
+ }
230
+ }
231
+ return plainObj;
232
+ }
233
+ async function secureResponse(data, options) {
234
+ const buffer = await encodeSecure(data, options);
235
+ const cleanBuffer = buffer.slice();
236
+ return new Response(cleanBuffer, {
237
+ headers: {
238
+ "Content-Type": "application/x-protobuf",
239
+ ...options?.corsHeaders
240
+ }
241
+ });
242
+ }
243
+ async function parseSecureRequest(request, options = {}) {
244
+ const buffer = await request.arrayBuffer();
245
+ return decodeSecure(buffer, options);
246
+ }
247
+ function createProtobufHooks(globalOptions = {}) {
248
+ return {
249
+ async onRequest(context) {
250
+ const { options: reqOptions } = context;
251
+ const mergedOptions = {
252
+ ...globalOptions,
253
+ ...reqOptions
254
+ };
255
+ const headers = reqOptions.headers instanceof Headers ? reqOptions.headers : new Headers(reqOptions.headers);
256
+ if (isProtobufContentType(headers.get("Content-Type")) && reqOptions.body && !(reqOptions.body instanceof Uint8Array)) {
257
+ reqOptions.body = await encodeSecure(reqOptions.body, mergedOptions);
258
+ }
259
+ if (isProtobufContentType(headers.get("Accept")) && !reqOptions.responseType) {
260
+ reqOptions.responseType = "arrayBuffer";
261
+ }
262
+ reqOptions.headers = headers;
263
+ },
264
+ async onResponse(context) {
265
+ const { response, options: reqOptions } = context;
266
+ if (!response?._data || response.status === 204) return;
267
+ const mergedOptions = {
268
+ ...globalOptions,
269
+ ...reqOptions
270
+ };
271
+ if (isProtobufContentType(response.headers.get("Content-Type"))) {
272
+ try {
273
+ response._data = await decodeSecure(response._data, mergedOptions);
274
+ } catch (e) {
275
+ console.log("Error [Protobuf Decode Error]", e);
276
+ response._data = null;
277
+ }
278
+ } else if (response._data instanceof ArrayBuffer) {
279
+ const text = decoder.decode(response._data);
280
+ try {
281
+ response._data = JSON.parse(text);
282
+ } catch {
283
+ response._data = text;
284
+ }
285
+ }
286
+ }
287
+ };
288
+ }
289
+
290
+ export {
291
+ PROTOBUF_CONTENT_TYPE,
292
+ isProtobufContentType,
293
+ setProtobufRequestHeaders,
294
+ xorTransform,
295
+ createXorObfuscator,
296
+ encodeSecure,
297
+ decodeSecure,
298
+ secureResponse,
299
+ parseSecureRequest,
300
+ createProtobufHooks
301
+ };
302
+ //# sourceMappingURL=chunk-SAIJRTYF.mjs.map