{"_id":"@reflet/express","_rev":"28-f5b5d31191eb53d57373ca4b37a5b655","name":"@reflet/express","dist-tags":{"latest":"2.0.0","next":"2.0.0-next.13"},"versions":{"1.0.0":{"name":"@reflet/express","version":"1.0.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app","nest"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","express":"^4.16.0","reflect-metadata":"^0.1.13"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"060475b5d5a89cfa3f917b00a8ffec76f636e3fe","_id":"@reflet/express@1.0.0","_nodeVersion":"10.16.0","_npmVersion":"lerna/3.16.4/node@v10.16.0+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-V8tCKBPmSU6H39Cd9ZhYqLun2d9CrlfpDEMy4tYlKgvEX9W7jHN8Rmg9SsScSMu0QWtJlmhJwGtzpW20JgdEWA==","shasum":"91ced5cc29b56f9af07c42e9a020654ffcfe2b37","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.0.0.tgz","fileCount":19,"unpackedSize":92986,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdldzICRA9TVsSAnZWagAARrUP/2vxQ1C0rXcySdzfvJAT\n9xBf5GTf2Ls0uVNgjE6o1D3QxizcUzZfq+34ismaCqbntJN4xZHMOmtCKuLd\nYrtvMS+eWF43PHihjihuqyigllatxtxwmwOGCBh7nqdr0cpjeZLmUoEHPvGU\nnzoIrn7D6tQpoHy/gVdCERkoOYlJio4AY7RjWSWOuX4RZtaUk2hVdUyN0tx2\ndJeExL5/FDciVk5dGdTAaOOE/Kcx+mdwr4lyQz1AnADh9I834eWHTjbflrxM\nMJyggeKhx0hSKdX/KzE4Ae2kYOTBli5zkXyNNpmO7zqMJiP67Pn3CLUvY2mB\nOrNWONN2usRCoFvy3SUbLM+guGidtuOu/tay84x3mxdCEAdjmA4iMmo+t6Kz\nm8x6wWA3XCYU/kscl8vcQnkmHKOpMgHKs+zlY7ynrU0HBbkQIfs206DiF36S\n0iBwSSKEj0VFqFcXmCb3i/K5iUVlax8sr9yBiy1l/roOf7eQKpK9lVPP7eXZ\nboE+V2eKZkAUTSo5uS4f2snyNSBiAg1C00fFBcgMrGq+byzZGTfakbbBBQYR\npvhZunZyDfmyjdO5t87uz5FionVNVbwOgDbzIGTCkloPLxiADOtfz9ppfXZK\nE4vBhlIgV9QHNyQwldaiUnexjnLP9xH0yVjL4MVUBtsXGd3VFIUvvF73uTs+\npOyL\r\n=gO9m\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGwSjR6Nn3UoJ1e8ReXVSKhaXA4O7DAaYeT7jnhUGdJcAiEAzeRxPsz9dGEavfrvg3XCkeKtjeFeB3muVdXnEi/I8nM="}]},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.0.0_1570102471505_0.45571246144974475"},"_hasShrinkwrap":false},"1.1.0":{"name":"@reflet/express","version":"1.1.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app","nest"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"a0338b37abb10f9c02d33e05f3739483b62cf92e","_id":"@reflet/express@1.1.0","_nodeVersion":"12.15.0","_npmVersion":"lerna/3.20.2/node@v12.15.0+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-q+PqFLRc1nrB4B2NZnuWk3tk32QdvTpVrD7MJPAPgmunCR1lwHA/s1fzWdUXe6fDDuInxezHHKy6RlkwMm36aA==","shasum":"0ddb58d8bf94d397a83ad69da5bbd28aeb2ccae1","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.1.0.tgz","fileCount":19,"unpackedSize":93207,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJejE6ZCRA9TVsSAnZWagAAPfMP/0G1xNXyhLo3jeHQ2o26\ngooqyGsGvx0cJYAZusBzEpr+1QBwqOVcZfB3nSVclIulZ2rgp07fIVLr6AES\n1Mkmpe/SuaqruynXh8Ctn3NOnubPCPeFgn84wvSxeYFon2QD4n2T80KaZqYP\ngW1tjSNq+TxR50NucBHr4u/HzIKk83lfqgcGzrCFAoNRHSDnrzJtS89ZyjjA\nVUizN8F522N2wdZNRm5FecrGNsRwSIj86MXorW1nmBqCf3hF7w01fCfvmPXz\n2p2QCrTIxUuMuZ8I5irWrNU2CattaE7kRxFeg7ZkchNFUESVMjeumiSfE/uV\nDbvb/4A9Ppg6Wc9nN3i/i9eoh7+3Wz6G2PvkNSMAbrtsAggjLeyK2xC+V07N\njna6DdcskDveOcJI7pp4Zvrp4wU3s88GqwrTGkp3nlKa8Glab3jJEXyd432S\n9mrJUQEN03LWeWRh1aPsWkaA0Tq/2QDAsR/u0gGWTYrDS9qk9J+vIci17lff\n1fg/v3xnPzyWtoiPv4g9WWzEfronJmz3U7ImM5BemMJhR/rhGXzlSPlqb6AF\niSGE9WyTpwDbpY0mSsPzttj3MV1XZOUfmvSlPg9jANPK0sQm/lHllNnbsD1B\nzb8odjaIGcpGHmAuIjUzL+tJwWRyInafy9NIN6EUzwTkgQtflQREQuSKV+9O\ns945\r\n=wHS3\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBqSlod/p4j+xrAp/wUYOkBjHf3EPxZx/kjuZxi+FrDQAiAZLoeyrpqrzhHiB7FUbZuoAoUgnf5Rb6qccbN5TQo6RA=="}]},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.1.0_1586253465006_0.12240139869114208"},"_hasShrinkwrap":false},"1.2.0":{"name":"@reflet/express","version":"1.2.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app","nest"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"0cdabd3d527d6a695b86a90ce8f75409198a38e2","_id":"@reflet/express@1.2.0","_nodeVersion":"12.15.0","_npmVersion":"lerna/3.20.2/node@v12.15.0+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-9UMDrVYcbEE4G0Dp+5+xtsu/FyRAXJfdgTZGMuFAwPgsIXWqFd0ztTHQ94PdQxsIdoY/15y5YLOyzd49ZyqxwA==","shasum":"5ded33b3ee66f75b6e80790d0e4f50d41624213c","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.2.0.tgz","fileCount":19,"unpackedSize":95055,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeoYbdCRA9TVsSAnZWagAAMZQP/1uw2uvcR0rs/RYV1+Ns\n+bPFPUJhsqo+nquYmKWCdpCdpEJID7fU1+CKZn5cXGdO+jNUOO+TEjQtyQCk\ny8WOVNS0hhg+reXyErvHgLeNoUW21AGyrG7U6R/I2JvrkjD0l9gdbkXw7FCm\njs0UQlt8Cky3yzc1EkjZegJTyEFPaY+LY0U9/eGAC3bsQyDfuyS5Xr6tc8aS\nsnfqcf3XV4bL1F/PE2gH1esO74yBenwJiWHUgSy/9eFsEN/j2eARwJdULDcF\n5QLOWRA7qhO5pHLZw6TXe/eRcjSlM77C++Si8LF+uLRJE2IylK/rFqgYrahv\nfVpQs0RCWSSFprbhm45pf8VS1P0MmqJbUC8MvelAzOF+2/3PoS6vgSeRva7s\nVwxy5NFqUnPsWj73gpzjYgA0oF006kOlNHd8F66z49yD9YhVMxgbKSQeGP7M\nO8DaQc8SfC6rGfPkROofJ20IqJL3/s1uykW0IMJo+H1KuqQOxCZ1HEdb/I5A\n+qpexyWoHnrIspNHHyQqvxAUI7EKIv6kDjUbp/CtRxq4VQj73aV4q58gFk3w\nbYlINTcs0OfUJ4Pw1NqqreNqBjxO1I6Bohsk+eOAPPblfmV4a4VOcxzVtvNZ\n7RjqtfnPvQlmnpUhe6Nh5fOsihuxuHt8EdsgdfFjF7qT7xjyIcpEVDdFbgeQ\nk/UV\r\n=kax4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCKO31vC24nAHIim5j9rnmQaxIWwxbXGOwyY3UiFX4dCwIgN08xfYPD8bjhPwlEUWJPVqXvUWijCbKsGPMkWKpoM0U="}]},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.2.0_1587644124634_0.6894011610049584"},"_hasShrinkwrap":false},"1.3.0":{"name":"@reflet/express","version":"1.3.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app","nest"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"8de57d651ba3cb36600585db8829b5c1bd80f596","_id":"@reflet/express@1.3.0","_nodeVersion":"12.15.0","_npmVersion":"lerna/3.20.2/node@v12.15.0+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-1ujDl5CwT4Ct3S3a2FPKDel8sqaJhn8W6Ff1KhQQJGj+BoqIAcwCSxQFtpf9k4bXx+6LLhM/cKNyciAm8Io6ug==","shasum":"c58bcc6ff8ad5d6bda7b5943910853e210b3d4ca","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.3.0.tgz","fileCount":18,"unpackedSize":95634,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJepaCPCRA9TVsSAnZWagAAQpAP/1rYNh0BA5tWYGqAy/i7\njj3TroA0MPoI71JWCX0Nfdws3V0ahjVzucqk866gg0ZWAdZZZJY2mFf57cDX\nGqQW6XemT/s9tjpWunzRWu0iU6c/FUSFqd5sfx6Wi9TgbS/ufZslN85pphKu\n/0Lt9cvkZsng43dcz8+ppKn4Udu4U9JY2lls1yNjBPUTpa6OBe3FIps0zxCg\n+y1MaCFZmFCOjfkdqNO0IxNfSqh9upgRIRSnlgrebo5PZ/xApqeCWGf5JIZp\nCbYgzGYarRJfZW9QDZOXJ+jwORiGI9weJaBG+6o3uNRTNze5xwKAbyO5/0Nk\nwzhUytxGwmOwX9s8e2RRHOi6gukBuq3YY5w2NNLr9iffvMu5D2dN2ULhIJCw\nSd1Ilpo6i2UfgREYSxQqBETB/RdipcNNz4FFe9gq59GKUx0F22d7JNEkrZyP\n4/wSggCZKekUP62VPIOmOiRRYAvjEvH8a7YQngvsZOM3vg9vbDAHwMpNdu6p\n22qicsYwR/4JC1YGqfEiqx0IHLQiqhiS7lt6ZuxujYcNHC88BDZ59qciZLQa\n4HPCh35E7FXIZecU5AdL2SrqrWTxUBkf3vGVjVP++gNLCk0GT+5wJ0L3UOT/\ndkgkmmW6az2q6/cbQ8aQ/KjjTNyclQEo2H7zJQoR7Kd1C8PLn4ATZzQScAnS\nIhYj\r\n=F93g\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIESfRdkuJVZKUQ4m5bl/mUroFKM414et297vZa0B2JtKAiAeEX/MRDnrHHrg01+LM6HWSvwciizh9rP7pMM1f1wTFw=="}]},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.3.0_1587912846812_0.1052322284687941"},"_hasShrinkwrap":false},"1.3.1":{"name":"@reflet/express","version":"1.3.1","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app","nest"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"6c1370ba8da688ea37f8e4efe581e10c09dd305d","_id":"@reflet/express@1.3.1","_nodeVersion":"12.15.0","_npmVersion":"lerna/3.20.2/node@v12.15.0+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-CqqBib2+TwSRGMqgmkxxYJ3hw5EY+pZNXaEuEQoXgUwykQo5n9XZLNnROFmRuRX4rEf3bOr5dxearOWYLdI+VA==","shasum":"30003500fb99516da5136c8c47138161cfcd035e","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.3.1.tgz","fileCount":18,"unpackedSize":97142,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqGfQCRA9TVsSAnZWagAA4aMQAIsNgh0DujbmnqhutGPs\nAh+Px0QBUwvQYLxvdnkwefu9P97HY1HjHirFHJWoTgr5JpvjBZ4WBOP4WFcK\nvaZD3kk7R2pOUflHFmIf1EPwBNwZj2emAMfESiey2ATbs8/5EOdLhPCu/SCn\nbHaX46ixSSZzlMoxMEPmG/bLiKiw4ac/cyusMf6MDBiN61SK6446ClPcYzP7\nk3YbBs/iMGvBxrqwxDObNxN4Vp335HUe8xEW7F1b54lgRxAIihcbSb6Rhb2l\n4Qd3zRmid/pqokSF2zAdA7E63/h+h/5dyzmIfUxLCHamp4/LLL6ykm/jwFIu\nXQjmsUXK8nSmLn7AYCZXntNRElfWGzC+kN5y/s/OgaezAdC5jNzMJt9i2SnI\nbajmu9jjGLraa7U30Ll8DUcZ3WatTQA5J0MDUMQCMlSBntvj3HKrh7X77aVp\nm2gFHzbJsp/sIb85NvwHbRmspWYxXo33WTff0LF5KBmPJN6QccWsZZrZqEJ0\nUk/easaKPaSQr6YdSAyItwsds7qTgX2HUGDEKNAfwo9vTQWF6y2vA9XpVa0q\n2HxbhBmpq6BqtzXh5PT2Nnfs7GjnAF2r63ZPKFI5HY2EkATWsa+tYdpXGM3O\n6IAoFyMdbVWUabpPxfjmZIVZZGJMi0HUYDfw0Yu35gSdjX8jo2FvzDd/Lkmw\nnGWX\r\n=m0vu\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDLNaHXWSC18CeXlif0traILwSHwAKghh+5TN0Tqj4+RwIgPhtWPnm/OvpprbA9wmz/1BeKQkbTt1r3xU/Byfozmig="}]},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.3.1_1588094927531_0.8218212880015054"},"_hasShrinkwrap":false},"1.3.2":{"name":"@reflet/express","version":"1.3.2","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.6","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"82ce413defd045186fa383999e2ed4eefdd3a672","_id":"@reflet/express@1.3.2","_nodeVersion":"12.16.3","_npmVersion":"lerna/3.21.0/node@v12.16.3+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-34yBVGx0x0z7yZXdvPsmZdDKtHjXJ0pg7Nf9uabhZPxkYKx6sxXEyQ8NjXbYyoqzW6x7DMZT3JI+WE0DxWTdbA==","shasum":"dbbac0a4e2fd87aed0498b552b5cf9ba1ff5392a","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.3.2.tgz","fileCount":18,"unpackedSize":97235,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeyvt3CRA9TVsSAnZWagAAW0AP/jYh1/H7WYN6+v2hXWZ8\noStb+r38Mjy/yujmVDPBCIFz5Q55qjy/5wHc8KrtOQXhLCRqyKy28ptFJToN\nykk8mbZN+oJTzo+aVMbkxzS2Z40oa81BvN1AK1Ehk33I9S7h4iEZX/aJPhX8\nZulhNyLSFJXR47jRnM83HgTmt6xknOSB9VgYdPny7LbImufzVbvS+OHSXt2q\n6CysCMgddIQMxLRjNhh+tXdHxLwUrNcP2CGncZkfgq+KYo6I5O+VR4/LOQie\nPasmz17kMC66yg4H7vW4/8ybV0/1+pV4/5rH9yMrRbSffZXV0ZT8BqMIv7CL\n3nED6+dV0/pEtgylbzrLP5JItuAsuE7xcY2Dqud8b02t9dS6qedYbFpedi6F\nfUWTtpw/Qs9Lj4ETJhwJsiDyUUP2EzDU3XFDqgCt5WLBgRUp8AZionJ36TKm\nAslahxLZErX1XQK3SPhz89pQgLW5VmDdmuvG4/a9idx3oZgXnHamlIU2got9\n2F3rbVvDCssc+8RV7637EykmIrAC5k+Dugg0BbIEvPz1WAKppeHRiM8ONksH\n+gj0QpZRGWUlhPF4JWkDgd1E323ZLXaw+q34qtw31KOMLJA4cuOhLgkujfCX\nGmZVZnuB/TG1Z85YWKSKmarivmBrMR05xqINns6vI+CeXAT41XYnyEgqn25+\nJ0Q+\r\n=KYIJ\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIErYI+anntuxcYwG06ILWqfGpghiPbyi1+1J163CUlKQAiEA+/J4VGQklfEUiT1BFBtR9U+j9I41AmtdOD/FjQqbowI="}]},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.3.2_1590360950981_0.7663744539841053"},"_hasShrinkwrap":false},"1.4.0":{"name":"@reflet/express","version":"1.4.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.9","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"7589e8c4fbfe88d13dedfd94215e26b15c214e9f","_id":"@reflet/express@1.4.0","_nodeVersion":"12.19.1","_npmVersion":"lerna/3.22.1/node@v12.19.1+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-0u71VcWXR+i/I+3Ym5g/PF4B14VgLNFGm/rodXi6TzdXYvsFQpaqYen0UbTHdNJegbSbYlDBXKGfrYd8NRVe3A==","shasum":"e7f964a6e6773999fec63577a4f51b9a75ee33dd","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.4.0.tgz","fileCount":18,"unpackedSize":103277,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf37u4CRA9TVsSAnZWagAA3asP/0kRPqgxJyP5KdyasRQx\nQZDNwvDP0XL4MgjEx+MKUL+Cu5ZYR6XRs+6TpPukmduYzE+jeYd/CdPN24It\nnbUw/6uIrkJuz00BgjHHNuaH/+pD8AisajM0WOz5FADHBVUAxnzdjIJdbgqi\n8XV56QI7p0QrB4RaPsbD4vyO7O367zlChLmI3YUxYoczfZz0kG08Y0+Okn6w\nqLs49yohmZWMtq/89XCYCM5nu64eBvjj4Li57NCpgfH/YrSgL8auIKpAo5wS\nIHYy32+/s7Ot1m7WQMitg6i2/1PDUBUu1+CLJMB806mpgpCyQ+p7XKgz6Jd3\nD1uwiDpqANIf7upVni/jLyn2KDrnN+FEmtINNCQUYRGShrc91OX1bRJqIRnX\nEYiEcQ590LzSubDLzP79Q1h+QXzFGqKTAG69LElfr3SlorCvJKtzHuc95evf\nCg+/Irj0Gk2rFWaZn2tsGCnzomABNQqCLUfPHZP/5BfFz4nnlF8rEceJtEQF\n4md65eDyjp9FCnY3geHGaBlCT9VIk+gBqIJM61nnA+solAxlsy71TfKfZkad\nKjf0suGxWSl0UFm9ZgkwcJz0RP7eonH054+rcxjmRijLn2sIP8SGNJya3PmD\nuGBATUDnyE69MvhoQhK6nT64mmXKQb0PP2YIcbbvtJUe/TzJFmgoPTtIP9Vz\nRkAZ\r\n=aN+C\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEcWDooFE8vNy6Q/eWAihJizP8VtwI1xmdYcqEcPVXJrAiEA9u4Zznzv1IpTVh01ds9jL5fkGHdjJMsmiLUOqCszaiM="}]},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.4.0_1608498103809_0.14898508162516277"},"_hasShrinkwrap":false},"1.5.0":{"name":"@reflet/express","version":"1.5.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.9","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"a27d1361428f7d91edf83cd6a127e52d65b6a602","_id":"@reflet/express@1.5.0","_nodeVersion":"12.19.1","_npmVersion":"lerna/3.22.1/node@v12.19.1+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-bP6J7KKMLOmYpRyr9YXJIGU4VJE9hJMJgbQx5KmvMqRsY4WecchqGWEwuy5HJNhI6ItB2hnZ1M7bSUKeJAk+VA==","shasum":"1d5c433a08b22ec88cacc0a5aca1b95e8ac79aed","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.5.0.tgz","fileCount":18,"unpackedSize":104379,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf9JKsCRA9TVsSAnZWagAAOvsP/iUwePUQQPqYryk8mAk0\nj3Ak093cZ45m/zEtCDB2ZsQPcIvU+SrsC7l0V84Jp7G4guNv19rlymDzvhKe\nbC6ElNL4Nsy7OKgCbTxCw82eUKfQwpNfi0a0a62w5p5q4kc4xcj/wYxhowlx\n/GdZtaslrf7C8bfihvTTiAyJVZ5cr/1ShaeyGnDT5UzcsJvTYviOSvKyCYQ0\nK5b6bFVrusnvWLAjI5vRipxKyj1956KgyGu+5unoUejWhfWhEPio8vKq3MZD\nme80oqM5S6wdYGP90rerDl9Tn4wibFPfG+q6VzUHixPdK+Unv/PIt8ARsPLn\nFXcMJ2Ob7z9nr0nxjc0oh6xdp/l1tug/NbJNFZeMzmTsryYWy/0Sg1o0HHnu\n7NH+Y/a+AB2P3UXCCV1AZ6lxXSRP6nowujuUMjQVmShEfowqcq8T0Xvvg/qU\n2U5ug2rzNsmbiQ+LsqILe4EEyGlOj4aU4VT8KAw7nFdeKAFcRNMgGQar54B/\ngKgiGi+FR1sK67lRue+x0LY0M422mUfKVgNE6G9sTnaTOn6S+1U7AclMjBZN\nFeFNDTc+U99OYoO0gYzksXT5S6K/BFkqVQoXA1OsUDopPzSFLlll2zKeW4wv\nqHFr2yjEHPdPtdR/PyVALilh95yAZ+plSFN7cNQvwIcipC2mJq8Y0jLvXwHo\nV0tq\r\n=ABQT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFJ1m+97778YlxKlhQG8Bf6GdqkvWw1BfgPQi2CX7Jv3AiEAs6Y5ppf29kHHiJ/IASL6UKAIj4xgg5bRMvlpBI1nDV4="}]},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.5.0_1609863851209_0.803471364684706"},"_hasShrinkwrap":false},"1.5.1":{"name":"@reflet/express","version":"1.5.1","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.9","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"c99aef79424ad0d1495ef0e92cb3f138e4d513e1","_id":"@reflet/express@1.5.1","_nodeVersion":"12.19.1","_npmVersion":"lerna/3.22.1/node@v12.19.1+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-422uLZcab0nTueeVm29oibRMSuAVt9r9NFyRAsy4rM7U9fFe4hC1IEjY4EcRqWKBc3jPTYsrpjNIwDwCJBfAJw==","shasum":"43e43bebe1f92ab58131e88d6d7a59517cb0ac9b","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.5.1.tgz","fileCount":18,"unpackedSize":104676,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf9JQMCRA9TVsSAnZWagAAGpsP/R77uDygjM6Sj1bBX5CO\npC1iw4f8xhMl6A3nvFC9meW5w58scjL0p4Bn6qEPbB4RWWOVccpKeTCMYedK\nCwVLwyk0dY698CEQZi0cNkbdyp15LZWEhs7lh4i4Irboc9JPCsUjOXEekEu6\nGahnXO4mgp27a83qHgI0nBz1NwU5Og7+SMIe/LwziLGZloZ43EWs64ODmnlx\n6B+2eWsAMaNFe+2wrO0L1XJFGf5K0roRA9z25zOjEItCV49ENkHIAqMfHxe7\nipsiyakp5KhOW03zPbzsV2975XGZBQ5S7eai78W7OKiCvwqu2tAlyR+b2hx6\nhDuocY4JOjU3JeT+3CNU2RrtPU6aHXjmaCbK9PUJD/1dxuU4N//uCrcRKnAc\nEmGCSRaIRfbWkpviTyw9hAJLw7BwPjEq3fYDwKQvFagZD7M+qu9t3wdiWqyP\n0yW1KBiekF75NC5xFdzJyXwbcshQe9Cm+v1KnnpJGpe+ozc0pHPyYzQCv7RY\npWJxL0ktK4+Mw29ZSHN2NvDhemO2kqnh8A0L+YPNeS+BhbLES/3XoWpo3axG\n1XFzFOp6RTXLIw3eb15358Ju9iH4W3ZFBhjpwzt3R3Su6xAQhWnG7/PAidOf\n4wcSG/BugrvCgYTaCpSwILU6XLncFVtQqI1Z6Petfoy3jwX/vMHZ4lORUqEd\n8PYe\r\n=Knoh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIALBxPx9QX34dsofdnW3y/sK9duFQ0sty7+b+lIH6LeNAiAoTHiVsWZ66sNVf3Tufnz+EfPpGSy8BdpwPapiyI0osg=="}]},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.5.1_1609864204318_0.831418381724369"},"_hasShrinkwrap":false},"1.5.2":{"name":"@reflet/express","version":"1.5.2","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.9","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"b047e108875c8925351be4114071867094ab2786","_id":"@reflet/express@1.5.2","_nodeVersion":"12.19.1","_npmVersion":"lerna/3.22.1/node@v12.19.1+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-lIFAE3IPugGRoDvLyjFh79wMeDbioy6iEodh1p9zxqprGYDLt6rlnpx8y8BJf6RfNRQFsczjn8ERQ7jBBkYo8g==","shasum":"7339e582075748539292a296a99f2f48fe71d5a2","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.5.2.tgz","fileCount":18,"unpackedSize":106116,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgJqx8CRA9TVsSAnZWagAAsmcP/0S6KsEVRACjNxUsgITO\nPIVZ+6pHWqokfCLpDwJebtbAVEqTJenq0BpbmUtsFpfjfQ5EdDvl3q5UM6Ay\nUY5FdMi2nUhISuhK25/nCBQPZCjkXr/2pQ1sPDvbQbbFgJN4Z+X1hWSlLIXg\n/5exQ1WPyGk6fGxGLu/EvesMcz3+XodsUDmCrU/sJJ4KEEKtvdF+aErpCR9C\n5QL7LKBHVkI7kDqnYyfjrLPEQ9uLrJR7d+MLeMP2zcrFjcDX6g8hXR2NAL2O\ni9gM7ZCDSO52C+B5Lmms5136HwhNABD7DYdRXTvQRi5Aj1XSYe5+fnr7qP9x\nTQfybJgvTntAmcq/fO5SCIwljvWkH5yB2vdMhBHYnW5By1JZDLYp47ar4d+Q\ne8oWrAvyQRxp2l5Pmw5DqHlcXE1JYMxhBBdkW8DGIENN19z8y0Y4r18BOET/\nOMlDODuRAKV7YXYIOfE5Im/Oc/sS5oAZgfqIcRR6QsZox0oWtOGeuUpfnkQx\npDGKpCAkgbWZmfLdDKlEmSUyxlsUe1pzok590/KHlWR4rD047qiU2GwlQ4lt\nsZUXIAw4UoeDm7d1pvyHxTgIQzCxZi57IUnuUKTo1W4wyg6+f9ssnx0+j0IN\npoZA4M9YnzKvBtr7a3H1v+4YNXaIW3dC0e6nPl2tIswMwFs40ycSjqavZ5HH\n12wC\r\n=TB2z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHi19ox/+tibQjdEkssnT0x4ODegAbiNJVtbcA8sadQXAiEA+HdCnPTTTjp67War5m/MpBBSW+ru4IAcx3r1VLmrDZU="}]},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.5.2_1613147259808_0.991899055276148"},"_hasShrinkwrap":false},"1.5.3":{"name":"@reflet/express","version":"1.5.3","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.9","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"e7affc07ed9e3e5bd40f69bba17994f7fdd1cecf","_id":"@reflet/express@1.5.3","_nodeVersion":"12.19.1","_npmVersion":"lerna/3.22.1/node@v12.19.1+x64 (win32)","_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"dist":{"integrity":"sha512-GcYBtjlIQA6lFtx0vTqRFbfsoOu/6CimlZMzLzog/PiOk56AIGaCZGL2Cjqw5o9zEiNSrRhq4CJdUyn+lnhgDQ==","shasum":"2453e00ab53fd6ea26bd7f4f0d9e96b189117166","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.5.3.tgz","fileCount":18,"unpackedSize":107222,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgLokXCRA9TVsSAnZWagAAclAP/j0AsphxOyxxPfAKS+pk\nqcWZp0Ijf4rF9sM15LKnHMjRF901Lld2kwEbZUCmaWjm7mdo0KRTlYQ1Fbfo\nQCILhSRRSG3uj1j3rs4BfhJMgdjZhFMyq7XSsyFLRQ/kZcrZ9rW9s8yKU+JI\nxbipk0XVb1yFxFkeBhmKA9CogNGLmQJqi8hk4hmdttgivwq5ogPOtSqyx8hG\neRn5ZUdOh1pNFCyoluycLBxw2UGJ2yP5CqUbuB2k3miEsKPiSKvP2crkJZDN\nOiZv1o/i6Eown7mBO7YheLVTozjnBEOnu5VojQk9oJxnR9QIeElmaYkHkepb\n5PQAKNtr3wezfk4/o7mwZ+2v6/EtQkpxr+zztUNKMIDOnz62mQxs+xjGYIWK\n+oGKQnWJUOu3M8SFvIWDuj1LdVHh+rWyofm8CYkJiLKJQxI8qwZWv6v4b7Is\n9hz03qDUxNuw0G9/3aXMoYwPpP4e6A+lXH/IX1mkdfskPSPK0E39lhWxe8lK\nwZhocB0qJz/ZUjzswqi88WuwVVdhXDFMp7SzQZcC/bib9Rh/Q+b6mh8IZZmF\nQtJS/uyJdfIfwje+7Xa4s/QPbVy9EEHqmoKanPXZRxP+Pi+BF1Wvr0NwUyhz\nUrYqHi1aPA5ibAivxrAbdkyZ8xpwxB3vcRC6if7+89fXHY+iFkp4F5a3dYrt\n3J36\r\n=Y5wA\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDG/QTPSxnt0+I/Dal3/5Hlnocc4lWQf1oLTCe/3UZRuAIgJXtIgKQZphShz10m+mUHTpHaDxevslcJoy0BVOZnXKQ="}]},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.5.3_1613662486684_0.5937443204825392"},"_hasShrinkwrap":false},"1.6.0":{"name":"@reflet/express","version":"1.6.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"ae36ba29ae2e0a0e4a387c4a0236df7051ea06a9","_id":"@reflet/express@1.6.0","_nodeVersion":"14.17.4","_npmVersion":"lerna/4.0.0/node@v14.17.4+x64 (win32)","dist":{"integrity":"sha512-/ziDX+PaHi7aGqDnBfjqiLYxmsWvFD478QHeEhaHZtTb8egvceyq/2PnJ7tel7FNdBy8jiapOKQOXcve8aJ6qg==","shasum":"0685dd0e761700c37570a8c5c58b06bde0555e86","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.6.0.tgz","fileCount":19,"unpackedSize":127531,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhDGoaCRA9TVsSAnZWagAAlhkP/12cfLA7aDFbbc/DVbh9\n//2Vyp/v26bZBFTL/TEbxBG8a3ggvTcufE4PJMcTuwtCWREsVsfQBqnmzIZ4\n/o+8YUCJQfh6ubvufl4zIYy8ml9F3tM4p0swxorUAx1dnNd6sbf+MOVEEq8X\n5JruYSdUsS0LaOF9lw1kubBtnNw5WVLBrn0UbPE/3I5q770I/W0x+rSDaVaJ\nGtlrPivPYaHkMy5ptEjCCV24/ah5vI7GEpBMtdzVn6QmtoeckDRJ3NSfdxoJ\nvK18tFJ123geAYL90MFqFejWTQiZseMIZ48/++bWhGHAyI31UNfpRxrZtAiz\nUupJoGVlZw8UDwEkRfDErDG5nMFr4eLX5wTFQQwv1mbxzh9bwKieDamEZrvd\nSsyKTx7QH7129MBzvDB8lzAX26QMMTNix0JvI503MGFxmQEoQzhLYXgChzE/\nOgeGWjAmh+LP0cXu2uHUEjIiAKerH/b2Vy8jgg8lHxsBwRXW1kASdeNO5OSB\n6tQE8/KVtjya0PlySyaYxMw3HI6KLQDIBWo8IXJ/83G9cQgZ7NRWKzga6SLw\niA0kTx1ie1uksBPrGtKlo98VaNGWeGkeMuGpXflAFULqzQWFyRSQ7nZ/w4sF\n/kIOJrongx4kTFIx0HVTnih333q9fRAW0nWcbJeABy0Y0YZx7tgOcb2pG5jB\nfZvG\r\n=K/dT\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC3hX/ReWZiouxnGdj9BiLd0tVBxQY1RUbXpR4nc7wOtgIhAMzwYQXE0USmiQIczvXcICBy9TU2c0ek0Lu/NyE54NJO"}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.6.0_1628203545980_0.9006763486949447"},"_hasShrinkwrap":false},"2.0.0-next.0":{"name":"@reflet/express","version":"2.0.0-next.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"555c3d38e85b5cf9546bae0f7b2868f75b7211e4","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        \"emitDecoratorMetadata\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express express && yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [{ path: '/foo', router: Foo }])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  { path: '/decorated', router: Decorated },\n  { path: '/plain', router: plain }\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [{ path: '/items', router: ItemRouter }])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [{ path: '/elements', router: ItemRouter }])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Response, @Next next: NextFunction) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Response, @Req() req: Request) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: { userId: string; bookId: string }) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: { size?: string; color?: string }) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: IncomingHttpHeaders) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion. You can still opt-out by expanding the input type to `string` or `any`:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers<string>('x-custom') custom: string) {}\n}\n```\n\n##### 💡 Tip\n\nUse **[HTTP request headers enum](https://github.com/jeremyben/tshttp/tree/master/header)** from the same maintainer (that would be me) for an even better developer experience.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nA final option marks your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated], true)\n```\n\nWith this option turned on, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). _Comparison is done by **reference** and by **name**._\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [express.json(), express.urlencoded()],\n  true\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[HTTP status enums](https://github.com/jeremyben/tshttp/tree/master/status)** from the same maintainer (me again) for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont()`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont()\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[HTTP Errors](https://github.com/jeremyben/tshttp/tree/master/error)** from the same maintainer (you know who) for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  revealErrorMessage: true, \n  revealErrorName: true,\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: 'always'` always sends the error with `res.json`.\n  \n* `sendAsJson: 'never'` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: 'always'` always logs errors.\n* `log: 'never'` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `revealErrorMessage`, `revealErrorName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, and `Send` options, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, RegistrationArray } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Catch(finalHandler({ \n  sendAsJson: 'always',\n  log: 'always',\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: RegistrationArray) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","readmeFilename":"README.MD","_id":"@reflet/express@2.0.0-next.0","_nodeVersion":"14.17.4","_npmVersion":"lerna/4.0.0/node@v14.17.4+x64 (win32)","dist":{"integrity":"sha512-39MMvPKXMUvTksOLPKPwi7SmEl8+WTSX9tJpNnSWwps9eg7EaBJvC3rTsvTEOV2zp2INi4Aa2xwGslsi9ibyUA==","shasum":"4e4b88dce32fd51e18358b71934b034cd56f94c8","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.0.tgz","fileCount":20,"unpackedSize":122785,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDzKF4MSuNPHoIb2ptiA7fCXnF6jQLjHGzEF/WGIZ9XFwIgWjPsBaDomVpFKpNBea+2rcJ6M+WDGxphEC2WTikx554="}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.0_1633386939629_0.4559759622197277"},"_hasShrinkwrap":false},"2.0.0-next.1":{"name":"@reflet/express","version":"2.0.0-next.1","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"e419b54ee676ede7c05cff293ce40421660461a7","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        \"emitDecoratorMetadata\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express express && yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [{ path: '/foo', router: Foo }])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  { path: '/decorated', router: Decorated },\n  { path: '/plain', router: plain }\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [{ path: '/items', router: ItemRouter }])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [{ path: '/elements', router: ItemRouter }])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Response, @Next next: NextFunction) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Response, @Req() req: Request) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: { userId: string; bookId: string }) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: { size?: string; color?: string }) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: IncomingHttpHeaders) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion. You can still opt-out by expanding the input type to `string` or `any`:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers<string>('x-custom') custom: string) {}\n}\n```\n\n##### 💡 Tip\n\nUse **[HTTP request headers enum](https://github.com/jeremyben/tshttp/tree/master/header)** from the same maintainer (that would be me) for an even better developer experience.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupeByReference: true, dedupeByName: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \nComparison is done by function reference with `dedupeByReference` and by function name with `dedupeByName`.\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupeByReference: true, dedupeByName: true },\n    { handler: express.urlencoded(), dedupeByReference: true, dedupeByName: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[HTTP status enums](https://github.com/jeremyben/tshttp/tree/master/status)** from the same maintainer (me again) for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont()`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont()\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[HTTP Errors](https://github.com/jeremyben/tshttp/tree/master/error)** from the same maintainer (you know who) for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  revealErrorMessage: '4xx', \n  revealErrorName: 'always',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: 'always'` always sends the error with `res.json`.\n  \n* `sendAsJson: 'never'` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: 'always'` always logs errors.\n* `log: 'never'` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `revealErrorMessage`, `revealErrorName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `'always'` always reveals the property (beware of information leakage).\n* `'never'` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of the `'always'` option as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, and `Send` options, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, RegistrationArray } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Catch(finalHandler({ \n  sendAsJson: 'always',\n  log: 'always',\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: RegistrationArray) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","readmeFilename":"README.MD","_id":"@reflet/express@2.0.0-next.1","_nodeVersion":"14.17.4","_npmVersion":"lerna/4.0.0/node@v14.17.4+x64 (win32)","dist":{"integrity":"sha512-XVSafH4yW+Hv9BojPU1xem58vrINxIqSakHGFOJuQOfnd2sOHOvHr8DHc5/GmYHhg6wZXgrmTwkxLk+H2vgnsQ==","shasum":"8ac74e4de7a034c2f5e0635d06fce9ae2e3c3c5e","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.1.tgz","fileCount":20,"unpackedSize":126023,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCZsP8PFmDYYgA3Ee6TcIz0r9lJlytN4OVt6jzq7cSUzAIhANbCKjM2lbBWO5jmE+/UfTowwxfxXItfUkhMX7KnG+/H"}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.1_1636650773929_0.42336689005141936"},"_hasShrinkwrap":false},"2.0.0-next.2":{"name":"@reflet/express","version":"2.0.0-next.2","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"0789b79957a68cfa5f778d09c6a4a61946945470","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        \"emitDecoratorMetadata\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express express && yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Response, @Next next: NextFunction) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Response, @Req() req: Request) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: { userId: string; bookId: string }) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: { size?: string; color?: string }) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: IncomingHttpHeaders) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion. You can still opt-out by expanding the input type to `string` or `any`:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers<string>('x-custom') custom: string) {}\n}\n```\n\n##### 💡 Tip\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for an even better developer experience.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont()`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont()\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  revealErrorMessage: '4xx', \n  revealErrorName: 'always',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: 'always'` always sends the error with `res.json`.\n  \n* `sendAsJson: 'never'` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: 'always'` always logs errors.\n* `log: 'never'` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `revealErrorMessage`, `revealErrorName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `'always'` always reveals the property (beware of information leakage).\n* `'never'` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of the `'always'` option as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, and `Send` options, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Catch(finalHandler({ \n  sendAsJson: 'always',\n  log: 'always',\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","readmeFilename":"README.MD","_id":"@reflet/express@2.0.0-next.2","_nodeVersion":"14.17.4","_npmVersion":"lerna/4.0.0/node@v14.17.4+x64 (win32)","dist":{"integrity":"sha512-XSopVxg5gWwEFzOHsNIGAC28BT8jWtVHdh46QNEdx+mjwE8qUDQs4xHD4S6qEmztiMQnrwcdtYC8t36Efd84gg==","shasum":"70d05e1c2c493c263e6e5bbfc75847919a8cdb97","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.2.tgz","fileCount":20,"unpackedSize":125374,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCID5bXLD7kECY9YnV9RQ5SFKglM4dYCM/tnWmsOCBEbfKAiEA88YkzFsq8Ptzaz28iq6Ns/iW27OiVDnPpwIlf/8VXrU="}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.2_1636742138243_0.14435070964668983"},"_hasShrinkwrap":false},"2.0.0-next.3":{"name":"@reflet/express","version":"2.0.0-next.3","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"gitHead":"4901916b85ebcf823fe1973fc80f96c0b25f369f","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        \"emitDecoratorMetadata\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Response, @Next next: NextFunction) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Response, @Req() req: Request) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: { userId: string; bookId: string }) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: { size?: string; color?: string }) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: import('@reflet/http').RequestHeader.Record) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont()`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont()\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  exposeMessage: '4xx', \n  exposeName: 'always',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: 'always'` always sends the error with `res.json`.\n  \n* `sendAsJson: 'never'` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: 'always'` always logs errors.\n* `log: 'never'` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `exposeMessage`, `exposeName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `'always'` always reveals the property (beware of information leakage).\n* `'never'` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of the `'always'` option as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, and `Send` options, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Catch(finalHandler({ \n  sendAsJson: 'always',\n  log: 'always',\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","readmeFilename":"README.MD","_id":"@reflet/express@2.0.0-next.3","_nodeVersion":"14.17.4","_npmVersion":"lerna/4.0.0/node@v14.17.4+x64 (win32)","dist":{"integrity":"sha512-/Kh7IPb2vyTd6EAL6rWVFNowiGWfUbKzY+7NtzhJm/RV/NdBuaOuxFNfp0PEhoZPhf5pxrauE8LolbBtgV5FQA==","shasum":"2877d05c15cbc15b8b1d7c869b53695a33989f73","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.3.tgz","fileCount":20,"unpackedSize":123989,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIGiTaCoTHo8WpkRXxY53LWwnhnwEIhK96+zuNL/ERkrFAiEAtplbB/MSN8lsPwDdzFBn8bZlYhZk0TYX0tcEKLdYNr4="}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.3_1636925383868_0.41096009273960576"},"_hasShrinkwrap":false},"2.0.0-next.4":{"name":"@reflet/express","version":"2.0.0-next.4","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        \"emitDecoratorMetadata\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont()`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont()\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  exposeMessage: '4xx', \n  exposeName: 'always',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: 'always'` always sends the error with `res.json`.\n  \n* `sendAsJson: 'never'` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: 'always'` always logs errors.\n* `log: 'never'` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `exposeMessage`, `exposeName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `'always'` always reveals the property (beware of information leakage).\n* `'never'` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of the `'always'` option as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, and `Send` options, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Catch(finalHandler({ \n  sendAsJson: 'always',\n  log: 'always',\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.4","dist":{"shasum":"8303e36520b9f21a82b917170a492e0cad769f09","integrity":"sha512-Tj3tYW2aFnM6tL05qpiplCo1FE4TLdFbgz1EqFmZSrpFU5nHdmINI3nuj9WIx8r/vJV8Ea9S9PAEXEseFEIYvQ==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.4.tgz","fileCount":22,"unpackedSize":124571,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhrhixCRA9TVsSAnZWagAArmMQAIS7m8U5CXxZd6NlXfNz\ntOjEZfygjlGQmf+boxjabEhTHvcqVNeAABgfSAmn1rvReccpf9pu2U/KlMWY\nNPk9oE1vnSGzwZ94VvbJs19aqJ9br6WHKKZsbEykXMpr0kxB+7XpJrV37bDa\nRMK1llb5YP+dZeEFdRZtohcVNGdjbktj9BUAdcGA84T+NEgjfJKQ+nXWig9b\nWN+tfeiiItkUhIs7tGuABu7qQjgbZFraDZbzxfCW1nRx9iCxbm62xTOXeQUr\najzWGTJvcSqrB0nYm1Y1NFirnhU7aCtmDGa+FYBiFvTmGlnJ6KzUvMA2NHXr\nkYFWfLJpWK++qqEyShG/CuRymrNlimmVIH1H0pSYbEU5vVVSGW60nRciEUre\nrZVxGyEtIFC/HVByfnTUyrasbxUeMzK72cfqrIeKwtazZuM6XJ5W+acqubLC\nbPUj9bGmyWAPBWEQ5WmHK2yBEfElMF17cG8pivxquXrf8rELuNPpnLSpXB7K\nEV/ph4jJWmFUZu0CfqyFI9hvhA1ideK55RmRNiI21sQc07nSB6Jd4q59PuG7\nYltQ07gCW2oMxj3ySXNKmH7fEn/xlQybJPmF+5hgNngtY7HGcAAcOyhv/piR\nepEvIqlJBpbeTPaRLy3+gUDdbS08VZSdg16FwjYngyJEAj/H/ovYqTCY8eqm\nLnPQ\r\n=2T7L\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIDC8BUStcZBO0EDIlUEwSXqPwpnSMcTDZwkK3QqZXEdGAiByA5eQE1jpjrEytf1MaJn6TVaYZnlm3zOEeKM93aQ3UA=="}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.4_1638799537839_0.4932994525932468"},"_hasShrinkwrap":false},"2.0.0-next.5":{"name":"@reflet/express","version":"2.0.0-next.5","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont()`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont()\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  exposeMessage: '4xx', \n  exposeName: '4xx',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: true` always sends the error with `res.json`.\n  \n* `sendAsJson: false` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: true` always logs errors.\n* `log: false` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `exposeMessage`, `exposeName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `true` always reveals the property (beware of information leakage).\n* `false` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of passing `true` as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, and `Send` options, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Catch(finalHandler({ \n  sendAsJson: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.5","dist":{"shasum":"d3e5e3c703b5d3fdb73d9a7a75826bbef225ced8","integrity":"sha512-O/f6cEhd+0Scr0/Rzzg+xZjHCn4+hZ9A9z+UBCNmnKnfKRLU6lVWfRGtLn1wF8cw7lC5xSIm+zWlqmV4mK4C5Q==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.5.tgz","fileCount":22,"unpackedSize":124396,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJh4BQ9CRA9TVsSAnZWagAAPCoQAKBAnEkABDuYP0l5RR7G\nsCNg+PIJHFc8RS0xWxxf+l9tMWgfIKsQPUqf1guqB/j4rCFtyqnQQgUX7u+K\nV/FOBgqKameRvJiACxzw96aIJDtvvVIsz7xzZh6dLzLgAjcJBL3jOR/4dSVJ\np31JP1JbSRowUbgwRKVOfw2uJUNEny3thF0jDF/ITG76lQy42eLFknYpFa8d\nhFAx6l1a820v+owo1ifR/ROvssf0edIekbC4jxHNVGR5V1DPcFA1E103XjS9\nWtIbcBMlubLhQTfxh0S9yE1kVEmZojksmuGw7n6YAAtp6kZOpnlOWpwpb22q\nrCv4r7tvJ00dtvpiEQU6Z7zRVUu93RRawbK5/HFwVRNPnkSPn+05vZfUoj8L\nbEPZ8UA1onzCWLJWos9BtqpsoGhghhAKiy7+kcFsrqoIrHNvJWWdoj3EQOF4\nymt7DW0pfR8MA4BQlEI+QLh41HHx4Ro00fi7QsqVShtnGk9C2BOgU/6x4SUB\nHmRnRwZskRYqNFbP15aWRGIa/C7NyjKun9k3Jnq9nHmNeFNPbXnnJXAm8ONW\n1GkwVSNCCVJkqdSE/4iJ50GHDkUN88Z76LI6CUtkZMIoW8AZOCZ78x+Avq97\nT9oSdv1DXNGnvdHet5fbzWgj21pKxcQKn11BTVqR3YS5xyl4agce4YnUZcyh\nxVdb\r\n=QTPs\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC1FqqYN4bSJ2iA4/ILl90vJjaGdYjDk2RhJYGKrVW2NgIhAL+2s01XJ7Oj4FgLo1QvFkZvhhnKc2DTpaZdPeK6i97+"}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.5_1642075197547_0.10716039586295811"},"_hasShrinkwrap":false},"2.0.0-next.6":{"name":"@reflet/express","version":"2.0.0-next.6","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont()`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont()\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  exposeMessage: '4xx', \n  exposeName: '4xx',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: true` always sends the error with `res.json`.\n  \n* `sendAsJson: false` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: true` always logs errors.\n* `log: false` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `exposeMessage`, `exposeName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `true` always reveals the property (beware of information leakage).\n* `false` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of passing `true` as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, and `Send` options, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Catch(finalHandler({ \n  sendAsJson: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.6","dist":{"shasum":"884373303b2b8789bcafcfc92f2b689ace0e0fbb","integrity":"sha512-OQmxCMykZppn15kIpg2jEcAbcn7PjnpGeWl3lVUaTk8gA5aTMOwwO7mbm2dYup6xbeR8wS0+Ryl5L2tmcLf7Ew==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.6.tgz","fileCount":22,"unpackedSize":123849,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiH6itACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqBnBAAjlKaXbvRFCOW+//dfY2/Hhfrjab7wf5Ulxde4FZLaSJ9wL2r\r\n75EFTnJtAkIISxRUlb1SYnapoFJx4kMIoEgl47T63p2+/VPshWD3veoudMbO\r\na0E/d3mExS+pGIrveo3LU5UTfU9Q+6imK5AB9r4HDwDl00roiolVPgW0x2Wm\r\nhMuLCSQil04oWJk7g79B6pEQbDpo5YHgJq3erow6HhNtZCnbYS3BmP2WrjYK\r\n+McVVnNL2mASBa2blN9cxhqHKocrHiFE68Q8hMhqmyYns+rkopirIhEt9F+O\r\nhI7BeXTiKvkOdQOBK5j3E3YJfNmBwS8/iL5oIesOZUaMctQukQ41LgtpPtZq\r\nYmTk6OIo5GGvviTY35yWM1XT9bTqVtEsyhERY64PccedOu6RBUVeIZI7fTPt\r\nLBIC9rbYn9CoC1YmslY+LCaTQBROHb0dgaEPRhZ6lrsT2KO/zP/ILN/UwpDS\r\nQcjnUCsC2hmyShg4FHnHgrPoNCGViOqcj6KGPR44BwdShp1EDiOEogU/yU9c\r\n8VzhFenpQkzK+G47qcypCqZ/l+/NJnSaghEn19pz6N+J4FwjfVOwUh6Kw2OJ\r\nuVSPX7bIRacTNn+Pn4aM2qjhnlwjHJ/AksQo5XxWWgoMvW5DYmV3YharjYKN\r\ny9KAiNtj9KCtY47Pu9UblaoeN0dOf+gt6c8=\r\n=+9Jf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIDK4LSxPBZ3oJqLsMImb9r++tKl9Xpxc7CXHYVTLpBQhAiEAoz/van/Rw4PaLyyPykUZqr/aP0T8dGMqXnpwNsKmpvI="}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.6_1646241965482_0.04735275449078458"},"_hasShrinkwrap":false},"2.0.0-next.7":{"name":"@reflet/express","version":"2.0.0-next.7","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@Router.ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `Router.ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@Router.ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  exposeMessage: '4xx', \n  exposeName: '4xx',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: true` always sends the error with `res.json`.\n  \n* `sendAsJson: false` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: true` always logs errors.\n* `log: false` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `exposeMessage`, `exposeName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `true` always reveals the property (beware of information leakage).\n* `false` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of passing `true` as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `Router.ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  sendAsJson: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.7","dist":{"shasum":"9a1f25e2ab969548bc7cf56856c07acc74a8dd81","integrity":"sha512-8yAS0FAY3r8QgM9OgTvmL7E8EyZ4mfg6F/HOBJvFIayF21VCfZGMa/QkJDoB6ytkWmqhisoMJATLjlnx7MUtsA==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.7.tgz","fileCount":22,"unpackedSize":131039,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiH/J+ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqkKA/+O4EAn8vLlYxbkFKuiwOBRGcFXG9q/cUCPtBHyH72oHe59UwP\r\nbNeJgwU2BGJ++AQp8IybY6qw06AW232TFLFmPB7l94obWbiCHW1zPMUnP5t2\r\nNwVWuKvxoXrB6h4PgZv0BBzjkUWkcDGJ4cRPvYE83S2x2U5ua5AYnylomzh3\r\nDmCUH0Aa7KL1cQwT9rNdy91Raex6g9LztYrnQ9THHOI3wBn9p3EzrvD5wKLv\r\njU2ajQpZBg94Bb0ZOFIu2Jizhzj8s1uPYWFJvspOWf+DE6WeI5uZT5sFePDk\r\nSzten3xfbw/4jk7RpBklkOLpp8lvEe+t//1mk01BV7o1dO+/o9xYQmtaxb5C\r\nnUVff8roUbjxqphlAmTTX/gS1MXdpjBe6ZQrk2xxEiAg/EVZvB0rXVeHF2Kn\r\ngGVE5Hg2B3wfHj+e4/YBPad5+qgjQgMQqcxO9AJW3SQRTBgb6g76WDPwsrV5\r\n4sD+DSqPymK0PhIajt2RrKXyQ34yjzJG7wXkHYJrNgD8vz5DYtTpZhoJJjEs\r\nxn1idH6QNp0K5ZcNdhFcLAw+0rhN4ZJEtWpT76KlIkfPTo4GBm4cfjl6KhH8\r\npkaCXQL6TA24Tpf2nZZtsbSgH2JG5JD+2X8KAlv3Jq6A/NzZGFG7zPQqhGkv\r\nFIc4LYPBq+EGvW0AUOeYucdj8BmZGCV5l1w=\r\n=UA6Z\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDJ/gzGh2g/Kt3QMDl+j/d7kYGNcTUmj1eGFmLgBPjT1QIgFyYto62noVfEJ8XhvWjbPNN2V0lHKZav/4c1461JeNI="}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.7_1646260862039_0.25096147758051757"},"_hasShrinkwrap":false},"2.0.0-next.8":{"name":"@reflet/express","version":"2.0.0-next.8","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  exposeMessage: '4xx', \n  exposeName: '4xx',\n  cleanStatusAndHeaders: true,\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: true` always sends the error with `res.json`.\n  \n* `sendAsJson: false` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `log`\n\n* `log: true` always logs errors.\n* `log: false` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `exposeMessage`, `exposeName`\n\nError `message` and `name` are not serialized by default. These options make `message` or `name` enumerable so they can be serialized.\n\n* `true` always reveals the property (beware of information leakage).\n* `false` never reveals the property (default).\n* `'4xx'` only reveals the property on client errors.\n\n_`'5xx'` is not available as an option, to avoid information leakage to the client. In that regard, beware of passing `true` as well._\n\n##### `cleanStatusAndHeaders`\n\nThis option deletes any `status`, `statusCode`, and `headers` properties from the error object after they have been applied to the response.\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  sendAsJson: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.8","dist":{"shasum":"6e4f74645c80966f75810c0a45defd9672b4aad8","integrity":"sha512-PCrlBKF140eFErw6mEpyTngHYORYUQMEH85iNfdja4/ZO6wAnQ3cypSX5sHdGBZLprfJ+r0aw/uhi4NNL+m/WA==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.8.tgz","fileCount":22,"unpackedSize":128986,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiIMLGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqHnw//QbPDYRjZDgoLZQppWv9bi45xFRxwVHsWvQpIwbqe/MZXXjpB\r\nJvC3X56QyUn9vdIuN0lmHSXu/ugvqSLSueGLoIeyvFNip/WWAO5LYaJWGXLB\r\nrd2lRftO3Gbq4CPuyinOA4AT/WfbrmVe7e7zVvwnkI8w2xmy8kMY+ruzX18r\r\n7TmtpLYvSm6ZEqlU82NT3ZABa+Czi5PsrXA5RJSnA5ichx6tWZnC/8jnQfzx\r\nk5gObXSsv/pars04/yo3z4m/yiPJv9hEgWgz/AlQJO0po+xxB3dKEH6zrZhb\r\n3LKqUvM+ZcfGT1A6PWxXByn7+uWENMW37Ysg03KZsqQ/QevTLG9eAl3wu9hK\r\nciZutZkDyjvGydPHEvsaayH4rSW63ctuYAKWJoEDv0sczSAqjU+8qJ6RUJuQ\r\nWJL+EUGgZe2/PoUW+QuCDa3IL6Aeqzcj/rAcPSpvQZlZ1nw3Xr6YCsfB5boq\r\nEiJTAw0+IbM3aMfwItC5br0MT0WMusZK58m2AxAK1ZMEjnBd0Y2/jMnIf8XP\r\nHiUERYomE2aUeGosVXHwrAVuLXDL77AfNZpZyHWK4OFwol36+Thc4iSZvuLb\r\noNhj8eYnauzO/Y63Phbhp87IxD/q2f1Oc/n4lHhAcYX2iKO+Ud3Qv+rsKqpx\r\nAgObL9c9BnANFc8FxlYC1CvVlUVLCz6BDhQ=\r\n=ZUnC\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDffeBAbSFhS9wiADSGKpOZv1+AEtylnFDvBv0k1AghzgIhAMY+EOjRmyFUeLUPCFGL5zK+QhU7rNKTzSFUi6ZzryIQ"}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.8_1646314181973_0.19795023372700493"},"_hasShrinkwrap":false},"1.6.1":{"name":"@reflet/express","version":"1.6.1","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=8.10"},"engineStrict":true,"peerDependencies":{"@types/express":"^4.16.0","@types/node":">=8","express":"^4.16.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@types/express":"^4.17.13","express":"^4.17.1"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build"},"licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@1.6.1","dist":{"shasum":"9a6b7bac30e4e324ecff9eb2d23e39b8754b5267","integrity":"sha512-JXHmXpeoKy/JrIZcJdlBC1b4EF2QW8YmhK+0rIPsxSTlWDOM28Jl9mc8PLekTDOC7Eamrel2yZqTXcRn7YLYtg==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-1.6.1.tgz","fileCount":21,"unpackedSize":127138,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDxAqEH7pA1xWnry24sovRRXD7E0CC6jXp9RQtnT7YSiQIgU2whshlWdmduKi4JKD/ksr0xCkQmqXxXg1twnTk378g="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiU+2aACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp5zw/+O+EckGEir39q1Wlu8w6XIrZsfK+ralN0y999fwyRNFbS0TVt\r\nysKTdjjmhSS1Qdp9vD5oCB7jXpzRainnV3MVVvLN7QaXJzEXEHqg7uzjzYnZ\r\nta2tDEUqWMdLqbiiT0Ci6J3rZ9yaSGexsr8eNbV6uxdXaXBNbIznF+7TFOZR\r\nxZNJ2PcNQJBjriXvOv+wiVjiJ/TZ24K+ifIEEC4O7S3UFsXE0itZpW2Sa4eO\r\no10ALIwHsniF7Mvhal95oNSWn8d/8Tv3pJY5f+y0usKnaqdbqjyJbcqVnjnt\r\ndL2G5HgWL4ZaMjuGVhgUGUwMV/3enPSqWHOW9zwpHToqJrWDpMHzbP4esClD\r\nzIy1AHaAinYFqZ/QUcukjLEp8Swn+JTlkCcfWxx/zgnXFrQs4BfAnHbOQnsL\r\nvpoUmhNLOKFPVd+w5O9Dtgs21lR+dSpILsXOF3qNvQRAkfx5gDNhQPD2A4V3\r\nS+cGNIR5YBXOgV/MiRkxF70dJ4OKqdwEu5Hma9lrdZ91w7j9eEL3q7TIcTz1\r\nFk6wQ7eb/6kg0EmLWVa1NEaycpC1rehwaU3n824V/uahv52j7p8f70g+LkUp\r\n8eMg0zG77AWsiu05VJomSoQSqy3YO8ct7GfI+lnTvLRChep0IOOqMGeTYOfo\r\nc5YcH7sj7yOmelngiF9aPmcjW3Kqdac15ZM=\r\n=Zqay\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_1.6.1_1649667482398_0.779358757501708"},"_hasShrinkwrap":false},"2.0.0-next.9":{"name":"@reflet/express","version":"2.0.0-next.9","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: true` always sends the error with `res.json`.\n  \n* `sendAsJson: false` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `exposeInJson`\n\nBy default, Error `message` and `name` are not serialized to json.\n\nWith this option, you can either hide all error properties or expose some of them in the json response:\n\n- `true`: exposes all properties (stack included, beware of information leakage !), _default in development_.\n- `false`: exposes nothing (empty object), _default in production `NODE_ENV === 'production'`_.\n- array of strings: whitelists specifics properties.\n\nYou can pass a function with the status code as parameter for more conditional whitelisting:\n\n```ts\nfinalHandler({\n  sendAsJson: true,\n  exposeInJson(statusCode) {\n    // expose all properties in development\n    if (process.env !== 'production') return true\n\n    // expose only some properties of client errors in production\n    return statusCode < 500 ? ['message', 'data'] : false\n  }\n})\n```\n\n##### `log`\n\n* `log: true` always logs errors.\n* `log: false` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  sendAsJson: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.9","dist":{"shasum":"41174b013eb24f9c43fbe9348c9f33da858156e1","integrity":"sha512-GY3acm7Yr20iCGFx1/uiHCPctWyp5QqmQiaviXBou6qOUWfUZK2QBGg80CeYGkhF42iiFpW5BMfCma/w65pcDw==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.9.tgz","fileCount":22,"unpackedSize":129429,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHA2NmvLIIPI3duaLvN4Yz9mRM3NQUHksvR8mGZy1x8YAiAUca2D1lWtNx8qQuDhf3mVSC+Xh6lYNJ25aeCFC29TWg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJiVC71ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmppgw/+PmPn5m4vAauEXI7uQ0BAHLZOC64pt6YDPN1yqRCdFPwXlg+R\r\nWbWHq9Dq8WPdkicYXJ+VOWDHHTrd/k8xkf8qukiDJ8eaP4Sa4TguSD0d4LHO\r\nUJLJhhyMOhXZZtnj8qIu5aB5lJbzQve14H9geN+Ar4SKSKWk/zNaKM1pjzz2\r\nRbkb9zitmGlqAhOL+E6jZ2c/6xgs4A+xEi1R4l6pKDsdnQrvNqTSDr3rMRuH\r\ntLHx19sJ7TB1yMi3omsNKzrqz/14rJYSh9wakLqofVSNECimYKbbIDqdKC9P\r\n17Xhsfx0DWc3Wzfcyk9fr4z0lvabyVsbUH6v4PvPc/bP+dkAInHwYN2yJJMI\r\n+LzUsD+2rkin/t9uMqFCGXYnrYWn17emkV6UAYXuuSW5UMjXrRvcODeNkEde\r\nUz3hOIjxBwH6btb0Q3iEuHtdYZ0eovF3DcBXn7T3q2HsNOQZo9Hu1tpWpfl2\r\nxUwo5wPLZpGCgApc0sdDp9N2G0wIZSKGcgTmgGJ1Pnxx83q/uCst6d5Zd2TG\r\nTrXiIpJj98ho59nuB3YxRj8R2zqRJJ+UFchOvKw3aD/v32z5D5Z2bgftpTxj\r\niSyDsuJ9Zcs/xOuReXKYR9RtmwQ0tz0DKFzQDaqVJj5H5Znnz4tRjcn9lIQH\r\nHONhOgC16tNSvKvRh2c8Te73vYKgbxOQHqc=\r\n=Qqn6\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.9_1649684213789_0.8531871459714653"},"_hasShrinkwrap":false},"2.0.0-next.10":{"name":"@reflet/express","version":"2.0.0-next.10","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous `path` property:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooRouter {\n  constructor() {\n    register(this, [['/items', ItemRouter]])\n  }\n}\n\n@Router('/bar')\nclass BarRouter {\n  constructor() {\n    register(this, [['/elements', ItemRouter]])\n  }\n}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  sendAsJson: 'from-response-type',\n  log: '5xx',\n  notFoundHandler: true\n}))\n```\n\n##### `sendAsJson`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `sendAsJson: true` always sends the error with `res.json`.\n  \n* `sendAsJson: false` sends the error with `res.send` (default).\n\n* `sendAsJson: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `sendAsJson: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `exposeInJson`\n\nBy default, Error `message` and `name` are not serialized to json.\n\nWith this option, you can either hide all error properties or expose some of them in the json response:\n\n- `true`: exposes all properties (stack included, beware of information leakage !), _default in development_.\n- `false`: exposes nothing (empty object), _default in production `NODE_ENV === 'production'`_.\n- array of strings: whitelists specifics properties.\n\nYou can pass a function with the status code as parameter for more conditional whitelisting:\n\n```ts\nfinalHandler({\n  sendAsJson: true,\n  exposeInJson(statusCode) {\n    // expose all properties in development\n    if (process.env !== 'production') return true\n\n    // expose only some properties of client errors in production\n    return statusCode < 500 ? ['message', 'data'] : false\n  }\n})\n```\n\n##### `log`\n\n* `log: true` always logs errors.\n* `log: false` never logs errors (default).\n* `log: '5xx'` only logs server errors.\n\n##### `logger`\n\nBy default, errors are logged to `stderr` with `console.error`.\n\nYou can bind a custom logger like [winston](https://github.com/winstonjs/winston) or [pino](https://github.com/pinojs/pino):\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log: '5xx',\n  logger: logger.error, \n})\n```\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  sendAsJson: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.10","dist":{"shasum":"b4aebcc439abc1d891f1408a951d88202cd45848","integrity":"sha512-nY63Qsf24HkbCCuu8Au3XGqWJJteGdtPympu5UsdnrJncoQoqZ37ls1uObLum5/yPTdt1QF0IXW9SvjjxXuUDA==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.10.tgz","fileCount":22,"unpackedSize":129488,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDPT+UER0bn1yyRFufpywBtDPrCmkyIwVImb3/tQtY5PgIhAPNxSvG8MyFIigC/oe44/V/6+VrHqJvcWecf1Nc1U+8v"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJibvi0ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqATBAAlmoK3jATx6FPmsa9UCk2geg8pZH0Ys9UqrjvtlYjNQJATZU2\r\nLZFmY6HPHsX4wxtdOsxuNnKgoLQA91WGRDvV+gso9MP5NaX3V04T0Tz3aoEJ\r\noOkGPwM3qCINAQ+U81Sd3sOQSw7uB6CubUabTLiBX4ikzfljAhIji7xWgffq\r\nHtNRuxkAibXYqQjqWJRVbDM8yuVPxDnjx9fSWJ6E2IEegj+7N5ENF+CAp86w\r\np/tHAsHggGuDI6YOMcgUY2nqkc3CoJpZBmtsoKqmBists54LoWDwdNNnRrPI\r\nOMl8xfrvfYs+uCW3aIeD6idIFwT0C60LitPykR4wj9UfQN6kZZ10qjgrpwog\r\nyf+aN50tDP7TQb2cuPkAwqnySfJ93klbw6PNy4spdf0F9uyotpQgsx3QQMpU\r\n0/k9ulAceHXEQOF8U0NF+yCIA5+PkddlHZ11x8EVThMqz29dt3aqPfoXh9EW\r\nF0zUIUkqYidLNsKF7tYkhCSLguC8WF4bew+XEGojIswnYCqO+eAQ38h902Pw\r\nYYgsMPswHhDMPB6qwnYe6CZKBbP93iwFiOmtX9d8kJoCRvbTfcnKaogFewZK\r\ngJUFFFG+SzbNSy6IpstZpCK27CU7GTKaf2dJvfxBU9s6dRKNAmKdCeSVXa3o\r\nNUCYzxYcGQcH4MkhROz46SwpQY0Gkb5ntZc=\r\n=lbf2\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.10_1651439795894_0.9814461574574618"},"_hasShrinkwrap":false},"2.0.0-next.11":{"name":"@reflet/express","version":"2.0.0-next.11","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous path tuple:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\n@Router.Children(() => [['/items', ItemRouter]])\nclass FooRouter {}\n\n@Router('/bar')\n@Router.Children(() => [['/elements', ItemRouter]])\nclass BarRouter {}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  json: 'from-response-type',\n  log: '5xx',\n  notFoundHandler: true\n}))\n```\n\n##### `json`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `json: true` always sends the error with `res.json`.\n  \n* `json: false` passes the error to `next` to be handled by express final handler (default).\n\n* `json: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `json: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `expose`\n\nBy default, Error `message` and `name` are not serialized to json.\n\nWith this option, you can either hide all error properties or expose some of them in the serialized response:\n\n* `true`: exposes all properties (stack included, beware of information leakage !).\n* `false`: exposes nothing (empty object).\n* `string[]`: whitelists specifics properties.\n* `(status) => boolean | string[]`: function for more conditional whitelisting:\n\n```ts\nfinalHandler({\n  json: true,\n  expose(status) {\n    // expose all properties in non production environment\n    if (process.env !== 'production') {\n      return true\n    }\n\n    // expose only some properties of client errors in production\n    if (status < 500) {\n      return ['message', 'code', 'data']\n    } else {\n      return false\n    }\n  }\n})\n```\n\n##### `log`\n\n* `log: true` always logs errors (with `console.error`).\n* `log: false` never logs errors, _default_.\n* `log: '5xx'` only logs server errors (with `console.error`).\n* If you need the flexibility to log more infos or use a dedicated logger other that `console.error`, you can pass a function like so:\n\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log(err, req, res) {\n    logger.error({\n      err,\n      status: res.statusCode,\n      path: req.url,\n      timestamp: new Date().toISOString(),\n    })\n  },\n})\n```\n\n_The response object type only exposes safe properties, so you don't send the response by accident._\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: <number>` defines the same default handler, with a custom status code.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  json: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.11","dist":{"shasum":"2f67f203b577199c62bc202aa297f9a03ef0190f","integrity":"sha512-HjfxoP63TA9e/Uktk83Q3lhIUxiRHoHB2M6vI8Tna0iNO1vIRbSzhSL4lGPhCWVaebsOw1Gh6x8WnnUMqFv8gw==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.11.tgz","fileCount":22,"unpackedSize":131025,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQDx4DT6CaS0isypXaUepEUAqGbN+dMgrgH3guwLGyy3qAIhALDBNpSpr3fDCd9DI8iVso1YN9XX6Y7Itxy+wtKMSlxq"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJil7xaACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrE8Q//cOkrrYIsW5Qv2UmB5zRFajHi5eQJ6YSQbpzQgpOBfkHbEHh2\r\n7QGIYIm1fjO1+8TwMbYIfQampjsM2YRxMvA+9jiu7gwb5uK0LyDaj2kr+hEz\r\nMRh8OueVHTA9bH+Fj8ggsKqJ7xIzZItHPgy5Bq+j1ZAHxNi2+vB+ofGApcPs\r\nKDRJtkBvB7kuKyPRMGYjxPD7jKAk1AcNQJRMhhbyzqPmVzoJJoT6TKa+7FuI\r\n9NVm2HMvu2VUlVCP5jLeTzsuwTpvULT2DujmNgIXCPvbQypE5s4w+qY6oxam\r\n6m0gU4n5PLPil+LnYtwmY/0KjhNk2VBr7DhdueuxVZSGElNiADPUy2b7l+M+\r\nwmc/dbmqCgjiZvYs3+Msn2SWmyfC2QAO0GBj6dzZPU6I/CxOBsxb+lA9/q4Y\r\nFZJUgoAzSJMo2K6sINPsc+R4tQm+Ul67FfiNUqsGLoclL4O5rxf1/FH1eJ8c\r\nGbmnkq5VJ01AEf6x80QDNdSjyPb2ncP1ZrLJDPPzlHeHaMWyMAdwTIUMuBE+\r\nU33YLuRgRVz6fMley74SdwEEXrqhAl27mLQsWJYrap1HrI2xWeOAyML1RJPU\r\n1NMa+vLqm917Bk1iYykPf8UQXhh9Wk5R6sOMLzVBA5xbMd2bEsfVI+OWuEQl\r\nfRHndx4a249Cxra0xXT7CTSPl8LTJBTk6E8=\r\n=XXbR\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.11_1654111322652_0.3878747393313562"},"_hasShrinkwrap":false},"2.0.0-next.12":{"name":"@reflet/express","version":"2.0.0-next.12","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous path tuple:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\n@Router.Children(() => [['/items', ItemRouter]])\nclass FooRouter {}\n\n@Router('/bar')\n@Router.Children(() => [['/elements', ItemRouter]])\nclass BarRouter {}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nBy the way, you can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Change response status\n\n> 🔦 `@Send({ status: XXX, undefinedStatus: XXX, nullStatus: XXX })`<br>\n> 💫 Related Express method: [`res.status`](https://expressjs.com/en/4x/api.html#res.status)\n\nBy default in Node.js, HTTP response status code is set to `200`. To set another code:\n\n```ts\n@Send({ status: 201 })\n@Post('/me')\ncreate() {\n  return { name: 'Jeremy' } // 201 status\n}\n```\n\nYou can conditionaly set status for `undefined` and `null` values:\n\n```ts\n@Send({ nullStatus: 205, undefinedStatus: 404 })\n@Get('/things')\nlist() {\n  if (conditionA) return // 404 status\n  if (conditionB) return null // 205 status\n  return {} // 200 status\n}\n```\n\n##### 💡 Tip\n\nUse **[`SuccessStatus` enum](../http/README.md#status-)**  from `@reflet/http` for an even better developer experience.\n\n### Share and override\n\nDecorate classes with specific `Send` options so they act as a base for methods' `Send` options.\n\n```ts\n@Send({ json: true, status: 100 })\nclass PeopleRouter {\n  @Send({ status: 200 }) // extends class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // 200 status, Content-Type: 'application/json'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  json: 'from-response-type',\n  log: '5xx',\n  notFoundHandler: true\n}))\n```\n\n##### `json`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `json: true` always sends the error with `res.json`.\n  \n* `json: false` passes the error to `next` to be handled by express final handler (default).\n\n* `json: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `json: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `expose`\n\nBy default, Error `message` and `name` are not serialized to json.\n\nWith this option, you can either hide all error properties or expose some of them in the serialized response:\n\n* `true`: exposes all properties (stack included, beware of information leakage !).\n* `false`: exposes nothing (empty object).\n* `string[]`: whitelists specifics properties.\n* `(status) => boolean | string[]`: function for more conditional whitelisting:\n\n```ts\nfinalHandler({\n  json: true,\n  expose(status) {\n    // expose all properties in non production environment\n    if (process.env !== 'production') {\n      return true\n    }\n\n    // expose only some properties of client errors in production\n    if (status < 500) {\n      return ['message', 'code', 'data']\n    } else {\n      return false\n    }\n  }\n})\n```\n\n##### `log`\n\n* `log: true` always logs errors (with `console.error`).\n* `log: false` never logs errors, _default_.\n* `log: '5xx'` only logs server errors (with `console.error`).\n* If you need the flexibility to log more infos or use a dedicated logger other that `console.error`, you can pass a function like so:\n\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log(err, req, res) {\n    logger.error({\n      err,\n      status: res.statusCode,\n      path: req.url,\n      timestamp: new Date().toISOString(),\n    })\n  },\n})\n```\n\n_The response object type only exposes safe properties, so you don't send the response by accident._\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: <number>` defines the same default handler, with a custom status code.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  json: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.12","dist":{"shasum":"26fa212df3868055327848f7c027cdeb1a7eadd6","integrity":"sha512-xGy+7eGKvFQWkRuNIigyGjoFzDd8jgH9ptiC5qo1rxjSkoDJgCSSh2PYiRfnl3xwR7ZnnKQxB8hkc2YDrsSAhw==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.12.tgz","fileCount":22,"unpackedSize":130737,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD+zCLsLLUKJG1c3pPe81sskRYZz6Kt1J7TZSTeRiwPOgIhAMKTWTTeeuKOTz+SCELk4V8udIj4IwHKqZMPN2Eulr0/"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJil762ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrHrw/+NykX77vvKijBHlPsf5B2ewoMA2e3ZcG024igJrcZes7ixPQB\r\nG6U67ecSG/8NIEbV5iNusIvmt9TR1Hv9ByVJGAOZq1yQK8yYC3r3XOO1XuLi\r\nmi++r7PrAkvaxW0ST6f7qgYNEeuL4nYXk9E7ib/truXL/6V8+OuRn1Wt45zo\r\n+3ac0/Izmir0kjjUAnDhpVDDJUdeQQhq2+aSdEtkxiZeihaVmsAtUitSUWlY\r\nP5tT5UIoMJdTWiXimrq1Lt7NJnuBZBY0w5aGrGiv4fg/pwT4Hp6nNMthqKA4\r\nnaVPMhP8PNj/Vo2qUAWptYGRTv9AE3AaXkAoP9zDLJDThypaf9c2V/m0OWOM\r\nQwx+5H9LKFy3VRIqExHm2WsgB+RMwJCzUh/n51YLDMxuGPNORzWTH+eCM9g6\r\nge2y3bRvEnW7RfwARn6Nj0/yCNrq3Uo9ustKijuwZhbY52aI8v2vkIupUgNT\r\ndSUT7gHi0Q3uOkU0qTMzCQ/fGPhEEuBCLfgonnc33E3t7LuOoaV/0rNidCts\r\nFpeUpWOBI+bbGLHdckTW6WWTiu3s/RDfmoo1R/ckRSi5eiBjsH6XQRvsB3m1\r\neS/W4bh60QgPQdO9D6bZY989eYuFp9bmWEFbIBdB9P1Y59fjMxj7GOFgMvT7\r\nMpbKA6X9cZq4EuHX34gsCca+zAxehkWBvLE=\r\n=k+Eh\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.12_1654111926335_0.8069116619567849"},"_hasShrinkwrap":false},"2.0.0-next.13":{"name":"@reflet/express","version":"2.0.0-next.13","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"https://github.com/jeremyben/reflet/tree/master/express"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0-next.1","@types/express":"^4.17.0","@types/node":">=10","express":"^4.17.0","reflect-metadata":"^0.1.13"},"devDependencies":{"@reflet/http":"^1.0.0-next.2","@types/express":"^4.17.13","express":"^4.17.3"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"readmeFilename":"README.MD","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. <details>\n    <summary>Make sure you have decorators enabled. (click for details)</summary>\n    <p>\n\n    * Enable them in your TypeScript compiler options.\n\n        ```json\n        \"experimentalDecorators\": true,\n        ```\n\n    * Install `reflect-metadata` shim.\n\n        ```sh\n        yarn add reflect-metadata\n        ```\n\n    * Import the shim in your program before everything else.\n\n        ```ts\n        import 'reflect-metadata'\n        ```\n\n    </p>\n    </details>\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    yarn add @reflet/express @reflet/http express\n    yarn add -D @types/express @types/node\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import 'reflect-metadata'\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous path tuple:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\n@Router.Children(() => [['/items', ItemRouter]])\nclass FooRouter {}\n\n@Router('/bar')\n@Router.Children(() => [['/elements', ItemRouter]])\nclass BarRouter {}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nYou can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Custom handler\n\n```ts\n@Send<string>((data, { res }) => {\n  res.json({ name: data })\n})\n@Get('/me')\nget() {\n  return 'Jeremy' \n}\n```\n\n### Share and override\n\nDecorate a class with `Send` to apply its behavior to all its methods. You override the behavior on a method level.\n\n```ts\n@Send({ json: true })\nclass PeopleRouter {\n  @Send({ json: false }) // override class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // Content-Type: 'text/html'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  json: 'from-response-type',\n  log: '5xx',\n  notFoundHandler: true\n}))\n```\n\n##### `json`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `json: true` always sends the error with `res.json`.\n  \n* `json: false` passes the error to `next` to be handled by express final handler (default).\n\n* `json: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `json: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `expose`\n\nBy default, Error `message` and `name` are not serialized to json.\n\nWith this option, you can either hide all error properties or expose some of them in the serialized response:\n\n* `true`: exposes all properties (stack included, beware of information leakage !).\n* `false`: exposes nothing (empty object).\n* `string[]`: whitelists specifics properties.\n* `(status) => boolean | string[]`: function for more conditional whitelisting:\n\n```ts\nfinalHandler({\n  json: true,\n  expose(status) {\n    // expose all properties in non production environment\n    if (process.env !== 'production') {\n      return true\n    }\n\n    // expose only some properties of client errors in production\n    if (status < 500) {\n      return ['message', 'code', 'data']\n    } else {\n      return false\n    }\n  }\n})\n```\n\n##### `log`\n\n* `log: true` always logs errors (with `console.error`).\n* `log: false` never logs errors, _default_.\n* `log: '5xx'` only logs server errors (with `console.error`).\n* If you need the flexibility to log more infos or use a dedicated logger other that `console.error`, you can pass a function like so:\n\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log(err, req, res) {\n    logger.error({\n      err,\n      status: res.statusCode,\n      path: req.url,\n      timestamp: new Date().toISOString(),\n    })\n  },\n})\n```\n\n_The response object type only exposes safe properties, so you don't send the response by accident._\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: <number>` defines the same default handler, with a custom status code.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  json: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","licenseText":"MIT License\n\nCopyright (c) 2019 Jeremy Bensimon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n","_id":"@reflet/express@2.0.0-next.13","dist":{"shasum":"cf386f61fbe3edb44bd91527572e9068a7f3acda","integrity":"sha512-JuiJ/xdt35owat3Xxg64VX6h4XkyjKjADp/ar6UpISSxdIOqPYzR1Nrsuee1hZSttceIe8sjb1gsJceKQmP7ug==","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0-next.13.tgz","fileCount":22,"unpackedSize":130017,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGLsUPmJAG47xccELfK7w1DVNLsbEScxpQfBOgx7uDbXAiBzW6zkeWTOWrOmo9UDxmTJCXIuDtnT1QAB9rdH7Y8Zcw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJisMUHACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoTbw/9EjUXkrRrhDbw38SQ0VCyIBRZd3uji9LcRnrV+Kymu6zsbRsu\r\n7SCHIkJ1C9rlTmDOo9K7YYgI6IYeVFDitNWnwlw58E1m7R3lYfyWK/cIuTQ/\r\ngU30X0nNiCcBZdxSEmweMdEn8kEB+In0E8j9heLX3zpLURPA7itHhEsKfjcL\r\nI/HBjMeebBNKWGXpiPFlVeLLNaLLZ9Y/oJ0yL5IHUUCwGGvuCUouzR9z2T3p\r\ncZ8I0sULu24pcgaa0EOb4y6rYB650HB5oK0Ra15cCYJbLlictGyqZWEasbO/\r\nab5s21EFqbTQ+s/66y6uGwBzl0Z+spMOPbrNtCI1GWa7J/FPus2awvbgUgce\r\n71Q0Ebw/upLxnRApjAJRrlW8bCBR0HGRUrMH+5jrXoQ/Ivm3CsqwUDfkB2w4\r\no876vwsDSm+Q3YhfZ+hKlri1pTq7Zdo8l0zyknnWxOXYVbGfX37eh45C35p5\r\ndmkyw4LDE5RdYoVP+C2kQXKwW73J4c/P1tS6NCsiDPugyuo48gG5oRM5MFzJ\r\nFA8Ekt/ZDIExlyKBm5L+a4LocsbdgnqVYbXvFEpp1EKv4HzioWOnTTVskR5J\r\nHNaNZThEq3KEITQ/foY9rAwMzrM+9+FzF6o8uCj2cOckv0fdGFktgbcRM+MA\r\napFySp5JcMNnVvd1i7Bi53QcQC9P1LwN6Zk=\r\n=H/k+\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0-next.13_1655751943439_0.8976442808545291"},"_hasShrinkwrap":false},"2.0.0":{"name":"@reflet/express","version":"2.0.0","author":{"name":"Jeremy Bensimon"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/jeremyben/reflet.git#master"},"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"main":"dist/index.js","types":"dist/index.d.ts","publishConfig":{"access":"public"},"engines":{"node":">=10"},"engineStrict":true,"peerDependencies":{"@reflet/http":"^1.0.0","@types/express":"^4.17.0","express":"^4.17.0"},"devDependencies":{"@reflet/http":"^1.0.0","@types/express":"^4.17.17","express":"^4.18.2"},"scripts":{"build":"ts-node -T ../build.ts","test":"jest --config ../jest.config.js","test:watch":"yarn test --watch --verbose false","test:file":"yarn test --testPathPattern","preversion":"yarn test --coverage && ts-node -T ../testing/summary.ts && git add coverage-summary.json","prepublishOnly":"yarn run build","publish:next":"yarn publish --tag next"},"gitHead":"e8c4725ae9051728c87ceddef5cd031c0b65b7e2","bugs":{"url":"https://github.com/jeremyben/reflet/issues"},"homepage":"https://github.com/jeremyben/reflet/tree/master#readme","_id":"@reflet/express@2.0.0","_nodeVersion":"18.14.2","_npmVersion":"lerna/7.1.4/node@v18.14.2+x64 (win32)","dist":{"integrity":"sha512-cscENtZb6YZtouO+b5VyGd3oUd14JT+zikULggxLBsISXjG0poHs65qHG6s3mV6MRmZZ4bkwGln0MCt/XpxIKw==","shasum":"e117e3bff7029d8f53f111318b57e3cdfe7dd893","tarball":"https://registry.npmjs.org/@reflet/express/-/express-2.0.0.tgz","fileCount":21,"unpackedSize":130128,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBASxvIQAZEd4hmz46tBTAIGjbTk4OVksER9VnFXr6zuAiEAhVpbzAWRy+Jx4t8XZ6myybwArADtqEN/dKB5r9J7Cc8="}]},"_npmUser":{"name":"jeben","email":"bensimon.jeremy@gmail.com"},"directories":{},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/express_2.0.0_1690745441801_0.7321515195313162"},"_hasShrinkwrap":false}},"time":{"created":"2019-10-03T11:34:31.286Z","1.0.0":"2019-10-03T11:34:32.231Z","modified":"2023-07-30T19:30:42.072Z","1.1.0":"2020-04-07T09:57:45.156Z","1.2.0":"2020-04-23T12:15:24.733Z","1.3.0":"2020-04-26T14:54:06.912Z","1.3.1":"2020-04-28T17:28:47.694Z","1.3.2":"2020-05-24T22:55:51.110Z","1.4.0":"2020-12-20T21:01:43.935Z","1.5.0":"2021-01-05T16:24:11.639Z","1.5.1":"2021-01-05T16:30:04.538Z","1.5.2":"2021-02-12T16:27:39.962Z","1.5.3":"2021-02-18T15:34:46.864Z","1.6.0":"2021-08-05T22:45:46.543Z","2.0.0-next.0":"2021-10-04T22:35:39.804Z","2.0.0-next.1":"2021-11-11T17:12:54.122Z","2.0.0-next.2":"2021-11-12T18:35:38.462Z","2.0.0-next.3":"2021-11-14T21:29:44.120Z","2.0.0-next.4":"2021-12-06T14:05:37.994Z","2.0.0-next.5":"2022-01-13T11:59:57.679Z","2.0.0-next.6":"2022-03-02T17:26:05.652Z","2.0.0-next.7":"2022-03-02T22:41:02.251Z","2.0.0-next.8":"2022-03-03T13:29:42.143Z","1.6.1":"2022-04-11T08:58:02.508Z","2.0.0-next.9":"2022-04-11T13:36:53.941Z","2.0.0-next.10":"2022-05-01T21:16:36.046Z","2.0.0-next.11":"2022-06-01T19:22:02.852Z","2.0.0-next.12":"2022-06-01T19:32:06.480Z","2.0.0-next.13":"2022-06-20T19:05:43.682Z","2.0.0":"2023-07-30T19:30:41.967Z"},"maintainers":[{"name":"jeben","email":"bensimon.jeremy@gmail.com"}],"description":"Well-defined and well-typed express decorators","keywords":["express","decorators","typescript","framework","router","app"],"repository":{"type":"git","url":"git+https://github.com/jeremyben/reflet.git#master"},"author":{"name":"Jeremy Bensimon"},"license":"MIT","readme":"# `@reflet/express` 🌠\n\n[![lines coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=lines&query=total.lines.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![statements coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=statements&query=total.statements.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![functions coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=functions&query=total.functions.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n[![branches coverage](https://img.shields.io/badge/dynamic/json?url=https://raw.githubusercontent.com/jeremyben/reflet/master/express/coverage-summary.json&label=branches&query=total.branches.pct&color=brightgreen&suffix=%&logo=jest)](./coverage-summary.json)\n\n> [!IMPORTANT]  \n> Upgrade from **v1** to **v2** : [Migration guide](../express/MIGRATION.md)\n\nThe **best** decorators for [Express](https://expressjs.com/). Have a look at [Reflet's philosophy](../README.MD#Philosophy-).\n\n* [Getting started](#getting-started)\n* [Routing](#routing)\n* [Middlewares](#middlewares)\n* [Request properties injection](#request-properties-injection)\n* [Sending return value](#sending-return-value)\n* [Error handling](#error-handling)\n* [Application class](#application-class)\n* [Pure dependency injection](#pure-dependency-injection)\n\n## Getting started\n\n1. Enable experimental decorators in TypeScript compiler options.<br>_No need to install \"reflect-metadata\"._\n\n    ```json\n    \"experimentalDecorators\": true,\n    ```\n\n2. Install the package along with peer dependencies.\n\n    ```sh\n    npm i @reflet/express @reflet/http express\n    npm i -D @types/express\n    ```\n\n3. Create your decorated routing routers.\n\n    ```ts\n    // thing.router.ts\n    import { Get, Post, Res, Params, Body, Router } from '@reflet/express'\n\n    @Router('/things')\n    export class ThingRouter {\n      @Get()\n      async list(@Res res: Response) {\n        const things = await db.collection('things').find({})\n        res.send(things)\n      }\n\n      @Get('/:id')\n      async get(@Params('id') id: string, @Res res: Response) {\n        const thing = await db.collection('things').find({ id })\n        res.send(thing)\n      }\n\n      @Post()\n      async create(@Res res: Response, @Body body: Thing) {\n        const newThing = await db.collection('things').insertOne(body)\n        res.status(201).send(newThing)\n      }\n    }\n    ```\n\n4. Register them on your Express application.\n\n    ```ts\n    // server.ts\n    import express from 'express'\n    import { register } from '@reflet/express'\n    import { ThingRouter } from './thing.router.ts'\n\n    const app = express()\n    app.use(someGlobalMiddleware)\n\n    register(app, [ThingRouter, /*...*/])\n\n    app.listen(3000)\n    ```\n\n### The Express way\n\n> 🔦 `register(app, [routers])`\n\nAs you can see, the main method `register` simply accepts an Express app and an array of your classes.\n\nYou still apply your global middlewares and start your server in the Express way you already know. This means you can progressively add Reflet to your existing app. 😉\n\nIf you have a more complex bootstraping, reflet allows you to inherit the express original application with [Application class](#application-class).\n\n## Routing\n\nTo handle requests with a class, let's call it a router (or a controller if you prefer), you simply have to decorate its methods with route decorators.\n\n### Common route decorators\n\n> 🔦 `@Get(path)`, `@Post(path)`, `@Patch(path)`, `@Put(path)`, `@Delete(path)`<br>\n> 💫 Related Express methods: [`app.get`](https://expressjs.com/en/4x/api.html#app.get.method), [`app.post`](https://expressjs.com/en/4x/api.html#app.post.method), [`app.put`](https://expressjs.com/en/4x/api.html#app.put.method), [`app.delete`](https://expressjs.com/en/4x/api.html#app.delete.method)\n\nReflet directly exposes common route decorators handling the majority of routing use cases.\nHere is a comparaison of Reflet and plain Express for basic requests:\n\n<table>\n<thead>\n<tr>\n  <th>HTTP request</th>\n  <th>Reflet</th>\n  <th>Express</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```http\nGET http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Get('/foo')\nget(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPOST http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Post('/foo')\ncreate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.post('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPATCH http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Patch('/foo')\nupdate(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.patch('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nPUT http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Put('/foo')\nreplace(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.put('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```http\nDELETE http://host/foo\n```\n\n  </td>\n  <td>\n\n```ts\n@Delete('/foo')\nremove(req, res, next) {}\n```\n\n  </td>\n  <td>\n\n```ts\napp.delete('/foo', (req, res, next) => {})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\nPretty obvious, like any other decorator framework.\n\n#### Other route decorators\n\n> 🔦 `@Route(method, path)`<br>\n> 💫 Related Express methods: [`app.METHOD`](https://expressjs.com/en/4x/api.html#app.METHOD), [`app.all`](https://expressjs.com/en/4x/api.html#app.all)\n\nCommon route decorators are created from `Route`, a decorator in itself, that can be used to create a route decorator for any other [routing method](https://expressjs.com/en/4x/api.html#routing-methods) supported by Express (plus the [`all` method](https://expressjs.com/en/4x/api.html#app.all)).\n\nAs a convenience, `Route` is also a namespace that gives access to all route decorators as its properties.\n\n```ts\nconst Options = (path?: string | RegExp) => Route('options', path)\n\n@Router('/')\nclass ThingRouter {\n  @Options('/things')\n  opts(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.All('/things')\n  all(req: Request, res: Response, next: NextFunction) {}\n\n  @Route.Get('/things')\n  get(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n#### Handler with multiple verbs\n\nYou can share the same handler with multiple HTTP verbs, by passing an array to `Route`.\n\n```ts\nconst Patch_Put = (path: string | RegExp) => Route(['patch', 'put'], path)\n\nclass ThingRouter {\n  @Patch_Put('/things/:id')\n  update(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Router\n\n> 🔦 `@Router(path, options?)`<br>\n> 💫 Related Express method: [`express.Router`](https://expressjs.com/en/4x/api.html#express.router)\n\nYou then attach routes to an Express [Router](https://expressjs.com/en/4x/api.html#router), so they can share a root path, just like with plain Express.\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n\n  @Get('/:id')\n  get(req: Request, res: Response, next: NextFunction) {}\n\n  @Post('/:id')\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\nExpress [Router options](https://expressjs.com/en/4x/api.html#express.router) can be defined as a second argument:\n\n```ts\n@Router('/things', { strict: true, caseSensitive: true })\n```\n\n🗣️ Beware of VSCode auto-import, it will first try to import `Router` from Express instead of Reflet.\n\n#### Nested routers\n\n> 🔦 `@Router.Children(register)`\n\nYou can register child routers with the dedicated decorator `Router.Children`:\n\n```ts\n@Router('/album')\n@Router.Children(() => [TrackRouter])\nclass AlbumRouter {}\n\n@Router('/:albumId/track', { mergeParams: true })\nclass TrackRouter {}\n```\n\n#### Paths centralization and constraint\n\nYou might want the root paths of your routers to be centralized as well, so you can have a glance at all of them. 👀<br>You can register your routers as a tuple with a path constraint (Reflet will enforce those paths):\n\n```ts\n@Router('/foo')\nclass Foo {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nregister(app, [['/foo', Foo]])\n```\n\n_Also possible with child routers._\n\n##### Plain express routers\n\nTo be able to progressively switch to Reflet, you can still register your plain express routers, with the help of the previous path tuple:\n\n```ts\n@Router('/decorated')\nclass Decorated {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\nconst plain = express.Router().get('', (req, res, next) => {})\n\nregister(app, [\n  ['/decorated', Decorated],\n  ['/plain', plain]\n])\n```\n\n_Also possible with child routers._\n\n#### Dynamic nested routers\n\n> 🔦 `Router.Dynamic(options?)`\n\nA dynamic router is a router without a predefined path. Its path is then defined at registration.\n\nUseful if you need to share a child router with multiple parents, and attach it on different paths.\n\n```ts\n@Router.Dynamic()\nclass ItemRouter {\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\n@Router.Children(() => [['/items', ItemRouter]])\nclass FooRouter {}\n\n@Router('/bar')\n@Router.Children(() => [['/elements', ItemRouter]])\nclass BarRouter {}\n```\n\n### Handler parameters injection\n\n> 🔦 `@Req`, `@Res`, `@Next`<br>\n> 💫 Related Express objects: [`req`](https://expressjs.com/en/4x/api.html#req), [`res`](https://expressjs.com/en/4x/api.html#res)\n\nYou can inject the handler parameters in any order by applying dedicated parameter decorators:\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Res res: Res, @Next next: Next) {\n    res.send('done')\n  }\n\n  @Post()\n  create(@Res() res: Res, @Req() req: Req) {\n    res.json(req.body)\n  }\n}\n```\n\nYou can apply them **with or without invokation**, how flexible is that. 😉\n\nThe decorators when used as types, are convenient references to express interfaces (so you don't need to import them).\n\nLooking for other decorators like `@Body` ? [Request properties injection](#request-properties-injection).\n\n### Async support\n\nAsync functions (routes and middlewares) are properly wrapped to pass errors on to `next` and to the express error handling system.\n\n```ts\nclass ThingRouter {\n  @Get('/thing')\n  async get() {\n    await Promise.reject('oops') // properly handled by next callback: next('oops')\n  }\n}\n```\n\n## Middlewares\n\n> 🔦 `@Use(...middlewares)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\nApply middlewares on specific routes or whole routers:\n\n```ts\n@Use(express.json(), express.urlencoded())\n@Use(cors())\n@Router('/things')\nclass ThingRouter {\n  @Use((req, res, next) => next())\n  @Get()\n  list() {}\n}\n```\n\n`Use` is highly versatile, like the underlying `app.use` method. You can pass **as many** middlewares as you want inside a `Use` decorator, and you can apply **as many** `Use` decorators as you want on a single class or method.\n\nReflet respects Express flow and will apply class-scoped middlewares to the newly created Express Router:\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Use(A)\n@Use(B, C)\n@Router('/foo')\nclass Foo {\n  @Use(D)\n  @Get()\n  get(req, res, next) {}\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.use(A, B, C)\nrouter.get('', D, (req, res, next) => {})\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n##### About order\n\nSuccessive `Use` will be applied in the order they are written, even though decorator functions in JS are executed in a bottom-up way (due to their _wrapping_ nature).\n\n### Scoped router middlewares\n\n> 🔦 `@ScopedMiddlewares`\n\nExpress does not isolate middlewares of routers that share the same path ([related issue](https://github.com/expressjs/express/issues/2760)).\n\nIf you wish to circumvent this default behavior, add `ScopedMiddlewares` decorator to a router, to scope its middlewares (and its error handlers) to its routes only.\n\n```ts\n@Router('/foo')\n@ScopedMiddlewares\n@Use(authenticate)\nclass FooSecret {\n  @Get()\n  getSecret(req: Request, res: Response, next: NextFunction) {}\n}\n\n@Router('/foo')\nclass FooPublic {\n  @Get()\n  getPublic(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n### Create your own middleware decorator 🔧\n\nThe versatility of `Use` allows for powerful extension.\n\n```ts\nfunction UseStatus(statusCode: number) {\n  return Use((req, res, next) => {\n    res.status(statusCode)\n    next()\n  })\n}\n\n@Router('/things')\nclass ThingRouter {\n  @UseStatus(201)\n  @Post()\n  create(req: Request, res: Response, next: NextFunction) {}\n}\n```\n\n🗣️ As a naming convention, custom middleware decorators' name should begin with `Use`.\n\n### Little extra 🧩\n\nBefore you go and copy the code above... Reflet makes full use of, well, `Use` and provides an add-on module for convenient middleware decorators: **[Reflet/express-middlewares](../express-middlewares)**\n\nHere's a list of them:\n\n* `UseGuards` for request authorization handling.\n* `UseInterceptor` for response body manipulation.\n* `UseOnFinish` for response side effects.\n* `UseStatus` for response status.\n* `UseSet` for response headers.\n* `UseType` for response content-type.\n* `UseIf` for conditional middlewares.\n\nConvinced yet ? Go over to [the doc](../express-middlewares/README.MD).\n\n## Request properties injection\n\nDirectly inject Request properties (and even their sub-properties) in handler parameters. Just like with `Req`, `Res` or `Next`, **invokation is optional**.\n\n### Route params\n\n> 🔦 `@Params(name?)`<br>\n> 💫 Related Express object: [`req.params`](https://expressjs.com/en/4x/api.html#req.params)\n\n```ts\nclass UserRouter {\n  // Whole params object\n  @Get('/users/:userId/things/:thingId')\n  get(@Params params: Params<'userId' | 'thingId'>) {}\n\n  // Specific name\n  @Get('/users/:userId/things/:thingId')\n  get(@Params('userId') userId: string, @Params('thingId') thingId: string) {}\n}\n```\n\n### Query string\n\n> 🔦 `@Query(field?)`<br>\n> 💫 Related Express object: [`req.query`](https://expressjs.com/en/4x/api.html#req.query)\n\nGiven the request: `GET http://host/things?size=large&color=green`\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole query object\n  @Get()\n  list(@Query query: Query) {}\n\n  // Specific field\n  @Get()\n  list(@Query('size') size?: string, @Query('color') color?: string) {}\n}\n```\n\n### Request body\n\n> 🔦 `@Body(key?)`<br>\n> 💫 Related Express object: [`req.body`](https://expressjs.com/en/4x/api.html#req.body)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole body\n  @Patch('/:id')\n  update(@Body body: Partial<Thing>) {}\n\n  // Specific key\n  @Patch('/:id')\n  update(@Body<Thing>('name') name: string) {}\n}\n```\n\n`Body` will automatically apply the following Express body parsers on the routes using it:\n\n* `express.json()`\n* `express.urlencoded({ extended: true })`\n\nYou can `Use` the same body parsers (or apply them globally on your app) with different options and they will take precedence:\n\n```ts\n@Use(express.json({ limit: '500kb' }))\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@Body body: Thing) {} // default jsonParser won't be applied again here.\n}\n```\n\n### Request headers\n\n> 🔦 `@Headers(header?)`<br>\n> 💫 Related Node.js object: [`req.headers`](https://nodejs.org/api/http.html#http_message_headers)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  // Whole headers object\n  @Get()\n  list(@Headers headers: Headers) {}\n  \n  // Specific header\n  @Get()\n  list(@Headers('user-agent') userAgent: string) {}\n}\n```\n\n`Header` input type is narrowed to a union of known **request headers** (instead of just `string`), so typos are prevented and you have that sweet auto-completion.\n\nAugment the union with the help of the global namespace `RefletHttp`:\n\n```ts\ndeclare global {\n  namespace RefletHttp {\n    interface RequestHeader {\n      XCustom: 'x-custom'\n    }\n  }\n}\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@Headers('x-custom') custom: string) {}\n}\n```\n\nUse **[`RequestHeader` enum](../http/README.md#header-)** from `@reflet/http` for better discoverability and documentation.\n\n### Create your own parameter decorator 🔧\n\n> 🔦 `createParamDecorator(requestMapper, [middlewares]?, deduplicateMiddlewares?)`\n\nInject and manipulate whatever you need from the Request object:\n\n```ts\nconst CurrentUser = createParamDecorator((req) => req.user)\n\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\n#### Add implicit middlewares\n\nIf your decorator needs any middleware, to work **as is**, Reflet got you covered:\n\n```ts\nconst isAuthenticated: RequestHandler = (req, res, next) => {\n  // validate and attach user to req...\n  next()\n}\n\nconst CurrentUser = createParamDecorator((req) => req.user, [isAuthenticated])\n```\n\nNow what if this implicit middleware is already applied explicitely before ? You might not want it to be executed twice:\n\n```ts\n@Use(isAuthenticated)\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list(@CurrentUser user: User) {}\n}\n```\n\nYou can mark your custom decorator's middlewares for **deduplication**:\n\n```ts\nconst CurrentUser = createParamDecorator(\n  (req) => req.user, \n  [{ handler: isAuthenticated, dedupe: true }]\n)\n```\n\nWith these options, on registering, Reflet won't add the implicit middlewares if they're already applied locally (on a route or router) or globally (on the app). \n\nComparison to deduplicate is done:\n* by function reference with `dedupe: 'by-reference'`\n* by function name with `dedupe: 'by-name'`\n* by both function reference and name with `dedupe: true`\n\nThat's basically how the `Body` decorator works with its body parsers.\n\nThis mecanism is really powerful 🦾 and allows your custom decorator to be decoupled yet still integrate nicely within any router.\n\n#### Example with input\n\n```ts\nconst BodyTrimmed = (key: string) => createParamDecorator(\n  (req) => {\n    if (typeof req.body[key] === 'string') return req.body[key].trim()\n    else return req.body[key]\n  },\n  [\n    { handler: express.json(), dedupe: true },\n    { handler: express.urlencoded(), dedupe: true },\n  ]\n)\n\n@Router('/things')\nclass ThingRouter {\n  @Post()\n  create(@BodyTrimmed('name') name: string) {}\n}\n```\n\n## Sending return value\n\n> 🔦 `@Send(options?)`<br>\n> 💫 Related Express method: [`res.send`](https://expressjs.com/en/4x/api.html#res.send)\n\nYou want your methods' return value to be handled for you ?<br>Then simply tell Reflet to `Send` it.\n\n```ts\n@Send()\n@Get('/me')\nget() {\n  return { name: 'Jeremy' }\n}\n```\n\nYou can still use the Response object to send your data, and Reflet will figure that it has already been sent. 😉\n\n### Async and stream support\n\n* Promises are resolved before being sent.\n* Readable streams are piped into the response.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return Promise.resolve('done')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  Promise.resolve('done').then(value => res.send(value))\n})\n```\n\n  </td>\n</tr>\n<tr>\n  <td>\n\n```ts\n@Send()\n@Get('/')\nget() {\n  return createReadStream('path/to/file')\n}\n```\n\n  </td>\n  <td>\n\n```ts\napp.get('/', (req, res, next) => {\n  createReadStream('path/to/file').pipe(res)\n})\n```\n\n  </td>\n</tr>\n<tbody>\n</table>\n\n### Force JSON response\n\n> 🔦 `@Send({ json: true })`<br>\n> 💫 Related Express method: [`res.json`](https://expressjs.com/en/4x/api.html#res.json)\n\nBehind the scene `Send` uses, you've guessed it, the [`res.send`](https://expressjs.com/en/4x/api.html#res.send) Express method. It already sends a proper JSON response for Objects and Arrays, but you might want to force JSON for any type with the help of [`res.json`](https://expressjs.com/en/4x/api.html#res.json):\n\n```ts\n@Send({ json: true }) // will use res.json behind the scene\n@Get('/me')\nget() {\n  return 'Jeremy' // Content-Type: 'application/json'\n}\n```\n\n### Custom handler\n\n```ts\n@Send<string>((data, { res }) => {\n  if (data === undefined) res.status(404)\n  if (data === null) res.status(204)\n  \n  res.json({ name: data })\n})\n@Get('/me')\nget() {\n  return 'Jeremy' \n}\n```\n\n### Share and override\n\nDecorate a class with `Send` to apply its behavior to all its methods. You override the behavior on a method level.\n\n```ts\n@Send({ json: true })\nclass PeopleRouter {\n  @Send({ json: false }) // override class send options\n  @Get('/me')\n  get() {\n    return 'Jeremy' // Content-Type: 'text/html'\n  }\n}\n```\n\n#### Make exceptions\n\n> 🔦 `@Send.Dont`\n\nYou need to take full control back in one of your methods ? Apply `Send.Dont` to exclude a method from `Send` behavior.\n\n```ts\n@Send()\n@Router('/things')\nclass ThingRouter {\n  @Get()\n  list() {\n    return db.collection('things').find({})\n  }\n\n  @Send.Dont\n  @Post()\n  create(@Res res: Response) {\n    res.write('complex')\n    res.end('stuff')\n  }\n}\n```\n\n### Why opt-in and not default ❔\n\nOther frameworks choose to handle and send the return value by default. Reflet chooses not to.\n\nIt's not that Reflet dislikes magic. But magic should be explicit and have its own decorator.<br> Magic should be under control 🧙‍, that's the reason for the `Send` decorator.\n\n## Error handling\n\n### Local error handler\n\n> 🔦 `@Catch(errorHandler)`<br>\n> 💫 Related Express method: [`app.use`](https://expressjs.com/en/4x/api.html#app.use)\n\n```ts\n@Router('/things')\nclass ThingRouter {\n  @Catch((err, req, res, next) => {\n    res.status(400)\n    next(err)\n  })\n  @Get()\n  list(req: Request, res: Response, next: NextFunction) {\n    throw Error('Nope') // or next('Nope')\n  }\n}\n```\n\nIf Router decorator is used, Reflet will apply class-scoped error handlers to the newly created Express Router.\n\n<table>\n<thead>\n<tr>\n  <th>Reflet</th>\n  <th>Express equivalent</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n  <td>\n\n```ts\n@Catch(A)\n@Router('/foo')\nclass Foo {\n  @Catch(B)\n  @Catch(C)\n  @Get()\n  get(req, res, next) {\n    throw Error()\n  }\n}\n```\n\n  </td>\n  <td>\n\n```ts\nconst router = express.Router()\nrouter.get('', (req, res, next) => { throw Error() }, B, C)\nrouter.use(A)\napp.use('/foo', router)\n```\n\n  </td>\n</tr>\n</tbody>\n</table>\n\n##### About order\n\nLogically, class-scoped error handlers are applied further down the handlers' stack than method-scoped error handlers.<br>And like with `Use`, successive `Catch` will be applied in the order they are written.\n\n##### 💡 Tip\n\nThrow some **[`HTTPError`](../http/README.md#error-)** from `@reflet/http` for an even better developer experience. _Compatible with express default error handler as well._\n\n### Final Handler\n\n> 🔦 `finalHandler(options)`\n\n```ts\nconst app = express()\n\nregister(app, [ThingRouter])\n\napp.use(finalHandler({\n  json: 'from-response-type',\n  log: '5xx',\n  notFoundHandler: true\n}))\n```\n\n##### `json`\n\nExpress default error handler always sends a `text/html` response ([source code](https://github.com/pillarjs/finalhandler/blob/v1.1.2/index.js#L272-L311)). This doesn't go well with today's world of JSON APIs.\n\n* `json: true` always sends the error with `res.json`.\n  \n* `json: false` passes the error to `next` to be handled by express final handler (default).\n\n* `json: 'from-response-type'` sends the error with `res.json` by looking for `Content-Type` on the response:\n\n    ```ts\n    res.type('json')\n    // ...\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n* `json: 'from-response-type-or-request'` first looks for `Content-Type` on the response, or infers it from `X-Requested-With` or `Accept` headers on the request:\n\n    ```http\n    GET http://host/foo\n    Accept: application/json\n    ```\n\n    ```ts\n    throw Error('Nope') // Content-Type: 'application/json'\n    ```\n\n##### `expose`\n\nBy default, Error `message` and `name` are not serialized to json.\n\nWith this option, you can either hide all error properties or expose some of them in the serialized response:\n\n* `true`: exposes all properties (stack included, beware of information leakage !).\n* `false`: exposes nothing (empty object).\n* `string[]`: whitelists specifics properties.\n* `(status) => boolean | string[]`: function for more conditional whitelisting:\n\n```ts\nfinalHandler({\n  json: true,\n  expose(status) {\n    // expose all properties in non production environment\n    if (process.env !== 'production') {\n      return true\n    }\n\n    // expose only some properties of client errors in production\n    if (status < 500) {\n      return ['message', 'code', 'data']\n    } else {\n      return false\n    }\n  }\n})\n```\n\n##### `log`\n\n* `log: true` always logs errors (with `console.error`).\n* `log: false` never logs errors, _default_.\n* `log: '5xx'` only logs server errors (with `console.error`).\n* If you need the flexibility to log more infos or use a dedicated logger other that `console.error`, you can pass a function like so:\n\n```ts\nimport * as pino from \"pino\";\nconst logger = pino()\n\nfinalHandler({\n  log(err, req, res) {\n    logger.error({\n      err,\n      status: res.statusCode,\n      path: req.url,\n      timestamp: new Date().toISOString(),\n    })\n  },\n})\n```\n\n_The response object type only exposes safe properties, so you don't send the response by accident._\n\n##### `notFoundHandler`\n\nLike the error handler, Express default route handler always sends a `text/html` response when the route is not found.\n\n* `notFoundHandler: true` defines a default handler similar to the Express one, with a 404 status, but compatible with json.\n* `notFoundHandler: <number>` defines the same default handler, with a custom status code.\n* `notFoundHandler: (req, res, next) => {}` lets you define your own.\n\n## Application class\n\n> 🔦 `Application`\n\nHave you ever tried to turn `express()` into a proper class ? Reflet did. 😁\n\n```ts\nimport * as express from 'express'\nimport { Application } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\nconst app = new Application()\n\napp.use(express.json(), express.urlencoded())\napp.register([UserRouter]) // register is now a method !\n\napp.listen(3000)\n```\n\nNot much for now, but you can extend this class and use all the decorators, as if they were global :\nRoutes will be attached at the root, and middlewares, error handlers, `Send` options, and `ScopedMiddlewares`, will be shared globally !\n\n```ts\nimport * as express from 'express'\nimport { Application, Registration, Use, Catch, Send, Router } from '@reflet/express'\nimport { UserRouter } from './user.router'\n\n@Send({ json: true })\n@Use(express.json(), express.urlencoded())\n@Router.ScopedMiddlewares\n@Catch(finalHandler({ \n  json: true,\n  log: true,\n  notFoundHandler: true,\n}))\nclass MyApp extends Application {\n  constructor(routers: Registration[]) {\n    super()\n    this.register(routers)\n  }\n\n  @Get('/healthcheck')\n  healthcheck() {\n    return { success: true }\n  }\n}\n\nconst app = new MyApp([UserRouter])\n\napp.listen(3000)\n```\n\n_If you call `register` multiple times, Reflet will make sure global middlewares are added only once, and gloral error handlers are still at the end of the stack._\n\n## Pure dependency injection\n\nIf you want to go full OOP and your routers have constructor dependencies, Reflet will enforce passing them as instances (along with their dependencies) instead of classes, to the `register` function which then acts as a _[Composition Root](https://blog.ploeh.dk/2011/07/28/CompositionRoot/)_.\n\n```ts\ninterface IUserService {\n  getUsers(): Promise<User[]>\n}\n\nclass UserService implements IUserService {\n  async getUsers() {\n    return db.collection('users').find({})\n  }\n}\n\nclass UserRouter {\n  constructor(private userService: IUserService) {}\n\n  @Get('/user')\n  async getAllUsers(@Res res: Response) {\n    const users = await this.userService.getUsers()\n    res.send(users)\n  }\n}\n\nregister(app, [\n  new UserRouter(new UserService())\n])\n```\n\nNo DI Container magic, no cumbersome `@Inject` decorator 😵... Only _**[pure DI](https://blog.ploeh.dk/2014/06/10/pure-di/)**_, which is the simplest and the most strongly typed DI.\n\nYou can even pass dependencies down your nested routers:\n\n```ts\n@Router('/parent')\n@Router.Children<typeof ParentRouter>((service) => [new NestedRouter(service)])\nclass ParentRouter {\n  constructor(private service: Service) {}\n}\n\nregister(app, [new ParentRouter(new Service())])\n```\n","readmeFilename":"README.MD","homepage":"https://github.com/jeremyben/reflet/tree/master#readme","bugs":{"url":"https://github.com/jeremyben/reflet/issues"}}