@ember-data-mirror/request 5.4.0-alpha.64 → 5.4.0-alpha.70
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/addon-main.cjs +5 -0
- package/{addon/context-DMaVGooY.js → dist/debug-CS6nHZzv.js} +254 -268
- package/dist/debug-CS6nHZzv.js.map +1 -0
- package/{addon → dist}/fetch.js +3 -3
- package/dist/fetch.js.map +1 -0
- package/dist/index.js +673 -0
- package/{addon → dist}/index.js.map +1 -1
- package/package.json +27 -39
- package/unstable-preview-types/-private/debug.d.ts +1 -1
- package/unstable-preview-types/-private/debug.d.ts.map +1 -1
- package/unstable-preview-types/-private/manager.d.ts +1 -1
- package/unstable-preview-types/-private/manager.d.ts.map +1 -1
- package/unstable-preview-types/-private/promise-cache.d.ts.map +1 -1
- package/unstable-preview-types/-private/utils.d.ts +1 -1
- package/unstable-preview-types/-private/utils.d.ts.map +1 -1
- package/unstable-preview-types/index.d.ts +4 -4
- package/addon/context-DMaVGooY.js.map +0 -1
- package/addon/fetch.js.map +0 -1
- package/addon/index.js +0 -240
- package/addon-main.js +0 -94
package/addon-main.cjs
ADDED
|
@@ -1,250 +1,8 @@
|
|
|
1
|
+
import { getOrSetUniversal, getOrSetGlobal } from '@warp-drive-mirror/core-types/-private';
|
|
1
2
|
import { STRUCTURED, IS_FUTURE, SkipCache } from '@warp-drive-mirror/core-types/request';
|
|
2
|
-
import { macroCondition,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
throw new TypeError("attempted to use private field on non-instance");
|
|
6
|
-
}
|
|
7
|
-
return receiver;
|
|
8
|
-
}
|
|
9
|
-
var id = 0;
|
|
10
|
-
function _classPrivateFieldKey(name) {
|
|
11
|
-
return "__private_" + id++ + "_" + name;
|
|
12
|
-
}
|
|
13
|
-
const BODY_TYPES = {
|
|
14
|
-
type: 'string',
|
|
15
|
-
klass: ['Blob', 'ArrayBuffer', 'TypedArray', 'DataView', 'FormData', 'URLSearchParams', 'ReadableStream']
|
|
16
|
-
};
|
|
17
|
-
const ValidKeys = new Map([['records', 'array'], ['data', 'json'], ['body', BODY_TYPES], ['disableTestWaiter', 'boolean'], ['options', 'object'], ['cacheOptions', 'object'], ['op', 'string'], ['store', 'object'], ['url', 'string'], ['cache', ['default', 'force-cache', 'no-cache', 'no-store', 'only-if-cached', 'reload']], ['credentials', ['include', 'omit', 'same-origin']], ['destination', ['', 'object', 'audio', 'audioworklet', 'document', 'embed', 'font', 'frame', 'iframe', 'image', 'manifest', 'paintworklet', 'report', 'script', 'sharedworker', 'style', 'track', 'video', 'worker', 'xslt']], ['headers', 'headers'], ['integrity', 'string'], ['keepalive', 'boolean'], ['method', ['GET', 'PUT', 'PATCH', 'DELETE', 'POST', 'OPTIONS']], ['mode', ['same-origin', 'cors', 'navigate', 'no-cors']], ['redirect', ['error', 'follow', 'manual']], ['referrer', 'string'], ['signal', 'AbortSignal'], ['controller', 'AbortController'], ['referrerPolicy', ['', 'same-origin', 'no-referrer', 'no-referrer-when-downgrade', 'origin', 'origin-when-cross-origin', 'strict-origin', 'strict-origin-when-cross-origin', 'unsafe-url']]]);
|
|
18
|
-
const IS_FROZEN = Symbol('FROZEN');
|
|
19
|
-
const IS_COLLECTION = Symbol.for('Collection');
|
|
20
|
-
function freezeHeaders(headers) {
|
|
21
|
-
headers.delete = headers.set = headers.append = () => {
|
|
22
|
-
throw new Error(`Cannot Mutate Immutatable Headers, use headers.clone to get a copy`);
|
|
23
|
-
};
|
|
24
|
-
upgradeHeaders(headers);
|
|
25
|
-
return headers;
|
|
26
|
-
}
|
|
27
|
-
function deepFreeze(value) {
|
|
28
|
-
if (value && value[IS_FROZEN]) {
|
|
29
|
-
return value;
|
|
30
|
-
}
|
|
31
|
-
const _type = typeof value;
|
|
32
|
-
switch (_type) {
|
|
33
|
-
case 'boolean':
|
|
34
|
-
case 'string':
|
|
35
|
-
case 'number':
|
|
36
|
-
case 'symbol':
|
|
37
|
-
case 'undefined':
|
|
38
|
-
case 'bigint':
|
|
39
|
-
return value;
|
|
40
|
-
case 'function':
|
|
41
|
-
throw new Error(`Cannot deep-freeze a function`);
|
|
42
|
-
case 'object':
|
|
43
|
-
{
|
|
44
|
-
const _niceType = niceTypeOf(value);
|
|
45
|
-
switch (_niceType) {
|
|
46
|
-
case 'array':
|
|
47
|
-
{
|
|
48
|
-
if (value[IS_COLLECTION]) {
|
|
49
|
-
return value;
|
|
50
|
-
}
|
|
51
|
-
const arr = value.map(deepFreeze);
|
|
52
|
-
arr[IS_FROZEN] = true;
|
|
53
|
-
return Object.freeze(arr);
|
|
54
|
-
}
|
|
55
|
-
case 'null':
|
|
56
|
-
return value;
|
|
57
|
-
case 'object':
|
|
58
|
-
Object.keys(value).forEach(key => {
|
|
59
|
-
try {
|
|
60
|
-
value[key] = deepFreeze(value[key]);
|
|
61
|
-
} catch {
|
|
62
|
-
// continue
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
value[IS_FROZEN] = true;
|
|
66
|
-
return Object.freeze(value);
|
|
67
|
-
case 'headers':
|
|
68
|
-
return freezeHeaders(value);
|
|
69
|
-
case 'Collection':
|
|
70
|
-
case 'Store':
|
|
71
|
-
case 'AbortSignal':
|
|
72
|
-
return value;
|
|
73
|
-
case 'date':
|
|
74
|
-
case 'map':
|
|
75
|
-
case 'set':
|
|
76
|
-
case 'error':
|
|
77
|
-
case 'stream':
|
|
78
|
-
default:
|
|
79
|
-
// eslint-disable-next-line no-console
|
|
80
|
-
// console.log(`Cannot deep-freeze ${_niceType}`);
|
|
81
|
-
return value;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
function isMaybeContext(request) {
|
|
87
|
-
if (request && typeof request === 'object') {
|
|
88
|
-
const keys = Object.keys(request);
|
|
89
|
-
if (keys.length === 1 && keys[0] === 'request') {
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return false;
|
|
94
|
-
}
|
|
95
|
-
function niceTypeOf(v) {
|
|
96
|
-
if (v === null) {
|
|
97
|
-
return 'null';
|
|
98
|
-
}
|
|
99
|
-
if (typeof v === 'string') {
|
|
100
|
-
return v ? 'non-empty-string' : 'empty-string';
|
|
101
|
-
}
|
|
102
|
-
if (!v) {
|
|
103
|
-
return typeof v;
|
|
104
|
-
}
|
|
105
|
-
if (Array.isArray(v)) {
|
|
106
|
-
return 'array';
|
|
107
|
-
}
|
|
108
|
-
if (v instanceof Date) {
|
|
109
|
-
return 'date';
|
|
110
|
-
}
|
|
111
|
-
if (v instanceof Map) {
|
|
112
|
-
return 'map';
|
|
113
|
-
}
|
|
114
|
-
if (v instanceof Set) {
|
|
115
|
-
return 'set';
|
|
116
|
-
}
|
|
117
|
-
if (v instanceof Error) {
|
|
118
|
-
return 'error';
|
|
119
|
-
}
|
|
120
|
-
if (v instanceof ReadableStream || v instanceof WritableStream || v instanceof TransformStream) {
|
|
121
|
-
return 'stream';
|
|
122
|
-
}
|
|
123
|
-
if (v instanceof Headers) {
|
|
124
|
-
return 'headers';
|
|
125
|
-
}
|
|
126
|
-
if (typeof v === 'object' && v.constructor && v.constructor.name !== 'Object') {
|
|
127
|
-
return v.constructor.name;
|
|
128
|
-
}
|
|
129
|
-
return typeof v;
|
|
130
|
-
}
|
|
131
|
-
function validateKey(key, value, errors) {
|
|
132
|
-
const schema = ValidKeys.get(key);
|
|
133
|
-
if (!schema && !IgnoredKeys.has(key)) {
|
|
134
|
-
errors.push(`InvalidKey: '${key}'`);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
if (schema) {
|
|
138
|
-
if (schema === BODY_TYPES) {
|
|
139
|
-
if (typeof value === 'string' || value instanceof ReadableStream) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
let type = niceTypeOf(value);
|
|
143
|
-
if (schema.klass.includes(type)) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
errors.push(`InvalidValue: key 'body' should be a string or one of '${schema.klass.join("', '")}', received ${'<a value of type ' + niceTypeOf(value) + '>'}`);
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
if (Array.isArray(schema)) {
|
|
150
|
-
if (!schema.includes(value)) {
|
|
151
|
-
errors.push(`InvalidValue: key ${key} should be a one of '${schema.join("', '")}', received ${typeof value === 'string' ? value : '<a value of type ' + niceTypeOf(value) + '>'}`);
|
|
152
|
-
}
|
|
153
|
-
return;
|
|
154
|
-
} else if (schema === 'json') {
|
|
155
|
-
try {
|
|
156
|
-
JSON.stringify(value);
|
|
157
|
-
} catch (e) {
|
|
158
|
-
errors.push(`InvalidValue: key ${key} should be a JSON serializable value, but failed to serialize with Error - ${e.message}`);
|
|
159
|
-
}
|
|
160
|
-
return;
|
|
161
|
-
} else if (schema === 'headers') {
|
|
162
|
-
if (!(value instanceof Headers)) {
|
|
163
|
-
errors.push(`InvalidValue: key ${key} should be an instance of Headers, received ${niceTypeOf(value)}`);
|
|
164
|
-
}
|
|
165
|
-
return;
|
|
166
|
-
} else if (schema === 'record') {
|
|
167
|
-
const _type = typeof value;
|
|
168
|
-
// record must extend plain object or Object.create(null)
|
|
169
|
-
if (!value || _type !== 'object' || value.constructor && value.constructor !== Object) {
|
|
170
|
-
errors.push(`InvalidValue: key ${key} should be a dictionary of string keys to string values, received ${niceTypeOf(value)}`);
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
const keys = Object.keys(value);
|
|
174
|
-
keys.forEach(k => {
|
|
175
|
-
let v = value[k];
|
|
176
|
-
if (typeof k !== 'string') {
|
|
177
|
-
errors.push(`\tThe key ${String(k)} on ${key} should be a string key`);
|
|
178
|
-
} else if (typeof v !== 'string') {
|
|
179
|
-
errors.push(`\tThe value of ${key}.${k} should be a string not ${niceTypeOf(v)}`);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
return;
|
|
183
|
-
} else if (schema === 'string') {
|
|
184
|
-
if (typeof value !== 'string' || value.length === 0) {
|
|
185
|
-
errors.push(`InvalidValue: key ${key} should be a non-empty string, received ${typeof value === 'string' ? "''" : typeof value}`);
|
|
186
|
-
}
|
|
187
|
-
return;
|
|
188
|
-
} else if (schema === 'object') {
|
|
189
|
-
if (!value || Array.isArray(value) || typeof value !== 'object') {
|
|
190
|
-
errors.push(`InvalidValue: key ${key} should be an object`);
|
|
191
|
-
}
|
|
192
|
-
return;
|
|
193
|
-
} else if (schema === 'boolean') {
|
|
194
|
-
if (typeof value !== 'boolean') {
|
|
195
|
-
errors.push(`InvalidValue: key ${key} should be a boolean, received ${typeof value}`);
|
|
196
|
-
}
|
|
197
|
-
return;
|
|
198
|
-
} else if (schema === 'array') {
|
|
199
|
-
if (!Array.isArray(value)) {
|
|
200
|
-
errors.push(`InvalidValue: key ${key} should be an array, received ${typeof value}`);
|
|
201
|
-
}
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
const IgnoredKeys = new Set([]);
|
|
207
|
-
function assertValidRequest(request, isTopLevel) {
|
|
208
|
-
if (macroCondition(getOwnConfig().env.DEBUG)) {
|
|
209
|
-
// handle basic shape
|
|
210
|
-
if (!request) {
|
|
211
|
-
throw new Error(`Expected ${isTopLevel ? 'RequestManager.request' : 'next'}(<request>) to be called with a request, but none was provided.`);
|
|
212
|
-
}
|
|
213
|
-
if (Array.isArray(request) || typeof request !== 'object') {
|
|
214
|
-
throw new Error(`The \`request\` passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` should be an object, received \`${niceTypeOf(request)}\``);
|
|
215
|
-
}
|
|
216
|
-
if (Object.keys(request).length === 0) {
|
|
217
|
-
throw new Error(`The \`request\` passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` was empty (\`{}\`). Requests need at least one valid key.`);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// handle accidentally passing context entirely
|
|
221
|
-
if (request instanceof Context) {
|
|
222
|
-
throw new Error(`Expected a request passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` but received the previous handler's context instead`);
|
|
223
|
-
}
|
|
224
|
-
// handle Object.assign({}, context);
|
|
225
|
-
if (isMaybeContext(request)) {
|
|
226
|
-
throw new Error(`Expected a request passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` but received an object with a request key instead.`);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// handle schema
|
|
230
|
-
const keys = Object.keys(request);
|
|
231
|
-
const validationErrors = [];
|
|
232
|
-
const isLegacyRequest = Boolean('op' in request && !request.url);
|
|
233
|
-
keys.forEach(key => {
|
|
234
|
-
if (isLegacyRequest && key === 'data') {
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
validateKey(key, request[key], validationErrors);
|
|
238
|
-
});
|
|
239
|
-
if (validationErrors.length) {
|
|
240
|
-
const error = new Error(`Invalid Request passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\`.\n\nThe following issues were found:\n\n\t${validationErrors.join('\n\t')}`);
|
|
241
|
-
error.errors = validationErrors;
|
|
242
|
-
throw error;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
const PromiseCache = new WeakMap();
|
|
247
|
-
const RequestMap = new Map();
|
|
3
|
+
import { macroCondition, getGlobalConfig } from '@embroider/macros';
|
|
4
|
+
const PromiseCache = getOrSetUniversal('PromiseCache', new WeakMap());
|
|
5
|
+
const RequestMap = getOrSetUniversal('RequestMap', new Map());
|
|
248
6
|
function setRequestResult(requestId, result) {
|
|
249
7
|
RequestMap.set(requestId, result);
|
|
250
8
|
}
|
|
@@ -260,7 +18,7 @@ function setPromiseResult(promise, result) {
|
|
|
260
18
|
function getPromiseResult(promise) {
|
|
261
19
|
return PromiseCache.get(promise);
|
|
262
20
|
}
|
|
263
|
-
const IS_CACHE_HANDLER = Symbol('IS_CACHE_HANDLER');
|
|
21
|
+
const IS_CACHE_HANDLER = getOrSetGlobal('IS_CACHE_HANDLER', Symbol('IS_CACHE_HANDLER'));
|
|
264
22
|
function curryFuture(owner, inbound, outbound) {
|
|
265
23
|
owner.setStream(inbound.getStream());
|
|
266
24
|
inbound.then(doc => {
|
|
@@ -345,7 +103,7 @@ function isCacheHandler(handler, index) {
|
|
|
345
103
|
return index === 0 && Boolean(handler[IS_CACHE_HANDLER]);
|
|
346
104
|
}
|
|
347
105
|
function executeNextHandler(wares, request, i, god) {
|
|
348
|
-
if (macroCondition(
|
|
106
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
349
107
|
if (i === wares.length) {
|
|
350
108
|
throw new Error(`No handler was able to handle this request.`);
|
|
351
109
|
}
|
|
@@ -368,7 +126,7 @@ function executeNextHandler(wares, request, i, god) {
|
|
|
368
126
|
});
|
|
369
127
|
outcome = Promise.resolve(outcome);
|
|
370
128
|
}
|
|
371
|
-
} else if (macroCondition(
|
|
129
|
+
} else if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
372
130
|
if (!outcome || !(outcome instanceof Promise) && !(typeof outcome === 'object' && 'then' in outcome)) {
|
|
373
131
|
// eslint-disable-next-line no-console
|
|
374
132
|
console.log({
|
|
@@ -480,13 +238,13 @@ function cloneResponseProperties(response) {
|
|
|
480
238
|
};
|
|
481
239
|
}
|
|
482
240
|
class ContextOwner {
|
|
241
|
+
hasSetStream = false;
|
|
242
|
+
hasSetResponse = false;
|
|
243
|
+
hasSubscribers = false;
|
|
244
|
+
stream = createDeferred();
|
|
245
|
+
response = null;
|
|
246
|
+
nextCalled = 0;
|
|
483
247
|
constructor(request, god, isRoot = false) {
|
|
484
|
-
this.hasSetStream = false;
|
|
485
|
-
this.hasSetResponse = false;
|
|
486
|
-
this.hasSubscribers = false;
|
|
487
|
-
this.stream = createDeferred();
|
|
488
|
-
this.response = null;
|
|
489
|
-
this.nextCalled = 0;
|
|
490
248
|
this.isRoot = isRoot;
|
|
491
249
|
this.requestId = god.id;
|
|
492
250
|
this.controller = request.controller || god.controller;
|
|
@@ -502,7 +260,7 @@ class ContextOwner {
|
|
|
502
260
|
let enhancedRequest = Object.assign({
|
|
503
261
|
signal: this.controller.signal
|
|
504
262
|
}, request);
|
|
505
|
-
if (macroCondition(
|
|
263
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
506
264
|
if (!request?.cacheOptions?.[SkipCache]) {
|
|
507
265
|
request = deepFreeze(request);
|
|
508
266
|
enhancedRequest = deepFreeze(enhancedRequest);
|
|
@@ -563,7 +321,7 @@ class ContextOwner {
|
|
|
563
321
|
}
|
|
564
322
|
setResponse(response) {
|
|
565
323
|
if (this.hasSetResponse) {
|
|
566
|
-
if (macroCondition(
|
|
324
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
567
325
|
throw new Error(`Cannot setResponse when a response has already been set`);
|
|
568
326
|
}
|
|
569
327
|
return;
|
|
@@ -572,7 +330,7 @@ class ContextOwner {
|
|
|
572
330
|
if (response instanceof Response) {
|
|
573
331
|
// TODO potentially avoid cloning in prod
|
|
574
332
|
let responseData = cloneResponseProperties(response);
|
|
575
|
-
if (macroCondition(
|
|
333
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
576
334
|
responseData = deepFreeze(responseData);
|
|
577
335
|
}
|
|
578
336
|
this.response = responseData;
|
|
@@ -585,25 +343,253 @@ class ContextOwner {
|
|
|
585
343
|
}
|
|
586
344
|
}
|
|
587
345
|
}
|
|
588
|
-
var _owner = /*#__PURE__*/_classPrivateFieldKey("owner");
|
|
589
346
|
class Context {
|
|
347
|
+
#owner;
|
|
590
348
|
constructor(owner) {
|
|
591
|
-
Object.defineProperty(this, _owner, {
|
|
592
|
-
writable: true,
|
|
593
|
-
value: void 0
|
|
594
|
-
});
|
|
595
349
|
this.id = owner.requestId;
|
|
596
|
-
|
|
350
|
+
this.#owner = owner;
|
|
597
351
|
this.request = owner.enhancedRequest;
|
|
598
352
|
}
|
|
599
353
|
setStream(stream) {
|
|
600
|
-
|
|
354
|
+
this.#owner.setStream(stream);
|
|
601
355
|
}
|
|
602
356
|
setResponse(response) {
|
|
603
|
-
|
|
357
|
+
this.#owner.setResponse(response);
|
|
604
358
|
}
|
|
605
359
|
get hasRequestedStream() {
|
|
606
|
-
return
|
|
360
|
+
return this.#owner.hasRequestedStream;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const BODY_TYPES = {
|
|
364
|
+
type: 'string',
|
|
365
|
+
klass: ['Blob', 'ArrayBuffer', 'TypedArray', 'DataView', 'FormData', 'URLSearchParams', 'ReadableStream']
|
|
366
|
+
};
|
|
367
|
+
const ValidKeys = new Map([['records', 'array'], ['data', 'json'], ['body', BODY_TYPES], ['disableTestWaiter', 'boolean'], ['options', 'object'], ['cacheOptions', 'object'], ['op', 'string'], ['store', 'object'], ['url', 'string'], ['cache', ['default', 'force-cache', 'no-cache', 'no-store', 'only-if-cached', 'reload']], ['credentials', ['include', 'omit', 'same-origin']], ['destination', ['', 'object', 'audio', 'audioworklet', 'document', 'embed', 'font', 'frame', 'iframe', 'image', 'manifest', 'paintworklet', 'report', 'script', 'sharedworker', 'style', 'track', 'video', 'worker', 'xslt']], ['headers', 'headers'], ['integrity', 'string'], ['keepalive', 'boolean'], ['method', ['GET', 'PUT', 'PATCH', 'DELETE', 'POST', 'OPTIONS']], ['mode', ['same-origin', 'cors', 'navigate', 'no-cors']], ['redirect', ['error', 'follow', 'manual']], ['referrer', 'string'], ['signal', 'AbortSignal'], ['controller', 'AbortController'], ['referrerPolicy', ['', 'same-origin', 'no-referrer', 'no-referrer-when-downgrade', 'origin', 'origin-when-cross-origin', 'strict-origin', 'strict-origin-when-cross-origin', 'unsafe-url']]]);
|
|
368
|
+
const IS_FROZEN = getOrSetGlobal('IS_FROZEN', Symbol('FROZEN'));
|
|
369
|
+
const IS_COLLECTION = getOrSetGlobal('IS_COLLECTION', Symbol.for('Collection'));
|
|
370
|
+
function freezeHeaders(headers) {
|
|
371
|
+
headers.delete = headers.set = headers.append = () => {
|
|
372
|
+
throw new Error(`Cannot Mutate Immutatable Headers, use headers.clone to get a copy`);
|
|
373
|
+
};
|
|
374
|
+
upgradeHeaders(headers);
|
|
375
|
+
return headers;
|
|
376
|
+
}
|
|
377
|
+
function deepFreeze(value) {
|
|
378
|
+
if (value && value[IS_FROZEN]) {
|
|
379
|
+
return value;
|
|
380
|
+
}
|
|
381
|
+
const _type = typeof value;
|
|
382
|
+
switch (_type) {
|
|
383
|
+
case 'boolean':
|
|
384
|
+
case 'string':
|
|
385
|
+
case 'number':
|
|
386
|
+
case 'symbol':
|
|
387
|
+
case 'undefined':
|
|
388
|
+
case 'bigint':
|
|
389
|
+
return value;
|
|
390
|
+
case 'function':
|
|
391
|
+
throw new Error(`Cannot deep-freeze a function`);
|
|
392
|
+
case 'object':
|
|
393
|
+
{
|
|
394
|
+
const _niceType = niceTypeOf(value);
|
|
395
|
+
switch (_niceType) {
|
|
396
|
+
case 'array':
|
|
397
|
+
{
|
|
398
|
+
if (value[IS_COLLECTION]) {
|
|
399
|
+
return value;
|
|
400
|
+
}
|
|
401
|
+
const arr = value.map(deepFreeze);
|
|
402
|
+
arr[IS_FROZEN] = true;
|
|
403
|
+
return Object.freeze(arr);
|
|
404
|
+
}
|
|
405
|
+
case 'null':
|
|
406
|
+
return value;
|
|
407
|
+
case 'object':
|
|
408
|
+
Object.keys(value).forEach(key => {
|
|
409
|
+
try {
|
|
410
|
+
value[key] = deepFreeze(value[key]);
|
|
411
|
+
} catch {
|
|
412
|
+
// continue
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
value[IS_FROZEN] = true;
|
|
416
|
+
return Object.freeze(value);
|
|
417
|
+
case 'headers':
|
|
418
|
+
return freezeHeaders(value);
|
|
419
|
+
case 'Collection':
|
|
420
|
+
case 'Store':
|
|
421
|
+
case 'AbortSignal':
|
|
422
|
+
return value;
|
|
423
|
+
case 'date':
|
|
424
|
+
case 'map':
|
|
425
|
+
case 'set':
|
|
426
|
+
case 'error':
|
|
427
|
+
case 'stream':
|
|
428
|
+
default:
|
|
429
|
+
// console.log(`Cannot deep-freeze ${_niceType}`);
|
|
430
|
+
return value;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
function isMaybeContext(request) {
|
|
436
|
+
if (request && typeof request === 'object') {
|
|
437
|
+
const keys = Object.keys(request);
|
|
438
|
+
if (keys.length === 1 && keys[0] === 'request') {
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
function niceTypeOf(v) {
|
|
445
|
+
if (v === null) {
|
|
446
|
+
return 'null';
|
|
447
|
+
}
|
|
448
|
+
if (typeof v === 'string') {
|
|
449
|
+
return v ? 'non-empty-string' : 'empty-string';
|
|
450
|
+
}
|
|
451
|
+
if (!v) {
|
|
452
|
+
return typeof v;
|
|
453
|
+
}
|
|
454
|
+
if (Array.isArray(v)) {
|
|
455
|
+
return 'array';
|
|
456
|
+
}
|
|
457
|
+
if (v instanceof Date) {
|
|
458
|
+
return 'date';
|
|
459
|
+
}
|
|
460
|
+
if (v instanceof Map) {
|
|
461
|
+
return 'map';
|
|
462
|
+
}
|
|
463
|
+
if (v instanceof Set) {
|
|
464
|
+
return 'set';
|
|
465
|
+
}
|
|
466
|
+
if (v instanceof Error) {
|
|
467
|
+
return 'error';
|
|
468
|
+
}
|
|
469
|
+
if (v instanceof ReadableStream || v instanceof WritableStream || v instanceof TransformStream) {
|
|
470
|
+
return 'stream';
|
|
471
|
+
}
|
|
472
|
+
if (v instanceof Headers) {
|
|
473
|
+
return 'headers';
|
|
474
|
+
}
|
|
475
|
+
if (typeof v === 'object' && v.constructor && v.constructor.name !== 'Object') {
|
|
476
|
+
return v.constructor.name;
|
|
477
|
+
}
|
|
478
|
+
return typeof v;
|
|
479
|
+
}
|
|
480
|
+
function validateKey(key, value, errors) {
|
|
481
|
+
const schema = ValidKeys.get(key);
|
|
482
|
+
if (!schema && !IgnoredKeys.has(key)) {
|
|
483
|
+
errors.push(`InvalidKey: '${key}'`);
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (schema) {
|
|
487
|
+
if (schema === BODY_TYPES) {
|
|
488
|
+
if (typeof value === 'string' || value instanceof ReadableStream) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const type = niceTypeOf(value);
|
|
492
|
+
if (schema.klass.includes(type)) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
errors.push(`InvalidValue: key 'body' should be a string or one of '${schema.klass.join("', '")}', received ${'<a value of type ' + niceTypeOf(value) + '>'}`);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (Array.isArray(schema)) {
|
|
499
|
+
if (!schema.includes(value)) {
|
|
500
|
+
errors.push(`InvalidValue: key ${key} should be a one of '${schema.join("', '")}', received ${typeof value === 'string' ? value : '<a value of type ' + niceTypeOf(value) + '>'}`);
|
|
501
|
+
}
|
|
502
|
+
return;
|
|
503
|
+
} else if (schema === 'json') {
|
|
504
|
+
try {
|
|
505
|
+
JSON.stringify(value);
|
|
506
|
+
} catch (e) {
|
|
507
|
+
errors.push(`InvalidValue: key ${key} should be a JSON serializable value, but failed to serialize with Error - ${e.message}`);
|
|
508
|
+
}
|
|
509
|
+
return;
|
|
510
|
+
} else if (schema === 'headers') {
|
|
511
|
+
if (!(value instanceof Headers)) {
|
|
512
|
+
errors.push(`InvalidValue: key ${key} should be an instance of Headers, received ${niceTypeOf(value)}`);
|
|
513
|
+
}
|
|
514
|
+
return;
|
|
515
|
+
} else if (schema === 'record') {
|
|
516
|
+
const _type = typeof value;
|
|
517
|
+
// record must extend plain object or Object.create(null)
|
|
518
|
+
if (!value || _type !== 'object' || value.constructor && value.constructor !== Object) {
|
|
519
|
+
errors.push(`InvalidValue: key ${key} should be a dictionary of string keys to string values, received ${niceTypeOf(value)}`);
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const keys = Object.keys(value);
|
|
523
|
+
keys.forEach(k => {
|
|
524
|
+
const v = value[k];
|
|
525
|
+
if (typeof k !== 'string') {
|
|
526
|
+
errors.push(`\tThe key ${String(k)} on ${key} should be a string key`);
|
|
527
|
+
} else if (typeof v !== 'string') {
|
|
528
|
+
errors.push(`\tThe value of ${key}.${k} should be a string not ${niceTypeOf(v)}`);
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
return;
|
|
532
|
+
} else if (schema === 'string') {
|
|
533
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
534
|
+
errors.push(`InvalidValue: key ${key} should be a non-empty string, received ${typeof value === 'string' ? "''" : typeof value}`);
|
|
535
|
+
}
|
|
536
|
+
return;
|
|
537
|
+
} else if (schema === 'object') {
|
|
538
|
+
if (!value || Array.isArray(value) || typeof value !== 'object') {
|
|
539
|
+
errors.push(`InvalidValue: key ${key} should be an object`);
|
|
540
|
+
}
|
|
541
|
+
return;
|
|
542
|
+
} else if (schema === 'boolean') {
|
|
543
|
+
if (typeof value !== 'boolean') {
|
|
544
|
+
errors.push(`InvalidValue: key ${key} should be a boolean, received ${typeof value}`);
|
|
545
|
+
}
|
|
546
|
+
return;
|
|
547
|
+
} else if (schema === 'array') {
|
|
548
|
+
if (!Array.isArray(value)) {
|
|
549
|
+
errors.push(`InvalidValue: key ${key} should be an array, received ${typeof value}`);
|
|
550
|
+
}
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
const IgnoredKeys = new Set([]);
|
|
556
|
+
function assertValidRequest(request, isTopLevel) {
|
|
557
|
+
if (macroCondition(getGlobalConfig().WarpDrive.env.DEBUG)) {
|
|
558
|
+
// handle basic shape
|
|
559
|
+
if (!request) {
|
|
560
|
+
throw new Error(`Expected ${isTopLevel ? 'RequestManager.request' : 'next'}(<request>) to be called with a request, but none was provided.`);
|
|
561
|
+
}
|
|
562
|
+
if (Array.isArray(request) || typeof request !== 'object') {
|
|
563
|
+
throw new Error(`The \`request\` passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` should be an object, received \`${niceTypeOf(request)}\``);
|
|
564
|
+
}
|
|
565
|
+
if (Object.keys(request).length === 0) {
|
|
566
|
+
throw new Error(`The \`request\` passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` was empty (\`{}\`). Requests need at least one valid key.`);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// handle accidentally passing context entirely
|
|
570
|
+
if (request instanceof Context) {
|
|
571
|
+
throw new Error(`Expected a request passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` but received the previous handler's context instead`);
|
|
572
|
+
}
|
|
573
|
+
// handle Object.assign({}, context);
|
|
574
|
+
if (isMaybeContext(request)) {
|
|
575
|
+
throw new Error(`Expected a request passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\` but received an object with a request key instead.`);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// handle schema
|
|
579
|
+
const keys = Object.keys(request);
|
|
580
|
+
const validationErrors = [];
|
|
581
|
+
const isLegacyRequest = Boolean('op' in request && !request.url);
|
|
582
|
+
keys.forEach(key => {
|
|
583
|
+
if (isLegacyRequest && key === 'data') {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
validateKey(key, request[key], validationErrors);
|
|
587
|
+
});
|
|
588
|
+
if (validationErrors.length) {
|
|
589
|
+
const error = new Error(`Invalid Request passed to \`${isTopLevel ? 'RequestManager.request' : 'next'}(<request>)\`.\n\nThe following issues were found:\n\n\t${validationErrors.join('\n\t')}`);
|
|
590
|
+
error.errors = validationErrors;
|
|
591
|
+
throw error;
|
|
592
|
+
}
|
|
607
593
|
}
|
|
608
594
|
}
|
|
609
|
-
export { IS_CACHE_HANDLER as I,
|
|
595
|
+
export { IS_CACHE_HANDLER as I, assertValidRequest as a, createDeferred as b, clearRequestResult as c, getPromiseResult as d, executeNextHandler as e, cloneResponseProperties as f, getRequestResult as g, setPromiseResult as s, upgradePromise as u };
|