jimpex 7.0.1 → 8.0.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 (388) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/LICENSE +1 -1
  3. package/README.md +446 -434
  4. package/dist/app/index.d.ts +13 -0
  5. package/dist/app/index.js +19 -0
  6. package/dist/app/index.js.map +1 -0
  7. package/dist/app/jimpex.d.ts +13 -0
  8. package/dist/app/jimpex.js +440 -0
  9. package/dist/app/jimpex.js.map +1 -0
  10. package/dist/controllers/common/config.d.ts +78 -0
  11. package/dist/controllers/common/config.js +89 -0
  12. package/dist/controllers/common/config.js.map +1 -0
  13. package/dist/controllers/common/health.d.ts +82 -0
  14. package/dist/controllers/common/health.js +97 -0
  15. package/dist/controllers/common/health.js.map +1 -0
  16. package/dist/controllers/common/index.d.ts +21 -0
  17. package/dist/controllers/common/index.js +21 -0
  18. package/dist/controllers/common/index.js.map +1 -0
  19. package/dist/controllers/common/statics.d.ts +215 -0
  20. package/dist/controllers/common/statics.js +202 -0
  21. package/dist/controllers/common/statics.js.map +1 -0
  22. package/dist/controllers/index.d.ts +24 -0
  23. package/dist/controllers/index.js +20 -0
  24. package/dist/controllers/index.js.map +1 -0
  25. package/dist/controllers/utils/gateway.d.ts +724 -0
  26. package/dist/controllers/utils/gateway.js +425 -0
  27. package/dist/controllers/utils/gateway.js.map +1 -0
  28. package/dist/controllers/utils/index.d.ts +16 -0
  29. package/dist/controllers/utils/index.js +19 -0
  30. package/dist/controllers/utils/index.js.map +1 -0
  31. package/dist/esm/app/index.js +2 -0
  32. package/dist/esm/app/index.js.map +1 -0
  33. package/dist/esm/app/jimpex.js +415 -0
  34. package/dist/esm/app/jimpex.js.map +1 -0
  35. package/dist/esm/chunk-T2T6Q22Z.js +11 -0
  36. package/dist/esm/chunk-T2T6Q22Z.js.map +1 -0
  37. package/dist/esm/controllers/common/config.js +62 -0
  38. package/dist/esm/controllers/common/config.js.map +1 -0
  39. package/dist/esm/controllers/common/health.js +70 -0
  40. package/dist/esm/controllers/common/health.js.map +1 -0
  41. package/dist/esm/controllers/common/index.js +4 -0
  42. package/dist/esm/controllers/common/index.js.map +1 -0
  43. package/dist/esm/controllers/common/statics.js +173 -0
  44. package/dist/esm/controllers/common/statics.js.map +1 -0
  45. package/dist/esm/controllers/index.js +3 -0
  46. package/dist/esm/controllers/index.js.map +1 -0
  47. package/dist/esm/controllers/utils/gateway.js +404 -0
  48. package/dist/esm/controllers/utils/gateway.js.map +1 -0
  49. package/dist/esm/controllers/utils/index.js +2 -0
  50. package/dist/esm/controllers/utils/index.js.map +1 -0
  51. package/dist/esm/index.js +7 -0
  52. package/dist/esm/index.js.map +1 -0
  53. package/dist/esm/middlewares/common/errorHandler.js +92 -0
  54. package/dist/esm/middlewares/common/errorHandler.js.map +1 -0
  55. package/dist/esm/middlewares/common/forceHTTPS.js +41 -0
  56. package/dist/esm/middlewares/common/forceHTTPS.js.map +1 -0
  57. package/dist/esm/middlewares/common/hsts.js +53 -0
  58. package/dist/esm/middlewares/common/hsts.js.map +1 -0
  59. package/dist/esm/middlewares/common/index.js +4 -0
  60. package/dist/esm/middlewares/common/index.js.map +1 -0
  61. package/dist/esm/middlewares/html/fastHTML.js +104 -0
  62. package/dist/esm/middlewares/html/fastHTML.js.map +1 -0
  63. package/dist/esm/middlewares/html/index.js +3 -0
  64. package/dist/esm/middlewares/html/index.js.map +1 -0
  65. package/dist/esm/middlewares/html/showHTML.js +68 -0
  66. package/dist/esm/middlewares/html/showHTML.js.map +1 -0
  67. package/dist/esm/middlewares/index.js +4 -0
  68. package/dist/esm/middlewares/index.js.map +1 -0
  69. package/dist/esm/middlewares/utils/index.js +2 -0
  70. package/dist/esm/middlewares/utils/index.js.map +1 -0
  71. package/dist/esm/middlewares/utils/versionValidator.js +101 -0
  72. package/dist/esm/middlewares/utils/versionValidator.js.map +1 -0
  73. package/dist/esm/services/common/appError.js +52 -0
  74. package/dist/esm/services/common/appError.js.map +1 -0
  75. package/dist/esm/services/common/httpError.js +19 -0
  76. package/dist/esm/services/common/httpError.js.map +1 -0
  77. package/dist/esm/services/common/index.js +17 -0
  78. package/dist/esm/services/common/index.js.map +1 -0
  79. package/dist/esm/services/common/sendFile.js +27 -0
  80. package/dist/esm/services/common/sendFile.js.map +1 -0
  81. package/dist/esm/services/frontend/frontendFs.js +38 -0
  82. package/dist/esm/services/frontend/frontendFs.js.map +1 -0
  83. package/dist/esm/services/frontend/index.js +11 -0
  84. package/dist/esm/services/frontend/index.js.map +1 -0
  85. package/dist/esm/services/html/htmlGenerator.js +144 -0
  86. package/dist/esm/services/html/htmlGenerator.js.map +1 -0
  87. package/dist/esm/services/html/index.js +11 -0
  88. package/dist/esm/services/html/index.js.map +1 -0
  89. package/dist/esm/services/http/apiClient.js +71 -0
  90. package/dist/esm/services/http/apiClient.js.map +1 -0
  91. package/dist/esm/services/http/http.js +125 -0
  92. package/dist/esm/services/http/http.js.map +1 -0
  93. package/dist/esm/services/http/index.js +17 -0
  94. package/dist/esm/services/http/index.js.map +1 -0
  95. package/dist/esm/services/http/responsesBuilder.js +105 -0
  96. package/dist/esm/services/http/responsesBuilder.js.map +1 -0
  97. package/dist/esm/services/index.js +6 -0
  98. package/dist/esm/services/index.js.map +1 -0
  99. package/dist/esm/services/utils/ensureBearerToken.js +78 -0
  100. package/dist/esm/services/utils/ensureBearerToken.js.map +1 -0
  101. package/dist/esm/services/utils/index.js +11 -0
  102. package/dist/esm/services/utils/index.js.map +1 -0
  103. package/dist/esm/types/events.js +1 -0
  104. package/dist/esm/types/events.js.map +1 -0
  105. package/dist/esm/types/express.js +1 -0
  106. package/dist/esm/types/express.js.map +1 -0
  107. package/dist/esm/types/http.js +1 -0
  108. package/dist/esm/types/http.js.map +1 -0
  109. package/dist/esm/types/index.js +7 -0
  110. package/dist/esm/types/index.js.map +1 -0
  111. package/dist/esm/types/options.js +1 -0
  112. package/dist/esm/types/options.js.map +1 -0
  113. package/dist/esm/types/utils.js +1 -0
  114. package/dist/esm/types/utils.js.map +1 -0
  115. package/dist/esm/types/wootils.js +1 -0
  116. package/dist/esm/types/wootils.js.map +1 -0
  117. package/dist/esm/utils/fns/index.js +5 -0
  118. package/dist/esm/utils/fns/index.js.map +1 -0
  119. package/dist/esm/utils/fns/others.js +6 -0
  120. package/dist/esm/utils/fns/others.js.map +1 -0
  121. package/dist/esm/utils/fns/routes.js +25 -0
  122. package/dist/esm/utils/fns/routes.js.map +1 -0
  123. package/dist/esm/utils/fns/statuses.js +6 -0
  124. package/dist/esm/utils/fns/statuses.js.map +1 -0
  125. package/dist/esm/utils/fns/text.js +6 -0
  126. package/dist/esm/utils/fns/text.js.map +1 -0
  127. package/dist/esm/utils/index.js +3 -0
  128. package/dist/esm/utils/index.js.map +1 -0
  129. package/dist/esm/utils/wrappers.js +41 -0
  130. package/dist/esm/utils/wrappers.js.map +1 -0
  131. package/dist/index.d.ts +46 -0
  132. package/dist/index.js +24 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/jimpex-7eaee271.d.ts +1278 -0
  135. package/dist/middlewares/common/errorHandler.d.ts +131 -0
  136. package/dist/middlewares/common/errorHandler.js +119 -0
  137. package/dist/middlewares/common/errorHandler.js.map +1 -0
  138. package/dist/middlewares/common/forceHTTPS.d.ts +68 -0
  139. package/dist/middlewares/common/forceHTTPS.js +68 -0
  140. package/dist/middlewares/common/forceHTTPS.js.map +1 -0
  141. package/dist/middlewares/common/hsts.d.ts +109 -0
  142. package/dist/middlewares/common/hsts.js +80 -0
  143. package/dist/middlewares/common/hsts.js.map +1 -0
  144. package/dist/middlewares/common/index.d.ts +21 -0
  145. package/dist/middlewares/common/index.js +21 -0
  146. package/dist/middlewares/common/index.js.map +1 -0
  147. package/dist/middlewares/html/fastHTML.d.ts +180 -0
  148. package/dist/middlewares/html/fastHTML.js +131 -0
  149. package/dist/middlewares/html/fastHTML.js.map +1 -0
  150. package/dist/middlewares/html/index.d.ts +21 -0
  151. package/dist/middlewares/html/index.js +20 -0
  152. package/dist/middlewares/html/index.js.map +1 -0
  153. package/dist/middlewares/html/showHTML.d.ts +127 -0
  154. package/dist/middlewares/html/showHTML.js +95 -0
  155. package/dist/middlewares/html/showHTML.js.map +1 -0
  156. package/dist/middlewares/index.d.ts +30 -0
  157. package/dist/middlewares/index.js +21 -0
  158. package/dist/middlewares/index.js.map +1 -0
  159. package/dist/middlewares/utils/index.d.ts +19 -0
  160. package/dist/middlewares/utils/index.js +19 -0
  161. package/dist/middlewares/utils/index.js.map +1 -0
  162. package/dist/middlewares/utils/versionValidator.d.ts +214 -0
  163. package/dist/middlewares/utils/versionValidator.js +128 -0
  164. package/dist/middlewares/utils/versionValidator.js.map +1 -0
  165. package/dist/services/common/appError.d.ts +138 -0
  166. package/dist/services/common/appError.js +80 -0
  167. package/dist/services/common/appError.js.map +1 -0
  168. package/dist/services/common/httpError.d.ts +79 -0
  169. package/dist/services/common/httpError.js +44 -0
  170. package/dist/services/common/httpError.js.map +1 -0
  171. package/dist/services/common/index.d.ts +47 -0
  172. package/dist/services/common/index.js +41 -0
  173. package/dist/services/common/index.js.map +1 -0
  174. package/dist/services/common/sendFile.d.ts +102 -0
  175. package/dist/services/common/sendFile.js +51 -0
  176. package/dist/services/common/sendFile.js.map +1 -0
  177. package/dist/services/frontend/frontendFs.d.ts +96 -0
  178. package/dist/services/frontend/frontendFs.js +71 -0
  179. package/dist/services/frontend/frontendFs.js.map +1 -0
  180. package/dist/services/frontend/index.d.ts +40 -0
  181. package/dist/services/frontend/index.js +35 -0
  182. package/dist/services/frontend/index.js.map +1 -0
  183. package/dist/services/html/htmlGenerator.d.ts +237 -0
  184. package/dist/services/html/htmlGenerator.js +171 -0
  185. package/dist/services/html/htmlGenerator.js.map +1 -0
  186. package/dist/services/html/index.d.ts +43 -0
  187. package/dist/services/html/index.js +35 -0
  188. package/dist/services/html/index.js.map +1 -0
  189. package/dist/services/http/apiClient.d.ts +169 -0
  190. package/dist/services/http/apiClient.js +96 -0
  191. package/dist/services/http/apiClient.js.map +1 -0
  192. package/dist/services/http/http.d.ts +175 -0
  193. package/dist/services/http/http.js +158 -0
  194. package/dist/services/http/http.js.map +1 -0
  195. package/dist/services/http/index.d.ts +50 -0
  196. package/dist/services/http/index.js +41 -0
  197. package/dist/services/http/index.js.map +1 -0
  198. package/dist/services/http/responsesBuilder.d.ts +178 -0
  199. package/dist/services/http/responsesBuilder.js +132 -0
  200. package/dist/services/http/responsesBuilder.js.map +1 -0
  201. package/dist/services/index.d.ts +33 -0
  202. package/dist/services/index.js +23 -0
  203. package/dist/services/index.js.map +1 -0
  204. package/dist/services/utils/ensureBearerToken.d.ts +157 -0
  205. package/dist/services/utils/ensureBearerToken.js +105 -0
  206. package/dist/services/utils/ensureBearerToken.js.map +1 -0
  207. package/dist/services/utils/index.d.ts +43 -0
  208. package/dist/services/utils/index.js +35 -0
  209. package/dist/services/utils/index.js.map +1 -0
  210. package/dist/types/events.d.ts +13 -0
  211. package/dist/types/events.js +17 -0
  212. package/dist/types/events.js.map +1 -0
  213. package/dist/types/express.d.ts +10 -0
  214. package/dist/types/express.js +17 -0
  215. package/dist/types/express.js.map +1 -0
  216. package/dist/types/http.d.ts +79 -0
  217. package/dist/types/http.js +17 -0
  218. package/dist/types/http.js.map +1 -0
  219. package/dist/types/index.d.ts +14 -0
  220. package/dist/types/index.js +24 -0
  221. package/dist/types/index.js.map +1 -0
  222. package/dist/types/options.d.ts +13 -0
  223. package/dist/types/options.js +17 -0
  224. package/dist/types/options.js.map +1 -0
  225. package/dist/types/utils.d.ts +48 -0
  226. package/dist/types/utils.js +17 -0
  227. package/dist/types/utils.js.map +1 -0
  228. package/dist/types/wootils.d.ts +4 -0
  229. package/dist/types/wootils.js +17 -0
  230. package/dist/types/wootils.js.map +1 -0
  231. package/dist/utils/fns/index.d.ts +5 -0
  232. package/dist/utils/fns/index.js +22 -0
  233. package/dist/utils/fns/index.js.map +1 -0
  234. package/dist/utils/fns/others.d.ts +17 -0
  235. package/dist/utils/fns/others.js +29 -0
  236. package/dist/utils/fns/others.js.map +1 -0
  237. package/dist/utils/fns/routes.d.ts +39 -0
  238. package/dist/utils/fns/routes.js +51 -0
  239. package/dist/utils/fns/routes.js.map +1 -0
  240. package/dist/utils/fns/statuses.d.ts +45 -0
  241. package/dist/utils/fns/statuses.js +35 -0
  242. package/dist/utils/fns/statuses.js.map +1 -0
  243. package/dist/utils/fns/text.d.ts +9 -0
  244. package/dist/utils/fns/text.js +29 -0
  245. package/dist/utils/fns/text.js.map +1 -0
  246. package/dist/utils/index.d.ts +18 -0
  247. package/dist/utils/index.js +20 -0
  248. package/dist/utils/index.js.map +1 -0
  249. package/dist/utils/wrappers.d.ts +13 -0
  250. package/dist/utils/wrappers.js +68 -0
  251. package/dist/utils/wrappers.js.map +1 -0
  252. package/examples/basic/404.html +12 -0
  253. package/examples/basic/README.md +30 -0
  254. package/examples/basic/app.ts +18 -0
  255. package/examples/basic/controller.ts +45 -0
  256. package/examples/basic/index.ts +19 -0
  257. package/examples/basic/middleware.ts +13 -0
  258. package/examples/basic/service.ts +11 -0
  259. package/package.json +59 -38
  260. package/src/app/index.ts +1 -0
  261. package/src/app/jimpex.ts +743 -0
  262. package/src/controllers/common/config.ts +115 -0
  263. package/src/controllers/common/health.ts +128 -0
  264. package/src/controllers/common/index.ts +3 -0
  265. package/src/controllers/common/statics.ts +380 -0
  266. package/src/controllers/index.ts +2 -0
  267. package/src/controllers/utils/gateway.ts +1186 -0
  268. package/src/controllers/utils/index.ts +1 -0
  269. package/src/index.ts +6 -0
  270. package/src/middlewares/common/errorHandler.ts +203 -0
  271. package/src/middlewares/common/forceHTTPS.ts +83 -0
  272. package/src/middlewares/common/hsts.ts +135 -0
  273. package/src/middlewares/common/index.ts +3 -0
  274. package/src/middlewares/html/fastHTML.ts +255 -0
  275. package/src/middlewares/html/index.ts +2 -0
  276. package/src/middlewares/html/showHTML.ts +165 -0
  277. package/src/middlewares/index.ts +3 -0
  278. package/src/middlewares/utils/index.ts +1 -0
  279. package/src/middlewares/utils/versionValidator.ts +289 -0
  280. package/src/services/common/appError.ts +158 -0
  281. package/src/services/common/httpError.ts +74 -0
  282. package/src/services/common/index.ts +29 -0
  283. package/src/services/common/sendFile.ts +106 -0
  284. package/src/services/frontend/frontendFs.ts +101 -0
  285. package/src/services/frontend/index.ts +21 -0
  286. package/src/services/html/htmlGenerator.ts +356 -0
  287. package/src/services/html/index.ts +21 -0
  288. package/src/services/http/apiClient.ts +221 -0
  289. package/src/services/http/http.ts +286 -0
  290. package/src/services/http/index.ts +29 -0
  291. package/src/services/http/responsesBuilder.ts +265 -0
  292. package/src/services/index.ts +5 -0
  293. package/src/services/utils/ensureBearerToken.ts +202 -0
  294. package/src/services/utils/index.ts +21 -0
  295. package/src/types/events.ts +303 -0
  296. package/src/types/express.ts +21 -0
  297. package/src/types/http.ts +77 -0
  298. package/src/types/index.ts +6 -0
  299. package/src/types/options.ts +248 -0
  300. package/src/types/utils.ts +52 -0
  301. package/src/types/wootils.ts +4 -0
  302. package/src/utils/fns/index.ts +4 -0
  303. package/src/utils/fns/others.ts +15 -0
  304. package/src/utils/fns/routes.ts +64 -0
  305. package/src/utils/fns/statuses.ts +44 -0
  306. package/src/utils/fns/text.ts +8 -0
  307. package/src/utils/index.ts +2 -0
  308. package/src/utils/wrappers.ts +537 -0
  309. package/tsconfig.json +5 -8
  310. package/tsup.config.ts +10 -0
  311. package/src/app/index.js +0 -692
  312. package/src/constants/eventNames.js +0 -48
  313. package/src/constants/index.js +0 -7
  314. package/src/controllers/common/configuration.js +0 -116
  315. package/src/controllers/common/health.js +0 -79
  316. package/src/controllers/common/index.js +0 -7
  317. package/src/controllers/common/statics.js +0 -336
  318. package/src/controllers/index.js +0 -9
  319. package/src/controllers/utils/gateway.js +0 -1039
  320. package/src/controllers/utils/index.js +0 -3
  321. package/src/index.js +0 -30
  322. package/src/middlewares/common/errorHandler.js +0 -185
  323. package/src/middlewares/common/forceHTTPS.js +0 -80
  324. package/src/middlewares/common/hsts.js +0 -122
  325. package/src/middlewares/common/index.js +0 -7
  326. package/src/middlewares/html/fastHTML.js +0 -298
  327. package/src/middlewares/html/index.js +0 -5
  328. package/src/middlewares/html/showHTML.js +0 -167
  329. package/src/middlewares/index.js +0 -11
  330. package/src/middlewares/utils/index.js +0 -3
  331. package/src/middlewares/utils/versionValidator.js +0 -261
  332. package/src/services/common/appError.js +0 -136
  333. package/src/services/common/httpError.js +0 -60
  334. package/src/services/common/index.js +0 -25
  335. package/src/services/common/sendFile.js +0 -68
  336. package/src/services/frontend/frontendFs.js +0 -85
  337. package/src/services/frontend/index.js +0 -17
  338. package/src/services/html/htmlGenerator.js +0 -391
  339. package/src/services/html/index.js +0 -17
  340. package/src/services/http/apiClient.js +0 -148
  341. package/src/services/http/http.js +0 -256
  342. package/src/services/http/index.js +0 -25
  343. package/src/services/http/responsesBuilder.js +0 -193
  344. package/src/services/index.js +0 -15
  345. package/src/services/utils/ensureBearerToken.js +0 -147
  346. package/src/services/utils/index.js +0 -19
  347. package/src/types.js +0 -377
  348. package/src/utils/functions.js +0 -78
  349. package/src/utils/wrappers.js +0 -131
  350. package/types/app/index.d.ts +0 -417
  351. package/types/constants/eventNames.d.ts +0 -93
  352. package/types/constants/index.d.ts +0 -2
  353. package/types/controllers/common/configuration.d.ts +0 -71
  354. package/types/controllers/common/health.d.ts +0 -55
  355. package/types/controllers/common/index.d.ts +0 -4
  356. package/types/controllers/common/statics.d.ts +0 -271
  357. package/types/controllers/index.d.ts +0 -3
  358. package/types/controllers/utils/gateway.d.ts +0 -947
  359. package/types/controllers/utils/index.d.ts +0 -2
  360. package/types/index.d.ts +0 -15
  361. package/types/middlewares/common/errorHandler.d.ts +0 -143
  362. package/types/middlewares/common/forceHTTPS.d.ts +0 -64
  363. package/types/middlewares/common/hsts.d.ts +0 -111
  364. package/types/middlewares/common/index.d.ts +0 -4
  365. package/types/middlewares/html/fastHTML.d.ts +0 -238
  366. package/types/middlewares/html/index.d.ts +0 -3
  367. package/types/middlewares/html/showHTML.d.ts +0 -128
  368. package/types/middlewares/index.d.ts +0 -4
  369. package/types/middlewares/utils/index.d.ts +0 -2
  370. package/types/middlewares/utils/versionValidator.d.ts +0 -247
  371. package/types/services/common/appError.d.ts +0 -89
  372. package/types/services/common/httpError.d.ts +0 -37
  373. package/types/services/common/index.d.ts +0 -18
  374. package/types/services/common/sendFile.d.ts +0 -56
  375. package/types/services/frontend/frontendFs.d.ts +0 -72
  376. package/types/services/frontend/index.d.ts +0 -3
  377. package/types/services/html/htmlGenerator.d.ts +0 -298
  378. package/types/services/html/index.d.ts +0 -3
  379. package/types/services/http/apiClient.d.ts +0 -141
  380. package/types/services/http/http.d.ts +0 -159
  381. package/types/services/http/index.d.ts +0 -18
  382. package/types/services/http/responsesBuilder.d.ts +0 -140
  383. package/types/services/index.d.ts +0 -6
  384. package/types/services/utils/ensureBearerToken.d.ts +0 -137
  385. package/types/services/utils/index.d.ts +0 -16
  386. package/types/types.d.ts +0 -280
  387. package/types/utils/functions.d.ts +0 -55
  388. package/types/utils/wrappers.d.ts +0 -127
package/README.md CHANGED
@@ -2,148 +2,229 @@
2
2
 
3
3
  [![GitHub Workflow Status (main)](https://img.shields.io/github/workflow/status/homer0/jimpex/Test/main?style=flat-square)](https://github.com/homer0/jimpex/actions?query=workflow%3ATest)
4
4
  [![Coveralls GitHub](https://img.shields.io/coveralls/github/homer0/jimpex.svg?style=flat-square)](https://coveralls.io/github/homer0/jimpex?branch=main)
5
- [![David](https://img.shields.io/david/homer0/jimpex.svg?style=flat-square)](https://david-dm.org/homer0/jimpex)
6
- [![David](https://img.shields.io/david/dev/homer0/jimpex.svg?style=flat-square)](https://david-dm.org/homer0/jimpex)
5
+ ![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/npm/jimpex)
7
6
 
8
7
  Express as dependency injection container.
9
8
 
10
- Jimpex is an implementation of [Express](https://expressjs.com), one of the most popular web frameworks for Node, using [Jimple](https://github.com/fjorgemota/jimple), a Javascript port of [Pimple](https://pimple.symfony.com) dependency injection container.
9
+ Jimpex is an implementation of [Express](https://expressjs.com), one of the most popular web frameworks for Node, using [Jimple](https://github.com/fjorgemota/jimple), a Javascript port of [Pimple](https://github.com/silexphp/Pimple) dependency injection container.
10
+
11
+ > ⚠️ If you want to upgrade to v8, please read the [migration guide](https://github.com/homer0/jimpex/blob/main/documents/migration-v8.md).
12
+
13
+ - [🍿 Usage](#🍿-usage)
14
+ - [🎨 Creating your app](#🎨-creating-your-app)
15
+ - [🤖 Boot](#🤖-boot)
16
+ - [⚙️ Options and configuration](#⚙️-options-and-configuration)
17
+ - [Options](#options)
18
+ - [Configuration](#configuration)
19
+ - [🚀 Starting your app](#🚀-starting-the-app)
20
+ - [✅ HTTPS](#✅-https)
21
+ - [HTTP2](#http2)
22
+ - [🛠 Services](#🛠-services)
23
+ - [Configurable services](#configurable-services)
24
+ - [🚦 Controllers](#🚦-controller)
25
+ - [Configurable controllers](#configurable-controllers)
26
+ - [Controllers with services](#controllers-with-services)
27
+ - [⚡️ Middlewares](#⚡️-middlewares)
28
+ - [Configurable middlewares](#configurable-middlewares)
29
+ - [Middlewares with services](#middlewares-with-services)
30
+ - [💪 TypeScript](#💪-typescript)
31
+ - [🤞 Examples](#🤞-examples)
32
+ - [🤘 Development](#development)
33
+ - [NPM scripts](#npm-scripts)
34
+ - [Repository hooks](#repository-hooks)
35
+ - [Commits conventions](#commits-conventions)
36
+ - [Releases](#releases)
37
+ - [Testing](#testing)
38
+ - [Code linting and formatting](#code-linting-and-formatting)
39
+ - [Documentation](#documentation)
40
+ - [👀 Motivation](#👀-motivation)
41
+
42
+ ## 🍿 Usage
43
+
44
+ ### 🎨 Creating your app
45
+
46
+ ```ts
47
+ import { jimpex } from 'jimpex';
11
48
 
12
- ## Usage
13
-
14
- ### Creating your app
49
+ const app = jimpex();
50
+ app.set('something', () => new Something());
51
+ app.mount('/hello', (req, res) => res.send('Hello World!'));
52
+ app.listen(2509, () => {
53
+ console.log('The app is running!');
54
+ });
55
+ ```
15
56
 
16
- You have two ways of creating an app: by defining a class and using the `boot` method to add all your services and customizations; or with the `jimpex` function:
57
+ That's all: you create the app, register/set your dependencies, and mount your routes.
17
58
 
18
- #### Class
59
+ Alternatively, you could import the class, subclass it, and make use of the "life cycle" methods to configure it:
19
60
 
20
- ```js
21
- const { Jimpex } = require('jimpex');
22
- // OR import { Jimpex } from 'jimpex/esm';
61
+ ```ts
62
+ import { Jimpex } from 'jimpex';
23
63
 
24
64
  class MyApp extends Jimpex {
25
65
  boot() {
26
- // Do all your custom stuff...
27
- this.register(...);
28
- this.mount(...);
66
+ this.set('something', () => new Something());
67
+ app.mount('/hello', (req, res) => res.send('Hello World!'));
29
68
  }
30
69
  }
31
- ```
32
-
33
- The class constructor has two parameters:
34
70
 
35
- ```js
36
- (options = {}, configuration = null) => Jimpex
71
+ const app = new MyApp();
72
+ app.listen(2509, () => {
73
+ console.log('The app is running!');
74
+ });
37
75
  ```
38
76
 
39
- 1. The options to customize the application. You can read about them on the [Jimpex Options documentation](./documents/options.md).
40
- 2. The default configuration, in case you don't want Jimpex to try loading an external configuration file.
77
+ ### 🤖 Boot
41
78
 
42
- When definining the application as a class, there are two _protected_ (helper) methods that you can use to overwrite the options and even define priority resources that the implementation could access/overwrite if they manually handle the "boot":
79
+ The `boot` method gets called right from the constructor, when the `boot` option is set to `true` (its default value), and the idea is for you to use it to add all your customizations (as seen in the example above).
43
80
 
44
- ##### Adding resources that can be overriden
81
+ Like `boot`, there's another "helper method" that you can use to register your dependencies: `_init`; the difference is that `_init` gets called from the constructor before the `boot` options gets validated. This allows you to create scenarios in which you could register some resources on `_init`, disable the call to `boot`, overwrite what you set on `_init`, and manually call `boot`:
45
82
 
46
- ```js
83
+ ```ts
47
84
  class MyApp extends Jimpex {
48
85
  _init() {
49
- this.set('env', 'PROD');
86
+ this.set('message', 'Hello Charo!');
87
+ }
88
+
89
+ boot() {
90
+ app.mount('/hello', (req, res) => res.send(this.get('message')));
50
91
  }
51
92
  }
93
+
94
+ const app = new MyApp({ boot: false });
95
+ app.set('message', 'Hello Pili!');
96
+ app.boot();
52
97
  ```
53
98
 
54
- The `_init` method is called before `boot` gets validated, so even if the constructor option `boot` is set to `false`, `_init` will be called.
99
+ Now, this may look like an unnecessary feature, but if you consider the possiblity of different entry points based on environment, maybe to enable debugging tools on dev, this becomes really useful.
55
100
 
56
- Now, let's say you want to execute the application on a development environment; instead of adding `if`s to check the environment, you could do something like this on your development file:
101
+ ### ⚙️ Options and configuration
57
102
 
58
- ```js
59
- const MyApp = require('...');
103
+ On Jimpex, you have two sets of "settings": the options, which are in the code when you create the application; and the configuration, which may be related to the environment in which the application is running.
60
104
 
61
- const app = new MyApp({ boot: false });
62
- app.set('env', 'DEV');
63
- app.boot();
64
- ...
105
+ #### Options
106
+
107
+ You can read all about the different options in [its own documentation](https://github.com/homer0/jimpex/blob/main/documents/options.md), but they're more related to the application capabilities. For example:
108
+
109
+ - Whether or not to call `boot`.
110
+ - Whether or not Express should remove the `x-powered-by` header.
111
+ - Which env var to check for the environment configuration (you'll see more about this in a sec).
112
+
113
+ And depending on how you defined your application, you have two ways to customize the options.
114
+
115
+ First, if you used the function, you can just send them as a parameter:
116
+
117
+ ```ts
118
+ import { jimpex } from 'jimpex';
119
+
120
+ const app = jimpex({
121
+ boot: false,
122
+ express: {
123
+ disableXPoweredBy: true,
124
+ },
125
+ config: {
126
+ environmentVariable: 'NODE_ENV',
127
+ },
128
+ });
65
129
  ```
66
130
 
67
- ##### Modifying the options
131
+ And yes, you could also use this approach with the class, as both the function and the class constructor share the same parameters, but if you want to already define your options inside your subclass, there's a _protected_ helper for it: `_initOptions`.
132
+
133
+ ```ts
134
+ import { Jimpex } from 'jimpex';
68
135
 
69
- ```js
70
136
  class MyApp extends Jimpex {
71
137
  _initOptions() {
72
138
  return {
73
- configuration: {
74
- loadFromEnvironment: false,
139
+ boot: false,
140
+ express: {
141
+ disableXPoweredBy: true,
142
+ },
143
+ config: {
144
+ environmentVariable: 'NODE_ENV',
75
145
  },
76
146
  };
77
147
  }
78
148
  }
79
149
  ```
80
150
 
81
- If you are subclassing `Jimpex`, it highly probable that if the default options need to be changed, you would want to do it from within the class, rather than forcing all implementations to do it.
151
+ The advantage of `_initOptions` is not only that you don't need to overwrite the constructor, but that you can still receive the options from the constructor, and Jimpex will automatically deep merge the ones on `_initOptions` on top of them.
82
152
 
83
- One way would be to overwrite the constructor and call `super` with the customizations, the other would be using this method: The constructor automatically merges the result of `_initOptions` on top of the defaults so you won't have to override anything.
153
+ #### Configuration
84
154
 
85
- There are a lot of different options, so I would recommend reading the [Jimpex Options documentation](./documents/options.md).
155
+ These are the settings that are more related to the runtime, and that can change depending on the environment. The most basic example of a "configuration setting" would be the port in which the application runs: you could run it on local env in 3000, and on production in 80 (or 443).
86
156
 
87
- #### Function
157
+ While the configuration is more easily managed with external (config) files, you could also send it in the options:
88
158
 
89
- ```js
90
- const { jimpex } = require('jimpex');
91
- // OR import { jimpex } from 'jimpex/esm';
159
+ ```ts
160
+ import { jimpex } from 'jimpex';
92
161
 
93
- const app = jimpex();
94
- app.register(...);
95
- app.mount(...);
96
- ```
97
-
98
- The idea of the function is to be used on scenarios where a class may be too much or you have a single implementation, like on a lamda serverless.
162
+ const app = jimpex({
163
+ config: {
164
+ default: {
165
+ port: 3000,
166
+ },
167
+ },
168
+ });
99
169
 
100
- The function has almost the same signature as the class constructor:
170
+ // or
101
171
 
102
- ```js
103
- (options = {}, configuration = null) => Jimpex
172
+ const app2 = jimpex(
173
+ { someOption: false },
174
+ {
175
+ port: 3000,
176
+ },
177
+ );
104
178
  ```
105
179
 
106
- 1. The options to customize the application. You can read about them on the [Jimpex Options documentation](./documents/options.md).
107
- 2. The default configuration. The big difference here is that, even if you send `null`, Jimpex won't try to load an external configuration file.
180
+ You can use the option `config.default`, or just the second parameter of both the function and the class.
108
181
 
109
- #### App configuration
182
+ > ⚠️ If you don't configure the `port` and call `start()`, the application will throw an error.
110
183
 
111
- Jimpex, by default, depends on external configuration files and, as a base configuration, it will try to load `./config/app/app.config.js`. Of course this is extremely configurable through the [Jimpex Options](./documents/options.md).
184
+ That's the basic usage, but as mentioned before, the configuration is more easily managed with external files: when loading the configuration, which happens when the server starts, it will try to look for a file `config/app.config.js`, and if it exists, it will set whatever it (default) exports as the configuration.
112
185
 
113
- A configuration file is just a Javascript file that exports an Object, for example:
186
+ So, we could write the configuration from the example above and use it like this:
114
187
 
115
- ```js
116
- module.exports = {
117
- port: 2509,
188
+ ```ts
189
+ // config/app.config.js
190
+ export default {
191
+ port: 3000,
118
192
  };
119
- ```
120
193
 
121
- > If that's how you default configuration file looks like, the app will run on the port `2509`.
194
+ // src/index.js
195
+ import { jimpex } from 'jimpex';
122
196
 
123
- If you don't want the application to load an external file, you could use the second parameter of either the class or the function:
124
-
125
- ```js
126
- new MyApp({ ... }, { port: 2509 });
127
- // OR
128
- jimpex({ ... }, { port: 2509 });
197
+ const app = jimpex();
198
+ app.start();
129
199
  ```
130
200
 
131
- Now, to access the configuration service, you just call `appConfiguration`:
201
+ Now, the really great feature about the config files, is that you could extend them and manage which one gets loaded depending on the environment: When loading the configuration, Jimpex will check the value of the environment variable `CONFIG` and try to load a config file `config/app.config.${CONFIG}.js`. For example:
132
202
 
133
- ```js
134
- const config = app.get('appConfiguration');
203
+ You could have the default configuration with the port set to `3000`, and a "staging" configuration with the port set to `80`.
204
+
205
+ ```ts
206
+ // config/app.config.js
207
+ export default {
208
+ port: 3000,
209
+ };
210
+
211
+ // config/app.config.staging.js
212
+ export default {
213
+ port: 80,
214
+ };
135
215
  ```
136
216
 
137
- Then you can read its settings using `.get(setting)`:
217
+ And if `CONFIG` is set to `staging` when the application starts, the staging configuration will be loaded.
138
218
 
139
- ```js
140
- console.log(config.get('port'));
141
- // Will log 2509
219
+ Finally, you can access the configuration settings with the `config` service:
220
+
221
+ ```ts
222
+ const port = app.get('config').get('port');
142
223
  ```
143
224
 
144
- To get more information about how the `appConfiguration` service works, you can check [its documentation on the wootils repository](https://github.com/homer0/wootils/blob/main/documents/node/appConfiguration.md).
225
+ > You can read more about the options for the configuration service in the [options documentation](https://github.com/homer0/jimpex/blob/main/documents/options.md), but it's basically an implementation of [`@homer0/simple-config`](https://www.npmjs.com/package/@homer0/simple-config).
145
226
 
146
- #### Starting the application
227
+ ### 🚀 Starting the app
147
228
 
148
229
  ```js
149
230
  app.listen(2509, () => {
@@ -168,46 +249,39 @@ app.stop();
168
249
  // Done, the app is not longer running.
169
250
  ```
170
251
 
171
- ### HTTPS && HTTP2
252
+ ### HTTPS
172
253
 
173
- To enable HTTPS on your application, just like for the `port`, you need to create a `https` key on your configuration, "enable it" and provide the paths for the credentials:
254
+ HTTPS is enabled via configuration, not options, just like the application port:
174
255
 
175
- ```js
176
- module.exports = {
256
+ ```ts
257
+ // config/app.config.js
258
+ export default {
177
259
  port: 2509,
178
260
  https: {
179
261
  enabled: true,
180
262
  credentials: {
181
- cert: 'cert-file',
182
- key: 'key-file',
263
+ cert: '...cert-file',
264
+ key: '...key-file',
183
265
  },
184
266
  },
185
267
  };
186
268
  ```
187
269
 
188
- By default, Jimpex will look for those files relative to the project root directory, but you can change so it will look on a path relative to the directory where the application executable is located:
270
+ By default, Jimpex will look for those files relative to the project root directory, but you can change so it will look on a path relative to the directory where the application executable is located by setting `https.credentials.onHome` to `false`.
189
271
 
190
- ```js
191
- {
192
- // ...
193
- credentials: {
194
- onHome: false,
195
- cert: 'cert-file',
196
- key: 'key-file',
197
- },
198
- }
199
- ```
272
+ #### HTTP2
200
273
 
201
- Also, once you have HTTPS enabled, you can also enable [HTTP/2](https://en.wikipedia.org/wiki/HTTP/2):
274
+ To enable [HTTP/2](https://en.wikipedia.org/wiki/HTTP/2), you MUST enable HTTPS first, and then just add a flag in the configuration:
202
275
 
203
- ```js
204
- module.exports = {
276
+ ```ts
277
+ // config/app.config.js
278
+ export default {
205
279
  port: 2509,
206
280
  https: {
207
281
  enabled: true,
208
282
  credentials: {
209
- cert: 'cert-file',
210
- key: 'key-file',
283
+ cert: '...cert-file',
284
+ key: '...key-file',
211
285
  },
212
286
  },
213
287
  http2: {
@@ -216,543 +290,481 @@ module.exports = {
216
290
  };
217
291
  ```
218
292
 
219
- > **Important:** HTTPS MUST BE enabled in order to use HTTP/2.
220
-
221
- Under the hood, Jimpex uses [Spdy](https://yarnpkg.com/package/spdy) for the HTTP/2 support, and Spdy has custom options you can send in order to define how it will work; you can send options to Spdy by adding a `spdy` key inside the `http2` object:
293
+ Under the hood, Jimpex uses [Spdy](https://npmjs.com/package/spdy) for the HTTP/2 support, and Spdy has custom options you can send in order to define how it will work; you can send options to Spdy by adding a `spdy` key inside the `http2` object:
222
294
 
223
- ```js
224
- {
225
- // ...
295
+ ```ts
296
+ // config/app.config.js
297
+ export default {
298
+ port: 2509,
299
+ https: {
300
+ enabled: true,
301
+ credentials: {
302
+ cert: '...cert-file',
303
+ key: '...key-file',
304
+ },
305
+ },
226
306
  http2: {
227
307
  enabled: true,
228
308
  spdy: {
229
309
  'x-forwarded-for': '127.0.0.1',
230
310
  },
231
311
  },
232
- }
312
+ };
233
313
  ```
234
314
 
235
- ### Defining a service
315
+ ### 🛠 Services
236
316
 
237
- To define a service and its provider, you would write your service as a `class` or a `function` and then wrap it on the `provider` function Jimpex exports:
317
+ This is the most-core functionality that Jimple, and Jimpex, provide. You can easily create providers for services/resources that you want to use in your application:
238
318
 
239
- ```js
240
- const { provider } = require('jimpex');
319
+ ```ts
320
+ // src/my-service.js
321
+ import { provider } from 'jimpex';
241
322
 
242
- // Create your service
243
- class MyService {
244
- constructor(depOne, depTwo);
323
+ export class MyService {
324
+ constructor(config) {
325
+ this.config = config;
326
+ }
327
+
328
+ getMeThePort() {
329
+ return this.config.get('port');
330
+ }
245
331
  }
246
332
 
247
- // Define the provider
248
- const myService = provider((app) => {
249
- app.set('myService', () => new MyService(
250
- app.get('depOne'),
251
- app.get('depTwo')
252
- ));
333
+ export const myService = provider((app) => {
334
+ app.set('myService', () => new MyService(app.get('config')));
253
335
  });
254
-
255
- // Export the service and its provider
256
- module.exports.MyService = MyService;
257
- module.exports.myService = myService;
258
336
  ```
259
337
 
260
- > 1. You could just export the provider, but I believe is a good practice to export both in case another part of your app wants to extend the class and overwrite the service on the container.
261
- > 2. That why of using `module.expots` is so the class can be imported on JSDoc comments.
338
+ > You could just export the provider, but I believe is a good practice to export both, in case another part of your app wants to extend the class and overwrite the service on the container.
262
339
 
263
- Then, on you app, you would simple `register` the provider:
340
+ The, on the app, you would simple `register` the provider:
264
341
 
265
- ```js
266
- const { Jimpex } = require('jimpex');
267
- const { myService } = require('...');
342
+ ```ts
343
+ import { Jimpex } from 'jimpex';
344
+ import { myService } from './my-service';
268
345
 
269
346
  class MyApp extends Jimpex {
270
347
  boot() {
271
- ...
272
348
  this.register(myService);
273
349
  }
274
350
  }
275
351
  ```
276
352
 
277
- Done, your service is now available.
353
+ Done, your service is now available in the container.
278
354
 
279
- #### Defining a configurable service
355
+ Jimpex already comes with a few built-in service providers ready to be used, and you can read about them on the [services document](https://github.com/homer0/jimpex/blob/main/documents/services.md).
280
356
 
281
- In case you want to create a service that could accept custom setting when instantiated, you can use a _"provider creator"_:
357
+ ##### Configurable services
282
358
 
283
- ```js
284
- const { providerCreator } = require('jimpex');
359
+ Since the version of Jimple that Jimpex uses under the hood is [`@homer0/jimple`](https://www.npmjs.com/package/@homer0/jimple), my custom "fork", you can also create "configureable providers":
360
+
361
+ ```ts
362
+ // src/my-service.js
363
+ import { providerCreator } from 'jimpex';
364
+
365
+ export class MyService {
366
+ constructor(config) {
367
+ this.config = config;
368
+ }
285
369
 
286
- // Create your service
287
- class MyService {
288
- constructor(depOne, depTwo, options = {});
370
+ getMeThePort() {
371
+ return this.config.get('port');
372
+ }
289
373
  }
290
374
 
291
- // Define the provider
292
- const myService = providerCreator((options) => (app) => {
293
- app.set('myService', () => new MyService(
294
- app.get('depOne'),
295
- app.get('depTwo'),
296
- settings
297
- ));
375
+ export const myService = providerCreator((options = {}) => (app) => {
376
+ const { serviceName = 'myService' } = options;
377
+ app.set(serviceName, () => new MyService(app.get('config')));
298
378
  });
299
-
300
- // Export the service and its provider
301
- module.exports = {
302
- MyService,
303
- myService,
304
- };
305
379
  ```
306
380
 
307
- The special behavior the creators have, is that you can call them as a function, sending the settings, or just use them on the `register`, so **it's very important that the settings must be optional**:
381
+ If you are thinking this is just a HOF, you are wrong. The "magic" of the creator version is that it can be used as a provider and/or as a function:
308
382
 
309
- ```js
310
- const { Jimpex } = require('jimpex');
311
- const { myService } = require('...');
383
+ ```ts
384
+ import { Jimpex } from 'jimpex';
385
+ import { myService } from './my-service';
312
386
 
313
387
  class MyApp extends Jimpex {
314
388
  boot() {
315
- ...
316
389
  this.register(myService);
317
- // or
318
- this.register(myService({ ... }));
390
+ this.register(
391
+ myService({
392
+ serviceName: 'myService2',
393
+ }),
394
+ );
319
395
  }
320
396
  }
321
397
  ```
322
398
 
323
- ### Adding a controller
399
+ Check the README of [`@homer0/jimple`](https://www.npmjs.com/package/@homer0/jimple) for more information about providers.
324
400
 
325
- To add controller you need to use the `controller` function and return a list of routes:
401
+ ### 🚦 Controllers
326
402
 
327
- ```js
328
- const { controller } = require('jimpex');
403
+ To define a controller, you just need to use the `controller` wrapper (like `provider`), modify a router, and return it:
404
+
405
+ ```ts
406
+ // src/health-controller.js
407
+ import { controller } from 'jimpex';
329
408
 
330
409
  // (Optional) Define a class to organize your route handlers.
331
- class HealthController {
410
+ export class HealthController {
332
411
  health() {
333
412
  return (req, res) => {
334
413
  res.write('Everything works!');
414
+ res.end();
335
415
  };
336
416
  }
337
417
  }
338
418
 
339
419
  // Define the controller
340
- const healthController = controller((app) => {
420
+ export const healthController = controller((app) => {
341
421
  const ctrl = new HealthController();
342
- // Get the router service
422
+ // Get an instance of the router service
343
423
  const router = app.get('router');
344
424
  // Return the router with all the routes
345
- return router
346
- .get('/', ctrl.health())
347
- .get(...);
425
+ return router.get('/', ctrl.health()).get('/health', (req, res) => {
426
+ res.write('Everything works!');
427
+ res.end();
428
+ });
348
429
  });
349
-
350
- // Export the controller class and the controller itself
351
- module.exports.HealthController = HealthController;
352
- module.exports.healthController = healthController;
353
430
  ```
354
431
 
355
- > 1. You could just export the controller, but I believe is a good practice to export both in case another part of your app wants to extend the class and mount a new route withs its inherit functionalities.
356
- > 2. That why of using `module.expots` is so the class can be imported on JSDoc comments.
357
- > 3. The function inside the `controller` wrapper won't be called until the app is started. In case you are wondering about the lazy loading of the services that you may inject.
432
+ > 1. You could just export the controller, but I believe is a good practice to export both, in case another part of your app wants to extend the class and mount a new route with its inherited functionalities.
433
+ > 2. In case you are wondering about the lazy loading of the services that you may inject, the function inside the `controller` wrapper won't be called until the app is started.
358
434
 
359
435
  Then, on you app, you would `mount` the controller:
360
436
 
361
- ```js
362
- const { Jimpex } = require('jimpex');
363
- const { healthController } = require('...');
437
+ ```ts
438
+ import { Jimpex } from 'jimpex';
439
+ import { healthController } from './health-controller';
364
440
 
365
441
  class MyApp extends Jimpex {
366
442
  boot() {
367
- ...
368
443
  this.mount('/health', healthController);
369
444
  }
370
445
  }
371
446
  ```
372
447
 
373
- #### Defining a configurable controller
448
+ Jimpex already comes with a few built-in controllers ready to be used, and you can read about them on the [controllers document](https://github.com/homer0/jimpex/blob/main/documents/controllers.md).
374
449
 
375
- Like with _"providers creators", you can define controllers that accept custom settings when
376
- instantiated, using a _"controller creator"_:
450
+ #### Configurable controllers
377
451
 
378
- ```js
379
- const { controllerCreator } = require('jimpex');
452
+ The same as with the services, you can define controllers that accept custom options for the moment they are mounted:
380
453
 
381
- // (Optional) Define a class to organize your route handlers.
382
- class HealthController {
383
- constructor(settings = {});
454
+ ```ts
455
+ // src/health-controller.js
456
+ import { controllerCreator } from 'jimpex';
384
457
 
458
+ // (Optional) Define a class to organize your route handlers.
459
+ export class HealthController {
385
460
  health() {
386
461
  return (req, res) => {
387
462
  res.write('Everything works!');
463
+ res.end();
388
464
  };
389
465
  }
390
466
  }
391
467
 
392
468
  // Define the controller
393
- const healthController = controllerCreator((settings) => (app) => {
394
- const ctrl = new HealthController(settings);
395
- // Get the router service
469
+ export const healthController = controllerCreator((options = {}) => (app) => {
470
+ const ctrl = new HealthController();
471
+ // Get an instance of the router service
396
472
  const router = app.get('router');
473
+ // Read the custom options
474
+ const { altRoute = '/health' } = options;
475
+
397
476
  // Return the router with all the routes
398
- return router
399
- .get('/', ctrl.health())
400
- .get(...);
477
+ return router.get('/', ctrl.health()).get(altRoute, (req, res) => {
478
+ res.write('Everything works!');
479
+ res.end();
480
+ });
401
481
  });
402
-
403
- // Export the controller class and the controller itself
404
- module.exports.HealthController = HealthController;
405
- module.exports.healthController = healthController;
406
482
  ```
407
483
 
408
- The special behavior the creators have, is that you can call them as a function, sending the settings, or just use them with `mount` as regular controllers; and since they can be used as regular controllers, **it's very important that the settings are optional**:
484
+ And like with the provider creators, these can be used as a controller, or as a function:
409
485
 
410
- ```js
411
- const { Jimpex } = require('jimpex');
412
- const { healthController } = require('...');
486
+ ```ts
487
+ import { Jimpex } from 'jimpex';
488
+ import { healthController } from './health-controller';
413
489
 
414
490
  class MyApp extends Jimpex {
415
491
  boot() {
416
- ...
417
492
  this.mount('/health', healthController);
418
- // or
419
- this.mount('/health', healthController({ ... }));
493
+ this.mount(
494
+ '/hp',
495
+ healthController({
496
+ altRoute: '/status',
497
+ }),
498
+ );
420
499
  }
421
500
  }
422
501
  ```
423
502
 
424
- #### Defining a controller that registers a service
425
-
426
- If for some reason, your controller needs to register a service the rest of the container needs to have access to and you plan to do it on the `controller`/`controllerCreator` callback, you could end up messing with the _lazyness_ of the container: If a middleware or another controller tries to access the service and the controller that registers it is mounter after it, it will get an error as the service doesn't exist yet.
503
+ #### Controllers with services
427
504
 
428
- To solve this issue, you can use a "controller provider":
505
+ If for some reason, your controller needs to register a service that the rest of the container needs to have access to, and you plan to do it on the `controller`/`controllerCreator` callback, you could end up messing with the _lazyness_ of the container: If a middleware or another controller tries to access the service and the controller that registers it is mounted after it, it will get an error as the service _doesn't exist yet_.
429
506
 
430
- ```js
431
- const { provider, controller } = require('jimpex');
507
+ A way to solve this issue would be with a `provider`/`providerCreator`, mounting the controller:
432
508
 
433
- // (Optional) Define a class to organize your route handlers.
434
- class HealthController {
435
- health() {
436
- return (req, res) => {
437
- res.write('Everything works!');
438
- };
439
- }
440
- }
509
+ ```ts
510
+ // dont-do-this.js
511
+ import { provider, controller } from 'jimpex';
441
512
 
442
- // Define the controller
443
- const healthController = provider(app) => {
444
- // Register the controller as a service (or any other resource)
445
- app.set('health', () => new HealthController());
446
- return controller(() => {
447
- // Get the controller as a service
448
- const ctrl = app.get('health');
449
- // Get the router service
450
- const router = app.get('router');
451
- // Return the router with all the routes
452
- return router
453
- .get('/', ctrl.health())
454
- .get(...);
455
- });
513
+ export const wrong = provider((app) => {
514
+ app.set('wrong', () => new WrongService());
515
+ app.mount(
516
+ '/',
517
+ controller((app) => {
518
+ const wrong = app.get('wrong');
519
+ return router.get('/', wrong.doSomething());
520
+ }),
521
+ );
456
522
  });
457
-
458
- // Export the controller class and the controller itself
459
- module.exports.HealthController = HealthController;
460
- module.exports.healthController = healthController;
461
523
  ```
462
524
 
463
- And you would mount it just like any other contorller:
525
+ The main problem with that approach is that you would have to `register` it as a provider, so the route for the controller would need to be defined inside the callback.
464
526
 
465
- ```js
466
- const { Jimpex } = require('jimpex');
467
- const { healthController } = require('...');
527
+ So, for this case, Jimpex has a special wrapper, which is very similar, but that it allows you to `mount` it:
468
528
 
469
- class MyApp extends Jimpex {
470
- boot() {
471
- ...
472
- this.mount('/health', healthController);
473
- }
474
- }
475
- ```
529
+ ```ts
530
+ // controller-provider.js
531
+ import { controllerProvider, controller } from 'jimpex';
476
532
 
477
- And in the case you need a "creator", you could use a "provider creator" and return a controller:
533
+ export const good = controllerProvider((app) => {
534
+ app.set('good', () => new GoodService());
478
535
 
479
- ```js
480
- const healthController = providerCreator((settings) => (app) => {
481
- // Register the controller as a service (or any other resource) and send the settings
482
- app.set('health', () => new HealthController(settings));
483
- return controller(() => {
484
- // Get the controller as a service
485
- const ctrl = app.get('health');
486
- // Get the router service
487
- const router = app.get('router');
488
- // Return the router with all the routes
489
- return router
490
- .get('/', ctrl.health())
491
- .get(...);
536
+ return controller((app) => {
537
+ const good = app.get('good');
538
+ return router.get('/', good.doSomething());
492
539
  });
493
540
  });
494
541
  ```
495
542
 
496
- ### Adding a middleware
543
+ The `controllerProvider` wrapper allows you to register something in the callback, and expects a wrapped `controller` to be returned. That way, you can `mount` it, and specify the root outside.
497
544
 
498
- To add a new middleware you need to use the `middleware` function and return a function:
545
+ And like `provider`, and `controller`, there's also a `controllerProviderCreator`.
499
546
 
500
- ```js
501
- const { middlware } = require('jimpex');
547
+ ### ⚡️ Middlewares
548
+
549
+ To create a new middleware, you just need to use the `middleware` wrapper and return it:
550
+
551
+ ```ts
552
+ // my-middleware.js
553
+ import { middleware } from 'jimpex';
502
554
 
503
555
  // Define your middleware function (or class if it gets more complex)
504
- const greetingsMiddleware = () => (req, res, next) => {
505
- console.log('Hello!');
556
+ export const greetingsMiddleware = () => (req, res, next) => {
557
+ try {
558
+ res.write('Hello World!');
559
+ res.end();
560
+ } catch (err) {
561
+ next(err);
562
+ }
506
563
  };
507
564
 
508
565
  // Define the middleware
509
- const greetings = middleware(() => greetingsMiddleware());
510
-
511
- // Export the function and the middleware
512
- module.exports.greetingsMiddleware = greetingsMiddleware;
513
- module.exports.greetings = greetings;
566
+ export const greetings = middleware(() => greetingsMiddleware());
514
567
  ```
515
568
 
516
- > 1. You could just export the provider, but I believe is a good practice to export both in case another part of your app wants to extend the class or use the function.
517
- > 2. That why of using `module.expots` is so the function can be imported on JSDoc comments.
569
+ Then, on the app, you would `use` it:
518
570
 
519
- Then, on you app, you would `use` the controller:
520
-
521
- ```js
522
- const { Jimpex } = require('jimpex');
523
- const { greetings } = require('...');
571
+ ```ts
572
+ import { Jimpex } from 'jimpex';
573
+ import { greetings } from './my-middleware';
524
574
 
525
575
  class MyApp extends Jimpex {
526
576
  boot() {
527
- ...
528
577
  this.use(greetings);
529
578
  }
530
579
  }
531
580
  ```
532
581
 
533
- #### Defining a configurable middleware
582
+ Now, middlewares can also be `mount`ed in specific routes:
534
583
 
535
- Like with controllers and providers, you can also create a middleware that can accept settings when instantiated, with a _"middleware creator"_:
584
+ ```ts
585
+ import { Jimpex } from 'jimpex';
586
+ import { greetings } from './my-middleware';
536
587
 
537
- ```js
538
- const { middlwareCreator } = require('jimpex');
539
-
540
- // Define your middleware function (or class if it gets more complex)
541
- const greetingsMiddleware = (message = 'Hello!') => (req, res, next) => {
542
- console.log(message);
543
- };
544
-
545
- // Define the middleware
546
- const greetings = middlewareCreator((message) => greetingsMiddleware(message));
547
-
548
- // Export the function and the middleware
549
- module.exports.greetingsMiddleware = greetingsMiddleware;
550
- module.exports.greetings = greetings;
588
+ class MyApp extends Jimpex {
589
+ boot() {
590
+ this.mount('/greetings', greetings);
591
+ }
592
+ }
551
593
  ```
552
594
 
553
- The special behavior the creators have, is that you can call them as a function, sending the settings, or just register them with `use` as regular middlewares, so **it's very important that the settings must be optional**:
595
+ And, if you don't need access to the container in the middleware definition, you could also `mount`/`use` it as a _raw_ Express' middleware:
554
596
 
555
- ```js
556
- const { Jimpex } = require('jimpex');
557
- const { greetings } = require('...');
597
+ ```ts
598
+ import { Jimpex } from 'jimpex';
599
+
600
+ const greetingsMiddleware = (req, res, next) => {
601
+ try {
602
+ res.write('Hello World!');
603
+ res.end();
604
+ } catch (err) {
605
+ next(err);
606
+ }
607
+ };
558
608
 
559
609
  class MyApp extends Jimpex {
560
610
  boot() {
561
- ...
562
- this.use(greetings);
611
+ this.use(greetingsMiddleware);
563
612
  // or
564
- this.use(greetings('Howdy!'));
613
+ this.mount('/greetings', greetingsMiddleware);
565
614
  }
566
615
  }
567
616
  ```
568
617
 
569
- #### Defining a middleware that registers a service
618
+ Jimpex already comes with a few built-in middlewares ready to be used, and you can read about them on the [middlewares document](https://github.com/homer0/jimpex/blob/main/documents/middlewares.md).
570
619
 
571
- Just like the "controller provider", you can also create a "middleware provider", a middleware that also registers something on the contianer without messing with the _lazyness_ of the container:
620
+ #### Configurable middlewares
572
621
 
573
- ```js
574
- const { provider, middleware } = require('jimpex');
575
- // Define the class that will work as a service
576
- class Greeter {
577
- // Add a method that could be used on its "service role"
578
- greet() {
579
- return 'Hello!';
580
- }
581
- // Add a method for the actual middleware
582
- middleware() {
583
- return (req, res, next) => {
584
- console.log(this.greet());
585
- };
622
+ Just like the `controllerCreator` wrapper, you can also use the `middlewareCreator` wrapper to define middlewares that accept custom options:
623
+
624
+ ```ts
625
+ // my-middleware.js
626
+ import { middlwareCreator } from 'jimpex';
627
+
628
+ // Define your middleware function (or class if it gets more complex)
629
+ export const greetingsMiddleware = (message) => (req, res, next) => {
630
+ try {
631
+ res.write(message);
632
+ res.end();
633
+ } catch (err) {
634
+ next(err);
586
635
  }
587
- }
588
- // Define the provider
589
- const greetings = provider((app) => {
590
- // Register the class as a service
591
- app.set('greeter', () => new Greeter());
592
- // Return the actual middleware
593
- return middleware(() => app.get('greeter').middleware());
594
- })
636
+ };
595
637
 
596
- // Export the class and the provider
597
- module.exports.greetingsMiddleware = greetingsMiddleware;
598
- module.exports.greetings = greetings;
638
+ // Define the middleware
639
+ export const greetings = middleware((options) => {
640
+ const { message = 'Hello Charo!' } = options;
641
+ return greetingsMiddleware(message);
642
+ });
599
643
  ```
600
644
 
601
- And you would mount it just like any other contorller:
645
+ And now you can use it as a middleware, or as a function that returns a middleware:
602
646
 
603
- ```js
604
- const { Jimpex } = require('jimpex');
605
- const { greetings } = require('...');
647
+ ```ts
648
+ import { Jimpex } from 'jimpex';
649
+ import { greetings } from './my-middleware';
606
650
 
607
651
  class MyApp extends Jimpex {
608
652
  boot() {
609
- ...
610
653
  this.use(greetings);
654
+ // or
655
+ this.mount(
656
+ '/greetings',
657
+ greetings({
658
+ message: 'Hello Pili!',
659
+ }),
660
+ );
611
661
  }
612
662
  }
613
663
  ```
614
664
 
615
- And in the case you need a "creator", you could use a "provider creator" and return a controller:
616
-
617
- ```js
618
- const greetings = providerCreator((settings) => (app) => {
619
- // Register the class as a service and send the settings
620
- app.set('greeter', () => new Greeter(settings));
621
- // Return the actual middleware
622
- return middleware(() => app.get('greeter').middleware());
623
- });
624
- ```
625
-
626
- ### Proxy mode
627
-
628
- You can enable the "proxy mode" by setting the `proxy` option to `true` on either the function or the class and it allows you to access and register resources using dot notation:
629
-
630
- ```js
631
- // Set the option
632
- const app = jimpex({ proxy: true });
665
+ #### Middlewares with services
633
666
 
634
- app.myService = () => new MyService();
635
- // = app.set('myService', () => new MyService();
667
+ If, for some reason, your middleware needs to register a service before being mounted, just like the `controllerProvider`, you have the `middlewareProvider` wrapper:
636
668
 
637
- app.myService.doSomething();
638
- // = app.get('myService').doSomething();
669
+ ```ts
670
+ // middleware-provider.js
671
+ import { middlewareProvider, middleware } from 'jimpex';
639
672
 
640
- doSomething(app.$myService);
641
- // = doSomething(app.try('myService'));
642
- ```
673
+ class MiddlewareService {
674
+ getMiddleware() {
675
+ return (req, res) => {
676
+ res.write('Everything works!');
677
+ res.end();
678
+ };
679
+ }
680
+ }
643
681
 
644
- When using the class, as you would expect, the constructor would give you the original instance and then you would have to call `.ref()` to get either the proxy or the original (depending on the setting):
682
+ export const middlewareService = middlewareProvider((app) => {
683
+ app.set('middlewareService', () => new MiddlewareService());
645
684
 
646
- ```js
647
- const original = new Jimpex({ proxy: true });
648
- const app = original.ref();
685
+ return middleware((app) => {
686
+ const service = app.get('middlewareService');
687
+ return service.getMiddleware();
688
+ });
689
+ });
649
690
  ```
650
691
 
651
- But for the function, what you get as return value is actually the call for `.ref()`, that's why the first example could use the proxy mode without calling it.
652
-
653
- Internally, when `proxy` is enabled, all providers, controllers and middlewares will receive the proxy instead of the original.
654
-
655
- ## Built-in features
656
-
657
- Jimpex comes with a few services, middlewares and controllers that you can import and use on your app, some of them [are activated by default on the options](./documents/options.md), but others you have to implement manually:
692
+ And finally, you also have `middlewareProviderCreator` to create a middleware that can register a service, with custom options.
658
693
 
659
- ### Controllers
694
+ ## 💪 TypeScript
660
695
 
661
- - **Configuration:** Allows you to see and switch the current configuration. It can be enabled or disabled by using a setting on the configuration.
662
- - **Health:** Shows the version and name of the configuration, just to check the app is running.
663
- - **Statics:** It allows your app to server specific files from any directory, without having to use the `static` middleware.
664
- - **Gateway:** It allows you to automatically generate a set of routes that will make gateway requests to an specific API.
696
+ After v8, Jimpex was completely rewritten in TypeScript, so you can use it with no problems in your TypeScript projects. For more information, please refer to the [TypeScript document](https://github.com/homer0/jimpex/blob/main/documents/typescript.md).
665
697
 
666
- [Read more about the built-in controllers](./documents/controllers.md)
698
+ ## 🤞 Examples
667
699
 
668
- ### Middlewares
700
+ You can find the example projects in the `example` directory. To run them, you can use the `npm run example` command. By default, it runs the `basic` example, but you can also specify the name of the example you want to run:
669
701
 
670
- - **Error handler:** Allows you to generate responses for errors and potentially hide uncaught exceptions under a generic message, unless it's disabled via configuration settings.
671
- - **Force HTTPS:** Redirect all incoming traffic from HTTP to HTTPS. It also allows you to set routes to ignore the redirection.
672
- - **HSTS header:** It configures a `Strict-Transport-Security` header and includes it on every response.
673
- - **Fast HTML:** Allows your app to skip unnecessary processing by showing an specific HTML when a requested route doesn't have a controller for it or is not on a "whitelist".
674
- - **Show HTML:** A really simple middleware to serve an HTML file. Its true feature is that it can be hooked up to the **HTML Generator** service.
675
- - **Version validator:** If you mount it on a route it will generate a `409` error if the request doesn't have a version parameter with the same version as the one on the configuration.
676
-
677
- [Read more about the built-in controllers](./documents/middlewares.md)
678
-
679
- ### Services
680
-
681
- - **API client:** An implementation of the [wootils API Client](https://github.com/homer0/wootils/blob/main/documents/shared/APIClient.md) but that is connected to the HTTP service, to allow logging and forwarding of the headers.
682
- - **App Error:** A very simple subclass of `Error` but with support for context information. It can be used to customize the error handler responses.
683
- - **Ensure bearer token:** A service-middleware that allows you to validate and retrieve a bearer token from the incoming requests `Authorization` header.
684
- - **HTTP Error:** Another type of error, but specific for the HTTP requests the app does with the API client.
685
- - **Send File:** It allows you to send a file on a response with a path relative to the app executable.
686
- - **Frontend Fs:** Useful for when your app has a bundled frontend, it allows you to read, write and delete files with paths relative to the app executable.
687
- - **HTML Generator:** A service that allows you to generate an HTML file when the app gets started and inject contents of the configuration as a `window` variable.
688
- - **HTTP:** A set of utilities to work with HTTP requests and responses.
689
- - **Responses builder:** A service that generates JSON and HTML responses.
690
-
691
- [Read more about the built-in services](./documents/services.md)
692
-
693
- The service also implements a few other services from the [wootils](https://github.com/homer0/wootils) as core utilities:
694
-
695
- - [`appLogger`](https://github.com/homer0/wootils/blob/main/documents/node/logger.md): The logger service.
696
- - [`environmentUtils`](https://github.com/homer0/wootils/blob/main/documents/node/environmentUtils.md): The service that reads the environment variables.
697
- - [`packageInfo`](https://github.com/homer0/wootils/blob/main/documents/node/packageInfo.md): The app package.json information.
698
- - [`pathUtils`](https://github.com/homer0/wootils/blob/main/documents/node/pathUtils.md): The service to build paths relative to the project root directory.
699
- - [`rootRequire`](https://github.com/homer0/wootils/blob/main/documents/node/rootRequire.md): The service to make requires relatives to the project root directory.
700
- - [`events`](https://github.com/homer0/wootils/blob/main/documents/shared/eventsHub.md): To handle the app events.
702
+ ```bash
703
+ npm run example [name-of-the-directory]
704
+ ```
701
705
 
702
- ## Development
706
+ ## 🤘 Development
703
707
 
704
- ### NPM/Yarn Tasks
708
+ ### NPM scripts
705
709
 
706
- | Task | Description |
707
- |------------|--------------------------------------|
708
- | `docs` | Generates the project documentation. |
709
- | `lint` | Lints the staged files. |
710
- | `lint:all` | Lints the entire project code. |
711
- | `test` | Runs the project unit tests. |
712
- | `todo` | Lists all the pending to-do's. |
710
+ | Script | Description |
711
+ | ------------- | ------------------------------------ |
712
+ | `build` | Transpiles the TypeScript code. |
713
+ | `docs` | Generates the project documentation. |
714
+ | `lint` | Lints and formats the staged files. |
715
+ | `lint:all` | Lints the entire project code. |
716
+ | `types:check` | Validates the types definitions. |
717
+ | `test` | Runs the project unit tests. |
718
+ | `todo` | Lists all the pending to-do's. |
719
+ | `example` | Runs an example project. |
713
720
 
714
721
  ### Repository hooks
715
722
 
716
- I use [`husky`](https://yarnpkg.com/package/husky) to automatically install the repository hooks so the code will be tested and linted before any commit, and the dependencies updated after every merge.
723
+ I use [`husky`](https://npmjs.com/package/husky) to automatically install the repository hooks:
724
+
725
+ | Hook | Description |
726
+ | ------------ | ---------------------------------------- |
727
+ | `commit-msg` | Ensures the use of conventional commits. |
728
+ | `pre-commit` | Lints and formats the staged files. |
729
+ | `pre-push` | Validates the types and run the tests. |
730
+ | `post-merge` | Updates the dependencies (`npm i`). |
717
731
 
718
- #### Commits convention
732
+ ### Commits conventions
719
733
 
720
- I use [conventional commits](https://www.conventionalcommits.org) with [`commitlint`](https://commitlint.js.org) in order to support semantic releases. The one that sets it up is actually husky, that installs a script that runs `commitlint` on the `git commit` command.
734
+ I use [conventional commits](https://www.conventionalcommits.org) with [`commitlint`](https://commitlint.js.org) in order to support semantic releases. The one that sets it up is actually `husky`, since it installs a script that runs `commitlint` on the commit message validation.
721
735
 
722
736
  The configuration is on the `commitlint` property of the `package.json`.
723
737
 
724
738
  ### Releases
725
739
 
726
- I use [`semantic-release`](https://yarnpkg.com/package/semantic-release) and a GitHub action to automatically release on NPM everything that gets merged to main.
740
+ I use [`semantic-release`](https://npmjs.com/package/semantic-release) and a GitHub action to automatically release on NPM everything that gets merged to main.
727
741
 
728
742
  The configuration for `semantic-release` is on `./releaserc` and the workflow for the release is on `./.github/workflow/release.yml`.
729
743
 
730
744
  ### Testing
731
745
 
732
- I use [Jest](https://facebook.github.io/jest/) to test the project.
746
+ I use [Jest](https://jestjs.io) to test the project.
733
747
 
734
748
  The configuration file is on `./.jestrc.js`, the tests are on `./tests` and the script that runs it is on `./utils/scripts/test`.
735
749
 
736
750
  ### Code linting and formatting
737
751
 
738
- For linting, I use [ESlint](https://eslint.org) with [my own custom configuration](https://yarnpkg.com/package/@homer0/eslint-plugin); there are two configuration files, `./.eslintrc` for the source and the tooling, and `./tests/.eslintrc`, and there's also a `./.eslintignore` to exclude some files.
752
+ For linting, I use [ESlint](https://eslint.org) with [my own custom configuration](https://npmjs.com/package/@homer0/eslint-plugin).
753
+
754
+ There are two configuration files, `./.eslintrc` for the source and the tooling, and `./tests/.eslintrc`, and there's also a `./.eslintignore` to exclude some files.
739
755
 
740
- And for formatting, I use [Prettier](https://prettier.io) with [my JSDoc plugin](https://yarnpkg.com/package/@homer0/prettier-plugin-jsdoc) and [my own custom configuration](https://yarnpkg.com/package/@homer0/prettier-config). The configuration file is `./.prettierrc`.
756
+ For formatting, I use [Prettier](https://prettier.io) with [my JSDoc plugin](https://npmjs.com/package/@homer0/prettier-plugin-jsdoc) and [my own custom configuration](https://npmjs.com/package/@homer0/prettier-config). The configuration file is `./.prettierrc`.
741
757
 
742
758
  The script that runs them is `./utils/scripts/lint`; the script `lint-all` only runs ESLint, and runs it for the entire project.
743
759
 
744
760
  ### Documentation
745
761
 
746
- I use [JSDoc](https://jsdoc.app) to generate an HTML documentation site for the project.
747
-
748
- The configuration file is `./.jsdoc.js` and the script that runs it is on `./utils/scripts/docs`.
749
-
750
- ### To-Dos
762
+ I use [TypeDoc](https://typedoc.org) to generate an HTML documentation site for the project.
751
763
 
752
- I use `@todo` comments to write all the pending improvements and fixes, and [Leasot](https://yarnpkg.com/en/package/leasot) to generate a report. The script that runs it is on `./utils/scripts/todo`.
764
+ The configuration file is `./.typedoc.json` and the script that runs it is on `./utils/scripts/docs`.
753
765
 
754
- ## Motivation/Introduction
766
+ ## 👀 Motivation
755
767
 
756
- A friend who's also web developer brought the idea of start using a dependency injection container on Node, and how Jimple was a great tool for it, and from that moment on I can't think of starting an app without using it. It not only allows you to implement dependency injection on a simple and clean way but it also kind of forces you to have a really good organization of your code.
768
+ A friend, who's also web developer, brought the idea of start using a dependency injection container on Node, and how Jimple was a great tool for it; from the moment I tried Jimple, I could never think of starting another project without it: It not only allows you to implement dependency injection on a simple and clean way, but it also kind of forces you to have a really good organization of your code.
757
769
 
758
- A couple of months after that, the same friend told me that we should do something similar to [Silex](https://silex.symfony.com/), which is based on Pimple, with Express. I ran with the idea and... this project is what I think a mix of Jimple and Express would look like. To be clear, **this is not a port of Silex**.
770
+ A couple of months after that, the same friend told me that we should do something similar to [Silex](https://github.com/silexphp/Silex), which is based on Pimple, butwith Express. I ran with the idea and... this project is what I think a mix of Jimple and Express would look like. To be clear, **this is not a port of Silex**.