@loopback/rest 4.0.0-alpha.8 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (388) hide show
  1. package/CHANGELOG.md +1822 -0
  2. package/LICENSE +1 -1
  3. package/README.md +30 -58
  4. package/dist/body-parsers/body-parser.d.ts +25 -0
  5. package/dist/body-parsers/body-parser.helpers.d.ts +44 -0
  6. package/dist/body-parsers/body-parser.helpers.js +102 -0
  7. package/dist/body-parsers/body-parser.helpers.js.map +1 -0
  8. package/dist/body-parsers/body-parser.js +159 -0
  9. package/dist/body-parsers/body-parser.js.map +1 -0
  10. package/dist/body-parsers/body-parser.json.d.ts +9 -0
  11. package/dist/body-parsers/body-parser.json.js +43 -0
  12. package/dist/body-parsers/body-parser.json.js.map +1 -0
  13. package/dist/body-parsers/body-parser.raw.d.ts +12 -0
  14. package/dist/body-parsers/body-parser.raw.js +39 -0
  15. package/dist/body-parsers/body-parser.raw.js.map +1 -0
  16. package/dist/body-parsers/body-parser.stream.d.ts +12 -0
  17. package/dist/body-parsers/body-parser.stream.js +28 -0
  18. package/dist/body-parsers/body-parser.stream.js.map +1 -0
  19. package/dist/body-parsers/body-parser.text.d.ts +9 -0
  20. package/dist/body-parsers/body-parser.text.js +38 -0
  21. package/dist/body-parsers/body-parser.text.js.map +1 -0
  22. package/dist/body-parsers/body-parser.urlencoded.d.ts +9 -0
  23. package/dist/body-parsers/body-parser.urlencoded.js +36 -0
  24. package/dist/body-parsers/body-parser.urlencoded.js.map +1 -0
  25. package/dist/body-parsers/index.d.ts +8 -0
  26. package/dist/body-parsers/index.js +16 -0
  27. package/dist/body-parsers/index.js.map +1 -0
  28. package/dist/body-parsers/types.d.ts +51 -0
  29. package/dist/body-parsers/types.js +12 -0
  30. package/dist/body-parsers/types.js.map +1 -0
  31. package/dist/coercion/coerce-parameter.d.ts +9 -0
  32. package/dist/coercion/coerce-parameter.js +166 -0
  33. package/dist/coercion/coerce-parameter.js.map +1 -0
  34. package/dist/coercion/utils.d.ts +43 -0
  35. package/dist/coercion/utils.js +96 -0
  36. package/dist/coercion/utils.js.map +1 -0
  37. package/dist/coercion/validator.d.ts +49 -0
  38. package/dist/coercion/validator.js +85 -0
  39. package/dist/coercion/validator.js.map +1 -0
  40. package/dist/http-handler.d.ts +38 -0
  41. package/dist/http-handler.js +68 -0
  42. package/dist/http-handler.js.map +1 -0
  43. package/dist/index.d.ts +36 -1
  44. package/dist/index.js +40 -6
  45. package/dist/index.js.map +1 -0
  46. package/dist/keys.d.ts +198 -0
  47. package/dist/keys.js +202 -0
  48. package/dist/keys.js.map +1 -0
  49. package/dist/parse-json.d.ts +11 -0
  50. package/dist/parse-json.js +42 -0
  51. package/dist/parse-json.js.map +1 -0
  52. package/dist/parser.d.ts +11 -0
  53. package/dist/parser.js +76 -0
  54. package/dist/parser.js.map +1 -0
  55. package/{dist6/src/providers/find-route.d.ts → dist/providers/find-route.provider.d.ts} +3 -1
  56. package/dist/providers/find-route.provider.js +36 -0
  57. package/dist/providers/find-route.provider.js.map +1 -0
  58. package/dist/providers/index.d.ts +6 -0
  59. package/dist/providers/index.js +14 -0
  60. package/dist/providers/index.js.map +1 -0
  61. package/dist/{src/providers/invoke-method.d.ts → providers/invoke-method.provider.d.ts} +3 -1
  62. package/dist/providers/invoke-method.provider.js +30 -0
  63. package/dist/providers/invoke-method.provider.js.map +1 -0
  64. package/dist/providers/log-error.provider.d.ts +6 -0
  65. package/dist/providers/log-error.provider.js +21 -0
  66. package/dist/providers/log-error.provider.js.map +1 -0
  67. package/dist/providers/parse-params.provider.d.ts +15 -0
  68. package/dist/providers/parse-params.provider.js +41 -0
  69. package/dist/providers/parse-params.provider.js.map +1 -0
  70. package/dist/providers/reject.provider.d.ts +10 -0
  71. package/dist/providers/reject.provider.js +47 -0
  72. package/dist/providers/reject.provider.js.map +1 -0
  73. package/dist/{src/providers/send.d.ts → providers/send.provider.d.ts} +1 -4
  74. package/dist/{src/providers/send.js → providers/send.provider.js} +4 -6
  75. package/dist/providers/send.provider.js.map +1 -0
  76. package/dist/request-context.d.ts +36 -0
  77. package/dist/request-context.js +104 -0
  78. package/dist/request-context.js.map +1 -0
  79. package/dist/rest-http-error.d.ts +37 -0
  80. package/dist/rest-http-error.js +51 -0
  81. package/dist/rest-http-error.js.map +1 -0
  82. package/dist/rest.application.d.ts +232 -0
  83. package/dist/rest.application.js +174 -0
  84. package/dist/rest.application.js.map +1 -0
  85. package/dist/rest.component.d.ts +15 -0
  86. package/dist/rest.component.js +72 -0
  87. package/dist/rest.component.js.map +1 -0
  88. package/dist/rest.server.d.ts +443 -0
  89. package/dist/rest.server.js +748 -0
  90. package/dist/rest.server.js.map +1 -0
  91. package/dist/router/base-route.d.ts +29 -0
  92. package/dist/router/base-route.js +41 -0
  93. package/dist/router/base-route.js.map +1 -0
  94. package/dist/router/controller-route.d.ts +61 -0
  95. package/dist/router/controller-route.js +160 -0
  96. package/dist/router/controller-route.js.map +1 -0
  97. package/dist/router/external-express-routes.d.ts +24 -0
  98. package/dist/router/external-express-routes.js +90 -0
  99. package/dist/router/external-express-routes.js.map +1 -0
  100. package/dist/router/handler-route.d.ts +12 -0
  101. package/dist/router/handler-route.js +30 -0
  102. package/dist/router/handler-route.js.map +1 -0
  103. package/dist/router/index.d.ts +14 -0
  104. package/dist/router/index.js +25 -0
  105. package/dist/router/index.js.map +1 -0
  106. package/dist/router/openapi-path.d.ts +14 -0
  107. package/dist/router/openapi-path.js +64 -0
  108. package/dist/router/openapi-path.js.map +1 -0
  109. package/dist/router/redirect-route.d.ts +23 -0
  110. package/dist/router/redirect-route.js +50 -0
  111. package/dist/router/redirect-route.js.map +1 -0
  112. package/dist/router/regexp-router.d.ts +25 -0
  113. package/dist/router/regexp-router.js +84 -0
  114. package/dist/router/regexp-router.js.map +1 -0
  115. package/dist/router/rest-router.d.ts +35 -0
  116. package/dist/{src/internal-types.js → router/rest-router.js} +2 -2
  117. package/dist/router/rest-router.js.map +1 -0
  118. package/dist/router/route-entry.d.ts +46 -0
  119. package/dist/router/route-entry.js +20 -0
  120. package/dist/router/route-entry.js.map +1 -0
  121. package/dist/router/route-sort.d.ts +7 -0
  122. package/dist/router/route-sort.js +75 -0
  123. package/dist/router/route-sort.js.map +1 -0
  124. package/dist/router/router-base.d.ts +42 -0
  125. package/dist/router/router-base.js +101 -0
  126. package/dist/router/router-base.js.map +1 -0
  127. package/dist/router/router-spec.d.ts +3 -0
  128. package/dist/router/router-spec.js +40 -0
  129. package/dist/router/router-spec.js.map +1 -0
  130. package/dist/router/routing-table.d.ts +32 -0
  131. package/dist/router/routing-table.js +86 -0
  132. package/dist/router/routing-table.js.map +1 -0
  133. package/dist/router/trie-router.d.ts +13 -0
  134. package/dist/router/trie-router.js +55 -0
  135. package/dist/router/trie-router.js.map +1 -0
  136. package/dist/router/trie.d.ts +59 -0
  137. package/dist/router/trie.js +180 -0
  138. package/dist/router/trie.js.map +1 -0
  139. package/{dist6/src → dist}/sequence.d.ts +28 -23
  140. package/dist/sequence.js +112 -0
  141. package/dist/sequence.js.map +1 -0
  142. package/dist/spec-enhancers/consolidate.spec-enhancer.d.ts +68 -0
  143. package/dist/spec-enhancers/consolidate.spec-enhancer.js +145 -0
  144. package/dist/spec-enhancers/consolidate.spec-enhancer.js.map +1 -0
  145. package/dist/spec-enhancers/info.spec-enhancer.d.ts +19 -0
  146. package/dist/spec-enhancers/info.spec-enhancer.js +89 -0
  147. package/dist/spec-enhancers/info.spec-enhancer.js.map +1 -0
  148. package/dist/types.d.ts +178 -0
  149. package/dist/types.js +12 -0
  150. package/dist/types.js.map +1 -0
  151. package/dist/validation/ajv-factory.provider.d.ts +12 -0
  152. package/dist/validation/ajv-factory.provider.js +87 -0
  153. package/dist/validation/ajv-factory.provider.js.map +1 -0
  154. package/dist/validation/request-body.validator.d.ts +14 -0
  155. package/dist/validation/request-body.validator.js +161 -0
  156. package/dist/validation/request-body.validator.js.map +1 -0
  157. package/dist/writer.d.ts +9 -0
  158. package/dist/writer.js +62 -0
  159. package/dist/writer.js.map +1 -0
  160. package/package.json +66 -38
  161. package/src/body-parsers/body-parser.helpers.ts +148 -0
  162. package/src/body-parsers/body-parser.json.ts +46 -0
  163. package/src/body-parsers/body-parser.raw.ts +42 -0
  164. package/src/body-parsers/body-parser.stream.ts +27 -0
  165. package/src/body-parsers/body-parser.text.ts +44 -0
  166. package/src/body-parsers/body-parser.ts +208 -0
  167. package/src/body-parsers/body-parser.urlencoded.ts +42 -0
  168. package/src/body-parsers/index.ts +13 -0
  169. package/src/body-parsers/types.ts +60 -0
  170. package/src/coercion/coerce-parameter.ts +207 -0
  171. package/src/coercion/utils.ts +103 -0
  172. package/src/coercion/validator.ts +98 -0
  173. package/src/http-handler.ts +84 -41
  174. package/src/index.ts +37 -30
  175. package/src/keys.ts +273 -20
  176. package/src/parse-json.ts +42 -0
  177. package/src/parser.ts +89 -104
  178. package/src/providers/{find-route.ts → find-route.provider.ts} +10 -7
  179. package/src/providers/index.ts +7 -9
  180. package/src/providers/{invoke-method.ts → invoke-method.provider.ts} +8 -5
  181. package/src/providers/log-error.provider.ts +27 -0
  182. package/src/providers/parse-params.provider.ts +42 -0
  183. package/src/providers/reject.provider.ts +44 -0
  184. package/src/providers/{send.ts → send.provider.ts} +2 -5
  185. package/src/request-context.ts +123 -0
  186. package/src/rest-http-error.ts +87 -0
  187. package/src/rest.application.ts +390 -0
  188. package/src/rest.component.ts +111 -0
  189. package/src/rest.server.ts +1192 -0
  190. package/src/router/base-route.ts +53 -0
  191. package/src/router/controller-route.ts +241 -0
  192. package/src/router/external-express-routes.ts +139 -0
  193. package/src/router/handler-route.ts +44 -0
  194. package/src/router/index.ts +24 -0
  195. package/src/router/openapi-path.ts +67 -0
  196. package/src/router/redirect-route.ts +64 -0
  197. package/src/router/regexp-router.ts +104 -0
  198. package/src/router/rest-router.ts +48 -0
  199. package/src/router/route-entry.ts +74 -0
  200. package/src/router/route-sort.ts +74 -0
  201. package/src/router/router-base.ts +124 -0
  202. package/src/router/router-spec.ts +36 -0
  203. package/src/router/routing-table.ts +83 -279
  204. package/src/router/trie-router.ts +57 -0
  205. package/src/router/trie.ts +233 -0
  206. package/src/sequence.ts +44 -37
  207. package/src/spec-enhancers/consolidate.spec-enhancer.ts +182 -0
  208. package/src/spec-enhancers/info.spec-enhancer.ts +92 -0
  209. package/src/types.ts +216 -0
  210. package/src/validation/ajv-factory.provider.ts +94 -0
  211. package/src/validation/request-body.validator.ts +208 -0
  212. package/src/writer.ts +41 -68
  213. package/api-docs/.DS_Store +0 -0
  214. package/api-docs/apple-touch-icon-114x114-precomposed.png +0 -0
  215. package/api-docs/apple-touch-icon-144x144-precomposed.png +0 -0
  216. package/api-docs/apple-touch-icon-57x57-precomposed.png +0 -0
  217. package/api-docs/apple-touch-icon-72x72-precomposed.png +0 -0
  218. package/api-docs/apple-touch-icon-precomposed.png +0 -0
  219. package/api-docs/apple-touch-icon.png +0 -0
  220. package/api-docs/css/bootstrap.min.css +0 -9
  221. package/api-docs/css/code-themes/arta.css +0 -158
  222. package/api-docs/css/code-themes/ascetic.css +0 -50
  223. package/api-docs/css/code-themes/brown_paper.css +0 -104
  224. package/api-docs/css/code-themes/brown_papersq.png +0 -0
  225. package/api-docs/css/code-themes/dark.css +0 -103
  226. package/api-docs/css/code-themes/default.css +0 -135
  227. package/api-docs/css/code-themes/far.css +0 -111
  228. package/api-docs/css/code-themes/github.css +0 -127
  229. package/api-docs/css/code-themes/googlecode.css +0 -144
  230. package/api-docs/css/code-themes/idea.css +0 -121
  231. package/api-docs/css/code-themes/ir_black.css +0 -104
  232. package/api-docs/css/code-themes/magula.css +0 -121
  233. package/api-docs/css/code-themes/monokai.css +0 -114
  234. package/api-docs/css/code-themes/pojoaque.css +0 -104
  235. package/api-docs/css/code-themes/pojoaque.jpg +0 -0
  236. package/api-docs/css/code-themes/rainbow.css +0 -114
  237. package/api-docs/css/code-themes/school_book.css +0 -111
  238. package/api-docs/css/code-themes/school_book.png +0 -0
  239. package/api-docs/css/code-themes/sl-theme.css +0 -45
  240. package/api-docs/css/code-themes/solarized_dark.css +0 -88
  241. package/api-docs/css/code-themes/solarized_light.css +0 -88
  242. package/api-docs/css/code-themes/sunburst.css +0 -158
  243. package/api-docs/css/code-themes/tomorrow-night-blue.css +0 -52
  244. package/api-docs/css/code-themes/tomorrow-night-bright.css +0 -51
  245. package/api-docs/css/code-themes/tomorrow-night-eighties.css +0 -51
  246. package/api-docs/css/code-themes/tomorrow-night.css +0 -52
  247. package/api-docs/css/code-themes/tomorrow.css +0 -49
  248. package/api-docs/css/code-themes/vs.css +0 -86
  249. package/api-docs/css/code-themes/xcode.css +0 -154
  250. package/api-docs/css/code-themes/zenburn.css +0 -115
  251. package/api-docs/css/main.css +0 -139
  252. package/api-docs/favicon.ico +0 -0
  253. package/api-docs/fonts/0ihfXUL2emPh0ROJezvraLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
  254. package/api-docs/fonts/OsJ2DjdpjqFRVUSto6IffLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
  255. package/api-docs/fonts/_aijTyevf54tkVDLy-dlnLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
  256. package/api-docs/index.html +0 -7082
  257. package/api-docs/js/main.js +0 -19
  258. package/api-docs/js/vendor/bootstrap.min.js +0 -6
  259. package/api-docs/js/vendor/jquery-1.10.1.min.js +0 -6
  260. package/api-docs/js/vendor/jquery.scrollTo-1.4.3.1.js +0 -218
  261. package/api-docs/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js +0 -11
  262. package/dist/src/http-handler.d.ts +0 -19
  263. package/dist/src/http-handler.js +0 -43
  264. package/dist/src/http-handler.js.map +0 -1
  265. package/dist/src/index.d.ts +0 -14
  266. package/dist/src/index.js +0 -33
  267. package/dist/src/index.js.map +0 -1
  268. package/dist/src/internal-types.d.ts +0 -67
  269. package/dist/src/internal-types.js.map +0 -1
  270. package/dist/src/keys.d.ts +0 -22
  271. package/dist/src/keys.js +0 -35
  272. package/dist/src/keys.js.map +0 -1
  273. package/dist/src/parser.d.ts +0 -11
  274. package/dist/src/parser.js +0 -98
  275. package/dist/src/parser.js.map +0 -1
  276. package/dist/src/providers/bind-element.d.ts +0 -7
  277. package/dist/src/providers/bind-element.js +0 -34
  278. package/dist/src/providers/bind-element.js.map +0 -1
  279. package/dist/src/providers/find-route.d.ts +0 -9
  280. package/dist/src/providers/find-route.js +0 -42
  281. package/dist/src/providers/find-route.js.map +0 -1
  282. package/dist/src/providers/get-from-context.d.ts +0 -7
  283. package/dist/src/providers/get-from-context.js +0 -34
  284. package/dist/src/providers/get-from-context.js.map +0 -1
  285. package/dist/src/providers/index.d.ts +0 -8
  286. package/dist/src/providers/index.js +0 -18
  287. package/dist/src/providers/index.js.map +0 -1
  288. package/dist/src/providers/invoke-method.js +0 -36
  289. package/dist/src/providers/invoke-method.js.map +0 -1
  290. package/dist/src/providers/log-error-provider.d.ts +0 -6
  291. package/dist/src/providers/log-error-provider.js +0 -17
  292. package/dist/src/providers/log-error-provider.js.map +0 -1
  293. package/dist/src/providers/parse-params.d.ts +0 -13
  294. package/dist/src/providers/parse-params.js +0 -22
  295. package/dist/src/providers/parse-params.js.map +0 -1
  296. package/dist/src/providers/reject.d.ts +0 -6
  297. package/dist/src/providers/reject.js +0 -40
  298. package/dist/src/providers/reject.js.map +0 -1
  299. package/dist/src/providers/send.js.map +0 -1
  300. package/dist/src/rest-component.d.ts +0 -12
  301. package/dist/src/rest-component.js +0 -50
  302. package/dist/src/rest-component.js.map +0 -1
  303. package/dist/src/rest-server.d.ts +0 -211
  304. package/dist/src/rest-server.js +0 -426
  305. package/dist/src/rest-server.js.map +0 -1
  306. package/dist/src/router/metadata.d.ts +0 -150
  307. package/dist/src/router/metadata.js +0 -410
  308. package/dist/src/router/metadata.js.map +0 -1
  309. package/dist/src/router/routing-table.d.ts +0 -68
  310. package/dist/src/router/routing-table.js +0 -204
  311. package/dist/src/router/routing-table.js.map +0 -1
  312. package/dist/src/sequence.d.ts +0 -81
  313. package/dist/src/sequence.js +0 -104
  314. package/dist/src/sequence.js.map +0 -1
  315. package/dist/src/writer.d.ts +0 -17
  316. package/dist/src/writer.js +0 -87
  317. package/dist/src/writer.js.map +0 -1
  318. package/dist6/index.d.ts +0 -1
  319. package/dist6/index.js +0 -12
  320. package/dist6/src/http-handler.d.ts +0 -19
  321. package/dist6/src/http-handler.js +0 -53
  322. package/dist6/src/http-handler.js.map +0 -1
  323. package/dist6/src/index.d.ts +0 -14
  324. package/dist6/src/index.js +0 -33
  325. package/dist6/src/index.js.map +0 -1
  326. package/dist6/src/internal-types.d.ts +0 -67
  327. package/dist6/src/internal-types.js +0 -7
  328. package/dist6/src/internal-types.js.map +0 -1
  329. package/dist6/src/keys.d.ts +0 -22
  330. package/dist6/src/keys.js +0 -35
  331. package/dist6/src/keys.js.map +0 -1
  332. package/dist6/src/parser.d.ts +0 -11
  333. package/dist6/src/parser.js +0 -108
  334. package/dist6/src/parser.js.map +0 -1
  335. package/dist6/src/providers/bind-element.d.ts +0 -7
  336. package/dist6/src/providers/bind-element.js +0 -34
  337. package/dist6/src/providers/bind-element.js.map +0 -1
  338. package/dist6/src/providers/find-route.js +0 -42
  339. package/dist6/src/providers/find-route.js.map +0 -1
  340. package/dist6/src/providers/get-from-context.d.ts +0 -7
  341. package/dist6/src/providers/get-from-context.js +0 -34
  342. package/dist6/src/providers/get-from-context.js.map +0 -1
  343. package/dist6/src/providers/index.d.ts +0 -8
  344. package/dist6/src/providers/index.js +0 -18
  345. package/dist6/src/providers/index.js.map +0 -1
  346. package/dist6/src/providers/invoke-method.d.ts +0 -7
  347. package/dist6/src/providers/invoke-method.js +0 -44
  348. package/dist6/src/providers/invoke-method.js.map +0 -1
  349. package/dist6/src/providers/log-error-provider.d.ts +0 -6
  350. package/dist6/src/providers/log-error-provider.js +0 -17
  351. package/dist6/src/providers/log-error-provider.js.map +0 -1
  352. package/dist6/src/providers/parse-params.d.ts +0 -13
  353. package/dist6/src/providers/parse-params.js +0 -22
  354. package/dist6/src/providers/parse-params.js.map +0 -1
  355. package/dist6/src/providers/reject.d.ts +0 -6
  356. package/dist6/src/providers/reject.js +0 -40
  357. package/dist6/src/providers/reject.js.map +0 -1
  358. package/dist6/src/providers/send.d.ts +0 -15
  359. package/dist6/src/providers/send.js +0 -24
  360. package/dist6/src/providers/send.js.map +0 -1
  361. package/dist6/src/rest-component.d.ts +0 -12
  362. package/dist6/src/rest-component.js +0 -50
  363. package/dist6/src/rest-component.js.map +0 -1
  364. package/dist6/src/rest-server.d.ts +0 -211
  365. package/dist6/src/rest-server.js +0 -444
  366. package/dist6/src/rest-server.js.map +0 -1
  367. package/dist6/src/router/metadata.d.ts +0 -150
  368. package/dist6/src/router/metadata.js +0 -410
  369. package/dist6/src/router/metadata.js.map +0 -1
  370. package/dist6/src/router/routing-table.d.ts +0 -68
  371. package/dist6/src/router/routing-table.js +0 -218
  372. package/dist6/src/router/routing-table.js.map +0 -1
  373. package/dist6/src/sequence.js +0 -114
  374. package/dist6/src/sequence.js.map +0 -1
  375. package/dist6/src/writer.d.ts +0 -17
  376. package/dist6/src/writer.js +0 -87
  377. package/dist6/src/writer.js.map +0 -1
  378. package/index.d.ts +0 -6
  379. package/index.js +0 -9
  380. package/src/internal-types.ts +0 -96
  381. package/src/providers/bind-element.ts +0 -15
  382. package/src/providers/get-from-context.ts +0 -16
  383. package/src/providers/log-error-provider.ts +0 -23
  384. package/src/providers/parse-params.ts +0 -20
  385. package/src/providers/reject.ts +0 -27
  386. package/src/rest-component.ts +0 -54
  387. package/src/rest-server.ts +0 -584
  388. package/src/router/metadata.ts +0 -517
@@ -0,0 +1,53 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/rest
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {Context, InvocationSource} from '@loopback/context';
7
+ import {OperationObject} from '@loopback/openapi-v3';
8
+ import {OperationArgs, OperationRetval} from '../types';
9
+ import {RouteEntry} from './route-entry';
10
+
11
+ /**
12
+ * Base implementation of RouteEntry
13
+ */
14
+ export abstract class BaseRoute implements RouteEntry {
15
+ public readonly verb: string;
16
+
17
+ /**
18
+ * Construct a new route
19
+ * @param verb - http verb
20
+ * @param path - http request path pattern
21
+ * @param spec - OpenAPI operation spec
22
+ */
23
+ constructor(
24
+ verb: string,
25
+ public readonly path: string,
26
+ public readonly spec: OperationObject,
27
+ ) {
28
+ this.verb = verb.toLowerCase();
29
+ }
30
+
31
+ abstract updateBindings(requestContext: Context): void;
32
+
33
+ abstract invokeHandler(
34
+ requestContext: Context,
35
+ args: OperationArgs,
36
+ ): Promise<OperationRetval>;
37
+
38
+ describe(): string {
39
+ return `"${this.verb} ${this.path}"`;
40
+ }
41
+
42
+ toString() {
43
+ return `${this.constructor.name} - ${this.verb} ${this.path}`;
44
+ }
45
+ }
46
+
47
+ export class RouteSource implements InvocationSource<RouteEntry> {
48
+ type = 'route';
49
+ constructor(readonly value: RouteEntry) {}
50
+ toString() {
51
+ return `${this.value.verb} ${this.value.path}`;
52
+ }
53
+ }
@@ -0,0 +1,241 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/rest
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {
7
+ BindingScope,
8
+ Constructor,
9
+ Context,
10
+ instantiateClass,
11
+ invokeMethod,
12
+ ValueOrPromise,
13
+ } from '@loopback/context';
14
+ import {CoreBindings} from '@loopback/core';
15
+ import {ControllerSpec, OperationObject} from '@loopback/openapi-v3';
16
+ import assert from 'assert';
17
+ import debugFactory from 'debug';
18
+ import HttpErrors from 'http-errors';
19
+ import {inspect} from 'util';
20
+ import {RestBindings} from '../keys';
21
+ import {OperationArgs, OperationRetval} from '../types';
22
+ import {BaseRoute, RouteSource} from './base-route';
23
+
24
+ const debug = debugFactory('loopback:rest:controller-route');
25
+ /*
26
+ * A controller instance with open properties/methods
27
+ */
28
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
29
+ export type ControllerInstance = {[name: string]: any} & object;
30
+
31
+ /**
32
+ * A factory function to create controller instances synchronously or
33
+ * asynchronously
34
+ */
35
+ export type ControllerFactory<T extends ControllerInstance> = (
36
+ ctx: Context,
37
+ ) => ValueOrPromise<T>;
38
+
39
+ /**
40
+ * Controller class
41
+ */
42
+ export type ControllerClass<T extends ControllerInstance> = Constructor<T>;
43
+
44
+ /**
45
+ * A route backed by a controller
46
+ */
47
+ export class ControllerRoute<T> extends BaseRoute {
48
+ protected readonly _controllerCtor: ControllerClass<T>;
49
+ protected readonly _controllerName: string;
50
+ protected readonly _methodName: string;
51
+ protected readonly _controllerFactory: ControllerFactory<T>;
52
+
53
+ /**
54
+ * Construct a controller based route
55
+ * @param verb - http verb
56
+ * @param path - http request path
57
+ * @param spec - OpenAPI operation spec
58
+ * @param controllerCtor - Controller class
59
+ * @param controllerFactory - A factory function to create a controller instance
60
+ * @param methodName - Controller method name, default to `x-operation-name`
61
+ */
62
+ constructor(
63
+ verb: string,
64
+ path: string,
65
+ spec: OperationObject,
66
+ controllerCtor: ControllerClass<T>,
67
+ controllerFactory?: ControllerFactory<T>,
68
+ methodName?: string,
69
+ ) {
70
+ const controllerName = spec['x-controller-name'] || controllerCtor.name;
71
+ methodName = methodName ?? spec['x-operation-name'];
72
+
73
+ if (!methodName) {
74
+ throw new Error(
75
+ 'methodName must be provided either via the ControllerRoute argument ' +
76
+ 'or via "x-operation-name" extension field in OpenAPI spec. ' +
77
+ `Operation: "${verb} ${path}" ` +
78
+ `Controller: ${controllerName}.`,
79
+ );
80
+ }
81
+
82
+ super(
83
+ verb,
84
+ path,
85
+ // Add x-controller-name and x-operation-name if not present
86
+ Object.assign(
87
+ {
88
+ 'x-controller-name': controllerName,
89
+ 'x-operation-name': methodName,
90
+ tags: [controllerName],
91
+ },
92
+ spec,
93
+ ),
94
+ );
95
+
96
+ this._controllerFactory =
97
+ controllerFactory ?? createControllerFactoryForClass(controllerCtor);
98
+ this._controllerCtor = controllerCtor;
99
+ this._controllerName = controllerName || controllerCtor.name;
100
+ this._methodName = methodName;
101
+ }
102
+
103
+ describe(): string {
104
+ return `${this._controllerName}.${this._methodName}`;
105
+ }
106
+
107
+ updateBindings(requestContext: Context) {
108
+ /*
109
+ * Bind current controller to the request context in `SINGLETON` scope.
110
+ * Within the same request, we always get the same instance of the
111
+ * current controller when `requestContext.get(CoreBindings.CONTROLLER_CURRENT)`
112
+ * is invoked.
113
+ *
114
+ * Please note the controller class itself can be bound to other scopes,
115
+ * such as SINGLETON or TRANSIENT (default) in the application or server
116
+ * context.
117
+ *
118
+ * - SINGLETON: all requests share the same instance of a given controller
119
+ * - TRANSIENT: each request has its own instance of a given controller
120
+ */
121
+ requestContext
122
+ .bind(CoreBindings.CONTROLLER_CURRENT)
123
+ .toDynamicValue(() => this._controllerFactory(requestContext))
124
+ .inScope(BindingScope.SINGLETON);
125
+ requestContext.bind(CoreBindings.CONTROLLER_CLASS).to(this._controllerCtor);
126
+ requestContext
127
+ .bind(CoreBindings.CONTROLLER_METHOD_NAME)
128
+ .to(this._methodName);
129
+ requestContext.bind(RestBindings.OPERATION_SPEC_CURRENT).to(this.spec);
130
+ }
131
+
132
+ async invokeHandler(
133
+ requestContext: Context,
134
+ args: OperationArgs,
135
+ ): Promise<OperationRetval> {
136
+ const controller = await requestContext.get<ControllerInstance>(
137
+ 'controller.current',
138
+ );
139
+ if (typeof controller[this._methodName] !== 'function') {
140
+ throw new HttpErrors.NotFound(
141
+ `Controller method not found: ${this.describe()}`,
142
+ );
143
+ }
144
+ // Invoke the method with dependency injection
145
+ return invokeMethod(controller, this._methodName, requestContext, args, {
146
+ source: new RouteSource(this),
147
+ });
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Create a controller factory function for a given binding key
153
+ * @param key - Binding key
154
+ */
155
+ export function createControllerFactoryForBinding<T>(
156
+ key: string,
157
+ ): ControllerFactory<T> {
158
+ return ctx => ctx.get<T>(key);
159
+ }
160
+
161
+ /**
162
+ * Create a controller factory function for a given class
163
+ * @param controllerCtor - Controller class
164
+ */
165
+ export function createControllerFactoryForClass<T>(
166
+ controllerCtor: ControllerClass<T>,
167
+ ): ControllerFactory<T> {
168
+ return async ctx => {
169
+ // By default, we get an instance of the controller from the context
170
+ // using `controllers.<controllerName>` as the key
171
+ let inst = await ctx.get<T>(`controllers.${controllerCtor.name}`, {
172
+ optional: true,
173
+ });
174
+ if (inst === undefined) {
175
+ inst = await instantiateClass<T>(controllerCtor, ctx);
176
+ }
177
+ return inst;
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Create a controller factory function for a given instance
183
+ * @param controllerCtor - Controller instance
184
+ */
185
+ export function createControllerFactoryForInstance<T>(
186
+ controllerInst: T,
187
+ ): ControllerFactory<T> {
188
+ return ctx => controllerInst;
189
+ }
190
+
191
+ /**
192
+ * Create routes for a controller with the given spec
193
+ * @param spec - Controller spec
194
+ * @param controllerCtor - Controller class
195
+ * @param controllerFactory - Controller factory
196
+ */
197
+ export function createRoutesForController<T>(
198
+ spec: ControllerSpec,
199
+ controllerCtor: ControllerClass<T>,
200
+ controllerFactory?: ControllerFactory<T>,
201
+ ) {
202
+ const routes: ControllerRoute<T>[] = [];
203
+ assert(
204
+ typeof spec === 'object' && !!spec,
205
+ 'API specification must be a non-null object',
206
+ );
207
+ if (!spec.paths || !Object.keys(spec.paths).length) {
208
+ return routes;
209
+ }
210
+
211
+ debug(
212
+ 'Creating route for controller with API %s',
213
+ inspect(spec, {depth: null}),
214
+ );
215
+
216
+ const basePath = spec.basePath ?? '/';
217
+ for (const p in spec.paths) {
218
+ for (const verb in spec.paths[p]) {
219
+ const opSpec: OperationObject = spec.paths[p][verb];
220
+ const fullPath = joinPath(basePath, p);
221
+ const route = new ControllerRoute(
222
+ verb,
223
+ fullPath,
224
+ opSpec,
225
+ controllerCtor,
226
+ controllerFactory,
227
+ );
228
+ routes.push(route);
229
+ }
230
+ }
231
+ return routes;
232
+ }
233
+
234
+ export function joinPath(basePath: string, path: string) {
235
+ const fullPath = [basePath, path]
236
+ .join('/') // Join by /
237
+ .replace(/(\/){2,}/g, '/') // Remove extra /
238
+ .replace(/\/$/, '') // Remove trailing /
239
+ .replace(/^(\/)?/, '/'); // Add leading /
240
+ return fullPath;
241
+ }
@@ -0,0 +1,139 @@
1
+ // Copyright IBM Corp. 2019. All Rights Reserved.
2
+ // Node module: @loopback/rest
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {Context} from '@loopback/context';
7
+ import {
8
+ executeExpressRequestHandler,
9
+ ExpressRequestHandler,
10
+ Request,
11
+ } from '@loopback/express';
12
+ import {
13
+ OpenApiSpec,
14
+ OperationObject,
15
+ SchemasObject,
16
+ } from '@loopback/openapi-v3';
17
+ import express from 'express';
18
+ import {PathParams} from 'express-serve-static-core';
19
+ import HttpErrors from 'http-errors';
20
+ import {ServeStaticOptions} from 'serve-static';
21
+ import {RequestContext} from '../request-context';
22
+ import {OperationArgs, OperationRetval, PathParameterValues} from '../types';
23
+ import {ResolvedRoute, RouteEntry} from './route-entry';
24
+ import {assignRouterSpec, RouterSpec} from './router-spec';
25
+
26
+ /**
27
+ * A registry of external, Express-style routes. These routes are invoked
28
+ * _after_ no LB4 route (controller or handler based) matched the incoming
29
+ * request.
30
+ *
31
+ * @internal
32
+ */
33
+ export class ExternalExpressRoutes {
34
+ protected _externalRoutes: express.Router = express.Router();
35
+ protected _staticRoutes: express.Router = express.Router();
36
+ protected _specForExternalRoutes: RouterSpec = {paths: {}};
37
+
38
+ get routerSpec(): RouterSpec {
39
+ return this._specForExternalRoutes;
40
+ }
41
+
42
+ public registerAssets(
43
+ path: PathParams,
44
+ rootDir: string,
45
+ options?: ServeStaticOptions,
46
+ ) {
47
+ this._staticRoutes.use(path, express.static(rootDir, options));
48
+ }
49
+
50
+ public mountRouter(
51
+ basePath: string,
52
+ router: ExpressRequestHandler,
53
+ spec: RouterSpec = {paths: {}},
54
+ ) {
55
+ this._externalRoutes.use(basePath, router);
56
+
57
+ spec = rebaseOpenApiSpec(spec, basePath);
58
+ assignRouterSpec(this._specForExternalRoutes, spec);
59
+ }
60
+
61
+ find(request: Request): ResolvedRoute {
62
+ return new ExternalRoute(
63
+ this._externalRoutes,
64
+ this._staticRoutes,
65
+ request.method,
66
+ request.url,
67
+ {
68
+ description: 'External route or a static asset',
69
+ 'x-visibility': 'undocumented',
70
+ responses: {},
71
+ },
72
+ );
73
+ }
74
+ }
75
+
76
+ class ExternalRoute implements RouteEntry, ResolvedRoute {
77
+ // ResolvedRoute API
78
+ readonly pathParams: PathParameterValues = [];
79
+ readonly schemas: SchemasObject = {};
80
+
81
+ constructor(
82
+ private readonly _externalRouter: express.Router,
83
+ private readonly _staticAssets: express.Router,
84
+ public readonly verb: string,
85
+ public readonly path: string,
86
+ public readonly spec: OperationObject,
87
+ ) {}
88
+
89
+ updateBindings(requestContext: Context): void {
90
+ // no-op
91
+ }
92
+
93
+ async invokeHandler(
94
+ {request, response}: RequestContext,
95
+ args: OperationArgs,
96
+ ): Promise<OperationRetval> {
97
+ let handled = await executeExpressRequestHandler(
98
+ this._externalRouter,
99
+ request,
100
+ response,
101
+ );
102
+ if (handled) return;
103
+
104
+ handled = await executeExpressRequestHandler(
105
+ this._staticAssets,
106
+ request,
107
+ response,
108
+ );
109
+ if (handled) return;
110
+
111
+ // Express router called next, which means no route was matched
112
+ throw new HttpErrors.NotFound(
113
+ `Endpoint "${request.method} ${request.path}" not found.`,
114
+ );
115
+ }
116
+
117
+ describe(): string {
118
+ // TODO(bajtos) provide better description for Express routes with spec
119
+ return `External Express route "${this.verb} ${this.path}"`;
120
+ }
121
+ }
122
+
123
+ export function rebaseOpenApiSpec<T extends Partial<OpenApiSpec>>(
124
+ spec: T,
125
+ basePath: string,
126
+ ): T {
127
+ if (!spec.paths) return spec;
128
+ if (!basePath || basePath === '/') return spec;
129
+
130
+ const localPaths = spec.paths;
131
+ // Don't modify the spec object provided to us.
132
+ spec = Object.assign({}, spec);
133
+ spec.paths = {};
134
+ for (const url in localPaths) {
135
+ spec.paths[`${basePath}${url}`] = localPaths[url];
136
+ }
137
+
138
+ return spec;
139
+ }
@@ -0,0 +1,44 @@
1
+ // Copyright IBM Corp. 2018,2020. All Rights Reserved.
2
+ // Node module: @loopback/rest
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {Context, invokeMethodWithInterceptors} from '@loopback/context';
7
+ import {OperationObject} from '@loopback/openapi-v3';
8
+ import {RestBindings} from '../keys';
9
+ import {OperationArgs, OperationRetval} from '../types';
10
+ import {BaseRoute, RouteSource} from './base-route';
11
+
12
+ export class Route extends BaseRoute {
13
+ constructor(
14
+ verb: string,
15
+ path: string,
16
+ public readonly spec: OperationObject,
17
+ protected readonly _handler: Function,
18
+ ) {
19
+ super(verb, path, spec);
20
+ }
21
+
22
+ describe(): string {
23
+ return this._handler.name || super.describe();
24
+ }
25
+
26
+ updateBindings(requestContext: Context) {
27
+ requestContext.bind(RestBindings.OPERATION_SPEC_CURRENT).to(this.spec);
28
+ }
29
+
30
+ async invokeHandler(
31
+ requestContext: Context,
32
+ args: OperationArgs,
33
+ ): Promise<OperationRetval> {
34
+ // Use `invokeMethodWithInterceptors` to invoke the handler function so
35
+ // that global interceptors are applied
36
+ return invokeMethodWithInterceptors(
37
+ requestContext,
38
+ this,
39
+ '_handler',
40
+ args,
41
+ {source: new RouteSource(this)},
42
+ );
43
+ }
44
+ }
@@ -0,0 +1,24 @@
1
+ // Copyright IBM Corp. 2018,2019. All Rights Reserved.
2
+ // Node module: @loopback/rest
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ // routes
7
+ export * from './route-entry';
8
+ export * from './base-route';
9
+ export * from './controller-route';
10
+ export * from './handler-route';
11
+ export * from './external-express-routes';
12
+ export * from './redirect-route';
13
+
14
+ // routers
15
+ export * from './rest-router';
16
+ export * from './trie-router';
17
+ export * from './regexp-router';
18
+
19
+ // helpers
20
+ export * from './routing-table';
21
+ export * from './route-sort';
22
+ export * from './openapi-path';
23
+ export * from './trie';
24
+ export * from './router-spec';
@@ -0,0 +1,67 @@
1
+ // Copyright IBM Corp. 2018,2019. All Rights Reserved.
2
+ // Node module: @loopback/rest
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {parse} from 'path-to-regexp';
7
+
8
+ /**
9
+ * OpenAPI spec 3.x does not specify the valid forms of path templates.
10
+ *
11
+ * Other ones such as [URI Template](https://tools.ietf.org/html/rfc6570#section-2.3)
12
+ * or [path-to-regexp](https://github.com/pillarjs/path-to-regexp#named-parameters)
13
+ * allows `[A-Za-z0-9_]`
14
+ */
15
+ const POSSIBLE_VARNAME_PATTERN = /\{([^\}]+)\}/g;
16
+ const VALID_VARNAME_PATTERN = /^[A-Za-z0-9_]+$/;
17
+
18
+ /**
19
+ * Validate the path to be compatible with OpenAPI path template. No parameter
20
+ * modifier, custom pattern, or unnamed parameter is allowed.
21
+ */
22
+ export function validateApiPath(path = '/') {
23
+ const tokens = parse(path);
24
+ for (const token of tokens) {
25
+ if (typeof token === 'string') continue;
26
+ if (typeof token === 'object') {
27
+ const name = token.name;
28
+ if (typeof name === 'string' && name !== '') {
29
+ throw new Error(
30
+ `Invalid path template: '${path}'. Please use {${name}} instead of ':${name}'`,
31
+ );
32
+ }
33
+ if (typeof name === 'number') {
34
+ throw new Error(`Unnamed parameter is not allowed in path '${path}'`);
35
+ }
36
+ const valid = token.prefix.match(VALID_VARNAME_PATTERN);
37
+ if (!valid) {
38
+ throw new Error(
39
+ `Invalid parameter name '${token.prefix}' found in path '${path}'`,
40
+ );
41
+ }
42
+ if (['?', '+', '*'].includes(token.modifier)) {
43
+ throw new Error(
44
+ `Parameter modifier '{${token.prefix}}${token.modifier}' is not allowed in path '${path}`,
45
+ );
46
+ }
47
+ }
48
+ }
49
+ return path;
50
+ }
51
+
52
+ /**
53
+ * Get all path variables. For example, `/root/{foo}/bar` => `['foo']`
54
+ */
55
+ export function getPathVariables(path: string) {
56
+ return path.match(POSSIBLE_VARNAME_PATTERN);
57
+ }
58
+
59
+ /**
60
+ * Convert an OpenAPI path to Express (path-to-regexp) style
61
+ * @param path - OpenAPI path with optional variables as `{var}`
62
+ */
63
+ export function toExpressPath(path: string) {
64
+ // Convert `.` to `\\.` so that path-to-regexp will treat it as the plain
65
+ // `.` character
66
+ return path.replace(POSSIBLE_VARNAME_PATTERN, '{:$1}').replace('.', '\\.');
67
+ }
@@ -0,0 +1,64 @@
1
+ // Copyright IBM Corp. 2019,2020. All Rights Reserved.
2
+ // Node module: @loopback/rest
3
+ // This file is licensed under the MIT License.
4
+ // License text available at https://opensource.org/licenses/MIT
5
+
6
+ import {OperationObject, SchemasObject} from '@loopback/openapi-v3';
7
+ import {ResolvedRoute, RouteEntry} from '.';
8
+ import {RequestContext} from '../request-context';
9
+ import {OperationArgs, OperationRetval, PathParameterValues} from '../types';
10
+
11
+ export class RedirectRoute implements RouteEntry, ResolvedRoute {
12
+ // ResolvedRoute API
13
+ readonly pathParams: PathParameterValues = [];
14
+ readonly schemas: SchemasObject = {};
15
+
16
+ // RouteEntry implementation
17
+ readonly verb: string = 'get';
18
+ readonly path: string;
19
+ readonly spec: OperationObject = {
20
+ description: 'LoopBack Redirect route',
21
+ 'x-visibility': 'undocumented',
22
+ responses: {},
23
+ };
24
+
25
+ constructor(
26
+ public readonly sourcePath: string,
27
+ public readonly targetLocation: string,
28
+ public readonly statusCode: number = 303,
29
+ ) {
30
+ this.path = sourcePath;
31
+ }
32
+
33
+ async invokeHandler(
34
+ {response}: RequestContext,
35
+ args: OperationArgs,
36
+ ): Promise<OperationRetval> {
37
+ response.redirect(this.statusCode, this.targetLocation);
38
+ }
39
+
40
+ updateBindings(requestContext: RequestContext) {
41
+ // no-op
42
+ }
43
+
44
+ describe(): string {
45
+ return `RedirectRoute from "${this.sourcePath}" to "${this.targetLocation}"`;
46
+ }
47
+
48
+ /**
49
+ * type guard type checker for this class
50
+ * @param obj
51
+ */
52
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
53
+ static isRedirectRoute(obj: any): obj is RedirectRoute {
54
+ const redirectOptions = obj as RedirectRoute;
55
+ if (
56
+ redirectOptions?.targetLocation &&
57
+ redirectOptions.spec &&
58
+ redirectOptions.spec.description === 'LoopBack Redirect route'
59
+ ) {
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ }