@i.un/api-client 1.1.1 → 1.1.3
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/README.md +172 -3
- package/README.zh-CN.md +172 -3
- package/dist/chain.d.mts +85 -0
- package/dist/chain.d.ts +85 -0
- package/dist/chain.js +168 -0
- package/dist/chain.js.map +1 -0
- package/dist/chain.mjs +7 -0
- package/dist/chain.mjs.map +1 -0
- package/dist/chunk-SJA6WQ2W.mjs +144 -0
- package/dist/chunk-SJA6WQ2W.mjs.map +1 -0
- package/dist/chunk-XARZ5KSG.mjs +182 -0
- package/dist/chunk-XARZ5KSG.mjs.map +1 -0
- package/dist/chunk-YUPTRDEZ.mjs +315 -0
- package/dist/chunk-YUPTRDEZ.mjs.map +1 -0
- package/dist/client.d.mts +54 -0
- package/dist/client.d.ts +54 -0
- package/dist/client.js +205 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +9 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.d.mts +5 -221
- package/dist/index.d.ts +5 -221
- package/dist/index.js +35 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19 -610
- package/dist/index.mjs.map +1 -1
- package/dist/protobuf.d.mts +92 -0
- package/dist/protobuf.d.ts +92 -0
- package/dist/protobuf.js +359 -0
- package/dist/protobuf.js.map +1 -0
- package/dist/protobuf.mjs +23 -0
- package/dist/protobuf.mjs.map +1 -0
- package/package.json +16 -1
package/README.md
CHANGED
|
@@ -90,9 +90,9 @@ You can override this protocol via configuration (see "Advanced: custom unwrappi
|
|
|
90
90
|
|
|
91
91
|
```ts
|
|
92
92
|
export interface ApiError extends Error {
|
|
93
|
-
code: number;
|
|
94
|
-
data?: unknown;
|
|
95
|
-
status?: number;
|
|
93
|
+
code: number; // business error code
|
|
94
|
+
data?: unknown; // backend data field
|
|
95
|
+
status?: number; // HTTP status code (for network-level errors)
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export const isApiError = (error: unknown): error is ApiError => {
|
|
@@ -267,8 +267,177 @@ The protocol details are entirely up to you.
|
|
|
267
267
|
|
|
268
268
|
---
|
|
269
269
|
|
|
270
|
+
## Request Chain Execution
|
|
271
|
+
|
|
272
|
+
The Request Chain engine (`executeRequestChain`) allows you to coordinate multiple dependent HTTP requests. It manages a shared **Context**, handles **Variable Substitution**, and supports **Smart Routing** via a strategy pattern.
|
|
273
|
+
|
|
274
|
+
### Core Concepts
|
|
275
|
+
|
|
276
|
+
- **Rule (`ChainRequestRule`)**: Defines a single step in the chain.
|
|
277
|
+
- **Context**: A shared object that accumulates results. Every step can read from and write to the context.
|
|
278
|
+
- **Handler (`NetworkHandler`)**: Decides which **Adapter** should execute a particular request based on the URL or Method.
|
|
279
|
+
|
|
280
|
+
### Rule Configuration (`ChainRequestRule`)
|
|
281
|
+
|
|
282
|
+
| Property | Type | Description |
|
|
283
|
+
| :--------------- | :---------------- | :------------------------------------------------------------------------------------------ |
|
|
284
|
+
| `key` | `string` | The key to store the result in the Context. |
|
|
285
|
+
| `request` | `HttpRequestSpec` | Method, URL, Headers, and initial Body. |
|
|
286
|
+
| `selector` | `string` | Optional. A dot-notation path (e.g., `user.id`) to extract specific data from the response. |
|
|
287
|
+
| `includeContext` | `boolean` | If true, the entire Context is merged into the request `body`. |
|
|
288
|
+
| `pickContext` | `string[]` | Specific keys from the Context to merge into the request `body`. |
|
|
289
|
+
| `payload` | `object` | Static data to merge into the request `body`. |
|
|
290
|
+
| `optional` | `boolean` | If true, the chain continues even if this request fails. |
|
|
291
|
+
|
|
292
|
+
### Variable Substitution
|
|
293
|
+
|
|
294
|
+
You can use `{{key.path}}` in `url`, `headers`, and `body`. The engine will replace these placeholders with values from the current Context.
|
|
295
|
+
|
|
296
|
+
### Detailed Example: 3-Step Orchestration
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
import { executeRequestChain } from "@i.un/api-client";
|
|
300
|
+
|
|
301
|
+
const rules = [
|
|
302
|
+
// Step 1: Get session
|
|
303
|
+
{
|
|
304
|
+
key: "auth",
|
|
305
|
+
request: { method: "POST", url: "/login", body: { user: "admin" } },
|
|
306
|
+
},
|
|
307
|
+
// Step 2: Use session token in URL and Headers
|
|
308
|
+
{
|
|
309
|
+
key: "profile",
|
|
310
|
+
request: {
|
|
311
|
+
method: "GET",
|
|
312
|
+
url: "/users/{{auth.userId}}",
|
|
313
|
+
headers: { "X-Session": "{{auth.token}}" },
|
|
314
|
+
},
|
|
315
|
+
selector: "data", // context.profile will only contain the 'data' field
|
|
316
|
+
},
|
|
317
|
+
// Step 3: Combine previous data into a new request
|
|
318
|
+
{
|
|
319
|
+
key: "update",
|
|
320
|
+
request: { method: "PUT", url: "/sync" },
|
|
321
|
+
pickContext: ["profile"], // body will be { profile: context.profile, ...payload }
|
|
322
|
+
payload: { source: "web-client" },
|
|
323
|
+
},
|
|
324
|
+
];
|
|
325
|
+
|
|
326
|
+
const result = await executeRequestChain(rules);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Custom Routing (Strategy Pattern)
|
|
330
|
+
|
|
331
|
+
You can provide a list of `NetworkHandler`s to route requests to different environments (e.g., redirecting `/ext/*` to a browser extension API while `/api/*` goes to standard fetch).
|
|
332
|
+
|
|
333
|
+
```ts
|
|
334
|
+
const handlers = [
|
|
335
|
+
{
|
|
336
|
+
name: "extension-router",
|
|
337
|
+
shouldHandle: (url) => url.startsWith("chrome-extension://"),
|
|
338
|
+
adapter: {
|
|
339
|
+
post: (url, body) => chrome.runtime.sendMessage({ url, body }),
|
|
340
|
+
get: (url) => ...
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
];
|
|
344
|
+
|
|
345
|
+
await executeRequestChain(rules, handlers);
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## Protobuf & Security
|
|
351
|
+
|
|
352
|
+
The Protobuf module provides a security layer over `ofetch`. It supports binary serialization, XOR obfuscation, and automatic integration via hooks.
|
|
353
|
+
|
|
354
|
+
### The Pipeline
|
|
355
|
+
|
|
356
|
+
1. **Object** -> **Transform** (Optional) -> **Protobuf Encode** -> **XOR Obfuscation** -> **Binary Payload**
|
|
357
|
+
|
|
358
|
+
### Integration Hooks
|
|
359
|
+
|
|
360
|
+
Use `createProtobufHooks` to add Protobuf support to your `api-client` instance.
|
|
361
|
+
|
|
362
|
+
```ts
|
|
363
|
+
import { createApiClient, createProtobufHooks } from "@i.un/api-client";
|
|
364
|
+
|
|
365
|
+
const hooks = createProtobufHooks({
|
|
366
|
+
// 1. XOR Encryption key (optional but recommended)
|
|
367
|
+
obfuscationKey: () => fetchSecretKeyFromServer(),
|
|
368
|
+
|
|
369
|
+
// 2. Custom transformations
|
|
370
|
+
transform: {
|
|
371
|
+
beforeEncode: (data) => ({ ...data, ts: Date.now() }),
|
|
372
|
+
afterDecode: (res) => res.data,
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
const client = createApiClient({
|
|
377
|
+
baseURL: "/api",
|
|
378
|
+
...hooks,
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
// usage: just set Content-Type or Accept to 'application/x-protobuf'
|
|
382
|
+
const data = await client.post(
|
|
383
|
+
"/secure-endpoint",
|
|
384
|
+
{ foo: "bar" },
|
|
385
|
+
{
|
|
386
|
+
headers: { "Content-Type": "application/x-protobuf" },
|
|
387
|
+
},
|
|
388
|
+
);
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Manual Header Configuration
|
|
392
|
+
|
|
393
|
+
If you are not using the automatic hooks or need to manually configure headers for a specific request, you can use the `setProtobufRequestHeaders` helper:
|
|
394
|
+
|
|
395
|
+
```ts
|
|
396
|
+
import { setProtobufRequestHeaders } from "@i.un/api-client";
|
|
397
|
+
|
|
398
|
+
// 1. Send and receive Protobuf (default)
|
|
399
|
+
const headers = setProtobufRequestHeaders({ "X-Custom": "val" });
|
|
400
|
+
// { "X-Custom": "val", "Content-Type": "application/x-protobuf", "Accept": "application/x-protobuf" }
|
|
401
|
+
|
|
402
|
+
// 2. Only receive Protobuf
|
|
403
|
+
const receiveOnly = setProtobufRequestHeaders({}, "receive");
|
|
404
|
+
// { "Accept": "application/x-protobuf" }
|
|
405
|
+
|
|
406
|
+
// Use with client
|
|
407
|
+
await client.get("/data", { headers: receiveOnly });
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Envelope Mode vs Custom Type Mode
|
|
411
|
+
|
|
412
|
+
- **Envelope Mode (Default)**: If no `protoType` is provided, the library uses a built-in `SecurePayload` (Timestamp + JSON-stringified data). This is the easiest way to hide data from DevTools without defining schemas for every API.
|
|
413
|
+
- **Custom Type Mode**: Provide a `protoType` (compiled from `.proto`) for full binary performance and type safety.
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
const hooks = createProtobufHooks({
|
|
417
|
+
protoType: MyCompiledMessage, // From protobufjs
|
|
418
|
+
});
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### Server-Side Usage (Node/Workers)
|
|
422
|
+
|
|
423
|
+
The library provides utilities for the server/worker side to handle these secure requests.
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
import { parseSecureRequest, secureResponse } from "@i.un/api-client";
|
|
427
|
+
|
|
428
|
+
// 1. Parse incoming request
|
|
429
|
+
const body = await parseSecureRequest(request, { obfuscationKey: "key" });
|
|
430
|
+
|
|
431
|
+
// 2. Send secure response
|
|
432
|
+
return await secureResponse({ success: true }, { obfuscationKey: "key" });
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
270
437
|
## Environment & Notes
|
|
271
438
|
|
|
439
|
+
---
|
|
440
|
+
|
|
272
441
|
- Built on `ofetch`, works in browsers, Node 18+, Nuxt, etc.
|
|
273
442
|
- Requires `fetch` / `Headers`:
|
|
274
443
|
- Browsers: built-in.
|
package/README.zh-CN.md
CHANGED
|
@@ -90,9 +90,9 @@ export interface ApiResult<T> {
|
|
|
90
90
|
|
|
91
91
|
```ts
|
|
92
92
|
export interface ApiError extends Error {
|
|
93
|
-
code: number;
|
|
94
|
-
data?: unknown;
|
|
95
|
-
status?: number;
|
|
93
|
+
code: number; // 业务错误码
|
|
94
|
+
data?: unknown; // 后端 data 字段
|
|
95
|
+
status?: number; // HTTP 状态码(仅网络层错误时可能存在)
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export const isApiError = (error: unknown): error is ApiError => {
|
|
@@ -259,8 +259,177 @@ const client = createApiClient({
|
|
|
259
259
|
|
|
260
260
|
---
|
|
261
261
|
|
|
262
|
+
## 请求链执行 (Request Chain)
|
|
263
|
+
|
|
264
|
+
请求链引擎 (`executeRequestChain`) 允许你编排多个相互依赖的 HTTP 请求。它管理一个共享的 **上下文 (Context)**,处理 **变量替换 (Variable Substitution)**,并支持通过策略模式实现的 **智能路由 (Smart Routing)**。
|
|
265
|
+
|
|
266
|
+
### 核心概念
|
|
267
|
+
|
|
268
|
+
- **规则 (`ChainRequestRule`)**: 定义链中的单个步骤。
|
|
269
|
+
- **上下文 (Context)**: 一个共享对象,用于累积结果。每个步骤都可以从上下文中读取数据或向其中写入结果。
|
|
270
|
+
- **处理器 (`NetworkHandler`)**: 根据 URL 或方法决定哪个 **适配器 (Adapter)** 应该执行特定的请求。
|
|
271
|
+
|
|
272
|
+
### 规则配置 (`ChainRequestRule`)
|
|
273
|
+
|
|
274
|
+
| 属性 | 类型 | 描述 |
|
|
275
|
+
| :--------------- | :---------------- | :----------------------------------------------------------- |
|
|
276
|
+
| `key` | `string` | 结果在上下文中的存储键名。 |
|
|
277
|
+
| `request` | `HttpRequestSpec` | 包含方法、URL、Header 和初始 Body。 |
|
|
278
|
+
| `selector` | `string` | 可选。使用点分隔的路径(如 `user.id`)从响应中提取特定数据。 |
|
|
279
|
+
| `includeContext` | `boolean` | 如果为 true,则将整个上下文合并到请求的 `body` 中。 |
|
|
280
|
+
| `pickContext` | `string[]` | 指定要合并到请求 `body` 中的上下文键列表。 |
|
|
281
|
+
| `payload` | `object` | 要合并到请求 `body` 中的静态数据。 |
|
|
282
|
+
| `optional` | `boolean` | 如果为 true,即使该请求失败,链式执行也会继续。 |
|
|
283
|
+
|
|
284
|
+
### 变量替换
|
|
285
|
+
|
|
286
|
+
你可以在 `url`、`headers` 和 `body` 中使用 `{{key.path}}`。引擎会自动将这些占位符替换为当前上下文中的值。
|
|
287
|
+
|
|
288
|
+
### 详细示例:三步请求编排
|
|
289
|
+
|
|
290
|
+
```ts
|
|
291
|
+
import { executeRequestChain } from "@i.un/api-client";
|
|
292
|
+
|
|
293
|
+
const rules = [
|
|
294
|
+
// 步骤 1: 获取登录会话
|
|
295
|
+
{
|
|
296
|
+
key: "auth",
|
|
297
|
+
request: { method: "POST", url: "/login", body: { user: "admin" } },
|
|
298
|
+
},
|
|
299
|
+
// 步骤 2: 在 URL 和 Header 中使用会话 Token
|
|
300
|
+
{
|
|
301
|
+
key: "profile",
|
|
302
|
+
request: {
|
|
303
|
+
method: "GET",
|
|
304
|
+
url: "/users/{{auth.userId}}",
|
|
305
|
+
headers: { "X-Session": "{{auth.token}}" },
|
|
306
|
+
},
|
|
307
|
+
selector: "data", // context.profile 将仅包含响应中的 'data' 字段
|
|
308
|
+
},
|
|
309
|
+
// 步骤 3: 结合之前的步骤数据发起新请求
|
|
310
|
+
{
|
|
311
|
+
key: "update",
|
|
312
|
+
request: { method: "PUT", url: "/sync" },
|
|
313
|
+
pickContext: ["profile"], // body 将会是 { profile: context.profile, ...payload }
|
|
314
|
+
payload: { source: "web-client" },
|
|
315
|
+
},
|
|
316
|
+
];
|
|
317
|
+
|
|
318
|
+
const result = await executeRequestChain(rules);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### 自定义路由 (策略模式)
|
|
322
|
+
|
|
323
|
+
你可以提供 `NetworkHandler` 列表,将请求路由到不同的环境(例如:将 `/ext/*` 重定向到浏览器扩展 API,而 `/api/*` 走标准 fetch)。
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
const handlers = [
|
|
327
|
+
{
|
|
328
|
+
name: "extension-router",
|
|
329
|
+
shouldHandle: (url) => url.startsWith("chrome-extension://"),
|
|
330
|
+
adapter: {
|
|
331
|
+
post: (url, body) => chrome.runtime.sendMessage({ url, body }),
|
|
332
|
+
get: (url) => ...
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
];
|
|
336
|
+
|
|
337
|
+
await executeRequestChain(rules, handlers);
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## Protobuf 与安全通信
|
|
343
|
+
|
|
344
|
+
Protobuf 模块为 `ofetch` 提供了一层安全保障。它支持二进制序列化、XOR 混淆以及通过 Hook 实现的自动集成。
|
|
345
|
+
|
|
346
|
+
### 处理流程
|
|
347
|
+
|
|
348
|
+
1. **对象** -> **转换 (Transform, 可选)** -> **Protobuf 编码** -> **XOR 混淆** -> **二进制负载 (Binary Payload)**
|
|
349
|
+
|
|
350
|
+
### 集成 Hook
|
|
351
|
+
|
|
352
|
+
由于使用了 `createProtobufHooks`,你可以轻松地为 `api-client` 实例添加 Protobuf 支持。
|
|
353
|
+
|
|
354
|
+
```ts
|
|
355
|
+
import { createApiClient, createProtobufHooks } from "@i.un/api-client";
|
|
356
|
+
|
|
357
|
+
const hooks = createProtobufHooks({
|
|
358
|
+
// 1. XOR 加密密钥 (可选,但推荐)
|
|
359
|
+
obfuscationKey: () => fetchSecretKeyFromServer(),
|
|
360
|
+
|
|
361
|
+
// 2. 自定义数据转换
|
|
362
|
+
transform: {
|
|
363
|
+
beforeEncode: (data) => ({ ...data, ts: Date.now() }),
|
|
364
|
+
afterDecode: (res) => res.data,
|
|
365
|
+
},
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
const client = createApiClient({
|
|
369
|
+
baseURL: "/api",
|
|
370
|
+
...hooks,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// 使用方法:只需将 Content-Type 或 Accept 设置为 'application/x-protobuf'
|
|
374
|
+
const data = await client.post(
|
|
375
|
+
"/secure-endpoint",
|
|
376
|
+
{ foo: "bar" },
|
|
377
|
+
{
|
|
378
|
+
headers: { "Content-Type": "application/x-protobuf" },
|
|
379
|
+
},
|
|
380
|
+
);
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### 手动配置请求头
|
|
384
|
+
|
|
385
|
+
如果你没有使用自动 Hook,或者需要为特定请求手动配置 Header,可以使用 `setProtobufRequestHeaders` 辅助函数:
|
|
386
|
+
|
|
387
|
+
```ts
|
|
388
|
+
import { setProtobufRequestHeaders } from "@i.un/api-client";
|
|
389
|
+
|
|
390
|
+
// 1. 同时发送和接收 Protobuf (默认)
|
|
391
|
+
const headers = setProtobufRequestHeaders({ "X-Custom": "val" });
|
|
392
|
+
// { "X-Custom": "val", "Content-Type": "application/x-protobuf", "Accept": "application/x-protobuf" }
|
|
393
|
+
|
|
394
|
+
// 2. 仅接收 Protobuf
|
|
395
|
+
const receiveOnly = setProtobufRequestHeaders({}, "receive");
|
|
396
|
+
// { "Accept": "application/x-protobuf" }
|
|
397
|
+
|
|
398
|
+
// 在 client 中使用
|
|
399
|
+
await client.get("/data", { headers: receiveOnly });
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### 信封模式 vs 自定义类型模式
|
|
403
|
+
|
|
404
|
+
- **信封模式 (默认)**:如果不提供 `protoType`,库将使用内置的 `SecurePayload`(包含时间戳和经过 JSON 序列化的数据)。这是在不为每个接口定义 Schema 的情况下,向开发者工具隐藏数据的最简单方法。
|
|
405
|
+
- **自定义类型模式**:提供一个 `protoType`(从 `.proto` 文件编译出的对象),以获得极致的二进制性能和类型安全。
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
const hooks = createProtobufHooks({
|
|
409
|
+
protoType: MyCompiledMessage, // 来自 protobufjs
|
|
410
|
+
});
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
### 服务端/边缘计算使用 (Node/Workers)
|
|
414
|
+
|
|
415
|
+
本库提供了服务端工具,用于处理这些安全请求。
|
|
416
|
+
|
|
417
|
+
```ts
|
|
418
|
+
import { parseSecureRequest, secureResponse } from "@i.un/api-client";
|
|
419
|
+
|
|
420
|
+
// 1. 解析进入的加密请求
|
|
421
|
+
const body = await parseSecureRequest(request, { obfuscationKey: "key" });
|
|
422
|
+
|
|
423
|
+
// 2. 发送加密响应
|
|
424
|
+
return await secureResponse({ success: true }, { obfuscationKey: "key" });
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
262
429
|
## 环境支持与注意事项
|
|
263
430
|
|
|
431
|
+
---
|
|
432
|
+
|
|
264
433
|
- 依赖 `ofetch`,可在浏览器、Node 18+、Nuxt 等环境使用。
|
|
265
434
|
- 需要环境有 `fetch` / `Headers`:
|
|
266
435
|
- 浏览器:原生支持。
|
package/dist/chain.d.mts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request Chain Runner
|
|
3
|
+
* 负责解析和执行通用的 HTTP 请求链 (Chain Execution)
|
|
4
|
+
* 适用于任何需要链式 HTTP 请求编排的场景
|
|
5
|
+
*/
|
|
6
|
+
/** Supported HTTP Methods */
|
|
7
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
8
|
+
/** HTTP 请求参数 */
|
|
9
|
+
interface HttpRequestSpec {
|
|
10
|
+
method: HttpMethod;
|
|
11
|
+
url: string;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
body?: any;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 网络适配器接口
|
|
17
|
+
* 定义实际发送请求的能力
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* 网络适配器接口
|
|
21
|
+
* 定义实际发送请求的能力
|
|
22
|
+
*/
|
|
23
|
+
interface NetworkAdapter {
|
|
24
|
+
get<T>(url: string, params?: any, headers?: Record<string, string>): Promise<T>;
|
|
25
|
+
post<T>(url: string, body?: any, headers?: Record<string, string>): Promise<T>;
|
|
26
|
+
put?<T>(url: string, body?: any, headers?: Record<string, string>): Promise<T>;
|
|
27
|
+
delete?<T>(url: string, params?: any, headers?: Record<string, string>): Promise<T>;
|
|
28
|
+
patch?<T>(url: string, body?: any, headers?: Record<string, string>): Promise<T>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 网络处理器接口 (Strategy Pattern)
|
|
32
|
+
* 组合了"匹配规则"和"执行能力"
|
|
33
|
+
*/
|
|
34
|
+
interface NetworkHandler {
|
|
35
|
+
/** 处理器名称 (用于调试) */
|
|
36
|
+
name?: string;
|
|
37
|
+
/** 判断该 URL 是否由此适配器处理 */
|
|
38
|
+
shouldHandle(url: string, method: HttpMethod): boolean;
|
|
39
|
+
/** 具体的网络适配器 */
|
|
40
|
+
adapter: NetworkAdapter;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 请求链规则 (Chain Step)
|
|
44
|
+
*/
|
|
45
|
+
interface ChainRequestRule {
|
|
46
|
+
/**
|
|
47
|
+
* 结果存储的键名 (Context Key)
|
|
48
|
+
* Fetch 结果存储: context[key] = response
|
|
49
|
+
*/
|
|
50
|
+
key?: string;
|
|
51
|
+
/**
|
|
52
|
+
* HTTP 请求详情
|
|
53
|
+
*/
|
|
54
|
+
request: HttpRequestSpec;
|
|
55
|
+
/**
|
|
56
|
+
* 数据提取选择器
|
|
57
|
+
* 用于从响应中提取特定数据, e.g., "elements.0"
|
|
58
|
+
*/
|
|
59
|
+
selector?: string;
|
|
60
|
+
/** 是否允许请求失败 (默认 false) */
|
|
61
|
+
optional?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* 是否包含上下文
|
|
64
|
+
* 如果为 true,请求 Body 将自动合并当前 Context 和 Payload
|
|
65
|
+
*/
|
|
66
|
+
includeContext?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* 上下文筛选列表 (优先级高于 includeContext)
|
|
69
|
+
* 指定需要合并到 Body 中的 Context Key 列表
|
|
70
|
+
* e.g., ["rawProfile", "rawCompany"]
|
|
71
|
+
*/
|
|
72
|
+
pickContext?: string[];
|
|
73
|
+
/** 额外 Payload (仅当 includeContext 为 true 或 pickContext 存在时合并) */
|
|
74
|
+
payload?: Record<string, any>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 请求链执行器 (Request Chain Engine)
|
|
78
|
+
* 支持链式请求、上下文累积、智能路由、变量替换
|
|
79
|
+
*
|
|
80
|
+
* @param requests 链式执行规则列表
|
|
81
|
+
* @param handlers 网络适配器处理器列表 (按顺序匹配)
|
|
82
|
+
*/
|
|
83
|
+
declare function executeRequestChain<T>(requests: ChainRequestRule[], handlers?: NetworkHandler[], getChainRequests?: (context: Record<string, any>) => ChainRequestRule[] | null | undefined, initContext?: Record<string, any>): Promise<T>;
|
|
84
|
+
|
|
85
|
+
export { type ChainRequestRule, type HttpRequestSpec, type NetworkAdapter, type NetworkHandler, executeRequestChain };
|
package/dist/chain.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request Chain Runner
|
|
3
|
+
* 负责解析和执行通用的 HTTP 请求链 (Chain Execution)
|
|
4
|
+
* 适用于任何需要链式 HTTP 请求编排的场景
|
|
5
|
+
*/
|
|
6
|
+
/** Supported HTTP Methods */
|
|
7
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
|
8
|
+
/** HTTP 请求参数 */
|
|
9
|
+
interface HttpRequestSpec {
|
|
10
|
+
method: HttpMethod;
|
|
11
|
+
url: string;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
body?: any;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 网络适配器接口
|
|
17
|
+
* 定义实际发送请求的能力
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* 网络适配器接口
|
|
21
|
+
* 定义实际发送请求的能力
|
|
22
|
+
*/
|
|
23
|
+
interface NetworkAdapter {
|
|
24
|
+
get<T>(url: string, params?: any, headers?: Record<string, string>): Promise<T>;
|
|
25
|
+
post<T>(url: string, body?: any, headers?: Record<string, string>): Promise<T>;
|
|
26
|
+
put?<T>(url: string, body?: any, headers?: Record<string, string>): Promise<T>;
|
|
27
|
+
delete?<T>(url: string, params?: any, headers?: Record<string, string>): Promise<T>;
|
|
28
|
+
patch?<T>(url: string, body?: any, headers?: Record<string, string>): Promise<T>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 网络处理器接口 (Strategy Pattern)
|
|
32
|
+
* 组合了"匹配规则"和"执行能力"
|
|
33
|
+
*/
|
|
34
|
+
interface NetworkHandler {
|
|
35
|
+
/** 处理器名称 (用于调试) */
|
|
36
|
+
name?: string;
|
|
37
|
+
/** 判断该 URL 是否由此适配器处理 */
|
|
38
|
+
shouldHandle(url: string, method: HttpMethod): boolean;
|
|
39
|
+
/** 具体的网络适配器 */
|
|
40
|
+
adapter: NetworkAdapter;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 请求链规则 (Chain Step)
|
|
44
|
+
*/
|
|
45
|
+
interface ChainRequestRule {
|
|
46
|
+
/**
|
|
47
|
+
* 结果存储的键名 (Context Key)
|
|
48
|
+
* Fetch 结果存储: context[key] = response
|
|
49
|
+
*/
|
|
50
|
+
key?: string;
|
|
51
|
+
/**
|
|
52
|
+
* HTTP 请求详情
|
|
53
|
+
*/
|
|
54
|
+
request: HttpRequestSpec;
|
|
55
|
+
/**
|
|
56
|
+
* 数据提取选择器
|
|
57
|
+
* 用于从响应中提取特定数据, e.g., "elements.0"
|
|
58
|
+
*/
|
|
59
|
+
selector?: string;
|
|
60
|
+
/** 是否允许请求失败 (默认 false) */
|
|
61
|
+
optional?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* 是否包含上下文
|
|
64
|
+
* 如果为 true,请求 Body 将自动合并当前 Context 和 Payload
|
|
65
|
+
*/
|
|
66
|
+
includeContext?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* 上下文筛选列表 (优先级高于 includeContext)
|
|
69
|
+
* 指定需要合并到 Body 中的 Context Key 列表
|
|
70
|
+
* e.g., ["rawProfile", "rawCompany"]
|
|
71
|
+
*/
|
|
72
|
+
pickContext?: string[];
|
|
73
|
+
/** 额外 Payload (仅当 includeContext 为 true 或 pickContext 存在时合并) */
|
|
74
|
+
payload?: Record<string, any>;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 请求链执行器 (Request Chain Engine)
|
|
78
|
+
* 支持链式请求、上下文累积、智能路由、变量替换
|
|
79
|
+
*
|
|
80
|
+
* @param requests 链式执行规则列表
|
|
81
|
+
* @param handlers 网络适配器处理器列表 (按顺序匹配)
|
|
82
|
+
*/
|
|
83
|
+
declare function executeRequestChain<T>(requests: ChainRequestRule[], handlers?: NetworkHandler[], getChainRequests?: (context: Record<string, any>) => ChainRequestRule[] | null | undefined, initContext?: Record<string, any>): Promise<T>;
|
|
84
|
+
|
|
85
|
+
export { type ChainRequestRule, type HttpRequestSpec, type NetworkAdapter, type NetworkHandler, executeRequestChain };
|