@data-client/rest 0.16.4 → 0.16.6
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 +65 -0
- package/dist/index.js +59 -60
- package/dist/index.umd.min.js +1 -1
- package/legacy/RestEndpoint.js +55 -27
- package/legacy/RestEndpointTypes.js +1 -1
- package/legacy/RestHelpers.js +2 -13
- package/legacy/index.js +1 -1
- package/legacy/pathToRegexp.js +2 -0
- package/lib/RestEndpoint.js +55 -27
- package/lib/RestEndpointTypes.d.ts +39 -19
- package/lib/RestEndpointTypes.d.ts.map +1 -1
- package/lib/RestEndpointTypes.js +1 -1
- package/lib/RestHelpers.d.ts +1 -1
- package/lib/RestHelpers.d.ts.map +1 -1
- package/lib/RestHelpers.js +2 -13
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/pathToRegexp.d.ts +3 -0
- package/lib/pathToRegexp.d.ts.map +1 -0
- package/lib/pathToRegexp.js +342 -0
- package/package.json +5 -4
- package/src/RestEndpoint.js +85 -34
- package/src/RestEndpointTypes.ts +71 -22
- package/src/RestHelpers.ts +8 -9
- package/src/__tests__/RestEndpoint.ts +485 -1
- package/src/__tests__/resource-construction.test.ts +47 -0
- package/src/index.ts +2 -0
- package/src/pathToRegexp.ts +2 -0
- package/ts4.0/RestEndpointTypes.d.ts +39 -19
- package/ts4.0/RestHelpers.d.ts +1 -1
- package/ts4.0/index.d.ts +2 -1
- package/ts4.0/pathToRegexp.d.ts +3 -0
- package/ts4.1/RestEndpointTypes.d.ts +39 -19
- package/ts4.1/RestHelpers.d.ts +1 -1
- package/ts4.1/index.d.ts +2 -1
- package/ts4.1/pathToRegexp.d.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@data-client/rest",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.6",
|
|
4
4
|
"description": "Quickly define typed REST resources and endpoints",
|
|
5
5
|
"homepage": "https://dataclient.io/rest",
|
|
6
6
|
"repository": {
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
},
|
|
85
85
|
"exports": {
|
|
86
86
|
".": {
|
|
87
|
+
"types": "./lib/index.d.ts",
|
|
87
88
|
"module": "./lib/index.js",
|
|
88
89
|
"import": "./node.mjs",
|
|
89
90
|
"require": "./dist/index.js",
|
|
@@ -116,7 +117,7 @@
|
|
|
116
117
|
"README.md"
|
|
117
118
|
],
|
|
118
119
|
"scripts": {
|
|
119
|
-
"build:lib": "NODE_ENV=production BROWSERSLIST_ENV='2020' POLYFILL_TARGETS='chrome>88,safari>14' yarn g:babel --out-dir lib",
|
|
120
|
+
"build:lib": "NODE_ENV=production BROWSERSLIST_ENV='2020' POLYFILL_TARGETS='chrome>88,safari>14' yarn g:babel --out-dir lib && NODE_ENV=production BROWSERSLIST_ENV='2020' yarn g:rollup",
|
|
120
121
|
"build:legacy:lib": "NODE_ENV=production BROWSERSLIST_ENV='2018' POLYFILL_TARGETS='chrome>80,safari>13,firefox>72' yarn g:babel --out-dir legacy",
|
|
121
122
|
"build:js:node": "BROWSERSLIST_ENV=node12 yarn g:rollup",
|
|
122
123
|
"build:js:browser": "BROWSERSLIST_ENV=legacy yarn g:rollup",
|
|
@@ -124,7 +125,7 @@
|
|
|
124
125
|
"build:clean": "yarn g:clean ts4.0 ts4.1 index.d.ts next.d.ts",
|
|
125
126
|
"build:legacy-types": "yarn g:downtypes lib ts4.0 --to=4.0 && yarn g:downtypes lib ts4.1 --to=4.1 && yarn g:copy --up 1 ./src-4.1-types/**/*.d.ts ./ts4.0/ && yarn g:copy --up 1 ./src-4.1-types/**/*.d.ts ./ts4.1 && yarn g:copy --up 1 ./src-4.0-types/**/*.d.ts ./ts4.0",
|
|
126
127
|
"build": "run build:lib && run build:legacy:lib && run build:bundle",
|
|
127
|
-
"dev": "
|
|
128
|
+
"dev": "NODE_ENV=production BROWSERSLIST_ENV='2020' POLYFILL_TARGETS='chrome>88,safari>14' yarn g:babel --out-dir lib -w",
|
|
128
129
|
"prepare": "run build:lib",
|
|
129
130
|
"prepack": "run prepare && run build:bundle && run build:legacy:lib",
|
|
130
131
|
"tsc:ci": "yarn g:tsc --project tsconfig.test.json",
|
|
@@ -135,7 +136,7 @@
|
|
|
135
136
|
"license": "Apache-2.0",
|
|
136
137
|
"dependencies": {
|
|
137
138
|
"@babel/runtime": "^7.20.0",
|
|
138
|
-
"@data-client/endpoint": "^0.16.
|
|
139
|
+
"@data-client/endpoint": "^0.16.6",
|
|
139
140
|
"path-to-regexp": "^8.1.0"
|
|
140
141
|
},
|
|
141
142
|
"devDependencies": {
|
package/src/RestEndpoint.js
CHANGED
|
@@ -12,6 +12,16 @@ import {
|
|
|
12
12
|
isPojo,
|
|
13
13
|
} from './RestHelpers.js';
|
|
14
14
|
|
|
15
|
+
const textLikeRe =
|
|
16
|
+
/\btext\b|\bxml\b|\bhtml\b|\bjavascript\b|\bcss\b|\bcsv\b|\burlencoded\b/;
|
|
17
|
+
|
|
18
|
+
function jsonResponse(response) {
|
|
19
|
+
return response.json().catch(error => {
|
|
20
|
+
error.status = 400;
|
|
21
|
+
throw error;
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
/** Simplifies endpoint definitions that follow REST patterns
|
|
16
26
|
*
|
|
17
27
|
* @see https://dataclient.io/rest/api/RestEndpoint
|
|
@@ -54,6 +64,21 @@ export default class RestEndpoint extends Endpoint {
|
|
|
54
64
|
(!('body' in this) || this.body !== undefined) &&
|
|
55
65
|
!['GET', 'DELETE'].includes(this.method);
|
|
56
66
|
|
|
67
|
+
/* istanbul ignore else */
|
|
68
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
69
|
+
if (
|
|
70
|
+
this.content &&
|
|
71
|
+
this.content !== 'json' &&
|
|
72
|
+
this.schema != null &&
|
|
73
|
+
typeof this.schema !== 'string' &&
|
|
74
|
+
typeof this.schema !== 'undefined'
|
|
75
|
+
) {
|
|
76
|
+
console.error(
|
|
77
|
+
`content '${this.content}' is incompatible with schema. Binary/text responses cannot be normalized. Use schema: undefined.`,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
57
82
|
Object.defineProperty(this, 'name', {
|
|
58
83
|
get() {
|
|
59
84
|
// using 'in' to ensure inheritance lookup
|
|
@@ -143,50 +168,76 @@ export default class RestEndpoint extends Endpoint {
|
|
|
143
168
|
}
|
|
144
169
|
|
|
145
170
|
parseResponse(response) {
|
|
146
|
-
// this should not have any content to read
|
|
147
171
|
if (response.status === 204) return Promise.resolve(null);
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
172
|
+
|
|
173
|
+
if (this.content) {
|
|
174
|
+
/* istanbul ignore else */
|
|
175
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
176
|
+
if (
|
|
177
|
+
this.content !== 'json' &&
|
|
178
|
+
this.schema != null &&
|
|
179
|
+
typeof this.schema !== 'string' &&
|
|
180
|
+
typeof this.schema !== 'undefined'
|
|
181
|
+
) {
|
|
182
|
+
const error = new NetworkError(response);
|
|
183
|
+
error.status = 400;
|
|
184
|
+
error.message = `content '${this.content}' is incompatible with schema. Binary/text responses cannot be normalized. Use schema: undefined.`;
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (this.content === 'stream') return Promise.resolve(response.body);
|
|
189
|
+
return this.content === 'json' ?
|
|
190
|
+
jsonResponse(response)
|
|
191
|
+
: response[this.content]();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const contentType = response.headers.get('content-type');
|
|
195
|
+
if (contentType?.includes('json')) return jsonResponse(response);
|
|
196
|
+
|
|
197
|
+
const isBinary = contentType && !textLikeRe.test(contentType);
|
|
198
|
+
|
|
199
|
+
if (
|
|
200
|
+
typeof this.schema === 'string' ||
|
|
201
|
+
typeof this.schema === 'undefined' ||
|
|
202
|
+
this.schema === null ||
|
|
203
|
+
this.process !== RestEndpoint.prototype.process
|
|
204
|
+
)
|
|
205
|
+
return isBinary ? response.blob() : response.text();
|
|
206
|
+
|
|
207
|
+
if (isBinary) {
|
|
208
|
+
const error = new NetworkError(response);
|
|
209
|
+
error.status = 400;
|
|
210
|
+
error.message = `Unexpected binary content-type for schema ${this.schema}`;
|
|
211
|
+
/* istanbul ignore else */
|
|
212
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
213
|
+
error.message = `Unexpected binary content-type "${contentType}" for schema ${this.schema}. Binary responses cannot be normalized. Use schema: undefined or set content: 'blob'.`;
|
|
214
|
+
}
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return response.text().then(text => {
|
|
219
|
+
const error = new NetworkError(response);
|
|
220
|
+
error.status = 404;
|
|
221
|
+
error.message = `Unexpected text response for schema ${this.schema}`;
|
|
222
|
+
/* istanbul ignore else */
|
|
223
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
152
224
|
if (
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return text;
|
|
158
|
-
|
|
159
|
-
const error = new NetworkError(response);
|
|
160
|
-
error.status = 404;
|
|
161
|
-
error.message = `Unexpected text response for schema ${this.schema}`;
|
|
162
|
-
// custom dev-only messages for more detailed cause
|
|
163
|
-
/* istanbul ignore else */
|
|
164
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
165
|
-
if (
|
|
166
|
-
!(
|
|
167
|
-
response.headers.get('content-type')?.includes('html') ||
|
|
168
|
-
text.startsWith('<!doctype html>')
|
|
169
|
-
)
|
|
170
|
-
) {
|
|
171
|
-
if (tryParse(text) !== undefined) {
|
|
172
|
-
error.message = `"content-type" header does not include "json", but JSON response found.
|
|
225
|
+
!(contentType?.includes('html') || text.startsWith('<!doctype html>'))
|
|
226
|
+
) {
|
|
227
|
+
if (tryParse(text) !== undefined) {
|
|
228
|
+
error.message = `"content-type" header does not include "json", but JSON response found.
|
|
173
229
|
See https://www.rfc-editor.org/rfc/rfc4627 for information on JSON responses
|
|
174
230
|
|
|
175
231
|
Using parsed JSON.
|
|
176
232
|
If text content was expected see https://dataclient.io/rest/api/RestEndpoint#parseResponse`;
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
error.message = `Unexpected html response for schema ${this.schema}
|
|
180
236
|
This likely means no API endpoint was configured for this request, resulting in an HTML fallback.
|
|
181
237
|
|
|
182
238
|
Response (first 300 characters): ${text.substring(0, 300)}`;
|
|
183
|
-
}
|
|
184
239
|
}
|
|
185
|
-
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return response.json().catch(error => {
|
|
189
|
-
error.status = 400;
|
|
240
|
+
}
|
|
190
241
|
throw error;
|
|
191
242
|
});
|
|
192
243
|
}
|
package/src/RestEndpointTypes.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
Denormalize,
|
|
2
3
|
EndpointExtraOptions,
|
|
3
4
|
EndpointInstanceInterface,
|
|
4
5
|
Schema,
|
|
@@ -14,6 +15,23 @@ import {
|
|
|
14
15
|
import { PathArgs, SoftPathArgs } from './pathTypes.js';
|
|
15
16
|
import { EndpointUpdateFunction } from './RestEndpointTypeHelp.js';
|
|
16
17
|
|
|
18
|
+
export type ContentType = 'json' | 'blob' | 'text' | 'arrayBuffer' | 'stream';
|
|
19
|
+
|
|
20
|
+
interface ContentTypeMap {
|
|
21
|
+
blob: Blob;
|
|
22
|
+
text: string;
|
|
23
|
+
arrayBuffer: ArrayBuffer;
|
|
24
|
+
stream: ReadableStream<Uint8Array>;
|
|
25
|
+
json: any;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type ContentReturnType<C extends ContentType> = ContentTypeMap[C];
|
|
29
|
+
|
|
30
|
+
type ContentSchemaGuard<O> =
|
|
31
|
+
O extends { content: 'blob' | 'text' | 'arrayBuffer' | 'stream' } ?
|
|
32
|
+
{ schema?: undefined }
|
|
33
|
+
: {};
|
|
34
|
+
|
|
17
35
|
export interface RestInstanceBase<
|
|
18
36
|
F extends FetchFunction = FetchFunction,
|
|
19
37
|
S extends Schema | undefined = any,
|
|
@@ -48,6 +66,8 @@ export interface RestInstanceBase<
|
|
|
48
66
|
readonly signal: AbortSignal | undefined;
|
|
49
67
|
/** @see https://dataclient.io/rest/api/RestEndpoint#paginationField */
|
|
50
68
|
readonly paginationField?: string;
|
|
69
|
+
/** @see https://dataclient.io/rest/api/RestEndpoint#content */
|
|
70
|
+
readonly content?: ContentType;
|
|
51
71
|
|
|
52
72
|
/* fetch lifecycles */
|
|
53
73
|
/* before-fetch */
|
|
@@ -105,7 +125,8 @@ export interface RestInstanceBase<
|
|
|
105
125
|
this: E,
|
|
106
126
|
options: Readonly<
|
|
107
127
|
RestEndpointExtendOptions<ExtendOptions, E, F> & ExtendOptions
|
|
108
|
-
|
|
128
|
+
> &
|
|
129
|
+
ContentSchemaGuard<ExtendOptions>,
|
|
109
130
|
): RestExtendedEndpoint<ExtendOptions, E>;
|
|
110
131
|
}
|
|
111
132
|
|
|
@@ -155,10 +176,10 @@ export interface RestInstance<
|
|
|
155
176
|
push: AddEndpoint<
|
|
156
177
|
F,
|
|
157
178
|
ExtractCollection<S>['push'],
|
|
158
|
-
|
|
179
|
+
Omit<O, 'body' | 'method'> & {
|
|
159
180
|
body:
|
|
160
|
-
| OptionsToAdderBodyArgument<O>
|
|
161
|
-
| OptionsToAdderBodyArgument<O>[]
|
|
181
|
+
| OptionsToAdderBodyArgument<O, ExtractCollection<S>['push']>
|
|
182
|
+
| OptionsToAdderBodyArgument<O, ExtractCollection<S>['push']>[]
|
|
162
183
|
| FormData;
|
|
163
184
|
}
|
|
164
185
|
>;
|
|
@@ -168,10 +189,10 @@ export interface RestInstance<
|
|
|
168
189
|
unshift: AddEndpoint<
|
|
169
190
|
F,
|
|
170
191
|
ExtractCollection<S>['unshift'],
|
|
171
|
-
|
|
192
|
+
Omit<O, 'body' | 'method'> & {
|
|
172
193
|
body:
|
|
173
|
-
| OptionsToAdderBodyArgument<O>
|
|
174
|
-
| OptionsToAdderBodyArgument<O>[]
|
|
194
|
+
| OptionsToAdderBodyArgument<O, ExtractCollection<S>['unshift']>
|
|
195
|
+
| OptionsToAdderBodyArgument<O, ExtractCollection<S>['unshift']>[]
|
|
175
196
|
| FormData;
|
|
176
197
|
}
|
|
177
198
|
>;
|
|
@@ -181,8 +202,13 @@ export interface RestInstance<
|
|
|
181
202
|
assign: AddEndpoint<
|
|
182
203
|
F,
|
|
183
204
|
ExtractCollection<S>,
|
|
184
|
-
|
|
185
|
-
body:
|
|
205
|
+
Omit<O, 'body' | 'method'> & {
|
|
206
|
+
body:
|
|
207
|
+
| Record<
|
|
208
|
+
string,
|
|
209
|
+
OptionsToAdderBodyArgument<O, ExtractCollection<S>['assign']>
|
|
210
|
+
>
|
|
211
|
+
| FormData;
|
|
186
212
|
}
|
|
187
213
|
>;
|
|
188
214
|
/** Remove item(s) (PATCH) from collection
|
|
@@ -191,10 +217,12 @@ export interface RestInstance<
|
|
|
191
217
|
remove: RemoveEndpoint<
|
|
192
218
|
F,
|
|
193
219
|
ExtractCollection<S>['remove'],
|
|
194
|
-
|
|
220
|
+
Omit<O, 'body' | 'method'> & {
|
|
195
221
|
body:
|
|
196
|
-
| OptionsToAdderBodyArgument<O>
|
|
197
|
-
|
|
|
222
|
+
| Partial<OptionsToAdderBodyArgument<O, ExtractCollection<S>['remove']>>
|
|
223
|
+
| Partial<
|
|
224
|
+
OptionsToAdderBodyArgument<O, ExtractCollection<S>['remove']>
|
|
225
|
+
>[]
|
|
198
226
|
| FormData;
|
|
199
227
|
}
|
|
200
228
|
>;
|
|
@@ -206,7 +234,9 @@ export interface RestInstance<
|
|
|
206
234
|
ExtractCollection<S>['move'],
|
|
207
235
|
{
|
|
208
236
|
path: 'movePath' extends keyof O ? O['movePath'] & string : O['path'];
|
|
209
|
-
body:
|
|
237
|
+
body:
|
|
238
|
+
| Partial<OptionsToAdderBodyArgument<O, ExtractCollection<S>['move']>>
|
|
239
|
+
| FormData;
|
|
210
240
|
}
|
|
211
241
|
>;
|
|
212
242
|
}
|
|
@@ -248,7 +278,10 @@ type OptionsToRestEndpoint<
|
|
|
248
278
|
Extract<O['sideEffect'], boolean | undefined>
|
|
249
279
|
: 'method' extends keyof O ? MethodToSide<O['method']>
|
|
250
280
|
: E['sideEffect'],
|
|
251
|
-
O['process'] extends {} ? ReturnType<O['process']>
|
|
281
|
+
O['process'] extends {} ? ReturnType<O['process']>
|
|
282
|
+
: 'content' extends keyof O ?
|
|
283
|
+
ContentReturnType<O['content'] & ContentType>
|
|
284
|
+
: ResolveType<F>,
|
|
252
285
|
{
|
|
253
286
|
path: Exclude<O['path'], undefined>;
|
|
254
287
|
body: 'body' extends keyof O ? O['body'] : E['body'];
|
|
@@ -276,7 +309,10 @@ type OptionsToRestEndpoint<
|
|
|
276
309
|
Extract<O['sideEffect'], boolean | undefined>
|
|
277
310
|
: 'method' extends keyof O ? MethodToSide<O['method']>
|
|
278
311
|
: E['sideEffect'],
|
|
279
|
-
O['process'] extends {} ? ReturnType<O['process']>
|
|
312
|
+
O['process'] extends {} ? ReturnType<O['process']>
|
|
313
|
+
: 'content' extends keyof O ?
|
|
314
|
+
ContentReturnType<O['content'] & ContentType>
|
|
315
|
+
: ResolveType<F>,
|
|
280
316
|
{
|
|
281
317
|
path: E['path'];
|
|
282
318
|
body: O['body'];
|
|
@@ -302,7 +338,10 @@ type OptionsToRestEndpoint<
|
|
|
302
338
|
Extract<O['sideEffect'], boolean | undefined>
|
|
303
339
|
: 'method' extends keyof O ? MethodToSide<O['method']>
|
|
304
340
|
: E['sideEffect'],
|
|
305
|
-
O['process'] extends {} ? ReturnType<O['process']>
|
|
341
|
+
O['process'] extends {} ? ReturnType<O['process']>
|
|
342
|
+
: 'content' extends keyof O ?
|
|
343
|
+
ContentReturnType<O['content'] & ContentType>
|
|
344
|
+
: ResolveType<F>,
|
|
306
345
|
{
|
|
307
346
|
path: E['path'];
|
|
308
347
|
body: E['body'];
|
|
@@ -343,9 +382,10 @@ export type RestExtendedEndpoint<
|
|
|
343
382
|
{ paginationField: E['getPage']['paginationField'] }
|
|
344
383
|
: unknown),
|
|
345
384
|
RestInstance<
|
|
346
|
-
(
|
|
347
|
-
|
|
348
|
-
|
|
385
|
+
(...args: Parameters<E>) => O['process'] extends {} ?
|
|
386
|
+
Promise<ReturnType<O['process']>>
|
|
387
|
+
: 'content' extends keyof O ?
|
|
388
|
+
Promise<ContentReturnType<O['content'] & ContentType>>
|
|
349
389
|
: ReturnType<E>,
|
|
350
390
|
'schema' extends keyof O ? O['schema'] : E['schema'],
|
|
351
391
|
'sideEffect' extends keyof O ? Extract<O['sideEffect'], boolean | undefined>
|
|
@@ -373,6 +413,8 @@ export interface PartialRestGenerics {
|
|
|
373
413
|
readonly paginationField?: string;
|
|
374
414
|
/** @see https://dataclient.io/rest/api/RestEndpoint#process */
|
|
375
415
|
process?(value: any, ...args: any): any;
|
|
416
|
+
/** @see https://dataclient.io/rest/api/RestEndpoint#content */
|
|
417
|
+
readonly content?: ContentType;
|
|
376
418
|
}
|
|
377
419
|
/** Generic types when constructing a RestEndpoint
|
|
378
420
|
*
|
|
@@ -532,8 +574,8 @@ type InferRestMethodWhenOmitted<O extends RestGenerics> =
|
|
|
532
574
|
type MethodArgForBodyInference<O extends RestGenerics> =
|
|
533
575
|
'method' extends keyof O ? O['method'] : InferRestMethodWhenOmitted<O>;
|
|
534
576
|
|
|
535
|
-
type OptionsToAdderBodyArgument<O extends { body?: any }> =
|
|
536
|
-
'body' extends keyof O ? O['body'] :
|
|
577
|
+
type OptionsToAdderBodyArgument<O extends { body?: any }, EntitySchema = any> =
|
|
578
|
+
'body' extends keyof O ? O['body'] : Partial<Denormalize<EntitySchema>>;
|
|
537
579
|
|
|
538
580
|
export interface RestEndpointOptions<
|
|
539
581
|
F extends FetchFunction = FetchFunction,
|
|
@@ -560,6 +602,8 @@ export interface RestEndpointOptions<
|
|
|
560
602
|
* @see https://dataclient.io/rest/api/RestEndpoint#parseResponse
|
|
561
603
|
*/
|
|
562
604
|
parseResponse?(response: Response): Promise<any>;
|
|
605
|
+
/** @see https://dataclient.io/rest/api/RestEndpoint#content */
|
|
606
|
+
content?: ContentType;
|
|
563
607
|
|
|
564
608
|
sideEffect?: boolean | undefined;
|
|
565
609
|
name?: string;
|
|
@@ -586,6 +630,8 @@ export type RestEndpointConstructorOptions<O extends RestGenerics = any> =
|
|
|
586
630
|
: SoftPathArgs<O['path']>,
|
|
587
631
|
OptionsToBodyArgument<O, MethodArgForBodyInference<O>>,
|
|
588
632
|
O['process'] extends {} ? ReturnType<O['process']>
|
|
633
|
+
: 'content' extends keyof O ?
|
|
634
|
+
ContentReturnType<O['content'] & ContentType>
|
|
589
635
|
: any /*Denormalize<O['schema']>*/
|
|
590
636
|
>,
|
|
591
637
|
O['schema']
|
|
@@ -607,6 +653,7 @@ export interface RestEndpoint<
|
|
|
607
653
|
: PathArgs<O['path']>,
|
|
608
654
|
OptionsToBodyArgument<O, MethodArgForBodyInference<O>>,
|
|
609
655
|
O['process'] extends {} ? ReturnType<O['process']>
|
|
656
|
+
: 'content' extends keyof O ? ContentReturnType<O['content'] & ContentType>
|
|
610
657
|
: any /*Denormalize<O['schema']>*/
|
|
611
658
|
>,
|
|
612
659
|
'schema' extends keyof O ? O['schema'] : undefined,
|
|
@@ -628,7 +675,9 @@ export interface RestEndpointConstructor {
|
|
|
628
675
|
sideEffect,
|
|
629
676
|
name,
|
|
630
677
|
...options
|
|
631
|
-
}: RestEndpointConstructorOptions<O> &
|
|
678
|
+
}: RestEndpointConstructorOptions<O> &
|
|
679
|
+
Readonly<O> &
|
|
680
|
+
ContentSchemaGuard<O>): RestEndpoint<O>;
|
|
632
681
|
readonly prototype: RestInstanceBase;
|
|
633
682
|
}
|
|
634
683
|
|
package/src/RestHelpers.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import {
|
|
2
|
+
compile,
|
|
3
|
+
PathFunction,
|
|
4
|
+
parse,
|
|
5
|
+
pathToRegexp,
|
|
6
|
+
Token,
|
|
7
|
+
ParamData,
|
|
8
|
+
} from './pathToRegexp.js';
|
|
10
9
|
import { ShortenPath } from './pathTypes.js';
|
|
11
10
|
|
|
12
11
|
const urlBaseCache: Record<string, PathFunction<object>> = Object.create(null);
|