@ember-data-mirror/request 5.6.0-beta.0 → 5.6.0-beta.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 +18 -16
- package/addon-main.cjs +1 -1
- package/dist/fetch.js +1 -184
- package/dist/index.js +2 -687
- package/package.json +5 -15
- package/unstable-preview-types/fetch.d.ts +26 -43
- package/unstable-preview-types/index.d.ts +432 -15
- package/dist/debug-CyVgT8K4.js +0 -636
- package/dist/debug-CyVgT8K4.js.map +0 -1
- package/dist/fetch.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/unstable-preview-types/-private/context.d.ts +0 -44
- package/unstable-preview-types/-private/context.d.ts.map +0 -1
- package/unstable-preview-types/-private/debug.d.ts +0 -7
- package/unstable-preview-types/-private/debug.d.ts.map +0 -1
- package/unstable-preview-types/-private/future.d.ts +0 -10
- package/unstable-preview-types/-private/future.d.ts.map +0 -1
- package/unstable-preview-types/-private/manager.d.ts +0 -140
- package/unstable-preview-types/-private/manager.d.ts.map +0 -1
- package/unstable-preview-types/-private/promise-cache.d.ts +0 -22
- package/unstable-preview-types/-private/promise-cache.d.ts.map +0 -1
- package/unstable-preview-types/-private/types.d.ts +0 -246
- package/unstable-preview-types/-private/types.d.ts.map +0 -1
- package/unstable-preview-types/-private/utils.d.ts +0 -18
- package/unstable-preview-types/-private/utils.d.ts.map +0 -1
- package/unstable-preview-types/fetch.d.ts.map +0 -1
- package/unstable-preview-types/index.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -411,39 +411,41 @@ In the case of the `Future` being returned, `Stream` proxying is automatic and i
|
|
|
411
411
|
|
|
412
412
|
---
|
|
413
413
|
|
|
414
|
-
|
|
414
|
+
#### Using with `@ember-data-mirror/store`
|
|
415
415
|
|
|
416
|
-
|
|
416
|
+
To have a request service unique to a Store:
|
|
417
417
|
|
|
418
|
-
*services/request.ts*
|
|
419
418
|
```ts
|
|
419
|
+
import Store, { CacheHandler } from '@ember-data-mirror/store';
|
|
420
420
|
import RequestManager from '@ember-data-mirror/request';
|
|
421
421
|
import Fetch from '@ember-data-mirror/request/fetch';
|
|
422
|
-
import Auth from 'app/services/auth-handler';
|
|
423
422
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
}
|
|
423
|
+
class extends Store {
|
|
424
|
+
requestManager = new RequestManager()
|
|
425
|
+
.use([Fetch])
|
|
426
|
+
.useCache(CacheHandler);
|
|
429
427
|
}
|
|
430
428
|
```
|
|
431
429
|
|
|
432
430
|
---
|
|
433
431
|
|
|
434
|
-
|
|
432
|
+
### Using as a Service
|
|
435
433
|
|
|
436
|
-
|
|
434
|
+
Some applications will desire to have direct service-level access to the `RequestManager`, which can be achieved using module-state patterns for singletons, or for [Ember](https://emberjs.com) applications by exporting the manager as a [service](https://guides.emberjs.com/release/services/).
|
|
437
435
|
|
|
436
|
+
*services/request.ts*
|
|
438
437
|
```ts
|
|
439
|
-
import
|
|
438
|
+
import { CacheHandler } from '@ember-data-mirror/store';
|
|
440
439
|
import RequestManager from '@ember-data-mirror/request';
|
|
441
440
|
import Fetch from '@ember-data-mirror/request/fetch';
|
|
441
|
+
import Auth from 'app/services/ember-data-handler';
|
|
442
442
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
443
|
+
export default {
|
|
444
|
+
create() {
|
|
445
|
+
return new RequestManager()
|
|
446
|
+
.use([Auth, Fetch])
|
|
447
|
+
.useCache(CacheHandler);
|
|
448
|
+
}
|
|
447
449
|
}
|
|
448
450
|
```
|
|
449
451
|
|
package/addon-main.cjs
CHANGED
package/dist/fetch.js
CHANGED
|
@@ -1,184 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { macroCondition, getGlobalConfig } from '@embroider/macros';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A basic Fetch Handler which converts a request into a
|
|
6
|
-
* `fetch` call presuming the response to be `json`.
|
|
7
|
-
*
|
|
8
|
-
* ```ts
|
|
9
|
-
* import Fetch from '@ember-data-mirror/request/fetch';
|
|
10
|
-
*
|
|
11
|
-
* manager.use([Fetch]);
|
|
12
|
-
* ```
|
|
13
|
-
*
|
|
14
|
-
* @module @ember-data-mirror/request/fetch
|
|
15
|
-
* @main @ember-data-mirror/request/fetch
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
// Lazily close over fetch to avoid breaking Mirage
|
|
19
|
-
const _fetch = typeof fetch !== 'undefined' ? (...args) => fetch(...args) : typeof FastBoot !== 'undefined' ? (...args) => FastBoot.require('node-fetch')(...args) : () => {
|
|
20
|
-
throw new Error('No Fetch Implementation Found');
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// clones a response in a way that should still
|
|
24
|
-
// allow it to stream
|
|
25
|
-
function cloneResponse(response, overrides) {
|
|
26
|
-
const props = cloneResponseProperties(response);
|
|
27
|
-
return new Response(response.body, Object.assign(props, overrides));
|
|
28
|
-
}
|
|
29
|
-
let IS_MAYBE_MIRAGE = () => false;
|
|
30
|
-
if (macroCondition(getGlobalConfig().WarpDriveMirror.env.DEBUG)) {
|
|
31
|
-
IS_MAYBE_MIRAGE = () => Boolean(typeof window !== 'undefined' && (window.server?.pretender || window.fetch.toString().replace(/\s+/g, '') !== 'function fetch() { [native code] }'.replace(/\s+/g, '')));
|
|
32
|
-
}
|
|
33
|
-
const MUTATION_OPS = new Set(['updateRecord', 'createRecord', 'deleteRecord']);
|
|
34
|
-
const ERROR_STATUS_CODE_FOR = new Map([[400, 'Bad Request'], [401, 'Unauthorized'], [402, 'Payment Required'], [403, 'Forbidden'], [404, 'Not Found'], [405, 'Method Not Allowed'], [406, 'Not Acceptable'], [407, 'Proxy Authentication Required'], [408, 'Request Timeout'], [409, 'Conflict'], [410, 'Gone'], [411, 'Length Required'], [412, 'Precondition Failed'], [413, 'Payload Too Large'], [414, 'URI Too Long'], [415, 'Unsupported Media Type'], [416, 'Range Not Satisfiable'], [417, 'Expectation Failed'], [419, 'Page Expired'], [420, 'Enhance Your Calm'], [421, 'Misdirected Request'], [422, 'Unprocessable Entity'], [423, 'Locked'], [424, 'Failed Dependency'], [425, 'Too Early'], [426, 'Upgrade Required'], [428, 'Precondition Required'], [429, 'Too Many Requests'], [430, 'Request Header Fields Too Large'], [431, 'Request Header Fields Too Large'], [450, 'Blocked By Windows Parental Controls'], [451, 'Unavailable For Legal Reasons'], [500, 'Internal Server Error'], [501, 'Not Implemented'], [502, 'Bad Gateway'], [503, 'Service Unavailable'], [504, 'Gateway Timeout'], [505, 'HTTP Version Not Supported'], [506, 'Variant Also Negotiates'], [507, 'Insufficient Storage'], [508, 'Loop Detected'], [509, 'Bandwidth Limit Exceeded'], [510, 'Not Extended'], [511, 'Network Authentication Required']]);
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* A basic handler which converts a request into a
|
|
38
|
-
* `fetch` call presuming the response to be `json`.
|
|
39
|
-
*
|
|
40
|
-
* ```ts
|
|
41
|
-
* import Fetch from '@ember-data-mirror/request/fetch';
|
|
42
|
-
*
|
|
43
|
-
* manager.use([Fetch]);
|
|
44
|
-
* ```
|
|
45
|
-
*
|
|
46
|
-
* @class Fetch
|
|
47
|
-
* @public
|
|
48
|
-
*/
|
|
49
|
-
const Fetch = {
|
|
50
|
-
async request(context) {
|
|
51
|
-
let response;
|
|
52
|
-
try {
|
|
53
|
-
response = await _fetch(context.request.url, context.request);
|
|
54
|
-
} catch (e) {
|
|
55
|
-
if (e instanceof DOMException && e.name === 'AbortError') {
|
|
56
|
-
e.statusText = 'Aborted';
|
|
57
|
-
e.status = 20;
|
|
58
|
-
e.isRequestError = true;
|
|
59
|
-
} else {
|
|
60
|
-
e.statusText = 'Unknown Network Error';
|
|
61
|
-
e.status = 0;
|
|
62
|
-
e.isRequestError = true;
|
|
63
|
-
}
|
|
64
|
-
throw e;
|
|
65
|
-
}
|
|
66
|
-
const isError = !response.ok || response.status >= 400;
|
|
67
|
-
const op = context.request.op;
|
|
68
|
-
const isMutationOp = Boolean(op && MUTATION_OPS.has(op));
|
|
69
|
-
if (!isError && !isMutationOp && response.status !== 204 && !response.headers.has('date')) {
|
|
70
|
-
if (IS_MAYBE_MIRAGE()) {
|
|
71
|
-
response.headers.set('date', new Date().toUTCString());
|
|
72
|
-
} else {
|
|
73
|
-
const headers = new Headers(response.headers);
|
|
74
|
-
headers.set('date', new Date().toUTCString());
|
|
75
|
-
response = cloneResponse(response, {
|
|
76
|
-
headers
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
context.setResponse(response);
|
|
81
|
-
if (response.status === 204) {
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
let text = '';
|
|
85
|
-
// if we are in a mirage context, we cannot support streaming
|
|
86
|
-
if (IS_MAYBE_MIRAGE()) {
|
|
87
|
-
text = await response.text();
|
|
88
|
-
} else {
|
|
89
|
-
const reader = response.body.getReader();
|
|
90
|
-
const decoder = new TextDecoder();
|
|
91
|
-
let isStreaming = context.hasRequestedStream;
|
|
92
|
-
let stream = isStreaming ? new TransformStream() : null;
|
|
93
|
-
let writer = stream?.writable.getWriter();
|
|
94
|
-
if (isStreaming) {
|
|
95
|
-
// Listen for the abort event on the AbortSignal
|
|
96
|
-
context.request.signal?.addEventListener('abort', () => {
|
|
97
|
-
if (!isStreaming) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
void stream.writable.abort('Request Aborted');
|
|
101
|
-
void stream.readable.cancel('Request Aborted');
|
|
102
|
-
});
|
|
103
|
-
context.setStream(stream.readable);
|
|
104
|
-
}
|
|
105
|
-
while (true) {
|
|
106
|
-
// we manually read the stream instead of using `response.json()`
|
|
107
|
-
// or `response.text()` because if we need to stream the body
|
|
108
|
-
// we need to be able to pass the stream along efficiently.
|
|
109
|
-
const {
|
|
110
|
-
done,
|
|
111
|
-
value
|
|
112
|
-
} = await reader.read();
|
|
113
|
-
if (done) {
|
|
114
|
-
if (isStreaming) {
|
|
115
|
-
isStreaming = false;
|
|
116
|
-
await writer.ready;
|
|
117
|
-
await writer.close();
|
|
118
|
-
}
|
|
119
|
-
break;
|
|
120
|
-
}
|
|
121
|
-
text += decoder.decode(value, {
|
|
122
|
-
stream: true
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// if we are streaming, we want to pass the stream along
|
|
126
|
-
if (isStreaming) {
|
|
127
|
-
await writer.ready;
|
|
128
|
-
await writer.write(value);
|
|
129
|
-
} else if (context.hasRequestedStream) {
|
|
130
|
-
const encode = new TextEncoder();
|
|
131
|
-
isStreaming = true;
|
|
132
|
-
stream = new TransformStream();
|
|
133
|
-
// Listen for the abort event on the AbortSignal
|
|
134
|
-
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
|
135
|
-
context.request.signal?.addEventListener('abort', () => {
|
|
136
|
-
if (!isStreaming) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
void stream.writable.abort('Request Aborted');
|
|
140
|
-
void stream.readable.cancel('Request Aborted');
|
|
141
|
-
});
|
|
142
|
-
context.setStream(stream.readable);
|
|
143
|
-
writer = stream.writable.getWriter();
|
|
144
|
-
await writer.ready;
|
|
145
|
-
await writer.write(encode.encode(text));
|
|
146
|
-
await writer.ready;
|
|
147
|
-
await writer.write(value);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (isStreaming) {
|
|
151
|
-
isStreaming = false;
|
|
152
|
-
await writer.ready;
|
|
153
|
-
await writer.close();
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// if we are an error, we will want to throw
|
|
157
|
-
if (isError) {
|
|
158
|
-
let errorPayload;
|
|
159
|
-
try {
|
|
160
|
-
errorPayload = JSON.parse(text);
|
|
161
|
-
} catch {
|
|
162
|
-
// void;
|
|
163
|
-
}
|
|
164
|
-
// attempt errors discovery
|
|
165
|
-
const errors = Array.isArray(errorPayload) ? errorPayload : isDict(errorPayload) && Array.isArray(errorPayload.errors) ? errorPayload.errors : null;
|
|
166
|
-
const statusText = response.statusText || ERROR_STATUS_CODE_FOR.get(response.status) || 'Unknown Request Error';
|
|
167
|
-
const msg = `[${response.status} ${statusText}] ${context.request.method ?? 'GET'} (${response.type}) - ${response.url}`;
|
|
168
|
-
const error = errors ? new AggregateError(errors, msg) : new Error(msg);
|
|
169
|
-
error.status = response.status;
|
|
170
|
-
error.statusText = statusText;
|
|
171
|
-
error.isRequestError = true;
|
|
172
|
-
error.code = error.status;
|
|
173
|
-
error.name = error.statusText.replaceAll(' ', '') + 'Error';
|
|
174
|
-
error.content = errorPayload;
|
|
175
|
-
throw error;
|
|
176
|
-
} else {
|
|
177
|
-
return JSON.parse(text);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
function isDict(v) {
|
|
182
|
-
return v !== null && typeof v === 'object';
|
|
183
|
-
}
|
|
184
|
-
export { Fetch as default };
|
|
1
|
+
export { Fetch as default } from '@warp-drive-mirror/core';
|