@jacraig/request 1.0.0
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 +201 -0
- package/README.md +2 -0
- package/lib/Request.cjs.js +471 -0
- package/lib/Request.esm.js +466 -0
- package/lib/Request.umd.js +475 -0
- package/lib/Request.umd.min.js +1 -0
- package/lib/declarations/Cache.d.ts +33 -0
- package/lib/declarations/Cache.d.ts.map +1 -0
- package/lib/declarations/Database.d.ts +15 -0
- package/lib/declarations/Database.d.ts.map +1 -0
- package/lib/declarations/Request.d.ts +62 -0
- package/lib/declarations/Request.d.ts.map +1 -0
- package/package.json +91 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import { Logger } from '@jacraig/woodchuck';
|
|
2
|
+
|
|
3
|
+
class DatabaseConnection {
|
|
4
|
+
constructor(dbName, tables, version) {
|
|
5
|
+
this.dbName = dbName;
|
|
6
|
+
this.tables = tables;
|
|
7
|
+
this.version = version;
|
|
8
|
+
const request = indexedDB.open(dbName, version);
|
|
9
|
+
request.onupgradeneeded = (ev) => {
|
|
10
|
+
this.database = ev.target.result;
|
|
11
|
+
if (!this.database) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
for (const table of tables) {
|
|
15
|
+
if (this.database.objectStoreNames.contains(table)) {
|
|
16
|
+
this.database.deleteObjectStore(table);
|
|
17
|
+
}
|
|
18
|
+
this.database.createObjectStore(table);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
request.onsuccess = (ev) => {
|
|
22
|
+
this.database = ev.target.result;
|
|
23
|
+
};
|
|
24
|
+
request.onerror = (ev) => {
|
|
25
|
+
Logger.error('Failed to open the database:', ev.target.error);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
openDatabase() {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const request = indexedDB.open(this.dbName, this.version);
|
|
31
|
+
request.onsuccess = (ev) => {
|
|
32
|
+
this.database = ev.target.result;
|
|
33
|
+
resolve(this);
|
|
34
|
+
};
|
|
35
|
+
request.onerror = (ev) => {
|
|
36
|
+
Logger.error('Failed to open the database:', ev.target.error);
|
|
37
|
+
reject(new Error('Failed to open the database:' + ev.target.error));
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
add(table, obj, key) {
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
if (!this.database) {
|
|
44
|
+
Logger.error('Database connection is not open');
|
|
45
|
+
reject(new Error('Database connection is not open'));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const transaction = this.database.transaction(table, 'readwrite');
|
|
49
|
+
const objectStore = transaction.objectStore(table);
|
|
50
|
+
const request = objectStore.put(obj, key);
|
|
51
|
+
request.onsuccess = () => {
|
|
52
|
+
resolve();
|
|
53
|
+
};
|
|
54
|
+
request.onerror = (ev) => {
|
|
55
|
+
Logger.error('Failed to add an object to the database: ', ev.target.error);
|
|
56
|
+
reject(new Error('Failed to add an object to the database: ' + ev.target.error));
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
remove(table, key) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
if (!this.database) {
|
|
63
|
+
Logger.error('Database connection is not open');
|
|
64
|
+
reject(new Error('Database connection is not open'));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const transaction = this.database.transaction(table, 'readwrite');
|
|
68
|
+
const objectStore = transaction.objectStore(table);
|
|
69
|
+
const request = objectStore.delete(key);
|
|
70
|
+
request.onsuccess = () => {
|
|
71
|
+
resolve();
|
|
72
|
+
};
|
|
73
|
+
request.onerror = (ev) => {
|
|
74
|
+
Logger.error('Failed to remove an object from the database: ', ev.target.error);
|
|
75
|
+
reject(new Error('Failed to remove an object from the database: ' + ev.target.error));
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
getByKey(table, key) {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
if (!this.database) {
|
|
82
|
+
Logger.error('Database connection is not open');
|
|
83
|
+
reject(new Error('Database connection is not open'));
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const transaction = this.database.transaction(table, 'readwrite');
|
|
87
|
+
const objectStore = transaction.objectStore(table);
|
|
88
|
+
const request = objectStore.get(key);
|
|
89
|
+
request.onsuccess = (ev) => {
|
|
90
|
+
resolve(ev.target.result);
|
|
91
|
+
};
|
|
92
|
+
request.onerror = (ev) => {
|
|
93
|
+
Logger.error('Failed to retrieve an object from the database: ', ev.target.error);
|
|
94
|
+
reject(new Error('Failed to retrieve an object from the database: ' + ev.target.error));
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
getKeys(table) {
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
if (!this.database) {
|
|
101
|
+
Logger.error('Database connection is not open');
|
|
102
|
+
reject(new Error('Database connection is not open'));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const transaction = this.database.transaction(table, 'readwrite');
|
|
106
|
+
const objectStore = transaction.objectStore(table);
|
|
107
|
+
const request = objectStore.getAllKeys();
|
|
108
|
+
request.onsuccess = (ev) => {
|
|
109
|
+
resolve(ev.target.result);
|
|
110
|
+
};
|
|
111
|
+
request.onerror = (ev) => {
|
|
112
|
+
Logger.error('Failed to retrieve an object from the database: ', ev.target.error);
|
|
113
|
+
reject(new Error('Failed to retrieve keys from the database: ' + ev.target.error));
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
get(table, query) {
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
119
|
+
if (!this.database) {
|
|
120
|
+
Logger.error('Database connection is not open');
|
|
121
|
+
reject(new Error('Database connection is not open'));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const transaction = this.database.transaction(table, 'readwrite');
|
|
125
|
+
const objectStore = transaction.objectStore(table);
|
|
126
|
+
const request = objectStore.get(query);
|
|
127
|
+
request.onsuccess = (ev) => {
|
|
128
|
+
resolve(ev.target.result);
|
|
129
|
+
};
|
|
130
|
+
request.onerror = (ev) => {
|
|
131
|
+
Logger.error('Failed to retrieve an object from the database: ', ev.target.error);
|
|
132
|
+
reject(new Error('Failed to retrieve an object from the database: ' + ev.target.error));
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
getAll(table, query) {
|
|
137
|
+
return new Promise((resolve, reject) => {
|
|
138
|
+
if (!this.database) {
|
|
139
|
+
Logger.error('Database connection is not open');
|
|
140
|
+
reject(new Error('Database connection is not open'));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const transaction = this.database.transaction(table, 'readwrite');
|
|
144
|
+
const objectStore = transaction.objectStore(table);
|
|
145
|
+
const request = objectStore.getAll(query);
|
|
146
|
+
request.onsuccess = (ev) => {
|
|
147
|
+
resolve(ev.target.result);
|
|
148
|
+
};
|
|
149
|
+
request.onerror = (ev) => {
|
|
150
|
+
Logger.error('Failed to retrieve an object from the database: ', ev.target.error);
|
|
151
|
+
reject(new Error('Failed to retrieve objects from the database: ' + ev.target.error));
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
class IndexedDbStorageProvider {
|
|
158
|
+
constructor() {
|
|
159
|
+
this.database = new DatabaseConnection("cacheStore", ["cache", "cacheEntryOptions"], 1);
|
|
160
|
+
}
|
|
161
|
+
async clear() {
|
|
162
|
+
await this.database.openDatabase();
|
|
163
|
+
let cacheEntryOptions = await this.database.getAll("cacheEntryOptions");
|
|
164
|
+
let cacheEntries = await this.database.getAll("cache");
|
|
165
|
+
for (let i = 0; i < cacheEntryOptions.length; i++) {
|
|
166
|
+
let cacheEntry = cacheEntries[i];
|
|
167
|
+
await this.remove(cacheEntry.key);
|
|
168
|
+
}
|
|
169
|
+
return this;
|
|
170
|
+
}
|
|
171
|
+
async getOptions(key) {
|
|
172
|
+
await this.database.openDatabase();
|
|
173
|
+
return this.database.getByKey("cacheEntryOptions", key);
|
|
174
|
+
}
|
|
175
|
+
async add(obj, key, options) {
|
|
176
|
+
await this.database.openDatabase();
|
|
177
|
+
await this.database.add("cache", obj, key);
|
|
178
|
+
await this.database.add("cacheEntryOptions", options, key);
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
async remove(key) {
|
|
182
|
+
await this.database.openDatabase();
|
|
183
|
+
await this.database.remove("cache", key);
|
|
184
|
+
await this.database.remove("cacheEntryOptions", key);
|
|
185
|
+
return this;
|
|
186
|
+
}
|
|
187
|
+
async get(key) {
|
|
188
|
+
await this.database.openDatabase();
|
|
189
|
+
return this.database.getByKey("cache", key);
|
|
190
|
+
}
|
|
191
|
+
async compact() {
|
|
192
|
+
await this.database.openDatabase();
|
|
193
|
+
let cacheEntryOptions = await this.database.getAll("cacheEntryOptions");
|
|
194
|
+
let cacheEntries = await this.database.getAll("cache");
|
|
195
|
+
let now = new Date().getTime();
|
|
196
|
+
for (let i = 0; i < cacheEntryOptions.length; i++) {
|
|
197
|
+
let cacheEntryOption = cacheEntryOptions[i];
|
|
198
|
+
let cacheEntry = cacheEntries[i];
|
|
199
|
+
if (cacheEntryOption.expirationTime == 0) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (cacheEntryOption.expirationTime < now) {
|
|
203
|
+
await this.remove(cacheEntry.key);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
class Cache {
|
|
210
|
+
constructor() { }
|
|
211
|
+
static configure(storageProvider = new IndexedDbStorageProvider()) {
|
|
212
|
+
this.storageProvider ??= globalThis.StorageProvider || storageProvider || new IndexedDbStorageProvider();
|
|
213
|
+
globalThis.StorageProvider = this.storageProvider;
|
|
214
|
+
}
|
|
215
|
+
static async set(key, value, entryOptions = { expirationTime: 0, slidingExpirationTime: 0, sliding: false }) {
|
|
216
|
+
Logger.debug("Setting object in cache: ", { "key": key, "value": value, "entryOptions": entryOptions });
|
|
217
|
+
this.configure();
|
|
218
|
+
await this.storageProvider.add(value, key, entryOptions);
|
|
219
|
+
}
|
|
220
|
+
static async get(key) {
|
|
221
|
+
Logger.debug("Getting object from cache: " + key);
|
|
222
|
+
this.configure();
|
|
223
|
+
await this.storageProvider.compact();
|
|
224
|
+
let returnValue = await this.storageProvider.get(key);
|
|
225
|
+
if (returnValue == null) {
|
|
226
|
+
return returnValue;
|
|
227
|
+
}
|
|
228
|
+
let entryOptions = await this.storageProvider.getOptions(key);
|
|
229
|
+
if (entryOptions.sliding) {
|
|
230
|
+
await this.set(key, returnValue, {
|
|
231
|
+
expirationTime: new Date().getTime() + entryOptions.slidingExpirationTime,
|
|
232
|
+
slidingExpirationTime: entryOptions.slidingExpirationTime,
|
|
233
|
+
sliding: true
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return returnValue;
|
|
237
|
+
}
|
|
238
|
+
static async remove(key) {
|
|
239
|
+
Logger.debug("Removing object from cache: " + key);
|
|
240
|
+
this.configure();
|
|
241
|
+
await this.storageProvider.remove(key);
|
|
242
|
+
}
|
|
243
|
+
static async clear() {
|
|
244
|
+
Logger.debug("Clearing cache");
|
|
245
|
+
this.configure();
|
|
246
|
+
await this.storageProvider.clear();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
class CancellationToken {
|
|
251
|
+
constructor() {
|
|
252
|
+
this.canceled = false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
class Request {
|
|
256
|
+
constructor(options) {
|
|
257
|
+
this.options = {
|
|
258
|
+
method: "GET",
|
|
259
|
+
url: "",
|
|
260
|
+
headers: {},
|
|
261
|
+
credentials: "same-origin",
|
|
262
|
+
serializer: JSON.stringify,
|
|
263
|
+
parser: (response) => response.json(),
|
|
264
|
+
success: (response) => { Logger.debug("Request response from " + this.options.url + ":", response); },
|
|
265
|
+
error: (reason) => { Logger.error("Request error from " + this.options.url + ":", reason); },
|
|
266
|
+
retry: (attempt) => { Logger.debug("Request retry on " + this.options.url + ":", { "attempt": attempt }); },
|
|
267
|
+
storageMode: StorageMode.NetworkFirst,
|
|
268
|
+
cacheKey: "",
|
|
269
|
+
timeout: 60000,
|
|
270
|
+
retryAttempts: 3,
|
|
271
|
+
retryDelay: 1000
|
|
272
|
+
};
|
|
273
|
+
this.abortController = null;
|
|
274
|
+
this.options = { ...this.options, ...options };
|
|
275
|
+
}
|
|
276
|
+
static get(url, data) {
|
|
277
|
+
return new Request({ method: "GET", url, data, cacheKey: url + JSON.stringify(data) })
|
|
278
|
+
.withHeaders({
|
|
279
|
+
"Accept": "application/json"
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
static post(url, data) {
|
|
283
|
+
return new Request({ method: "POST", url, data, cacheKey: url + JSON.stringify(data), storageMode: StorageMode.NetworkOnly })
|
|
284
|
+
.withHeaders({
|
|
285
|
+
"Content-Type": "application/json",
|
|
286
|
+
"Accept": "application/json"
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
static put(url, data) {
|
|
290
|
+
return new Request({ method: "PUT", url, data, cacheKey: url + JSON.stringify(data), storageMode: StorageMode.NetworkOnly })
|
|
291
|
+
.withHeaders({
|
|
292
|
+
"Content-Type": "application/json",
|
|
293
|
+
"Accept": "application/json"
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
static delete(url, data) {
|
|
297
|
+
return new Request({ method: "DELETE", url, data, cacheKey: url + JSON.stringify(data), storageMode: StorageMode.NetworkOnly })
|
|
298
|
+
.withHeaders({
|
|
299
|
+
"Accept": "application/json"
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
static ofType(method, url, data) {
|
|
303
|
+
return new Request({ method, url, data, cacheKey: url + JSON.stringify(data) })
|
|
304
|
+
.withHeaders({
|
|
305
|
+
"Accept": "application/json"
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
withAuthenticationProvider(authenticationProvider) {
|
|
309
|
+
this.options.authenticationProvider = authenticationProvider;
|
|
310
|
+
return this;
|
|
311
|
+
}
|
|
312
|
+
withHeaders(headers) {
|
|
313
|
+
this.options.headers = { ...this.options.headers, ...headers };
|
|
314
|
+
return this;
|
|
315
|
+
}
|
|
316
|
+
withCancellationToken(cancellationToken) {
|
|
317
|
+
this.options.cancellationToken = cancellationToken;
|
|
318
|
+
return this;
|
|
319
|
+
}
|
|
320
|
+
withCredentials(credentials) {
|
|
321
|
+
this.options.credentials = credentials;
|
|
322
|
+
return this;
|
|
323
|
+
}
|
|
324
|
+
withSerializer(serializer) {
|
|
325
|
+
this.options.serializer = serializer;
|
|
326
|
+
return this;
|
|
327
|
+
}
|
|
328
|
+
withParser(parser) {
|
|
329
|
+
this.options.parser = parser;
|
|
330
|
+
return this;
|
|
331
|
+
}
|
|
332
|
+
onSuccess(callback) {
|
|
333
|
+
this.options.success = callback ?? ((response) => { Logger.debug("Request response:", response); });
|
|
334
|
+
return this;
|
|
335
|
+
}
|
|
336
|
+
onError(callback) {
|
|
337
|
+
this.options.error = callback ?? ((reason) => { Logger.error("Request error:", reason); });
|
|
338
|
+
return this;
|
|
339
|
+
}
|
|
340
|
+
onRetry(callback) {
|
|
341
|
+
this.options.retry = callback ?? ((attempt) => { Logger.debug("Request retry:", { "attempt": attempt }); });
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
withStorageMode(storageMode) {
|
|
345
|
+
this.options.storageMode = storageMode;
|
|
346
|
+
return this;
|
|
347
|
+
}
|
|
348
|
+
withCacheKey(cacheKey) {
|
|
349
|
+
this.options.cacheKey = cacheKey;
|
|
350
|
+
return this;
|
|
351
|
+
}
|
|
352
|
+
withTimeout(timeout) {
|
|
353
|
+
this.options.timeout = timeout ?? 60000;
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
withRetryAttempts(retryAttempts) {
|
|
357
|
+
this.options.retryAttempts = retryAttempts;
|
|
358
|
+
return this;
|
|
359
|
+
}
|
|
360
|
+
withRetryDelay(retryDelay) {
|
|
361
|
+
this.options.retryDelay = retryDelay;
|
|
362
|
+
return this;
|
|
363
|
+
}
|
|
364
|
+
abort() {
|
|
365
|
+
if (this.abortController == null || this.options.error == null) {
|
|
366
|
+
return this;
|
|
367
|
+
}
|
|
368
|
+
this.abortController.abort();
|
|
369
|
+
this.options.error(new Error("The request was aborted."));
|
|
370
|
+
return this;
|
|
371
|
+
}
|
|
372
|
+
async send() {
|
|
373
|
+
const { authenticationProvider, method, url, data, headers, credentials, serializer, parser, success, error, storageMode, cacheKey, timeout, retryAttempts, retryDelay, retry, cancellationToken } = this.options;
|
|
374
|
+
const abortController = new AbortController();
|
|
375
|
+
this.abortController = abortController;
|
|
376
|
+
let attempts = 0;
|
|
377
|
+
let lastError = null;
|
|
378
|
+
let successMethod = success || ((response) => { Logger.debug("Request response from " + url + ":", response); });
|
|
379
|
+
let errorMethod = error || ((reason) => { Logger.error("Request error from " + url + ":", reason); });
|
|
380
|
+
let serializerMethod = serializer || JSON.stringify;
|
|
381
|
+
let parserMethod = parser || ((response) => response.json());
|
|
382
|
+
let retryMethod = retry || ((attempt) => { Logger.debug("Request retry on " + url + ":", { "attempt": attempt }); });
|
|
383
|
+
const sendRequest = async () => {
|
|
384
|
+
if (storageMode === StorageMode.StorageFirst || storageMode === StorageMode.StorageAndUpdate) {
|
|
385
|
+
const cachedValue = await Cache.get(cacheKey || "");
|
|
386
|
+
if (cachedValue !== undefined) {
|
|
387
|
+
successMethod(cachedValue);
|
|
388
|
+
if (storageMode === StorageMode.StorageFirst) {
|
|
389
|
+
return cachedValue;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
if (!navigator.onLine) {
|
|
394
|
+
if (storageMode === StorageMode.NetworkFirst) {
|
|
395
|
+
const cachedValue = await Cache.get(cacheKey || "");
|
|
396
|
+
if (cachedValue !== undefined) {
|
|
397
|
+
successMethod(cachedValue);
|
|
398
|
+
return cachedValue;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const errorMessage = new Error("System is offline");
|
|
402
|
+
errorMethod(errorMessage);
|
|
403
|
+
return Promise.reject(errorMessage);
|
|
404
|
+
}
|
|
405
|
+
try {
|
|
406
|
+
const serializedData = serializerMethod(data);
|
|
407
|
+
await authenticationProvider?.authenticate(this);
|
|
408
|
+
const response = await Promise.race([
|
|
409
|
+
fetch(url, {
|
|
410
|
+
method,
|
|
411
|
+
credentials,
|
|
412
|
+
headers,
|
|
413
|
+
body: serializedData,
|
|
414
|
+
signal: abortController.signal,
|
|
415
|
+
}),
|
|
416
|
+
this.handleTimeout(timeout)
|
|
417
|
+
]);
|
|
418
|
+
if (cancellationToken?.canceled) {
|
|
419
|
+
return Promise.reject(new Error("The request was canceled."));
|
|
420
|
+
}
|
|
421
|
+
if (response.status >= 200 && response.status < 300) {
|
|
422
|
+
const parsedResponse = await parserMethod(response);
|
|
423
|
+
successMethod(parsedResponse);
|
|
424
|
+
if (storageMode !== StorageMode.NetworkOnly) {
|
|
425
|
+
await Cache.set(cacheKey || "", parsedResponse);
|
|
426
|
+
}
|
|
427
|
+
return parsedResponse;
|
|
428
|
+
}
|
|
429
|
+
lastError = new Error(response.statusText);
|
|
430
|
+
if (response.status === 401) {
|
|
431
|
+
await authenticationProvider?.authenticationFailed(this, response);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
catch (err) {
|
|
435
|
+
lastError = err;
|
|
436
|
+
}
|
|
437
|
+
if (attempts < (retryAttempts || 0)) {
|
|
438
|
+
++attempts;
|
|
439
|
+
await new Promise(resolve => setTimeout(resolve, retryDelay));
|
|
440
|
+
retryMethod(attempts);
|
|
441
|
+
return sendRequest();
|
|
442
|
+
}
|
|
443
|
+
errorMethod(lastError);
|
|
444
|
+
return Promise.reject(lastError);
|
|
445
|
+
};
|
|
446
|
+
return sendRequest();
|
|
447
|
+
}
|
|
448
|
+
async handleTimeout(timeout) {
|
|
449
|
+
timeout ??= 60000;
|
|
450
|
+
await new Promise((_, reject) => {
|
|
451
|
+
setTimeout(() => {
|
|
452
|
+
reject(new Error('Request timeout'));
|
|
453
|
+
}, timeout);
|
|
454
|
+
});
|
|
455
|
+
throw new Error('Request timeout');
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
var StorageMode;
|
|
459
|
+
(function (StorageMode) {
|
|
460
|
+
StorageMode[StorageMode["NetworkFirst"] = 0] = "NetworkFirst";
|
|
461
|
+
StorageMode[StorageMode["StorageFirst"] = 1] = "StorageFirst";
|
|
462
|
+
StorageMode[StorageMode["NetworkOnly"] = 2] = "NetworkOnly";
|
|
463
|
+
StorageMode[StorageMode["StorageAndUpdate"] = 3] = "StorageAndUpdate";
|
|
464
|
+
})(StorageMode || (StorageMode = {}));
|
|
465
|
+
|
|
466
|
+
export { Cache, CancellationToken, IndexedDbStorageProvider, Request, StorageMode };
|