@yh-ui/request 0.1.21
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 +274 -0
- package/dist/adapters/fetch.cjs +157 -0
- package/dist/adapters/fetch.d.ts +25 -0
- package/dist/adapters/fetch.mjs +148 -0
- package/dist/adapters/index.cjs +27 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.mjs +2 -0
- package/dist/adapters/platform.cjs +394 -0
- package/dist/adapters/platform.d.ts +72 -0
- package/dist/adapters/platform.mjs +369 -0
- package/dist/cache/index.cjs +56 -0
- package/dist/cache/index.d.ts +21 -0
- package/dist/cache/index.mjs +14 -0
- package/dist/cache/indexedDB.cjs +188 -0
- package/dist/cache/indexedDB.d.ts +58 -0
- package/dist/cache/indexedDB.mjs +176 -0
- package/dist/cache/localStorage.cjs +158 -0
- package/dist/cache/localStorage.d.ts +58 -0
- package/dist/cache/localStorage.mjs +153 -0
- package/dist/cache/memory.cjs +112 -0
- package/dist/cache/memory.d.ts +71 -0
- package/dist/cache/memory.mjs +103 -0
- package/dist/graphql.cjs +255 -0
- package/dist/graphql.d.ts +192 -0
- package/dist/graphql.mjs +235 -0
- package/dist/http-cache.cjs +248 -0
- package/dist/http-cache.d.ts +156 -0
- package/dist/http-cache.mjs +233 -0
- package/dist/index.cjs +181 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.mjs +16 -0
- package/dist/interceptors/debug.cjs +139 -0
- package/dist/interceptors/debug.d.ts +92 -0
- package/dist/interceptors/debug.mjs +130 -0
- package/dist/interceptors/index.cjs +38 -0
- package/dist/interceptors/index.d.ts +6 -0
- package/dist/interceptors/index.mjs +3 -0
- package/dist/interceptors/progress.cjs +185 -0
- package/dist/interceptors/progress.d.ts +97 -0
- package/dist/interceptors/progress.mjs +177 -0
- package/dist/interceptors/security.cjs +154 -0
- package/dist/interceptors/security.d.ts +83 -0
- package/dist/interceptors/security.mjs +134 -0
- package/dist/plugin.cjs +166 -0
- package/dist/plugin.d.ts +106 -0
- package/dist/plugin.mjs +163 -0
- package/dist/request.cjs +396 -0
- package/dist/request.d.ts +111 -0
- package/dist/request.mjs +339 -0
- package/dist/types.cjs +13 -0
- package/dist/types.d.ts +157 -0
- package/dist/types.mjs +7 -0
- package/dist/useAIStream.cjs +125 -0
- package/dist/useAIStream.d.ts +89 -0
- package/dist/useAIStream.mjs +108 -0
- package/dist/useLoadMore.cjs +136 -0
- package/dist/useLoadMore.d.ts +84 -0
- package/dist/useLoadMore.mjs +134 -0
- package/dist/usePagination.cjs +141 -0
- package/dist/usePagination.d.ts +89 -0
- package/dist/usePagination.mjs +132 -0
- package/dist/useQueue.cjs +243 -0
- package/dist/useQueue.d.ts +118 -0
- package/dist/useQueue.mjs +239 -0
- package/dist/useRequest.cjs +325 -0
- package/dist/useRequest.d.ts +126 -0
- package/dist/useRequest.mjs +329 -0
- package/dist/useRequestQueue.cjs +36 -0
- package/dist/useRequestQueue.d.ts +52 -0
- package/dist/useRequestQueue.mjs +27 -0
- package/dist/useSSE.cjs +241 -0
- package/dist/useSSE.d.ts +74 -0
- package/dist/useSSE.mjs +226 -0
- package/dist/websocket.cjs +325 -0
- package/dist/websocket.d.ts +163 -0
- package/dist/websocket.mjs +316 -0
- package/package.json +61 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
export function detectPlatform() {
|
|
2
|
+
const globalObj = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : {};
|
|
3
|
+
if (typeof Deno !== "undefined") {
|
|
4
|
+
return {
|
|
5
|
+
environment: "deno",
|
|
6
|
+
supportsFetch: true,
|
|
7
|
+
supportsFormData: true,
|
|
8
|
+
supportsAbortController: true
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (typeof Bun !== "undefined") {
|
|
12
|
+
return {
|
|
13
|
+
environment: "bun",
|
|
14
|
+
supportsFetch: true,
|
|
15
|
+
supportsFormData: true,
|
|
16
|
+
supportsAbortController: true
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
if (globalObj.edgeRuntime !== void 0 || typeof navigator !== "undefined" && navigator.userAgent.includes("Cloudflare") || globalObj.caches !== void 0) {
|
|
20
|
+
return {
|
|
21
|
+
environment: "edge",
|
|
22
|
+
supportsFetch: true,
|
|
23
|
+
supportsFormData: true,
|
|
24
|
+
supportsAbortController: true
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (typeof process !== "undefined" && process.versions?.node) {
|
|
28
|
+
return {
|
|
29
|
+
environment: "node",
|
|
30
|
+
supportsFetch: typeof fetch !== "undefined",
|
|
31
|
+
supportsFormData: typeof FormData !== "undefined",
|
|
32
|
+
supportsAbortController: typeof AbortController !== "undefined"
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
environment: "browser",
|
|
37
|
+
supportsFetch: typeof fetch !== "undefined",
|
|
38
|
+
supportsFormData: typeof FormData !== "undefined",
|
|
39
|
+
supportsAbortController: typeof AbortController !== "undefined"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export const platform = detectPlatform();
|
|
43
|
+
export class NodeHttpAdapter {
|
|
44
|
+
name = "node-http";
|
|
45
|
+
http = NodeHttpAdapter.getHttpModule();
|
|
46
|
+
static getHttpModule() {
|
|
47
|
+
try {
|
|
48
|
+
return require("http");
|
|
49
|
+
} catch {
|
|
50
|
+
throw new Error("Node.js http module is not available");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
isSupported() {
|
|
54
|
+
return typeof process !== "undefined" && !!process.versions?.node;
|
|
55
|
+
}
|
|
56
|
+
async request(config) {
|
|
57
|
+
const { fullPath, method = "GET", headers = {}, data, signal, credentials } = config;
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const urlObj = new URL(fullPath);
|
|
60
|
+
const isHttps = urlObj.protocol === "https:";
|
|
61
|
+
const httpModule = isHttps ? require("https") : this.http;
|
|
62
|
+
const options = {
|
|
63
|
+
hostname: urlObj.hostname,
|
|
64
|
+
port: urlObj.port || (isHttps ? 443 : 80),
|
|
65
|
+
path: urlObj.pathname + urlObj.search,
|
|
66
|
+
method,
|
|
67
|
+
headers: {
|
|
68
|
+
...headers,
|
|
69
|
+
// 处理凭证
|
|
70
|
+
...credentials === "include" ? { Cookie: "" } : {}
|
|
71
|
+
},
|
|
72
|
+
timeout: config.timeout || 3e4
|
|
73
|
+
};
|
|
74
|
+
if (isHttps) {
|
|
75
|
+
Object.assign(options, {
|
|
76
|
+
rejectUnauthorized: false
|
|
77
|
+
// 允许自签名证书(可选配置)
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const req = httpModule.request(options, (res) => {
|
|
81
|
+
const chunks = [];
|
|
82
|
+
res.on("data", (chunk) => {
|
|
83
|
+
chunks.push(chunk);
|
|
84
|
+
});
|
|
85
|
+
res.on("end", () => {
|
|
86
|
+
const body = Buffer.concat(chunks).toString("utf-8");
|
|
87
|
+
let responseData;
|
|
88
|
+
if (config.responseType === "text") {
|
|
89
|
+
responseData = body;
|
|
90
|
+
} else if (config.responseType === "arraybuffer") {
|
|
91
|
+
responseData = Buffer.from(body).buffer;
|
|
92
|
+
} else if (config.responseType === "blob") {
|
|
93
|
+
responseData = Buffer.from(body);
|
|
94
|
+
} else {
|
|
95
|
+
try {
|
|
96
|
+
responseData = body ? JSON.parse(body) : null;
|
|
97
|
+
} catch {
|
|
98
|
+
responseData = body;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const mockResponse = {
|
|
102
|
+
ok: (res.statusCode || 200) >= 200 && (res.statusCode || 200) < 300,
|
|
103
|
+
status: res.statusCode || 200,
|
|
104
|
+
statusText: res.statusMessage || "",
|
|
105
|
+
headers: res.headers,
|
|
106
|
+
text: () => Promise.resolve(body),
|
|
107
|
+
json: () => Promise.resolve(responseData),
|
|
108
|
+
blob: () => Promise.resolve(Buffer.from(body)),
|
|
109
|
+
arrayBuffer: () => Promise.resolve(Buffer.from(body).buffer),
|
|
110
|
+
formData: () => Promise.resolve(new URLSearchParams(body))
|
|
111
|
+
};
|
|
112
|
+
resolve({
|
|
113
|
+
data: responseData,
|
|
114
|
+
response: mockResponse,
|
|
115
|
+
config,
|
|
116
|
+
requestId: config.requestId
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
req.on("timeout", () => {
|
|
121
|
+
req.destroy();
|
|
122
|
+
reject(new Error("Request timeout"));
|
|
123
|
+
});
|
|
124
|
+
req.on("error", (error) => {
|
|
125
|
+
reject(error);
|
|
126
|
+
});
|
|
127
|
+
if (signal) {
|
|
128
|
+
signal.addEventListener("abort", () => {
|
|
129
|
+
req.destroy();
|
|
130
|
+
reject(new DOMException("Aborted", "AbortError"));
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (data && method !== "GET") {
|
|
134
|
+
const body = typeof data === "string" ? data : JSON.stringify(data);
|
|
135
|
+
req.write(body);
|
|
136
|
+
}
|
|
137
|
+
req.end();
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export class DenoAdapter {
|
|
142
|
+
name = "deno";
|
|
143
|
+
isSupported() {
|
|
144
|
+
return typeof globalThis.Deno !== "undefined";
|
|
145
|
+
}
|
|
146
|
+
async request(config) {
|
|
147
|
+
const {
|
|
148
|
+
fullPath,
|
|
149
|
+
method = "GET",
|
|
150
|
+
headers = {},
|
|
151
|
+
data,
|
|
152
|
+
signal,
|
|
153
|
+
credentials,
|
|
154
|
+
responseType,
|
|
155
|
+
timeout
|
|
156
|
+
} = config;
|
|
157
|
+
const fetchOptions = {
|
|
158
|
+
method,
|
|
159
|
+
headers,
|
|
160
|
+
credentials
|
|
161
|
+
};
|
|
162
|
+
if (data && method !== "GET") {
|
|
163
|
+
if (data instanceof FormData) {
|
|
164
|
+
fetchOptions.body = data;
|
|
165
|
+
} else {
|
|
166
|
+
fetchOptions.body = JSON.stringify(data);
|
|
167
|
+
if (!headers["Content-Type"]) {
|
|
168
|
+
;
|
|
169
|
+
fetchOptions.headers["Content-Type"] = "application/json";
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const controller = new AbortController();
|
|
174
|
+
fetchOptions.signal = controller.signal;
|
|
175
|
+
if (timeout) {
|
|
176
|
+
setTimeout(() => controller.abort(), timeout).unref?.();
|
|
177
|
+
}
|
|
178
|
+
if (signal) {
|
|
179
|
+
signal.addEventListener("abort", () => controller.abort());
|
|
180
|
+
}
|
|
181
|
+
const response = await fetch(fullPath, fetchOptions);
|
|
182
|
+
let responseData;
|
|
183
|
+
switch (responseType) {
|
|
184
|
+
case "text":
|
|
185
|
+
responseData = await response.text();
|
|
186
|
+
break;
|
|
187
|
+
case "blob":
|
|
188
|
+
responseData = await response.blob();
|
|
189
|
+
break;
|
|
190
|
+
case "arraybuffer":
|
|
191
|
+
responseData = await response.arrayBuffer();
|
|
192
|
+
break;
|
|
193
|
+
case "formdata":
|
|
194
|
+
responseData = await response.formData();
|
|
195
|
+
break;
|
|
196
|
+
default:
|
|
197
|
+
const text = await response.text();
|
|
198
|
+
responseData = text ? JSON.parse(text) : null;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
data: responseData,
|
|
202
|
+
response,
|
|
203
|
+
config,
|
|
204
|
+
requestId: config.requestId
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export class BunAdapter {
|
|
209
|
+
name = "bun";
|
|
210
|
+
isSupported() {
|
|
211
|
+
return typeof globalThis.Bun !== "undefined";
|
|
212
|
+
}
|
|
213
|
+
// Bun 直接使用 fetch,与 FetchAdapter 相同
|
|
214
|
+
// 但保留此类以便未来可能的 Bun 特定优化
|
|
215
|
+
async request(config) {
|
|
216
|
+
const {
|
|
217
|
+
fullPath,
|
|
218
|
+
method = "GET",
|
|
219
|
+
headers = {},
|
|
220
|
+
data,
|
|
221
|
+
signal,
|
|
222
|
+
credentials,
|
|
223
|
+
responseType,
|
|
224
|
+
timeout
|
|
225
|
+
} = config;
|
|
226
|
+
const fetchOptions = {
|
|
227
|
+
method,
|
|
228
|
+
headers,
|
|
229
|
+
credentials
|
|
230
|
+
};
|
|
231
|
+
if (data && method !== "GET") {
|
|
232
|
+
if (data instanceof FormData) {
|
|
233
|
+
fetchOptions.body = data;
|
|
234
|
+
} else {
|
|
235
|
+
fetchOptions.body = JSON.stringify(data);
|
|
236
|
+
if (!headers["Content-Type"]) {
|
|
237
|
+
;
|
|
238
|
+
fetchOptions.headers["Content-Type"] = "application/json";
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (timeout) {
|
|
243
|
+
const controller = new AbortController();
|
|
244
|
+
fetchOptions.signal = controller.signal;
|
|
245
|
+
setTimeout(() => controller.abort(), timeout);
|
|
246
|
+
} else if (signal) {
|
|
247
|
+
fetchOptions.signal = signal;
|
|
248
|
+
}
|
|
249
|
+
const response = await fetch(fullPath, fetchOptions);
|
|
250
|
+
let responseData;
|
|
251
|
+
switch (responseType) {
|
|
252
|
+
case "text":
|
|
253
|
+
responseData = await response.text();
|
|
254
|
+
break;
|
|
255
|
+
case "blob":
|
|
256
|
+
responseData = await response.blob();
|
|
257
|
+
break;
|
|
258
|
+
case "arraybuffer":
|
|
259
|
+
responseData = await response.arrayBuffer();
|
|
260
|
+
break;
|
|
261
|
+
case "formdata":
|
|
262
|
+
responseData = await response.formData();
|
|
263
|
+
break;
|
|
264
|
+
default:
|
|
265
|
+
const text = await response.text();
|
|
266
|
+
responseData = text ? JSON.parse(text) : null;
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
data: responseData,
|
|
270
|
+
response,
|
|
271
|
+
config,
|
|
272
|
+
requestId: config.requestId
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
export class EdgeAdapter {
|
|
277
|
+
name = "edge";
|
|
278
|
+
isSupported() {
|
|
279
|
+
return platform.environment === "edge";
|
|
280
|
+
}
|
|
281
|
+
async request(config) {
|
|
282
|
+
const {
|
|
283
|
+
fullPath,
|
|
284
|
+
method = "GET",
|
|
285
|
+
headers = {},
|
|
286
|
+
data,
|
|
287
|
+
signal,
|
|
288
|
+
credentials,
|
|
289
|
+
responseType,
|
|
290
|
+
timeout
|
|
291
|
+
} = config;
|
|
292
|
+
const fetchOptions = {
|
|
293
|
+
method,
|
|
294
|
+
headers,
|
|
295
|
+
credentials
|
|
296
|
+
};
|
|
297
|
+
if (data && method !== "GET") {
|
|
298
|
+
if (data instanceof URLSearchParams) {
|
|
299
|
+
fetchOptions.body = data;
|
|
300
|
+
} else {
|
|
301
|
+
fetchOptions.body = JSON.stringify(data);
|
|
302
|
+
if (!headers["Content-Type"]) {
|
|
303
|
+
;
|
|
304
|
+
fetchOptions.headers["Content-Type"] = "application/json";
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (timeout) {
|
|
309
|
+
const controller = new AbortController();
|
|
310
|
+
fetchOptions.signal = controller.signal;
|
|
311
|
+
setTimeout(() => controller.abort(), timeout);
|
|
312
|
+
} else if (signal) {
|
|
313
|
+
fetchOptions.signal = signal;
|
|
314
|
+
}
|
|
315
|
+
const response = await fetch(fullPath, fetchOptions);
|
|
316
|
+
let responseData;
|
|
317
|
+
switch (responseType) {
|
|
318
|
+
case "text":
|
|
319
|
+
responseData = await response.text();
|
|
320
|
+
break;
|
|
321
|
+
case "blob":
|
|
322
|
+
responseData = await response.blob();
|
|
323
|
+
break;
|
|
324
|
+
case "arraybuffer":
|
|
325
|
+
responseData = await response.arrayBuffer();
|
|
326
|
+
break;
|
|
327
|
+
default:
|
|
328
|
+
const text = await response.text();
|
|
329
|
+
responseData = text ? JSON.parse(text) : null;
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
data: responseData,
|
|
333
|
+
response,
|
|
334
|
+
config,
|
|
335
|
+
requestId: config.requestId
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
export function getBestAdapter() {
|
|
340
|
+
const { environment } = platform;
|
|
341
|
+
switch (environment) {
|
|
342
|
+
case "deno":
|
|
343
|
+
return new DenoAdapter();
|
|
344
|
+
case "bun":
|
|
345
|
+
return new BunAdapter();
|
|
346
|
+
case "edge":
|
|
347
|
+
return new EdgeAdapter();
|
|
348
|
+
case "node":
|
|
349
|
+
return new NodeHttpAdapter();
|
|
350
|
+
case "browser":
|
|
351
|
+
default:
|
|
352
|
+
return new (require("./fetch")).FetchAdapter();
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
export function getAdapter(environment) {
|
|
356
|
+
switch (environment) {
|
|
357
|
+
case "deno":
|
|
358
|
+
return new DenoAdapter();
|
|
359
|
+
case "bun":
|
|
360
|
+
return new BunAdapter();
|
|
361
|
+
case "edge":
|
|
362
|
+
return new EdgeAdapter();
|
|
363
|
+
case "node":
|
|
364
|
+
return new NodeHttpAdapter();
|
|
365
|
+
case "browser":
|
|
366
|
+
default:
|
|
367
|
+
return new (require("./fetch")).FetchAdapter();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
createCache: true
|
|
8
|
+
};
|
|
9
|
+
exports.createCache = createCache;
|
|
10
|
+
var _memory = require("./memory.cjs");
|
|
11
|
+
Object.keys(_memory).forEach(function (key) {
|
|
12
|
+
if (key === "default" || key === "__esModule") return;
|
|
13
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
14
|
+
if (key in exports && exports[key] === _memory[key]) return;
|
|
15
|
+
Object.defineProperty(exports, key, {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () {
|
|
18
|
+
return _memory[key];
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
var _localStorage = require("./localStorage.cjs");
|
|
23
|
+
Object.keys(_localStorage).forEach(function (key) {
|
|
24
|
+
if (key === "default" || key === "__esModule") return;
|
|
25
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
26
|
+
if (key in exports && exports[key] === _localStorage[key]) return;
|
|
27
|
+
Object.defineProperty(exports, key, {
|
|
28
|
+
enumerable: true,
|
|
29
|
+
get: function () {
|
|
30
|
+
return _localStorage[key];
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
var _indexedDB = require("./indexedDB.cjs");
|
|
35
|
+
Object.keys(_indexedDB).forEach(function (key) {
|
|
36
|
+
if (key === "default" || key === "__esModule") return;
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
38
|
+
if (key in exports && exports[key] === _indexedDB[key]) return;
|
|
39
|
+
Object.defineProperty(exports, key, {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
get: function () {
|
|
42
|
+
return _indexedDB[key];
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
function createCache(type = "memory", options) {
|
|
47
|
+
switch (type) {
|
|
48
|
+
case "localStorage":
|
|
49
|
+
return new (require("./localStorage.cjs").LocalStorageCache)(options);
|
|
50
|
+
case "indexedDB":
|
|
51
|
+
return new (require("./indexedDB.cjs").IndexedDBCache)(options);
|
|
52
|
+
case "memory":
|
|
53
|
+
default:
|
|
54
|
+
return new (require("./memory.cjs").MemoryCache)();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 缓存系统导出
|
|
3
|
+
*/
|
|
4
|
+
export * from './memory';
|
|
5
|
+
export * from './localStorage';
|
|
6
|
+
export * from './indexedDB';
|
|
7
|
+
import { type CacheOptions } from './memory';
|
|
8
|
+
/**
|
|
9
|
+
* 创建缓存实例的工厂函数
|
|
10
|
+
*/
|
|
11
|
+
export type CacheType = 'memory' | 'localStorage' | 'indexedDB';
|
|
12
|
+
export interface CacheFactoryOptions {
|
|
13
|
+
/** 缓存类型 */
|
|
14
|
+
type?: CacheType;
|
|
15
|
+
/** 缓存选项 */
|
|
16
|
+
options?: CacheOptions;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 根据类型创建缓存实例
|
|
20
|
+
*/
|
|
21
|
+
export declare function createCache(type?: CacheType, options?: CacheOptions): any;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./memory.mjs";
|
|
2
|
+
export * from "./localStorage.mjs";
|
|
3
|
+
export * from "./indexedDB.mjs";
|
|
4
|
+
export function createCache(type = "memory", options) {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case "localStorage":
|
|
7
|
+
return new (require("./localStorage")).LocalStorageCache(options);
|
|
8
|
+
case "indexedDB":
|
|
9
|
+
return new (require("./indexedDB")).IndexedDBCache(options);
|
|
10
|
+
case "memory":
|
|
11
|
+
default:
|
|
12
|
+
return new (require("./memory")).MemoryCache();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.indexedDBCache = exports.IndexedDBCache = void 0;
|
|
7
|
+
class IndexedDBCache {
|
|
8
|
+
dbName;
|
|
9
|
+
storeName;
|
|
10
|
+
dbVersion;
|
|
11
|
+
db = null;
|
|
12
|
+
constructor(options = {}) {
|
|
13
|
+
this.dbName = options.dbName || "yh_request_cache";
|
|
14
|
+
this.storeName = options.storeName || "cache";
|
|
15
|
+
this.dbVersion = options.dbVersion || 1;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 打开数据库
|
|
19
|
+
*/
|
|
20
|
+
async openDB() {
|
|
21
|
+
if (this.db) return this.db;
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
24
|
+
request.onerror = () => {
|
|
25
|
+
reject(request.error);
|
|
26
|
+
};
|
|
27
|
+
request.onsuccess = () => {
|
|
28
|
+
this.db = request.result;
|
|
29
|
+
resolve(this.db);
|
|
30
|
+
};
|
|
31
|
+
request.onupgradeneeded = event => {
|
|
32
|
+
const db = event.target.result;
|
|
33
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
34
|
+
db.createObjectStore(this.storeName, {
|
|
35
|
+
keyPath: "key"
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 获取缓存
|
|
43
|
+
*/
|
|
44
|
+
async get(key, _staleTime) {
|
|
45
|
+
try {
|
|
46
|
+
const db = await this.openDB();
|
|
47
|
+
const transaction = db.transaction(this.storeName, "readonly");
|
|
48
|
+
const store = transaction.objectStore(this.storeName);
|
|
49
|
+
const request = store.get(key);
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
request.onsuccess = () => {
|
|
52
|
+
if (!request.result) {
|
|
53
|
+
resolve(void 0);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const item = request.result;
|
|
57
|
+
if (item.expireTime && Date.now() > item.expireTime) {
|
|
58
|
+
this.delete(key);
|
|
59
|
+
resolve(void 0);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
resolve(item.data);
|
|
63
|
+
};
|
|
64
|
+
request.onerror = () => {
|
|
65
|
+
reject(request.error);
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
} catch {
|
|
69
|
+
return void 0;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 设置缓存
|
|
74
|
+
*/
|
|
75
|
+
async set(key, data, options = {}) {
|
|
76
|
+
try {
|
|
77
|
+
const {
|
|
78
|
+
staleTime = 5 * 60 * 1e3
|
|
79
|
+
} = options;
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
const item = {
|
|
82
|
+
data,
|
|
83
|
+
expireTime: now + staleTime,
|
|
84
|
+
createTime: now
|
|
85
|
+
};
|
|
86
|
+
const db = await this.openDB();
|
|
87
|
+
const transaction = db.transaction(this.storeName, "readwrite");
|
|
88
|
+
const store = transaction.objectStore(this.storeName);
|
|
89
|
+
store.put({
|
|
90
|
+
key,
|
|
91
|
+
...item
|
|
92
|
+
});
|
|
93
|
+
await new Promise((resolve, reject) => {
|
|
94
|
+
transaction.oncomplete = () => resolve();
|
|
95
|
+
transaction.onerror = () => reject(transaction.error);
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.warn("IndexedDB cache set failed:", error);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* 删除缓存
|
|
103
|
+
*/
|
|
104
|
+
async delete(key) {
|
|
105
|
+
try {
|
|
106
|
+
const db = await this.openDB();
|
|
107
|
+
const transaction = db.transaction(this.storeName, "readwrite");
|
|
108
|
+
const store = transaction.objectStore(this.storeName);
|
|
109
|
+
store.delete(key);
|
|
110
|
+
await new Promise((resolve, reject) => {
|
|
111
|
+
transaction.oncomplete = () => resolve();
|
|
112
|
+
transaction.onerror = () => reject(transaction.error);
|
|
113
|
+
});
|
|
114
|
+
return true;
|
|
115
|
+
} catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 清空缓存
|
|
121
|
+
*/
|
|
122
|
+
async clear() {
|
|
123
|
+
try {
|
|
124
|
+
const db = await this.openDB();
|
|
125
|
+
const transaction = db.transaction(this.storeName, "readwrite");
|
|
126
|
+
const store = transaction.objectStore(this.storeName);
|
|
127
|
+
store.clear();
|
|
128
|
+
await new Promise((resolve, reject) => {
|
|
129
|
+
transaction.oncomplete = () => resolve();
|
|
130
|
+
transaction.onerror = () => reject(transaction.error);
|
|
131
|
+
});
|
|
132
|
+
} catch {}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* 检查缓存是否存在
|
|
136
|
+
*/
|
|
137
|
+
async has(key) {
|
|
138
|
+
const data = await this.get(key);
|
|
139
|
+
return data !== void 0;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 获取所有缓存 keys
|
|
143
|
+
*/
|
|
144
|
+
async keys() {
|
|
145
|
+
try {
|
|
146
|
+
const db = await this.openDB();
|
|
147
|
+
const transaction = db.transaction(this.storeName, "readonly");
|
|
148
|
+
const store = transaction.objectStore(this.storeName);
|
|
149
|
+
const request = store.getAllKeys();
|
|
150
|
+
return new Promise((resolve, reject) => {
|
|
151
|
+
request.onsuccess = () => {
|
|
152
|
+
resolve(request.result);
|
|
153
|
+
};
|
|
154
|
+
request.onerror = () => {
|
|
155
|
+
reject(request.error);
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
} catch {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 清理过期缓存
|
|
164
|
+
*/
|
|
165
|
+
async cleanup() {
|
|
166
|
+
try {
|
|
167
|
+
const db = await this.openDB();
|
|
168
|
+
const transaction = db.transaction(this.storeName, "readwrite");
|
|
169
|
+
const store = transaction.objectStore(this.storeName);
|
|
170
|
+
const request = store.getAll();
|
|
171
|
+
await new Promise((resolve, reject) => {
|
|
172
|
+
request.onsuccess = async () => {
|
|
173
|
+
const now = Date.now();
|
|
174
|
+
const items = request.result;
|
|
175
|
+
for (const item of items) {
|
|
176
|
+
if (item.expireTime && now > item.expireTime) {
|
|
177
|
+
store.delete(item.key);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
resolve();
|
|
181
|
+
};
|
|
182
|
+
request.onerror = () => reject(request.error);
|
|
183
|
+
});
|
|
184
|
+
} catch {}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
exports.IndexedDBCache = IndexedDBCache;
|
|
188
|
+
const indexedDBCache = exports.indexedDBCache = new IndexedDBCache();
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IndexedDB 缓存实现
|
|
3
|
+
* 适用于大量数据的持久化缓存
|
|
4
|
+
*/
|
|
5
|
+
export interface IndexedDBCacheOptions {
|
|
6
|
+
/** 数据库名称 */
|
|
7
|
+
dbName?: string;
|
|
8
|
+
/** 存储名称 */
|
|
9
|
+
storeName?: string;
|
|
10
|
+
/** 数据库版本 */
|
|
11
|
+
dbVersion?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* IndexedDB 缓存类
|
|
15
|
+
*/
|
|
16
|
+
export declare class IndexedDBCache {
|
|
17
|
+
private dbName;
|
|
18
|
+
private storeName;
|
|
19
|
+
private dbVersion;
|
|
20
|
+
private db;
|
|
21
|
+
constructor(options?: IndexedDBCacheOptions);
|
|
22
|
+
/**
|
|
23
|
+
* 打开数据库
|
|
24
|
+
*/
|
|
25
|
+
private openDB;
|
|
26
|
+
/**
|
|
27
|
+
* 获取缓存
|
|
28
|
+
*/
|
|
29
|
+
get<T>(key: string, _staleTime?: number): Promise<T | undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* 设置缓存
|
|
32
|
+
*/
|
|
33
|
+
set<T>(key: string, data: T, options?: {
|
|
34
|
+
staleTime?: number;
|
|
35
|
+
cacheTime?: number;
|
|
36
|
+
}): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* 删除缓存
|
|
39
|
+
*/
|
|
40
|
+
delete(key: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* 清空缓存
|
|
43
|
+
*/
|
|
44
|
+
clear(): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* 检查缓存是否存在
|
|
47
|
+
*/
|
|
48
|
+
has(key: string): Promise<boolean>;
|
|
49
|
+
/**
|
|
50
|
+
* 获取所有缓存 keys
|
|
51
|
+
*/
|
|
52
|
+
keys(): Promise<string[]>;
|
|
53
|
+
/**
|
|
54
|
+
* 清理过期缓存
|
|
55
|
+
*/
|
|
56
|
+
cleanup(): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
export declare const indexedDBCache: IndexedDBCache;
|