@mstuercke/api-utils 5.2.2 → 6.0.1
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/package.json +3 -5
- package/src/__mocks__/ignoreConsoleErrors.ts +10 -12
- package/src/rest/client/fetchRestApi.ts +33 -31
- package/src/rest/server/RestApi.ts +66 -57
- package/src/rest/server/buildRestApiRouteHandler.ts +18 -11
- package/src/rest/server/index.ts +2 -2
- package/src/rest/types/RestApiRequest.ts +10 -10
- package/src/rest/types/RestApiRequestHandler.ts +13 -13
- package/src/rest/types/RestApiRequestHandlerWithAuthentication.ts +7 -9
- package/src/rest/types/RestApiResponse.ts +3 -3
- package/src/rest/types/RestApiRoute.ts +13 -15
- package/src/rest/types/RestApiRouteHandler.ts +20 -13
- package/src/rest/types/RestApiRouteWithAuthentication.ts +7 -9
- package/src/rest/types/common/RestRequestHeadersWithAuthorization.ts +10 -8
- package/src/rest/types/common/index.ts +8 -8
- package/src/rest/types/index.ts +8 -8
- package/src/rest/types/internal/InternalRestApiRequest.ts +14 -12
- package/src/types/OmitNever.ts +1 -1
- package/src/ws/client/useWsApi.ts +68 -57
- package/src/ws/server/WsApi.ts +34 -36
- package/src/ws/server/buildWsApiRouteHandler.ts +15 -8
- package/src/ws/server/closeConnection.ts +7 -10
- package/src/ws/server/getApiGatewayManagementApiClient.ts +7 -8
- package/src/ws/server/getConnection.ts +5 -6
- package/src/ws/server/index.ts +8 -8
- package/src/ws/server/sendResponse.ts +13 -15
- package/src/ws/server/trpc/TrpcSubscriptionRequest.ts +10 -8
- package/src/ws/server/trpc/TrpcSubscriptionResponse.ts +2 -6
- package/src/ws/server/trpc/awsLambdaTrpcSubscriptionRequestHandler.ts +50 -46
- package/src/ws/server/trpc/isObservable.ts +3 -6
- package/src/ws/types/WsApiRequestHandler.ts +14 -13
- package/src/ws/types/WsApiRoute.ts +6 -8
- package/src/ws/types/WsApiRouteHandler.ts +7 -9
- package/src/ws/types/common/WsApiRequest.ts +2 -2
- package/src/ws/types/index.ts +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mstuercke/api-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.0.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"files": [
|
|
@@ -39,8 +39,6 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
|
-
"lint": "eslint ./src --max-warnings 0",
|
|
43
|
-
"lint:fix": "eslint ./src --fix",
|
|
44
42
|
"test:unit": "bun test",
|
|
45
43
|
"compile": "tsc",
|
|
46
44
|
"bump:major": "npm version major --git-tag-version false",
|
|
@@ -49,7 +47,7 @@
|
|
|
49
47
|
"release": "bun run scripts/release.ts"
|
|
50
48
|
},
|
|
51
49
|
"dependencies": {
|
|
52
|
-
"path-to-regexp": "^
|
|
50
|
+
"path-to-regexp": "^7.0.0"
|
|
53
51
|
},
|
|
54
52
|
"peerDependencies": {
|
|
55
53
|
"@aws-sdk/client-apigatewaymanagementapi": "^3.438.0",
|
|
@@ -57,7 +55,7 @@
|
|
|
57
55
|
"@types/aws-lambda": "^8.10.138"
|
|
58
56
|
},
|
|
59
57
|
"devDependencies": {
|
|
60
|
-
"@mstuercke/bun-utils": "6.0
|
|
58
|
+
"@mstuercke/bun-utils": "6.1.0",
|
|
61
59
|
"@trpc/server": "^11.0.0-rc.390",
|
|
62
60
|
"@types/aws-lambda": "^8.10.138",
|
|
63
61
|
"@types/bun": "^1.1.3",
|
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
import {afterEach, beforeEach} from 'bun:test'
|
|
2
|
-
|
|
1
|
+
import {afterEach, beforeEach} from 'bun:test'
|
|
3
2
|
|
|
4
3
|
export const ignoreConsoleErrors = (...messagesToIgnore: string[]) => {
|
|
5
|
-
let consoleError_original: typeof console.error
|
|
4
|
+
let consoleError_original: typeof console.error
|
|
6
5
|
beforeEach(() => {
|
|
7
|
-
consoleError_original = console.error
|
|
6
|
+
consoleError_original = console.error
|
|
8
7
|
console.error = (...data) => {
|
|
9
|
-
if (data.length === 1 && messagesToIgnore.includes(data[0]))
|
|
10
|
-
return;
|
|
8
|
+
if (data.length === 1 && messagesToIgnore.includes(data[0])) return
|
|
11
9
|
|
|
12
|
-
consoleError_original(...data)
|
|
13
|
-
}
|
|
14
|
-
})
|
|
10
|
+
consoleError_original(...data)
|
|
11
|
+
}
|
|
12
|
+
})
|
|
15
13
|
|
|
16
14
|
afterEach(() => {
|
|
17
|
-
console.error = consoleError_original
|
|
18
|
-
})
|
|
19
|
-
}
|
|
15
|
+
console.error = consoleError_original
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
RestApiRequest,
|
|
3
3
|
RestApiRoute,
|
|
4
4
|
RestPathParams,
|
|
@@ -8,40 +8,42 @@ import {
|
|
|
8
8
|
RestRequestHeadersWithAuthorization,
|
|
9
9
|
RestRequireAuthentication,
|
|
10
10
|
RestResponseBody,
|
|
11
|
-
} from '../types'
|
|
12
|
-
import {OmitNever} from '../types/internal'
|
|
13
|
-
|
|
11
|
+
} from '../types'
|
|
12
|
+
import type {OmitNever} from '../types/internal'
|
|
14
13
|
|
|
15
14
|
export async function fetchRestApi<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
PathParams extends RestPathParams,
|
|
16
|
+
QueryParams extends RestQueryParams,
|
|
17
|
+
RequestHeaders extends RestRequestHeaders,
|
|
18
|
+
RequestBody extends RestRequestBody,
|
|
19
|
+
ResponseBody extends RestResponseBody,
|
|
20
|
+
RequireAuthentication extends RestRequireAuthentication,
|
|
21
|
+
>(
|
|
22
|
+
restApiUrl: string,
|
|
23
|
+
route: RestApiRoute<PathParams, QueryParams, RequestHeaders, RequestBody, ResponseBody, RequireAuthentication>,
|
|
24
|
+
request: OmitNever<
|
|
25
|
+
RestApiRequest<
|
|
26
|
+
PathParams,
|
|
27
|
+
QueryParams,
|
|
28
|
+
RestRequestHeadersWithAuthorization<RequestHeaders, RequireAuthentication>,
|
|
29
|
+
RequestBody
|
|
30
|
+
>
|
|
31
|
+
>,
|
|
25
32
|
): Promise<ResponseBody> {
|
|
26
|
-
const pathParams = 'pathParams' in request ? request.pathParams as PathParams : undefined as never
|
|
27
|
-
const queryParams = 'queryParams' in request ? request.queryParams as QueryParams : undefined as never
|
|
28
|
-
const headers = 'headers' in request ? request.headers as RequestHeaders : undefined as never
|
|
29
|
-
const body = 'body' in request ? request.body as RequestBody : undefined as never
|
|
33
|
+
const pathParams = 'pathParams' in request ? (request.pathParams as PathParams) : (undefined as never)
|
|
34
|
+
const queryParams = 'queryParams' in request ? (request.queryParams as QueryParams) : (undefined as never)
|
|
35
|
+
const headers = 'headers' in request ? (request.headers as RequestHeaders) : (undefined as never)
|
|
36
|
+
const body = 'body' in request ? (request.body as RequestBody) : (undefined as never)
|
|
30
37
|
|
|
31
|
-
const url = `${restApiUrl}${route.buildUrl(pathParams, queryParams)}
|
|
32
|
-
const response = await fetch(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
body: body ? JSON.stringify(body) : null,
|
|
38
|
-
});
|
|
38
|
+
const url = `${restApiUrl}${route.buildUrl(pathParams, queryParams)}`
|
|
39
|
+
const response = await fetch(url, {
|
|
40
|
+
method: route.method,
|
|
41
|
+
headers: headers,
|
|
42
|
+
body: body ? JSON.stringify(body) : null,
|
|
43
|
+
})
|
|
39
44
|
|
|
40
|
-
if (!response.ok && response.status !== 404)
|
|
41
|
-
throw `Request ${route.method} ${url} failed`;
|
|
45
|
+
if (!response.ok && response.status !== 404) throw `Request ${route.method} ${url} failed`
|
|
42
46
|
|
|
43
|
-
const text = (await response.text()).trim()
|
|
44
|
-
return response.ok && response.status !== 204
|
|
45
|
-
? text ? JSON.parse(text) : null
|
|
46
|
-
: null;
|
|
47
|
+
const text = (await response.text()).trim()
|
|
48
|
+
return response.ok && response.status !== 204 ? (text ? JSON.parse(text) : null) : null
|
|
47
49
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {APIGatewayProxyEvent, APIGatewayProxyResult} from 'aws-lambda'
|
|
2
|
-
import {URL} from 'node:url'
|
|
3
|
-
import {match} from 'path-to-regexp'
|
|
4
|
-
import {
|
|
1
|
+
import type {APIGatewayProxyEvent, APIGatewayProxyResult} from 'aws-lambda'
|
|
2
|
+
import {URL} from 'node:url'
|
|
3
|
+
import {match} from 'path-to-regexp'
|
|
4
|
+
import type {
|
|
5
5
|
RestApiRouteHandler,
|
|
6
6
|
RestPathParams,
|
|
7
7
|
RestQueryParams,
|
|
@@ -9,51 +9,62 @@ import {
|
|
|
9
9
|
RestRequestHeaders,
|
|
10
10
|
RestRequireAuthentication,
|
|
11
11
|
RestResponseBody,
|
|
12
|
-
} from '../types'
|
|
13
|
-
|
|
12
|
+
} from '../types'
|
|
14
13
|
|
|
15
14
|
const DEFAULT_RESPONSE_HEADERS = {
|
|
16
15
|
'Content-Type': 'application/json; charset=utf-8',
|
|
17
16
|
'Access-Control-Allow-Origin': '*',
|
|
18
17
|
'Access-Control-Allow-Methods': '*',
|
|
19
18
|
'Access-Control-Allow-Headers': '*',
|
|
20
|
-
} as const
|
|
19
|
+
} as const
|
|
21
20
|
|
|
22
21
|
export type AnyRestApiRouteHandler = RestApiRouteHandler<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
RestPathParams,
|
|
23
|
+
RestQueryParams,
|
|
24
|
+
RestRequestHeaders,
|
|
25
|
+
RestRequestBody,
|
|
26
|
+
RestResponseBody,
|
|
27
|
+
RestRequireAuthentication
|
|
29
28
|
>
|
|
30
29
|
|
|
31
30
|
type MatchingRouteHandler = {
|
|
32
|
-
routeHandler: AnyRestApiRouteHandler
|
|
33
|
-
pathParams: RestPathParams
|
|
31
|
+
routeHandler: AnyRestApiRouteHandler
|
|
32
|
+
pathParams: RestPathParams
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
export class RestApi {
|
|
37
|
-
private routeHandlers: AnyRestApiRouteHandler[] = []
|
|
36
|
+
private routeHandlers: AnyRestApiRouteHandler[] = []
|
|
38
37
|
|
|
39
38
|
addRouteHandler<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
PathParams extends RestPathParams,
|
|
40
|
+
QueryParams extends RestQueryParams,
|
|
41
|
+
RequestHeaders extends RestRequestHeaders,
|
|
42
|
+
RequestBody extends RestRequestBody,
|
|
43
|
+
ResponseBody extends RestResponseBody,
|
|
44
|
+
RequireAuthentication extends RestRequireAuthentication,
|
|
45
|
+
>(
|
|
46
|
+
routeHandler: RestApiRouteHandler<
|
|
47
|
+
PathParams,
|
|
48
|
+
QueryParams,
|
|
49
|
+
RequestHeaders,
|
|
50
|
+
RequestBody,
|
|
51
|
+
ResponseBody,
|
|
52
|
+
RequireAuthentication
|
|
53
|
+
>,
|
|
54
|
+
) {
|
|
55
|
+
this.routeHandlers = [...this.routeHandlers, routeHandler as unknown as AnyRestApiRouteHandler]
|
|
56
|
+
return this
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
async handleRequest(
|
|
59
|
+
async handleRequest(
|
|
60
|
+
proxyEvent: APIGatewayProxyEvent,
|
|
61
|
+
onError?: (error: unknown) => Promise<void>,
|
|
62
|
+
): Promise<APIGatewayProxyResult> {
|
|
52
63
|
try {
|
|
53
|
-
const url = new URL(`${proxyEvent.headers?.['origin'] || 'https://no-origin'}${proxyEvent.path}`)
|
|
54
|
-
const routeHandler = this.getMatchingRouteHandler(url, proxyEvent.httpMethod)
|
|
64
|
+
const url = new URL(`${proxyEvent.headers?.['origin'] || 'https://no-origin'}${proxyEvent.path}`)
|
|
65
|
+
const routeHandler = this.getMatchingRouteHandler(url, proxyEvent.httpMethod)
|
|
55
66
|
if (!routeHandler && proxyEvent.httpMethod === 'OPTIONS') {
|
|
56
|
-
const allowedHttpMethods = this.getMatchingRouteHandlers(url).map(({routeHandler}) => routeHandler.route.method)
|
|
67
|
+
const allowedHttpMethods = this.getMatchingRouteHandlers(url).map(({routeHandler}) => routeHandler.route.method)
|
|
57
68
|
return {
|
|
58
69
|
statusCode: 200,
|
|
59
70
|
body: '',
|
|
@@ -61,7 +72,7 @@ export class RestApi {
|
|
|
61
72
|
...DEFAULT_RESPONSE_HEADERS,
|
|
62
73
|
'Access-Control-Allow-Methods': allowedHttpMethods.join(','),
|
|
63
74
|
},
|
|
64
|
-
}
|
|
75
|
+
}
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
if (!routeHandler)
|
|
@@ -69,12 +80,14 @@ export class RestApi {
|
|
|
69
80
|
statusCode: 405,
|
|
70
81
|
headers: DEFAULT_RESPONSE_HEADERS,
|
|
71
82
|
body: `Method ${proxyEvent.httpMethod} not allowed on ${proxyEvent.path}`,
|
|
72
|
-
}
|
|
83
|
+
}
|
|
73
84
|
|
|
74
|
-
const {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
85
|
+
const {
|
|
86
|
+
routeHandler: {requestHandler, route},
|
|
87
|
+
pathParams,
|
|
88
|
+
} = routeHandler
|
|
89
|
+
const userId = proxyEvent.requestContext.authorizer?.principalId
|
|
90
|
+
if (route.requireAuthentication && !userId) return {statusCode: 401, body: ''}
|
|
78
91
|
|
|
79
92
|
const responseBody = await requestHandler({
|
|
80
93
|
pathParams,
|
|
@@ -82,7 +95,7 @@ export class RestApi {
|
|
|
82
95
|
headers: proxyEvent.headers as Record<string, string>,
|
|
83
96
|
body: proxyEvent.body && JSON.parse(proxyEvent.body),
|
|
84
97
|
userId,
|
|
85
|
-
})
|
|
98
|
+
})
|
|
86
99
|
return {
|
|
87
100
|
statusCode: responseBody.status,
|
|
88
101
|
body: responseBody.body ? JSON.stringify(responseBody.body) : '',
|
|
@@ -90,55 +103,51 @@ export class RestApi {
|
|
|
90
103
|
...DEFAULT_RESPONSE_HEADERS,
|
|
91
104
|
...(responseBody.headers || {}),
|
|
92
105
|
},
|
|
93
|
-
}
|
|
106
|
+
}
|
|
94
107
|
} catch (error) {
|
|
95
|
-
if (onError)
|
|
96
|
-
await onError(error);
|
|
108
|
+
if (onError) await onError(error)
|
|
97
109
|
|
|
98
|
-
console.error(error)
|
|
110
|
+
console.error(error)
|
|
99
111
|
return {
|
|
100
112
|
statusCode: 500,
|
|
101
113
|
headers: DEFAULT_RESPONSE_HEADERS,
|
|
102
114
|
body: JSON.stringify({error}),
|
|
103
|
-
}
|
|
115
|
+
}
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
private getMatchingRouteHandlers(url: URL): MatchingRouteHandler[] {
|
|
108
120
|
return this.routeHandlers.reduce((matchingRouteHandlers, routeHandler) => {
|
|
109
|
-
const pathParams = this.extractPathParams(routeHandler, url)
|
|
121
|
+
const pathParams = this.extractPathParams(routeHandler, url)
|
|
110
122
|
const matchingRouteHandler: MatchingRouteHandler = {
|
|
111
123
|
routeHandler,
|
|
112
124
|
pathParams,
|
|
113
|
-
}
|
|
114
|
-
return pathParams
|
|
115
|
-
|
|
116
|
-
: matchingRouteHandlers;
|
|
117
|
-
}, [] as MatchingRouteHandler[]);
|
|
125
|
+
}
|
|
126
|
+
return pathParams ? [...matchingRouteHandlers, matchingRouteHandler] : matchingRouteHandlers
|
|
127
|
+
}, [] as MatchingRouteHandler[])
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
private getMatchingRouteHandler(url: URL, httpMethod: string): MatchingRouteHandler | undefined {
|
|
121
|
-
return this.getMatchingRouteHandlers(url)
|
|
122
|
-
.find(({routeHandler}) => routeHandler.route.method === httpMethod);
|
|
131
|
+
return this.getMatchingRouteHandlers(url).find(({routeHandler}) => routeHandler.route.method === httpMethod)
|
|
123
132
|
}
|
|
124
133
|
|
|
125
134
|
private extractPathParams(routeHandler: AnyRestApiRouteHandler, url: URL): object | never {
|
|
126
|
-
const matcher = match(routeHandler.route.path, {decode: decodeURIComponent})
|
|
127
|
-
return (matcher(url.pathname) || null)?.params as object | never
|
|
135
|
+
const matcher = match(routeHandler.route.path, {decode: decodeURIComponent})
|
|
136
|
+
return (matcher(url.pathname) || null)?.params as object | never
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
private extractQueryParams(proxyEvent: APIGatewayProxyEvent): object {
|
|
131
140
|
const keys = new Set([
|
|
132
141
|
...Object.keys(proxyEvent.queryStringParameters || {}),
|
|
133
142
|
...Object.keys(proxyEvent.multiValueQueryStringParameters || {}),
|
|
134
|
-
])
|
|
143
|
+
])
|
|
135
144
|
|
|
136
|
-
const queryParams: {
|
|
145
|
+
const queryParams: {[key: string]: string | string[] | undefined} = {}
|
|
137
146
|
for (const key of keys.values()) {
|
|
138
|
-
const singleValue = proxyEvent.queryStringParameters?.[key]
|
|
139
|
-
const multiValues = proxyEvent.multiValueQueryStringParameters?.[key] || []
|
|
140
|
-
queryParams[key] = multiValues.length > 1 ? multiValues : singleValue
|
|
147
|
+
const singleValue = proxyEvent.queryStringParameters?.[key]
|
|
148
|
+
const multiValues = proxyEvent.multiValueQueryStringParameters?.[key] || []
|
|
149
|
+
queryParams[key] = multiValues.length > 1 ? multiValues : singleValue
|
|
141
150
|
}
|
|
142
|
-
return queryParams
|
|
151
|
+
return queryParams
|
|
143
152
|
}
|
|
144
153
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
RestApiRequestHandler,
|
|
3
3
|
RestApiRoute,
|
|
4
4
|
RestApiRouteHandler,
|
|
@@ -8,19 +8,26 @@ import {
|
|
|
8
8
|
RestRequestHeaders,
|
|
9
9
|
RestRequireAuthentication,
|
|
10
10
|
RestResponseBody,
|
|
11
|
-
} from '../types'
|
|
11
|
+
} from '../types'
|
|
12
12
|
|
|
13
13
|
export const buildRestApiRouteHandler = <
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
PathParams extends RestPathParams = never,
|
|
15
|
+
QueryParams extends RestQueryParams = never,
|
|
16
|
+
RequestHeaders extends RestRequestHeaders = never,
|
|
17
|
+
RequestBody extends RestRequestBody = never,
|
|
18
|
+
ResponseBody extends RestResponseBody = never,
|
|
19
|
+
RequireAuthentication extends RestRequireAuthentication = false,
|
|
20
20
|
>(
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
route: RestApiRoute<PathParams, QueryParams, RequestHeaders, RequestBody, ResponseBody, RequireAuthentication>,
|
|
22
|
+
requestHandler: RestApiRequestHandler<
|
|
23
|
+
PathParams,
|
|
24
|
+
QueryParams,
|
|
25
|
+
RequestHeaders,
|
|
26
|
+
RequestBody,
|
|
27
|
+
ResponseBody,
|
|
28
|
+
RequireAuthentication
|
|
29
|
+
>,
|
|
23
30
|
): RestApiRouteHandler<PathParams, QueryParams, RequestHeaders, RequestBody, ResponseBody, RequireAuthentication> => ({
|
|
24
31
|
route,
|
|
25
32
|
requestHandler,
|
|
26
|
-
})
|
|
33
|
+
})
|
package/src/rest/server/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from './buildRestApiRouteHandler'
|
|
2
|
-
export * from './RestApi'
|
|
1
|
+
export * from './buildRestApiRouteHandler'
|
|
2
|
+
export * from './RestApi'
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {RestPathParams, RestQueryParams, RestRequestBody, RestRequestHeaders} from './common'
|
|
2
|
-
import {OmitNever} from './internal'
|
|
1
|
+
import type {RestPathParams, RestQueryParams, RestRequestBody, RestRequestHeaders} from './common'
|
|
2
|
+
import type {OmitNever} from './internal'
|
|
3
3
|
|
|
4
4
|
export type RestApiRequest<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
PathParams extends RestPathParams = never,
|
|
6
|
+
QueryParams extends RestQueryParams = never,
|
|
7
|
+
RequestHeaders extends RestRequestHeaders = never,
|
|
8
|
+
RequestBody extends RestRequestBody = never,
|
|
9
|
+
> = OmitNever<{
|
|
10
|
+
pathParams: PathParams
|
|
11
|
+
queryParams: QueryParams
|
|
12
|
+
headers: RequestHeaders
|
|
12
13
|
body: RequestBody
|
|
13
14
|
}>
|
|
14
|
-
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import {RestApiResponse} from './RestApiResponse'
|
|
2
|
-
import {
|
|
1
|
+
import type {RestApiResponse} from './RestApiResponse'
|
|
2
|
+
import type {
|
|
3
3
|
RestPathParams,
|
|
4
4
|
RestQueryParams,
|
|
5
5
|
RestRequestBody,
|
|
6
6
|
RestRequestHeaders,
|
|
7
7
|
RestRequireAuthentication,
|
|
8
8
|
RestResponseBody,
|
|
9
|
-
} from './common'
|
|
10
|
-
import {InternalRestApiRequest} from './internal'
|
|
9
|
+
} from './common'
|
|
10
|
+
import type {InternalRestApiRequest} from './internal'
|
|
11
11
|
|
|
12
12
|
export type RestApiRequestHandler<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
> = (
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
PathParams extends RestPathParams = never,
|
|
14
|
+
QueryParams extends RestQueryParams = never,
|
|
15
|
+
RequestHeaders extends RestRequestHeaders = never,
|
|
16
|
+
RequestBody extends RestRequestBody = never,
|
|
17
|
+
ResponseBody extends RestResponseBody = never,
|
|
18
|
+
RequireAuthentication extends RestRequireAuthentication = false,
|
|
19
|
+
> = (
|
|
20
|
+
request: InternalRestApiRequest<PathParams, QueryParams, RequestHeaders, RequestBody, RequireAuthentication>,
|
|
21
|
+
) => Promise<RestApiResponse<ResponseBody>>
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {RestApiRequestHandler} from './RestApiRequestHandler'
|
|
2
|
-
import {RestPathParams, RestQueryParams, RestRequestBody, RestRequestHeaders, RestResponseBody} from './common'
|
|
1
|
+
import type {RestApiRequestHandler} from './RestApiRequestHandler'
|
|
2
|
+
import type {RestPathParams, RestQueryParams, RestRequestBody, RestRequestHeaders, RestResponseBody} from './common'
|
|
3
3
|
|
|
4
4
|
export type RestApiRequestHandlerWithAuthentication<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
PathParams extends RestPathParams = never,
|
|
6
|
+
QueryParams extends RestQueryParams = never,
|
|
7
|
+
RequestHeaders extends RestRequestHeaders = never,
|
|
8
|
+
RequestBody extends RestRequestBody = never,
|
|
9
|
+
ResponseBody extends RestResponseBody = never,
|
|
10
10
|
> = RestApiRequestHandler<PathParams, QueryParams, RequestHeaders, RequestBody, ResponseBody, true>
|
|
11
|
-
|
|
12
|
-
|
|
@@ -1,34 +1,32 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type {
|
|
2
2
|
RestPathParams,
|
|
3
3
|
RestQueryParams,
|
|
4
4
|
RestRequestBody,
|
|
5
5
|
RestRequestHeaders,
|
|
6
6
|
RestRequireAuthentication,
|
|
7
7
|
RestResponseBody,
|
|
8
|
-
} from './common'
|
|
8
|
+
} from './common'
|
|
9
9
|
|
|
10
10
|
export type RestHttpMethod = 'GET' | 'POST' | 'DELETE' | 'PATCH' | 'PUT' | 'OPTIONS'
|
|
11
11
|
export type RestRoutePath = `/${string}`
|
|
12
12
|
|
|
13
13
|
export type RestApiRoute<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
PathParams extends RestPathParams = never,
|
|
15
|
+
QueryParams extends RestQueryParams = never,
|
|
16
|
+
RequestHeaders extends RestRequestHeaders = never,
|
|
17
|
+
RequestBody extends RestRequestBody = never,
|
|
18
|
+
ResponseBody extends RestResponseBody = never,
|
|
19
|
+
RequireAuthentication extends RestRequireAuthentication = false,
|
|
20
20
|
> = {
|
|
21
|
-
method: RestHttpMethod
|
|
22
|
-
path: RestRoutePath
|
|
23
|
-
buildUrl: (pathParams: PathParams, queryParams: QueryParams) => RestRoutePath
|
|
24
|
-
requireAuthentication: RequireAuthentication
|
|
21
|
+
method: RestHttpMethod
|
|
22
|
+
path: RestRoutePath
|
|
23
|
+
buildUrl: (pathParams: PathParams, queryParams: QueryParams) => RestRoutePath
|
|
24
|
+
requireAuthentication: RequireAuthentication
|
|
25
25
|
|
|
26
26
|
// this is a workaround to force optional generics to be typesafe
|
|
27
27
|
__types?: {
|
|
28
28
|
RequestHeaders: RequestHeaders
|
|
29
29
|
RequestBody: RequestBody
|
|
30
30
|
ResponseBody: ResponseBody
|
|
31
|
-
}
|
|
31
|
+
}
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
|
|
@@ -1,22 +1,29 @@
|
|
|
1
|
-
import {RestApiRequestHandler} from './RestApiRequestHandler'
|
|
2
|
-
import {RestApiRoute} from './RestApiRoute'
|
|
3
|
-
import {
|
|
1
|
+
import type {RestApiRequestHandler} from './RestApiRequestHandler'
|
|
2
|
+
import type {RestApiRoute} from './RestApiRoute'
|
|
3
|
+
import type {
|
|
4
4
|
RestPathParams,
|
|
5
5
|
RestQueryParams,
|
|
6
6
|
RestRequestBody,
|
|
7
7
|
RestRequestHeaders,
|
|
8
8
|
RestRequireAuthentication,
|
|
9
9
|
RestResponseBody,
|
|
10
|
-
} from './common'
|
|
10
|
+
} from './common'
|
|
11
11
|
|
|
12
12
|
export interface RestApiRouteHandler<
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
PathParams extends RestPathParams = never,
|
|
14
|
+
QueryParams extends RestQueryParams = never,
|
|
15
|
+
RequestHeaders extends RestRequestHeaders = never,
|
|
16
|
+
RequestBody extends RestRequestBody = never,
|
|
17
|
+
ResponseBody extends RestResponseBody = never,
|
|
18
|
+
RequireAuthentication extends RestRequireAuthentication = false,
|
|
19
|
+
> {
|
|
20
|
+
route: RestApiRoute<PathParams, QueryParams, RequestHeaders, RequestBody, ResponseBody, RequireAuthentication>
|
|
21
|
+
requestHandler: RestApiRequestHandler<
|
|
22
|
+
PathParams,
|
|
23
|
+
QueryParams,
|
|
24
|
+
RequestHeaders,
|
|
25
|
+
RequestBody,
|
|
26
|
+
ResponseBody,
|
|
27
|
+
RequireAuthentication
|
|
28
|
+
>
|
|
21
29
|
}
|
|
22
|
-
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {RestApiRoute} from './RestApiRoute'
|
|
2
|
-
import {RestPathParams, RestQueryParams, RestRequestBody, RestRequestHeaders, RestResponseBody} from './common'
|
|
1
|
+
import type {RestApiRoute} from './RestApiRoute'
|
|
2
|
+
import type {RestPathParams, RestQueryParams, RestRequestBody, RestRequestHeaders, RestResponseBody} from './common'
|
|
3
3
|
|
|
4
4
|
export type RestApiRouteWithAuthentication<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
PathParams extends RestPathParams = never,
|
|
6
|
+
QueryParams extends RestQueryParams = never,
|
|
7
|
+
RequestHeaders extends RestRequestHeaders = never,
|
|
8
|
+
RequestBody extends RestRequestBody = never,
|
|
9
|
+
ResponseBody extends RestResponseBody = never,
|
|
10
10
|
> = RestApiRoute<PathParams, QueryParams, RequestHeaders, RequestBody, ResponseBody, true>
|
|
11
|
-
|
|
12
|
-
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {BearerToken} from
|
|
2
|
-
import {RestRequestHeaders} from './RestRequestHeaders'
|
|
3
|
-
import {RestRequireAuthentication} from './RestRequireAuthentication'
|
|
1
|
+
import type {BearerToken} from './BearerToken'
|
|
2
|
+
import type {RestRequestHeaders} from './RestRequestHeaders'
|
|
3
|
+
import type {RestRequireAuthentication} from './RestRequireAuthentication'
|
|
4
4
|
|
|
5
|
-
export type AuthorizationHeader = {
|
|
5
|
+
export type AuthorizationHeader = {Authorization: BearerToken}
|
|
6
6
|
export type RestRequestHeadersWithAuthorization<
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
RequestHeaders extends RestRequestHeaders,
|
|
8
|
+
RequireAuthentication extends RestRequireAuthentication,
|
|
9
9
|
> = RequireAuthentication extends true
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
? [RequestHeaders] extends [never]
|
|
11
|
+
? AuthorizationHeader
|
|
12
|
+
: RequestHeaders & AuthorizationHeader
|
|
13
|
+
: RequestHeaders
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export * from './BearerToken'
|
|
2
|
-
export * from './RestRequestHeadersWithAuthorization'
|
|
3
|
-
export * from './RestPathParams'
|
|
4
|
-
export * from './RestQueryParams'
|
|
5
|
-
export * from './RestRequestBody'
|
|
6
|
-
export * from './RestRequestHeaders'
|
|
7
|
-
export * from './RestRequireAuthentication'
|
|
8
|
-
export * from './RestResponseBody'
|
|
1
|
+
export * from './BearerToken'
|
|
2
|
+
export * from './RestRequestHeadersWithAuthorization'
|
|
3
|
+
export * from './RestPathParams'
|
|
4
|
+
export * from './RestQueryParams'
|
|
5
|
+
export * from './RestRequestBody'
|
|
6
|
+
export * from './RestRequestHeaders'
|
|
7
|
+
export * from './RestRequireAuthentication'
|
|
8
|
+
export * from './RestResponseBody'
|