@warp-drive/utilities 5.6.0-alpha.11

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 (87) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +23 -0
  3. package/README.md +54 -0
  4. package/addon-main.cjs +5 -0
  5. package/declarations/-private/active-record/find-record.d.ts +66 -0
  6. package/declarations/-private/active-record/find-record.d.ts.map +1 -0
  7. package/declarations/-private/active-record/query.d.ts +54 -0
  8. package/declarations/-private/active-record/query.d.ts.map +1 -0
  9. package/declarations/-private/active-record/save-record.d.ts +144 -0
  10. package/declarations/-private/active-record/save-record.d.ts.map +1 -0
  11. package/declarations/-private/builder-utils.d.ts +5 -0
  12. package/declarations/-private/builder-utils.d.ts.map +1 -0
  13. package/declarations/-private/handlers/auto-compress.d.ts +153 -0
  14. package/declarations/-private/handlers/auto-compress.d.ts.map +1 -0
  15. package/declarations/-private/json-api/-utils.d.ts +110 -0
  16. package/declarations/-private/json-api/-utils.d.ts.map +1 -0
  17. package/declarations/-private/json-api/find-record.d.ts +66 -0
  18. package/declarations/-private/json-api/find-record.d.ts.map +1 -0
  19. package/declarations/-private/json-api/find-record.type-test.d.ts +2 -0
  20. package/declarations/-private/json-api/find-record.type-test.d.ts.map +1 -0
  21. package/declarations/-private/json-api/query.d.ts +104 -0
  22. package/declarations/-private/json-api/query.d.ts.map +1 -0
  23. package/declarations/-private/json-api/query.type-test.d.ts +2 -0
  24. package/declarations/-private/json-api/query.type-test.d.ts.map +1 -0
  25. package/declarations/-private/json-api/save-record.d.ts +191 -0
  26. package/declarations/-private/json-api/save-record.d.ts.map +1 -0
  27. package/declarations/-private/json-api/serialize.d.ts +57 -0
  28. package/declarations/-private/json-api/serialize.d.ts.map +1 -0
  29. package/declarations/-private/rest/find-record.d.ts +66 -0
  30. package/declarations/-private/rest/find-record.d.ts.map +1 -0
  31. package/declarations/-private/rest/query.d.ts +54 -0
  32. package/declarations/-private/rest/query.d.ts.map +1 -0
  33. package/declarations/-private/rest/save-record.d.ts +144 -0
  34. package/declarations/-private/rest/save-record.d.ts.map +1 -0
  35. package/declarations/-private/string/inflect.d.ts +105 -0
  36. package/declarations/-private/string/inflect.d.ts.map +1 -0
  37. package/declarations/-private/string/inflections.d.ts +10 -0
  38. package/declarations/-private/string/inflections.d.ts.map +1 -0
  39. package/declarations/-private/string/transform.d.ts +89 -0
  40. package/declarations/-private/string/transform.d.ts.map +1 -0
  41. package/declarations/-private.d.ts +2 -0
  42. package/declarations/-private.d.ts.map +1 -0
  43. package/declarations/active-record.d.ts +71 -0
  44. package/declarations/active-record.d.ts.map +1 -0
  45. package/declarations/handlers.d.ts +8 -0
  46. package/declarations/handlers.d.ts.map +1 -0
  47. package/declarations/index.d.ts +255 -0
  48. package/declarations/index.d.ts.map +1 -0
  49. package/declarations/json-api.d.ts +51 -0
  50. package/declarations/json-api.d.ts.map +1 -0
  51. package/declarations/rest.d.ts +51 -0
  52. package/declarations/rest.d.ts.map +1 -0
  53. package/declarations/string.d.ts +14 -0
  54. package/declarations/string.d.ts.map +1 -0
  55. package/dist/-private.js +7 -0
  56. package/dist/-private.js.map +1 -0
  57. package/dist/active-record.js +393 -0
  58. package/dist/active-record.js.map +1 -0
  59. package/dist/builder-utils-Donkk-BZ.js +22 -0
  60. package/dist/builder-utils-Donkk-BZ.js.map +1 -0
  61. package/dist/handlers.js +141 -0
  62. package/dist/handlers.js.map +1 -0
  63. package/dist/index.js +403 -0
  64. package/dist/index.js.map +1 -0
  65. package/dist/inflect-C1laviCe.js +376 -0
  66. package/dist/inflect-C1laviCe.js.map +1 -0
  67. package/dist/json-api.js +671 -0
  68. package/dist/json-api.js.map +1 -0
  69. package/dist/rest.js +393 -0
  70. package/dist/rest.js.map +1 -0
  71. package/dist/string.js +1 -0
  72. package/dist/string.js.map +1 -0
  73. package/logos/NCC-1701-a-blue.svg +4 -0
  74. package/logos/NCC-1701-a-gold.svg +4 -0
  75. package/logos/NCC-1701-a-gold_100.svg +1 -0
  76. package/logos/NCC-1701-a-gold_base-64.txt +1 -0
  77. package/logos/NCC-1701-a.svg +4 -0
  78. package/logos/README.md +4 -0
  79. package/logos/docs-badge.svg +2 -0
  80. package/logos/ember-data-logo-dark.svg +12 -0
  81. package/logos/ember-data-logo-light.svg +12 -0
  82. package/logos/github-header.svg +444 -0
  83. package/logos/social1.png +0 -0
  84. package/logos/social2.png +0 -0
  85. package/logos/warp-drive-logo-dark.svg +4 -0
  86. package/logos/warp-drive-logo-gold.svg +4 -0
  87. package/package.json +68 -0
@@ -0,0 +1,393 @@
1
+ import { buildBaseURL, buildQueryParams } from "./index.js";
2
+ import { p as pluralize, j as underscore } from "./inflect-C1laviCe.js";
3
+ import { e as extractCacheOptions, c as copyForwardUrlOptions } from "./builder-utils-Donkk-BZ.js";
4
+ import { recordIdentifierFor } from '@warp-drive/core';
5
+ import { macroCondition, getGlobalConfig } from '@embroider/macros';
6
+
7
+ /**
8
+ * Builds request options to fetch a single resource by a known id or identifier
9
+ * configured for the url and header expectations of most ActiveRecord APIs.
10
+ *
11
+ * **Basic Usage**
12
+ *
13
+ * ```ts
14
+ * import { findRecord } from '@warp-drive/utilities/active-record';
15
+ *
16
+ * const data = await store.request(findRecord('person', '1'));
17
+ * ```
18
+ *
19
+ * **With Options**
20
+ *
21
+ * ```ts
22
+ * import { findRecord } from '@warp-drive/utilities/active-record';
23
+ *
24
+ * const options = findRecord('person', '1', { include: ['pets', 'friends'] });
25
+ * const data = await store.request(options);
26
+ * ```
27
+ *
28
+ * **With an Identifier**
29
+ *
30
+ * ```ts
31
+ * import { findRecord } from '@warp-drive/utilities/active-record';
32
+ *
33
+ * const options = findRecord({ type: 'person', id: '1' }, { include: ['pets', 'friends'] });
34
+ * const data = await store.request(options);
35
+ * ```
36
+ *
37
+ * **Supplying Options to Modify the Request Behavior**
38
+ *
39
+ * The following options are supported:
40
+ *
41
+ * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.
42
+ * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.
43
+ * - `resourcePath` - The resource path to use for the request, defaults to pluralizing and underscoring the supplied type
44
+ * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this
45
+ * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.
46
+ * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the
47
+ * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,
48
+ * defaulting to `false` if none is configured.
49
+ * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)
50
+ *
51
+ * ```ts
52
+ * import { findRecord } from '@warp-drive/utilities/active-record';
53
+ *
54
+ * const options = findRecord('person', '1', { include: ['pets', 'friends'] }, { namespace: 'api/v2' });
55
+ * const data = await store.request(options);
56
+ * ```
57
+ *
58
+ * @public
59
+ * @param identifier
60
+ * @param options
61
+ */
62
+
63
+ function findRecord(arg1, arg2, arg3) {
64
+ const identifier = typeof arg1 === 'string' ? {
65
+ type: arg1,
66
+ id: arg2
67
+ } : arg1;
68
+ const options = (typeof arg1 === 'string' ? arg3 : arg2) || {};
69
+ const cacheOptions = extractCacheOptions(options);
70
+ const urlOptions = {
71
+ identifier,
72
+ op: 'findRecord',
73
+ resourcePath: pluralize(underscore(identifier.type))
74
+ };
75
+ copyForwardUrlOptions(urlOptions, options);
76
+ const url = buildBaseURL(urlOptions);
77
+ const headers = new Headers();
78
+ headers.append('Accept', 'application/json;charset=utf-8');
79
+ return {
80
+ url: options.include?.length ? `${url}?${buildQueryParams({
81
+ include: options.include
82
+ }, options.urlParamsSettings)}` : url,
83
+ method: 'GET',
84
+ headers,
85
+ cacheOptions,
86
+ op: 'findRecord',
87
+ records: [identifier]
88
+ };
89
+ }
90
+
91
+ /**
92
+ * Builds request options to query for resources, usually by a primary
93
+ * type, configured for the url and header expectations of most ActiveRecord APIs.
94
+ *
95
+ * **Basic Usage**
96
+ *
97
+ * ```ts
98
+ * import { query } from '@warp-drive/utilities/active-record';
99
+ *
100
+ * const data = await store.request(query('person'));
101
+ * ```
102
+ *
103
+ * **With Query Params**
104
+ *
105
+ * ```ts
106
+ * import { query } from '@warp-drive/utilities/active-record';
107
+ *
108
+ * const options = query('person', { include: ['pets', 'friends'] });
109
+ * const data = await store.request(options);
110
+ * ```
111
+ *
112
+ * **Supplying Options to Modify the Request Behavior**
113
+ *
114
+ * The following options are supported:
115
+ *
116
+ * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.
117
+ * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.
118
+ * - `resourcePath` - The resource path to use for the request, defaults to pluralizing and underscoring the supplied type
119
+ * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this
120
+ * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.
121
+ * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the
122
+ * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,
123
+ * defaulting to `false` if none is configured.
124
+ * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)
125
+ *
126
+ * ```ts
127
+ * import { query } from '@warp-drive/utilities/active-record';
128
+ *
129
+ * const options = query('person', { include: ['pets', 'friends'] }, { reload: true });
130
+ * const data = await store.request(options);
131
+ * ```
132
+ *
133
+ * @public
134
+ * @param identifier
135
+ * @param query
136
+ * @param options
137
+ */
138
+
139
+ function query(type,
140
+ // eslint-disable-next-line @typescript-eslint/no-shadow
141
+ query = {}, options = {}) {
142
+ const cacheOptions = extractCacheOptions(options);
143
+ const urlOptions = {
144
+ identifier: {
145
+ type
146
+ },
147
+ op: 'query',
148
+ resourcePath: pluralize(underscore(type))
149
+ };
150
+ copyForwardUrlOptions(urlOptions, options);
151
+ const url = buildBaseURL(urlOptions);
152
+ const headers = new Headers();
153
+ headers.append('Accept', 'application/json;charset=utf-8');
154
+ const queryString = buildQueryParams(query, options.urlParamsSettings);
155
+ return {
156
+ url: queryString ? `${url}?${queryString}` : url,
157
+ method: 'GET',
158
+ headers,
159
+ cacheOptions,
160
+ op: 'query'
161
+ };
162
+ }
163
+ function isExisting(identifier) {
164
+ return 'id' in identifier && identifier.id !== null && 'type' in identifier && identifier.type !== null;
165
+ }
166
+
167
+ /**
168
+ * Builds request options to delete record for resources,
169
+ * configured for the url, method and header expectations of ActiveRecord APIs.
170
+ *
171
+ * **Basic Usage**
172
+ *
173
+ * ```ts
174
+ * import { deleteRecord } from '@warp-drive/utilities/active-record';
175
+ *
176
+ * const person = store.peekRecord('person', '1');
177
+ *
178
+ * // mark record as deleted
179
+ * store.deleteRecord(person);
180
+ *
181
+ * // persist deletion
182
+ * const data = await store.request(deleteRecord(person));
183
+ * ```
184
+ *
185
+ * **Supplying Options to Modify the Request Behavior**
186
+ *
187
+ * The following options are supported:
188
+ *
189
+ * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.
190
+ * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.
191
+ * - `resourcePath` - The resource path to use for the request, defaults to pluralizing the supplied type
192
+ * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this
193
+ * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.
194
+ * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the
195
+ * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,
196
+ * defaulting to `false` if none is configured.
197
+ * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)
198
+ *
199
+ * ```ts
200
+ * import { deleteRecord } from '@warp-drive/utilities/active-record';
201
+ *
202
+ * const person = store.peekRecord('person', '1');
203
+ *
204
+ * // mark record as deleted
205
+ * store.deleteRecord(person);
206
+ *
207
+ * // persist deletion
208
+ * const options = deleteRecord(person, { namespace: 'api/v1' });
209
+ * const data = await store.request(options);
210
+ * ```
211
+ *
212
+ * @public
213
+ * @param record
214
+ * @param options
215
+ */
216
+
217
+ function deleteRecord(record, options = {}) {
218
+ const identifier = recordIdentifierFor(record);
219
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
220
+ if (!test) {
221
+ throw new Error(`Expected to be given a record instance`);
222
+ }
223
+ })(identifier) : {};
224
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
225
+ if (!test) {
226
+ throw new Error(`Cannot delete a record that does not have an associated type and id.`);
227
+ }
228
+ })(isExisting(identifier)) : {};
229
+ const urlOptions = {
230
+ identifier: identifier,
231
+ op: 'deleteRecord',
232
+ resourcePath: pluralize(underscore(identifier.type))
233
+ };
234
+ copyForwardUrlOptions(urlOptions, options);
235
+ const url = buildBaseURL(urlOptions);
236
+ const headers = new Headers();
237
+ headers.append('Accept', 'application/json;charset=utf-8');
238
+ return {
239
+ url,
240
+ method: 'DELETE',
241
+ headers,
242
+ op: 'deleteRecord',
243
+ data: {
244
+ record: identifier
245
+ },
246
+ records: [identifier]
247
+ };
248
+ }
249
+
250
+ /**
251
+ * Builds request options to create new record for resources,
252
+ * configured for the url, method and header expectations of most ActiveRecord APIs.
253
+ *
254
+ * **Basic Usage**
255
+ *
256
+ * ```ts
257
+ * import { createRecord } from '@warp-drive/utilities/active-record';
258
+ *
259
+ * const person = store.createRecord('person', { name: 'Ted' });
260
+ * const data = await store.request(createRecord(person));
261
+ * ```
262
+ *
263
+ * **Supplying Options to Modify the Request Behavior**
264
+ *
265
+ * The following options are supported:
266
+ *
267
+ * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.
268
+ * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.
269
+ * - `resourcePath` - The resource path to use for the request, defaults to pluralizing the supplied type
270
+ * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this
271
+ * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.
272
+ * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the
273
+ * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,
274
+ * defaulting to `false` if none is configured.
275
+ * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)
276
+ *
277
+ * ```ts
278
+ * import { createRecord } from '@warp-drive/utilities/active-record';
279
+ *
280
+ * const person = store.createRecord('person', { name: 'Ted' });
281
+ * const options = createRecord(person, { namespace: 'api/v1' });
282
+ * const data = await store.request(options);
283
+ * ```
284
+ *
285
+ * @public
286
+ * @param record
287
+ * @param options
288
+ */
289
+
290
+ function createRecord(record, options = {}) {
291
+ const identifier = recordIdentifierFor(record);
292
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
293
+ if (!test) {
294
+ throw new Error(`Expected to be given a record instance`);
295
+ }
296
+ })(identifier) : {};
297
+ const urlOptions = {
298
+ identifier: identifier,
299
+ op: 'createRecord',
300
+ resourcePath: pluralize(underscore(identifier.type))
301
+ };
302
+ copyForwardUrlOptions(urlOptions, options);
303
+ const url = buildBaseURL(urlOptions);
304
+ const headers = new Headers();
305
+ headers.append('Accept', 'application/json;charset=utf-8');
306
+ return {
307
+ url,
308
+ method: 'POST',
309
+ headers,
310
+ op: 'createRecord',
311
+ data: {
312
+ record: identifier
313
+ },
314
+ records: [identifier]
315
+ };
316
+ }
317
+
318
+ /**
319
+ * Builds request options to update existing record for resources,
320
+ * configured for the url, method and header expectations of most ActiveRecord APIs.
321
+ *
322
+ * **Basic Usage**
323
+ *
324
+ * ```ts
325
+ * import { updateRecord } from '@warp-drive/utilities/active-record';
326
+ *
327
+ * const person = store.peekRecord('person', '1');
328
+ * person.name = 'Chris';
329
+ * const data = await store.request(updateRecord(person));
330
+ * ```
331
+ *
332
+ * **Supplying Options to Modify the Request Behavior**
333
+ *
334
+ * The following options are supported:
335
+ *
336
+ * - `patch` - Allows caller to specify whether to use a PATCH request instead of a PUT request, defaults to `false`.
337
+ * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.
338
+ * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.
339
+ * - `resourcePath` - The resource path to use for the request, defaults to pluralizing the supplied type
340
+ * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this
341
+ * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.
342
+ * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the
343
+ * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,
344
+ * defaulting to `false` if none is configured.
345
+ * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)
346
+ *
347
+ * ```ts
348
+ * import { updateRecord } from '@warp-drive/utilities/active-record';
349
+ *
350
+ * const person = store.peekRecord('person', '1');
351
+ * person.name = 'Chris';
352
+ * const options = updateRecord(person, { patch: true });
353
+ * const data = await store.request(options);
354
+ * ```
355
+ *
356
+ * @public
357
+ * @param record
358
+ * @param options
359
+ */
360
+
361
+ function updateRecord(record, options = {}) {
362
+ const identifier = recordIdentifierFor(record);
363
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
364
+ if (!test) {
365
+ throw new Error(`Expected to be given a record instance`);
366
+ }
367
+ })(identifier) : {};
368
+ macroCondition(getGlobalConfig().WarpDrive.env.DEBUG) ? (test => {
369
+ if (!test) {
370
+ throw new Error(`Cannot update a record that does not have an associated type and id.`);
371
+ }
372
+ })(isExisting(identifier)) : {};
373
+ const urlOptions = {
374
+ identifier: identifier,
375
+ op: 'updateRecord',
376
+ resourcePath: pluralize(underscore(identifier.type))
377
+ };
378
+ copyForwardUrlOptions(urlOptions, options);
379
+ const url = buildBaseURL(urlOptions);
380
+ const headers = new Headers();
381
+ headers.append('Accept', 'application/json;charset=utf-8');
382
+ return {
383
+ url,
384
+ method: options.patch ? 'PATCH' : 'PUT',
385
+ headers,
386
+ op: 'updateRecord',
387
+ data: {
388
+ record: identifier
389
+ },
390
+ records: [identifier]
391
+ };
392
+ }
393
+ export { createRecord, deleteRecord, findRecord, query, updateRecord };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"active-record.js","sources":["../src/-private/active-record/find-record.ts","../src/-private/active-record/query.ts","../src/-private/active-record/save-record.ts"],"sourcesContent":["import type { TypeFromInstance } from '@warp-drive/core/types/record';\nimport type {\n FindRecordOptions,\n FindRecordRequestOptions,\n RemotelyAccessibleIdentifier,\n} from '@warp-drive/core/types/request';\nimport type { SingleResourceDataDocument } from '@warp-drive/core/types/spec/document';\n\nimport { buildBaseURL, buildQueryParams, type FindRecordUrlOptions } from '../../index.ts';\nimport { pluralize, underscore } from '../../string.ts';\nimport { copyForwardUrlOptions, extractCacheOptions } from '../builder-utils.ts';\n\nexport type FindRecordResultDocument<T> = Omit<SingleResourceDataDocument<T>, 'data'> & { data: T };\n\n/**\n * Builds request options to fetch a single resource by a known id or identifier\n * configured for the url and header expectations of most ActiveRecord APIs.\n *\n * **Basic Usage**\n *\n * ```ts\n * import { findRecord } from '@warp-drive/utilities/active-record';\n *\n * const data = await store.request(findRecord('person', '1'));\n * ```\n *\n * **With Options**\n *\n * ```ts\n * import { findRecord } from '@warp-drive/utilities/active-record';\n *\n * const options = findRecord('person', '1', { include: ['pets', 'friends'] });\n * const data = await store.request(options);\n * ```\n *\n * **With an Identifier**\n *\n * ```ts\n * import { findRecord } from '@warp-drive/utilities/active-record';\n *\n * const options = findRecord({ type: 'person', id: '1' }, { include: ['pets', 'friends'] });\n * const data = await store.request(options);\n * ```\n *\n * **Supplying Options to Modify the Request Behavior**\n *\n * The following options are supported:\n *\n * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.\n * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.\n * - `resourcePath` - The resource path to use for the request, defaults to pluralizing and underscoring the supplied type\n * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this\n * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.\n * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the\n * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,\n * defaulting to `false` if none is configured.\n * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)\n *\n * ```ts\n * import { findRecord } from '@warp-drive/utilities/active-record';\n *\n * const options = findRecord('person', '1', { include: ['pets', 'friends'] }, { namespace: 'api/v2' });\n * const data = await store.request(options);\n * ```\n *\n * @public\n * @param identifier\n * @param options\n */\nexport function findRecord<T>(\n identifier: RemotelyAccessibleIdentifier<TypeFromInstance<T>>,\n options?: FindRecordOptions<T>\n): FindRecordRequestOptions<FindRecordResultDocument<T>, T>;\nexport function findRecord(\n identifier: RemotelyAccessibleIdentifier,\n options?: FindRecordOptions\n): FindRecordRequestOptions;\nexport function findRecord<T>(\n type: TypeFromInstance<T>,\n id: string,\n options?: FindRecordOptions<T>\n): FindRecordRequestOptions<FindRecordResultDocument<T>, T>;\nexport function findRecord(type: string, id: string, options?: FindRecordOptions): FindRecordRequestOptions;\nexport function findRecord(\n arg1: string | RemotelyAccessibleIdentifier,\n arg2: string | FindRecordOptions | undefined,\n arg3?: FindRecordOptions\n): FindRecordRequestOptions {\n const identifier: RemotelyAccessibleIdentifier = typeof arg1 === 'string' ? { type: arg1, id: arg2 as string } : arg1;\n const options = ((typeof arg1 === 'string' ? arg3 : arg2) || {}) as FindRecordOptions;\n const cacheOptions = extractCacheOptions(options);\n const urlOptions: FindRecordUrlOptions = {\n identifier,\n op: 'findRecord',\n resourcePath: pluralize(underscore(identifier.type)),\n };\n\n copyForwardUrlOptions(urlOptions, options);\n\n const url = buildBaseURL(urlOptions);\n const headers = new Headers();\n headers.append('Accept', 'application/json;charset=utf-8');\n\n return {\n url: options.include?.length\n ? `${url}?${buildQueryParams({ include: options.include }, options.urlParamsSettings)}`\n : url,\n method: 'GET',\n headers,\n cacheOptions,\n op: 'findRecord',\n records: [identifier],\n };\n}\n","import type { QueryParamsSource } from '@warp-drive/core/types/params';\nimport type { TypeFromInstance } from '@warp-drive/core/types/record';\nimport type { ConstrainedRequestOptions, QueryRequestOptions } from '@warp-drive/core/types/request';\nimport type { CollectionResourceDataDocument } from '@warp-drive/core/types/spec/document';\n\nimport { buildBaseURL, buildQueryParams, type QueryUrlOptions } from '../../index.ts';\nimport { pluralize, underscore } from '../../string';\nimport { copyForwardUrlOptions, extractCacheOptions } from '../builder-utils.ts';\n\n/**\n * Builds request options to query for resources, usually by a primary\n * type, configured for the url and header expectations of most ActiveRecord APIs.\n *\n * **Basic Usage**\n *\n * ```ts\n * import { query } from '@warp-drive/utilities/active-record';\n *\n * const data = await store.request(query('person'));\n * ```\n *\n * **With Query Params**\n *\n * ```ts\n * import { query } from '@warp-drive/utilities/active-record';\n *\n * const options = query('person', { include: ['pets', 'friends'] });\n * const data = await store.request(options);\n * ```\n *\n * **Supplying Options to Modify the Request Behavior**\n *\n * The following options are supported:\n *\n * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.\n * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.\n * - `resourcePath` - The resource path to use for the request, defaults to pluralizing and underscoring the supplied type\n * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this\n * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.\n * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the\n * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,\n * defaulting to `false` if none is configured.\n * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)\n *\n * ```ts\n * import { query } from '@warp-drive/utilities/active-record';\n *\n * const options = query('person', { include: ['pets', 'friends'] }, { reload: true });\n * const data = await store.request(options);\n * ```\n *\n * @public\n * @param identifier\n * @param query\n * @param options\n */\nexport function query<T>(\n type: TypeFromInstance<T>,\n query?: QueryParamsSource,\n options?: ConstrainedRequestOptions\n): QueryRequestOptions<CollectionResourceDataDocument<T>, T>;\nexport function query(\n type: string,\n query?: QueryParamsSource,\n options?: ConstrainedRequestOptions\n): QueryRequestOptions;\nexport function query(\n type: string,\n // eslint-disable-next-line @typescript-eslint/no-shadow\n query: QueryParamsSource = {},\n options: ConstrainedRequestOptions = {}\n): QueryRequestOptions {\n const cacheOptions = extractCacheOptions(options);\n const urlOptions: QueryUrlOptions = {\n identifier: { type },\n op: 'query',\n resourcePath: pluralize(underscore(type)),\n };\n\n copyForwardUrlOptions(urlOptions, options);\n\n const url = buildBaseURL(urlOptions);\n const headers = new Headers();\n headers.append('Accept', 'application/json;charset=utf-8');\n const queryString = buildQueryParams(query, options.urlParamsSettings);\n\n return {\n url: queryString ? `${url}?${queryString}` : url,\n method: 'GET',\n headers,\n cacheOptions,\n op: 'query',\n };\n}\n","import { recordIdentifierFor } from '@warp-drive/core';\nimport { assert } from '@warp-drive/core/build-config/macros';\nimport type { StableExistingRecordIdentifier, StableRecordIdentifier } from '@warp-drive/core/types/identifier';\nimport type { TypedRecordInstance } from '@warp-drive/core/types/record';\nimport type {\n ConstrainedRequestOptions,\n CreateRequestOptions,\n DeleteRequestOptions,\n UpdateRequestOptions,\n} from '@warp-drive/core/types/request';\nimport type { SingleResourceDataDocument } from '@warp-drive/core/types/spec/document';\n\nimport {\n buildBaseURL,\n type CreateRecordUrlOptions,\n type DeleteRecordUrlOptions,\n type UpdateRecordUrlOptions,\n} from '../../index.ts';\nimport { pluralize, underscore } from '../../string';\nimport { copyForwardUrlOptions } from '../builder-utils.ts';\n\nfunction isExisting(identifier: StableRecordIdentifier): identifier is StableExistingRecordIdentifier {\n return 'id' in identifier && identifier.id !== null && 'type' in identifier && identifier.type !== null;\n}\n\n/**\n * Builds request options to delete record for resources,\n * configured for the url, method and header expectations of ActiveRecord APIs.\n *\n * **Basic Usage**\n *\n * ```ts\n * import { deleteRecord } from '@warp-drive/utilities/active-record';\n *\n * const person = store.peekRecord('person', '1');\n *\n * // mark record as deleted\n * store.deleteRecord(person);\n *\n * // persist deletion\n * const data = await store.request(deleteRecord(person));\n * ```\n *\n * **Supplying Options to Modify the Request Behavior**\n *\n * The following options are supported:\n *\n * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.\n * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.\n * - `resourcePath` - The resource path to use for the request, defaults to pluralizing the supplied type\n * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this\n * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.\n * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the\n * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,\n * defaulting to `false` if none is configured.\n * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)\n *\n * ```ts\n * import { deleteRecord } from '@warp-drive/utilities/active-record';\n *\n * const person = store.peekRecord('person', '1');\n *\n * // mark record as deleted\n * store.deleteRecord(person);\n *\n * // persist deletion\n * const options = deleteRecord(person, { namespace: 'api/v1' });\n * const data = await store.request(options);\n * ```\n *\n * @public\n * @param record\n * @param options\n */\nexport function deleteRecord<T>(record: T, options?: ConstrainedRequestOptions): DeleteRequestOptions<T>;\nexport function deleteRecord(record: unknown, options?: ConstrainedRequestOptions): DeleteRequestOptions;\nexport function deleteRecord(record: unknown, options: ConstrainedRequestOptions = {}): DeleteRequestOptions {\n const identifier = recordIdentifierFor(record);\n assert(`Expected to be given a record instance`, identifier);\n assert(`Cannot delete a record that does not have an associated type and id.`, isExisting(identifier));\n\n const urlOptions: DeleteRecordUrlOptions = {\n identifier: identifier,\n op: 'deleteRecord',\n resourcePath: pluralize(underscore(identifier.type)),\n };\n\n copyForwardUrlOptions(urlOptions, options);\n\n const url = buildBaseURL(urlOptions);\n const headers = new Headers();\n headers.append('Accept', 'application/json;charset=utf-8');\n\n return {\n url,\n method: 'DELETE',\n headers,\n op: 'deleteRecord',\n data: {\n record: identifier,\n },\n records: [identifier],\n };\n}\n\n/**\n * Builds request options to create new record for resources,\n * configured for the url, method and header expectations of most ActiveRecord APIs.\n *\n * **Basic Usage**\n *\n * ```ts\n * import { createRecord } from '@warp-drive/utilities/active-record';\n *\n * const person = store.createRecord('person', { name: 'Ted' });\n * const data = await store.request(createRecord(person));\n * ```\n *\n * **Supplying Options to Modify the Request Behavior**\n *\n * The following options are supported:\n *\n * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.\n * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.\n * - `resourcePath` - The resource path to use for the request, defaults to pluralizing the supplied type\n * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this\n * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.\n * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the\n * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,\n * defaulting to `false` if none is configured.\n * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)\n *\n * ```ts\n * import { createRecord } from '@warp-drive/utilities/active-record';\n *\n * const person = store.createRecord('person', { name: 'Ted' });\n * const options = createRecord(person, { namespace: 'api/v1' });\n * const data = await store.request(options);\n * ```\n *\n * @public\n * @param record\n * @param options\n */\nexport function createRecord<T>(record: T, options?: ConstrainedRequestOptions): CreateRequestOptions<T>;\nexport function createRecord(record: unknown, options?: ConstrainedRequestOptions): CreateRequestOptions;\nexport function createRecord(record: unknown, options: ConstrainedRequestOptions = {}): CreateRequestOptions {\n const identifier = recordIdentifierFor(record);\n assert(`Expected to be given a record instance`, identifier);\n\n const urlOptions: CreateRecordUrlOptions = {\n identifier: identifier,\n op: 'createRecord',\n resourcePath: pluralize(underscore(identifier.type)),\n };\n\n copyForwardUrlOptions(urlOptions, options);\n\n const url = buildBaseURL(urlOptions);\n const headers = new Headers();\n headers.append('Accept', 'application/json;charset=utf-8');\n\n return {\n url,\n method: 'POST',\n headers,\n op: 'createRecord',\n data: {\n record: identifier,\n },\n records: [identifier],\n };\n}\n\n/**\n * Builds request options to update existing record for resources,\n * configured for the url, method and header expectations of most ActiveRecord APIs.\n *\n * **Basic Usage**\n *\n * ```ts\n * import { updateRecord } from '@warp-drive/utilities/active-record';\n *\n * const person = store.peekRecord('person', '1');\n * person.name = 'Chris';\n * const data = await store.request(updateRecord(person));\n * ```\n *\n * **Supplying Options to Modify the Request Behavior**\n *\n * The following options are supported:\n *\n * - `patch` - Allows caller to specify whether to use a PATCH request instead of a PUT request, defaults to `false`.\n * - `host` - The host to use for the request, defaults to the `host` configured with `setBuildURLConfig`.\n * - `namespace` - The namespace to use for the request, defaults to the `namespace` configured with `setBuildURLConfig`.\n * - `resourcePath` - The resource path to use for the request, defaults to pluralizing the supplied type\n * - `reload` - Whether to forcibly reload the request if it is already in the store, not supplying this\n * option will delegate to the store's CachePolicy, defaulting to `false` if none is configured.\n * - `backgroundReload` - Whether to reload the request if it is already in the store, but to also resolve the\n * promise with the cached value, not supplying this option will delegate to the store's CachePolicy,\n * defaulting to `false` if none is configured.\n * - `urlParamsSetting` - an object containing options for how to serialize the query params (see `buildQueryParams`)\n *\n * ```ts\n * import { updateRecord } from '@warp-drive/utilities/active-record';\n *\n * const person = store.peekRecord('person', '1');\n * person.name = 'Chris';\n * const options = updateRecord(person, { patch: true });\n * const data = await store.request(options);\n * ```\n *\n * @public\n * @param record\n * @param options\n */\nexport function updateRecord<T extends TypedRecordInstance, RT extends TypedRecordInstance = T>(\n record: T,\n options?: ConstrainedRequestOptions & { patch?: boolean }\n): UpdateRequestOptions<SingleResourceDataDocument<RT>, T>;\nexport function updateRecord(\n record: unknown,\n options?: ConstrainedRequestOptions & { patch?: boolean }\n): UpdateRequestOptions;\nexport function updateRecord(\n record: unknown,\n options: ConstrainedRequestOptions & { patch?: boolean } = {}\n): UpdateRequestOptions {\n const identifier = recordIdentifierFor(record);\n assert(`Expected to be given a record instance`, identifier);\n assert(`Cannot update a record that does not have an associated type and id.`, isExisting(identifier));\n\n const urlOptions: UpdateRecordUrlOptions = {\n identifier: identifier,\n op: 'updateRecord',\n resourcePath: pluralize(underscore(identifier.type)),\n };\n\n copyForwardUrlOptions(urlOptions, options);\n\n const url = buildBaseURL(urlOptions);\n const headers = new Headers();\n headers.append('Accept', 'application/json;charset=utf-8');\n\n return {\n url,\n method: options.patch ? 'PATCH' : 'PUT',\n headers,\n op: 'updateRecord',\n data: {\n record: identifier,\n },\n records: [identifier],\n };\n}\n"],"names":["findRecord","arg1","arg2","arg3","identifier","type","id","options","cacheOptions","extractCacheOptions","urlOptions","op","resourcePath","pluralize","underscore","copyForwardUrlOptions","url","buildBaseURL","headers","Headers","append","include","length","buildQueryParams","urlParamsSettings","method","records","query","queryString","isExisting","deleteRecord","record","recordIdentifierFor","macroCondition","getGlobalConfig","WarpDrive","env","DEBUG","test","Error","data","createRecord","updateRecord","patch"],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ function copyForwardUrlOptions(urlOptions, options) {
2
+ if ('host' in options) {
3
+ urlOptions.host = options.host;
4
+ }
5
+ if ('namespace' in options) {
6
+ urlOptions.namespace = options.namespace;
7
+ }
8
+ if ('resourcePath' in options) {
9
+ urlOptions.resourcePath = options.resourcePath;
10
+ }
11
+ }
12
+ function extractCacheOptions(options) {
13
+ const cacheOptions = {};
14
+ if ('reload' in options) {
15
+ cacheOptions.reload = options.reload;
16
+ }
17
+ if ('backgroundReload' in options) {
18
+ cacheOptions.backgroundReload = options.backgroundReload;
19
+ }
20
+ return cacheOptions;
21
+ }
22
+ export { copyForwardUrlOptions as c, extractCacheOptions as e };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder-utils-Donkk-BZ.js","sources":["../src/-private/builder-utils.ts"],"sourcesContent":["import type { CacheOptions, ConstrainedRequestOptions } from '@warp-drive/core/types/request';\n\nimport type { UrlOptions } from '../index.ts';\n\nexport function copyForwardUrlOptions(urlOptions: UrlOptions, options: ConstrainedRequestOptions): void {\n if ('host' in options) {\n urlOptions.host = options.host;\n }\n if ('namespace' in options) {\n urlOptions.namespace = options.namespace;\n }\n if ('resourcePath' in options) {\n urlOptions.resourcePath = options.resourcePath;\n }\n}\n\nexport function extractCacheOptions(options: ConstrainedRequestOptions): CacheOptions {\n const cacheOptions: CacheOptions = {};\n if ('reload' in options) {\n cacheOptions.reload = options.reload;\n }\n if ('backgroundReload' in options) {\n cacheOptions.backgroundReload = options.backgroundReload;\n }\n return cacheOptions;\n}\n"],"names":["copyForwardUrlOptions","urlOptions","options","host","namespace","resourcePath","extractCacheOptions","cacheOptions","reload","backgroundReload"],"mappings":"AAIO,SAASA,qBAAqBA,CAACC,UAAsB,EAAEC,OAAkC,EAAQ;EACtG,IAAI,MAAM,IAAIA,OAAO,EAAE;AACrBD,IAAAA,UAAU,CAACE,IAAI,GAAGD,OAAO,CAACC,IAAI;AAChC;EACA,IAAI,WAAW,IAAID,OAAO,EAAE;AAC1BD,IAAAA,UAAU,CAACG,SAAS,GAAGF,OAAO,CAACE,SAAS;AAC1C;EACA,IAAI,cAAc,IAAIF,OAAO,EAAE;AAC7BD,IAAAA,UAAU,CAACI,YAAY,GAAGH,OAAO,CAACG,YAAY;AAChD;AACF;AAEO,SAASC,mBAAmBA,CAACJ,OAAkC,EAAgB;EACpF,MAAMK,YAA0B,GAAG,EAAE;EACrC,IAAI,QAAQ,IAAIL,OAAO,EAAE;AACvBK,IAAAA,YAAY,CAACC,MAAM,GAAGN,OAAO,CAACM,MAAM;AACtC;EACA,IAAI,kBAAkB,IAAIN,OAAO,EAAE;AACjCK,IAAAA,YAAY,CAACE,gBAAgB,GAAGP,OAAO,CAACO,gBAAgB;AAC1D;AACA,EAAA,OAAOF,YAAY;AACrB;;;;"}
@@ -0,0 +1,141 @@
1
+ function isCompressibleMethod(method) {
2
+ return method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE';
3
+ }
4
+ const SupportsRequestStreams = (() => {
5
+ let duplexAccessed = false;
6
+ const hasContentType = new Request('', {
7
+ body: new ReadableStream(),
8
+ method: 'POST',
9
+ // @ts-expect-error untyped
10
+ get duplex() {
11
+ duplexAccessed = true;
12
+ return 'half';
13
+ }
14
+ }).headers.has('Content-Type');
15
+ return duplexAccessed && !hasContentType;
16
+ })();
17
+
18
+ /**
19
+ * Options for configuring the AutoCompress handler.
20
+ *
21
+ */
22
+
23
+ const DEFAULT_CONSTRAINTS = {
24
+ Blob: 1000,
25
+ ArrayBuffer: 1000,
26
+ TypedArray: 1000,
27
+ DataView: 1000,
28
+ String: 1000
29
+ };
30
+ const TypedArray = Object.getPrototypeOf(Uint8Array.prototype);
31
+
32
+ /**
33
+ * A request handler that automatically compresses the request body
34
+ * if the request body is a string, array buffer, blob, or form data.
35
+ *
36
+ * This uses the [CompressionStream API](https://developer.mozilla.org/en-US/docs/Web/API/CompressionStream)
37
+ *
38
+ * The compression format as well as the kinds of data to compress can be
39
+ * configured using the `format` and `constraints` options.
40
+ *
41
+ * ```diff
42
+ * +import { AutoCompress } from '@ember-data/request-utils/handlers';
43
+ * import Fetch from '@ember-data/request/fetch';
44
+ * import RequestManager from '@ember-data/request';
45
+ * import Store from '@ember-data/store';
46
+ *
47
+ * class AppStore extends Store {
48
+ * requestManager = new RequestManager()
49
+ * .use([
50
+ * + new AutoCompress(),
51
+ * Fetch
52
+ * ]);
53
+ * }
54
+ * ```
55
+ *
56
+ * @class AutoCompress
57
+ * @public
58
+ * @since 5.5.0
59
+ */
60
+ class AutoCompress {
61
+ constructor(options = {}) {
62
+ const opts = {
63
+ format: options.format ?? 'gzip',
64
+ constraints: Object.assign({}, DEFAULT_CONSTRAINTS, options.constraints),
65
+ allowStreaming: options.allowStreaming ?? false,
66
+ forceStreaming: options.forceStreaming ?? false
67
+ };
68
+ this.options = opts;
69
+ }
70
+ request({
71
+ request
72
+ }, next) {
73
+ const {
74
+ constraints
75
+ } = this.options;
76
+ const {
77
+ body
78
+ } = request;
79
+ const shouldCompress = isCompressibleMethod(request.method) && request.options?.compress !== false && (
80
+ // prettier-ignore
81
+ 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);
82
+ if (!shouldCompress) return next(request);
83
+
84
+ // A convenient way to convert all of the supported body types to a readable
85
+ // stream is to use a `Response` object body
86
+ const response = new Response(request.body);
87
+ const stream = response.body?.pipeThrough(new CompressionStream(this.options.format));
88
+ const headers = new Headers(request.headers);
89
+ headers.set('Content-Encoding', encodingForFormat(this.options.format));
90
+
91
+ //
92
+ // For browsers that support it, `fetch` can receive a `ReadableStream` as
93
+ // the body, so all we need to do is to create a new `ReadableStream` and
94
+ // compress it on the fly
95
+ //
96
+ const forceStreaming = request.options?.forceStreaming ?? this.options.forceStreaming;
97
+ const allowStreaming = request.options?.allowStreaming ?? this.options.allowStreaming;
98
+ if (forceStreaming || SupportsRequestStreams && allowStreaming) {
99
+ const req = Object.assign({}, request, {
100
+ body: stream
101
+ });
102
+ if (SupportsRequestStreams) {
103
+ // @ts-expect-error untyped
104
+ req.duplex = 'half';
105
+ }
106
+ return next(req);
107
+
108
+ //
109
+ // For non-chromium browsers, we have to "pull" the stream to get the final
110
+ // bytes and supply the final byte array as the new request body.
111
+ //
112
+ } else {
113
+ // we need to pull the stream to get the final bytes
114
+ const resp = new Response(stream);
115
+ return resp.blob().then(blob => {
116
+ const req = Object.assign({}, request, {
117
+ body: blob,
118
+ headers
119
+ });
120
+ return next(req);
121
+ });
122
+ }
123
+ }
124
+ }
125
+ function canCompress(type, constraints, size) {
126
+ // if we have a value of 0, we can compress anything
127
+ if (constraints[type] === 0) return true;
128
+ if (constraints[type] === -1) return false;
129
+ return size >= constraints[type];
130
+ }
131
+ function encodingForFormat(format) {
132
+ switch (format) {
133
+ case 'gzip':
134
+ case 'deflate':
135
+ case 'deflate-raw':
136
+ return format;
137
+ default:
138
+ throw new Error(`Unsupported compression format: ${format}`);
139
+ }
140
+ }
141
+ export { AutoCompress, SupportsRequestStreams };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers.js","sources":["../src/-private/handlers/auto-compress.ts"],"sourcesContent":["import 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\nexport const SupportsRequestStreams = (() => {\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.prototype) 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 * @class AutoCompress\n * @public\n * @since 5.5.0\n */\nexport class AutoCompress implements Handler {\n declare options: Required<CompressionOptions> & { constraints: Required<Constraints> };\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 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 });\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 } else {\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}\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 throw new Error(`Unsupported compression format: ${format as unknown as string}`);\n }\n}\n"],"names":["isCompressibleMethod","method","SupportsRequestStreams","duplexAccessed","hasContentType","Request","body","ReadableStream","duplex","headers","has","DEFAULT_CONSTRAINTS","Blob","ArrayBuffer","TypedArray","DataView","String","Object","getPrototypeOf","Uint8Array","prototype","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","Error"],"mappings":"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"}