@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,104 @@
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 {inject} from '@loopback/context';
7
+ import {inspect} from 'util';
8
+ import {RestBindings} from '../keys';
9
+ import {PathParameterValues} from '../types';
10
+ import {toExpressPath} from './openapi-path';
11
+ import {RestRouterOptions} from './rest-router';
12
+ import {createResolvedRoute, ResolvedRoute, RouteEntry} from './route-entry';
13
+ import {compareRoute} from './route-sort';
14
+ import {BaseRouter} from './router-base';
15
+ import {pathToRegexp, Key} from 'path-to-regexp';
16
+
17
+ const debug = require('debug')('loopback:rest:router:regexp');
18
+
19
+ /**
20
+ * Route entry with path-to-regexp
21
+ */
22
+ interface RegExpRouteEntry extends RouteEntry {
23
+ regexp: RegExp;
24
+ keys: Key[];
25
+ }
26
+
27
+ /**
28
+ * Router implementation based on regexp matching
29
+ */
30
+ export class RegExpRouter extends BaseRouter {
31
+ private routes: RegExpRouteEntry[] = [];
32
+
33
+ // Sort the routes based on their paths and variables
34
+ private _sorted: boolean;
35
+ private _sort() {
36
+ if (!this._sorted) {
37
+ this.routes.sort(compareRoute);
38
+ this._sorted = true;
39
+ }
40
+ }
41
+
42
+ constructor(
43
+ @inject(RestBindings.ROUTER_OPTIONS, {optional: true})
44
+ options?: RestRouterOptions,
45
+ ) {
46
+ super(options);
47
+ }
48
+
49
+ protected addRouteWithPathVars(route: RouteEntry) {
50
+ const path = toExpressPath(route.path);
51
+ const keys: Key[] = [];
52
+ const regexp = pathToRegexp(path, keys, {
53
+ strict: this.options.strict,
54
+ end: true,
55
+ });
56
+ const entry: RegExpRouteEntry = Object.assign(route, {keys, regexp});
57
+ this.routes.push(entry);
58
+ this._sorted = false;
59
+ }
60
+
61
+ protected findRouteWithPathVars(
62
+ verb: string,
63
+ path: string,
64
+ ): ResolvedRoute | undefined {
65
+ this._sort();
66
+ for (const r of this.routes) {
67
+ debug('trying endpoint %s', inspect(r, {depth: 5}));
68
+ if (r.verb !== verb.toLowerCase()) {
69
+ debug(' -> verb mismatch');
70
+ continue;
71
+ }
72
+
73
+ const match = r.regexp.exec(path);
74
+ if (!match) {
75
+ debug(' -> path mismatch');
76
+ continue;
77
+ }
78
+
79
+ const pathParams = this._buildPathParams(r, match);
80
+ debug(' -> found with params: %j', pathParams);
81
+
82
+ return createResolvedRoute(r, pathParams);
83
+ }
84
+ return undefined;
85
+ }
86
+
87
+ protected listRoutesWithPathVars() {
88
+ this._sort();
89
+ return this.routes;
90
+ }
91
+
92
+ private _buildPathParams(
93
+ route: RegExpRouteEntry,
94
+ pathMatch: RegExpExecArray,
95
+ ): PathParameterValues {
96
+ const pathParams: PathParameterValues = {};
97
+ for (const ix in route.keys) {
98
+ const key = route.keys[ix];
99
+ const matchIndex = +ix + 1;
100
+ pathParams[key.name] = pathMatch[matchIndex];
101
+ }
102
+ return pathParams;
103
+ }
104
+ }
@@ -0,0 +1,48 @@
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 {Request} from '../types';
7
+ import {ResolvedRoute, RouteEntry} from './route-entry';
8
+
9
+ /*
10
+ /**
11
+ * Interface for router implementation
12
+ */
13
+ export interface RestRouter {
14
+ /**
15
+ * Add a route to the router
16
+ * @param route - A route entry
17
+ */
18
+ add(route: RouteEntry): void;
19
+
20
+ /**
21
+ * Find a matching route for the given http request
22
+ * @param request - Http request
23
+ * @returns The resolved route, if not found, `undefined` is returned
24
+ */
25
+ find(request: Request): ResolvedRoute | undefined;
26
+
27
+ /**
28
+ * List all routes
29
+ */
30
+ list(): RouteEntry[];
31
+ }
32
+
33
+ export type RestRouterOptions = {
34
+ /**
35
+ * When `true` it uses trailing slash to match. (default: `false`)
36
+ *
37
+ * 1. `strict` is true:
38
+ * - request `/orders` matches route `/orders` but not `/orders/`
39
+ * - request `/orders/` matches route `/orders/` but not `/orders`
40
+ *
41
+ * 2. `strict` is false (default)
42
+ * - request `/orders` matches route `/orders` first and falls back to `/orders/`
43
+ * - request `/orders/` matches route `/orders/` first and falls back to `/orders`
44
+ *
45
+ * See `strict routing` at http://expressjs.com/en/4x/api.html#app
46
+ */
47
+ strict?: boolean;
48
+ };
@@ -0,0 +1,74 @@
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} from '@loopback/context';
7
+ import {OperationObject, SchemasObject} from '@loopback/openapi-v3';
8
+ import {OperationArgs, OperationRetval, PathParameterValues} from '../types';
9
+
10
+ /**
11
+ * An entry in the routing table
12
+ */
13
+ export interface RouteEntry {
14
+ /**
15
+ * http verb
16
+ */
17
+ readonly verb: string;
18
+ /**
19
+ * http path
20
+ */
21
+ readonly path: string;
22
+ /**
23
+ * OpenAPI operation spec
24
+ */
25
+ readonly spec: OperationObject;
26
+
27
+ /**
28
+ * Update bindings for the request context
29
+ * @param requestContext
30
+ */
31
+ updateBindings(requestContext: Context): void;
32
+
33
+ /**
34
+ * A handler to invoke the resolved controller method
35
+ * @param requestContext
36
+ * @param args
37
+ */
38
+ invokeHandler(
39
+ requestContext: Context,
40
+ args: OperationArgs,
41
+ ): Promise<OperationRetval>;
42
+
43
+ describe(): string;
44
+ }
45
+
46
+ /**
47
+ * A route with path parameters resolved
48
+ */
49
+ export interface ResolvedRoute extends RouteEntry {
50
+ readonly pathParams: PathParameterValues;
51
+
52
+ /**
53
+ * Server/application wide schemas shared by multiple routes,
54
+ * e.g. model schemas. This is a temporary workaround for
55
+ * missing support for $ref references, see
56
+ * https://github.com/strongloop/loopback-next/issues/435
57
+ */
58
+ readonly schemas: SchemasObject;
59
+ }
60
+
61
+ export function createResolvedRoute(
62
+ route: RouteEntry,
63
+ pathParams: PathParameterValues,
64
+ ): ResolvedRoute {
65
+ return Object.create(route, {
66
+ pathParams: {
67
+ writable: false,
68
+ value: pathParams,
69
+ },
70
+ schemas: {
71
+ value: {},
72
+ },
73
+ });
74
+ }
@@ -0,0 +1,74 @@
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 {parse, Token} from 'path-to-regexp';
7
+ import {RouteEntry} from './route-entry';
8
+
9
+ /**
10
+ * Sorting order for http verbs
11
+ */
12
+ const HTTP_VERBS: {[name: string]: number} = {
13
+ post: 1,
14
+ put: 2,
15
+ patch: 3,
16
+ get: 4,
17
+ head: 5,
18
+ delete: 6,
19
+ options: 7,
20
+ };
21
+
22
+ /**
23
+ * Compare two routes by verb/path for sorting
24
+ * @param route1 - First route entry
25
+ * @param route2 - Second route entry
26
+ */
27
+ export function compareRoute(
28
+ route1: Pick<RouteEntry, 'verb' | 'path'>,
29
+ route2: Pick<RouteEntry, 'verb' | 'path'>,
30
+ ): number {
31
+ // First check the path tokens
32
+ const path1 = route1.path.replace(/{([^}]*)}(\/|$)/g, ':$1$2');
33
+ const path2 = route2.path.replace(/{([^}]*)}(\/|$)/g, ':$1$2');
34
+ const tokensForPath1: Token[] = toTokens(path1);
35
+ const tokensForPath2: Token[] = toTokens(path2);
36
+
37
+ const length =
38
+ tokensForPath1.length > tokensForPath2.length
39
+ ? tokensForPath1.length
40
+ : tokensForPath2.length;
41
+
42
+ for (let i = 0; i < length; i++) {
43
+ const token1 = tokensForPath1[i];
44
+ const token2 = tokensForPath2[i];
45
+ if (token1 === token2) continue;
46
+ if (token1 === undefined) return 1;
47
+ if (token2 === undefined) return -1;
48
+ if (token1 < token2) return -1;
49
+ if (token1 > token2) return 1;
50
+ }
51
+ // Then check verb
52
+ const verb1 = HTTP_VERBS[route1.verb.toLowerCase()] || HTTP_VERBS.get;
53
+ const verb2 = HTTP_VERBS[route2.verb.toLowerCase()] || HTTP_VERBS.get;
54
+ if (verb1 !== verb2) return verb1 - verb2;
55
+ return 0;
56
+ }
57
+
58
+ /**
59
+ *
60
+ * @param path - Parse a path template into tokens
61
+ */
62
+ function toTokens(path: string) {
63
+ const tokens: Token[] = [];
64
+ parse(path).forEach(p => {
65
+ if (typeof p === 'string') {
66
+ // The string can be /orders/count
67
+ tokens.push(...p.split('/').filter(Boolean));
68
+ } else {
69
+ // Use `{}` for wildcard as they are larger than any other ascii chars
70
+ tokens.push(`{}`);
71
+ }
72
+ });
73
+ return tokens;
74
+ }
@@ -0,0 +1,124 @@
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 {Request} from '../types';
7
+ import {getPathVariables} from './openapi-path';
8
+ import {createResolvedRoute, ResolvedRoute, RouteEntry} from './route-entry';
9
+ import {compareRoute} from './route-sort';
10
+ import {RestRouter, RestRouterOptions} from './rest-router';
11
+
12
+ /**
13
+ * Base router implementation that only handles path without variables
14
+ */
15
+ export abstract class BaseRouter implements RestRouter {
16
+ /**
17
+ * A map to optimize matching for routes without variables in the path
18
+ */
19
+ protected routesWithoutPathVars: {[key: string]: RouteEntry} = {};
20
+
21
+ constructor(protected options: RestRouterOptions = {strict: false}) {}
22
+
23
+ protected getKeyForRoute(route: RouteEntry) {
24
+ return this.getKey(route.verb, route.path);
25
+ }
26
+
27
+ add(route: RouteEntry) {
28
+ if (!getPathVariables(route.path)) {
29
+ const key = this.getKeyForRoute(route);
30
+ this.routesWithoutPathVars[key] = route;
31
+ } else {
32
+ this.addRouteWithPathVars(route);
33
+ }
34
+ }
35
+
36
+ protected getKeyForRequest(request: Request) {
37
+ return this.getKey(request.method, request.path);
38
+ }
39
+
40
+ find(request: Request) {
41
+ if (this.options.strict) {
42
+ return this.findRoute(request.method, request.path);
43
+ }
44
+ // Non-strict mode
45
+ let path = request.path;
46
+ // First try the exact match
47
+ const route = this.findRoute(request.method, path);
48
+ if (route || path === '/') return route;
49
+ if (path.endsWith('/')) {
50
+ // Fall back to the path without trailing slash
51
+ path = path.substring(0, path.length - 1);
52
+ } else {
53
+ // Fall back to the path with trailing slash
54
+ path = path + '/';
55
+ }
56
+ return this.findRoute(request.method, path);
57
+ }
58
+
59
+ private findRoute(verb: string, path: string) {
60
+ const key = this.getKey(verb, path);
61
+ const route = this.routesWithoutPathVars[key];
62
+ if (route) return createResolvedRoute(route, {});
63
+ else return this.findRouteWithPathVars(verb, path);
64
+ }
65
+
66
+ list() {
67
+ let routes = Object.values(this.routesWithoutPathVars);
68
+ routes = routes.concat(this.listRoutesWithPathVars());
69
+ // Sort the routes so that they show up in OpenAPI spec in order
70
+ return routes.sort(compareRoute);
71
+ }
72
+
73
+ /**
74
+ * Build a key for verb+path as `/<verb>/<path>`
75
+ * @param verb - HTTP verb/method
76
+ * @param path - URL path
77
+ */
78
+ protected getKey(verb: string, path: string) {
79
+ verb = normalizeVerb(verb);
80
+ path = normalizePath(path);
81
+ return `/${verb}${path}`;
82
+ }
83
+
84
+ // The following abstract methods need to be implemented by its subclasses
85
+ /**
86
+ * Add a route with path variables
87
+ * @param route - Route
88
+ */
89
+ protected abstract addRouteWithPathVars(route: RouteEntry): void;
90
+
91
+ /**
92
+ * Find a route with path variables for a given request
93
+ * @param request - Http request
94
+ */
95
+ protected abstract findRouteWithPathVars(
96
+ verb: string,
97
+ path: string,
98
+ ): ResolvedRoute | undefined;
99
+
100
+ /**
101
+ * List routes with path variables
102
+ */
103
+ protected abstract listRoutesWithPathVars(): RouteEntry[];
104
+ }
105
+
106
+ /**
107
+ * Normalize http verb to lowercase
108
+ * @param verb - Http verb
109
+ */
110
+ function normalizeVerb(verb: string) {
111
+ // Use lower case, default to `get`
112
+ return verb?.toLowerCase() || 'get';
113
+ }
114
+
115
+ /**
116
+ * Normalize path to make sure it starts with `/`
117
+ * @param path - Path
118
+ */
119
+ function normalizePath(path: string) {
120
+ // Prepend `/` if needed
121
+ path = path || '/';
122
+ path = path.startsWith('/') ? path : `/${path}`;
123
+ return path;
124
+ }
@@ -0,0 +1,36 @@
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 {OpenApiSpec} from '@loopback/openapi-v3';
7
+
8
+ export type RouterSpec = Pick<OpenApiSpec, 'paths' | 'components' | 'tags'>;
9
+
10
+ export function assignRouterSpec(target: RouterSpec, additions: RouterSpec) {
11
+ if (additions.components) {
12
+ if (!target.components) target.components = {};
13
+ for (const key in additions.components) {
14
+ if (!target.components[key]) target.components[key] = {};
15
+ Object.assign(target.components[key], additions.components[key]);
16
+ }
17
+ }
18
+
19
+ for (const url in additions.paths) {
20
+ if (!(url in target.paths)) target.paths[url] = {};
21
+ for (const verbOrKey in additions.paths[url]) {
22
+ // routes registered earlier takes precedence
23
+ if (verbOrKey in target.paths[url]) continue;
24
+ target.paths[url][verbOrKey] = additions.paths[url][verbOrKey];
25
+ }
26
+ }
27
+
28
+ if (additions.tags && additions.tags.length > 0) {
29
+ if (!target.tags) target.tags = [];
30
+ for (const tag of additions.tags) {
31
+ // tags defined earlier take precedence
32
+ if (target.tags.some(t => t.name === tag.name)) continue;
33
+ target.tags.push(tag);
34
+ }
35
+ }
36
+ }