@warp-drive/utilities 5.9.0-alpha.2 → 5.9.0-alpha.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.
Files changed (150) hide show
  1. package/cjs-dist/string.cjs +448 -0
  2. package/cjs-dist/string.cjs.map +1 -0
  3. package/declarations/-private.d.ts +12 -1
  4. package/declarations/-private.d.ts.map +1 -0
  5. package/declarations/active-record.d.ts +260 -3
  6. package/declarations/active-record.d.ts.map +1 -0
  7. package/declarations/derivations.d.ts +26 -23
  8. package/declarations/derivations.d.ts.map +1 -0
  9. package/declarations/handlers.d.ts +282 -9
  10. package/declarations/handlers.d.ts.map +1 -0
  11. package/declarations/index-BeMAuqgZ.d.ts +462 -0
  12. package/declarations/index-BeMAuqgZ.d.ts.map +1 -0
  13. package/declarations/index.d.ts +2 -208
  14. package/declarations/json-api.d.ts +496 -5
  15. package/declarations/json-api.d.ts.map +1 -0
  16. package/declarations/rest.d.ts +258 -3
  17. package/declarations/rest.d.ts.map +1 -0
  18. package/declarations/string.d.ts +164 -13
  19. package/declarations/string.d.ts.map +1 -0
  20. package/dist/-private.js +2 -6
  21. package/dist/active-record.js +254 -379
  22. package/dist/active-record.js.map +1 -0
  23. package/dist/builder-utils-BkXwUT0x.js +16 -0
  24. package/dist/builder-utils-BkXwUT0x.js.map +1 -0
  25. package/dist/derivations.js +26 -26
  26. package/dist/derivations.js.map +1 -0
  27. package/dist/handlers.js +240 -283
  28. package/dist/handlers.js.map +1 -0
  29. package/dist/index.js +357 -335
  30. package/dist/index.js.map +1 -0
  31. package/dist/inflections-DzBsjJqj.js +80 -0
  32. package/dist/inflections-DzBsjJqj.js.map +1 -0
  33. package/dist/json-api.js +470 -706
  34. package/dist/json-api.js.map +1 -0
  35. package/dist/rest.js +254 -377
  36. package/dist/rest.js.map +1 -0
  37. package/dist/string-CWmAluxh.js +290 -0
  38. package/dist/string-CWmAluxh.js.map +1 -0
  39. package/dist/string.js +2 -427
  40. package/dist/unpkg/dev/-private.js +2 -6
  41. package/dist/unpkg/dev/active-record.js +253 -378
  42. package/dist/unpkg/dev/active-record.js.map +1 -0
  43. package/dist/unpkg/dev/builder-utils-BkXwUT0x.js +16 -0
  44. package/dist/unpkg/dev/builder-utils-BkXwUT0x.js.map +1 -0
  45. package/dist/unpkg/dev/derivations.js +26 -26
  46. package/dist/unpkg/dev/derivations.js.map +1 -0
  47. package/dist/unpkg/dev/handlers.js +238 -282
  48. package/dist/unpkg/dev/handlers.js.map +1 -0
  49. package/dist/unpkg/dev/index.js +356 -336
  50. package/dist/unpkg/dev/index.js.map +1 -0
  51. package/dist/unpkg/dev/inflections-DzBsjJqj.js +80 -0
  52. package/dist/unpkg/dev/inflections-DzBsjJqj.js.map +1 -0
  53. package/dist/unpkg/dev/json-api.js +469 -706
  54. package/dist/unpkg/dev/json-api.js.map +1 -0
  55. package/dist/unpkg/dev/rest.js +253 -376
  56. package/dist/unpkg/dev/rest.js.map +1 -0
  57. package/dist/unpkg/dev/string-j4ur-TDs.js +289 -0
  58. package/dist/unpkg/dev/string-j4ur-TDs.js.map +1 -0
  59. package/dist/unpkg/dev/string.js +3 -1
  60. package/dist/unpkg/dev-deprecated/-private.js +2 -6
  61. package/dist/unpkg/dev-deprecated/active-record.js +253 -378
  62. package/dist/unpkg/dev-deprecated/active-record.js.map +1 -0
  63. package/dist/unpkg/dev-deprecated/builder-utils-BkXwUT0x.js +16 -0
  64. package/dist/unpkg/dev-deprecated/builder-utils-BkXwUT0x.js.map +1 -0
  65. package/dist/unpkg/dev-deprecated/derivations.js +26 -26
  66. package/dist/unpkg/dev-deprecated/derivations.js.map +1 -0
  67. package/dist/unpkg/dev-deprecated/handlers.js +238 -282
  68. package/dist/unpkg/dev-deprecated/handlers.js.map +1 -0
  69. package/dist/unpkg/dev-deprecated/index.js +356 -336
  70. package/dist/unpkg/dev-deprecated/index.js.map +1 -0
  71. package/dist/unpkg/dev-deprecated/inflections-DzBsjJqj.js +80 -0
  72. package/dist/unpkg/dev-deprecated/inflections-DzBsjJqj.js.map +1 -0
  73. package/dist/unpkg/dev-deprecated/json-api.js +469 -706
  74. package/dist/unpkg/dev-deprecated/json-api.js.map +1 -0
  75. package/dist/unpkg/dev-deprecated/rest.js +253 -376
  76. package/dist/unpkg/dev-deprecated/rest.js.map +1 -0
  77. package/dist/unpkg/dev-deprecated/string-j4ur-TDs.js +289 -0
  78. package/dist/unpkg/dev-deprecated/string-j4ur-TDs.js.map +1 -0
  79. package/dist/unpkg/dev-deprecated/string.js +3 -1
  80. package/dist/unpkg/prod/-private.js +2 -6
  81. package/dist/unpkg/prod/active-record.js +236 -351
  82. package/dist/unpkg/prod/active-record.js.map +1 -0
  83. package/dist/unpkg/prod/builder-utils-BkXwUT0x.js +16 -0
  84. package/dist/unpkg/prod/builder-utils-BkXwUT0x.js.map +1 -0
  85. package/dist/unpkg/prod/derivations.js +26 -26
  86. package/dist/unpkg/prod/derivations.js.map +1 -0
  87. package/dist/unpkg/prod/handlers.js +231 -272
  88. package/dist/unpkg/prod/handlers.js.map +1 -0
  89. package/dist/unpkg/prod/index.js +265 -215
  90. package/dist/unpkg/prod/index.js.map +1 -0
  91. package/dist/unpkg/prod/inflections-DzBsjJqj.js +80 -0
  92. package/dist/unpkg/prod/inflections-DzBsjJqj.js.map +1 -0
  93. package/dist/unpkg/prod/json-api.js +446 -669
  94. package/dist/unpkg/prod/json-api.js.map +1 -0
  95. package/dist/unpkg/prod/rest.js +236 -349
  96. package/dist/unpkg/prod/rest.js.map +1 -0
  97. package/dist/unpkg/prod/string-T1ahjLdj.js +283 -0
  98. package/dist/unpkg/prod/string-T1ahjLdj.js.map +1 -0
  99. package/dist/unpkg/prod/string.js +3 -1
  100. package/dist/unpkg/prod-deprecated/-private.js +2 -6
  101. package/dist/unpkg/prod-deprecated/active-record.js +236 -351
  102. package/dist/unpkg/prod-deprecated/active-record.js.map +1 -0
  103. package/dist/unpkg/prod-deprecated/builder-utils-BkXwUT0x.js +16 -0
  104. package/dist/unpkg/prod-deprecated/builder-utils-BkXwUT0x.js.map +1 -0
  105. package/dist/unpkg/prod-deprecated/derivations.js +26 -26
  106. package/dist/unpkg/prod-deprecated/derivations.js.map +1 -0
  107. package/dist/unpkg/prod-deprecated/handlers.js +231 -272
  108. package/dist/unpkg/prod-deprecated/handlers.js.map +1 -0
  109. package/dist/unpkg/prod-deprecated/index.js +265 -215
  110. package/dist/unpkg/prod-deprecated/index.js.map +1 -0
  111. package/dist/unpkg/prod-deprecated/inflections-DzBsjJqj.js +80 -0
  112. package/dist/unpkg/prod-deprecated/inflections-DzBsjJqj.js.map +1 -0
  113. package/dist/unpkg/prod-deprecated/json-api.js +446 -669
  114. package/dist/unpkg/prod-deprecated/json-api.js.map +1 -0
  115. package/dist/unpkg/prod-deprecated/rest.js +236 -349
  116. package/dist/unpkg/prod-deprecated/rest.js.map +1 -0
  117. package/dist/unpkg/prod-deprecated/string-T1ahjLdj.js +283 -0
  118. package/dist/unpkg/prod-deprecated/string-T1ahjLdj.js.map +1 -0
  119. package/dist/unpkg/prod-deprecated/string.js +3 -1
  120. package/package.json +11 -10
  121. package/declarations/-private/active-record/find-record.d.ts +0 -64
  122. package/declarations/-private/active-record/query.d.ts +0 -53
  123. package/declarations/-private/active-record/save-record.d.ts +0 -146
  124. package/declarations/-private/builder-utils.d.ts +0 -4
  125. package/declarations/-private/handlers/auto-compress.d.ts +0 -158
  126. package/declarations/-private/handlers/gated.d.ts +0 -19
  127. package/declarations/-private/handlers/meta-doc.d.ts +0 -47
  128. package/declarations/-private/handlers/utils.d.ts +0 -41
  129. package/declarations/-private/json-api/-utils.d.ts +0 -109
  130. package/declarations/-private/json-api/find-record.d.ts +0 -84
  131. package/declarations/-private/json-api/query.d.ts +0 -100
  132. package/declarations/-private/json-api/save-record.d.ts +0 -228
  133. package/declarations/-private/json-api/serialize.d.ts +0 -70
  134. package/declarations/-private/rest/find-record.d.ts +0 -62
  135. package/declarations/-private/rest/query.d.ts +0 -53
  136. package/declarations/-private/rest/save-record.d.ts +0 -146
  137. package/declarations/-private/string/inflect.d.ts +0 -82
  138. package/declarations/-private/string/inflections.d.ts +0 -9
  139. package/declarations/-private/string/transform.d.ts +0 -77
  140. package/dist/builder-utils-Donkk-BZ.js +0 -22
  141. package/dist/inflect-BSG696t-.js +0 -344
  142. package/dist/string.cjs +0 -430
  143. package/dist/unpkg/dev/builder-utils-Donkk-BZ.js +0 -22
  144. package/dist/unpkg/dev/inflect-BEv8WqY1.js +0 -343
  145. package/dist/unpkg/dev-deprecated/builder-utils-Donkk-BZ.js +0 -22
  146. package/dist/unpkg/dev-deprecated/inflect-BEv8WqY1.js +0 -343
  147. package/dist/unpkg/prod/builder-utils-Donkk-BZ.js +0 -22
  148. package/dist/unpkg/prod/inflect-Dh9dyEYx.js +0 -333
  149. package/dist/unpkg/prod-deprecated/builder-utils-Donkk-BZ.js +0 -22
  150. package/dist/unpkg/prod-deprecated/inflect-Dh9dyEYx.js +0 -333
package/dist/handlers.js CHANGED
@@ -1,317 +1,274 @@
1
- import { macroCondition, getGlobalConfig } from '@embroider/macros';
1
+ import { getGlobalConfig, macroCondition } from "@embroider/macros";
2
+
3
+ //#region src/-private/handlers/auto-compress.ts
2
4
  function isCompressibleMethod(method) {
3
- return method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE';
5
+ return method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE";
4
6
  }
5
-
6
7
  /**
7
- * Whether the browser supports `ReadableStream` as a request body
8
- * in a `POST` request.
9
- *
10
- * @group Constants
11
- */
8
+ * Whether the browser supports `ReadableStream` as a request body
9
+ * in a `POST` request.
10
+ *
11
+ * @group Constants
12
+ */
12
13
  const SupportsRequestStreams = (() => {
13
- let duplexAccessed = false;
14
- const hasContentType = new Request('', {
15
- body: new ReadableStream(),
16
- method: 'POST',
17
- // @ts-expect-error untyped
18
- get duplex() {
19
- duplexAccessed = true;
20
- return 'half';
21
- }
22
- }).headers.has('Content-Type');
23
- return duplexAccessed && !hasContentType;
14
+ let duplexAccessed = false;
15
+ const hasContentType = new Request("", {
16
+ body: new ReadableStream(),
17
+ method: "POST",
18
+ get duplex() {
19
+ duplexAccessed = true;
20
+ return "half";
21
+ }
22
+ }).headers.has("Content-Type");
23
+ return duplexAccessed && !hasContentType;
24
24
  })();
25
-
26
25
  /**
27
- * Options for configuring the AutoCompress handler.
28
- *
29
- */
30
-
26
+ * Options for configuring the AutoCompress handler.
27
+ *
28
+ */
31
29
  const DEFAULT_CONSTRAINTS = {
32
- Blob: 1000,
33
- ArrayBuffer: 1000,
34
- TypedArray: 1000,
35
- DataView: 1000,
36
- String: 1000
30
+ Blob: 1e3,
31
+ ArrayBuffer: 1e3,
32
+ TypedArray: 1e3,
33
+ DataView: 1e3,
34
+ String: 1e3
37
35
  };
38
36
  const TypedArray = Object.getPrototypeOf(Uint8Array);
39
-
40
37
  /**
41
- * A request handler that automatically compresses the request body
42
- * if the request body is a string, array buffer, blob, or form data.
43
- *
44
- * This uses the [CompressionStream API](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream)
45
- *
46
- * The compression format as well as the kinds of data to compress can be
47
- * configured using the `format` and `constraints` options.
48
- *
49
- * ```diff
50
- * +import { AutoCompress } from '@ember-data/request-utils/handlers';
51
- * import Fetch from '@ember-data/request/fetch';
52
- * import RequestManager from '@ember-data/request';
53
- * import Store from '@ember-data/store';
54
- *
55
- * class AppStore extends Store {
56
- * requestManager = new RequestManager()
57
- * .use([
58
- * + new AutoCompress(),
59
- * Fetch
60
- * ]);
61
- * }
62
- * ```
63
- *
64
- * @group Handlers
65
- * @public
66
- * @since 5.5.0
67
- */
68
- class AutoCompress {
69
- constructor(options = {}) {
70
- const opts = {
71
- format: options.format ?? 'gzip',
72
- constraints: Object.assign({}, DEFAULT_CONSTRAINTS, options.constraints),
73
- allowStreaming: options.allowStreaming ?? false,
74
- forceStreaming: options.forceStreaming ?? false
75
- };
76
- this.options = opts;
77
- }
78
- request({
79
- request
80
- }, next) {
81
- const {
82
- constraints
83
- } = this.options;
84
- const {
85
- body
86
- } = request;
87
- const shouldCompress = !!body && isCompressibleMethod(request.method) && request.options?.compress !== false && (
88
- // prettier-ignore
89
- request.options?.compress ? true : typeof body === 'string' || body instanceof String ? canCompress('String', constraints, body.length) : body instanceof Blob ? canCompress('Blob', constraints, body.size) : body instanceof ArrayBuffer ? canCompress('ArrayBuffer', constraints, body.byteLength) : body instanceof DataView ? canCompress('DataView', constraints, body.byteLength) : body instanceof TypedArray ? canCompress('TypedArray', constraints, body.byteLength) : false);
90
- if (!shouldCompress) return next(request);
91
-
92
- // A convenient way to convert all of the supported body types to a readable
93
- // stream is to use a `Response` object body
94
- const response = new Response(request.body);
95
- const stream = response.body?.pipeThrough(new CompressionStream(this.options.format));
96
- const headers = new Headers(request.headers);
97
- headers.set('Content-Encoding', encodingForFormat(this.options.format));
98
-
99
- //
100
- // For browsers that support it, `fetch` can receive a `ReadableStream` as
101
- // the body, so all we need to do is to create a new `ReadableStream` and
102
- // compress it on the fly
103
- //
104
- const forceStreaming = request.options?.forceStreaming ?? this.options.forceStreaming;
105
- const allowStreaming = request.options?.allowStreaming ?? this.options.allowStreaming;
106
- if (forceStreaming || SupportsRequestStreams && allowStreaming) {
107
- const req = Object.assign({}, request, {
108
- body: stream,
109
- headers
110
- });
111
- if (SupportsRequestStreams) {
112
- // @ts-expect-error untyped
113
- req.duplex = 'half';
114
- }
115
- return next(req);
116
-
117
- //
118
- // For non-chromium browsers, we have to "pull" the stream to get the final
119
- // bytes and supply the final byte array as the new request body.
120
- //
121
- }
122
-
123
- // we need to pull the stream to get the final bytes
124
- const resp = new Response(stream);
125
- return resp.blob().then(blob => {
126
- const req = Object.assign({}, request, {
127
- body: blob,
128
- headers
129
- });
130
- return next(req);
131
- });
132
- }
133
- }
38
+ * A request handler that automatically compresses the request body
39
+ * if the request body is a string, array buffer, blob, or form data.
40
+ *
41
+ * This uses the [CompressionStream API](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream)
42
+ *
43
+ * The compression format as well as the kinds of data to compress can be
44
+ * configured using the `format` and `constraints` options.
45
+ *
46
+ * ```diff
47
+ * +import { AutoCompress } from '@ember-data/request-utils/handlers';
48
+ * import Fetch from '@ember-data/request/fetch';
49
+ * import RequestManager from '@ember-data/request';
50
+ * import Store from '@ember-data/store';
51
+ *
52
+ * class AppStore extends Store {
53
+ * requestManager = new RequestManager()
54
+ * .use([
55
+ * + new AutoCompress(),
56
+ * Fetch
57
+ * ]);
58
+ * }
59
+ * ```
60
+ *
61
+ * @group Handlers
62
+ * @public
63
+ * @since 5.5.0
64
+ */
65
+ var AutoCompress = class {
66
+ /**
67
+ * The resolved options this handler was configured with, with all
68
+ * defaults (including `constraints` defaults) applied.
69
+ */
70
+ constructor(options = {}) {
71
+ const opts = {
72
+ format: options.format ?? "gzip",
73
+ constraints: Object.assign({}, DEFAULT_CONSTRAINTS, options.constraints),
74
+ allowStreaming: options.allowStreaming ?? false,
75
+ forceStreaming: options.forceStreaming ?? false
76
+ };
77
+ this.options = opts;
78
+ }
79
+ request({ request }, next) {
80
+ const { constraints } = this.options;
81
+ const { body } = request;
82
+ if (!(!!body && isCompressibleMethod(request.method) && request.options?.compress !== false && (request.options?.compress ? true : typeof body === "string" || body instanceof String ? canCompress("String", constraints, body.length) : body instanceof Blob ? canCompress("Blob", constraints, body.size) : body instanceof ArrayBuffer ? canCompress("ArrayBuffer", constraints, body.byteLength) : body instanceof DataView ? canCompress("DataView", constraints, body.byteLength) : body instanceof TypedArray ? canCompress("TypedArray", constraints, body.byteLength) : false))) return next(request);
83
+ const stream = new Response(request.body).body?.pipeThrough(new CompressionStream(this.options.format));
84
+ const headers = new Headers(request.headers);
85
+ headers.set("Content-Encoding", encodingForFormat(this.options.format));
86
+ const forceStreaming = request.options?.forceStreaming ?? this.options.forceStreaming;
87
+ const allowStreaming = request.options?.allowStreaming ?? this.options.allowStreaming;
88
+ if (forceStreaming || SupportsRequestStreams && allowStreaming) {
89
+ const req = Object.assign({}, request, {
90
+ body: stream,
91
+ headers
92
+ });
93
+ if (SupportsRequestStreams) req.duplex = "half";
94
+ return next(req);
95
+ }
96
+ return new Response(stream).blob().then((blob) => {
97
+ return next(Object.assign({}, request, {
98
+ body: blob,
99
+ headers
100
+ }));
101
+ });
102
+ }
103
+ };
134
104
  function canCompress(type, constraints, size) {
135
- // if we have a value of 0, we can compress anything
136
- if (constraints[type] === 0) return true;
137
- if (constraints[type] === -1) return false;
138
- return size >= constraints[type];
105
+ if (constraints[type] === 0) return true;
106
+ if (constraints[type] === -1) return false;
107
+ return size >= constraints[type];
139
108
  }
140
109
  function encodingForFormat(format) {
141
- switch (format) {
142
- case 'gzip':
143
- case 'deflate':
144
- case 'deflate-raw':
145
- return format;
146
- default:
147
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
148
- {
149
- throw new Error(`Unsupported compression format: ${format}`);
150
- }
151
- })() : {};
152
- // @ts-expect-error - unreachable code is reachable in production
153
- return format;
154
- }
110
+ switch (format) {
111
+ case "gzip":
112
+ case "deflate":
113
+ case "deflate-raw": return format;
114
+ default:
115
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
116
+ if (!test) throw new Error(`Unsupported compression format: ${format}`);
117
+ })(false);
118
+ return format;
119
+ }
155
120
  }
156
121
 
122
+ //#endregion
123
+ //#region src/-private/handlers/gated.ts
157
124
  /**
158
- * If CheckFn returns true, the wrapped handler will be used.
159
- * If CheckFn returns false, the wrapped handler will be skipped.
160
- */
161
-
125
+ * If CheckFn returns true, the wrapped handler will be used.
126
+ * If CheckFn returns false, the wrapped handler will be skipped.
127
+ */
162
128
  /**
163
- *
164
- * @group Handlers
165
- * @public
166
- */
167
- class Gate {
168
- constructor(handler, checkFn) {
169
- this.handler = handler;
170
- this.checkFn = checkFn;
171
- }
172
- request(context, next) {
173
- if (this.checkFn(context)) {
174
- return this.handler.request(context, next);
175
- }
176
- return next(context.request);
177
- }
178
- }
129
+ *
130
+ * @group Handlers
131
+ * @public
132
+ */
133
+ var Gate = class {
134
+ /**
135
+ * The wrapped handler to invoke when {@link Gate.checkFn | checkFn} returns `true`.
136
+ */
137
+ /**
138
+ * The predicate used to decide whether {@link Gate.handler | handler} should run for a given request.
139
+ */
140
+ constructor(handler, checkFn) {
141
+ this.handler = handler;
142
+ this.checkFn = checkFn;
143
+ }
144
+ request(context, next) {
145
+ if (this.checkFn(context)) return this.handler.request(context, next);
146
+ return next(context.request);
147
+ }
148
+ };
179
149
 
150
+ //#endregion
151
+ //#region src/-private/handlers/meta-doc.ts
180
152
  /**
181
- * MetaDocHandler processes requests that are marked as meta requests.
182
- *
183
- * It treats the response body as "entirely meta" transforming
184
- *
185
- * ```ts
186
- * {
187
- * some: "key",
188
- * another: "thing"
189
- * }
190
- * ```
191
- *
192
- * into
193
- *
194
- * ```ts
195
- * {
196
- * meta: {
197
- * some: "key",
198
- * another: "thing"
199
- * }
200
- * }
201
- * ```
202
- *
203
- * To activate this handler, a request should specify
204
- *
205
- * ```ts
206
- * options.isMetaRequest = true
207
- * ```
208
- *
209
- * For instance
210
- *
211
- * ```ts
212
- * store.request({
213
- * url: '/example',
214
- * options: {
215
- * isMetaRequest: true
216
- * }
217
- * });
218
- * ```
219
- *
220
- * Errors are not processed by this handler, so if the request fails and the error response
221
- * is not in {json:api} format additional processing may be needed.
222
- *
223
- * @group Handlers
224
- */
225
- const MetaDocHandler = {
226
- request(context, next) {
227
- if (!context.request.options?.isMetaRequest) {
228
- return next(context.request);
229
- }
230
- return next(context.request).then(response => {
231
- return processResponse(response);
232
- });
233
- }
234
- };
153
+ * MetaDocHandler processes requests that are marked as meta requests.
154
+ *
155
+ * It treats the response body as "entirely meta" transforming
156
+ *
157
+ * ```ts
158
+ * {
159
+ * some: "key",
160
+ * another: "thing"
161
+ * }
162
+ * ```
163
+ *
164
+ * into
165
+ *
166
+ * ```ts
167
+ * {
168
+ * meta: {
169
+ * some: "key",
170
+ * another: "thing"
171
+ * }
172
+ * }
173
+ * ```
174
+ *
175
+ * To activate this handler, a request should specify
176
+ *
177
+ * ```ts
178
+ * options.isMetaRequest = true
179
+ * ```
180
+ *
181
+ * For instance
182
+ *
183
+ * ```ts
184
+ * store.request({
185
+ * url: '/example',
186
+ * options: {
187
+ * isMetaRequest: true
188
+ * }
189
+ * });
190
+ * ```
191
+ *
192
+ * Errors are not processed by this handler, so if the request fails and the error response
193
+ * is not in {json:api} format additional processing may be needed.
194
+ *
195
+ * @group Handlers
196
+ */
197
+ const MetaDocHandler = { request(context, next) {
198
+ if (!context.request.options?.isMetaRequest) return next(context.request);
199
+ return next(context.request).then((response) => {
200
+ return processResponse(response);
201
+ });
202
+ } };
235
203
  function processResponse(response) {
236
- return {
237
- meta: response.content
238
- };
204
+ return { meta: response.content };
239
205
  }
240
- if (typeof FastBoot === 'undefined') {
241
- globalThis.addEventListener('beforeunload', function () {
242
- sessionStorage.setItem('tab-closed', 'true');
243
- });
244
- }
245
- function getTabId() {
246
- if (typeof sessionStorage === 'undefined') {
247
- return crypto.randomUUID();
248
- }
249
- const tabId = sessionStorage.getItem('tab-id');
250
- if (tabId) {
251
- const tabClosed = sessionStorage.getItem('tab-closed');
252
- if (tabClosed === 'true') {
253
- return tabId;
254
- }
255
206
 
256
- // fall through to generate a new tab id
257
- }
258
- const newTabId = crypto.randomUUID();
259
- sessionStorage.setItem('tab-id', newTabId);
260
- return newTabId;
207
+ //#endregion
208
+ //#region src/-private/handlers/utils.ts
209
+ if (typeof FastBoot === "undefined") globalThis.addEventListener("beforeunload", function() {
210
+ sessionStorage.setItem("tab-closed", "true");
211
+ });
212
+ function getTabId() {
213
+ if (typeof sessionStorage === "undefined") return crypto.randomUUID();
214
+ const tabId = sessionStorage.getItem("tab-id");
215
+ if (tabId) {
216
+ if (sessionStorage.getItem("tab-closed") === "true") return tabId;
217
+ }
218
+ const newTabId = crypto.randomUUID();
219
+ sessionStorage.setItem("tab-id", newTabId);
220
+ return newTabId;
261
221
  }
262
-
263
222
  /**
264
- * A unique identifier for the current browser tab
265
- * useful for observability/tracing and deduping
266
- * across multiple tabs.
267
- *
268
- * @group Constants
269
- */
223
+ * A unique identifier for the current browser tab
224
+ * useful for observability/tracing and deduping
225
+ * across multiple tabs.
226
+ *
227
+ * @group Constants
228
+ */
270
229
  const TAB_ID = getTabId();
271
230
  /**
272
- * The epoch seconds at which the tab id was generated
273
- *
274
- * @group Constants
275
- */
276
- const TAB_ASSIGNED = Math.floor(Date.now() / 1000);
277
-
231
+ * The epoch seconds at which the tab id was generated
232
+ *
233
+ * @group Constants
234
+ */
235
+ const TAB_ASSIGNED = Math.floor(Date.now() / 1e3);
278
236
  /**
279
- * Adds the `X-Amzn-Trace-Id` header to support observability
280
- * tooling around request routing.
281
- *
282
- * This makes use of the {@link TAB_ID} and {@link TAB_ASSIGNED}
283
- * to enable tracking the browser tab of origin across multiple requests.
284
- *
285
- * Follows the template: `Root=1-${now}-${uuidv4};TabId=1-${epochSeconds}-${tab-uuid}`
286
- *
287
- * @group Utility Functions
288
- */
237
+ * Adds the `X-Amzn-Trace-Id` header to support observability
238
+ * tooling around request routing.
239
+ *
240
+ * This makes use of the {@link TAB_ID} and {@link TAB_ASSIGNED}
241
+ * to enable tracking the browser tab of origin across multiple requests.
242
+ *
243
+ * Follows the template: `Root=1-${now}-${uuidv4};TabId=1-${epochSeconds}-${tab-uuid}`
244
+ *
245
+ * @group Utility Functions
246
+ */
289
247
  function addTraceHeader(headers) {
290
- const now = Math.floor(Date.now() / 1000);
291
- headers.set('X-Amzn-Trace-Id', `Root=1-${now}-${crypto.randomUUID()};TabId=1-${TAB_ASSIGNED}-${TAB_ID}`);
292
- return headers;
248
+ const now = Math.floor(Date.now() / 1e3);
249
+ headers.set("X-Amzn-Trace-Id", `Root=1-${now}-${crypto.randomUUID()};TabId=1-${TAB_ASSIGNED}-${TAB_ID}`);
250
+ return headers;
293
251
  }
294
-
295
252
  /**
296
- * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html
297
- * As of 2024-12-05 the maximum URL length is 8192 bytes.
298
- *
299
- * @group Constants
300
- */
253
+ * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html
254
+ * As of 2024-12-05 the maximum URL length is 8192 bytes.
255
+ *
256
+ * @group Constants
257
+ */
301
258
  const MAX_URL_LENGTH = 8192;
302
-
303
259
  /**
304
- * This assertion takes a URL and throws an error if the URL is longer than the maximum URL length.
305
- *
306
- * See also {@link MAX_URL_LENGTH}
307
- *
308
- * @group Utility Functions
309
- */
260
+ * This assertion takes a URL and throws an error if the URL is longer than the maximum URL length.
261
+ *
262
+ * See also {@link MAX_URL_LENGTH}
263
+ *
264
+ * @group Utility Functions
265
+ */
310
266
  function assertInvalidUrlLength(url) {
311
- macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
312
- if (!test) {
313
- throw new Error(`URL length ${url?.length} exceeds the maximum URL length of ${MAX_URL_LENGTH} bytes.\n\nConsider converting this request query a \`/query\` endpoint instead of a GET, or upgrade the current endpoint to be able to receive a POST request directly (ideally specifying the header HTTP-Method-Override: QUERY)\n\nThe Invalid URL is:\n\n${url}`);
314
- }
315
- })(!url || url.length <= MAX_URL_LENGTH) : {};
267
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) && ((test) => {
268
+ if (!test) throw new Error(`URL length ${url?.length} exceeds the maximum URL length of ${8192} bytes.\n\nConsider converting this request query a \`/query\` endpoint instead of a GET, or upgrade the current endpoint to be able to receive a POST request directly (ideally specifying the header HTTP-Method-Override: QUERY)\n\nThe Invalid URL is:\n\n${url}`);
269
+ })(!url || url.length <= 8192);
316
270
  }
317
- export { AutoCompress, Gate, MAX_URL_LENGTH, MetaDocHandler, SupportsRequestStreams, TAB_ASSIGNED, TAB_ID, addTraceHeader, assertInvalidUrlLength };
271
+
272
+ //#endregion
273
+ export { AutoCompress, Gate, MAX_URL_LENGTH, MetaDocHandler, SupportsRequestStreams, TAB_ASSIGNED, TAB_ID, addTraceHeader, assertInvalidUrlLength };
274
+ //# sourceMappingURL=handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.js","names":["isCompressibleMethod","method","SupportsRequestStreams","duplexAccessed","hasContentType","Request","body","ReadableStream","duplex","headers","has","DEFAULT_CONSTRAINTS","Blob","ArrayBuffer","TypedArray","DataView","String","Object","getPrototypeOf","Uint8Array","AutoCompress","constructor","options","opts","format","constraints","assign","allowStreaming","forceStreaming","request","next","shouldCompress","compress","canCompress","length","size","byteLength","response","Response","stream","pipeThrough","CompressionStream","Headers","set","encodingForFormat","req","resp","blob","then","type","macroCondition","getGlobalConfig","WarpDrive","env","DEBUG","test","Error","Gate","constructor","handler","checkFn","request","context","next","FastBoot","globalThis","addEventListener","sessionStorage","setItem","getTabId","crypto","randomUUID","tabId","getItem","tabClosed","newTabId","TAB_ID","TAB_ASSIGNED","Math","floor","Date","now","addTraceHeader","headers","set","MAX_URL_LENGTH","assertInvalidUrlLength","url","macroCondition","getGlobalConfig","WarpDrive","env","DEBUG","test","Error","length"],"sources":["../src/-private/handlers/auto-compress.ts","../src/-private/handlers/gated.ts","../src/-private/handlers/meta-doc.ts","../src/-private/handlers/utils.ts"],"sourcesContent":["import { assert } from '@warp-drive/core/build-config/macros';\nimport type { Future, Handler, NextFn } from '@warp-drive/core/request';\nimport type { HTTPMethod, RequestContext } from '@warp-drive/core/types/request';\n\nfunction isCompressibleMethod(method?: HTTPMethod): boolean {\n return method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE';\n}\n\n/**\n * Whether the browser supports `ReadableStream` as a request body\n * in a `POST` request.\n *\n * @group Constants\n */\nexport const SupportsRequestStreams: boolean = (() => {\n let duplexAccessed = false;\n\n const hasContentType = new Request('', {\n body: new ReadableStream(),\n method: 'POST',\n // @ts-expect-error untyped\n get duplex() {\n duplexAccessed = true;\n return 'half';\n },\n }).headers.has('Content-Type');\n\n return duplexAccessed && !hasContentType;\n})();\n\ninterface Constraints {\n /**\n * The minimum size at which to compress blobs\n *\n * @default 1000\n */\n Blob?: number;\n /**\n * The minimum size at which to compress array buffers\n *\n * @default 1000\n */\n ArrayBuffer?: number;\n /**\n * The minimum size at which to compress typed arrays\n *\n * @default 1000\n */\n TypedArray?: number;\n /**\n * The minimum size at which to compress data views\n *\n * @default 1000\n */\n DataView?: number;\n /**\n * The minimum size at which to compress strings\n *\n * @default 1000\n */\n String?: number;\n}\n\n/**\n * Options for configuring the AutoCompress handler.\n *\n */\ninterface CompressionOptions {\n /**\n * The compression format to use. Must be a valid\n * compression format supported by [CompressionStream](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream)\n *\n * The default is `gzip`.\n *\n */\n format?: CompressionFormat;\n\n /**\n * Some browsers support `ReadableStream` as a request body. This option\n * enables passing the compression stream as the request body instead of\n * the final compressed body when the browser supports doing so.\n *\n * This comes with several caveats:\n *\n * - the request will be put into `duplex: 'half'` mode. This should be\n * transparent to you, but it is worth noting.\n * - the request mode cannot be `no-cors` as requests with a `ReadableStream`\n * have no content length and thus are a new form of request that triggers\n * cors requirements and a preflight request.\n * - http/1.x is not supported.\n *\n * For additional reading about the restrictions of using `ReadableStream`\n * as a request body, see the [Chromium Documentation](https://developer.chrome.com/docs/capabilities/web-apis/fetch-streaming-requests#restrictions)\n *\n * Streaming can be enabled per-request in browsers which support it by\n * setting `request.options.allowStreaming` to `true`.\n *\n * Streaming can be forced even when the browser does not support it by setting\n * `request.options.forceStreaming` to `true`. This is useful if later handlers\n * in the chain can handle the request body as a stream.\n *\n * @default false\n */\n allowStreaming?: boolean;\n\n /**\n * If `true`, the request will be forced into streaming mode even\n * if the browser does not support it. This is useful if later handlers\n * in the chain can handle the request body as a stream.\n *\n * @default false\n */\n forceStreaming?: boolean;\n\n /**\n * The constraints for the request body. This is used to determine\n * whether to compress the request body or not.\n *\n * The defaults are:\n *\n * ```ts\n * {\n * Blob: 1000, // blob.size\n * ArrayBuffer: 1000, // buffer.byteLength\n * TypedArray: 1000, // array.byteLength\n * DataView: 1000, // view.byteLength\n * String: 1000, // string.length\n * }\n * ```\n *\n * The following body types are never compressed unless explicitly\n * configured by the request:\n * - `FormData`\n * - `URLSearchParams`\n * - `ReadableStream`\n *\n * A request.options.compress value of `false` will disable\n * compression for a request body of any type. While a value of\n * `true` will enable compression for the request.\n *\n * An undefined value will use the default, a value of `0` will\n * enable compression for all values, and a value of `-1` will\n * disable compression.\n *\n */\n constraints?: Constraints;\n}\n\nconst DEFAULT_CONSTRAINTS = {\n Blob: 1000,\n ArrayBuffer: 1000,\n TypedArray: 1000,\n DataView: 1000,\n String: 1000,\n};\nconst TypedArray = Object.getPrototypeOf(Uint8Array) as typeof Uint8Array;\n\n/**\n * A request handler that automatically compresses the request body\n * if the request body is a string, array buffer, blob, or form data.\n *\n * This uses the [CompressionStream API](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream)\n *\n * The compression format as well as the kinds of data to compress can be\n * configured using the `format` and `constraints` options.\n *\n * ```diff\n * +import { AutoCompress } from '@ember-data/request-utils/handlers';\n * import Fetch from '@ember-data/request/fetch';\n * import RequestManager from '@ember-data/request';\n * import Store from '@ember-data/store';\n *\n * class AppStore extends Store {\n * requestManager = new RequestManager()\n * .use([\n * + new AutoCompress(),\n * Fetch\n * ]);\n * }\n * ```\n *\n * @group Handlers\n * @public\n * @since 5.5.0\n */\nexport class AutoCompress implements Handler {\n /**\n * The resolved options this handler was configured with, with all\n * defaults (including `constraints` defaults) applied.\n */\n declare options: Required<CompressionOptions> & {\n /**\n * The resolved size constraints used to decide whether to compress a given request body.\n */\n constraints: Required<Constraints>;\n };\n\n constructor(options: CompressionOptions = {}) {\n const opts = {\n format: options.format ?? 'gzip',\n constraints: Object.assign({}, DEFAULT_CONSTRAINTS, options.constraints),\n allowStreaming: options.allowStreaming ?? false,\n forceStreaming: options.forceStreaming ?? false,\n };\n this.options = opts;\n }\n\n request<T>({ request }: RequestContext, next: NextFn<T>): Promise<T> | Future<T> {\n const { constraints } = this.options;\n const { body } = request;\n\n const shouldCompress =\n !!body &&\n isCompressibleMethod(request.method) &&\n request.options?.compress !== false &&\n // prettier-ignore\n (request.options?.compress ? true\n : typeof body === 'string' || body instanceof String ? canCompress('String', constraints, body.length)\n : body instanceof Blob ? canCompress('Blob', constraints, body.size)\n : body instanceof ArrayBuffer ? canCompress('ArrayBuffer', constraints, body.byteLength)\n : body instanceof DataView ? canCompress('DataView', constraints, body.byteLength)\n : body instanceof TypedArray ? canCompress('TypedArray', constraints, body.byteLength)\n : false);\n\n if (!shouldCompress) return next(request);\n\n // A convenient way to convert all of the supported body types to a readable\n // stream is to use a `Response` object body\n const response = new Response(request.body);\n const stream = response.body?.pipeThrough(new CompressionStream(this.options.format));\n const headers = new Headers(request.headers);\n headers.set('Content-Encoding', encodingForFormat(this.options.format));\n\n //\n // For browsers that support it, `fetch` can receive a `ReadableStream` as\n // the body, so all we need to do is to create a new `ReadableStream` and\n // compress it on the fly\n //\n const forceStreaming = request.options?.forceStreaming ?? this.options.forceStreaming;\n const allowStreaming = request.options?.allowStreaming ?? this.options.allowStreaming;\n if (forceStreaming || (SupportsRequestStreams && allowStreaming)) {\n const req = Object.assign({}, request, {\n body: stream,\n headers,\n });\n if (SupportsRequestStreams) {\n // @ts-expect-error untyped\n req.duplex = 'half';\n }\n\n return next(req);\n\n //\n // For non-chromium browsers, we have to \"pull\" the stream to get the final\n // bytes and supply the final byte array as the new request body.\n //\n }\n\n // we need to pull the stream to get the final bytes\n const resp = new Response(stream);\n return resp.blob().then((blob) => {\n const req = Object.assign({}, request, {\n body: blob,\n headers,\n });\n return next(req);\n }) as Promise<T>;\n }\n}\n\nfunction canCompress(type: keyof Constraints, constraints: Required<Constraints>, size: number): boolean {\n // if we have a value of 0, we can compress anything\n if (constraints[type] === 0) return true;\n if (constraints[type] === -1) return false;\n return size >= constraints[type];\n}\n\nfunction encodingForFormat(format: CompressionFormat): string {\n switch (format) {\n case 'gzip':\n case 'deflate':\n case 'deflate-raw':\n return format;\n default:\n assert(`Unsupported compression format: ${format as unknown as string}`);\n // @ts-expect-error - unreachable code is reachable in production\n return format;\n }\n}\n","import type { Future, Handler, NextFn } from '@warp-drive/core/request';\nimport type { RequestContext, StructuredDataDocument } from '@warp-drive/core/types/request';\n\n/**\n * If CheckFn returns true, the wrapped handler will be used.\n * If CheckFn returns false, the wrapped handler will be skipped.\n */\ntype CheckFn = (context: RequestContext) => boolean;\n\n/**\n *\n * @group Handlers\n * @public\n */\nexport class Gate implements Handler {\n /**\n * The wrapped handler to invoke when {@link Gate.checkFn | checkFn} returns `true`.\n */\n declare handler: Handler;\n /**\n * The predicate used to decide whether {@link Gate.handler | handler} should run for a given request.\n */\n declare checkFn: CheckFn;\n\n constructor(handler: Handler, checkFn: CheckFn) {\n this.handler = handler;\n this.checkFn = checkFn;\n }\n\n request<T = unknown>(context: RequestContext, next: NextFn<T>): Promise<T | StructuredDataDocument<T>> | Future<T> {\n if (this.checkFn(context)) {\n return this.handler.request(context, next);\n }\n return next(context.request);\n }\n}\n","import type { StoreRequestContext } from '@warp-drive/core';\nimport type { Handler, NextFn } from '@warp-drive/core/request';\nimport type { StructuredDataDocument } from '@warp-drive/core/types/request';\n\n/**\n * MetaDocHandler processes requests that are marked as meta requests.\n *\n * It treats the response body as \"entirely meta\" transforming\n *\n * ```ts\n * {\n * some: \"key\",\n * another: \"thing\"\n * }\n * ```\n *\n * into\n *\n * ```ts\n * {\n * \t meta: {\n * some: \"key\",\n * another: \"thing\"\n * }\n * }\n * ```\n *\n * To activate this handler, a request should specify\n *\n * ```ts\n * options.isMetaRequest = true\n * ```\n *\n * For instance\n *\n * ```ts\n * store.request({\n * url: '/example',\n * options: {\n * isMetaRequest: true\n * }\n * });\n * ```\n *\n * Errors are not processed by this handler, so if the request fails and the error response\n * is not in {json:api} format additional processing may be needed.\n *\n * @group Handlers\n */\nexport const MetaDocHandler: Handler = {\n request<T>(context: StoreRequestContext, next: NextFn<T>): Promise<T | StructuredDataDocument<T> | Awaited<T>> {\n if (!context.request.options?.isMetaRequest) {\n return next(context.request);\n }\n\n return next(context.request).then((response) => {\n return processResponse<T>(response);\n });\n },\n};\n\nfunction processResponse<T>(response: StructuredDataDocument<T>): T {\n return {\n meta: response.content,\n } as T;\n}\n","import { assert } from '@warp-drive/core/build-config/macros';\n\nif (typeof FastBoot === 'undefined') {\n globalThis.addEventListener('beforeunload', function () {\n sessionStorage.setItem('tab-closed', 'true');\n });\n}\n\nfunction getTabId() {\n if (typeof sessionStorage === 'undefined') {\n return crypto.randomUUID();\n }\n\n const tabId = sessionStorage.getItem('tab-id');\n if (tabId) {\n const tabClosed = sessionStorage.getItem('tab-closed');\n if (tabClosed === 'true') {\n return tabId;\n }\n\n // fall through to generate a new tab id\n }\n\n const newTabId = crypto.randomUUID();\n sessionStorage.setItem('tab-id', newTabId);\n return newTabId;\n}\n\n/**\n * A unique identifier for the current browser tab\n * useful for observability/tracing and deduping\n * across multiple tabs.\n *\n * @group Constants\n */\nexport const TAB_ID: string = getTabId();\n/**\n * The epoch seconds at which the tab id was generated\n *\n * @group Constants\n */\nexport const TAB_ASSIGNED: number = Math.floor(Date.now() / 1000);\n\n/**\n * Adds the `X-Amzn-Trace-Id` header to support observability\n * tooling around request routing.\n *\n * This makes use of the {@link TAB_ID} and {@link TAB_ASSIGNED}\n * to enable tracking the browser tab of origin across multiple requests.\n *\n * Follows the template: `Root=1-${now}-${uuidv4};TabId=1-${epochSeconds}-${tab-uuid}`\n *\n * @group Utility Functions\n */\nexport function addTraceHeader(headers: Headers): Headers {\n const now = Math.floor(Date.now() / 1000);\n headers.set('X-Amzn-Trace-Id', `Root=1-${now}-${crypto.randomUUID()};TabId=1-${TAB_ASSIGNED}-${TAB_ID}`);\n\n return headers;\n}\n\n/**\n * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html\n * As of 2024-12-05 the maximum URL length is 8192 bytes.\n *\n * @group Constants\n */\nexport const MAX_URL_LENGTH = 8192;\n\n/**\n * This assertion takes a URL and throws an error if the URL is longer than the maximum URL length.\n *\n * See also {@link MAX_URL_LENGTH}\n *\n * @group Utility Functions\n */\nexport function assertInvalidUrlLength(url: string | undefined): void {\n assert(\n `URL length ${url?.length} exceeds the maximum URL length of ${MAX_URL_LENGTH} bytes.\\n\\nConsider converting this request query a \\`/query\\` endpoint instead of a GET, or upgrade the current endpoint to be able to receive a POST request directly (ideally specifying the header HTTP-Method-Override: QUERY)\\n\\nThe Invalid URL is:\\n\\n${url}`,\n !url || url.length <= MAX_URL_LENGTH\n );\n}\n"],"mappings":"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"}