@warp-drive/utilities 5.10.0-alpha.12 → 5.10.0-alpha.14

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 (102) hide show
  1. package/README.md +9 -0
  2. package/cjs-dist/string.cjs +19 -0
  3. package/cjs-dist/string.cjs.map +1 -1
  4. package/dist/active-record.d.ts +21 -0
  5. package/dist/active-record.d.ts.map +1 -1
  6. package/dist/active-record.js +13 -1
  7. package/dist/active-record.js.map +1 -1
  8. package/dist/derivations.d.ts +7 -0
  9. package/dist/derivations.d.ts.map +1 -1
  10. package/dist/derivations.js +6 -0
  11. package/dist/derivations.js.map +1 -1
  12. package/dist/handlers.d.ts +34 -1
  13. package/dist/handlers.d.ts.map +1 -1
  14. package/dist/handlers.js +25 -1
  15. package/dist/handlers.js.map +1 -1
  16. package/dist/{index-D6QIwzqm.d.ts → index-Ds06tKwC.d.ts} +39 -1
  17. package/dist/index-Ds06tKwC.d.ts.map +1 -0
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +39 -0
  20. package/dist/index.js.map +1 -1
  21. package/dist/json-api.d.ts +51 -1
  22. package/dist/json-api.d.ts.map +1 -1
  23. package/dist/json-api.js +37 -1
  24. package/dist/json-api.js.map +1 -1
  25. package/dist/rest.d.ts +20 -0
  26. package/dist/rest.d.ts.map +1 -1
  27. package/dist/rest.js +13 -1
  28. package/dist/rest.js.map +1 -1
  29. package/dist/{string-CWmAluxh.js → string-BZACNuLp.js} +20 -1
  30. package/dist/string-BZACNuLp.js.map +1 -0
  31. package/dist/string.d.ts +33 -0
  32. package/dist/string.d.ts.map +1 -1
  33. package/dist/string.js +1 -1
  34. package/dist/unpkg/dev/active-record.js +13 -1
  35. package/dist/unpkg/dev/active-record.js.map +1 -1
  36. package/dist/unpkg/dev/derivations.js +6 -0
  37. package/dist/unpkg/dev/derivations.js.map +1 -1
  38. package/dist/unpkg/dev/handlers.js +25 -1
  39. package/dist/unpkg/dev/handlers.js.map +1 -1
  40. package/dist/unpkg/dev/index.js +39 -0
  41. package/dist/unpkg/dev/index.js.map +1 -1
  42. package/dist/unpkg/dev/json-api.js +37 -1
  43. package/dist/unpkg/dev/json-api.js.map +1 -1
  44. package/dist/unpkg/dev/rest.js +13 -1
  45. package/dist/unpkg/dev/rest.js.map +1 -1
  46. package/dist/unpkg/dev/{string-j4ur-TDs.js → string-I8KHJXV7.js} +20 -1
  47. package/dist/unpkg/dev/string-I8KHJXV7.js.map +1 -0
  48. package/dist/unpkg/dev/string.js +1 -1
  49. package/dist/unpkg/dev-deprecated/active-record.js +13 -1
  50. package/dist/unpkg/dev-deprecated/active-record.js.map +1 -1
  51. package/dist/unpkg/dev-deprecated/derivations.js +6 -0
  52. package/dist/unpkg/dev-deprecated/derivations.js.map +1 -1
  53. package/dist/unpkg/dev-deprecated/handlers.js +25 -1
  54. package/dist/unpkg/dev-deprecated/handlers.js.map +1 -1
  55. package/dist/unpkg/dev-deprecated/index.js +39 -0
  56. package/dist/unpkg/dev-deprecated/index.js.map +1 -1
  57. package/dist/unpkg/dev-deprecated/json-api.js +37 -1
  58. package/dist/unpkg/dev-deprecated/json-api.js.map +1 -1
  59. package/dist/unpkg/dev-deprecated/rest.js +13 -1
  60. package/dist/unpkg/dev-deprecated/rest.js.map +1 -1
  61. package/dist/unpkg/dev-deprecated/{string-j4ur-TDs.js → string-I8KHJXV7.js} +20 -1
  62. package/dist/unpkg/dev-deprecated/string-I8KHJXV7.js.map +1 -0
  63. package/dist/unpkg/dev-deprecated/string.js +1 -1
  64. package/dist/unpkg/prod/active-record.js +13 -1
  65. package/dist/unpkg/prod/active-record.js.map +1 -1
  66. package/dist/unpkg/prod/derivations.js +6 -0
  67. package/dist/unpkg/prod/derivations.js.map +1 -1
  68. package/dist/unpkg/prod/handlers.js +25 -1
  69. package/dist/unpkg/prod/handlers.js.map +1 -1
  70. package/dist/unpkg/prod/index.js +39 -0
  71. package/dist/unpkg/prod/index.js.map +1 -1
  72. package/dist/unpkg/prod/json-api.js +37 -1
  73. package/dist/unpkg/prod/json-api.js.map +1 -1
  74. package/dist/unpkg/prod/rest.js +13 -1
  75. package/dist/unpkg/prod/rest.js.map +1 -1
  76. package/dist/unpkg/prod/string-D8BEYx2W.js +302 -0
  77. package/dist/unpkg/prod/string-D8BEYx2W.js.map +1 -0
  78. package/dist/unpkg/prod/string.js +1 -1
  79. package/dist/unpkg/prod-deprecated/active-record.js +13 -1
  80. package/dist/unpkg/prod-deprecated/active-record.js.map +1 -1
  81. package/dist/unpkg/prod-deprecated/derivations.js +6 -0
  82. package/dist/unpkg/prod-deprecated/derivations.js.map +1 -1
  83. package/dist/unpkg/prod-deprecated/handlers.js +25 -1
  84. package/dist/unpkg/prod-deprecated/handlers.js.map +1 -1
  85. package/dist/unpkg/prod-deprecated/index.js +39 -0
  86. package/dist/unpkg/prod-deprecated/index.js.map +1 -1
  87. package/dist/unpkg/prod-deprecated/json-api.js +37 -1
  88. package/dist/unpkg/prod-deprecated/json-api.js.map +1 -1
  89. package/dist/unpkg/prod-deprecated/rest.js +13 -1
  90. package/dist/unpkg/prod-deprecated/rest.js.map +1 -1
  91. package/dist/unpkg/prod-deprecated/{string-T1ahjLdj.js → string-D8BEYx2W.js} +20 -1
  92. package/dist/unpkg/prod-deprecated/string-D8BEYx2W.js.map +1 -0
  93. package/dist/unpkg/prod-deprecated/string.js +1 -1
  94. package/logos/README.md +1 -1
  95. package/package.json +6 -6
  96. package/dist/index-D6QIwzqm.d.ts.map +0 -1
  97. package/dist/string-CWmAluxh.js.map +0 -1
  98. package/dist/unpkg/dev/string-j4ur-TDs.js.map +0 -1
  99. package/dist/unpkg/dev-deprecated/string-j4ur-TDs.js.map +0 -1
  100. package/dist/unpkg/prod/string-T1ahjLdj.js +0 -283
  101. package/dist/unpkg/prod/string-T1ahjLdj.js.map +0 -1
  102. package/dist/unpkg/prod-deprecated/string-T1ahjLdj.js.map +0 -1
@@ -1,3 +1,11 @@
1
+ /**
2
+ * A selection of pre-built request handlers for handling common
3
+ * request scenarios.
4
+ *
5
+ * @summary Ready-made request handlers for body compression, conditional handling, and meta-only responses, plus
6
+ * tracing helpers.
7
+ * @module
8
+ */
1
9
  import { RequestContext, StructuredDataDocument } from "@warp-drive/core/types/request";
2
10
  import { Future, Handler, NextFn } from "@warp-drive/core/request";
3
11
  //#region src/-private/handlers/auto-compress.d.ts
@@ -5,9 +13,18 @@ import { Future, Handler, NextFn } from "@warp-drive/core/request";
5
13
  * Whether the browser supports `ReadableStream` as a request body
6
14
  * in a `POST` request.
7
15
  *
16
+ * @summary Whether the current browser can send a `ReadableStream` as a `fetch` request body, detected once at
17
+ * module load.
8
18
  * @group Constants
9
19
  */
10
20
  export declare const SupportsRequestStreams: boolean;
21
+ /**
22
+ * The minimum body size, per body type, at which {@link AutoCompress} compresses a request
23
+ * body. Passed as {@link CompressionOptions.constraints}.
24
+ *
25
+ * @summary Minimum request body sizes, per body type, at which `AutoCompress` compresses a body.
26
+ * @public
27
+ */
11
28
  interface Constraints {
12
29
  /**
13
30
  * The minimum size at which to compress blobs
@@ -41,8 +58,10 @@ interface Constraints {
41
58
  String?: number;
42
59
  }
43
60
  /**
44
- * Options for configuring the AutoCompress handler.
61
+ * Options for configuring the {@link AutoCompress} handler.
45
62
  *
63
+ * @summary Options for `new AutoCompress()`: the compression format, size constraints and whether to stream the body.
64
+ * @public
46
65
  */
47
66
  interface CompressionOptions {
48
67
  /**
@@ -145,6 +164,8 @@ interface CompressionOptions {
145
164
  * }
146
165
  * ```
147
166
  *
167
+ * @summary Request handler that compresses large `POST`, `PUT`, `PATCH`, and `DELETE` bodies with `CompressionStream`,
168
+ * optionally streaming them.
148
169
  * @group Handlers
149
170
  * @public
150
171
  * @since 5.5.0
@@ -172,6 +193,8 @@ export declare class AutoCompress implements Handler {
172
193
  type CheckFn = (context: RequestContext) => boolean;
173
194
  /**
174
195
  *
196
+ * @summary Request handler that wraps another handler and runs it only when a check function returns true for the
197
+ * request.
175
198
  * @group Handlers
176
199
  * @public
177
200
  */
@@ -232,6 +255,7 @@ export declare class Gate implements Handler {
232
255
  * Errors are not processed by this handler, so if the request fails and the error response
233
256
  * is not in {json:api} format additional processing may be needed.
234
257
  *
258
+ * @summary Request handler that wraps the whole response body in `meta` for requests with `options.isMetaRequest` set.
235
259
  * @group Handlers
236
260
  */
237
261
  export declare const MetaDocHandler: Handler;
@@ -242,12 +266,15 @@ export declare const MetaDocHandler: Handler;
242
266
  * useful for observability/tracing and deduping
243
267
  * across multiple tabs.
244
268
  *
269
+ * @summary Random UUID identifying the current browser tab, kept in `sessionStorage` across reloads, for request
270
+ * tracing.
245
271
  * @group Constants
246
272
  */
247
273
  export declare const TAB_ID: string;
248
274
  /**
249
275
  * The epoch seconds at which the tab id was generated
250
276
  *
277
+ * @summary Epoch seconds recorded when this module loaded, paired with `TAB_ID` in trace headers.
251
278
  * @group Constants
252
279
  */
253
280
  export declare const TAB_ASSIGNED: number;
@@ -260,6 +287,8 @@ export declare const TAB_ASSIGNED: number;
260
287
  *
261
288
  * Follows the template: `Root=1-${now}-${uuidv4};TabId=1-${epochSeconds}-${tab-uuid}`
262
289
  *
290
+ * @summary Sets an `X-Amzn-Trace-Id` header carrying a per-request id and the tab id, so requests can be traced to
291
+ * their browser tab.
263
292
  * @group Utility Functions
264
293
  */
265
294
  export declare function addTraceHeader(headers: Headers): Headers;
@@ -267,6 +296,7 @@ export declare function addTraceHeader(headers: Headers): Headers;
267
296
  * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html
268
297
  * As of 2024-12-05 the maximum URL length is 8192 bytes.
269
298
  *
299
+ * @summary The 8192-byte URL length limit, taken from AWS CloudFront, that `assertInvalidUrlLength` checks against.
270
300
  * @group Constants
271
301
  */
272
302
  export declare const MAX_URL_LENGTH = 8192;
@@ -275,8 +305,11 @@ export declare const MAX_URL_LENGTH = 8192;
275
305
  *
276
306
  * See also {@link MAX_URL_LENGTH}
277
307
  *
308
+ * @summary Dev-mode assertion that throws when a URL is longer than `MAX_URL_LENGTH`, suggesting a `POST` or `QUERY`
309
+ * request instead.
278
310
  * @group Utility Functions
279
311
  */
280
312
  export declare function assertInvalidUrlLength(url: string | undefined): void;
281
313
  //#endregion
314
+ export type { CompressionOptions, Constraints };
282
315
  //# sourceMappingURL=handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.d.ts","names":[],"sources":["../src/-private/handlers/auto-compress.ts","../src/-private/handlers/gated.ts","../src/-private/handlers/meta-doc.ts","../src/-private/handlers/utils.ts"],"mappings":";;;;;;;;;qBAca;UAgBH;;;;;;EAMR;;;;;;EAMA;;;;;;EAMA;;;;;;EAMA;;;;;;EAMA;;;;;;UAOQ;;;;;;;;EAQR,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BT;;;;;;;;EASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAwCH,wBAAwB;;;;;EAKnC,SAAiB,SAAS;;;;IAIxB,aAAa,SAAS;;EAGxB,YAAY,UAAS;EAUrB,QAAQ,KAAK,WAAW,gBAAgB,MAAM,OAAO,KAAK,QAAQ,KAAK,OAAO;;;;;;;;KCxM3E,WAAW,SAAS;;;;;;qBAOZ,gBAAgB;;;;EAI3B,SAAiB;;;;EAIjB,SAAiB;EAEjB,YAAY,SAAS,SAAS,SAAS;EAKvC,QAAQ,aAAa,SAAS,gBAAgB,MAAM,OAAO,KAAK,QAAQ,IAAI,uBAAuB,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCoBrG,gBAAgB;;;;;;;;;;qBCdhB;;;;;;qBAMA;;;;;;;;;;;;wBAaG,eAAe,SAAS,UAAU;;;;;;;qBAarC;;;;;;;;wBASG,uBAAuB"}
1
+ {"version":3,"file":"handlers.d.ts","names":[],"sources":["../src/-private/handlers/auto-compress.ts","../src/-private/handlers/gated.ts","../src/-private/handlers/meta-doc.ts","../src/-private/handlers/utils.ts"],"mappings":";;;;;;;;;;;;;;;;;;;qBAgBa;;;;;;;;UAuBI;;;;;;EAMf;;;;;;EAMA;;;;;;EAMA;;;;;;EAMA;;;;;;EAMA;;;;;;;;UASe;;;;;;;;EAQf,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BT;;;;;;;;EASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCA,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA0CH,wBAAwB;;;;;EAKnC,SAAiB,SAAS;;;;IAIxB,aAAa,SAAS;;EAGxB,YAAY,UAAS;EAUrB,QAAQ,KAAK,WAAW,gBAAgB,MAAM,OAAO,KAAK,QAAQ,KAAK,OAAO;;;;;;;;KCrN3E,WAAW,SAAS;;;;;;;;qBASZ,gBAAgB;;;;EAI3B,SAAiB;;;;EAIjB,SAAiB;EAEjB,YAAY,SAAS,SAAS,SAAS;EAKvC,QAAQ,aAAa,SAAS,gBAAgB,MAAM,OAAO,KAAK,QAAQ,IAAI,uBAAuB,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCmBrG,gBAAgB;;;;;;;;;;;;qBCbhB;;;;;;;qBAOA;;;;;;;;;;;;;;wBAeG,eAAe,SAAS,UAAU;;;;;;;;qBAcrC;;;;;;;;;;wBAWG,uBAAuB"}
package/dist/handlers.js CHANGED
@@ -8,6 +8,8 @@ function isCompressibleMethod(method) {
8
8
  * Whether the browser supports `ReadableStream` as a request body
9
9
  * in a `POST` request.
10
10
  *
11
+ * @summary Whether the current browser can send a `ReadableStream` as a `fetch` request body, detected once at
12
+ * module load.
11
13
  * @group Constants
12
14
  */
13
15
  const SupportsRequestStreams = (() => {
@@ -23,8 +25,17 @@ const SupportsRequestStreams = (() => {
23
25
  return duplexAccessed && !hasContentType;
24
26
  })();
25
27
  /**
26
- * Options for configuring the AutoCompress handler.
28
+ * The minimum body size, per body type, at which {@link AutoCompress} compresses a request
29
+ * body. Passed as {@link CompressionOptions.constraints}.
27
30
  *
31
+ * @summary Minimum request body sizes, per body type, at which `AutoCompress` compresses a body.
32
+ * @public
33
+ */
34
+ /**
35
+ * Options for configuring the {@link AutoCompress} handler.
36
+ *
37
+ * @summary Options for `new AutoCompress()`: the compression format, size constraints and whether to stream the body.
38
+ * @public
28
39
  */
29
40
  const DEFAULT_CONSTRAINTS = {
30
41
  Blob: 1e3,
@@ -58,6 +69,8 @@ const TypedArray = Object.getPrototypeOf(Uint8Array);
58
69
  * }
59
70
  * ```
60
71
  *
72
+ * @summary Request handler that compresses large `POST`, `PUT`, `PATCH`, and `DELETE` bodies with `CompressionStream`,
73
+ * optionally streaming them.
61
74
  * @group Handlers
62
75
  * @public
63
76
  * @since 5.5.0
@@ -127,6 +140,8 @@ function encodingForFormat(format) {
127
140
  */
128
141
  /**
129
142
  *
143
+ * @summary Request handler that wraps another handler and runs it only when a check function returns true for the
144
+ * request.
130
145
  * @group Handlers
131
146
  * @public
132
147
  */
@@ -192,6 +207,7 @@ var Gate = class {
192
207
  * Errors are not processed by this handler, so if the request fails and the error response
193
208
  * is not in {json:api} format additional processing may be needed.
194
209
  *
210
+ * @summary Request handler that wraps the whole response body in `meta` for requests with `options.isMetaRequest` set.
195
211
  * @group Handlers
196
212
  */
197
213
  const MetaDocHandler = { request(context, next) {
@@ -224,12 +240,15 @@ function getTabId() {
224
240
  * useful for observability/tracing and deduping
225
241
  * across multiple tabs.
226
242
  *
243
+ * @summary Random UUID identifying the current browser tab, kept in `sessionStorage` across reloads, for request
244
+ * tracing.
227
245
  * @group Constants
228
246
  */
229
247
  const TAB_ID = getTabId();
230
248
  /**
231
249
  * The epoch seconds at which the tab id was generated
232
250
  *
251
+ * @summary Epoch seconds recorded when this module loaded, paired with `TAB_ID` in trace headers.
233
252
  * @group Constants
234
253
  */
235
254
  const TAB_ASSIGNED = Math.floor(Date.now() / 1e3);
@@ -242,6 +261,8 @@ const TAB_ASSIGNED = Math.floor(Date.now() / 1e3);
242
261
  *
243
262
  * Follows the template: `Root=1-${now}-${uuidv4};TabId=1-${epochSeconds}-${tab-uuid}`
244
263
  *
264
+ * @summary Sets an `X-Amzn-Trace-Id` header carrying a per-request id and the tab id, so requests can be traced to
265
+ * their browser tab.
245
266
  * @group Utility Functions
246
267
  */
247
268
  function addTraceHeader(headers) {
@@ -253,6 +274,7 @@ function addTraceHeader(headers) {
253
274
  * Source: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html
254
275
  * As of 2024-12-05 the maximum URL length is 8192 bytes.
255
276
  *
277
+ * @summary The 8192-byte URL length limit, taken from AWS CloudFront, that `assertInvalidUrlLength` checks against.
256
278
  * @group Constants
257
279
  */
258
280
  const MAX_URL_LENGTH = 8192;
@@ -261,6 +283,8 @@ const MAX_URL_LENGTH = 8192;
261
283
  *
262
284
  * See also {@link MAX_URL_LENGTH}
263
285
  *
286
+ * @summary Dev-mode assertion that throws when a URL is longer than `MAX_URL_LENGTH`, suggesting a `POST` or `QUERY`
287
+ * request instead.
264
288
  * @group Utility Functions
265
289
  */
266
290
  function assertInvalidUrlLength(url) {
@@ -1 +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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"}
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 * @summary Whether the current browser can send a `ReadableStream` as a `fetch` request body, detected once at\n * module load.\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\n/**\n * The minimum body size, per body type, at which {@link AutoCompress} compresses a request\n * body. Passed as {@link CompressionOptions.constraints}.\n *\n * @summary Minimum request body sizes, per body type, at which `AutoCompress` compresses a body.\n * @public\n */\nexport interface 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 {@link AutoCompress} handler.\n *\n * @summary Options for `new AutoCompress()`: the compression format, size constraints and whether to stream the body.\n * @public\n */\nexport interface 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 * @summary Request handler that compresses large `POST`, `PUT`, `PATCH`, and `DELETE` bodies with `CompressionStream`,\n * optionally streaming them.\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 * @summary Request handler that wraps another handler and runs it only when a check function returns true for the\n * request.\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 * @summary Request handler that wraps the whole response body in `meta` for requests with `options.isMetaRequest` set.\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 * @summary Random UUID identifying the current browser tab, kept in `sessionStorage` across reloads, for request\n * tracing.\n * @group Constants\n */\nexport const TAB_ID: string = getTabId();\n/**\n * The epoch seconds at which the tab id was generated\n *\n * @summary Epoch seconds recorded when this module loaded, paired with `TAB_ID` in trace headers.\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 * @summary Sets an `X-Amzn-Trace-Id` header carrying a per-request id and the tab id, so requests can be traced to\n * their browser tab.\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 * @summary The 8192-byte URL length limit, taken from AWS CloudFront, that `assertInvalidUrlLength` checks against.\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 * @summary Dev-mode assertion that throws when a URL is longer than `MAX_URL_LENGTH`, suggesting a `POST` or `QUERY`\n * request instead.\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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"}
@@ -4,6 +4,7 @@ import { QueryParamsSerializationOptions, QueryParamsSource, Serializable } from
4
4
  * The global configuration used by {@link buildBaseURL} when a call does
5
5
  * not provide its own `host`/`namespace`. Set via {@link setBuildURLConfig}.
6
6
  *
7
+ * @summary The global `host` and `namespace` that `buildBaseURL` prefixes onto URLs when a call does not pass its own.
7
8
  * @public
8
9
  */
9
10
  interface BuildURLConfig {
@@ -23,6 +24,10 @@ interface BuildURLConfig {
23
24
  * These values may still be overridden by passing
24
25
  * them to buildBaseURL directly.
25
26
  *
27
+ * The [Basic Usage](/guides/the-manual/cookbook/basic-usage#step-2-configure-some-request-defaults)
28
+ * guide sets these defaults through the `@warp-drive/utilities/json-api` version of this function,
29
+ * which also sets this global configuration.
30
+ *
26
31
  * This method may be called as many times as needed.
27
32
  * host values of `''` or `'/'` are equivalent.
28
33
  *
@@ -49,12 +54,14 @@ interface BuildURLConfig {
49
54
  * });
50
55
  * ```
51
56
  *
57
+ * @summary Sets the app-wide default `host` and `namespace` used by `buildBaseURL` and the request builders.
52
58
  * @public
53
59
  */
54
60
  declare function setBuildURLConfig(config: BuildURLConfig): void;
55
61
  /**
56
62
  * {@link buildBaseURL} options for a `findRecord` request.
57
63
  *
64
+ * @summary Options passed to `buildBaseURL` to build the URL for fetching one resource by type and id.
58
65
  * @public
59
66
  */
60
67
  interface FindRecordUrlOptions {
@@ -91,6 +98,7 @@ interface FindRecordUrlOptions {
91
98
  /**
92
99
  * {@link buildBaseURL} options for a `query` request.
93
100
  *
101
+ * @summary Options passed to `buildBaseURL` to build the URL for querying a collection of one resource type.
94
102
  * @public
95
103
  */
96
104
  interface QueryUrlOptions {
@@ -123,6 +131,8 @@ interface QueryUrlOptions {
123
131
  /**
124
132
  * {@link buildBaseURL} options for a `findMany` request.
125
133
  *
134
+ * @summary Options passed to `buildBaseURL` to build the URL for fetching several resources, pathed by the first
135
+ * identifier's type.
126
136
  * @public
127
137
  */
128
138
  interface FindManyUrlOptions {
@@ -159,6 +169,8 @@ interface FindManyUrlOptions {
159
169
  /**
160
170
  * {@link buildBaseURL} options for a `findRelatedCollection` request.
161
171
  *
172
+ * @summary Options passed to `buildBaseURL` to build the URL for a record's has-many relationship, ending in the
173
+ * field name.
162
174
  * @public
163
175
  */
164
176
  interface FindRelatedCollectionUrlOptions {
@@ -199,6 +211,8 @@ interface FindRelatedCollectionUrlOptions {
199
211
  /**
200
212
  * {@link buildBaseURL} options for a `findRelatedRecord` request.
201
213
  *
214
+ * @summary Options passed to `buildBaseURL` to build the URL for a record's belongs-to relationship, ending in the
215
+ * field name.
202
216
  * @public
203
217
  */
204
218
  interface FindRelatedResourceUrlOptions {
@@ -239,6 +253,7 @@ interface FindRelatedResourceUrlOptions {
239
253
  /**
240
254
  * {@link buildBaseURL} options for a `createRecord` request.
241
255
  *
256
+ * @summary Options passed to `buildBaseURL` to build the collection URL a new record of a given type is saved to.
242
257
  * @public
243
258
  */
244
259
  interface CreateRecordUrlOptions {
@@ -271,6 +286,7 @@ interface CreateRecordUrlOptions {
271
286
  /**
272
287
  * {@link buildBaseURL} options for an `updateRecord` request.
273
288
  *
289
+ * @summary Options passed to `buildBaseURL` to build the URL for saving changes to an existing record by type and id.
274
290
  * @public
275
291
  */
276
292
  interface UpdateRecordUrlOptions {
@@ -307,6 +323,7 @@ interface UpdateRecordUrlOptions {
307
323
  /**
308
324
  * {@link buildBaseURL} options for a `deleteRecord` request.
309
325
  *
326
+ * @summary Options passed to `buildBaseURL` to build the URL for deleting an existing record by type and id.
310
327
  * @public
311
328
  */
312
329
  interface DeleteRecordUrlOptions {
@@ -344,6 +361,7 @@ interface DeleteRecordUrlOptions {
344
361
  * {@link buildBaseURL} options for building a URL directly from a `resourcePath`
345
362
  * without an associated request operation.
346
363
  *
364
+ * @summary Options passed to `buildBaseURL` to build a URL from an explicit `resourcePath` with no request `op`.
347
365
  * @public
348
366
  */
349
367
  interface GenericUrlOptions {
@@ -373,6 +391,7 @@ interface GenericUrlOptions {
373
391
  * - {@link DeleteRecordUrlOptions}
374
392
  * - {@link GenericUrlOptions}
375
393
  *
394
+ * @summary Any of the option shapes `buildBaseURL` accepts, one per request `op` plus a generic `resourcePath` form.
376
395
  * @public
377
396
  */
378
397
  type UrlOptions = FindRecordUrlOptions | QueryUrlOptions | FindManyUrlOptions | FindRelatedCollectionUrlOptions | FindRelatedResourceUrlOptions | CreateRecordUrlOptions | UpdateRecordUrlOptions | DeleteRecordUrlOptions | GenericUrlOptions;
@@ -381,6 +400,9 @@ type UrlOptions = FindRecordUrlOptions | QueryUrlOptions | FindManyUrlOptions |
381
400
  * Does not include support for building query params (see `buildQueryParams`)
382
401
  * so that it may be composed cleanly with other query-params strategies.
383
402
  *
403
+ * See the [Builders](/guides/the-manual/requests/builders) guide for writing your own request
404
+ * builders.
405
+ *
384
406
  * Usage:
385
407
  *
386
408
  * ```ts
@@ -410,6 +432,7 @@ type UrlOptions = FindRecordUrlOptions | QueryUrlOptions | FindManyUrlOptions |
410
432
  * - 'findRecord' 'query' 'findMany' 'findRelatedCollection' 'findRelatedRecord'` 'createRecord' 'updateRecord' 'deleteRecord'
411
433
  * - Depending on the value of `op`, `identifier` or `identifiers` will be required.
412
434
  *
435
+ * @summary Joins host, namespace, resource path, id, and relationship field into a request URL without query params.
413
436
  * @public
414
437
  */
415
438
  declare function buildBaseURL(urlOptions: UrlOptions): string;
@@ -417,6 +440,11 @@ declare function buildBaseURL(urlOptions: UrlOptions): string;
417
440
  * filter out keys of an object that have falsy values or point to empty arrays
418
441
  * returning a new object with only those keys that have truthy values / non-empty arrays
419
442
  *
443
+ * See [Cache Keys for Requests](/guides/the-manual/requests/builders#cache-keys-for-requests) for
444
+ * why builders need stable query params.
445
+ *
446
+ * @summary Returns a copy of an object without keys whose values are `undefined`, `null`, empty strings, or empty
447
+ * arrays.
420
448
  * @public
421
449
  * @param source object to filter keys with empty values from
422
450
  * @return A new object with the keys that contained empty values removed
@@ -426,6 +454,9 @@ declare function filterEmpty(source: Record<string, Serializable>): Record<strin
426
454
  * Sorts query params by both key and value returning a new URLSearchParams
427
455
  * object with the keys inserted in sorted order.
428
456
  *
457
+ * See [Cache Keys for Requests](/guides/the-manual/requests/builders#cache-keys-for-requests) for
458
+ * why builders need stable query params.
459
+ *
429
460
  * Treats `included` specially, splicing it into an array if it is a string and sorting the array.
430
461
  *
431
462
  * The `params` given are never mutated: neither the object itself nor any array
@@ -440,6 +471,8 @@ declare function filterEmpty(source: Record<string, Serializable>): Record<strin
440
471
  * 'repeat': appends the key for every value e.g. `&ids=1&ids=2`
441
472
  * 'comma' (default): appends the key once with a comma separated list of values e.g. `&ids=1,2`
442
473
  *
474
+ * @summary Builds a `URLSearchParams` with keys and array values sorted, so equivalent queries produce identical
475
+ * params.
443
476
  * @public
444
477
  * @return A {@link URLSearchParams} with keys inserted in sorted order
445
478
  */
@@ -447,6 +480,9 @@ declare function sortQueryParams(params: QueryParamsSource, options?: QueryParam
447
480
  /**
448
481
  * Sorts query params by both key and value, returning a query params string
449
482
  *
483
+ * See [Cache Keys for Requests](/guides/the-manual/requests/builders#cache-keys-for-requests) for
484
+ * why builders need stable query params.
485
+ *
450
486
  * Treats `included` specially, splicing it into an array if it is a string and sorting the array.
451
487
  *
452
488
  * The `params` given are never mutated: neither the object itself nor any array
@@ -461,10 +497,12 @@ declare function sortQueryParams(params: QueryParamsSource, options?: QueryParam
461
497
  * 'repeat': appends the key for every value e.g. `ids=1&ids=2`
462
498
  * 'comma' (default): appends the key once with a comma separated list of values e.g. `ids=1,2`
463
499
  *
500
+ * @summary Serializes query params into a string with keys and array values sorted, so equivalent queries share one
501
+ * URL.
464
502
  * @public
465
503
  * @return A sorted query params string without the leading `?`
466
504
  */
467
505
  declare function buildQueryParams(params: QueryParamsSource, options?: QueryParamsSerializationOptions): string;
468
506
  //#endregion
469
507
  export { FindRecordUrlOptions as a, GenericUrlOptions as c, UrlOptions as d, buildBaseURL as f, sortQueryParams as g, setBuildURLConfig as h, FindManyUrlOptions as i, QueryUrlOptions as l, filterEmpty as m, CreateRecordUrlOptions as n, FindRelatedCollectionUrlOptions as o, buildQueryParams as p, DeleteRecordUrlOptions as r, FindRelatedResourceUrlOptions as s, BuildURLConfig as t, UpdateRecordUrlOptions as u };
470
- //# sourceMappingURL=index-D6QIwzqm.d.ts.map
508
+ //# sourceMappingURL=index-Ds06tKwC.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-Ds06tKwC.d.ts","names":[],"sources":["../src/index.ts"],"mappings":";;;;;;;;;UAqBiB;;;;EAIf;;;;EAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgDc,kBAAkB,QAAQ;;;;;;;UA8BzB;;;;EAIf;;;;EAIA;;;;IAIE;;;;IAIA;;;;;EAKF;;;;EAIA;;;;EAIA;;;;;;;;UASe;;;;EAIf;;;;EAIA;;;;IAIE;;;;;EAKF;;;;EAIA;;;;EAIA;;;;;;;;;UAUe;;;;EAIf;;;;EAIA;;;;IAIE;;;;IAIA;;;;;EAKF;;;;EAIA;;;;EAIA;;;;;;;;;UASe;;;;EAIf;;;;EAIA;;;;IAIE;;;;IAIA;;;;;EAKF;;;;EAIA;;;;EAIA;;;;EAIA;;;;;;;;;UAUe;;;;EAIf;;;;EAIA;;;;IAIE;;;;IAIA;;;;;EAKF;;;;EAIA;;;;EAIA;;;;EAIA;;;;;;;;UASe;;;;EAIf;;;;EAIA;;;;IAIE;;;;;EAKF;;;;EAIA;;;;EAIA;;;;;;;;UASe;;;;EAIf;;;;EAIA;;;;IAIE;;;;IAIA;;;;;EAKF;;;;EAIA;;;;EAIA;;;;;;;;UASe;;;;EAIf;;;;EAIA;;;;IAIE;;;;IAIA;;;;;EAKF;;;;EAIA;;;;EAIA;;;;;;;;;UAUe;;;;EAIf;;;;EAIA;;;;EAIA;;;;;;;;;;;;;;;;;;KAmBU,aACR,uBACA,kBACA,qBACA,kCACA,gCACA,yBACA,yBACA,yBACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyEY,aAAa,YAAY;;;;;;;;;;;;;;iBAiIzB,YAAY,QAAQ,eAAe,gBAAgB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwClE,gBAAgB,QAAQ,mBAAmB,UAAU,kCAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwFvF,iBAAiB,QAAQ,mBAAmB,UAAU"}
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as FindRecordUrlOptions, c as GenericUrlOptions, d as UrlOptions, f as buildBaseURL, g as sortQueryParams, h as setBuildURLConfig, i as FindManyUrlOptions, l as QueryUrlOptions, m as filterEmpty, n as CreateRecordUrlOptions, o as FindRelatedCollectionUrlOptions, p as buildQueryParams, r as DeleteRecordUrlOptions, s as FindRelatedResourceUrlOptions, t as BuildURLConfig, u as UpdateRecordUrlOptions } from "./index-D6QIwzqm.js";
1
+ import { a as FindRecordUrlOptions, c as GenericUrlOptions, d as UrlOptions, f as buildBaseURL, g as sortQueryParams, h as setBuildURLConfig, i as FindManyUrlOptions, l as QueryUrlOptions, m as filterEmpty, n as CreateRecordUrlOptions, o as FindRelatedCollectionUrlOptions, p as buildQueryParams, r as DeleteRecordUrlOptions, s as FindRelatedResourceUrlOptions, t as BuildURLConfig, u as UpdateRecordUrlOptions } from "./index-Ds06tKwC.js";
2
2
  export { BuildURLConfig, CreateRecordUrlOptions, DeleteRecordUrlOptions, FindManyUrlOptions, FindRecordUrlOptions, FindRelatedCollectionUrlOptions, FindRelatedResourceUrlOptions, GenericUrlOptions, QueryUrlOptions, UpdateRecordUrlOptions, UrlOptions, buildBaseURL, buildQueryParams, filterEmpty, setBuildURLConfig, sortQueryParams };