@rest-vir/define-service 1.3.4 → 1.5.0
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.
|
@@ -104,7 +104,7 @@ export declare const endpointInitShape: Shape<{
|
|
|
104
104
|
}> | import("@sinclair/typebox").TUnsafe<RegExp> | import("@sinclair/typebox").TString | import("@sinclair/typebox").TUndefined | import("@sinclair/typebox").TUnsafe<() => void> | import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUnsafe<{
|
|
105
105
|
anyOrigin: boolean;
|
|
106
106
|
}> | import("@sinclair/typebox").TUnsafe<RegExp> | import("@sinclair/typebox").TString | import("@sinclair/typebox").TUnsafe<() => void>)[]>>)[]>>>;
|
|
107
|
-
methods: import("@sinclair/typebox").TUnsafe<Partial<Record<HttpMethod, boolean
|
|
107
|
+
methods: Shape<import("@sinclair/typebox").TUnsafe<Partial<Record<HttpMethod, boolean>>>>;
|
|
108
108
|
bypassResponseValidation: Shape<import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TBoolean | import("@sinclair/typebox").TNull | import("@sinclair/typebox").TUndefined)[]>>>;
|
|
109
109
|
customProps: Shape<import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<(import("@sinclair/typebox").TUndefined | import("@sinclair/typebox").TUnsafe<Record<never, unknown>>)[]>>>;
|
|
110
110
|
}>;
|
|
@@ -18,6 +18,8 @@ export type GenericFetchEndpointParams = PartialWithUndefined<GenericPathParams>
|
|
|
18
18
|
bypassResponseValidation?: undefined | boolean;
|
|
19
19
|
method?: HttpMethod | undefined;
|
|
20
20
|
options?: Omit<RequestInit, 'body' | 'method'> | undefined;
|
|
21
|
+
/** If `true`, Skip automatic request data `'Content-Type'` header assignment. */
|
|
22
|
+
skipAutomaticContentType?: boolean | undefined;
|
|
21
23
|
/**
|
|
22
24
|
* A custom fetch implementation. Useful for debugging or unit testing. This can safely be
|
|
23
25
|
* omitted to use the default JavaScript built-in global `fetch` function.
|
|
@@ -32,6 +34,15 @@ export type GenericFetchEndpointParams = PartialWithUndefined<GenericPathParams>
|
|
|
32
34
|
* @package [`@rest-vir/define-service`](https://www.npmjs.com/package/@rest-vir/define-service)
|
|
33
35
|
*/
|
|
34
36
|
export type FetchMethod<EndpointToFetch extends Pick<EndpointDefinition, 'methods'>> = IsEqual<KeyCount<Record<ExtractKeysWithMatchingValues<EndpointToFetch['methods'], true>, boolean>>, 1> extends true ? never : Extract<HttpMethod, ExtractKeysWithMatchingValues<EndpointToFetch['methods'], true>> | `${Extract<HttpMethod, ExtractKeysWithMatchingValues<EndpointToFetch['methods'], true>>}`;
|
|
37
|
+
/**
|
|
38
|
+
* Properties from {@link GenericFetchEndpointParams} that are also used in
|
|
39
|
+
* {@link FetchEndpointParams}.
|
|
40
|
+
*
|
|
41
|
+
* @category Internal
|
|
42
|
+
* @category Package : @rest-vir/define-service
|
|
43
|
+
* @package [`@rest-vir/define-service`](https://www.npmjs.com/package/@rest-vir/define-service)
|
|
44
|
+
*/
|
|
45
|
+
export type GenericFetchEndpointKeysAllowedInSpecificParams = 'options' | 'bypassResponseValidation' | 'skipAutomaticContentType';
|
|
35
46
|
/**
|
|
36
47
|
* All type safe parameters for sending a request to an endpoint using {@link fetchEndpoint}.
|
|
37
48
|
*
|
|
@@ -64,7 +75,7 @@ export type FetchEndpointParams<EndpointToFetch extends SelectFrom<EndpointDefin
|
|
|
64
75
|
method?: never;
|
|
65
76
|
} : {
|
|
66
77
|
method: FetchMethod<EndpointToFetch>;
|
|
67
|
-
}) & (AllowFetchMock extends true ? Pick<GenericFetchEndpointParams, '
|
|
78
|
+
}) & (AllowFetchMock extends true ? Pick<GenericFetchEndpointParams, 'fetch' | GenericFetchEndpointKeysAllowedInSpecificParams> : Pick<GenericFetchEndpointParams, GenericFetchEndpointKeysAllowedInSpecificParams>)> : GenericFetchEndpointParams;
|
|
68
79
|
/**
|
|
69
80
|
* Type safe output from sending a request to an endpoint definition. Used by {@link fetchEndpoint}.
|
|
70
81
|
*
|
|
@@ -84,7 +95,10 @@ export type FetchEndpointOutput<EndpointToFetch extends Readonly<SelectFrom<Endp
|
|
|
84
95
|
response: Readonly<Response>;
|
|
85
96
|
}> | Readonly<{
|
|
86
97
|
ok: false;
|
|
87
|
-
data:
|
|
98
|
+
data: EndpointToFetch extends SelectFrom<EndpointDefinition, {
|
|
99
|
+
requestDataShape: true;
|
|
100
|
+
responseDataShape: true;
|
|
101
|
+
}> ? EndpointExecutorData<EndpointToFetch>['response'] | string | undefined : any;
|
|
88
102
|
response: Readonly<Response>;
|
|
89
103
|
}>;
|
|
90
104
|
/**
|
|
@@ -172,7 +186,7 @@ export declare function buildEndpointRequestInit<const EndpointToFetch extends R
|
|
|
172
186
|
serviceOrigin: true;
|
|
173
187
|
serviceName: true;
|
|
174
188
|
};
|
|
175
|
-
}>, ...[{ method, options, pathParams, requestData, searchParams, wildcard },]: CollapsedFetchEndpointParams<EndpointToFetch, false>): {
|
|
189
|
+
}>, ...[{ method, options, pathParams, requestData, searchParams, wildcard, skipAutomaticContentType, },]: CollapsedFetchEndpointParams<EndpointToFetch, false>): {
|
|
176
190
|
url: string;
|
|
177
191
|
requestInit: RequestInit;
|
|
178
192
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { check } from '@augment-vir/assert';
|
|
2
2
|
import { addPrefix, filterMap, getObjectTypedEntries, HttpMethod, mapObject, } from '@augment-vir/common';
|
|
3
|
-
import { assertValidShape } from 'object-shape-tester';
|
|
3
|
+
import { assertValidShape, checkWrapValidShape } from 'object-shape-tester';
|
|
4
4
|
import { buildUrl } from 'url-vir';
|
|
5
5
|
import { parseJsonWithUndefined } from '../augments/json.js';
|
|
6
6
|
function defaultFetch(...[url, requestInit,]) {
|
|
@@ -64,10 +64,11 @@ export async function fetchEndpoint(endpoint, ...params) {
|
|
|
64
64
|
const { requestInit, url } = buildEndpointRequestInit(endpoint, ...params);
|
|
65
65
|
/* node:coverage ignore next: all tests mock fetch so we're never going to have a fallback here. */
|
|
66
66
|
const response = await (fetch || defaultFetch)(url, requestInit, endpoint);
|
|
67
|
+
const responseText = await response.clone().text();
|
|
68
|
+
const responseData = endpoint.responseDataShape
|
|
69
|
+
? parseJsonWithUndefined(responseText)
|
|
70
|
+
: undefined;
|
|
67
71
|
if (response.ok) {
|
|
68
|
-
const responseData = endpoint.responseDataShape
|
|
69
|
-
? parseJsonWithUndefined(await response.text())
|
|
70
|
-
: undefined;
|
|
71
72
|
if (endpoint.responseDataShape && !bypassResponseValidation) {
|
|
72
73
|
assertValidShape(responseData, endpoint.responseDataShape, { allowExtraKeys: true });
|
|
73
74
|
}
|
|
@@ -78,10 +79,16 @@ export async function fetchEndpoint(endpoint, ...params) {
|
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
81
|
else {
|
|
82
|
+
const validResponseData = endpoint.responseDataShape
|
|
83
|
+
? bypassResponseValidation
|
|
84
|
+
? responseData
|
|
85
|
+
: checkWrapValidShape(responseData, endpoint.responseDataShape, {
|
|
86
|
+
allowExtraKeys: true,
|
|
87
|
+
})
|
|
88
|
+
: undefined;
|
|
81
89
|
return {
|
|
82
90
|
ok: false,
|
|
83
|
-
|
|
84
|
-
data: (await response.text()) || undefined,
|
|
91
|
+
data: validResponseData || responseText || undefined,
|
|
85
92
|
response,
|
|
86
93
|
};
|
|
87
94
|
}
|
|
@@ -93,7 +100,7 @@ export async function fetchEndpoint(endpoint, ...params) {
|
|
|
93
100
|
* @category Package : @rest-vir/define-service
|
|
94
101
|
* @package [`@rest-vir/define-service`](https://www.npmjs.com/package/@rest-vir/define-service)
|
|
95
102
|
*/
|
|
96
|
-
export function buildEndpointRequestInit(endpoint, ...[{ method, options = {}, pathParams, requestData, searchParams, wildcard } = {},]) {
|
|
103
|
+
export function buildEndpointRequestInit(endpoint, ...[{ method, options = {}, pathParams, requestData, searchParams, wildcard, skipAutomaticContentType, } = {},]) {
|
|
97
104
|
const headers = mapObject(options.headers instanceof Headers
|
|
98
105
|
? Object.fromEntries(options.headers.entries())
|
|
99
106
|
: check.isArray(options.headers)
|
|
@@ -105,11 +112,11 @@ export function buildEndpointRequestInit(endpoint, ...[{ method, options = {}, p
|
|
|
105
112
|
};
|
|
106
113
|
});
|
|
107
114
|
if (!headers['content-type']) {
|
|
108
|
-
if (requestData instanceof FormData) {
|
|
115
|
+
if (requestData instanceof FormData || skipAutomaticContentType) {
|
|
109
116
|
/**
|
|
110
|
-
* Do not set `content-type` manually when submitting form data because
|
|
111
|
-
*
|
|
112
|
-
*
|
|
117
|
+
* Do not set `content-type` manually when submitting form data because `fetch` will set
|
|
118
|
+
* it automatically _and_ include a boundary in the content type, which is needed for
|
|
119
|
+
* reading the form data properly.
|
|
113
120
|
*/
|
|
114
121
|
}
|
|
115
122
|
else if (requestData) {
|
|
@@ -9,7 +9,7 @@ import { type OriginRequirement } from '../util/origin.js';
|
|
|
9
9
|
* @category Package : @rest-vir/define-service
|
|
10
10
|
* @package [`@rest-vir/define-service`](https://www.npmjs.com/package/@rest-vir/define-service)
|
|
11
11
|
*/
|
|
12
|
-
export type MinimalService<ServiceName extends string =
|
|
12
|
+
export type MinimalService<ServiceName extends string = any> = {
|
|
13
13
|
serviceName: IsEqual<ServiceName, ''> extends true ? never : ServiceName;
|
|
14
14
|
/**
|
|
15
15
|
* The origin at which the service will be hosted. Fetch requests and WebSocket connections will
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rest-vir/define-service",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Define an connect to a declarative and type safe REST and WebSocket service.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rest",
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
"test:update": "npm test update"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@augment-vir/assert": "^31.
|
|
44
|
-
"@augment-vir/common": "^31.
|
|
45
|
-
"date-vir": "^8.
|
|
46
|
-
"type-fest": "^5.
|
|
47
|
-
"url-vir": "^2.1.
|
|
43
|
+
"@augment-vir/assert": "^31.59.1",
|
|
44
|
+
"@augment-vir/common": "^31.59.1",
|
|
45
|
+
"date-vir": "^8.1.0",
|
|
46
|
+
"type-fest": "^5.4.3",
|
|
47
|
+
"url-vir": "^2.1.7"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@augment-vir/test": "^31.
|
|
50
|
+
"@augment-vir/test": "^31.59.1",
|
|
51
51
|
"@web/dev-server-esbuild": "^1.0.4",
|
|
52
52
|
"@web/test-runner": "^0.20.2",
|
|
53
53
|
"@web/test-runner-commands": "^0.9.0",
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
"@web/test-runner-visual-regression": "^0.10.0",
|
|
56
56
|
"istanbul-smart-text-reporter": "^1.1.5",
|
|
57
57
|
"markdown-code-example-inserter": "^3.0.3",
|
|
58
|
-
"object-shape-tester": "^6.
|
|
59
|
-
"typedoc": "^0.28.
|
|
60
|
-
"ws": "^8.
|
|
58
|
+
"object-shape-tester": "^6.11.0",
|
|
59
|
+
"typedoc": "^0.28.16",
|
|
60
|
+
"ws": "^8.19.0"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"object-shape-tester": ">=5"
|