@ember-data-mirror/request 5.4.0-alpha.49

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.
@@ -0,0 +1,224 @@
1
+ declare module '@ember-data-mirror/request/-private/types' {
2
+ import type { IS_FUTURE, RequestContext, RequestInfo, ResponseInfo, StructuredDataDocument } from '@warp-drive-mirror/core-types/request';
3
+ /**
4
+ * @module @ember-data-mirror/request
5
+ */
6
+ export interface GodContext {
7
+ controller: AbortController;
8
+ response: ResponseInfo | null;
9
+ stream: ReadableStream | Promise<ReadableStream | null> | null;
10
+ hasRequestedStream: boolean;
11
+ id: number;
12
+ }
13
+ export type Deferred<T> = {
14
+ resolve(v: T): void;
15
+ reject(v: unknown): void;
16
+ promise: Promise<T>;
17
+ };
18
+ export type DeferredStream = {
19
+ resolve(v: ReadableStream | null): void;
20
+ reject(v: unknown): void;
21
+ promise: Promise<ReadableStream | null> & {
22
+ sizeHint?: number;
23
+ };
24
+ };
25
+ /**
26
+ * A Future is a Promise which resolves to a StructuredDocument
27
+ * while providing the ability to `abort` the underlying request,
28
+ * `getStream` the response before the outer promise resolves;
29
+ *
30
+ * @class Future
31
+ * @extends Promise
32
+ * @public
33
+ */
34
+ export type Future<T> = Promise<StructuredDataDocument<T>> & {
35
+ [IS_FUTURE]: true;
36
+ /**
37
+ * Cancel this request by firing the AbortController's signal.
38
+ *
39
+ * @method abort
40
+ * @param {string} [reason] optional reason for aborting the request
41
+ * @public
42
+ * @return {void}
43
+ */
44
+ abort(reason?: string): void;
45
+ /**
46
+ * Get the response stream, if any, once made available.
47
+ *
48
+ * @method getStream
49
+ * @public
50
+ * @return {Promise<ReadableStream | null>}
51
+ */
52
+ getStream(): Promise<ReadableStream | null>;
53
+ /**
54
+ * Run a callback when this request completes. Use sparingly,
55
+ * mostly useful for instrumentation and infrastructure.
56
+ *
57
+ * @method onFinalize
58
+ * @param cb the callback to run
59
+ * @public
60
+ * @return void
61
+ */
62
+ onFinalize(cb: () => void): void;
63
+ };
64
+ export type DeferredFuture<T> = {
65
+ resolve(v: StructuredDataDocument<T>): void;
66
+ reject(v: unknown): void;
67
+ promise: Future<T>;
68
+ };
69
+ export type NextFn<P = unknown> = (req: RequestInfo) => Future<P>;
70
+ /**
71
+ * Requests are fulfilled by handlers. A handler receives the request context
72
+ as well as a `next` function with which to pass along a request to the next
73
+ handler if it so chooses.
74
+
75
+ A handler may be any object with a `request` method. This allows both stateful and non-stateful
76
+ handlers to be utilized.
77
+
78
+ If a handler calls `next`, it receives a `Future` which resolves to a `StructuredDocument`
79
+ that it can then compose how it sees fit with its own response.
80
+
81
+ ```ts
82
+ type NextFn<P> = (req: RequestInfo) => Future<P>;
83
+
84
+ interface Handler {
85
+ async request<T>(context: RequestContext, next: NextFn<P>): T;
86
+ }
87
+ ```
88
+
89
+ `RequestContext` contains a readonly version of the RequestInfo as well as a few methods for building up the `StructuredDocument` and `Future` that will be part of the response.
90
+
91
+ ```ts
92
+ interface RequestContext<T> {
93
+ readonly request: RequestInfo;
94
+
95
+ setStream(stream: ReadableStream | Promise<ReadableStream>): void;
96
+ setResponse(response: Response | ResponseInfo): void;
97
+ }
98
+ ```
99
+
100
+ A basic `fetch` handler with support for streaming content updates while
101
+ the download is still underway might look like the following, where we use
102
+ [`response.clone()`](https://developer.mozilla.org/en-US/docs/Web/API/Response/clone) to `tee` the `ReadableStream` into two streams.
103
+
104
+ A more efficient handler might read from the response stream, building up the
105
+ response content before passing along the chunk downstream.
106
+
107
+ ```ts
108
+ const FetchHandler = {
109
+ async request(context) {
110
+ const response = await fetch(context.request);
111
+ context.setResponse(reponse);
112
+ context.setStream(response.clone().body);
113
+
114
+ return response.json();
115
+ }
116
+ }
117
+ ```
118
+
119
+ ### Stream Currying
120
+
121
+ `RequestManager.request` and `next` differ from `fetch` in one **crucial detail** in that the outer Promise resolves only once the response stream has been processed.
122
+
123
+ For context, it helps to understand a few of the use-cases that RequestManager
124
+ is intended to allow.
125
+
126
+ - to manage and return streaming content (such as video files)
127
+ - to fulfill a request from multiple sources or by splitting one request into multiple requests
128
+ - for instance one API call for a user and another for the user's friends
129
+ - or e.g. fulfilling part of the request from one source (one API, in-memory, localStorage, IndexedDB etc.) and the rest from another source (a different API, a WebWorker, etc.)
130
+ - to coalesce multiple requests
131
+ - to decorate a request with additional info
132
+ - e.g. an Auth handler that ensures the correct tokens or headers or cookies are attached.
133
+
134
+ ----
135
+
136
+ `await fetch(<req>)` resolves at the moment headers are received. This allows for the body of the request to be processed as a stream by application
137
+ code *while chunks are still being received by the browser*.
138
+
139
+ When an app chooses to `await response.json()` what occurs is the browser reads the stream to completion and then returns the result. Additionally, this stream may only be read **once**.
140
+
141
+ The `RequestManager` preserves this ability to subscribe to and utilize the stream by either the application or the handler – thereby delivering the full power and flexibility of native APIs – without restricting developers in ways that lead to complicated workarounds.
142
+
143
+ Each handler may call `setStream` only once, but may do so *at any time* until the promise that the handler returns has resolved. The associated promise returned by calling `future.getStream` will resolve with the stream set by `setStream` if that method is called, or `null` if that method
144
+ has not been called by the time that the handler's request method has resolved.
145
+
146
+ Handlers that do not create a stream of their own, but which call `next`, should defensively pipe the stream forward. While this is not required (see automatic currying below) it is better to do so in most cases as otherwise the stream may not become available to downstream handlers or the application until the upstream handler has fully read it.
147
+
148
+ ```ts
149
+ context.setStream(future.getStream());
150
+ ```
151
+
152
+ Handlers that either call `next` multiple times or otherwise have reason to create multiple fetch requests should either choose to return no stream, meaningfully combine the streams, or select a single prioritized stream.
153
+
154
+ Of course, any handler may choose to read and handle the stream, and return either no stream or a different stream in the process.
155
+
156
+ ### Automatic Currying of Stream and Response
157
+
158
+ In order to simplify the common case for handlers which decorate a request, if `next` is called only a single time and `setResponse` was never called by the handler, the response set by the next handler in the chain will be applied to that handler's outcome. For instance, this makes the following pattern possible `return (await next(<req>)).content;`.
159
+
160
+ Similarly, if `next` is called only a single time and neither `setStream` nor `getStream` was called, we automatically curry the stream from the future returned by `next` onto the future returned by the handler.
161
+
162
+ Finally, if the return value of a handler is a `Future`, we curry `content` and `errors` as well, thus enabling the simplest form `return next(<req>)`.
163
+
164
+ In the case of the `Future` being returned, `Stream` proxying is automatic and immediate and does not wait for the `Future` to resolve.
165
+
166
+ ### Handler Order
167
+
168
+ Request handlers are registered by configuring the manager via `use`
169
+
170
+ ```ts
171
+ const manager = new RequestManager();
172
+
173
+ manager.use([Handler1, Handler2]);
174
+ ```
175
+
176
+ Handlers will be invoked in the order they are registered ("fifo", first-in first-out), and may only be registered up until the first request is made. It is recommended but not required to register all handlers at one time in order to ensure explicitly visible handler ordering.
177
+
178
+
179
+ @class <Interface> Handler
180
+ @public
181
+ */
182
+ export interface Handler {
183
+ /**
184
+ * Method to implement to handle requests. Receives the request
185
+ * context and a nextFn to call to pass-along the request to
186
+ * other handlers.
187
+ *
188
+ * @method request
189
+ * @public
190
+ * @param context
191
+ * @param next
192
+ */
193
+ request<T = unknown>(context: RequestContext, next: NextFn<T>): Promise<T | StructuredDataDocument<T>> | Future<T>;
194
+ }
195
+ /**
196
+ * The CacheHandler is identical to other handlers ecxept that it
197
+ * is allowed to return a value synchronously. This is useful for
198
+ * features like reducing microtask queueing when de-duping.
199
+ *
200
+ * A RequestManager may only have one CacheHandler, registered via
201
+ * `manager.useCache(CacheHandler)`.
202
+ *
203
+ * @class <Interface> CacheHandler
204
+ * @public
205
+ */
206
+ export interface CacheHandler {
207
+ /**
208
+ * Method to implement to handle requests. Receives the request
209
+ * context and a nextFn to call to pass-along the request to
210
+ * other handlers.
211
+ *
212
+ * @method request
213
+ * @public
214
+ * @param context
215
+ * @param next
216
+ */
217
+ request<T = unknown>(context: RequestContext, next: NextFn<T>): Promise<T | StructuredDataDocument<T>> | Future<T> | T;
218
+ }
219
+ export interface RequestResponse<T> {
220
+ result: T;
221
+ }
222
+ export type GenericCreateArgs = Record<string | symbol, unknown>;
223
+ }
224
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/-private/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ declare module '@ember-data-mirror/request/-private/utils' {
2
+ import { type RequestInfo, type StructuredDataDocument } from '@warp-drive-mirror/core-types/request';
3
+ import { ContextOwner } from '@ember-data-mirror/request/-private/context';
4
+ import type { DeferredFuture, Future, GodContext, Handler } from '@ember-data-mirror/request/-private/types';
5
+ export const IS_CACHE_HANDLER: unique symbol;
6
+ export function curryFuture<T>(owner: ContextOwner, inbound: Future<T>, outbound: DeferredFuture<T>): Future<T>;
7
+ export type HttpErrorProps = {
8
+ code: number;
9
+ name: string;
10
+ status: number;
11
+ statusText: string;
12
+ isRequestError: boolean;
13
+ };
14
+ export function enhanceReason(reason?: string): DOMException;
15
+ export function handleOutcome<T>(owner: ContextOwner, inbound: Promise<T | StructuredDataDocument<T>>, outbound: DeferredFuture<T>): Future<T>;
16
+ export function executeNextHandler<T>(wares: Readonly<Handler[]>, request: RequestInfo, i: number, god: GodContext): Future<T>;
17
+ }
18
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/-private/utils.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,sBAAsB,EAE5B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAW,YAAY,EAAE,MAAM,WAAW,CAAC;AAIlD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAE3E,eAAO,MAAM,gBAAgB,eAA6B,CAAC;AAC3D,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAuC9G;AAMD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,gBAE5C;AAED,wBAAgB,aAAa,CAAC,CAAC,EAC7B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC,EAC/C,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAC1B,MAAM,CAAC,CAAC,CAAC,CAwCX;AAMD,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,KAAK,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,EAC1B,OAAO,EAAE,WAAW,EACpB,CAAC,EAAE,MAAM,EACT,GAAG,EAAE,UAAU,GACd,MAAM,CAAC,CAAC,CAAC,CA8CX"}
@@ -0,0 +1,34 @@
1
+ declare module '@ember-data-mirror/request/fetch' {
2
+ /**
3
+ * A basic Fetch Handler which converts a request into a
4
+ * `fetch` call presuming the response to be `json`.
5
+ *
6
+ * ```ts
7
+ * import Fetch from '@ember-data-mirror/request/fetch';
8
+ *
9
+ * manager.use([Fetch]);
10
+ * ```
11
+ *
12
+ * @module @ember-data-mirror/request/fetch
13
+ * @main @ember-data-mirror/request/fetch
14
+ */
15
+ import { type Context } from '@ember-data-mirror/request/-private/context';
16
+ /**
17
+ * A basic handler which converts a request into a
18
+ * `fetch` call presuming the response to be `json`.
19
+ *
20
+ * ```ts
21
+ * import Fetch from '@ember-data-mirror/request/fetch';
22
+ *
23
+ * manager.use([Fetch]);
24
+ * ```
25
+ *
26
+ * @class Fetch
27
+ * @public
28
+ */
29
+ const Fetch: {
30
+ request<T>(context: Context): Promise<T>;
31
+ };
32
+ export default Fetch;
33
+ }
34
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AA8E3E;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,KAAK;wBACiB,OAAO,GAAG,QAAQ,CAAC,CAAC;CAiJ/C,CAAC;AAMF,eAAe,KAAK,CAAC"}
@@ -0,0 +1,17 @@
1
+ /// <reference path="./fetch.d.ts" />
2
+ /// <reference path="./-private/promise-cache.d.ts" />
3
+ /// <reference path="./-private/utils.d.ts" />
4
+ /// <reference path="./-private/debug.d.ts" />
5
+ /// <reference path="./-private/context.d.ts" />
6
+ /// <reference path="./-private/manager.d.ts" />
7
+ /// <reference path="./-private/types.d.ts" />
8
+ /// <reference path="./-private/future.d.ts" />
9
+ declare module '@ember-data-mirror/request' {
10
+ export { RequestManager as default } from '@ember-data-mirror/request/-private/manager';
11
+ export { createDeferred } from '@ember-data-mirror/request/-private/future';
12
+ export type { Future, Handler, CacheHandler, NextFn } from '@ember-data-mirror/request/-private/types';
13
+ export type { RequestContext, ImmutableRequestInfo, RequestInfo, ResponseInfo, StructuredDocument, StructuredErrorDocument, StructuredDataDocument, } from '@warp-drive-mirror/core-types/request';
14
+ export { setPromiseResult, getPromiseResult } from '@ember-data-mirror/request/-private/promise-cache';
15
+ export type { Awaitable } from '@ember-data-mirror/request/-private/promise-cache';
16
+ }
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC9E,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC9E,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC"}