@openstax/ts-utils 1.33.1 → 1.34.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 (504) hide show
  1. package/.cfnlintrc +2 -0
  2. package/.github/CODEOWNERS +1 -0
  3. package/.github/workflows/ci.yml +36 -0
  4. package/.github/workflows/lint.yml +55 -0
  5. package/.nvmrc +1 -0
  6. package/.syncignore +4 -0
  7. package/.syncpackrc +18 -0
  8. package/CONTRIBUTING.md +96 -0
  9. package/LICENSE +661 -0
  10. package/Procfile +1 -0
  11. package/README.md +62 -90
  12. package/app.json +23 -0
  13. package/cspell.json +32 -0
  14. package/deploy/constants.env +21 -0
  15. package/deploy/deploy.bash +157 -0
  16. package/deploy/deployment-alt-region.cfn.yml +70 -0
  17. package/deploy/deployment.cfn.yml +650 -0
  18. package/deploy/destroy-deployment.bash +23 -0
  19. package/deploy/shared.cfn.yml +94 -0
  20. package/docs/lambda-build.md +35 -0
  21. package/package.json +12 -228
  22. package/packages/frontend/README.md +46 -0
  23. package/packages/frontend/package.json +101 -0
  24. package/packages/frontend/public/favicon.ico +0 -0
  25. package/packages/frontend/public/index.html +107 -0
  26. package/packages/frontend/public/maintenance.html +59 -0
  27. package/packages/frontend/public/manifest.json +15 -0
  28. package/packages/frontend/public/robots.txt +3 -0
  29. package/packages/frontend/script/make-certificate.bash +49 -0
  30. package/packages/frontend/script/server/cli.js +11 -0
  31. package/packages/frontend/script/server/index.js +47 -0
  32. package/packages/frontend/script/start.bash +22 -0
  33. package/packages/frontend/script/trust-localhost.bash +7 -0
  34. package/packages/frontend/src/auth/authProvider.ts +10 -0
  35. package/packages/frontend/src/auth/useAuth.ts +33 -0
  36. package/packages/frontend/src/components/Pagination.tsx +26 -0
  37. package/packages/frontend/src/configProvider/index.ts +53 -0
  38. package/packages/frontend/src/configProvider/use.ts +41 -0
  39. package/packages/frontend/src/core/context/services.spec.tsx +39 -0
  40. package/packages/frontend/src/core/context/services.tsx +16 -0
  41. package/packages/frontend/src/core/index.spec.ts +7 -0
  42. package/packages/frontend/src/core/index.ts +20 -0
  43. package/packages/frontend/src/core/services.tsx +14 -0
  44. package/packages/frontend/src/core/types.ts +3 -0
  45. package/packages/frontend/src/example/api.ts +28 -0
  46. package/packages/frontend/src/example/components/Layout.tsx +23 -0
  47. package/packages/frontend/src/example/screens/Home.spec.tsx +68 -0
  48. package/packages/frontend/src/example/screens/Home.tsx +78 -0
  49. package/packages/frontend/src/example/screens/ThingList.spec.tsx +60 -0
  50. package/packages/frontend/src/example/screens/ThingList.tsx +75 -0
  51. package/packages/frontend/src/example/screens/ThingView.spec.tsx +71 -0
  52. package/packages/frontend/src/example/screens/ThingView.tsx +47 -0
  53. package/packages/frontend/src/example/screens/index.ts +9 -0
  54. package/packages/frontend/src/index.css +159 -0
  55. package/packages/frontend/src/index.tsx +67 -0
  56. package/packages/frontend/src/react-app-env.d.ts +1 -0
  57. package/packages/frontend/src/routing/components/RouteLink.spec.tsx +55 -0
  58. package/packages/frontend/src/routing/components/RouteLink.tsx +35 -0
  59. package/packages/frontend/src/routing/middleware.ts +6 -0
  60. package/packages/frontend/src/routing/useQuery.ts +14 -0
  61. package/packages/frontend/src/setupProxy.js +19 -0
  62. package/packages/frontend/src/setupTests.ts +9 -0
  63. package/packages/frontend/src/tests/testServices.tsx +23 -0
  64. package/packages/frontend/tsconfig.json +27 -0
  65. package/packages/lambda/.eslintrc.js +64 -0
  66. package/packages/lambda/jest-global-setup.js +3 -0
  67. package/packages/lambda/jest-setup-after-env.js +1 -0
  68. package/packages/lambda/jest.config.js +31 -0
  69. package/packages/lambda/jest.resolver.js +17 -0
  70. package/packages/lambda/package.json +68 -0
  71. package/packages/lambda/script/build.bash +19 -0
  72. package/packages/lambda/script/bundle-functions.bash +10 -0
  73. package/packages/lambda/script/lambdaLocalProxy.js +16 -0
  74. package/packages/lambda/script/lambdaLocalProxy.spec.ts +147 -0
  75. package/packages/lambda/script/utils/getRouteData.ts +7 -0
  76. package/packages/lambda/script/utils/routeDataLoader.js +8 -0
  77. package/packages/lambda/script/utils/routeDataLoader.spec.ts +8 -0
  78. package/packages/lambda/src/functions/serviceApi/core/index.ts +7 -0
  79. package/packages/lambda/src/functions/serviceApi/core/request.spec.ts +38 -0
  80. package/packages/lambda/src/functions/serviceApi/core/request.ts +42 -0
  81. package/packages/lambda/src/functions/serviceApi/core/routes.spec.ts +7 -0
  82. package/packages/lambda/src/functions/serviceApi/core/routes.ts +10 -0
  83. package/packages/lambda/src/functions/serviceApi/core/services.ts +9 -0
  84. package/packages/lambda/src/functions/serviceApi/core/types.ts +13 -0
  85. package/packages/lambda/src/functions/serviceApi/entry/lambda/https-xray.ts +4 -0
  86. package/packages/lambda/src/functions/serviceApi/entry/lambda/index.spec.ts +48 -0
  87. package/packages/lambda/src/functions/serviceApi/entry/lambda/index.ts +58 -0
  88. package/packages/lambda/src/functions/serviceApi/entry/lambda/services.ts +36 -0
  89. package/packages/lambda/src/functions/serviceApi/entry/local.ts +71 -0
  90. package/packages/lambda/src/functions/serviceApi/versions/v0/example/documentSearchMiddleware.spec.ts +16 -0
  91. package/packages/lambda/src/functions/serviceApi/versions/v0/example/documentSearchMiddleware.ts +41 -0
  92. package/packages/lambda/src/functions/serviceApi/versions/v0/example/documentStoreMiddleware.spec.ts +78 -0
  93. package/packages/lambda/src/functions/serviceApi/versions/v0/example/documentStoreMiddleware.ts +70 -0
  94. package/packages/lambda/src/functions/serviceApi/versions/v0/example/routes.spec.ts +306 -0
  95. package/packages/lambda/src/functions/serviceApi/versions/v0/example/routes.ts +176 -0
  96. package/packages/lambda/src/functions/serviceApi/versions/v0/index.spec.ts +263 -0
  97. package/packages/lambda/src/functions/serviceApi/versions/v0/index.ts +134 -0
  98. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/authMiddleware.spec.ts +23 -0
  99. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/authMiddleware.ts +32 -0
  100. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/configMiddleware.spec.ts +10 -0
  101. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/configMiddleware.ts +7 -0
  102. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/frontendFileServerMiddleware.spec.ts +13 -0
  103. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/frontendFileServerMiddleware.ts +23 -0
  104. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/paginationMiddleware.spec.ts +9 -0
  105. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/paginationMiddleware.ts +9 -0
  106. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/searchMiddleware.spec.ts +12 -0
  107. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/searchMiddleware.ts +21 -0
  108. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/userRoleValidatorMiddleware.spec.ts +21 -0
  109. package/packages/lambda/src/functions/serviceApi/versions/v0/middleware/userRoleValidatorMiddleware.ts +18 -0
  110. package/packages/lambda/tsconfig.json +30 -0
  111. package/packages/lambda/webpack.config.js +97 -0
  112. package/packages/utils/.eslintrc.js +64 -0
  113. package/packages/utils/README.md +118 -0
  114. package/packages/utils/jest-global-setup.js +3 -0
  115. package/packages/utils/jest.config.js +25 -0
  116. package/packages/utils/jest.resolver.js +17 -0
  117. package/packages/utils/package.json +238 -0
  118. package/packages/utils/src/assertions/index.spec.ts +126 -0
  119. package/{dist/esm/assertions/index.js → packages/utils/src/assertions/index.ts} +64 -49
  120. package/packages/utils/src/aws/ssmService.ts +7 -0
  121. package/packages/utils/src/config/awsParameterConfig.ts +24 -0
  122. package/packages/utils/src/config/envConfig.ts +58 -0
  123. package/packages/utils/src/config/index.spec.ts +165 -0
  124. package/{dist/esm/config/index.d.ts → packages/utils/src/config/index.ts} +29 -13
  125. package/packages/utils/src/config/lambdaParameterConfig.ts +49 -0
  126. package/{dist/esm/config/replaceConfig.js → packages/utils/src/config/replaceConfig.ts} +16 -6
  127. package/packages/utils/src/config/resolveConfigValue.ts +10 -0
  128. package/packages/utils/src/errors/index.spec.ts +35 -0
  129. package/{dist/esm/errors/index.js → packages/utils/src/errors/index.ts} +57 -41
  130. package/packages/utils/src/fetch/fetchStatusRetry.spec.ts +197 -0
  131. package/packages/utils/src/fetch/fetchStatusRetry.ts +33 -0
  132. package/packages/utils/src/fetch/index.spec.ts +34 -0
  133. package/packages/utils/src/fetch/index.ts +87 -0
  134. package/packages/utils/src/guards/index.spec.ts +58 -0
  135. package/{dist/esm/guards/index.d.ts → packages/utils/src/guards/index.ts} +10 -7
  136. package/packages/utils/src/index.spec.ts +471 -0
  137. package/packages/utils/src/middleware/apiErrorHandler.spec.ts +65 -0
  138. package/packages/utils/src/middleware/apiErrorHandler.ts +67 -0
  139. package/packages/utils/src/middleware/apiSlowResponseMiddleware.spec.ts +184 -0
  140. package/packages/utils/src/middleware/apiSlowResponseMiddleware.ts +71 -0
  141. package/packages/utils/src/middleware/index.spec.ts +99 -0
  142. package/{dist/cjs/middleware/index.d.ts → packages/utils/src/middleware/index.ts} +53 -5
  143. package/packages/utils/src/middleware/lambdaCorsResponseMiddleware.spec.ts +103 -0
  144. package/packages/utils/src/middleware/lambdaCorsResponseMiddleware.ts +52 -0
  145. package/packages/utils/src/middleware/throwNotFoundMiddleware.spec.ts +20 -0
  146. package/packages/utils/src/middleware/throwNotFoundMiddleware.ts +11 -0
  147. package/packages/utils/src/misc/hashValue.ts +18 -0
  148. package/packages/utils/src/misc/helpers.ts +259 -0
  149. package/packages/utils/src/misc/merge.ts +48 -0
  150. package/{dist/esm/misc/partitionSequence.js → packages/utils/src/misc/partitionSequence.ts} +23 -15
  151. package/packages/utils/src/pagination/index.spec.ts +150 -0
  152. package/packages/utils/src/pagination/index.ts +117 -0
  153. package/{dist/esm/routing/helpers.js → packages/utils/src/routing/helpers.ts} +42 -30
  154. package/packages/utils/src/routing/index.spec.ts +553 -0
  155. package/packages/utils/src/routing/index.ts +424 -0
  156. package/packages/utils/src/routing/validators/zod.spec.ts +16 -0
  157. package/packages/utils/src/routing/validators/zod.ts +14 -0
  158. package/packages/utils/src/services/accountsGateway/README.md +3 -0
  159. package/packages/utils/src/services/accountsGateway/index.spec.ts +518 -0
  160. package/packages/utils/src/services/accountsGateway/index.ts +251 -0
  161. package/packages/utils/src/services/apiGateway/README.md +93 -0
  162. package/packages/utils/src/services/apiGateway/index.spec.ts +254 -0
  163. package/packages/utils/src/services/apiGateway/index.ts +189 -0
  164. package/packages/utils/src/services/authProvider/README.md +21 -0
  165. package/packages/utils/src/services/authProvider/browser.spec.ts +391 -0
  166. package/packages/utils/src/services/authProvider/browser.ts +209 -0
  167. package/packages/utils/src/services/authProvider/decryption.spec.ts +337 -0
  168. package/packages/utils/src/services/authProvider/decryption.ts +98 -0
  169. package/packages/utils/src/services/authProvider/index.ts +93 -0
  170. package/packages/utils/src/services/authProvider/stub.spec.ts +29 -0
  171. package/packages/utils/src/services/authProvider/subrequest.spec.ts +105 -0
  172. package/packages/utils/src/services/authProvider/subrequest.ts +68 -0
  173. package/packages/utils/src/services/authProvider/utils/decryptAndVerify.spec.ts +128 -0
  174. package/packages/utils/src/services/authProvider/utils/decryptAndVerify.ts +106 -0
  175. package/packages/utils/src/services/authProvider/utils/embeddedAuthProvider.spec.ts +26 -0
  176. package/packages/utils/src/services/authProvider/utils/embeddedAuthProvider.ts +57 -0
  177. package/packages/utils/src/services/authProvider/utils/userRoleValidator.spec.ts +135 -0
  178. package/packages/utils/src/services/authProvider/utils/userRoleValidator.ts +49 -0
  179. package/packages/utils/src/services/authProvider/utils/userSubrequest.spec.ts +26 -0
  180. package/packages/utils/src/services/authProvider/utils/userSubrequest.ts +10 -0
  181. package/packages/utils/src/services/documentStore/dynamoEncoding.ts +57 -0
  182. package/packages/utils/src/services/documentStore/fileSystemAssert.spec.ts +43 -0
  183. package/packages/utils/src/services/documentStore/fileSystemAssert.ts +10 -0
  184. package/{dist/cjs/services/documentStore/index.d.ts → packages/utils/src/services/documentStore/index.ts} +8 -8
  185. package/packages/utils/src/services/documentStore/unversioned/README.md +13 -0
  186. package/packages/utils/src/services/documentStore/unversioned/dynamodb.spec.ts +859 -0
  187. package/packages/utils/src/services/documentStore/unversioned/dynamodb.ts +243 -0
  188. package/packages/utils/src/services/documentStore/unversioned/file-system.spec.ts +629 -0
  189. package/packages/utils/src/services/documentStore/unversioned/file-system.ts +194 -0
  190. package/{dist/cjs/services/documentStore/unversioned/index.d.ts → packages/utils/src/services/documentStore/unversioned/index.ts} +2 -0
  191. package/packages/utils/src/services/documentStore/versioned/README.md +13 -0
  192. package/packages/utils/src/services/documentStore/versioned/dynamodb.spec.ts +376 -0
  193. package/packages/utils/src/services/documentStore/versioned/dynamodb.ts +167 -0
  194. package/packages/utils/src/services/documentStore/versioned/file-system.spec.ts +262 -0
  195. package/packages/utils/src/services/documentStore/versioned/file-system.ts +90 -0
  196. package/packages/utils/src/services/documentStore/versioned/index.ts +25 -0
  197. package/packages/utils/src/services/exercisesGateway/README.md +5 -0
  198. package/packages/utils/src/services/exercisesGateway/index.spec.ts +326 -0
  199. package/packages/utils/src/services/exercisesGateway/index.ts +163 -0
  200. package/packages/utils/src/services/fileServer/index.spec.ts +88 -0
  201. package/packages/utils/src/services/fileServer/index.ts +43 -0
  202. package/packages/utils/src/services/fileServer/localFileServer.spec.ts +182 -0
  203. package/packages/utils/src/services/fileServer/localFileServer.ts +159 -0
  204. package/packages/utils/src/services/fileServer/s3FileServer.spec.ts +266 -0
  205. package/packages/utils/src/services/fileServer/s3FileServer.ts +155 -0
  206. package/packages/utils/src/services/launchParams/index.spec.ts +366 -0
  207. package/packages/utils/src/services/launchParams/signer.ts +73 -0
  208. package/packages/utils/src/services/launchParams/verifier.ts +120 -0
  209. package/packages/utils/src/services/logger/console.spec.ts +29 -0
  210. package/{dist/esm/services/logger/console.js → packages/utils/src/services/logger/console.ts} +5 -2
  211. package/packages/utils/src/services/logger/index.spec.ts +65 -0
  212. package/{dist/esm/services/logger/index.d.ts → packages/utils/src/services/logger/index.ts} +23 -9
  213. package/packages/utils/src/services/lrsGateway/README.md +5 -0
  214. package/packages/utils/src/services/lrsGateway/addStatementDefaultFields.ts +22 -0
  215. package/packages/utils/src/services/lrsGateway/attempt-utils.spec.ts +847 -0
  216. package/packages/utils/src/services/lrsGateway/attempt-utils.ts +358 -0
  217. package/packages/utils/src/services/lrsGateway/file-system.spec.ts +363 -0
  218. package/packages/utils/src/services/lrsGateway/file-system.ts +165 -0
  219. package/packages/utils/src/services/lrsGateway/index.spec.ts +194 -0
  220. package/packages/utils/src/services/lrsGateway/index.ts +257 -0
  221. package/packages/utils/src/services/lrsGateway/xapiUtils.spec.ts +887 -0
  222. package/packages/utils/src/services/lrsGateway/xapiUtils.ts +262 -0
  223. package/packages/utils/src/services/postgresConnection/index.spec.ts +170 -0
  224. package/packages/utils/src/services/postgresConnection/index.ts +84 -0
  225. package/packages/utils/src/services/searchProvider/README.md +3 -0
  226. package/packages/utils/src/services/searchProvider/index.ts +59 -0
  227. package/packages/utils/src/services/searchProvider/memorySearchTheBadWay.spec.ts +526 -0
  228. package/packages/utils/src/services/searchProvider/memorySearchTheBadWay.ts +223 -0
  229. package/packages/utils/src/services/searchProvider/openSearch.spec.ts +926 -0
  230. package/packages/utils/src/services/searchProvider/openSearch.ts +195 -0
  231. package/{dist/esm/types.d.ts → packages/utils/src/types.ts} +34 -6
  232. package/packages/utils/tsconfig.json +31 -0
  233. package/packages/utils/tsconfig.without-specs.cjs.json +7 -0
  234. package/packages/utils/tsconfig.without-specs.esm.json +7 -0
  235. package/packages/utils/tsconfig.without-specs.json +6 -0
  236. package/scripts/build.bash +24 -0
  237. package/scripts/ci.bash +10 -0
  238. package/scripts/start.bash +29 -0
  239. package/dist/cjs/assertions/index.d.ts +0 -89
  240. package/dist/cjs/assertions/index.js +0 -157
  241. package/dist/cjs/aws/ssmService.d.ts +0 -5
  242. package/dist/cjs/aws/ssmService.js +0 -9
  243. package/dist/cjs/config/awsParameterConfig.d.ts +0 -10
  244. package/dist/cjs/config/awsParameterConfig.js +0 -26
  245. package/dist/cjs/config/envConfig.d.ts +0 -24
  246. package/dist/cjs/config/envConfig.js +0 -57
  247. package/dist/cjs/config/index.d.ts +0 -48
  248. package/dist/cjs/config/index.js +0 -35
  249. package/dist/cjs/config/lambdaParameterConfig.d.ts +0 -12
  250. package/dist/cjs/config/lambdaParameterConfig.js +0 -45
  251. package/dist/cjs/config/replaceConfig.d.ts +0 -14
  252. package/dist/cjs/config/replaceConfig.js +0 -22
  253. package/dist/cjs/config/resolveConfigValue.d.ts +0 -5
  254. package/dist/cjs/config/resolveConfigValue.js +0 -12
  255. package/dist/cjs/errors/index.d.ts +0 -88
  256. package/dist/cjs/errors/index.js +0 -123
  257. package/dist/cjs/fetch/fetchStatusRetry.d.ts +0 -8
  258. package/dist/cjs/fetch/fetchStatusRetry.js +0 -27
  259. package/dist/cjs/fetch/index.d.ts +0 -64
  260. package/dist/cjs/fetch/index.js +0 -55
  261. package/dist/cjs/guards/index.d.ts +0 -38
  262. package/dist/cjs/guards/index.js +0 -44
  263. package/dist/cjs/index.js +0 -20
  264. package/dist/cjs/middleware/apiErrorHandler.d.ts +0 -24
  265. package/dist/cjs/middleware/apiErrorHandler.js +0 -42
  266. package/dist/cjs/middleware/apiSlowResponseMiddleware.d.ts +0 -23
  267. package/dist/cjs/middleware/apiSlowResponseMiddleware.js +0 -54
  268. package/dist/cjs/middleware/index.js +0 -48
  269. package/dist/cjs/middleware/lambdaCorsResponseMiddleware.d.ts +0 -20
  270. package/dist/cjs/middleware/lambdaCorsResponseMiddleware.js +0 -44
  271. package/dist/cjs/middleware/throwNotFoundMiddleware.d.ts +0 -4
  272. package/dist/cjs/middleware/throwNotFoundMiddleware.js +0 -14
  273. package/dist/cjs/misc/hashValue.d.ts +0 -10
  274. package/dist/cjs/misc/hashValue.js +0 -17
  275. package/dist/cjs/misc/helpers.d.ts +0 -124
  276. package/dist/cjs/misc/helpers.js +0 -214
  277. package/dist/cjs/misc/merge.d.ts +0 -21
  278. package/dist/cjs/misc/merge.js +0 -45
  279. package/dist/cjs/misc/partitionSequence.d.ts +0 -35
  280. package/dist/cjs/misc/partitionSequence.js +0 -55
  281. package/dist/cjs/pagination/index.d.ts +0 -91
  282. package/dist/cjs/pagination/index.js +0 -83
  283. package/dist/cjs/routing/helpers.d.ts +0 -57
  284. package/dist/cjs/routing/helpers.js +0 -90
  285. package/dist/cjs/routing/index.d.ts +0 -290
  286. package/dist/cjs/routing/index.js +0 -295
  287. package/dist/cjs/routing/validators/zod.d.ts +0 -4
  288. package/dist/cjs/routing/validators/zod.js +0 -14
  289. package/dist/cjs/services/accountsGateway/index.d.ts +0 -92
  290. package/dist/cjs/services/accountsGateway/index.js +0 -138
  291. package/dist/cjs/services/apiGateway/index.d.ts +0 -68
  292. package/dist/cjs/services/apiGateway/index.js +0 -118
  293. package/dist/cjs/services/authProvider/browser.d.ts +0 -40
  294. package/dist/cjs/services/authProvider/browser.js +0 -155
  295. package/dist/cjs/services/authProvider/decryption.d.ts +0 -19
  296. package/dist/cjs/services/authProvider/decryption.js +0 -73
  297. package/dist/cjs/services/authProvider/index.d.ts +0 -63
  298. package/dist/cjs/services/authProvider/index.js +0 -34
  299. package/dist/cjs/services/authProvider/subrequest.d.ts +0 -13
  300. package/dist/cjs/services/authProvider/subrequest.js +0 -49
  301. package/dist/cjs/services/authProvider/utils/decryptAndVerify.d.ts +0 -28
  302. package/dist/cjs/services/authProvider/utils/decryptAndVerify.js +0 -91
  303. package/dist/cjs/services/authProvider/utils/embeddedAuthProvider.d.ts +0 -26
  304. package/dist/cjs/services/authProvider/utils/embeddedAuthProvider.js +0 -47
  305. package/dist/cjs/services/authProvider/utils/userRoleValidator.d.ts +0 -13
  306. package/dist/cjs/services/authProvider/utils/userRoleValidator.js +0 -37
  307. package/dist/cjs/services/authProvider/utils/userSubrequest.d.ts +0 -3
  308. package/dist/cjs/services/authProvider/utils/userSubrequest.js +0 -13
  309. package/dist/cjs/services/documentStore/dynamoEncoding.d.ts +0 -10
  310. package/dist/cjs/services/documentStore/dynamoEncoding.js +0 -52
  311. package/dist/cjs/services/documentStore/fileSystemAssert.d.ts +0 -1
  312. package/dist/cjs/services/documentStore/fileSystemAssert.js +0 -14
  313. package/dist/cjs/services/documentStore/index.js +0 -2
  314. package/dist/cjs/services/documentStore/unversioned/dynamodb.d.ts +0 -31
  315. package/dist/cjs/services/documentStore/unversioned/dynamodb.js +0 -233
  316. package/dist/cjs/services/documentStore/unversioned/file-system.d.ts +0 -32
  317. package/dist/cjs/services/documentStore/unversioned/file-system.js +0 -214
  318. package/dist/cjs/services/documentStore/unversioned/index.js +0 -2
  319. package/dist/cjs/services/documentStore/versioned/dynamodb.d.ts +0 -25
  320. package/dist/cjs/services/documentStore/versioned/dynamodb.js +0 -143
  321. package/dist/cjs/services/documentStore/versioned/file-system.d.ts +0 -25
  322. package/dist/cjs/services/documentStore/versioned/file-system.js +0 -73
  323. package/dist/cjs/services/documentStore/versioned/index.d.ts +0 -17
  324. package/dist/cjs/services/documentStore/versioned/index.js +0 -2
  325. package/dist/cjs/services/exercisesGateway/index.d.ts +0 -67
  326. package/dist/cjs/services/exercisesGateway/index.js +0 -107
  327. package/dist/cjs/services/fileServer/index.d.ts +0 -30
  328. package/dist/cjs/services/fileServer/index.js +0 -19
  329. package/dist/cjs/services/fileServer/localFileServer.d.ts +0 -13
  330. package/dist/cjs/services/fileServer/localFileServer.js +0 -132
  331. package/dist/cjs/services/fileServer/s3FileServer.d.ts +0 -14
  332. package/dist/cjs/services/fileServer/s3FileServer.js +0 -132
  333. package/dist/cjs/services/launchParams/index.js +0 -7
  334. package/dist/cjs/services/launchParams/signer.d.ts +0 -23
  335. package/dist/cjs/services/launchParams/signer.js +0 -58
  336. package/dist/cjs/services/launchParams/verifier.d.ts +0 -21
  337. package/dist/cjs/services/launchParams/verifier.js +0 -129
  338. package/dist/cjs/services/logger/console.d.ts +0 -4
  339. package/dist/cjs/services/logger/console.js +0 -12
  340. package/dist/cjs/services/logger/index.d.ts +0 -39
  341. package/dist/cjs/services/logger/index.js +0 -31
  342. package/dist/cjs/services/lrsGateway/addStatementDefaultFields.d.ts +0 -5
  343. package/dist/cjs/services/lrsGateway/addStatementDefaultFields.js +0 -21
  344. package/dist/cjs/services/lrsGateway/attempt-utils.d.ts +0 -70
  345. package/dist/cjs/services/lrsGateway/attempt-utils.js +0 -258
  346. package/dist/cjs/services/lrsGateway/file-system.d.ts +0 -15
  347. package/dist/cjs/services/lrsGateway/file-system.js +0 -150
  348. package/dist/cjs/services/lrsGateway/index.d.ts +0 -122
  349. package/dist/cjs/services/lrsGateway/index.js +0 -148
  350. package/dist/cjs/services/lrsGateway/xapiUtils.d.ts +0 -68
  351. package/dist/cjs/services/lrsGateway/xapiUtils.js +0 -109
  352. package/dist/cjs/services/postgresConnection/index.d.ts +0 -28
  353. package/dist/cjs/services/postgresConnection/index.js +0 -65
  354. package/dist/cjs/services/searchProvider/index.d.ts +0 -67
  355. package/dist/cjs/services/searchProvider/index.js +0 -2
  356. package/dist/cjs/services/searchProvider/memorySearchTheBadWay.d.ts +0 -20
  357. package/dist/cjs/services/searchProvider/memorySearchTheBadWay.js +0 -191
  358. package/dist/cjs/services/searchProvider/openSearch.d.ts +0 -28
  359. package/dist/cjs/services/searchProvider/openSearch.js +0 -154
  360. package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +0 -1
  361. package/dist/cjs/types.d.ts +0 -31
  362. package/dist/cjs/types.js +0 -2
  363. package/dist/esm/assertions/index.d.ts +0 -89
  364. package/dist/esm/aws/ssmService.d.ts +0 -5
  365. package/dist/esm/aws/ssmService.js +0 -6
  366. package/dist/esm/config/awsParameterConfig.d.ts +0 -10
  367. package/dist/esm/config/awsParameterConfig.js +0 -22
  368. package/dist/esm/config/envConfig.d.ts +0 -24
  369. package/dist/esm/config/envConfig.js +0 -53
  370. package/dist/esm/config/index.js +0 -17
  371. package/dist/esm/config/lambdaParameterConfig.d.ts +0 -12
  372. package/dist/esm/config/lambdaParameterConfig.js +0 -38
  373. package/dist/esm/config/replaceConfig.d.ts +0 -14
  374. package/dist/esm/config/resolveConfigValue.d.ts +0 -5
  375. package/dist/esm/config/resolveConfigValue.js +0 -8
  376. package/dist/esm/errors/index.d.ts +0 -88
  377. package/dist/esm/fetch/fetchStatusRetry.d.ts +0 -8
  378. package/dist/esm/fetch/fetchStatusRetry.js +0 -23
  379. package/dist/esm/fetch/index.d.ts +0 -64
  380. package/dist/esm/fetch/index.js +0 -46
  381. package/dist/esm/guards/index.js +0 -36
  382. package/dist/esm/index.d.ts +0 -4
  383. package/dist/esm/index.js +0 -4
  384. package/dist/esm/middleware/apiErrorHandler.d.ts +0 -24
  385. package/dist/esm/middleware/apiErrorHandler.js +0 -38
  386. package/dist/esm/middleware/apiSlowResponseMiddleware.d.ts +0 -23
  387. package/dist/esm/middleware/apiSlowResponseMiddleware.js +0 -50
  388. package/dist/esm/middleware/index.d.ts +0 -47
  389. package/dist/esm/middleware/index.js +0 -44
  390. package/dist/esm/middleware/lambdaCorsResponseMiddleware.d.ts +0 -20
  391. package/dist/esm/middleware/lambdaCorsResponseMiddleware.js +0 -40
  392. package/dist/esm/middleware/throwNotFoundMiddleware.d.ts +0 -4
  393. package/dist/esm/middleware/throwNotFoundMiddleware.js +0 -10
  394. package/dist/esm/misc/hashValue.d.ts +0 -10
  395. package/dist/esm/misc/hashValue.js +0 -13
  396. package/dist/esm/misc/helpers.d.ts +0 -124
  397. package/dist/esm/misc/helpers.js +0 -199
  398. package/dist/esm/misc/merge.d.ts +0 -21
  399. package/dist/esm/misc/merge.js +0 -40
  400. package/dist/esm/misc/partitionSequence.d.ts +0 -35
  401. package/dist/esm/pagination/index.d.ts +0 -91
  402. package/dist/esm/pagination/index.js +0 -77
  403. package/dist/esm/routing/helpers.d.ts +0 -57
  404. package/dist/esm/routing/index.d.ts +0 -290
  405. package/dist/esm/routing/index.js +0 -246
  406. package/dist/esm/routing/validators/zod.d.ts +0 -4
  407. package/dist/esm/routing/validators/zod.js +0 -10
  408. package/dist/esm/services/accountsGateway/index.d.ts +0 -92
  409. package/dist/esm/services/accountsGateway/index.js +0 -131
  410. package/dist/esm/services/apiGateway/index.d.ts +0 -68
  411. package/dist/esm/services/apiGateway/index.js +0 -77
  412. package/dist/esm/services/authProvider/browser.d.ts +0 -40
  413. package/dist/esm/services/authProvider/browser.js +0 -151
  414. package/dist/esm/services/authProvider/decryption.d.ts +0 -19
  415. package/dist/esm/services/authProvider/decryption.js +0 -69
  416. package/dist/esm/services/authProvider/index.d.ts +0 -63
  417. package/dist/esm/services/authProvider/index.js +0 -26
  418. package/dist/esm/services/authProvider/subrequest.d.ts +0 -13
  419. package/dist/esm/services/authProvider/subrequest.js +0 -45
  420. package/dist/esm/services/authProvider/utils/decryptAndVerify.d.ts +0 -28
  421. package/dist/esm/services/authProvider/utils/decryptAndVerify.js +0 -85
  422. package/dist/esm/services/authProvider/utils/embeddedAuthProvider.d.ts +0 -26
  423. package/dist/esm/services/authProvider/utils/embeddedAuthProvider.js +0 -40
  424. package/dist/esm/services/authProvider/utils/userRoleValidator.d.ts +0 -13
  425. package/dist/esm/services/authProvider/utils/userRoleValidator.js +0 -33
  426. package/dist/esm/services/authProvider/utils/userSubrequest.d.ts +0 -3
  427. package/dist/esm/services/authProvider/utils/userSubrequest.js +0 -6
  428. package/dist/esm/services/documentStore/dynamoEncoding.d.ts +0 -10
  429. package/dist/esm/services/documentStore/dynamoEncoding.js +0 -45
  430. package/dist/esm/services/documentStore/fileSystemAssert.d.ts +0 -1
  431. package/dist/esm/services/documentStore/fileSystemAssert.js +0 -10
  432. package/dist/esm/services/documentStore/index.d.ts +0 -14
  433. package/dist/esm/services/documentStore/index.js +0 -1
  434. package/dist/esm/services/documentStore/unversioned/dynamodb.d.ts +0 -31
  435. package/dist/esm/services/documentStore/unversioned/dynamodb.js +0 -226
  436. package/dist/esm/services/documentStore/unversioned/file-system.d.ts +0 -32
  437. package/dist/esm/services/documentStore/unversioned/file-system.js +0 -174
  438. package/dist/esm/services/documentStore/unversioned/index.d.ts +0 -2
  439. package/dist/esm/services/documentStore/unversioned/index.js +0 -1
  440. package/dist/esm/services/documentStore/versioned/dynamodb.d.ts +0 -25
  441. package/dist/esm/services/documentStore/versioned/dynamodb.js +0 -139
  442. package/dist/esm/services/documentStore/versioned/file-system.d.ts +0 -25
  443. package/dist/esm/services/documentStore/versioned/file-system.js +0 -69
  444. package/dist/esm/services/documentStore/versioned/index.d.ts +0 -17
  445. package/dist/esm/services/documentStore/versioned/index.js +0 -1
  446. package/dist/esm/services/exercisesGateway/index.d.ts +0 -67
  447. package/dist/esm/services/exercisesGateway/index.js +0 -70
  448. package/dist/esm/services/fileServer/index.d.ts +0 -30
  449. package/dist/esm/services/fileServer/index.js +0 -13
  450. package/dist/esm/services/fileServer/localFileServer.d.ts +0 -13
  451. package/dist/esm/services/fileServer/localFileServer.js +0 -125
  452. package/dist/esm/services/fileServer/s3FileServer.d.ts +0 -14
  453. package/dist/esm/services/fileServer/s3FileServer.js +0 -125
  454. package/dist/esm/services/launchParams/index.d.ts +0 -2
  455. package/dist/esm/services/launchParams/index.js +0 -2
  456. package/dist/esm/services/launchParams/signer.d.ts +0 -23
  457. package/dist/esm/services/launchParams/signer.js +0 -51
  458. package/dist/esm/services/launchParams/verifier.d.ts +0 -21
  459. package/dist/esm/services/launchParams/verifier.js +0 -92
  460. package/dist/esm/services/logger/console.d.ts +0 -4
  461. package/dist/esm/services/logger/index.js +0 -27
  462. package/dist/esm/services/lrsGateway/addStatementDefaultFields.d.ts +0 -5
  463. package/dist/esm/services/lrsGateway/addStatementDefaultFields.js +0 -14
  464. package/dist/esm/services/lrsGateway/attempt-utils.d.ts +0 -70
  465. package/dist/esm/services/lrsGateway/attempt-utils.js +0 -236
  466. package/dist/esm/services/lrsGateway/file-system.d.ts +0 -15
  467. package/dist/esm/services/lrsGateway/file-system.js +0 -110
  468. package/dist/esm/services/lrsGateway/index.d.ts +0 -122
  469. package/dist/esm/services/lrsGateway/index.js +0 -111
  470. package/dist/esm/services/lrsGateway/xapiUtils.d.ts +0 -68
  471. package/dist/esm/services/lrsGateway/xapiUtils.js +0 -99
  472. package/dist/esm/services/postgresConnection/index.d.ts +0 -28
  473. package/dist/esm/services/postgresConnection/index.js +0 -58
  474. package/dist/esm/services/searchProvider/index.d.ts +0 -67
  475. package/dist/esm/services/searchProvider/index.js +0 -1
  476. package/dist/esm/services/searchProvider/memorySearchTheBadWay.d.ts +0 -20
  477. package/dist/esm/services/searchProvider/memorySearchTheBadWay.js +0 -187
  478. package/dist/esm/services/searchProvider/openSearch.d.ts +0 -28
  479. package/dist/esm/services/searchProvider/openSearch.js +0 -150
  480. package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +0 -1
  481. package/dist/esm/types.js +0 -1
  482. package/script/bin/.init-params-script.bash.swp +0 -0
  483. /package/{script → packages/utils/script}/bin/copy-from-template.bash +0 -0
  484. /package/{script → packages/utils/script}/bin/delete-stack.bash +0 -0
  485. /package/{script → packages/utils/script}/bin/deploy.bash +0 -0
  486. /package/{script → packages/utils/script}/bin/destroy-deployment.bash +0 -0
  487. /package/{script → packages/utils/script}/bin/empty-bucket.bash +0 -0
  488. /package/{script → packages/utils/script}/bin/get-arg.bash +0 -0
  489. /package/{script → packages/utils/script}/bin/get-deployed-environments.bash +0 -0
  490. /package/{script → packages/utils/script}/bin/get-env-param.bash +0 -0
  491. /package/{script → packages/utils/script}/bin/get-kwarg.bash +0 -0
  492. /package/{script → packages/utils/script}/bin/get-stack-param.bash +0 -0
  493. /package/{script → packages/utils/script}/bin/has-flag.bash +0 -0
  494. /package/{script → packages/utils/script}/bin/init-constants-script.bash +0 -0
  495. /package/{script → packages/utils/script}/bin/init-params-script.bash +0 -0
  496. /package/{script → packages/utils/script}/bin/stack-exists.bash +0 -0
  497. /package/{script → packages/utils/script}/bin/update-utils.bash +0 -0
  498. /package/{script → packages/utils/script}/bin/upload-pager-duty-endpoints.bash +0 -0
  499. /package/{script → packages/utils/script}/bin/upload-params.bash +0 -0
  500. /package/{script → packages/utils/script}/bin/which.bash +0 -0
  501. /package/{script → packages/utils/script}/bin-entry.bash +0 -0
  502. /package/{script → packages/utils/script}/build.bash +0 -0
  503. /package/{dist/cjs/index.d.ts → packages/utils/src/index.ts} +0 -0
  504. /package/{dist/cjs/services/launchParams/index.d.ts → packages/utils/src/services/launchParams/index.ts} +0 -0
@@ -1,6 +1,8 @@
1
1
  import { assertErrorInstanceOf } from '../assertions';
2
2
  import { InvalidRequestError } from '../errors';
3
3
  import { isPlainObject } from '../guards';
4
+ import type { HttpHeaders } from '.';
5
+
4
6
  /**
5
7
  * Get the value of a header, case insensitive; note if there are multiple headers of the same
6
8
  * value, this only returns the first value
@@ -8,41 +10,50 @@ import { isPlainObject } from '../guards';
8
10
  * @param headers
9
11
  * @param name the name of the header, case ignored
10
12
  */
11
- export const getHeader = (headers, name) => {
12
- const key = Object.keys(headers).find(header => header.toLowerCase() === name.toLowerCase());
13
- const value = key ? headers[key] : undefined;
14
- return value instanceof Array
15
- ? value[0]
16
- : value;
13
+ export const getHeader = (headers: HttpHeaders, name: string) => {
14
+ const key = Object.keys(headers).find(header => header.toLowerCase() === name.toLowerCase());
15
+ const value = key ? headers[key] : undefined;
16
+
17
+ return value instanceof Array
18
+ ? value[0]
19
+ : value
20
+ ;
17
21
  };
22
+
18
23
  /**
19
24
  * Gets the body of a request
20
25
  * @param request
21
26
  * @throws InvalidRequestError if the content type is not application/json or not parsable
22
27
  */
23
- export const getRequestBody = (request) => {
24
- if (getHeader(request.headers, 'content-type') !== 'application/json') {
25
- throw new InvalidRequestError('unknown content type: ' + getHeader(request.headers, 'content-type'));
26
- }
27
- if (!request.body) {
28
- return {};
29
- }
30
- try {
31
- return JSON.parse(request.body);
32
- }
33
- catch (error) {
34
- // Since the body is provided by the user, invalid JSON in the body is an invalid request
35
- // We return the message which tells them why the JSON is invalid, but no backtrace
36
- throw new InvalidRequestError(assertErrorInstanceOf(error, SyntaxError).message);
37
- }
28
+ export const getRequestBody = (request: {headers: HttpHeaders; body?: string | undefined}) => {
29
+ if (getHeader(request.headers, 'content-type') !== 'application/json') {
30
+ throw new InvalidRequestError(
31
+ 'unknown content type: ' + getHeader(request.headers, 'content-type')
32
+ );
33
+ }
34
+
35
+ if (!request.body) {
36
+ return {};
37
+ }
38
+
39
+ try {
40
+ return JSON.parse(request.body);
41
+ } catch (error) {
42
+ // Since the body is provided by the user, invalid JSON in the body is an invalid request
43
+ // We return the message which tells them why the JSON is invalid, but no backtrace
44
+ throw new InvalidRequestError(assertErrorInstanceOf(error, SyntaxError).message);
45
+ }
38
46
  };
47
+
39
48
  /* utils and middleware for loading request payload (must follow this pattern for `PayloadForRoute` to work) */
49
+
40
50
  /**
41
51
  * stub validator because writing validators is annoying
42
52
  */
43
- export const unsafePayloadValidator = () => (input) => {
44
- return isPlainObject(input) && Object.keys(input).length > 0;
53
+ export const unsafePayloadValidator = <T>() => (input: any): input is T => {
54
+ return isPlainObject(input) && Object.keys(input).length > 0;
45
55
  };
56
+
46
57
  /**
47
58
  * Middleware that validates the request payload and adds it to the middleware (with key `payload`)
48
59
  * so it can be accessed downstream.
@@ -73,11 +84,12 @@ export const unsafePayloadValidator = () => (input) => {
73
84
  * }
74
85
  * );
75
86
  */
76
- export const requestPayloadProvider = (validator) => () => (requestServices) => {
77
- const payload = getRequestBody(requestServices.request);
78
- // for more precise error messages, throw your own InvalidRequestError from your validator function
79
- if (!validator(payload)) {
80
- throw new InvalidRequestError();
81
- }
82
- return { ...requestServices, payload };
87
+ export const requestPayloadProvider = <T>(validator: (input: any) => input is T) => () => <M extends {request: Parameters<typeof getRequestBody>[0]}>(requestServices: M) => {
88
+ const payload = getRequestBody(requestServices.request) as T;
89
+
90
+ // for more precise error messages, throw your own InvalidRequestError from your validator function
91
+ if (!validator(payload)) {
92
+ throw new InvalidRequestError();
93
+ }
94
+ return {...requestServices, payload};
83
95
  };
@@ -0,0 +1,553 @@
1
+ import { getKeyValue } from '..';
2
+ import { InvalidRequestError, UnauthorizedError } from '../errors';
3
+ import { makeComposeMiddleware } from '../middleware';
4
+ import { apiHtmlResponse, apiJsonResponse, apiTextResponse, getHeader, getRequestBody, makeCreateRoute, makeGetRequestResponder, makeRenderRouteUrl, requestPayloadProvider, unsafePayloadValidator } from '../routing';
5
+ import { createConsoleLogger } from '../services/logger/console';
6
+ import { routesList } from '.';
7
+
8
+ interface RouteRequest {
9
+ path: string;
10
+ }
11
+ interface RouteResponse {
12
+ body: string;
13
+ }
14
+ // ts weak type makes this fail if it has no properties
15
+ type AppServices = {
16
+ asdf: string;
17
+ };
18
+
19
+ const composeMiddleware = makeComposeMiddleware<AppServices, {}>();
20
+ const createRoute = makeCreateRoute<AppServices, RouteRequest, {}>();
21
+
22
+ describe('getRequestBody', () => {
23
+ it('gets it', () => {
24
+ const request = {
25
+ headers: {
26
+ 'content-type': 'application/json'
27
+ },
28
+ body: '{"foo":"bar"}'
29
+ };
30
+ expect(getRequestBody(request)).toEqual({foo: 'bar'});
31
+ });
32
+
33
+ it('defaults to empty object', () => {
34
+ const request = {
35
+ headers: {
36
+ 'content-type': 'application/json'
37
+ },
38
+ body: ''
39
+ };
40
+ expect(getRequestBody(request)).toEqual({});
41
+ });
42
+
43
+ it('throws if json content type is not set', () => {
44
+ const request = {
45
+ headers: {
46
+ 'content-type': 'application/text'
47
+ },
48
+ body: '{"foo":"bar"}'
49
+ };
50
+ expect(() => getRequestBody(request)).toThrow();
51
+ });
52
+
53
+ it('throws if content type is not set', () => {
54
+ const request = {
55
+ headers: {
56
+ },
57
+ body: '{"foo":"bar"}'
58
+ };
59
+ expect(() => getRequestBody(request)).toThrow();
60
+ });
61
+
62
+ it('throws if body is not valid json', () => {
63
+ const request = {
64
+ headers: {
65
+ 'content-type': 'application/json'
66
+ },
67
+ body: 'foobar'
68
+ };
69
+ expect(() => getRequestBody(request)).toThrow();
70
+ });
71
+ });
72
+
73
+ describe('getRequestResponder', () => {
74
+ const services = {asdf: 'asdf'};
75
+
76
+ afterEach(() => {
77
+ jest.clearAllMocks();
78
+ });
79
+
80
+ it('executes static route', () => {
81
+ const request = {
82
+ path: '/foo'
83
+ };
84
+
85
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({
86
+ body: 'response to test route 1'
87
+ })});
88
+
89
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
90
+ routes: () => ([testRoute]),
91
+ pathExtractor: getKeyValue('path')
92
+ });
93
+ const result = getRequestResponder(services)(request);
94
+
95
+ expect(result?.body).toBe('response to test route 1');
96
+ });
97
+
98
+ it('uses route matcher', () => {
99
+ const request = {
100
+ path: '/foo'
101
+ };
102
+ const createRouteWithExtra = makeCreateRoute<AppServices, RouteRequest, {theOne: boolean}>();
103
+
104
+ const testRoute1 = createRouteWithExtra({name: 'test', theOne: false, path: '/foo', handler: () => ({
105
+ body: 'response to test route 1'
106
+ })});
107
+ const testRoute2 = createRouteWithExtra({name: 'test', theOne: true, path: '/foo', handler: () => ({
108
+ body: 'response to test route 2'
109
+ })});
110
+
111
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute1 | typeof testRoute2, RouteRequest, RouteResponse>()({
112
+ routes: () => ([testRoute1, testRoute2]),
113
+ routeMatcher: (_request, route) => route.theOne,
114
+ pathExtractor: getKeyValue('path')
115
+ });
116
+ const result = getRequestResponder(services)(request);
117
+
118
+ expect(result?.body).toBe('response to test route 2');
119
+ });
120
+
121
+ it('executes parameterized route', () => {
122
+ const request = {
123
+ path: '/foo/some-path'
124
+ };
125
+
126
+ const testRoute = createRoute({name: 'test', path: '/foo/:part', handler: (params: {part: string}) => ({
127
+ body: 'response to test route 2: ' + params.part
128
+ })});
129
+
130
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
131
+ routes: () => ([testRoute]),
132
+ pathExtractor: getKeyValue('path')
133
+ });
134
+
135
+ const result = getRequestResponder(services)(request);
136
+
137
+ expect(result?.body).toBe('response to test route 2: some-path');
138
+ });
139
+
140
+ it('returns undefined for unknown route', () => {
141
+ const request = {
142
+ path: '/foobar'
143
+ };
144
+
145
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({
146
+ body: 'response to test route 1'
147
+ })});
148
+
149
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
150
+ routes: () => ([testRoute]),
151
+ pathExtractor: getKeyValue('path')
152
+ });
153
+
154
+ const result = getRequestResponder(services)(request);
155
+
156
+ expect(result).toBeUndefined();
157
+ });
158
+
159
+ it('rethrows errors without an error handler', () => {
160
+ const request = {
161
+ path: '/foo'
162
+ };
163
+
164
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: (): RouteResponse => {
165
+ throw new UnauthorizedError();
166
+ }});
167
+
168
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
169
+ routes: () => ([testRoute]),
170
+ pathExtractor: getKeyValue('path')
171
+ });
172
+
173
+ expect(() => getRequestResponder(services)(request)).toThrow(UnauthorizedError);
174
+ });
175
+
176
+ it('rethrows errors with an error handler', () => {
177
+ const request = {
178
+ path: '/foo'
179
+ };
180
+
181
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: (): RouteResponse => {
182
+ throw new UnauthorizedError();
183
+ }});
184
+
185
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
186
+ routes: () => ([testRoute]),
187
+ pathExtractor: getKeyValue('path'),
188
+ errorHandler: (e: Error) => {
189
+ throw e;
190
+ }
191
+ });
192
+
193
+ expect(() => getRequestResponder(services)(request)).toThrow(UnauthorizedError);
194
+ });
195
+
196
+ it('handles errors with an error handler', () => {
197
+ const request = {
198
+ path: '/foo'
199
+ };
200
+
201
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: (): RouteResponse => {
202
+ throw new UnauthorizedError();
203
+ }});
204
+
205
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
206
+ routes: () => ([testRoute]),
207
+ pathExtractor: getKeyValue('path'),
208
+ errorHandler: (_e: Error) => {
209
+ return {body: 'handled'};
210
+ }
211
+ });
212
+
213
+ const result = getRequestResponder(services)(request);
214
+
215
+ expect(result?.body).toBe('handled');
216
+ });
217
+
218
+ it('handles async errors with an error handler', async() => {
219
+ const request = {
220
+ path: '/foo'
221
+ };
222
+
223
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: async() => {
224
+ throw new UnauthorizedError();
225
+ }});
226
+
227
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, Promise<RouteResponse>>()({
228
+ routes: () => ([testRoute]),
229
+ pathExtractor: getKeyValue('path'),
230
+ errorHandler: async(_e: Error) => {
231
+ return {body: 'handled'};
232
+ }
233
+ });
234
+
235
+ const result = await getRequestResponder(services)(request);
236
+
237
+ expect(result?.body).toBe('handled');
238
+ });
239
+
240
+ it('handles errors with middleware with an error handler', () => {
241
+ const request = {
242
+ path: '/foo'
243
+ };
244
+
245
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: (): RouteResponse => {
246
+ throw new UnauthorizedError();
247
+ }});
248
+
249
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
250
+ routes: () => ([testRoute]),
251
+ pathExtractor: getKeyValue('path'),
252
+ errorHandler: (_e: Error) => {
253
+ return {body: 'handled'};
254
+ }
255
+ });
256
+
257
+ const result = getRequestResponder(services, () => (response) => response ? {body: `hello - ${response.body}`} : response)(request);
258
+
259
+ expect(result?.body).toBe('hello - handled');
260
+ });
261
+
262
+ it('handles async errors with middleware with an error handler', async() => {
263
+ const request = {
264
+ path: '/foo'
265
+ };
266
+
267
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: async() => {
268
+ throw new UnauthorizedError();
269
+ }});
270
+
271
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, Promise<RouteResponse>>()({
272
+ routes: () => ([testRoute]),
273
+ pathExtractor: getKeyValue('path'),
274
+ errorHandler: async(_e: Error) => {
275
+ return {body: 'handled'};
276
+ }
277
+ });
278
+
279
+ const result = await getRequestResponder(services, () => async(response) => {
280
+ const result = await response;
281
+ return result ? {body: `hello - ${result.body}`} : result;
282
+ })(request);
283
+
284
+ expect(result?.body).toBe('hello - handled');
285
+ });
286
+
287
+ it('handles errors from middleware with an error handler', () => {
288
+ const request = {
289
+ path: '/foo'
290
+ };
291
+
292
+ const testRoute = createRoute({name: 'test', path: '/foo',
293
+ requestServiceProvider: composeMiddleware(
294
+ () => (): {} => {
295
+ throw new Error();
296
+ }
297
+ )},
298
+ (): RouteResponse => {
299
+ return {body: 'asdf'};
300
+ }
301
+ );
302
+
303
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
304
+ routes: () => ([testRoute]),
305
+ pathExtractor: getKeyValue('path'),
306
+ errorHandler: (_e: Error) => {
307
+ return {body: 'handled'};
308
+ }
309
+ });
310
+
311
+ const result = getRequestResponder(services)(request);
312
+
313
+ expect(result?.body).toBe('handled');
314
+ });
315
+
316
+ it('handles async errors from middleware with an error handler', async() => {
317
+ const request = {
318
+ path: '/foo'
319
+ };
320
+
321
+ const testRoute = createRoute({name: 'test', path: '/foo',
322
+ requestServiceProvider: composeMiddleware(
323
+ () => (): {} => {
324
+ throw new Error();
325
+ }
326
+ )},
327
+ async() => {
328
+ return {body: 'asdf'};
329
+ }
330
+ );
331
+
332
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, Promise<RouteResponse>>()({
333
+ routes: () => ([testRoute]),
334
+ pathExtractor: getKeyValue('path'),
335
+ errorHandler: async(_e: Error) => {
336
+ return {body: 'handled'};
337
+ }
338
+ });
339
+
340
+ const result = await getRequestResponder(services)(request);
341
+
342
+ expect(result?.body).toBe('handled');
343
+ });
344
+
345
+ it('rethrows errors from middleware without an error handler', () => {
346
+ const request = {
347
+ path: '/foo'
348
+ };
349
+
350
+ const requestServiceProvider = composeMiddleware(
351
+ () => (): {} => {
352
+ throw new UnauthorizedError();
353
+ }
354
+ );
355
+
356
+ const testRoute = createRoute({name: 'test', path: '/foo', requestServiceProvider, handler: (): RouteResponse => {
357
+ return {body: 'asdf'};
358
+ }});
359
+
360
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
361
+ routes: () => ([testRoute]),
362
+ pathExtractor: getKeyValue('path'),
363
+ });
364
+
365
+ expect(() => getRequestResponder(services)(request)).toThrow(UnauthorizedError);
366
+ });
367
+
368
+ it('rethrows errors from middleware with an error handler', () => {
369
+ const request = {
370
+ path: '/foo'
371
+ };
372
+
373
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: (): RouteResponse => {
374
+ throw new UnauthorizedError();
375
+ }});
376
+
377
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
378
+ routes: () => ([testRoute]),
379
+ pathExtractor: getKeyValue('path'),
380
+ errorHandler: (e: Error) => {
381
+ throw e;
382
+ }
383
+ });
384
+
385
+ expect(() => getRequestResponder(services)(request)).toThrow(UnauthorizedError);
386
+ });
387
+
388
+ it('uses middleware on route response', () => {
389
+ const request = {
390
+ path: '/foo'
391
+ };
392
+
393
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({
394
+ body: 'response to test route 1'
395
+ })});
396
+
397
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
398
+ routes: () => ([testRoute]),
399
+ pathExtractor: getKeyValue('path'),
400
+ });
401
+
402
+ const result = getRequestResponder(services, () => (response) => response ? {body: `hello - ${response.body}`} : response)(request);
403
+
404
+ expect(result?.body).toBe('hello - response to test route 1');
405
+ });
406
+
407
+ it('uses middleware on unknown response', () => {
408
+ const request = {
409
+ path: '/foobar'
410
+ };
411
+
412
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({
413
+ body: 'response to test route 1'
414
+ })});
415
+
416
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
417
+ routes: () => ([testRoute]),
418
+ pathExtractor: getKeyValue('path'),
419
+ });
420
+
421
+ const result = getRequestResponder(services, () => (response) => response ? response : 'default')(request);
422
+
423
+ expect(result).toBe('default');
424
+ });
425
+
426
+ it('attaches request context to logger', () => {
427
+ const request = {
428
+ path: '/foo'
429
+ };
430
+
431
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({
432
+ body: 'response to test route 1'
433
+ })});
434
+
435
+ const logger = createConsoleLogger();
436
+ const subContext = logger.createSubContext();
437
+ const setContextSpy = jest.spyOn(logger, 'setContext');
438
+ jest.spyOn(logger, 'createSubContext').mockReturnValue(subContext);
439
+ const setSubContextSpy = jest.spyOn(subContext, 'setContext');
440
+
441
+ const getRequestResponder = makeGetRequestResponder<AppServices, typeof testRoute, RouteRequest, RouteResponse>()({
442
+ routes: () => ([testRoute]),
443
+ logExtractor: request => ({path: request.path}),
444
+ pathExtractor: getKeyValue('path')
445
+ });
446
+ getRequestResponder({...services, logger})(request);
447
+
448
+ expect(setContextSpy).not.toHaveBeenCalled();
449
+ expect(setSubContextSpy).toHaveBeenCalledWith({path: '/foo'});
450
+ });
451
+ });
452
+
453
+ describe('getHeader', () => {
454
+ it('ignores multi-value headers', () => {
455
+ expect(getHeader({headerKey: ['value1', 'value2']}, 'headerKey')).toBe('value1');
456
+ });
457
+ });
458
+
459
+ describe('renderRouteUrl', () => {
460
+ it('renders routes', () => {
461
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({body: 'asdf'})});
462
+ const renderRouteUrl = makeRenderRouteUrl<typeof testRoute>();
463
+
464
+ expect(renderRouteUrl(testRoute, undefined)).toBe('/foo');
465
+ });
466
+
467
+ it('renders routes with params', () => {
468
+ const testRoute = createRoute({name: 'test', path: '/foo/:part', handler: (_param: {part: string}) => ({body: 'asdf'})});
469
+ const renderRouteUrl = makeRenderRouteUrl<typeof testRoute>();
470
+
471
+ expect(renderRouteUrl(testRoute, {part: 'foo'})).toBe('/foo/foo');
472
+ });
473
+
474
+ it('renders routes with query', () => {
475
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({body: 'asdf'})});
476
+ const renderRouteUrl = makeRenderRouteUrl<typeof testRoute>();
477
+
478
+ expect(renderRouteUrl(testRoute, undefined, {param: 'someParam'})).toBe('/foo?param=someParam');
479
+ });
480
+ });
481
+
482
+ describe('apiJsonResponse', () => {
483
+ it('makes a response', () => {
484
+ expect(apiJsonResponse(200, {key: 'value'})).toEqual({
485
+ statusCode: 200,
486
+ data: {key: 'value'},
487
+ body: '{"key":"value"}',
488
+ headers: {'content-type': 'application/json'}
489
+ });
490
+ });
491
+ });
492
+
493
+ describe('apiTextResponse', () => {
494
+ it('makes a response', () => {
495
+ expect(apiTextResponse(200, 'some text')).toEqual({
496
+ statusCode: 200,
497
+ data: 'some text',
498
+ body: 'some text',
499
+ headers: {'content-type': 'text/plain'}
500
+ });
501
+ });
502
+ });
503
+
504
+ describe('apiHtmlResponse', () => {
505
+ it('makes a response', () => {
506
+ expect(apiHtmlResponse(200, 'some text')).toEqual({
507
+ statusCode: 200,
508
+ data: 'some text',
509
+ body: 'some text',
510
+ headers: {'content-type': 'text/html'}
511
+ });
512
+ });
513
+ });
514
+
515
+ describe('requestPayloadProvider', () => {
516
+ it('provides a payload', () => {
517
+ const provider = requestPayloadProvider(unsafePayloadValidator<{key: string}>());
518
+ const {payload} = provider()({
519
+ request: {headers: {'content-type': 'application/json'}, body: '{"key":"string"}'}
520
+ });
521
+
522
+ expect(payload).toEqual({key: 'string'});
523
+ });
524
+
525
+ it('doesn\'t fuss with type', () => {
526
+ const request = {otherRequestValue: 'someValue', headers: {'content-type': 'application/json'}, body: '{"key":"string"}'};
527
+ const composeMiddleware = makeComposeMiddleware<{}, {request: typeof request}>();
528
+ const provider = requestPayloadProvider(unsafePayloadValidator<{key: string}>());
529
+ const result = composeMiddleware(provider)({})({request});
530
+
531
+ expect(result.request.otherRequestValue).toBe('someValue');
532
+ });
533
+
534
+ it('throws when validator fails', () => {
535
+ const validatorThatFails = (_input: any): _input is {key: string} => false;
536
+
537
+ const provider = requestPayloadProvider(validatorThatFails);
538
+
539
+ expect(() =>
540
+ provider()({
541
+ request: {headers: {'content-type': 'application/json'}, body: '{"key":"string"}'}
542
+ })
543
+ ).toThrow(InvalidRequestError);
544
+ });
545
+ });
546
+
547
+ describe('routesList', () => {
548
+ it ('returns route list', () => {
549
+ const testRoute = createRoute({name: 'test', path: '/foo', handler: () => ({body: 'asdf'})});
550
+ const list = routesList([testRoute]);
551
+ expect(list[0]).toBe(testRoute);
552
+ });
553
+ });