@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.
- package/CHANGELOG.md +1 -0
- package/LICENSE.md +23 -0
- package/README.md +54 -0
- package/addon-main.cjs +5 -0
- package/declarations/-private/active-record/find-record.d.ts +66 -0
- package/declarations/-private/active-record/find-record.d.ts.map +1 -0
- package/declarations/-private/active-record/query.d.ts +54 -0
- package/declarations/-private/active-record/query.d.ts.map +1 -0
- package/declarations/-private/active-record/save-record.d.ts +144 -0
- package/declarations/-private/active-record/save-record.d.ts.map +1 -0
- package/declarations/-private/builder-utils.d.ts +5 -0
- package/declarations/-private/builder-utils.d.ts.map +1 -0
- package/declarations/-private/handlers/auto-compress.d.ts +153 -0
- package/declarations/-private/handlers/auto-compress.d.ts.map +1 -0
- package/declarations/-private/json-api/-utils.d.ts +110 -0
- package/declarations/-private/json-api/-utils.d.ts.map +1 -0
- package/declarations/-private/json-api/find-record.d.ts +66 -0
- package/declarations/-private/json-api/find-record.d.ts.map +1 -0
- package/declarations/-private/json-api/find-record.type-test.d.ts +2 -0
- package/declarations/-private/json-api/find-record.type-test.d.ts.map +1 -0
- package/declarations/-private/json-api/query.d.ts +104 -0
- package/declarations/-private/json-api/query.d.ts.map +1 -0
- package/declarations/-private/json-api/query.type-test.d.ts +2 -0
- package/declarations/-private/json-api/query.type-test.d.ts.map +1 -0
- package/declarations/-private/json-api/save-record.d.ts +191 -0
- package/declarations/-private/json-api/save-record.d.ts.map +1 -0
- package/declarations/-private/json-api/serialize.d.ts +57 -0
- package/declarations/-private/json-api/serialize.d.ts.map +1 -0
- package/declarations/-private/rest/find-record.d.ts +66 -0
- package/declarations/-private/rest/find-record.d.ts.map +1 -0
- package/declarations/-private/rest/query.d.ts +54 -0
- package/declarations/-private/rest/query.d.ts.map +1 -0
- package/declarations/-private/rest/save-record.d.ts +144 -0
- package/declarations/-private/rest/save-record.d.ts.map +1 -0
- package/declarations/-private/string/inflect.d.ts +105 -0
- package/declarations/-private/string/inflect.d.ts.map +1 -0
- package/declarations/-private/string/inflections.d.ts +10 -0
- package/declarations/-private/string/inflections.d.ts.map +1 -0
- package/declarations/-private/string/transform.d.ts +89 -0
- package/declarations/-private/string/transform.d.ts.map +1 -0
- package/declarations/-private.d.ts +2 -0
- package/declarations/-private.d.ts.map +1 -0
- package/declarations/active-record.d.ts +71 -0
- package/declarations/active-record.d.ts.map +1 -0
- package/declarations/handlers.d.ts +8 -0
- package/declarations/handlers.d.ts.map +1 -0
- package/declarations/index.d.ts +255 -0
- package/declarations/index.d.ts.map +1 -0
- package/declarations/json-api.d.ts +51 -0
- package/declarations/json-api.d.ts.map +1 -0
- package/declarations/rest.d.ts +51 -0
- package/declarations/rest.d.ts.map +1 -0
- package/declarations/string.d.ts +14 -0
- package/declarations/string.d.ts.map +1 -0
- package/dist/-private.js +7 -0
- package/dist/-private.js.map +1 -0
- package/dist/active-record.js +393 -0
- package/dist/active-record.js.map +1 -0
- package/dist/builder-utils-Donkk-BZ.js +22 -0
- package/dist/builder-utils-Donkk-BZ.js.map +1 -0
- package/dist/handlers.js +141 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.js +403 -0
- package/dist/index.js.map +1 -0
- package/dist/inflect-C1laviCe.js +376 -0
- package/dist/inflect-C1laviCe.js.map +1 -0
- package/dist/json-api.js +671 -0
- package/dist/json-api.js.map +1 -0
- package/dist/rest.js +393 -0
- package/dist/rest.js.map +1 -0
- package/dist/string.js +1 -0
- package/dist/string.js.map +1 -0
- package/logos/NCC-1701-a-blue.svg +4 -0
- package/logos/NCC-1701-a-gold.svg +4 -0
- package/logos/NCC-1701-a-gold_100.svg +1 -0
- package/logos/NCC-1701-a-gold_base-64.txt +1 -0
- package/logos/NCC-1701-a.svg +4 -0
- package/logos/README.md +4 -0
- package/logos/docs-badge.svg +2 -0
- package/logos/ember-data-logo-dark.svg +12 -0
- package/logos/ember-data-logo-light.svg +12 -0
- package/logos/github-header.svg +444 -0
- package/logos/social1.png +0 -0
- package/logos/social2.png +0 -0
- package/logos/warp-drive-logo-dark.svg +4 -0
- package/logos/warp-drive-logo-gold.svg +4 -0
- 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;;;;"}
|
package/dist/handlers.js
ADDED
|
@@ -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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"}
|