@openstax/ts-utils 1.21.11 → 1.23.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.
Files changed (252) hide show
  1. package/dist/cjs/assertions/index.d.ts +85 -0
  2. package/dist/cjs/assertions/index.js +157 -0
  3. package/dist/cjs/aws/ssmService.d.ts +5 -0
  4. package/dist/cjs/aws/ssmService.js +9 -0
  5. package/dist/cjs/config/awsParameterConfig.d.ts +10 -0
  6. package/dist/cjs/config/awsParameterConfig.js +26 -0
  7. package/dist/cjs/config/envConfig.d.ts +24 -0
  8. package/dist/cjs/config/envConfig.js +57 -0
  9. package/dist/cjs/config/index.d.ts +48 -0
  10. package/dist/cjs/config/index.js +35 -0
  11. package/dist/cjs/config/lambdaParameterConfig.d.ts +12 -0
  12. package/dist/cjs/config/lambdaParameterConfig.js +45 -0
  13. package/dist/cjs/config/replaceConfig.d.ts +14 -0
  14. package/dist/cjs/config/replaceConfig.js +22 -0
  15. package/dist/cjs/config/resolveConfigValue.d.ts +5 -0
  16. package/dist/cjs/config/resolveConfigValue.js +12 -0
  17. package/dist/cjs/errors/index.d.ts +77 -0
  18. package/dist/cjs/errors/index.js +109 -0
  19. package/dist/cjs/fetch/fetchStatusRetry.d.ts +7 -0
  20. package/dist/cjs/fetch/fetchStatusRetry.js +16 -0
  21. package/dist/cjs/fetch/index.d.ts +64 -0
  22. package/dist/cjs/fetch/index.js +55 -0
  23. package/dist/cjs/guards/index.d.ts +30 -0
  24. package/dist/cjs/guards/index.js +35 -0
  25. package/dist/cjs/index.d.ts +4 -0
  26. package/dist/cjs/index.js +20 -0
  27. package/dist/cjs/middleware/apiErrorHandler.d.ts +24 -0
  28. package/dist/cjs/middleware/apiErrorHandler.js +41 -0
  29. package/dist/cjs/middleware/apiSlowResponseMiddleware.d.ts +23 -0
  30. package/dist/cjs/middleware/apiSlowResponseMiddleware.js +54 -0
  31. package/dist/cjs/middleware/index.d.ts +47 -0
  32. package/dist/cjs/middleware/index.js +48 -0
  33. package/dist/cjs/middleware/lambdaCorsResponseMiddleware.d.ts +20 -0
  34. package/dist/cjs/middleware/lambdaCorsResponseMiddleware.js +42 -0
  35. package/dist/cjs/middleware/throwNotFoundMiddleware.d.ts +4 -0
  36. package/dist/cjs/middleware/throwNotFoundMiddleware.js +14 -0
  37. package/dist/cjs/misc/hashValue.d.ts +10 -0
  38. package/dist/cjs/misc/hashValue.js +17 -0
  39. package/dist/cjs/misc/helpers.d.ts +124 -0
  40. package/dist/cjs/misc/helpers.js +214 -0
  41. package/dist/cjs/misc/merge.d.ts +21 -0
  42. package/dist/cjs/misc/merge.js +45 -0
  43. package/dist/cjs/misc/partitionSequence.d.ts +35 -0
  44. package/dist/cjs/misc/partitionSequence.js +55 -0
  45. package/dist/cjs/pagination/index.d.ts +91 -0
  46. package/dist/cjs/pagination/index.js +83 -0
  47. package/dist/cjs/routing/helpers.d.ts +57 -0
  48. package/dist/cjs/routing/helpers.js +90 -0
  49. package/dist/cjs/routing/index.d.ts +272 -0
  50. package/dist/cjs/routing/index.js +270 -0
  51. package/dist/cjs/routing/validators/zod.d.ts +4 -0
  52. package/dist/cjs/routing/validators/zod.js +12 -0
  53. package/dist/cjs/services/accountsGateway/index.d.ts +85 -0
  54. package/dist/cjs/services/accountsGateway/index.js +118 -0
  55. package/dist/cjs/services/apiGateway/index.d.ts +63 -0
  56. package/dist/cjs/services/apiGateway/index.js +108 -0
  57. package/dist/cjs/services/authProvider/browser.d.ts +74 -0
  58. package/dist/cjs/services/authProvider/browser.js +154 -0
  59. package/dist/cjs/services/authProvider/decryption.d.ts +19 -0
  60. package/dist/cjs/services/authProvider/decryption.js +61 -0
  61. package/dist/cjs/services/authProvider/index.d.ts +61 -0
  62. package/dist/cjs/services/authProvider/index.js +26 -0
  63. package/dist/cjs/services/authProvider/subrequest.d.ts +16 -0
  64. package/dist/cjs/services/authProvider/subrequest.js +50 -0
  65. package/dist/cjs/services/authProvider/utils/decryptAndVerify.d.ts +29 -0
  66. package/dist/cjs/services/authProvider/utils/decryptAndVerify.js +91 -0
  67. package/dist/cjs/services/authProvider/utils/embeddedAuthProvider.d.ts +26 -0
  68. package/dist/cjs/services/authProvider/utils/embeddedAuthProvider.js +47 -0
  69. package/dist/cjs/services/authProvider/utils/userRoleValidator.d.ts +13 -0
  70. package/dist/cjs/services/authProvider/utils/userRoleValidator.js +37 -0
  71. package/dist/cjs/services/documentStore/dynamoEncoding.d.ts +10 -0
  72. package/dist/cjs/services/documentStore/dynamoEncoding.js +52 -0
  73. package/dist/cjs/services/documentStore/index.d.ts +14 -0
  74. package/dist/cjs/services/documentStore/index.js +2 -0
  75. package/dist/cjs/services/documentStore/unversioned/dynamodb.d.ts +16 -0
  76. package/dist/cjs/services/documentStore/unversioned/dynamodb.js +122 -0
  77. package/dist/cjs/services/documentStore/unversioned/file-system.d.ts +18 -0
  78. package/dist/cjs/services/documentStore/unversioned/file-system.js +121 -0
  79. package/dist/cjs/services/documentStore/unversioned/index.d.ts +2 -0
  80. package/dist/cjs/services/documentStore/unversioned/index.js +2 -0
  81. package/dist/cjs/services/documentStore/versioned/dynamodb.d.ts +22 -0
  82. package/dist/cjs/services/documentStore/versioned/dynamodb.js +135 -0
  83. package/dist/cjs/services/documentStore/versioned/file-system.d.ts +24 -0
  84. package/dist/cjs/services/documentStore/versioned/file-system.js +62 -0
  85. package/dist/cjs/services/documentStore/versioned/index.d.ts +17 -0
  86. package/dist/cjs/services/documentStore/versioned/index.js +2 -0
  87. package/dist/cjs/services/exercisesGateway/index.d.ts +71 -0
  88. package/dist/cjs/services/exercisesGateway/index.js +97 -0
  89. package/dist/cjs/services/fileServer/index.d.ts +17 -0
  90. package/dist/cjs/services/fileServer/index.js +19 -0
  91. package/dist/cjs/services/fileServer/localFileServer.d.ts +13 -0
  92. package/dist/cjs/services/fileServer/localFileServer.js +23 -0
  93. package/dist/cjs/services/fileServer/s3FileServer.d.ts +16 -0
  94. package/dist/cjs/services/fileServer/s3FileServer.js +25 -0
  95. package/dist/cjs/services/launchParams/index.d.ts +2 -0
  96. package/dist/cjs/services/launchParams/index.js +7 -0
  97. package/dist/cjs/services/launchParams/signer.d.ts +27 -0
  98. package/dist/cjs/services/launchParams/signer.js +58 -0
  99. package/dist/cjs/services/launchParams/verifier.d.ts +22 -0
  100. package/dist/cjs/services/launchParams/verifier.js +94 -0
  101. package/dist/cjs/services/logger/console.d.ts +4 -0
  102. package/dist/cjs/services/logger/console.js +12 -0
  103. package/dist/cjs/services/logger/index.d.ts +39 -0
  104. package/dist/cjs/services/logger/index.js +31 -0
  105. package/dist/cjs/services/lrsGateway/addStatementDefaultFields.d.ts +5 -0
  106. package/dist/cjs/services/lrsGateway/addStatementDefaultFields.js +21 -0
  107. package/dist/cjs/services/lrsGateway/attempt-utils.d.ts +70 -0
  108. package/dist/cjs/services/lrsGateway/attempt-utils.js +258 -0
  109. package/dist/cjs/services/lrsGateway/file-system.d.ts +17 -0
  110. package/dist/cjs/services/lrsGateway/file-system.js +140 -0
  111. package/dist/cjs/services/lrsGateway/index.d.ts +125 -0
  112. package/dist/cjs/services/lrsGateway/index.js +138 -0
  113. package/dist/cjs/services/lrsGateway/xapiUtils.d.ts +61 -0
  114. package/dist/cjs/services/lrsGateway/xapiUtils.js +94 -0
  115. package/dist/cjs/services/postgresConnection/index.d.ts +35 -0
  116. package/dist/cjs/services/postgresConnection/index.js +63 -0
  117. package/dist/cjs/services/searchProvider/index.d.ts +31 -0
  118. package/dist/cjs/services/searchProvider/index.js +2 -0
  119. package/dist/cjs/services/searchProvider/memorySearchTheBadWay.d.ts +14 -0
  120. package/dist/cjs/services/searchProvider/memorySearchTheBadWay.js +89 -0
  121. package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -0
  122. package/dist/cjs/types.d.ts +31 -0
  123. package/dist/cjs/types.js +2 -0
  124. package/dist/esm/assertions/index.d.ts +85 -0
  125. package/dist/esm/assertions/index.js +146 -0
  126. package/dist/esm/aws/ssmService.d.ts +5 -0
  127. package/dist/esm/aws/ssmService.js +6 -0
  128. package/dist/esm/config/awsParameterConfig.d.ts +10 -0
  129. package/dist/esm/config/awsParameterConfig.js +22 -0
  130. package/dist/esm/config/envConfig.d.ts +24 -0
  131. package/dist/esm/config/envConfig.js +53 -0
  132. package/dist/esm/config/index.d.ts +48 -0
  133. package/dist/esm/config/index.js +17 -0
  134. package/dist/esm/config/lambdaParameterConfig.d.ts +12 -0
  135. package/dist/esm/config/lambdaParameterConfig.js +38 -0
  136. package/dist/esm/config/replaceConfig.d.ts +14 -0
  137. package/dist/esm/config/replaceConfig.js +18 -0
  138. package/dist/esm/config/resolveConfigValue.d.ts +5 -0
  139. package/dist/esm/config/resolveConfigValue.js +8 -0
  140. package/dist/esm/errors/index.d.ts +77 -0
  141. package/dist/esm/errors/index.js +99 -0
  142. package/dist/esm/fetch/fetchStatusRetry.d.ts +7 -0
  143. package/dist/esm/fetch/fetchStatusRetry.js +12 -0
  144. package/dist/esm/fetch/index.d.ts +64 -0
  145. package/dist/esm/fetch/index.js +46 -0
  146. package/dist/esm/guards/index.d.ts +30 -0
  147. package/dist/esm/guards/index.js +28 -0
  148. package/dist/esm/index.d.ts +4 -0
  149. package/dist/esm/index.js +4 -0
  150. package/dist/esm/middleware/apiErrorHandler.d.ts +24 -0
  151. package/dist/esm/middleware/apiErrorHandler.js +37 -0
  152. package/dist/esm/middleware/apiSlowResponseMiddleware.d.ts +23 -0
  153. package/dist/esm/middleware/apiSlowResponseMiddleware.js +50 -0
  154. package/dist/esm/middleware/index.d.ts +47 -0
  155. package/dist/esm/middleware/index.js +44 -0
  156. package/dist/esm/middleware/lambdaCorsResponseMiddleware.d.ts +20 -0
  157. package/dist/esm/middleware/lambdaCorsResponseMiddleware.js +38 -0
  158. package/dist/esm/middleware/throwNotFoundMiddleware.d.ts +4 -0
  159. package/dist/esm/middleware/throwNotFoundMiddleware.js +10 -0
  160. package/dist/esm/misc/hashValue.d.ts +10 -0
  161. package/dist/esm/misc/hashValue.js +13 -0
  162. package/dist/esm/misc/helpers.d.ts +124 -0
  163. package/dist/esm/misc/helpers.js +199 -0
  164. package/dist/esm/misc/merge.d.ts +21 -0
  165. package/dist/esm/misc/merge.js +40 -0
  166. package/dist/esm/misc/partitionSequence.d.ts +35 -0
  167. package/dist/esm/misc/partitionSequence.js +48 -0
  168. package/dist/esm/pagination/index.d.ts +91 -0
  169. package/dist/esm/pagination/index.js +77 -0
  170. package/dist/esm/routing/helpers.d.ts +57 -0
  171. package/dist/esm/routing/helpers.js +83 -0
  172. package/dist/esm/routing/index.d.ts +272 -0
  173. package/dist/esm/routing/index.js +232 -0
  174. package/dist/esm/routing/validators/zod.d.ts +4 -0
  175. package/dist/esm/routing/validators/zod.js +8 -0
  176. package/dist/esm/services/accountsGateway/index.d.ts +85 -0
  177. package/dist/esm/services/accountsGateway/index.js +111 -0
  178. package/dist/esm/services/apiGateway/index.d.ts +63 -0
  179. package/dist/esm/services/apiGateway/index.js +77 -0
  180. package/dist/esm/services/authProvider/browser.d.ts +74 -0
  181. package/dist/esm/services/authProvider/browser.js +150 -0
  182. package/dist/esm/services/authProvider/decryption.d.ts +19 -0
  183. package/dist/esm/services/authProvider/decryption.js +57 -0
  184. package/dist/esm/services/authProvider/index.d.ts +61 -0
  185. package/dist/esm/services/authProvider/index.js +18 -0
  186. package/dist/esm/services/authProvider/subrequest.d.ts +16 -0
  187. package/dist/esm/services/authProvider/subrequest.js +43 -0
  188. package/dist/esm/services/authProvider/utils/decryptAndVerify.d.ts +29 -0
  189. package/dist/esm/services/authProvider/utils/decryptAndVerify.js +85 -0
  190. package/dist/esm/services/authProvider/utils/embeddedAuthProvider.d.ts +26 -0
  191. package/dist/esm/services/authProvider/utils/embeddedAuthProvider.js +40 -0
  192. package/dist/esm/services/authProvider/utils/userRoleValidator.d.ts +13 -0
  193. package/dist/esm/services/authProvider/utils/userRoleValidator.js +33 -0
  194. package/dist/esm/services/documentStore/dynamoEncoding.d.ts +10 -0
  195. package/dist/esm/services/documentStore/dynamoEncoding.js +45 -0
  196. package/dist/esm/services/documentStore/index.d.ts +14 -0
  197. package/dist/esm/services/documentStore/index.js +1 -0
  198. package/dist/esm/services/documentStore/unversioned/dynamodb.d.ts +16 -0
  199. package/dist/esm/services/documentStore/unversioned/dynamodb.js +118 -0
  200. package/dist/esm/services/documentStore/unversioned/file-system.d.ts +18 -0
  201. package/dist/esm/services/documentStore/unversioned/file-system.js +91 -0
  202. package/dist/esm/services/documentStore/unversioned/index.d.ts +2 -0
  203. package/dist/esm/services/documentStore/unversioned/index.js +1 -0
  204. package/dist/esm/services/documentStore/versioned/dynamodb.d.ts +22 -0
  205. package/dist/esm/services/documentStore/versioned/dynamodb.js +131 -0
  206. package/dist/esm/services/documentStore/versioned/file-system.d.ts +24 -0
  207. package/dist/esm/services/documentStore/versioned/file-system.js +58 -0
  208. package/dist/esm/services/documentStore/versioned/index.d.ts +17 -0
  209. package/dist/esm/services/documentStore/versioned/index.js +1 -0
  210. package/dist/esm/services/exercisesGateway/index.d.ts +71 -0
  211. package/dist/esm/services/exercisesGateway/index.js +70 -0
  212. package/dist/esm/services/fileServer/index.d.ts +17 -0
  213. package/dist/esm/services/fileServer/index.js +13 -0
  214. package/dist/esm/services/fileServer/localFileServer.d.ts +13 -0
  215. package/dist/esm/services/fileServer/localFileServer.js +16 -0
  216. package/dist/esm/services/fileServer/s3FileServer.d.ts +16 -0
  217. package/dist/esm/services/fileServer/s3FileServer.js +21 -0
  218. package/dist/esm/services/launchParams/index.d.ts +2 -0
  219. package/dist/esm/services/launchParams/index.js +2 -0
  220. package/dist/esm/services/launchParams/signer.d.ts +27 -0
  221. package/dist/esm/services/launchParams/signer.js +51 -0
  222. package/dist/esm/services/launchParams/verifier.d.ts +22 -0
  223. package/dist/esm/services/launchParams/verifier.js +67 -0
  224. package/dist/esm/services/logger/console.d.ts +4 -0
  225. package/dist/esm/services/logger/console.js +8 -0
  226. package/dist/esm/services/logger/index.d.ts +39 -0
  227. package/dist/esm/services/logger/index.js +27 -0
  228. package/dist/esm/services/lrsGateway/addStatementDefaultFields.d.ts +5 -0
  229. package/dist/esm/services/lrsGateway/addStatementDefaultFields.js +14 -0
  230. package/dist/esm/services/lrsGateway/attempt-utils.d.ts +70 -0
  231. package/dist/esm/services/lrsGateway/attempt-utils.js +236 -0
  232. package/dist/esm/services/lrsGateway/file-system.d.ts +17 -0
  233. package/dist/esm/services/lrsGateway/file-system.js +110 -0
  234. package/dist/esm/services/lrsGateway/index.d.ts +125 -0
  235. package/dist/esm/services/lrsGateway/index.js +111 -0
  236. package/dist/esm/services/lrsGateway/xapiUtils.d.ts +61 -0
  237. package/dist/esm/services/lrsGateway/xapiUtils.js +84 -0
  238. package/dist/esm/services/postgresConnection/index.d.ts +35 -0
  239. package/dist/esm/services/postgresConnection/index.js +56 -0
  240. package/dist/esm/services/searchProvider/index.d.ts +31 -0
  241. package/dist/esm/services/searchProvider/index.js +1 -0
  242. package/dist/esm/services/searchProvider/memorySearchTheBadWay.d.ts +14 -0
  243. package/dist/esm/services/searchProvider/memorySearchTheBadWay.js +85 -0
  244. package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -0
  245. package/dist/esm/types.d.ts +31 -0
  246. package/dist/esm/types.js +1 -0
  247. package/package.json +16 -16
  248. package/script/bin/deploy.bash +8 -0
  249. package/script/bin/get-env-param.bash +3 -3
  250. package/script/bin/init-params-script.bash +10 -1
  251. package/script/bin/upload-params.bash +3 -3
  252. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pageNumberPagination = exports.loadMorePagination = exports.createPaginationMiddleware = void 0;
4
+ const assertions_1 = require("../assertions");
5
+ const errors_1 = require("../errors");
6
+ const routing_1 = require("../routing");
7
+ /**
8
+ * helper to create middleware with the given paginator. aside from taking care of annoying to write pagination logic, these helpers also make
9
+ * sure that all item list responses have the same formatting.
10
+ *
11
+ * eg:
12
+ * const getQueryParams = getKeyValueOr('queryStringParameters', {} as QueryParams);
13
+ * const setUnusedQueryParams = putKeyValue('queryStringParameters');
14
+ *
15
+ * export const loadMorePaginationMiddleware = createPaginationMiddleware<ApiRouteRequest>()({getQueryParams, setUnusedQueryParams, paginator: loadMorePagination});
16
+ * export const pageNumberPaginationMiddleware = createPaginationMiddleware<ApiRouteRequest>()({getQueryParams, setUnusedQueryParams, paginator: pageNumberPagination});
17
+ *
18
+ * eg the pagination middleware then provides your necessary inputs (getPageToken... in this case) and formats the response:
19
+ * const result = await services.myDocumentStore.getVersions(key, services.pagination.getPageTokenNumber());
20
+ *
21
+ * if (!result) {
22
+ * throw new NotFoundError('requested item not found');
23
+ * }
24
+ *
25
+ * return apiJsonResponse(200, services.pagination.getPaginationResponse(result));
26
+ */
27
+ const createPaginationMiddleware = () => ({ getQueryParams, setUnusedQueryParams, paginator }) => () => (middleware, match) => {
28
+ const queryParams = getQueryParams(middleware.request);
29
+ const pagination = paginator(queryParams, match);
30
+ // remove pagination params from downstream logic
31
+ middleware.request = setUnusedQueryParams(middleware.request, pagination.getUnusedQueryParams());
32
+ return { ...middleware, pagination };
33
+ };
34
+ exports.createPaginationMiddleware = createPaginationMiddleware;
35
+ const loadMorePagination = (queryParams, { route, params }) => {
36
+ const { pageToken, ...otherParams } = queryParams;
37
+ return {
38
+ getUnusedQueryParams: () => otherParams,
39
+ getPageTokenString: () => pageToken,
40
+ getPageTokenNumber: () => pageToken && typeof pageToken === 'string'
41
+ ? (0, assertions_1.notNaN)(parseInt(pageToken, 10), () => { throw new errors_1.InvalidRequestError(); })
42
+ : undefined,
43
+ getPaginationResponse: ({ items, ...meta }) => {
44
+ return {
45
+ items,
46
+ meta,
47
+ links: {
48
+ nextPage: meta.nextPageToken
49
+ ? (0, routing_1.renderAnyRouteUrl)(route, params, { ...queryParams, pageToken: meta.nextPageToken.toString() })
50
+ : undefined,
51
+ }
52
+ };
53
+ },
54
+ };
55
+ };
56
+ exports.loadMorePagination = loadMorePagination;
57
+ const pageNumberPagination = (queryParams, { route, params }) => {
58
+ const { page, ...otherParams } = queryParams;
59
+ const numberPage = page && typeof page === 'string'
60
+ ? (0, assertions_1.notNaN)(parseInt(page, 10), () => { throw new errors_1.InvalidRequestError(); })
61
+ : undefined;
62
+ return {
63
+ getUnusedQueryParams: () => otherParams,
64
+ getPaginationParams: () => ({ page: numberPage }),
65
+ getPaginationResponse: ({ items, ...meta }) => {
66
+ return {
67
+ items,
68
+ meta,
69
+ links: {
70
+ firstPage: (0, routing_1.renderAnyRouteUrl)(route, params, { ...queryParams, page: '1' }),
71
+ lastPage: (0, routing_1.renderAnyRouteUrl)(route, params, { ...queryParams, page: meta.totalPages.toString() }),
72
+ nextPage: meta.currentPage < meta.totalPages
73
+ ? (0, routing_1.renderAnyRouteUrl)(route, params, { ...queryParams, page: (meta.currentPage + 1).toString() })
74
+ : undefined,
75
+ prevPage: meta.currentPage > 1
76
+ ? (0, routing_1.renderAnyRouteUrl)(route, params, { ...queryParams, page: (meta.currentPage - 1).toString() })
77
+ : undefined
78
+ }
79
+ };
80
+ },
81
+ };
82
+ };
83
+ exports.pageNumberPagination = pageNumberPagination;
@@ -0,0 +1,57 @@
1
+ import type { HttpHeaders } from '.';
2
+ /**
3
+ * Get the value of a header, case insensitive; note if there are multiple headers of the same
4
+ * value, this only returns the first value
5
+ *
6
+ * @param headers
7
+ * @param name the name of the header, case ignored
8
+ */
9
+ export declare const getHeader: (headers: HttpHeaders, name: string) => string | undefined;
10
+ /**
11
+ * Gets the body of a request
12
+ * @param request
13
+ * @throws InvalidRequestError if the content type is not application/json or not parsable
14
+ */
15
+ export declare const getRequestBody: (request: {
16
+ headers: HttpHeaders;
17
+ body?: string | undefined;
18
+ }) => any;
19
+ /**
20
+ * stub validator because writing validators is annoying
21
+ */
22
+ export declare const unsafePayloadValidator: <T>() => (input: any) => input is T;
23
+ /**
24
+ * Middleware that validates the request payload and adds it to the middleware (with key `payload`)
25
+ * so it can be accessed downstream.
26
+ *
27
+ * This middleware accomplishes a few things:
28
+ * - establishes type of payload for route body logic
29
+ * - validates the payload for route logic
30
+ * - establishes type of payload for client logic calling this route
31
+ *
32
+ * @param validator a guard function that takes the request payload and returns true if it is valid,
33
+ * narrowing the type of the payload to the correct type
34
+ * @throws InvalidRequestError if the payload is not valid
35
+ *
36
+ * @example
37
+ * export const exampleRoute = createRoute({
38
+ * name: 'exampleRoute', method: METHOD.POST, path: '/example/:id',
39
+ * requestServiceProvider: composeServiceMiddleware(
40
+ * // here we are adding to previously composed middleware
41
+ * requestServiceProvider,
42
+ * requestPayloadProvider(validatePayload)
43
+ * )},
44
+ * async(params: {id: string}, services) => {
45
+ * const result = await services.myDocumentStore.putItem({
46
+ * ...services.payload,
47
+ * id: params.id,
48
+ * });
49
+ * return apiJsonResponse(201, result);
50
+ * }
51
+ * );
52
+ */
53
+ export declare const requestPayloadProvider: <T>(validator: (input: any) => input is T) => () => <M extends {
54
+ request: Parameters<typeof getRequestBody>[0];
55
+ }>(requestServices: M) => M & {
56
+ payload: T;
57
+ };
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestPayloadProvider = exports.unsafePayloadValidator = exports.getRequestBody = exports.getHeader = void 0;
4
+ const assertions_1 = require("../assertions");
5
+ const errors_1 = require("../errors");
6
+ const guards_1 = require("../guards");
7
+ /**
8
+ * Get the value of a header, case insensitive; note if there are multiple headers of the same
9
+ * value, this only returns the first value
10
+ *
11
+ * @param headers
12
+ * @param name the name of the header, case ignored
13
+ */
14
+ const getHeader = (headers, name) => {
15
+ const key = Object.keys(headers).find(header => header.toLowerCase() === name.toLowerCase());
16
+ const value = key ? headers[key] : undefined;
17
+ return value instanceof Array
18
+ ? value[0]
19
+ : value;
20
+ };
21
+ exports.getHeader = getHeader;
22
+ /**
23
+ * Gets the body of a request
24
+ * @param request
25
+ * @throws InvalidRequestError if the content type is not application/json or not parsable
26
+ */
27
+ const getRequestBody = (request) => {
28
+ if ((0, exports.getHeader)(request.headers, 'content-type') !== 'application/json') {
29
+ throw new errors_1.InvalidRequestError('unknown content type: ' + (0, exports.getHeader)(request.headers, 'content-type'));
30
+ }
31
+ if (!request.body) {
32
+ return {};
33
+ }
34
+ try {
35
+ return JSON.parse(request.body);
36
+ }
37
+ catch (error) {
38
+ // Since the body is provided by the user, invalid JSON in the body is an invalid request
39
+ // We return the message which tells them why the JSON is invalid, but no backtrace
40
+ throw new errors_1.InvalidRequestError((0, assertions_1.assertErrorInstanceOf)(error, SyntaxError).message);
41
+ }
42
+ };
43
+ exports.getRequestBody = getRequestBody;
44
+ /* utils and middleware for loading request payload (must follow this pattern for `PayloadForRoute` to work) */
45
+ /**
46
+ * stub validator because writing validators is annoying
47
+ */
48
+ const unsafePayloadValidator = () => (input) => {
49
+ return (0, guards_1.isPlainObject)(input) && Object.keys(input).length > 0;
50
+ };
51
+ exports.unsafePayloadValidator = unsafePayloadValidator;
52
+ /**
53
+ * Middleware that validates the request payload and adds it to the middleware (with key `payload`)
54
+ * so it can be accessed downstream.
55
+ *
56
+ * This middleware accomplishes a few things:
57
+ * - establishes type of payload for route body logic
58
+ * - validates the payload for route logic
59
+ * - establishes type of payload for client logic calling this route
60
+ *
61
+ * @param validator a guard function that takes the request payload and returns true if it is valid,
62
+ * narrowing the type of the payload to the correct type
63
+ * @throws InvalidRequestError if the payload is not valid
64
+ *
65
+ * @example
66
+ * export const exampleRoute = createRoute({
67
+ * name: 'exampleRoute', method: METHOD.POST, path: '/example/:id',
68
+ * requestServiceProvider: composeServiceMiddleware(
69
+ * // here we are adding to previously composed middleware
70
+ * requestServiceProvider,
71
+ * requestPayloadProvider(validatePayload)
72
+ * )},
73
+ * async(params: {id: string}, services) => {
74
+ * const result = await services.myDocumentStore.putItem({
75
+ * ...services.payload,
76
+ * id: params.id,
77
+ * });
78
+ * return apiJsonResponse(201, result);
79
+ * }
80
+ * );
81
+ */
82
+ const requestPayloadProvider = (validator) => () => (requestServices) => {
83
+ const payload = (0, exports.getRequestBody)(requestServices.request);
84
+ // for more precise error messages, throw your own InvalidRequestError from your validator function
85
+ if (!validator(payload)) {
86
+ throw new errors_1.InvalidRequestError();
87
+ }
88
+ return { ...requestServices, payload };
89
+ };
90
+ exports.requestPayloadProvider = requestPayloadProvider;
@@ -0,0 +1,272 @@
1
+ import { Logger } from '../services/logger';
2
+ /** HTTP query parameters */
3
+ export declare type QueryParams = Record<string, string | undefined | string[] | null>;
4
+ /**
5
+ * The type for a map of string substitutions to use when building route paths, e.g. a route may
6
+ * be defined as `'/api/:id'` and then rendered as `'/api/123'` when the `id` route param is set
7
+ * to `'123'`
8
+ */
9
+ export declare type RouteParams = {
10
+ [key: string]: string;
11
+ };
12
+ /** A type that is compatible with any `Route` type */
13
+ export declare type AnyRoute<R> = R extends Route<infer N, infer P, infer Sa, infer Sr, infer Ri, infer Ro> ? Route<N, P, Sa, Sr, Ri, Ro> : never;
14
+ export declare type AnySpecificRoute<R, Sa, Ri, Ro> = R extends Route<infer N, infer P, Sa, infer Sr, Ri, Ro> & infer E ? Route<N, P, Sa, Sr, Ri, Ro> & E : never;
15
+ /** The inferred "route output" (`Ro`) type for a given route */
16
+ export declare type OutputForRoute<R> = R extends Route<any, any, any, any, any, infer Ro> ? Ro : never;
17
+ /** The inferred type for the params of the provided route type, `R`; may be undefined */
18
+ export declare type ParamsForRoute<R> = R extends Route<any, infer P, any, any, any, any> ? P : never;
19
+ /** The inferred type for the request services of the provided route type, `R`. */
20
+ export declare type RequestServicesForRoute<R> = R extends Route<any, any, any, infer Sr, any, any> ? Sr : never;
21
+ /** The type for the params of the provided route type, `R`; will be `{}` if undefined */
22
+ export declare type ParamsForRouteOrEmpty<R> = ParamsForRoute<R> extends undefined ? {} : Exclude<ParamsForRoute<R>, undefined>;
23
+ /** derives the route match type for this route, which includes the route itself and the matching params. */
24
+ export declare type RouteMatchRecord<R> = R extends AnyRoute<R> ? {
25
+ route: R;
26
+ params: ParamsForRoute<R>;
27
+ } : never;
28
+ /**
29
+ * The conditional type for the payload for a given route, `R`. This isn't a route structure, its
30
+ * a convention based on the request middleware
31
+ */
32
+ export declare type PayloadForRoute<R> = RequestServicesForRoute<R> extends {
33
+ payload: any;
34
+ } ? RequestServicesForRoute<R>['payload'] : undefined;
35
+ declare type RequestServiceProvider<Sa, Sr, Ri> = (app: Sa) => <R>(middleware: {
36
+ request: Ri;
37
+ logger: Logger;
38
+ }, match: RouteMatchRecord<R>) => Sr;
39
+ declare type RouteHandler<P, Sr, Ro> = (params: P, request: Sr) => Ro;
40
+ declare type Route<N extends string, P extends RouteParams | undefined, Sa, Sr, Ri, Ro> = (Sr extends undefined ? {
41
+ requestServiceProvider?: RequestServiceProvider<Sa, Sr, Ri> | undefined;
42
+ } : {
43
+ requestServiceProvider: RequestServiceProvider<Sa, Sr, Ri>;
44
+ }) & {
45
+ name: N;
46
+ path: string;
47
+ handler: (params: P, request: Sr) => Ro;
48
+ };
49
+ declare type CreateRouteConfig<Sa, Sr, Ri, N extends string, Ex> = (Sr extends undefined ? {
50
+ requestServiceProvider?: RequestServiceProvider<Sa, Sr, Ri> | undefined;
51
+ } : {
52
+ requestServiceProvider: RequestServiceProvider<Sa, Sr, Ri>;
53
+ }) & {
54
+ name: N;
55
+ path: string;
56
+ } & Ex;
57
+ /**
58
+ * Interface for a function that creates a route. There are two overloaded signatures, because
59
+ * sometimes typescript can't figure out the value of `Sr` between the handler and the service
60
+ * provider. Forcing it through the provider types first by putting the handler in a subsequent
61
+ * argument seems to help.
62
+ */
63
+ export interface CreateRoute<Sa, Ri, Ex> {
64
+ <N extends string, Ro, Sr extends unknown | undefined = undefined, P extends RouteParams | undefined = undefined>(config: CreateRouteConfig<Sa, Sr, Ri, N, Ex> & {
65
+ handler: RouteHandler<P, Sr, Ro>;
66
+ }): Route<N, P, Sa, Sr, Ri, Ro> & Ex;
67
+ <N extends string, Ro, Sr extends unknown | undefined, P extends RouteParams | undefined = undefined>(config: CreateRouteConfig<Sa, Sr, Ri, N, Ex>, handler: RouteHandler<P, Sr, Ro>): Route<N, P, Sa, Sr, Ri, Ro> & Ex;
68
+ }
69
+ /**
70
+ * Makes a createRoute function that can be used to create routes (this is a factory factory). The
71
+ * `makeCreateRoute` function is typically called once in the backend and once in the frontend to
72
+ * set the types for the resulting `createRoute` function -- that latter function is called once
73
+ * per route. E.g. for the backend, the call could look like:
74
+ *
75
+ * ```
76
+ * export const createRoute = makeCreateRoute<AppServices, ApiRouteRequest, {
77
+ * method: METHOD;
78
+ * }>();
79
+ * ```
80
+ *
81
+ * Notes:
82
+ * * The `{method: METHOD}` defines the `Ex` extension type; here, the `method` property is only
83
+ * relevant to backend routes.
84
+ * * when defining the `createRoute` method, only the request input format is defined, the output
85
+ * format is derived from the routes.
86
+ *
87
+ * When calling the resulting `createRoute` function, the only required params of the route are the
88
+ * name, path, and handler. Other params can be added to the type and then later used in the
89
+ * routeMatcher.
90
+ *
91
+ * eg when defining requestServiceProvider in line, the types have a hard time, it helps to put in another argument:
92
+ * ```
93
+ * export const exampleRoute = createRoute({
94
+ * name: 'exampleRoute', method: METHOD.GET, path: '/api/example/:key',
95
+ * requestServiceProvider: composeServiceMiddleware({
96
+ * cookieAuthMiddleware,
97
+ * documentStoreMiddleware,
98
+ * }},
99
+ * async(params: {key: string}, services) => {
100
+ * const result = await services.myDocumentStore.getItem(params.key);
101
+ *
102
+ * if (!result) {
103
+ * throw new NotFoundError('requested item not found');
104
+ * }
105
+ *
106
+ * return apiJsonResponse(200, result);
107
+ * }
108
+ * );
109
+ * ```
110
+ * eg when using a pre-existing provider variable the types work better:
111
+ * ```
112
+ * export const exampleRoute = createRoute({
113
+ * name: 'exampleRoute', method: METHOD.GET, path: '/api/example/:key',
114
+ * requestServiceProvider,
115
+ * handler: async(params: {key: string}, services) => {
116
+ * const result = await services.myDocumentStore.getItem(params.key);
117
+ *
118
+ * if (!result) {
119
+ * throw new NotFoundError('requested item not found');
120
+ * }
121
+ *
122
+ * return apiJsonResponse(200, result);
123
+ * }
124
+ * });
125
+ * ```
126
+ */
127
+ export declare const makeCreateRoute: <Sa, Ri, Ex = {}>() => CreateRoute<Sa, Ri, Ex>;
128
+ /**
129
+ * Makes a renderRouteUrl function that can be used to render route paths (this is a factory
130
+ * factory). The returned function takes a `route`, `params`, and `query` and returns a string
131
+ * with the params and query substituted into the route path.
132
+ *
133
+ * this function is initialized using the Ru type which indicates the specific routes wired into
134
+ * the application, which means that if you try to build a url with a route which is not wired
135
+ * into the router you will get a type error. this is a feature to prevent referencing routes that
136
+ * don't exist or aren't handling requests properly.
137
+ *
138
+ * if you are making a helper function or need to render a route outside your application, you
139
+ * can use the `renderAnyRouteUrl` function
140
+ */
141
+ export declare const makeRenderRouteUrl: <Ru extends {
142
+ path: string;
143
+ }>() => <R extends Ru>(route: R, params: ParamsForRoute<R>, query?: QueryParams) => string;
144
+ /**
145
+ * A pre-made result from `makeRenderRouteUrl`, this function interpolates parameter and query
146
+ * arguments into a route path.
147
+ *
148
+ * prefer using `renderRouteUrl` initialized with your applications route union
149
+ * when possible to help catch improperly initialized routes.
150
+ *
151
+ * @param route the route that has a `path` to be interpolated
152
+ * @param params the parameters to interpolate into the route path
153
+ * @param query the query parameters to add to the route path
154
+ * @returns the interpolated route path
155
+ */
156
+ export declare const renderAnyRouteUrl: <R extends any>(route: R, params: ParamsForRoute<R>, query?: QueryParams) => string;
157
+ declare type RequestPathExtractor<Ri> = (request: Ri) => string;
158
+ declare type RequestLogExtractor<Ri> = (request: Ri) => JsonCompatibleStruct;
159
+ declare type RequestRouteMatcher<Ri, R> = (request: Ri, route: R) => boolean;
160
+ declare type CompatibleServices<T1> = keyof T1 extends 'logger' ? T1 extends {
161
+ logger: Logger;
162
+ } ? T1 : never : T1 & {
163
+ logger?: Logger;
164
+ };
165
+ declare type RequestResponder<Sa, Ri, Ro> = {
166
+ (services: CompatibleServices<Sa>): (request: Ri) => Ro | undefined;
167
+ <RoF>(services: CompatibleServices<Sa>, responseMiddleware: (app: Sa) => (response: Ro | undefined, request: {
168
+ request: Ri;
169
+ logger: Logger;
170
+ }) => RoF): (request: Ri) => RoF;
171
+ };
172
+ /**
173
+ * A factory factory for creating request responders (functions that take a request and return a
174
+ * response -- these functions let us implement Lambda `handler` functions).
175
+ *
176
+ * Use it in two steps. First, call it with the general business logic that defines routes, logs,
177
+ * errors, etc:
178
+ * ```
179
+ * const getRequestResponder = makeGetRequestResponder<
180
+ * AppServices, TRoutes, ApiRouteRequest, Promise<ApiRouteResponse>
181
+ * >() // this empty invocation helps typescript mix defined and inferred types
182
+ * ({
183
+ * routes: apiRoutes, // the route definitions
184
+ * pathExtractor, // how to get the path out of the request format
185
+ * routeMatcher, // logic for matching route (beyond path matching, optional)
186
+ * errorHandler, // any special error handling
187
+ * });
188
+ * ```
189
+ * Note here that among other things we're specifying a generic response format that the response
190
+ * and error handling middleware can use, if any routes have responses that don't adhere to this
191
+ * it'll complain about it.
192
+ *
193
+ * Next, we use the `getRequestResponder` to create a responder for a specific lambda entrypoint:
194
+ * ```
195
+ * export const handler: (request: APIGatewayProxyEventV2): Promise<ApiRouteResponse> =>
196
+ * getRequestResponder(
197
+ * lambdaServices, // the AppServices for this entrypoint
198
+ * lambdaMiddleware // environment specific response middleware (like cors)
199
+ * );
200
+ * ```
201
+ */
202
+ export declare const makeGetRequestResponder: <Sa, Ru, Ri, Ro>() => ({ routes, pathExtractor, routeMatcher, errorHandler, logExtractor }: {
203
+ routes: () => AnySpecificRoute<Ru, Sa, Ri, Ro>[];
204
+ pathExtractor: RequestPathExtractor<Ri>;
205
+ logExtractor?: RequestLogExtractor<Ri> | undefined;
206
+ routeMatcher?: RequestRouteMatcher<Ri, AnySpecificRoute<Ru, Sa, Ri, Ro>> | undefined;
207
+ errorHandler?: ((e: Error, logger: Logger) => Ro) | undefined;
208
+ }) => RequestResponder<Sa, Ri, Ro>;
209
+ /** HTTP Headers */
210
+ export declare type HttpHeaders = {
211
+ [key: string]: string | undefined | string[];
212
+ };
213
+ /** A type that works in JSON */
214
+ export declare type JsonCompatibleValue = string | number | null | undefined | boolean;
215
+ /** A JSON array type */
216
+ export declare type JsonCompatibleArray = Array<JsonCompatibleValue | JsonCompatibleStruct | JsonCompatibleStruct>;
217
+ /** A JSON object type */
218
+ export declare type JsonCompatibleStruct = {
219
+ [key: string]: JsonCompatibleStruct | JsonCompatibleValue | JsonCompatibleArray;
220
+ };
221
+ /** The type for an API response */
222
+ export declare type ApiResponse<S extends number, T> = {
223
+ isBase64Encoded?: boolean;
224
+ statusCode: S;
225
+ data: T;
226
+ body: string;
227
+ headers?: {
228
+ [key: string]: string;
229
+ };
230
+ };
231
+ /**
232
+ * Returns a JSON response. Handles serializing the data to JSON and setting the content-type header.
233
+ * @param statusCode e.g. 201
234
+ * @param data the object to be serialized to JSON
235
+ * @param headers HTTP headers
236
+ * @example
237
+ * return apiJsonResponse(
238
+ * 200, {
239
+ * message: "hello, world!",
240
+ * foo: "bar",
241
+ * },
242
+ * { 'X-Frame-Options': 'DENY' }
243
+ * );
244
+ */
245
+ export declare const apiJsonResponse: <S extends number, T extends JsonCompatibleStruct>(statusCode: S, data: T, headers?: HttpHeaders | undefined) => ApiResponse<S, T>;
246
+ /**
247
+ * Returns a plain text response. Handles setting the content-type header.
248
+ * @param statusCode e.g. 201
249
+ * @param data some string
250
+ * @param headers HTTP headers
251
+ * @example return apiTextResponse(200, 'some text')
252
+ */
253
+ export declare const apiTextResponse: <S extends number>(statusCode: S, data: string, headers?: HttpHeaders | undefined) => ApiResponse<S, string>;
254
+ /**
255
+ * Returns an HTML response. Handles setting the content-type header.
256
+ * @param statusCode e.g. 201
257
+ * @param data some string
258
+ * @param headers HTTP headers
259
+ * @example return apiHtmlResponse(200, '<b>some text</b>')
260
+ */
261
+ export declare const apiHtmlResponse: <S extends number>(statusCode: S, data: string, headers?: HttpHeaders | undefined) => ApiResponse<S, string>;
262
+ /** HTTP method enum */
263
+ export declare enum METHOD {
264
+ GET = "GET",
265
+ HEAD = "HEAD",
266
+ POST = "POST",
267
+ PUT = "PUT",
268
+ PATCH = "PATCH",
269
+ DELETE = "DELETE",
270
+ OPTIONS = "OPTIONS"
271
+ }
272
+ export * from './helpers';