@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.
Files changed (35) hide show
  1. package/package.json +3 -5
  2. package/src/__mocks__/ignoreConsoleErrors.ts +10 -12
  3. package/src/rest/client/fetchRestApi.ts +33 -31
  4. package/src/rest/server/RestApi.ts +66 -57
  5. package/src/rest/server/buildRestApiRouteHandler.ts +18 -11
  6. package/src/rest/server/index.ts +2 -2
  7. package/src/rest/types/RestApiRequest.ts +10 -10
  8. package/src/rest/types/RestApiRequestHandler.ts +13 -13
  9. package/src/rest/types/RestApiRequestHandlerWithAuthentication.ts +7 -9
  10. package/src/rest/types/RestApiResponse.ts +3 -3
  11. package/src/rest/types/RestApiRoute.ts +13 -15
  12. package/src/rest/types/RestApiRouteHandler.ts +20 -13
  13. package/src/rest/types/RestApiRouteWithAuthentication.ts +7 -9
  14. package/src/rest/types/common/RestRequestHeadersWithAuthorization.ts +10 -8
  15. package/src/rest/types/common/index.ts +8 -8
  16. package/src/rest/types/index.ts +8 -8
  17. package/src/rest/types/internal/InternalRestApiRequest.ts +14 -12
  18. package/src/types/OmitNever.ts +1 -1
  19. package/src/ws/client/useWsApi.ts +68 -57
  20. package/src/ws/server/WsApi.ts +34 -36
  21. package/src/ws/server/buildWsApiRouteHandler.ts +15 -8
  22. package/src/ws/server/closeConnection.ts +7 -10
  23. package/src/ws/server/getApiGatewayManagementApiClient.ts +7 -8
  24. package/src/ws/server/getConnection.ts +5 -6
  25. package/src/ws/server/index.ts +8 -8
  26. package/src/ws/server/sendResponse.ts +13 -15
  27. package/src/ws/server/trpc/TrpcSubscriptionRequest.ts +10 -8
  28. package/src/ws/server/trpc/TrpcSubscriptionResponse.ts +2 -6
  29. package/src/ws/server/trpc/awsLambdaTrpcSubscriptionRequestHandler.ts +50 -46
  30. package/src/ws/server/trpc/isObservable.ts +3 -6
  31. package/src/ws/types/WsApiRequestHandler.ts +14 -13
  32. package/src/ws/types/WsApiRoute.ts +6 -8
  33. package/src/ws/types/WsApiRouteHandler.ts +7 -9
  34. package/src/ws/types/common/WsApiRequest.ts +2 -2
  35. package/src/ws/types/index.ts +5 -5
@@ -1,65 +1,65 @@
1
- import {PostToConnectionCommand} from '@aws-sdk/client-apigatewaymanagementapi';
2
- import {AnyTRPCRouter, callTRPCProcedure, inferRouterContext} from '@trpc/server';
3
- import {APIGatewayProxyEvent, APIGatewayProxyResult} from 'aws-lambda';
4
- import {getApiGatewayManagementApiClient} from '../getApiGatewayManagementApiClient';
5
- import {getConnection} from '../getConnection';
6
- import {TrpcSubscriptionRequest} from './TrpcSubscriptionRequest';
7
- import {TrpcSubscriptionResponse} from './TrpcSubscriptionResponse';
8
- import {isObservable} from './isObservable';
1
+ import {GoneException, PostToConnectionCommand} from '@aws-sdk/client-apigatewaymanagementapi'
2
+ import {type AnyTRPCRouter, callTRPCProcedure, type inferRouterContext} from '@trpc/server'
3
+ import type {APIGatewayProxyEvent, APIGatewayProxyResult, Context} from 'aws-lambda'
4
+ import {getApiGatewayManagementApiClient} from '../getApiGatewayManagementApiClient'
5
+ import {getConnection} from '../getConnection'
6
+ import type {TrpcSubscriptionRequest} from './TrpcSubscriptionRequest'
7
+ import type {TrpcSubscriptionResponse} from './TrpcSubscriptionResponse'
8
+ import {isObservable} from './isObservable'
9
9
 
10
10
  export const awsLambdaTrpcSubscriptionRequestHandler = <Router extends AnyTRPCRouter>(opts: {
11
11
  router: Router
12
12
  createContext?: (event: APIGatewayProxyEvent) => inferRouterContext<Router> | Promise<inferRouterContext<Router>>
13
13
  }) => {
14
- const {router, createContext} = opts;
14
+ const {router, createContext} = opts
15
15
 
16
- return async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
17
- const connection = getConnection(event);
16
+ return async (event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> => {
17
+ context.callbackWaitsForEmptyEventLoop = false
18
+ const connection = getConnection(event)
18
19
 
19
- if (!event.body || event.body === '[]')
20
- return {statusCode: 200, body: '{}'};
20
+ if (!event.body || event.body === '[]') return {statusCode: 200, body: '{}'}
21
21
 
22
- const request = (JSON.parse(event.body) as TrpcSubscriptionRequest);
22
+ const request = JSON.parse(event.body) as TrpcSubscriptionRequest
23
23
 
24
24
  const sendMessage = async (response: TrpcSubscriptionResponse) => {
25
25
  await getApiGatewayManagementApiClient(connection.endpoint).send(
26
- new PostToConnectionCommand({
27
- ConnectionId: connection.connectionId,
28
- Data: JSON.stringify(response),
29
- }),
30
- );
31
- };
26
+ new PostToConnectionCommand({
27
+ ConnectionId: connection.connectionId,
28
+ Data: JSON.stringify(response),
29
+ }),
30
+ )
31
+ }
32
32
  const stopConnection = async (): Promise<void> => {
33
33
  await sendMessage({
34
34
  id: request.id,
35
35
  result: {type: 'stopped'},
36
- });
37
- };
36
+ })
37
+ }
38
38
 
39
39
  try {
40
- const messageQueue: TrpcSubscriptionResponse[] = [];
40
+ const messageQueue: TrpcSubscriptionResponse[] = []
41
41
 
42
42
  if (request.method === 'subscription.stop') {
43
- await stopConnection();
43
+ await stopConnection()
44
44
  }
45
45
 
46
46
  if (request.method === 'subscription') {
47
47
  messageQueue.push({
48
48
  id: request.id,
49
49
  result: {type: 'started'},
50
- });
50
+ })
51
51
 
52
- const procedure = (await callTRPCProcedure({
52
+ const procedure = await callTRPCProcedure({
53
53
  procedures: router._def.procedures,
54
54
  path: request.params.path,
55
55
  type: 'subscription',
56
- ctx: await createContext?.(event) || {},
56
+ ctx: (await createContext?.(event)) || {},
57
57
  getRawInput: async () => request.params.input,
58
- }));
58
+ })
59
59
 
60
60
  if (!isObservable(procedure)) {
61
- console.error(`observable`, procedure);
62
- throw `Procedure is not an observable!`;
61
+ console.error(`observable`, procedure)
62
+ throw `Procedure is not an observable!`
63
63
  }
64
64
 
65
65
  procedure.subscribe({
@@ -70,42 +70,46 @@ export const awsLambdaTrpcSubscriptionRequestHandler = <Router extends AnyTRPCRo
70
70
  type: 'data',
71
71
  data: data,
72
72
  },
73
- });
73
+ })
74
74
  },
75
75
  error: (err) => {
76
- console.error(err);
76
+ console.error(err)
77
77
  messageQueue.push({
78
78
  id: request.id,
79
79
  result: {type: 'stopped'},
80
- });
80
+ })
81
81
  },
82
82
  complete: () => {
83
83
  messageQueue.push({
84
84
  id: request.id,
85
85
  result: {type: 'stopped'},
86
- });
86
+ })
87
87
  },
88
- });
88
+ })
89
89
 
90
- let stopped = false;
90
+ let stopped = false
91
91
  while (!stopped) {
92
- const message = messageQueue.shift();
93
- if (!message)
94
- continue;
92
+ if (messageQueue.length === 0) await new Promise((resolve) => setTimeout(resolve, 10))
93
+ const message = messageQueue.shift()
94
+ if (!message) continue
95
95
 
96
- await sendMessage(message);
96
+ await sendMessage(message)
97
97
 
98
- stopped = message.result.type === 'stopped';
98
+ stopped = message.result.type === 'stopped'
99
99
  }
100
100
  }
101
101
  } catch (err) {
102
- console.error(err);
103
- await stopConnection();
102
+ if (err instanceof GoneException) {
103
+ console.info('Connection closed by client')
104
+ } else {
105
+ console.error(err)
106
+ await stopConnection()
107
+ }
104
108
  }
105
109
 
106
110
  return {
107
111
  statusCode: 200,
108
112
  body: '{}',
109
- };
110
- };
111
- };
113
+ }
114
+ }
115
+ }
@@ -1,8 +1,5 @@
1
- import type {Observable} from '@trpc/server/observable';
1
+ import type {Observable} from '@trpc/server/observable'
2
2
 
3
3
  export const isObservable = (value: unknown): value is Observable<unknown, unknown> => {
4
- return !!value
5
- && typeof value === 'object'
6
- && `subscribe` in value
7
- && `pipe` in value;
8
- };
4
+ return !!value && typeof value === 'object' && `subscribe` in value && `pipe` in value
5
+ }
@@ -1,15 +1,16 @@
1
- import {OmitNever} from '../../types/OmitNever';
2
- import {WsApiConnection} from './WsApiConnection';
3
- import {WsApiAction, WsApiRequest, WsApiResponse} from './common';
1
+ import type {OmitNever} from '../../types/OmitNever'
2
+ import type {WsApiConnection} from './WsApiConnection'
3
+ import type {WsApiAction, WsApiRequest, WsApiResponse} from './common'
4
4
 
5
5
  export type WsApiRequestHandler<
6
- Action extends WsApiAction,
7
- Request extends WsApiRequest<Action>,
8
- Response extends WsApiResponse,
9
- > = (request: Request & { action: Action }, responseActions: OmitNever<{
10
- connection: WsApiConnection
11
- sendResponse: [Response] extends [never] ? never : (response: Response) => Promise<void>
12
- closeConnection: () => Promise<void>
13
- }>) => Promise<void>;
14
-
15
-
6
+ Action extends WsApiAction,
7
+ Request extends WsApiRequest<Action>,
8
+ Response extends WsApiResponse,
9
+ > = (
10
+ request: Request & {action: Action},
11
+ responseActions: OmitNever<{
12
+ connection: WsApiConnection
13
+ sendResponse: [Response] extends [never] ? never : (response: Response) => Promise<void>
14
+ closeConnection: () => Promise<void>
15
+ }>,
16
+ ) => Promise<void>
@@ -1,9 +1,9 @@
1
- import {WsApiAction, WsApiRequest, WsApiResponse} from './common';
1
+ import type {WsApiAction, WsApiRequest, WsApiResponse} from './common'
2
2
 
3
3
  export type WsApiRoute<
4
- Action extends WsApiAction,
5
- Request extends WsApiRequest<Action>,
6
- Response extends WsApiResponse,
4
+ Action extends WsApiAction,
5
+ Request extends WsApiRequest<Action>,
6
+ Response extends WsApiResponse,
7
7
  > = {
8
8
  action: Action
9
9
 
@@ -11,7 +11,5 @@ export type WsApiRoute<
11
11
  __types?: {
12
12
  Request: Request
13
13
  Response: Response
14
- };
15
- };
16
-
17
-
14
+ }
15
+ }
@@ -1,14 +1,12 @@
1
- import {WsApiRequestHandler} from './WsApiRequestHandler';
2
- import {WsApiRoute} from './WsApiRoute';
3
- import {WsApiAction, WsApiRequest, WsApiResponse} from './common';
1
+ import type {WsApiRequestHandler} from './WsApiRequestHandler'
2
+ import type {WsApiRoute} from './WsApiRoute'
3
+ import type {WsApiAction, WsApiRequest, WsApiResponse} from './common'
4
4
 
5
5
  export type WsApiRouteHandler<
6
- Action extends WsApiAction,
7
- Request extends WsApiRequest<Action>,
8
- Response extends WsApiResponse,
6
+ Action extends WsApiAction,
7
+ Request extends WsApiRequest<Action>,
8
+ Response extends WsApiResponse,
9
9
  > = {
10
- route: WsApiRoute<Action, Request, Response>,
10
+ route: WsApiRoute<Action, Request, Response>
11
11
  requestHandler: WsApiRequestHandler<Action, Request, Response>
12
12
  }
13
-
14
-
@@ -1,3 +1,3 @@
1
- import {WsApiAction} from './WsApiAction';
1
+ import type {WsApiAction} from './WsApiAction'
2
2
 
3
- export type WsApiRequest<Action extends WsApiAction> = { action: Action }
3
+ export type WsApiRequest<Action extends WsApiAction> = {action: Action}
@@ -1,5 +1,5 @@
1
- export * from './common';
2
- export * from './WsApiConnection';
3
- export * from './WsApiRequestHandler';
4
- export * from './WsApiRoute';
5
- export * from './WsApiRouteHandler';
1
+ export * from './common'
2
+ export * from './WsApiConnection'
3
+ export * from './WsApiRequestHandler'
4
+ export * from './WsApiRoute'
5
+ export * from './WsApiRouteHandler'