@aiao/rxdb-adapter-http 0.0.26
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/LICENSE +21 -0
- package/README.md +269 -0
- package/dist/RxDBAdapterHttp.d.ts +251 -0
- package/dist/RxDBAdapterHttp.d.ts.map +1 -0
- package/dist/change-feed.d.ts +66 -0
- package/dist/change-feed.d.ts.map +1 -0
- package/dist/chunking.d.ts +29 -0
- package/dist/chunking.d.ts.map +1 -0
- package/dist/conditional-cache.d.ts +175 -0
- package/dist/conditional-cache.d.ts.map +1 -0
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/errors.d.ts +215 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/handler-contract.d.ts +41 -0
- package/dist/handler-contract.d.ts.map +1 -0
- package/dist/http.interface.d.ts +519 -0
- package/dist/http.interface.d.ts.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +864 -0
- package/dist/metadata.d.ts +15 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/pagination.d.ts +30 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/rest.d.ts +94 -0
- package/dist/rest.d.ts.map +1 -0
- package/dist/transport.d.ts +174 -0
- package/dist/transport.d.ts.map +1 -0
- package/package.json +64 -0
- package/src/RxDBAdapterHttp.ts +786 -0
- package/src/change-feed.ts +470 -0
- package/src/chunking.ts +68 -0
- package/src/conditional-cache.ts +271 -0
- package/src/config.ts +83 -0
- package/src/errors.ts +295 -0
- package/src/handler-contract.ts +77 -0
- package/src/http.interface.ts +554 -0
- package/src/index.ts +25 -0
- package/src/metadata.ts +94 -0
- package/src/pagination.ts +184 -0
- package/src/rest.ts +476 -0
- package/src/transport.ts +699 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { QueryCacheEntityMetadata } from '@aiao/rxdb';
|
|
2
|
+
/**
|
|
3
|
+
* 校验并规范化 handler 解析出的 metadata 行。
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* **不得直接透传远端的串**,哪怕它合法:合法与规范是两件事,而破坏字典序的四种形态
|
|
7
|
+
* (时区偏移、缺毫秒、`+00:00` 代替 `Z`、多于 3 位小数秒)全都合法。
|
|
8
|
+
*
|
|
9
|
+
* @param entityName - 实体名,出错时写进错误便于定位
|
|
10
|
+
* @param rows - handler `parse` 出来的行,尚未校验
|
|
11
|
+
* @returns 只含 `id` 与 `updatedAt` 的规范化 metadata
|
|
12
|
+
* @throws HttpInvalidMetadataError 不是数组、行不是对象、缺字段或 `updatedAt` 不合契约
|
|
13
|
+
*/
|
|
14
|
+
export declare const canonicalizeMetadata: (entityName: string, rows: unknown[]) => QueryCacheEntityMetadata[];
|
|
15
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAwD3D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,EAAE,MAAM,OAAO,EAAE,KAAG,wBAAwB,EAWlG,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { QueryCacheEntityMetadata, RuleGroup } from '@aiao/rxdb';
|
|
2
|
+
import { FetchMetadataHandler, HttpNumericConfig } from './http.interface.js';
|
|
3
|
+
import { HttpTransport } from './transport.js';
|
|
4
|
+
/** 翻页所需的协作方 */
|
|
5
|
+
export interface PaginationDeps {
|
|
6
|
+
transport: HttpTransport;
|
|
7
|
+
handler: FetchMetadataHandler;
|
|
8
|
+
config: Pick<HttpNumericConfig, 'pageSize' | 'maxEmptyPages' | 'maxPages'>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 翻完一次 `fetchMetadata` 的所有页并合并。
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* 返回 `Promise` 而不是 `Observable` 是刻意的:调用方用 `from(promise)` 包一层就天然
|
|
15
|
+
* 满足「恰好发射一次再 complete」(AC#23)。把 Observable 的构造留在循环里,等于给
|
|
16
|
+
* 「每页发一次」留了门——而 `forkJoin` 只留最后一次发射,前面各页当场丢失。
|
|
17
|
+
*
|
|
18
|
+
* 翻页模式按**首页的返回形状**锁定,中途换形态即抛错:两种形态各有各的终止判据,
|
|
19
|
+
* 混用会让它们互相盖掉,正是本包要防的静默截断。
|
|
20
|
+
*
|
|
21
|
+
* @param deps - transport、handler 与三个翻页相关配置
|
|
22
|
+
* @param ctx - 实体名与查询条件,逐页原样透传给 handler
|
|
23
|
+
* @returns 所有页合并、且逐页 canonicalize 过的 metadata
|
|
24
|
+
* @throws HttpPaginationError 换形态 / token 不推进 / 连续空页触顶 / 总页数触顶
|
|
25
|
+
*/
|
|
26
|
+
export declare const fetchAllMetadataPages: (deps: PaginationDeps, ctx: {
|
|
27
|
+
entityName: string;
|
|
28
|
+
where: RuleGroup<unknown>;
|
|
29
|
+
}) => Promise<QueryCacheEntityMetadata[]>;
|
|
30
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,KAAK,EAAwB,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEzG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,eAAe;AACf,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,GAAG,eAAe,GAAG,UAAU,CAAC,CAAC;CAC5E;AAgED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,GAChC,MAAM,cAAc,EACpB,KAAK;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;CAAE,KACrD,OAAO,CAAC,wBAAwB,EAAE,CAgDpC,CAAC"}
|
package/dist/rest.d.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { HttpHandlers, HttpMethod } from './http.interface.js';
|
|
2
|
+
/** 模板支持的占位符,**只有这两个**。 */
|
|
3
|
+
export type RestPlaceholder = 'entity' | 'id';
|
|
4
|
+
/** 可用模板表达的操作,与 {@link HttpHandlers} 的七个字段一一对应。 */
|
|
5
|
+
export type RestOperation = 'fetchMetadata' | 'findByIds' | 'create' | 'update' | 'delete' | 'version' | 'isTableExisted';
|
|
6
|
+
/** 单个操作的路径模板与方法覆盖。 */
|
|
7
|
+
export interface RestOperationTemplate {
|
|
8
|
+
/** 相对 `baseUrl` 的路径模板(也可给绝对 URL),占位符写作 `:entity` / `:id` */
|
|
9
|
+
path: string;
|
|
10
|
+
/** 缺省取该操作的默认方法,见 {@link createRestHandlers} */
|
|
11
|
+
method?: HttpMethod;
|
|
12
|
+
}
|
|
13
|
+
/** {@link createRestHandlers} 的配置。 */
|
|
14
|
+
export interface RestHandlersOptions {
|
|
15
|
+
/**
|
|
16
|
+
* 实体名 → 资源路径片段,例如 `{ Recipe: 'recipes' }`。
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* 值**可以含 `/`**(`v1/recipes` 合法):它来自配置,是开发者写下的常量,不是数据。
|
|
20
|
+
* 与之相对,`:id` 的取值来自远端行,必须 `encodeURIComponent` —— 一个含 `/` 的 id
|
|
21
|
+
* 不做转义就会拼出另一个资源的地址。两者的来源不同,处理方式因此不同。
|
|
22
|
+
*
|
|
23
|
+
* 未列出的实体直接用实体名本身作路径片段。
|
|
24
|
+
*/
|
|
25
|
+
resources?: Record<string, string>;
|
|
26
|
+
/**
|
|
27
|
+
* 逐操作覆盖路径与方法。
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* 三种取值语义不同:**缺省** = 用默认模板(`version` / `isTableExisted` 的默认是「不产出」);
|
|
31
|
+
* **给对象** = 用它;**给 `null`** = 不产出该 handler。
|
|
32
|
+
*
|
|
33
|
+
* `null` 是有意义的一档而不是冗余写法:写 duck 的「不支持」在 core 侧表现为**属性缺席**
|
|
34
|
+
* (`QueryCacheEngine` 用 `if (!this.remoteAdapter.create)` 特性探测),
|
|
35
|
+
* 只读后端必须能把 `create` 关掉,否则 `repo.create()` 会发出一个注定 405 的请求,
|
|
36
|
+
* 而不是 AC#4 那句清晰的「Remote adapter does not support create」。
|
|
37
|
+
*
|
|
38
|
+
* `fetchMetadata` / `findByIds` 不可关:它们是 `RxDBAdapterRemoteBase` 两个 abstract
|
|
39
|
+
* 成员的落地点,关掉整条 QueryCache 读路径都不成立。
|
|
40
|
+
*/
|
|
41
|
+
templates?: {
|
|
42
|
+
[K in RestOperation]?: RestOperationTemplate | null;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* 用 REST 资源 URL 模板产出一整套 {@link HttpHandlers}(US-212 AC#27)。
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* 产出的 handler 与手写的**完全等价**:同样只做协议 mapping,不碰网络——发请求、注入
|
|
50
|
+
* auth、提取 `status`、翻页、分块、单次发射仍全在适配器一侧。因此本模块拿不到、也不需要
|
|
51
|
+
* 改动阶段 A 的任何契约。
|
|
52
|
+
*
|
|
53
|
+
* 默认模板(方法 / 路径):
|
|
54
|
+
*
|
|
55
|
+
* | 操作 | 方法 | 路径 | 默认产出 |
|
|
56
|
+
* | ---------------- | ------- | ------------------- | -------- |
|
|
57
|
+
* | `fetchMetadata` | `POST` | `:entity/metadata` | 是(不可关) |
|
|
58
|
+
* | `findByIds` | `POST` | `:entity/by-ids` | 是(不可关) |
|
|
59
|
+
* | `create` | `POST` | `:entity` | 是 |
|
|
60
|
+
* | `update` | `PATCH` | `:entity/:id` | 是 |
|
|
61
|
+
* | `delete` | `POST` | `:entity/delete` | 是 |
|
|
62
|
+
* | `version` | `GET` | — | 否 |
|
|
63
|
+
* | `isTableExisted` | `HEAD` | — | 否 |
|
|
64
|
+
*
|
|
65
|
+
* 最后两行的路径栏是 `—` 而**不是**留空:这两个操作没有默认路径,不配
|
|
66
|
+
* `templates.version.path` / `templates.isTableExisted.path` 就整个不产出 handler。
|
|
67
|
+
* `isTableExisted` 的方法栏仍写 `HEAD`,那是给了路径之后才生效的默认方法
|
|
68
|
+
* (不给默认路径的理由见 `REST_OPERATIONS` 里那一条的注释)。
|
|
69
|
+
*
|
|
70
|
+
* 请求体形状:`fetchMetadata` 发 `{ where, offset, limit, pageToken }`(`where` 是 JSON
|
|
71
|
+
* `RuleGroup`,**不是 SQL**),`findByIds` 与 `delete` 发 `{ ids }`,
|
|
72
|
+
* `create` / `update` 直接发调用方给的数据。
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* rxdb.adapter('http', db => new RxDBAdapterHttp(db, {
|
|
77
|
+
* baseUrl: 'https://api.example.com/v1',
|
|
78
|
+
* handlers: createRestHandlers({
|
|
79
|
+
* resources: { Recipe: 'recipes' },
|
|
80
|
+
* templates: { version: { path: 'meta/version' }, delete: null }
|
|
81
|
+
* })
|
|
82
|
+
* }));
|
|
83
|
+
* // fetchMetadata → POST https://api.example.com/v1/recipes/metadata
|
|
84
|
+
* // update → PATCH https://api.example.com/v1/recipes/{id}
|
|
85
|
+
* // delete → 不产出,repo.delete() 走 AC#4 的 fail-fast
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @param options - 资源映射与逐操作的模板覆盖
|
|
89
|
+
* @returns 可直接交给 `RxDBAdapterHttp` 的 handler 集合
|
|
90
|
+
* @throws HttpConfigError 模板路径为空 / 含 `?`、`#`、空白 / 方法非法 / 占位符集合不匹配 /
|
|
91
|
+
* 关闭了必选 handler / `resources` 的值不是合法路径片段
|
|
92
|
+
*/
|
|
93
|
+
export declare const createRestHandlers: (options?: RestHandlersOptions) => HttpHandlers;
|
|
94
|
+
//# sourceMappingURL=rest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../src/rest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAGV,YAAY,EACZ,UAAU,EAGX,MAAM,qBAAqB,CAAC;AAE7B,0BAA0B;AAC1B,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,IAAI,CAAC;AAE9C,kDAAkD;AAClD,MAAM,MAAM,aAAa,GACvB,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,gBAAgB,CAAC;AAEhG,sBAAsB;AACtB,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,sCAAsC;AACtC,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,EAAE;SAAG,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,qBAAqB,GAAG,IAAI;KAAE,CAAC;CACrE;AAmRD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAS,mBAAwB,KAAG,YAiFtE,CAAC"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { HttpAuthHook, HttpEtagUnreadableHook, HttpRequestSpec } from './http.interface.js';
|
|
2
|
+
/** {@link HttpTransport} 的构造参数。 */
|
|
3
|
+
export interface HttpTransportOptions {
|
|
4
|
+
/** 相对 URL 的基地址 */
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
/** 单个请求的超时上限(毫秒),已由 `resolveHttpConfig` 校验为 finite 正整数 */
|
|
7
|
+
requestTimeoutMs: number;
|
|
8
|
+
/** 适配器持有的断开信号,`disconnect()` 时 abort */
|
|
9
|
+
disconnectSignal: AbortSignal;
|
|
10
|
+
auth?: HttpAuthHook;
|
|
11
|
+
/** 附加到所有请求的 header */
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
/**
|
|
14
|
+
* 条件请求配置;**缺席即禁用**,此时行为与阶段 A 逐字相同(US-212 AC#28)。
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* 诊断回调挂在**这个对象里**而不是与它并列,US-215 AC#4「开关关着时回调不触发」
|
|
18
|
+
* 因此由结构本身担保:开关关着时整个 `conditional` 不存在,回调无处可取,
|
|
19
|
+
* 不需要在触发点上再判一次开关状态。
|
|
20
|
+
*/
|
|
21
|
+
conditional?: {
|
|
22
|
+
maxEntries: number;
|
|
23
|
+
onEtagUnreadable?: HttpEtagUnreadableHook;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* 每次**实际发出**的请求的结局:成功传 `null`,失败传已 `classify` 过的错误。
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* 供 local-first 的可达性判定使用,接到 `ReachabilityMonitor.report` 上。
|
|
30
|
+
* 缺席即不上报(非浏览器宿主、独立使用 transport 的场景)。
|
|
31
|
+
*
|
|
32
|
+
* **传的是分类后的错误**:`fetch` 在 node/undici 下抛的裸 `TypeError('fetch failed')`
|
|
33
|
+
* 一条 `isNetworkError` 判据都不命中,原样上报等于永远判不出离线。
|
|
34
|
+
*
|
|
35
|
+
* 请求没发出去的失败(auth hook 抛错、header 非法、body 不可序列化)**不上报**——
|
|
36
|
+
* 那些是本地问题,与远端够不够得着无关,见 {@link HttpTransport.#prepare}。
|
|
37
|
+
*/
|
|
38
|
+
reportResult?: (error: unknown | null) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 读非 2xx 的响应体当错误详情,读不出来就算了——**除非是 `disconnect()` 打断的**。
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* 两种读失败必须分开,因为「状态码是不是仍算数」的答案相反:
|
|
45
|
+
*
|
|
46
|
+
* - **连接中途断 / 超时**:`409` 是远端给出的真实回答,连接当时是通的。丢掉详情、
|
|
47
|
+
* 保留 `HttpResponseError(409)` 才对——判成离线会让 `offlineFallback` 把一次业务
|
|
48
|
+
* 冲突静默换成陈旧缓存。这条由「拿到状态码的响应即使 body 读不完」一例冻结。
|
|
49
|
+
* - **`disconnect()`**:调用方自己叫停,`HttpResponseError` 就是把「我取消了」报成
|
|
50
|
+
* 「服务端出错了」,两者的处置完全相反。`.catch(() => undefined)` 一把吞掉时,
|
|
51
|
+
* {@link HttpTransport.classify} 本来分得清,只是永远收不到那个错误。
|
|
52
|
+
*
|
|
53
|
+
* 所以判据是**断开信号**而不是错误的形状:超时与断开的 `AbortError` 长得一模一样。
|
|
54
|
+
*
|
|
55
|
+
* @param response - 已拿到状态码的非 2xx 响应
|
|
56
|
+
* @param disconnectSignal - 适配器的断开信号
|
|
57
|
+
* @returns 响应体文本;读失败且非主动断开时为 `undefined`
|
|
58
|
+
*/
|
|
59
|
+
export declare const readErrorBody: (response: Response, disconnectSignal: AbortSignal) => Promise<string | undefined>;
|
|
60
|
+
/**
|
|
61
|
+
* 执行 handler 产出的请求描述。
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* 一次请求一个 `AbortController`:它同时接超时定时器与适配器的断开信号,
|
|
65
|
+
* 但**记录是谁先触发的**——两者都表现为 `AbortError`,而语义相反。
|
|
66
|
+
* 超时可降级(远端暂时够不着),断开不可降级(是调用方自己叫停的)。
|
|
67
|
+
*/
|
|
68
|
+
export declare class HttpTransport {
|
|
69
|
+
#private;
|
|
70
|
+
private readonly options;
|
|
71
|
+
constructor(options: HttpTransportOptions);
|
|
72
|
+
/**
|
|
73
|
+
* 发请求并解码 JSON 响应体,非 2xx 抛错。
|
|
74
|
+
*
|
|
75
|
+
* @remarks
|
|
76
|
+
* 启用条件请求且 `operation` 属于 {@link CONDITIONAL_OPERATIONS} 时,本方法额外做两件事
|
|
77
|
+
* (US-212 AC#28):带上 `if-none-match`、把 304 还原成上次 200 的解析结果。
|
|
78
|
+
* 未启用时这两条都不发生,行为与阶段 A 逐字相同。
|
|
79
|
+
*
|
|
80
|
+
* @param spec - handler 产出的请求描述
|
|
81
|
+
* @param operation - 出错时写进错误的操作名,如 `fetchMetadata`
|
|
82
|
+
* @param entityName - 仅用于诊断载荷(US-215)。**不影响任何判定**:传不传都不改变
|
|
83
|
+
* 是否走条件缓存,免得漏传一个诊断参数变成静默丢缓存——那正是本参数要治的病
|
|
84
|
+
* @returns 已 JSON 解码的响应体
|
|
85
|
+
* @throws HttpResponseError 响应状态非 2xx(带数字 `status`)。**未请求校验却收到 304
|
|
86
|
+
* 也走这里**——静默当成空集会让整表判成孤儿
|
|
87
|
+
* @throws HttpInvalidResponseError 状态 2xx 但响应体不是合法 JSON
|
|
88
|
+
* @throws HttpRequestBuildError 请求体不可序列化,或 header 非法(请求不发出)
|
|
89
|
+
* @throws NetworkOfflineError 传输失败或单请求超时
|
|
90
|
+
* @throws HttpDisconnectedError 请求被 `disconnect()` 取消
|
|
91
|
+
*/
|
|
92
|
+
sendJson(spec: HttpRequestSpec, operation: string, entityName?: string): Promise<unknown>;
|
|
93
|
+
/**
|
|
94
|
+
* 清空条件请求缓存。
|
|
95
|
+
*
|
|
96
|
+
* @remarks
|
|
97
|
+
* 由适配器的 `disconnect()` 调用(AC#28 的「`disconnect()` 清空」)。未启用条件请求时
|
|
98
|
+
* 是 no-op——没有缓存可清,不是错误。
|
|
99
|
+
*/
|
|
100
|
+
clearConditionalCache(): void;
|
|
101
|
+
/**
|
|
102
|
+
* 发请求、只判状态码,**不碰响应体**。
|
|
103
|
+
*
|
|
104
|
+
* @remarks
|
|
105
|
+
* 给 `delete` duck 用:core 的 duck 签名返回 `Observable<void>`,没有可解析的东西,
|
|
106
|
+
* 而 `204 No Content` 的空体喂给 {@link sendJson} 会当场变成「响应体不是合法 JSON」——
|
|
107
|
+
* 一次成功的删除被报成协议错误。
|
|
108
|
+
*
|
|
109
|
+
* 不解析但要**读完**:理由见 {@link discardBody}。非 2xx 那一支由 `assertOk` 的
|
|
110
|
+
* `response.text()` 顺带消费掉,只有成功路径需要显式收口。
|
|
111
|
+
*
|
|
112
|
+
* @param spec - handler 产出的请求描述
|
|
113
|
+
* @param operation - 出错时写进错误的操作名
|
|
114
|
+
* @throws HttpResponseError 响应状态非 2xx(带数字 `status`)
|
|
115
|
+
* @throws HttpRequestBuildError 请求体不可序列化,或 header 非法(请求不发出)
|
|
116
|
+
* @throws NetworkOfflineError 传输失败或单请求超时
|
|
117
|
+
* @throws HttpDisconnectedError 请求被 `disconnect()` 取消
|
|
118
|
+
*/
|
|
119
|
+
sendVoid(spec: HttpRequestSpec, operation: string): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* 把请求描述里的相对 URL 拼成最终地址。
|
|
122
|
+
*
|
|
123
|
+
* @remarks
|
|
124
|
+
* 给 `isTableExisted` 用:它按状态码自己分流,抛错时要能报出和其他路径**一致**的 URL。
|
|
125
|
+
* 让调用方自己拼一遍,两处规则迟早分叉。
|
|
126
|
+
*/
|
|
127
|
+
resolveUrl(spec: HttpRequestSpec): string;
|
|
128
|
+
/**
|
|
129
|
+
* 发请求,并在**超时窗口内**消费响应。
|
|
130
|
+
*
|
|
131
|
+
* @remarks
|
|
132
|
+
* 给 `isTableExisted` 用:它要把 404 读成「表不存在」而不是失败,
|
|
133
|
+
* 所以判定必须在拿得到 `status` 的这一层做,不能交给会抛错的 {@link sendJson}。
|
|
134
|
+
*
|
|
135
|
+
* 交出的是 `consume` 回调而不是 `Response`:**响应体也必须罩在同一个 deadline 下**。
|
|
136
|
+
* 详见 {@link HttpTransport.#send}。
|
|
137
|
+
*
|
|
138
|
+
* @param spec - handler 产出的请求描述
|
|
139
|
+
* @param operation - 出错时写进错误的操作名
|
|
140
|
+
* @param consume - 在超时窗口内消费 `Response`;抛出的 {@link HttpAdapterError} 原样透出
|
|
141
|
+
* @returns `consume` 的返回值
|
|
142
|
+
* @throws HttpRequestBuildError 请求体不可序列化,或 header 非法(请求不发出)
|
|
143
|
+
* @throws NetworkOfflineError 传输失败或单请求超时
|
|
144
|
+
* @throws HttpDisconnectedError 请求被 `disconnect()` 取消
|
|
145
|
+
*/
|
|
146
|
+
execute<T>(spec: HttpRequestSpec, operation: string, consume: (response: Response) => Promise<T>): Promise<T>;
|
|
147
|
+
/**
|
|
148
|
+
* 合并 header,**auth hook 优先级最高**。
|
|
149
|
+
*
|
|
150
|
+
* @remarks
|
|
151
|
+
* 顺序:适配器默认 → `spec.headers` → auth hook。auth 排最后是因为它是唯一
|
|
152
|
+
* 有正确性含义的一组——被 handler 的静态 header 覆盖掉就是发出一个未认证的请求。
|
|
153
|
+
*
|
|
154
|
+
* 合并必须**大小写不敏感**(见 {@link mergeHeaders}),否则「排最后」根本不等于「覆盖」:
|
|
155
|
+
* 静态配置写 `Authorization`、auth hook 返回 `authorization`,`Object.assign` 按字面键
|
|
156
|
+
* 当成两个 header 全留下,`Headers` 再按 RFC 把同名字段合并成 `旧, 新`——
|
|
157
|
+
* 请求带着一个过期凭据和一个新凭据一起上线,且没有任何一步报错。
|
|
158
|
+
*/
|
|
159
|
+
private buildHeaders;
|
|
160
|
+
/**
|
|
161
|
+
* 把 fetch 的失败归类成三种可判别的错误。
|
|
162
|
+
*
|
|
163
|
+
* @remarks
|
|
164
|
+
* 主动断开与超时都表现为 `AbortError`,靠 `timedOut` 标志分流,而不是靠错误对象——
|
|
165
|
+
* 二者的 `AbortError` 长得一模一样。分错的代价不对称:断开被当成超时会让「用户
|
|
166
|
+
* 叫停」静默变成「读缓存返回」。
|
|
167
|
+
*
|
|
168
|
+
* 传输失败一律包成 core 的 `NetworkOfflineError`,不是自定义类:`isNetworkError`
|
|
169
|
+
* 的第 1 条判据是 `instanceof NetworkOfflineError`,包成别的它认不出,
|
|
170
|
+
* 而 node/undici 的失败消息 `fetch failed` 又不命中第 5 条的正则——两头落空。
|
|
171
|
+
*/
|
|
172
|
+
private classify;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EAEtB,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAE7B,mCAAmC;AACnC,MAAM,WAAW,oBAAoB;IACnC,kBAAkB;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,gBAAgB,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,gBAAgB,EAAE,WAAW,CAAC;IAC9B,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,sBAAsB,CAAA;KAAE,CAAC;IAChF;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;CAChD;AAyFD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,aAAa,GAAU,UAAU,QAAQ,EAAE,kBAAkB,WAAW,KAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CASjH,CAAC;AAwKF;;;;;;;GAOG;AACH,qBAAa,aAAa;;IAIZ,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,oBAAoB;IAI1D;;;;;;;;;;;;;;;;;;;OAmBG;IACG,QAAQ,CAAC,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW/F;;;;;;OAMG;IACH,qBAAqB,IAAI,IAAI;IAI7B;;;;;;;;;;;;;;;;;OAiBG;IACG,QAAQ,CAAC,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM;IAIzC;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAInH;;;;;;;;;;;OAWG;YACW,YAAY;IAY1B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,QAAQ;CAsMjB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aiao/rxdb-adapter-http",
|
|
3
|
+
"version": "0.0.26",
|
|
4
|
+
"description": "HTTP remote adapter for RxDB QueryCache: JSON RuleGroup over your own REST API.",
|
|
5
|
+
"homepage": "https://rxdb.netlify.app/docs/adapters/http",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/aiao-io/rxdb/issues"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"aiao",
|
|
11
|
+
"rxdb",
|
|
12
|
+
"http",
|
|
13
|
+
"rest",
|
|
14
|
+
"querycache",
|
|
15
|
+
"sync",
|
|
16
|
+
"local-first"
|
|
17
|
+
],
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/aiao-io/rxdb.git",
|
|
22
|
+
"directory": "packages/rxdb-adapter-http"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"module": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
"./package.json": "./package.json",
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js",
|
|
34
|
+
"default": "./dist/index.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"src",
|
|
40
|
+
"!src/**/*.spec.*",
|
|
41
|
+
"!src/**/*.test.*",
|
|
42
|
+
"!src/**/__tests__/**",
|
|
43
|
+
"!**/*.tsbuildinfo"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"nx": {
|
|
49
|
+
"name": "rxdb-adapter-http",
|
|
50
|
+
"tags": [
|
|
51
|
+
"js-lib"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"rxjs": "^7.8.2",
|
|
56
|
+
"@aiao/rxdb": "0.0.26"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@aiao/rxdb-plugin-history": "0.0.26",
|
|
60
|
+
"@aiao/rxdb-plugin-querycache": "0.0.26",
|
|
61
|
+
"@aiao/rxdb-plugin-sync": "0.0.26",
|
|
62
|
+
"@aiao/rxdb-test": "0.0.26"
|
|
63
|
+
}
|
|
64
|
+
}
|