iota-fetch 0.0.4 → 0.1.1
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 +206 -92
- package/lib/axios/fetch.d.ts +6 -0
- package/lib/axios/fetch.d.ts.map +1 -0
- package/lib/axios/fetchFun.d.ts +5 -0
- package/lib/axios/fetchFun.d.ts.map +1 -0
- package/lib/axios/instance.d.ts +5 -0
- package/lib/axios/instance.d.ts.map +1 -0
- package/lib/axios/models.d.ts +32 -0
- package/lib/axios/models.d.ts.map +1 -0
- package/lib/axios/requestQueue.d.ts +16 -0
- package/lib/axios/requestQueue.d.ts.map +1 -0
- package/lib/bundle.cjs.js +2887 -1086
- package/lib/bundle.cjs.js.map +1 -1
- package/lib/bundle.esm.js +2888 -1085
- package/lib/bundle.esm.js.map +1 -1
- package/lib/example/index.d.ts +3 -0
- package/lib/example/index.d.ts.map +1 -0
- package/lib/main.d.ts +4 -0
- package/lib/main.d.ts.map +1 -0
- package/package.json +27 -8
- package/babel.config.cjs +0 -11
- package/public/index.html +0 -67
- package/rollup.config.js +0 -56
- package/src/axios/fetch.js +0 -32
- package/src/axios/fetchFun.js +0 -40
- package/src/axios/instance.js +0 -8
- package/src/axios/resQueue.js +0 -39
- package/src/main.js +0 -5
package/README.md
CHANGED
|
@@ -1,92 +1,206 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
1
|
+
# iota-fetch
|
|
2
|
+
|
|
3
|
+
一个基于 **axios** 的二次封装请求库,提供统一的 `get/post/delete/put/patch` 调用方式,并内置**请求队列**能力(可按 key 中断单个请求或中断全部请求)。支持自定义 axios 默认配置、请求/响应拦截器,以及可选的 loading 显示/隐藏钩子。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i iota-fetch axios
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> 本项目本身依赖 `axios`,如果你在业务工程里已安装 axios,可按你的依赖管理策略处理(避免重复安装/版本冲突)。
|
|
12
|
+
|
|
13
|
+
## 快速开始
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { createFetch } from "iota-fetch";
|
|
17
|
+
|
|
18
|
+
const fetch = createFetch({
|
|
19
|
+
requestConfig: {
|
|
20
|
+
baseURL: "https://api.example.com",
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json;charset=utf-8",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// GET:第二个参数会作为 query params
|
|
28
|
+
const list = await fetch.get("/items", { page: 1, pageSize: 10 });
|
|
29
|
+
|
|
30
|
+
// POST:第二个参数会作为 body data
|
|
31
|
+
const created = await fetch.post("/items", { name: "foo" });
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API
|
|
35
|
+
|
|
36
|
+
### `createFetch(options)`
|
|
37
|
+
|
|
38
|
+
创建一个包含 `get/post/delete/put/patch` 的请求对象。
|
|
39
|
+
|
|
40
|
+
#### 参数 `options`
|
|
41
|
+
|
|
42
|
+
- **`requestConfig`**: `CreateAxiosDefaults`
|
|
43
|
+
- axios 实例默认配置(如 `baseURL`、`timeout`、`headers` 等)
|
|
44
|
+
- **`requestIntercept?`**: `() => { onFulfilled, onRejected }`
|
|
45
|
+
- 请求拦截器工厂函数(内部会 `instance.interceptors.request.use(...)`)
|
|
46
|
+
- **`responseIntercept?`**: `() => { onFulfilled, onRejected }`
|
|
47
|
+
- 响应拦截器工厂函数(内部会 `instance.interceptors.response.use(...)`)
|
|
48
|
+
- **`loading?`**: `{ show(): void; hide(): void }`
|
|
49
|
+
- 传入后可配合单次请求的 `config.loading` 控制显示/隐藏
|
|
50
|
+
|
|
51
|
+
#### 返回值
|
|
52
|
+
|
|
53
|
+
返回 `fetch` 对象:
|
|
54
|
+
|
|
55
|
+
- **`fetch.get(url, data?, config?)`**
|
|
56
|
+
- **`fetch.delete(url, data?, config?)`**
|
|
57
|
+
- **`fetch.post(url, data?, config?)`**
|
|
58
|
+
- **`fetch.put(url, data?, config?)`**
|
|
59
|
+
- **`fetch.patch(url, data?, config?)`**
|
|
60
|
+
|
|
61
|
+
其中:
|
|
62
|
+
- `url: string`
|
|
63
|
+
- `data?: any`
|
|
64
|
+
- `config?: AxiosRequestConfig & { loading?: boolean }`
|
|
65
|
+
|
|
66
|
+
行为规则:
|
|
67
|
+
- `get/delete`:`data` 会被放到 `params`
|
|
68
|
+
- `post/put/patch`:`data` 会被放到 `data`
|
|
69
|
+
- 返回值:默认 `Promise<R>`,内部 `resolve(res.data)`
|
|
70
|
+
|
|
71
|
+
### 拦截器示例
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import type { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from "axios";
|
|
75
|
+
import { createFetch } from "iota-fetch";
|
|
76
|
+
|
|
77
|
+
const fetch = createFetch({
|
|
78
|
+
requestConfig: { baseURL: "https://api.example.com" },
|
|
79
|
+
requestIntercept: () => ({
|
|
80
|
+
onFulfilled: (config: InternalAxiosRequestConfig) => {
|
|
81
|
+
config.headers.set("X-Token", "your-token");
|
|
82
|
+
return config;
|
|
83
|
+
},
|
|
84
|
+
onRejected: (error: AxiosError) => Promise.reject(error),
|
|
85
|
+
}),
|
|
86
|
+
responseIntercept: () => ({
|
|
87
|
+
onFulfilled: (resp: AxiosResponse) => resp,
|
|
88
|
+
onRejected: (error: AxiosError) => Promise.reject(error),
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Loading 示例
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { createFetch } from "iota-fetch";
|
|
97
|
+
|
|
98
|
+
const loading = {
|
|
99
|
+
show: () => console.log("loading show"),
|
|
100
|
+
hide: () => console.log("loading hide"),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const fetch = createFetch({
|
|
104
|
+
requestConfig: { baseURL: "https://api.example.com" },
|
|
105
|
+
loading,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// 只有当 config.loading 为 true 才会触发 show/hide
|
|
109
|
+
await fetch.get("/items", { page: 1 }, { loading: true });
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## 请求队列与取消请求
|
|
113
|
+
|
|
114
|
+
包对外导出 `requestQueue`,内部用 `AbortController` 管理请求。
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { requestQueue } from "iota-fetch";
|
|
118
|
+
|
|
119
|
+
// 获取当前队列(Map<key, AbortController>)
|
|
120
|
+
const q = requestQueue.getQueue();
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### key 规则
|
|
124
|
+
|
|
125
|
+
key 默认由以下规则生成:
|
|
126
|
+
|
|
127
|
+
1. 基础部分:`method + "-" + url`
|
|
128
|
+
2. 数据部分:如果存在 `data`,则对其进行以下处理:
|
|
129
|
+
- 递归排序对象键
|
|
130
|
+
- 清洗数据(过滤 `undefined` 和函数)
|
|
131
|
+
- 将处理后的数据转换为 JSON 字符串
|
|
132
|
+
- 使用 MD5 生成哈希值
|
|
133
|
+
3. 最终 key:`基础部分 + "-" + MD5哈希值`
|
|
134
|
+
|
|
135
|
+
这样处理的好处是:
|
|
136
|
+
- 相同的请求参数(无论顺序如何)会生成相同的 key
|
|
137
|
+
- 避免了复杂参数导致 key 过长的问题
|
|
138
|
+
- 提高了 key 的唯一性和安全性
|
|
139
|
+
|
|
140
|
+
你也可以手动生成:
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const key = requestQueue.createKey("get", "/items", { page: 1 });
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
示例:
|
|
147
|
+
```ts
|
|
148
|
+
// 以下两个请求会生成相同的 key
|
|
149
|
+
const key1 = requestQueue.createKey("get", "/items", { page: 1, size: 10 });
|
|
150
|
+
const key2 = requestQueue.createKey("get", "/items", { size: 10, page: 1 });
|
|
151
|
+
|
|
152
|
+
// 输出示例:"get-/items-5f4dcc3b5aa765d61d8327deb882cf99"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 中断单个请求
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
requestQueue.abortive(key);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 中断所有请求
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
requestQueue.removeResAll();
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 同 key 自动取消旧请求(内置行为)
|
|
168
|
+
|
|
169
|
+
当发起新请求时,如果队列里已存在同一个 key,会先取消旧请求再登记新请求(避免相同请求并发造成的覆盖与浪费)。
|
|
170
|
+
|
|
171
|
+
> 注意:是否算“同一个请求”取决于 key(包含 `method/url/data` 的 JSON 字符串)。
|
|
172
|
+
|
|
173
|
+
## 开发与构建
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# 构建产物到 lib/(CJS + ESM + d.ts)
|
|
177
|
+
npm run build
|
|
178
|
+
|
|
179
|
+
# 开发模式(watch + 本地静态服务 + livereload)
|
|
180
|
+
npm run start
|
|
181
|
+
|
|
182
|
+
# 自动发布脚本(检查代码更新、npm 登录状态、版本管理)
|
|
183
|
+
npm run release
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
构建输出(默认):
|
|
187
|
+
- `lib/bundle.cjs.js`
|
|
188
|
+
- `lib/bundle.esm.js`
|
|
189
|
+
- `lib/main.d.ts`
|
|
190
|
+
|
|
191
|
+
## 发布流程
|
|
192
|
+
|
|
193
|
+
1. 运行 `npm run release` 启动发布流程
|
|
194
|
+
2. 脚本会检查代码是否有更新
|
|
195
|
+
3. 检查 npm 是否登录
|
|
196
|
+
4. 显示当前版本和仓库版本
|
|
197
|
+
5. 选择版本升级类型(小版本/中版本/大版本)
|
|
198
|
+
6. 执行构建和发布
|
|
199
|
+
7. 显示远程包的最新版本
|
|
200
|
+
|
|
201
|
+
## 版本管理
|
|
202
|
+
|
|
203
|
+
- **小版本**:修复 bug,向后兼容
|
|
204
|
+
- **中版本**:添加新功能,向后兼容
|
|
205
|
+
- **大版本**:不向后兼容的变更
|
|
206
|
+
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FetchSturt, Loading, Options } from "./models";
|
|
2
|
+
declare const createFetch: ({ requestConfig, requestIntercept, responseIntercept, loading, }: Options & {
|
|
3
|
+
loading?: Loading;
|
|
4
|
+
}) => FetchSturt;
|
|
5
|
+
export { createFetch };
|
|
6
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/axios/fetch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAa,UAAU,EAAY,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAElF,QAAA,MAAM,WAAW,GAAI,kEAKlB,OAAO,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,eAiBjC,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AxiosInstance } from "axios";
|
|
2
|
+
import { Loading, RequestConfig } from "./models";
|
|
3
|
+
declare const fetchData: <D, R = Record<string, any> | any>(instance: AxiosInstance, { url, method, data, config }: RequestConfig<D>, loading?: Loading) => Promise<R>;
|
|
4
|
+
export default fetchData;
|
|
5
|
+
//# sourceMappingURL=fetchFun.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetchFun.d.ts","sourceRoot":"","sources":["../../src/axios/fetchFun.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAsB,MAAM,OAAO,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAGlD,QAAA,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EACjD,UAAU,aAAa,EACvB,+BAA+B,aAAa,CAAC,CAAC,CAAC,EAC/C,UAAU,OAAO,KAChB,OAAO,CAAC,CAAC,CAoCX,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../../src/axios/instance.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,QAAA,MAAM,cAAc,GAAI,wDAAwD,OAAO,KAAG,aAkBzF,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AxiosError, AxiosRequestConfig, AxiosResponse, CreateAxiosDefaults, InternalAxiosRequestConfig, Method } from "axios";
|
|
2
|
+
export interface Options {
|
|
3
|
+
requestConfig: CreateAxiosDefaults;
|
|
4
|
+
requestIntercept?: () => {
|
|
5
|
+
onFulfilled: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig;
|
|
6
|
+
onRejected: (error: AxiosError) => Promise<AxiosError>;
|
|
7
|
+
};
|
|
8
|
+
responseIntercept?: () => {
|
|
9
|
+
onFulfilled: (response: AxiosResponse) => AxiosResponse;
|
|
10
|
+
onRejected: (error: AxiosError) => Promise<AxiosError>;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export type ConfigPorps = {
|
|
14
|
+
loading?: boolean;
|
|
15
|
+
} & AxiosRequestConfig;
|
|
16
|
+
export interface RequestConfig<D = any> {
|
|
17
|
+
url: string;
|
|
18
|
+
method: Method;
|
|
19
|
+
data?: D;
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
config?: ConfigPorps;
|
|
22
|
+
}
|
|
23
|
+
export type Loading = {
|
|
24
|
+
show: () => void;
|
|
25
|
+
hide: () => void;
|
|
26
|
+
};
|
|
27
|
+
export type FuncName = "get" | "post" | "delete" | "put" | "patch";
|
|
28
|
+
export type FetchFunc = {
|
|
29
|
+
<D = any, R = Record<string, any>>(url: string, data?: D, config?: ConfigPorps): Promise<R>;
|
|
30
|
+
};
|
|
31
|
+
export type FetchSturt = Record<FuncName, FetchFunc>;
|
|
32
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/axios/models.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,0BAA0B,EAC1B,MAAM,EACP,MAAM,OAAO,CAAC;AAEf,MAAM,WAAW,OAAO;IACtB,aAAa,EAAE,mBAAmB,CAAC;IAEnC,gBAAgB,CAAC,EAAE,MAAM;QACvB,WAAW,EAAE,CAAC,MAAM,EAAE,0BAA0B,KAAK,0BAA0B,CAAC;QAChF,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;KACxD,CAAC;IAEF,iBAAiB,CAAC,EAAE,MAAM;QACxB,WAAW,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,aAAa,CAAC;QACxD,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;KACxD,CAAC;CACH;AAED,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,kBAAkB,CAAC;AAErE,MAAM,WAAW,aAAa,CAAC,CAAC,GAAG,GAAG;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC;AAEnE,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC7F,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
declare class RequestQueue {
|
|
2
|
+
private static instance;
|
|
3
|
+
private queue;
|
|
4
|
+
constructor();
|
|
5
|
+
private sortObjectKeys;
|
|
6
|
+
getQueue(): Map<string, AbortController>;
|
|
7
|
+
createKey<T>(method: string, path: string, data?: T): string;
|
|
8
|
+
setQueue(key: string, controller: AbortController): void;
|
|
9
|
+
deleteQueue(key: string): void;
|
|
10
|
+
hasQueue(key: string): boolean;
|
|
11
|
+
abortive(key: string): void;
|
|
12
|
+
removeResAll(): void;
|
|
13
|
+
}
|
|
14
|
+
declare let requestQueue: RequestQueue;
|
|
15
|
+
export { requestQueue };
|
|
16
|
+
//# sourceMappingURL=requestQueue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requestQueue.d.ts","sourceRoot":"","sources":["../../src/axios/requestQueue.ts"],"names":[],"mappings":"AAEA,cAAM,YAAY;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAe;IACtC,OAAO,CAAC,KAAK,CAA+B;;IAe5C,OAAO,CAAC,cAAc;IAkBf,QAAQ,IAAI,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;IAKxC,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,MAAM;IAU5D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe;IAKjD,WAAW,CAAC,GAAG,EAAE,MAAM;IAKvB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAK9B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAO3B,YAAY,IAAI,IAAI;CAI5B;AAED,QAAA,IAAI,YAAY,cAAqB,CAAC;AAEtC,OAAO,EAAE,YAAY,EAAE,CAAC"}
|