mirror of
https://github.com/nestjs/nest.git
synced 2026-02-22 07:21:39 +00:00
Compare commits
957 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
caa8a8f6fe | ||
|
|
63581c9d18 | ||
|
|
4bf2fd4747 | ||
|
|
d47fc5142d | ||
|
|
fdcf5b2f50 | ||
|
|
1a03bd7565 | ||
|
|
b2cf9149b5 | ||
|
|
2e75a27ef3 | ||
|
|
5c9df2438d | ||
|
|
53c07e563e | ||
|
|
b8205f5eef | ||
|
|
64ba27d4ed | ||
|
|
e3e615a4f3 | ||
|
|
63113d85c5 | ||
|
|
7bdb6d5c87 | ||
|
|
e471603ebc | ||
|
|
f9fe42f4d4 | ||
|
|
4c35caaf8d | ||
|
|
1e49562a2e | ||
|
|
6b6ebf3ca9 | ||
|
|
4566dbca5f | ||
|
|
4f9ad51db9 | ||
|
|
23eed20abc | ||
|
|
f934e7848d | ||
|
|
f69d157013 | ||
|
|
365c40bd98 | ||
|
|
1d35d7b687 | ||
|
|
5bb4fc5aa4 | ||
|
|
fb1ba6ceca | ||
|
|
9a7ee41b10 | ||
|
|
31055aba24 | ||
|
|
c7edd139ea | ||
|
|
d788b7d5b9 | ||
|
|
1e09584c36 | ||
|
|
0b0c1748ed | ||
|
|
41b01254ac | ||
|
|
c6021b1502 | ||
|
|
121013e2c9 | ||
|
|
6d66fee96b | ||
|
|
20173294ef | ||
|
|
0a4fd93361 | ||
|
|
7de6f40c45 | ||
|
|
63eb125aa4 | ||
|
|
dbf3999373 | ||
|
|
ecf9c6b57a | ||
|
|
d86e43c822 | ||
|
|
d3f119b09e | ||
|
|
e29eee1090 | ||
|
|
dbb7c682f9 | ||
|
|
365948c227 | ||
|
|
a1d6eccc76 | ||
|
|
51005735fe | ||
|
|
4d3819ef6f | ||
|
|
685344309a | ||
|
|
73e5008e4c | ||
|
|
43817a9f71 | ||
|
|
0913b7cdc4 | ||
|
|
0aef269531 | ||
|
|
466fe92370 | ||
|
|
399ac86db7 | ||
|
|
2a1cc6291a | ||
|
|
3b7429357d | ||
|
|
1394305bf3 | ||
|
|
502e0bfaaa | ||
|
|
ea25c7dfbd | ||
|
|
76f2918f17 | ||
|
|
fb5ee1ddb2 | ||
|
|
49b2fc04b9 | ||
|
|
2788b8b6f1 | ||
|
|
2113d86ac8 | ||
|
|
fdf11a51ae | ||
|
|
37a7121736 | ||
|
|
af6b73300f | ||
|
|
5d7573ed2f | ||
|
|
6babebbfab | ||
|
|
a00750de1d | ||
|
|
3f1a491987 | ||
|
|
2b0b7a54fe | ||
|
|
45a44ee3cf | ||
|
|
dc71c4753a | ||
|
|
e9e8214bfc | ||
|
|
60db92b52b | ||
|
|
3f81fa103a | ||
|
|
14263c7aa1 | ||
|
|
ec20b131f7 | ||
|
|
67ae27490b | ||
|
|
fc77e4fca8 | ||
|
|
762b6bf6a7 | ||
|
|
fa22622f42 | ||
|
|
8608ac31eb | ||
|
|
2250c4955e | ||
|
|
ac73124e85 | ||
|
|
1cb094c7b2 | ||
|
|
53c3a059aa | ||
|
|
d151218010 | ||
|
|
1d0b0e65dc | ||
|
|
5902643a71 | ||
|
|
613af5c963 | ||
|
|
899fb9b1f5 | ||
|
|
05721f43af | ||
|
|
dc02e98a89 | ||
|
|
df4eca1399 | ||
|
|
1aec93d03e | ||
|
|
e0bf2b252c | ||
|
|
11266b36eb | ||
|
|
3ad7aaabf9 | ||
|
|
f8c423ee80 | ||
|
|
1589ff39c1 | ||
|
|
370c8d3cc6 | ||
|
|
2bc6a604d1 | ||
|
|
87ff00395a | ||
|
|
ba2abaded4 | ||
|
|
43325c1bd4 | ||
|
|
f31d5a6f64 | ||
|
|
c9c643991d | ||
|
|
5708741f75 | ||
|
|
addadd9abe | ||
|
|
74c0d3575f | ||
|
|
8448580ebd | ||
|
|
c54a67bf74 | ||
|
|
24b2007be8 | ||
|
|
5fb192b24d | ||
|
|
4cbf9c5338 | ||
|
|
e2a13b8000 | ||
|
|
736c40e443 | ||
|
|
9715b97932 | ||
|
|
894bf0182f | ||
|
|
61b824a2a8 | ||
|
|
9ba9822753 | ||
|
|
960335eadc | ||
|
|
93b803fbfd | ||
|
|
e45fd18db5 | ||
|
|
923bfc45a8 | ||
|
|
119794d40b | ||
|
|
88470dacdf | ||
|
|
625510bbd2 | ||
|
|
2a4386cedf | ||
|
|
aabd33c45a | ||
|
|
7854ad7d80 | ||
|
|
2b5d0cf2b9 | ||
|
|
f373c4189f | ||
|
|
3083a9a785 | ||
|
|
c994964bc8 | ||
|
|
b6f9f8c94b | ||
|
|
ca05e88a85 | ||
|
|
1be1ce21f5 | ||
|
|
66bf64e781 | ||
|
|
7737594a20 | ||
|
|
596b0d703b | ||
|
|
1110197e5b | ||
|
|
b142da095b | ||
|
|
06fd145147 | ||
|
|
c3bf1e4347 | ||
|
|
1def23a5d0 | ||
|
|
ab0bce9d4d | ||
|
|
2e6cea63df | ||
|
|
cc8968b18d | ||
|
|
bea45cb73e | ||
|
|
c5ce998377 | ||
|
|
27ce01cd43 | ||
|
|
0f20512d79 | ||
|
|
b8cd3aada0 | ||
|
|
291dc956e0 | ||
|
|
5c41909e94 | ||
|
|
052b6eedce | ||
|
|
d434b3f255 | ||
|
|
f67d012b33 | ||
|
|
347562d1d8 | ||
|
|
6390c54eac | ||
|
|
15a58901d6 | ||
|
|
e855ad6c97 | ||
|
|
9eb695cf81 | ||
|
|
35b19f3794 | ||
|
|
2a9a984e8c | ||
|
|
3da5b45cf6 | ||
|
|
95c974cd07 | ||
|
|
621fb133fa | ||
|
|
8385b254ce | ||
|
|
04a4f0029d | ||
|
|
80a05dcce7 | ||
|
|
2a773885e7 | ||
|
|
f6d09b1720 | ||
|
|
c6d271ab7f | ||
|
|
c13a49e9f8 | ||
|
|
555fff6d84 | ||
|
|
56fa3d8d5e | ||
|
|
1f5b466721 | ||
|
|
2c55fbe62c | ||
|
|
aa4dbfe400 | ||
|
|
fbd7c3edfa | ||
|
|
25dbb330cd | ||
|
|
9c175c408c | ||
|
|
8759c6ba20 | ||
|
|
e88e310731 | ||
|
|
5ac3637dee | ||
|
|
a96ceb440f | ||
|
|
5c0902f2d5 | ||
|
|
ae433f0daa | ||
|
|
de8d95d861 | ||
|
|
628d976151 | ||
|
|
3ba20525b0 | ||
|
|
c85d84d9e6 | ||
|
|
220905e9ee | ||
|
|
20967866da | ||
|
|
969778825c | ||
|
|
baba936dd5 | ||
|
|
6a37bddebe | ||
|
|
f2b56256d8 | ||
|
|
c505080a3f | ||
|
|
dc0bb8d673 | ||
|
|
8426f2c2ac | ||
|
|
8f2afeb0bb | ||
|
|
a285be8047 | ||
|
|
9dcdfb7cc2 | ||
|
|
9e25c55b21 | ||
|
|
2170ea25cb | ||
|
|
958bcaaa49 | ||
|
|
ec1c35fb77 | ||
|
|
c19bd5f502 | ||
|
|
697fd2cf66 | ||
|
|
da4a8a82d2 | ||
|
|
a4234bc252 | ||
|
|
7014fcd05c | ||
|
|
4311517e2a | ||
|
|
dd8e6977e8 | ||
|
|
9421ff1e3c | ||
|
|
b37f9b2c94 | ||
|
|
e699e4540c | ||
|
|
459d7ccabc | ||
|
|
213d066b2e | ||
|
|
572fcc462d | ||
|
|
60556a775a | ||
|
|
834b143272 | ||
|
|
26929c8bba | ||
|
|
9711141149 | ||
|
|
4b6eaae07d | ||
|
|
e1566d9d92 | ||
|
|
9bf05d4b9d | ||
|
|
6239dd32fe | ||
|
|
345033e376 | ||
|
|
96dfd1e976 | ||
|
|
9709c6dbde | ||
|
|
decbc97258 | ||
|
|
4293388a47 | ||
|
|
188da6b5eb | ||
|
|
7e9de1982a | ||
|
|
1ad836ed66 | ||
|
|
ccfcc19fbb | ||
|
|
864159fadd | ||
|
|
0b4c8f82bd | ||
|
|
b0114703e8 | ||
|
|
2af3dd22d5 | ||
|
|
3adf58888a | ||
|
|
bdca9f574c | ||
|
|
5e6790e1e8 | ||
|
|
7d849c96a6 | ||
|
|
621809bf0f | ||
|
|
40e3ea31a0 | ||
|
|
92758003ab | ||
|
|
447499a3c9 | ||
|
|
3db185118a | ||
|
|
98858b2b9a | ||
|
|
673fd1fec3 | ||
|
|
42c89e0c40 | ||
|
|
e18dd2ef45 | ||
|
|
04f4cdb01b | ||
|
|
b8fb74e769 | ||
|
|
45262b0529 | ||
|
|
5f234eb1d6 | ||
|
|
94fc5f6e32 | ||
|
|
77be992b2b | ||
|
|
f79037907d | ||
|
|
6399dfdcb4 | ||
|
|
b577f3e5ab | ||
|
|
ec520feba9 | ||
|
|
b02700c97f | ||
|
|
89a5a4e8d3 | ||
|
|
3089a6672b | ||
|
|
e2fba4a8e1 | ||
|
|
affe18febe | ||
|
|
9c64dca7d7 | ||
|
|
87853c5f5c | ||
|
|
9a919f067b | ||
|
|
066da15068 | ||
|
|
e0563a6403 | ||
|
|
5dc0ebdd7e | ||
|
|
c76a9370c9 | ||
|
|
5c95c16f6f | ||
|
|
a352fca952 | ||
|
|
7c90dc0e34 | ||
|
|
bdce2e1c4d | ||
|
|
958e61f6f1 | ||
|
|
3ad982d696 | ||
|
|
3ab96e694c | ||
|
|
c619067c86 | ||
|
|
4a00b83190 | ||
|
|
244cbe2e4f | ||
|
|
15a9489b58 | ||
|
|
7fcdeeca4a | ||
|
|
6630eebf7f | ||
|
|
ea32c88488 | ||
|
|
4d7560c3d6 | ||
|
|
81e1e21289 | ||
|
|
7eb2eb44cd | ||
|
|
c5c1eb3b97 | ||
|
|
4918bbeee4 | ||
|
|
e8b0b7574d | ||
|
|
6bd3a9c0ae | ||
|
|
7b1705543b | ||
|
|
858a2c72bb | ||
|
|
8d02c90cfb | ||
|
|
b06de50b1d | ||
|
|
aca45139a6 | ||
|
|
efbc7b9412 | ||
|
|
8646a72be0 | ||
|
|
591bd8b240 | ||
|
|
642b3ae62d | ||
|
|
a43d07b0f5 | ||
|
|
dd55ab15fd | ||
|
|
74366a9c86 | ||
|
|
c000f64ad8 | ||
|
|
25979c27c0 | ||
|
|
365d34255b | ||
|
|
df00a0a181 | ||
|
|
ba6d455b3c | ||
|
|
91c58e8abb | ||
|
|
5e2a8be2a5 | ||
|
|
99a884a64e | ||
|
|
b208b74f40 | ||
|
|
9064a29081 | ||
|
|
cdfee483ee | ||
|
|
039928983f | ||
|
|
e1392a892d | ||
|
|
9a15936e4c | ||
|
|
f673a221b3 | ||
|
|
daa39dbe68 | ||
|
|
3b617962dc | ||
|
|
8a1e89e637 | ||
|
|
3f51facdc2 | ||
|
|
3d6d17c618 | ||
|
|
1809667800 | ||
|
|
3a465aa2c3 | ||
|
|
0e6828cc81 | ||
|
|
282f774d6b | ||
|
|
9cb166852c | ||
|
|
1cc573bc74 | ||
|
|
7942cb5bc5 | ||
|
|
680f6fe3cd | ||
|
|
bc4df64c7c | ||
|
|
85e51e240c | ||
|
|
e619bc251a | ||
|
|
8588c3e02a | ||
|
|
87d5465507 | ||
|
|
3a6c4b3872 | ||
|
|
9608e8130d | ||
|
|
309b2b5148 | ||
|
|
f104bf6032 | ||
|
|
e4b91cbf6c | ||
|
|
30f1c3e72b | ||
|
|
e0a487b6c9 | ||
|
|
353e698971 | ||
|
|
1c91bd6642 | ||
|
|
2b1e5e924e | ||
|
|
fc8e4893f2 | ||
|
|
4e318997e1 | ||
|
|
60e18f547a | ||
|
|
0bd2365711 | ||
|
|
0a372c2332 | ||
|
|
b9396eea0a | ||
|
|
bae1182743 | ||
|
|
89f74648da | ||
|
|
ef9d1beb31 | ||
|
|
d8d736a1ba | ||
|
|
2751bddc84 | ||
|
|
e716c9d50b | ||
|
|
6056283d20 | ||
|
|
1d2d10f55f | ||
|
|
e7942c9868 | ||
|
|
75e7c64f5b | ||
|
|
574a517efe | ||
|
|
2ff445100b | ||
|
|
226a1ac28b | ||
|
|
8c315e9ffb | ||
|
|
efbc8d056f | ||
|
|
75c58dd39b | ||
|
|
83692f8c04 | ||
|
|
382eae9242 | ||
|
|
e72cfca000 | ||
|
|
d764c299bc | ||
|
|
14fc5de6cf | ||
|
|
0e412af378 | ||
|
|
17cec8ba2c | ||
|
|
e9f5606e52 | ||
|
|
80ecfacb36 | ||
|
|
6291443020 | ||
|
|
961e87ded4 | ||
|
|
60e78ef7f7 | ||
|
|
b36feb1009 | ||
|
|
b6bc35ee37 | ||
|
|
9c7dfd9a77 | ||
|
|
87f9fedbdd | ||
|
|
5f43413828 | ||
|
|
52df7c15de | ||
|
|
4d25621bac | ||
|
|
4275aac316 | ||
|
|
cd4e923164 | ||
|
|
7313176bf7 | ||
|
|
e0f5a6dbed | ||
|
|
004333e577 | ||
|
|
a446f268ce | ||
|
|
c0089cd9ae | ||
|
|
2cdee2557c | ||
|
|
a2edf96588 | ||
|
|
892cbe57de | ||
|
|
2ac7b58307 | ||
|
|
0fd7e91bd5 | ||
|
|
712d15d730 | ||
|
|
af906f7f1e | ||
|
|
faacef6d7f | ||
|
|
f2dd06338b | ||
|
|
784cb129f4 | ||
|
|
07e49bb567 | ||
|
|
1aa705c732 | ||
|
|
8289272861 | ||
|
|
026c1bd61c | ||
|
|
30fe142234 | ||
|
|
4d5bda66b1 | ||
|
|
9361b1b267 | ||
|
|
e5db699b22 | ||
|
|
ea78596e65 | ||
|
|
16c44b6eea | ||
|
|
bcd2041b9d | ||
|
|
25c604883e | ||
|
|
be250fa7c2 | ||
|
|
0effa64d3e | ||
|
|
f1ccd10976 | ||
|
|
90ebd68257 | ||
|
|
94daf20c1c | ||
|
|
7c0d8bae39 | ||
|
|
1f297a4d2b | ||
|
|
20d3dafdd5 | ||
|
|
68ba64055e | ||
|
|
e89ebfe7a5 | ||
|
|
8b965fa256 | ||
|
|
155c2568d3 | ||
|
|
d72415a61b | ||
|
|
62978f887f | ||
|
|
18dd2430b8 | ||
|
|
2db3ff8194 | ||
|
|
a57653fc1d | ||
|
|
4ea1535931 | ||
|
|
db7b8b03fa | ||
|
|
87c5ff8e1c | ||
|
|
86f3764f79 | ||
|
|
f5ba47b8d0 | ||
|
|
ab15176d68 | ||
|
|
88d23e9f82 | ||
|
|
3b9cdda6aa | ||
|
|
1a89c12c7c | ||
|
|
a8bf5e69ca | ||
|
|
afecbfbf30 | ||
|
|
7943f99478 | ||
|
|
d2d27bfb37 | ||
|
|
2779055391 | ||
|
|
08a6441e81 | ||
|
|
52ad72342f | ||
|
|
116143bf7e | ||
|
|
76430410b3 | ||
|
|
7dd22758fb | ||
|
|
3751f90f14 | ||
|
|
8f0385abbd | ||
|
|
0df89a252d | ||
|
|
ab7a1378c2 | ||
|
|
6f68460aec | ||
|
|
513904a684 | ||
|
|
628da342fb | ||
|
|
0a9652e568 | ||
|
|
7a11a16fd4 | ||
|
|
0bb19d68b3 | ||
|
|
d50bbcb131 | ||
|
|
93673dfde0 | ||
|
|
a7083ec5fa | ||
|
|
5f1e9a07d9 | ||
|
|
93cb5577ed | ||
|
|
5b0647a195 | ||
|
|
dd12820e79 | ||
|
|
ac19447c65 | ||
|
|
20fdfe744f | ||
|
|
dc918a621b | ||
|
|
800da43d06 | ||
|
|
01f69928d9 | ||
|
|
87e4fd93f6 | ||
|
|
23b86feed4 | ||
|
|
5f3ee807ff | ||
|
|
c709fc5f0c | ||
|
|
0e2fcd56b0 | ||
|
|
5b81cc2d79 | ||
|
|
a3fa4d6494 | ||
|
|
bd0e7b4c2f | ||
|
|
b7dcefe743 | ||
|
|
8152eada10 | ||
|
|
dba2d620ea | ||
|
|
9ca41ac387 | ||
|
|
5ed9e93795 | ||
|
|
6c1119316a | ||
|
|
2555e37465 | ||
|
|
6485231737 | ||
|
|
4cf5a56b84 | ||
|
|
14bef06a5e | ||
|
|
2f241b97a1 | ||
|
|
d151eff547 | ||
|
|
b802fb2ab4 | ||
|
|
0ae3dda8db | ||
|
|
96c29bf047 | ||
|
|
cf13b422fe | ||
|
|
653fe5d85b | ||
|
|
a195cfe503 | ||
|
|
402329812f | ||
|
|
621e003163 | ||
|
|
bd32372a2e | ||
|
|
9b5f13e16e | ||
|
|
a7d532409c | ||
|
|
1a05437d64 | ||
|
|
aa28011607 | ||
|
|
da2b73f0c6 | ||
|
|
1579c4df91 | ||
|
|
35f62f97d0 | ||
|
|
31dff982d0 | ||
|
|
ccd1ad20bd | ||
|
|
566a0130ea | ||
|
|
301b4b9896 | ||
|
|
5b64928574 | ||
|
|
92e40a9ca6 | ||
|
|
e0a08125fe | ||
|
|
00b47bd288 | ||
|
|
3515d5f8cd | ||
|
|
be60420106 | ||
|
|
fc912dc5ad | ||
|
|
2cd6f93317 | ||
|
|
0f8db9517c | ||
|
|
33700d2775 | ||
|
|
0f14a536a6 | ||
|
|
ff57e0758b | ||
|
|
43797ce9f7 | ||
|
|
6984cd4d46 | ||
|
|
a010835164 | ||
|
|
08477200de | ||
|
|
aa315672a1 | ||
|
|
9027fd284b | ||
|
|
2e287691da | ||
|
|
9d0dcc6080 | ||
|
|
bf50c2e24c | ||
|
|
83eda4f7e6 | ||
|
|
76874941dd | ||
|
|
b924dfacc9 | ||
|
|
bb0b702a53 | ||
|
|
d8add273e0 | ||
|
|
c05f6ea8b1 | ||
|
|
c12ee9aed0 | ||
|
|
219c7e5d14 | ||
|
|
902ab76007 | ||
|
|
0ca414bca7 | ||
|
|
e0ce225f76 | ||
|
|
c2eb2a7007 | ||
|
|
c7e9c2b756 | ||
|
|
0bcf4e9703 | ||
|
|
770b5e5723 | ||
|
|
2ae2852ed2 | ||
|
|
68d0c6256e | ||
|
|
415387ca62 | ||
|
|
09f30d084b | ||
|
|
56fae9c8d4 | ||
|
|
4dec3780a6 | ||
|
|
7f84126283 | ||
|
|
e0306625d7 | ||
|
|
3da20ddda0 | ||
|
|
733b9219c3 | ||
|
|
8427e5304a | ||
|
|
d7392ebf1e | ||
|
|
67e2815e8e | ||
|
|
77277a8380 | ||
|
|
c18bf44725 | ||
|
|
cfd9294b93 | ||
|
|
122c4bd521 | ||
|
|
2bfc98223d | ||
|
|
7fed9a9e64 | ||
|
|
098e64ca8a | ||
|
|
6adcfa12e5 | ||
|
|
0879ced66a | ||
|
|
fec5a25bdd | ||
|
|
181468b64a | ||
|
|
4cd801031b | ||
|
|
e710d96f10 | ||
|
|
bd042ea829 | ||
|
|
a640cc64ce | ||
|
|
ac3f458c56 | ||
|
|
d9b88811bd | ||
|
|
11e620149c | ||
|
|
879bfaace8 | ||
|
|
a8b8fe983f | ||
|
|
f4002e493b | ||
|
|
5974b6fed1 | ||
|
|
da30d10994 | ||
|
|
8bef02a1d4 | ||
|
|
2a47ec8366 | ||
|
|
3175f5f9e9 | ||
|
|
0ba8eccd4f | ||
|
|
74b9810b21 | ||
|
|
1415eb4d44 | ||
|
|
f06f8d6128 | ||
|
|
99b2790c80 | ||
|
|
5f257eca96 | ||
|
|
d3f17c293b | ||
|
|
6cf04e04aa | ||
|
|
d4ee608af0 | ||
|
|
416906280b | ||
|
|
b64fb788a5 | ||
|
|
2ad2ca2660 | ||
|
|
ab0fa46a18 | ||
|
|
0ce86d5277 | ||
|
|
3070be83d3 | ||
|
|
7ae9bb56a2 | ||
|
|
03e139e781 | ||
|
|
092347d225 | ||
|
|
5f5166802e | ||
|
|
439be39419 | ||
|
|
8bd21a61b6 | ||
|
|
b1cd819e19 | ||
|
|
d3d0356cc5 | ||
|
|
de514e87c9 | ||
|
|
d08217a113 | ||
|
|
f94dd3a79b | ||
|
|
ed1f0b8bc9 | ||
|
|
28a633e0c8 | ||
|
|
73dd312396 | ||
|
|
0ccb1cff0a | ||
|
|
c6adb8426a | ||
|
|
46a25ec282 | ||
|
|
fc24e3ed49 | ||
|
|
a016a5929e | ||
|
|
7922008e83 | ||
|
|
123c60bf1e | ||
|
|
e1ad600a26 | ||
|
|
eac011aa86 | ||
|
|
5b2fd40cfe | ||
|
|
30ac16c346 | ||
|
|
91d087362e | ||
|
|
77942475cf | ||
|
|
215bab121c | ||
|
|
db54167ce5 | ||
|
|
e2d3c9befa | ||
|
|
ea37d4d0d7 | ||
|
|
d8590f0b7c | ||
|
|
35c929d613 | ||
|
|
a9df6769a6 | ||
|
|
0ae7502038 | ||
|
|
5f4f41607e | ||
|
|
437ce199f7 | ||
|
|
7956564f40 | ||
|
|
6513aab6ff | ||
|
|
a8f5752e93 | ||
|
|
b2611998b0 | ||
|
|
26f54b9c75 | ||
|
|
31f7b9fea9 | ||
|
|
1003c2e926 | ||
|
|
7f1fff2aef | ||
|
|
57ea9c60ec | ||
|
|
722eced9cb | ||
|
|
e03f275cef | ||
|
|
9b5a615f55 | ||
|
|
9d9f77a137 | ||
|
|
ab4da0c3e3 | ||
|
|
e0eda209c2 | ||
|
|
1274af05f2 | ||
|
|
58abcdd625 | ||
|
|
c7ca97ba8b | ||
|
|
0e08cdd0f2 | ||
|
|
e03199e230 | ||
|
|
f047dc9c56 | ||
|
|
37db7d8a2c | ||
|
|
42820ad97d | ||
|
|
e7413664bb | ||
|
|
08e9122228 | ||
|
|
7d02baaaab | ||
|
|
918da9470f | ||
|
|
3bbc93a2ad | ||
|
|
c23eec9685 | ||
|
|
a2d9f533ce | ||
|
|
1935b9cd1d | ||
|
|
66667d8c64 | ||
|
|
7a277cedd4 | ||
|
|
9d75d4b393 | ||
|
|
74af340f9a | ||
|
|
68d0859575 | ||
|
|
a1b3cb4a50 | ||
|
|
190274d9cd | ||
|
|
d47591e811 | ||
|
|
21b38d3db8 | ||
|
|
a225632199 | ||
|
|
7c394b6110 | ||
|
|
eed921796f | ||
|
|
00631d9472 | ||
|
|
73e257edd2 | ||
|
|
a3453b4230 | ||
|
|
986dacfd4c | ||
|
|
f570ad9e8a | ||
|
|
2405b66075 | ||
|
|
9d0551ff25 | ||
|
|
1ccdd69f24 | ||
|
|
941de57770 | ||
|
|
80ab46f6b0 | ||
|
|
524dc72159 | ||
|
|
2170b2b81a | ||
|
|
6be0d39f77 | ||
|
|
58a01f5e1e | ||
|
|
8fd4479ee5 | ||
|
|
74f21e51fe | ||
|
|
07342bf84e | ||
|
|
320c118708 | ||
|
|
d61b88ee28 | ||
|
|
c8e6eb28e0 | ||
|
|
c1424d326c | ||
|
|
0f5f76fe17 | ||
|
|
701d77f78a | ||
|
|
b2a7ff3d6a | ||
|
|
3bb7020f4d | ||
|
|
b4a1cc2803 | ||
|
|
4f249cf88d | ||
|
|
596be624af | ||
|
|
c39eff5fd0 | ||
|
|
ed613668c0 | ||
|
|
a485b3d2d2 | ||
|
|
6f550ca25d | ||
|
|
7cc31bd279 | ||
|
|
555b42ee9d | ||
|
|
bcb58a61aa | ||
|
|
092a9bdb67 | ||
|
|
fdd973ceab | ||
|
|
cf28dfa565 | ||
|
|
a87bda1b9f | ||
|
|
811d9e7bde | ||
|
|
dc9e6bc814 | ||
|
|
c8f0fa82cf | ||
|
|
2bbda5aced | ||
|
|
8e6e505024 | ||
|
|
91b54b0985 | ||
|
|
2084157cf7 | ||
|
|
034594c195 | ||
|
|
bafe0f9f8e | ||
|
|
b17d2e974c | ||
|
|
664f531d2a | ||
|
|
2d334271ec | ||
|
|
ce6e0348ab | ||
|
|
f8c57b95a8 | ||
|
|
3368cf7e12 | ||
|
|
fb876baa97 | ||
|
|
3d652d3ce3 | ||
|
|
7d9209d605 | ||
|
|
c49a84b420 | ||
|
|
368e7b95b1 | ||
|
|
c97a376e09 | ||
|
|
a181753d51 | ||
|
|
fb77de075e | ||
|
|
a75882d166 | ||
|
|
90c7040524 | ||
|
|
0d629c9b86 | ||
|
|
b78f9fa32e | ||
|
|
a22e3e30c8 | ||
|
|
80b09e61fb | ||
|
|
cacfa2d552 | ||
|
|
8a7b5a54d3 | ||
|
|
f91cd20230 | ||
|
|
89c7c5009a | ||
|
|
3504f094f2 | ||
|
|
97a9bf05de | ||
|
|
59b4d5979c | ||
|
|
2b43740d5e | ||
|
|
46781cb3aa | ||
|
|
e11d3d6bf3 | ||
|
|
b5d8db6d14 | ||
|
|
8a56183422 | ||
|
|
3657d5fb34 | ||
|
|
05daee3a41 | ||
|
|
a5fb2b7c62 | ||
|
|
432cf5bf01 | ||
|
|
8326077bd5 | ||
|
|
a92b473798 | ||
|
|
7bf103f75f | ||
|
|
d9e4c0f6f2 | ||
|
|
66dfe04159 | ||
|
|
6d6b139250 | ||
|
|
3fb9f853bf | ||
|
|
f0728016a6 | ||
|
|
4704b672df | ||
|
|
b6f3059faf | ||
|
|
8f640dbfc4 | ||
|
|
b9cf146fdc | ||
|
|
61d8b7ecc9 | ||
|
|
b347a2a2e0 | ||
|
|
745c818cff | ||
|
|
a60acfac5a | ||
|
|
6ddd021290 | ||
|
|
c1cfa1d90f | ||
|
|
fc80d97f5f | ||
|
|
e0bfe8dbda | ||
|
|
e29ff99a4f | ||
|
|
4b12f02f8c | ||
|
|
0b64023fbd | ||
|
|
6697b71042 | ||
|
|
851402bc60 | ||
|
|
f258a00443 | ||
|
|
bf2af3c74a | ||
|
|
3cf5797529 | ||
|
|
3351c65a05 | ||
|
|
6656e04939 | ||
|
|
e5d7410666 | ||
|
|
eb7782d450 | ||
|
|
29ebb178d7 | ||
|
|
72e8d9ae2e | ||
|
|
8de690c45a | ||
|
|
4bf0159bde | ||
|
|
26bb6eb81e | ||
|
|
2c25480d9a | ||
|
|
0e94d636cf | ||
|
|
a5098eeeb5 | ||
|
|
c22f8a7795 | ||
|
|
8c609c22b2 | ||
|
|
9044a03a08 | ||
|
|
df212fd4db | ||
|
|
36e455f3b2 | ||
|
|
86092c2289 | ||
|
|
5b5c4b8476 | ||
|
|
696cc79598 | ||
|
|
54a6829f6f | ||
|
|
e1dc8ed33c | ||
|
|
b0e9c74500 | ||
|
|
afdbfe3c87 | ||
|
|
859cec20e7 | ||
|
|
8600abc93d | ||
|
|
1f81f7c3ca | ||
|
|
fb5c751ea9 | ||
|
|
d18195db66 | ||
|
|
47b454a978 | ||
|
|
e43cd89cfa | ||
|
|
04ecad8f55 | ||
|
|
3fb1024cfc | ||
|
|
680f92bdeb | ||
|
|
36db079cad | ||
|
|
3a91758010 | ||
|
|
80f1c33ae9 | ||
|
|
40ec0dd653 | ||
|
|
023369a0b5 | ||
|
|
07c4120092 | ||
|
|
739edd963f | ||
|
|
d38375828d | ||
|
|
3ab7258448 | ||
|
|
7e64117904 | ||
|
|
ac71d062eb | ||
|
|
e30b63c0ac | ||
|
|
5a89f3a2d9 | ||
|
|
cee55aa742 | ||
|
|
8b2dd9a084 | ||
|
|
ec6f0444bc | ||
|
|
ce122d6c24 | ||
|
|
8c3fe84d96 | ||
|
|
cc6d11f852 | ||
|
|
4418122356 | ||
|
|
3d16e3bcc7 | ||
|
|
1821a185d0 | ||
|
|
d0c1a45aac | ||
|
|
fa2b2bd2d2 | ||
|
|
95230ec32c | ||
|
|
e697f062ae | ||
|
|
8c3b9fb8c1 | ||
|
|
0d61521357 | ||
|
|
3b95188866 | ||
|
|
b8229461a7 | ||
|
|
c2a363c5bb | ||
|
|
c48797d6f2 | ||
|
|
5a3ef3db3b | ||
|
|
534419f604 | ||
|
|
a37b7fde98 | ||
|
|
c6ff840cfd | ||
|
|
ce74185ba5 | ||
|
|
6afe77bd5c | ||
|
|
6dbcfb1471 | ||
|
|
4e2d391413 | ||
|
|
ad445d9c42 | ||
|
|
d0c601a0bb | ||
|
|
ae3e959865 | ||
|
|
925f92a1c6 | ||
|
|
d5f6b3170e | ||
|
|
55d9edc21f | ||
|
|
0f58b760fe | ||
|
|
97f99ec51f | ||
|
|
27ae8d2dd3 | ||
|
|
fecc9b3bbf | ||
|
|
51f5a0e504 | ||
|
|
67ed9ffe34 | ||
|
|
56091c5623 | ||
|
|
ec0b89235f | ||
|
|
767f602d80 | ||
|
|
0b6ba94cf5 | ||
|
|
50fe1e7821 | ||
|
|
00fd801d64 | ||
|
|
6ae1e7017b | ||
|
|
ff7a474d6a | ||
|
|
93260220e6 | ||
|
|
2fdad5eff7 | ||
|
|
2e238409b4 | ||
|
|
122450bf94 | ||
|
|
663641eacb | ||
|
|
e8b9d66e1a | ||
|
|
60ca357fc6 | ||
|
|
3f0de4eefd | ||
|
|
d87fb4ddf1 | ||
|
|
928fd86b24 | ||
|
|
bddecac3a7 | ||
|
|
abad05002a | ||
|
|
bb98368648 | ||
|
|
8adec4f20f | ||
|
|
706195f23c | ||
|
|
644fec3fc0 | ||
|
|
77636ef203 | ||
|
|
0b34312790 | ||
|
|
333cb76561 | ||
|
|
ca58d03fb1 | ||
|
|
154c0fc9b2 | ||
|
|
f0ef3455cc | ||
|
|
ed6745427d | ||
|
|
383d87e5cd | ||
|
|
c2a795c155 | ||
|
|
451f2f8c72 | ||
|
|
9a36f933e1 | ||
|
|
63c2a14008 | ||
|
|
cabd6703ad | ||
|
|
f3c17e7588 | ||
|
|
485da680e7 | ||
|
|
08d19a6f27 | ||
|
|
6e5e55789c | ||
|
|
3631c1abe4 | ||
|
|
f5998e17c7 | ||
|
|
d76040bacc | ||
|
|
96f9e5fe8d | ||
|
|
41c998bee0 | ||
|
|
22c204df23 | ||
|
|
7f38657624 | ||
|
|
cc596184f0 | ||
|
|
1d8a64d54a | ||
|
|
6f4ac0ceb2 | ||
|
|
d4739e817a | ||
|
|
a0557c752b | ||
|
|
a39b2c2c3c | ||
|
|
e1307c58d3 | ||
|
|
6582e5c233 | ||
|
|
830ee31525 | ||
|
|
88cf1a178a |
41
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
41
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@@ -1,41 +0,0 @@
|
||||
---
|
||||
name: "\U0001F41B Bug Report"
|
||||
about: "If something isn't working as expected \U0001F914."
|
||||
title: ''
|
||||
labels: 'type: potential issue :broken_heart:,needs triage'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Bug Report
|
||||
|
||||
## Current behavior
|
||||
<!-- Describe how the issue manifests. -->
|
||||
|
||||
## Input Code
|
||||
<!-- REPL or Repo link if applicable: -->
|
||||
|
||||
```ts
|
||||
const your = (code) => here;
|
||||
```
|
||||
|
||||
## Expected behavior
|
||||
<!-- A clear and concise description of what you expected to happen (or code). -->
|
||||
|
||||
## Possible Solution
|
||||
<!--- Only if you have suggestions on a fix for the bug -->
|
||||
|
||||
## Environment
|
||||
|
||||
<pre><code>
|
||||
Nest version: X.Y.Z
|
||||
<!-- Check whether this is still an issue in the most recent Nest version -->
|
||||
|
||||
For Tooling issues:
|
||||
- Node version: XX <!-- run `node --version` -->
|
||||
- Platform: <!-- Mac, Linux, Windows -->
|
||||
|
||||
Others:
|
||||
<!-- Anything else relevant? Operating system version, IDE, package manager, ... -->
|
||||
</code></pre>
|
||||
|
||||
138
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
Normal file
138
.github/ISSUE_TEMPLATE/Bug_report.yml
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
name: "\U0001F41B Bug Report"
|
||||
description: "If something isn't working as expected \U0001F914"
|
||||
labels: ["needs triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- use our [Discord community](https://discord.gg/NestJS)
|
||||
- use [StackOverflow using the tag `nestjs`](https://stackoverflow.com/questions/tagged/nestjs)
|
||||
- If it's just a quick question you can ping [our Twitter](https://twitter.com/nestframework)
|
||||
|
||||
**NOTE:** You don't need to answer questions that you know that aren't relevant.
|
||||
|
||||
---
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "Is there an existing issue for this?"
|
||||
description: "Please search [here](https://github.com/nestjs/nest/issues?q=is%3Aissue) to see if an issue already exists for the bug you encountered"
|
||||
options:
|
||||
- label: "I have searched the existing issues"
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Current behavior"
|
||||
description: "How the issue manifests?"
|
||||
|
||||
- type: input
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Minimum reproduction code"
|
||||
description: "An URL to some git repository that reproduces this issue. [Wtf is a minimum reproduction?](https://jmcdo29.github.io/wtf-is-a-minimum-reproduction)"
|
||||
placeholder: "https://github.com/..."
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Steps to reproduce"
|
||||
description: |
|
||||
How the issue manifests?
|
||||
You could leave this blank if you alread write this in your reproduction code
|
||||
placeholder: |
|
||||
1. `npm i`
|
||||
2. `npm start:dev`
|
||||
3. See error...
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Expected behavior"
|
||||
description: "A clear and concise description of what you expected to happend (or code)"
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
|
||||
- type: checkboxes
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Package"
|
||||
description: |
|
||||
Which package (or packages) do you think your issue is related to?
|
||||
**Tip**: The first line of the stack trace can help you to figure out this
|
||||
|
||||
The package isn't listed below? Try to find its repository [here](https://github.com/orgs/nestjs/repositories) and open the issue there instead
|
||||
options:
|
||||
- label: "I don't know. Or some 3rd-party package"
|
||||
- label: "<code>@nestjs/common</code>"
|
||||
- label: "<code>@nestjs/core</code>"
|
||||
- label: "<code>@nestjs/microservices</code>"
|
||||
- label: "<code>@nestjs/platform-express</code>"
|
||||
- label: "<code>@nestjs/platform-fastify</code>"
|
||||
- label: "<code>@nestjs/platform-socket.io</code>"
|
||||
- label: "<code>@nestjs/platform-ws</code>"
|
||||
- label: "<code>@nestjs/testing</code>"
|
||||
- label: "<code>@nestjs/websockets</code>"
|
||||
- label: "Other (see below)"
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Other package"
|
||||
description: "If your issue is related to some package that is not listed above nor under @nestjs org, write its name here"
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: "NestJS version"
|
||||
description: |
|
||||
Which version of `@nestjs/core` are you using?
|
||||
**Tip**: Make sure that all of yours `@nestjs/*` dependencies are in sync!
|
||||
placeholder: "8.1.3"
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Packages versions"
|
||||
description: "You could leave your whole `package.json` dependencies list here, or just indicates which version of `@nestjs/*` are you using"
|
||||
placeholder: |
|
||||
- `@nestjs/common`: 8.1.3
|
||||
- `@nestjs/platform-express`: 8.1.3
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Node.js version"
|
||||
description: "Which version of Node.js are you using?"
|
||||
placeholder: "14.17.6"
|
||||
|
||||
- type: checkboxes
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "In which operating systems have you tested?"
|
||||
options:
|
||||
- label: macOS
|
||||
- label: Windows
|
||||
- label: Linux
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
---
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Other"
|
||||
description: |
|
||||
Anything else relevant? eg: Logs, OS version, IDE, package manager, etc.
|
||||
**Tip:** You can attach images, recordings or log files by clicking this area to highlight it and then dragging files in
|
||||
22
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
22
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
@@ -1,22 +0,0 @@
|
||||
---
|
||||
name: "\U0001F680 Feature Request"
|
||||
about: "I have a suggestion \U0001F63B!"
|
||||
title: ''
|
||||
labels: 'type: enhancement :wolf:,needs triage'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Feature Request
|
||||
|
||||
## Is your feature request related to a problem? Please describe.
|
||||
<!-- A clear and concise description of what the problem is. Ex. I have an issue when [...] -->
|
||||
|
||||
## Describe the solution you'd like
|
||||
<!-- A clear and concise description of what you want to happen. Add any considered drawbacks. -->
|
||||
|
||||
## Teachability, Documentation, Adoption, Migration Strategy
|
||||
<!-- If you can, explain how users will be able to use this and possibly write out a version the docs. Maybe a screenshot or design? -->
|
||||
|
||||
## What is the motivation / use case for changing the behavior?
|
||||
<!-- Describe the motivation or the concrete use case. -->
|
||||
54
.github/ISSUE_TEMPLATE/Feature_request.yml
vendored
Normal file
54
.github/ISSUE_TEMPLATE/Feature_request.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: "\U0001F680 Feature Request"
|
||||
description: "I have a suggestion \U0001F63B!"
|
||||
labels: ["type: enhancement :wolf:", "needs triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- use our [Discord community](https://discord.gg/NestJS)
|
||||
- use [StackOverflow using the tag `nestjs`](https://stackoverflow.com/questions/tagged/nestjs)
|
||||
- If it's just a quick question you can ping [our Twitter](https://twitter.com/nestframework)
|
||||
|
||||
---
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "Is there an existing issue that is already proposing this?"
|
||||
description: "Please search [here](https://github.com/nestjs/nest/issues?q=is%3Aissue) to see if an issue already exists for the feature you are requesting"
|
||||
options:
|
||||
- label: "I have searched the existing issues"
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Is your feature request related to a problem? Please describe it"
|
||||
description: "A clear and concise description of what the problem is"
|
||||
placeholder: |
|
||||
I have an issue when ...
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Describe the solution you'd like"
|
||||
description: "A clear and concise description of what you want to happen. Add any considered drawbacks"
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Teachability, documentation, adoption, migration strategy"
|
||||
description: "If you can, explain how users will be able to use this and possibly write out a version the docs. Maybe a screenshot or design?"
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "What is the motivation / use case for changing the behavior?"
|
||||
description: "Describe the motivation or the concrete use case"
|
||||
40
.github/ISSUE_TEMPLATE/Regression.md
vendored
40
.github/ISSUE_TEMPLATE/Regression.md
vendored
@@ -1,40 +0,0 @@
|
||||
---
|
||||
name: "\U0001F4A5 Regression"
|
||||
about: Report an unexpected while upgrading your Nest application!
|
||||
title: ''
|
||||
labels: 'type: bug :sob:,needs triage'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Regression
|
||||
|
||||
<!-- First check out: https://docs.nestjs.com/migration-guide -->
|
||||
|
||||
## Potential Commit/PR that introduced the regression**
|
||||
<!-- If you have time to investigate, what PR/date introduced this issue. -->
|
||||
|
||||
## Describe the regression
|
||||
<!-- A clear and concise description of what the regression is. -->
|
||||
|
||||
## Input Code
|
||||
<!--- If you have link to our REPL or a standalone repo please link that! -->
|
||||
|
||||
```ts
|
||||
const your = (code) => here;
|
||||
```
|
||||
|
||||
## Expected behavior/code
|
||||
<!-- A clear and concise description of what you expected to happen (or code). -->
|
||||
|
||||
## Environment
|
||||
<pre><code>
|
||||
Nest version: A.B.C -> X.Y.Z
|
||||
|
||||
For Tooling issues:
|
||||
- Node version: XX <!-- run `node --version` -->
|
||||
- Platform: <!-- Mac, Linux, Windows -->
|
||||
|
||||
Others:
|
||||
<!-- Anything else relevant? Operating system version, IDE, package manager, ... -->
|
||||
</code></pre>
|
||||
83
.github/ISSUE_TEMPLATE/Regression.yml
vendored
Normal file
83
.github/ISSUE_TEMPLATE/Regression.yml
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
name: "\U0001F4A5 Regression"
|
||||
description: "Report an unexpected while upgrading your Nest application!"
|
||||
labels: ["type: bug :sob:", "needs triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
## :warning: We use GitHub Issues to track bug reports, feature requests and regressions
|
||||
|
||||
If you are not sure that your issue is a bug, you could:
|
||||
|
||||
- use our [Discord community](https://discord.gg/NestJS)
|
||||
- use [StackOverflow using the tag `nestjs`](https://stackoverflow.com/questions/tagged/nestjs)
|
||||
- If it's just a quick question you can ping [our Twitter](https://twitter.com/nestframework)
|
||||
|
||||
**NOTE:** You don't need to answer questions that you know that aren't relevant.
|
||||
|
||||
---
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "Did you read the migration guide?"
|
||||
description: "Check out the [migration guide here](https://docs.nestjs.com/migration-guide)!"
|
||||
options:
|
||||
- label: "I have read the whole migration guide"
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "Is there an existing issue that is already proposing this?"
|
||||
description: "Please search [here](https://github.com/nestjs/nest/issues?q=is%3Aissue) to see if an issue already exists for the feature you are requesting"
|
||||
options:
|
||||
- label: "I have searched the existing issues"
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Potential Commit/PR that introduced the regression"
|
||||
description: "If you have time to investigate, what PR/date/version introduced this issue"
|
||||
placeholder: "PR #123 or commit 5b3c4a4"
|
||||
|
||||
- type: input
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "NestJS version"
|
||||
placeholder: "8.1.0 -> 8.1.3"
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Describe the regression"
|
||||
description: "A clear and concise description of what the regression is"
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: "Minimum reproduction code"
|
||||
description: "An URL to some git repository that reproduces this issue. [Wtf is a minimum reproduction?](https://jmcdo29.github.io/wtf-is-a-minimum-reproduction)"
|
||||
placeholder: "https://github.com/..."
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Input code"
|
||||
description: "Write some code snippets if you think it is worth it"
|
||||
value: |
|
||||
```ts
|
||||
|
||||
```
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Expected behavior"
|
||||
description: "A clear and concise description of what you expected to happend (or code)"
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Other"
|
||||
description: |
|
||||
Anything else relevant? eg: Logs, OS version, IDE, package manager, etc.
|
||||
**Tip:** You can attach images, recordings or log files by clicking this area to highlight it and then dragging files in
|
||||
48
.github/ISSUE_TEMPLATE/Suggestion_improve_performance.yml
vendored
Normal file
48
.github/ISSUE_TEMPLATE/Suggestion_improve_performance.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
title: "perf: "
|
||||
name: "\U0001F525 Suggestion for Improving Performance"
|
||||
description: "I have a suggestion that might improve the performance of Nest \U00002728"
|
||||
labels: ["type: enhancement :wolf:", "needs triage"]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "Is there an existing issue that is already proposing this?"
|
||||
description: "Please search [here](https://github.com/nestjs/nest/issues?q=is%3Aissue) to see if an issue already exists for this"
|
||||
options:
|
||||
- label: "I have searched the existing issues"
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "NestJS version"
|
||||
description: "Which version do you intend to improve?"
|
||||
placeholder: "8.1.3"
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Is your performance suggestion related to a problem? Please describe it"
|
||||
description: "A clear and concise description of what the problem is"
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Describe the performance enhancement you are proposing and how we can try it out"
|
||||
placeholder: |
|
||||
Cache `array.length` on the following lines ...
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: "Benchmarks result or another proof (eg: POC)"
|
||||
description: |
|
||||
If you've already prototyped a solution, share your results here
|
||||
If not, what makes you believe there will be a performance improvement?
|
||||
placeholder: |
|
||||
```
|
||||
```
|
||||
|
||||
MacBook Pro Mid 2014, 2.5 GHz Quad-Core Intel Core i7, 16 GB 1600 MHz DDR3, SSD
|
||||
|
||||
14
.github/ISSUE_TEMPLATE/Support_question.md
vendored
14
.github/ISSUE_TEMPLATE/Support_question.md
vendored
@@ -1,14 +0,0 @@
|
||||
---
|
||||
name: "\U0001F917 Support Question"
|
||||
about: "If you have a question \U0001F4AC, please check out our Discord or StackOverflow!"
|
||||
title: ''
|
||||
labels: 'type: question 🙌,needs triage'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- We primarily use GitHub as an issue tracker; for usage and support questions, please check out these resources below. Thanks! 😁. -->
|
||||
|
||||
* Discord Community Chat: https://discord.gg/G7Qnnhy
|
||||
* StackOverflow: https://stackoverflow.com/questions/tagged/nestjs using the tag `nestjs`
|
||||
* Twitter: If it's just a quick question you can ping our Twitter: https://twitter.com/nestframework
|
||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
## To encourage contributors to use issue templates, we don't allow blank issues
|
||||
blank_issues_enabled: false
|
||||
|
||||
contact_links:
|
||||
- name: "\u2753 Discord Community of NestJS"
|
||||
url: "https://discord.gg/NestJS"
|
||||
about: "Please ask support questions or discuss suggestions/enhancements here."
|
||||
@@ -69,7 +69,7 @@ A minimal reproduce scenario using a repository or Gist allows us to quickly con
|
||||
|
||||
<!-- We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it. -->
|
||||
|
||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that don't have enough info to be reproduced.
|
||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.
|
||||
|
||||
You can file new issues by filling out our [new issue form](https://github.com/nestjs/nest/issues/new).
|
||||
|
||||
@@ -173,7 +173,7 @@ $ npm i # (or yarn install)
|
||||
$ sh scripts/prepare.sh
|
||||
```
|
||||
|
||||
That will compile fresh packages and afterward, move them to all `sample` directories as well as integration tests.
|
||||
That will compile fresh packages and afterward, move them all to `sample` directories.
|
||||
|
||||
### <a name="common-scripts"></a>Commonly used NPM scripts
|
||||
|
||||
@@ -228,7 +228,7 @@ format that includes a **type**, a **scope** and a **subject**:
|
||||
|
||||
The **header** is mandatory and the **scope** of the header is optional.
|
||||
|
||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
|
||||
to read on GitHub as well as in various git tools.
|
||||
|
||||
Footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||
|
||||
13
Readme.md
13
Readme.md
@@ -67,8 +67,11 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
|
||||
<table style="text-align:center;"><tr><td>
|
||||
<a href="https://careers.labster.com/departments/platform" target="_blank"><img src="https://nestjs.com/img/labster-logo.png" width="170" valign="middle" /></a></td><td>
|
||||
<a href="https://weld.so/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="150" valign="middle" /></a></td><td>
|
||||
<a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td></tr></table>
|
||||
<a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="150" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td></</tr></table>
|
||||
|
||||
#### Silver Sponsors
|
||||
|
||||
@@ -76,8 +79,9 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<a href="https://neoteric.eu/" target="_blank"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" valign="middle" /></a> </td><td>
|
||||
<a href="http://gojob.com" target="_blank"><img src="http://nestjs.com/img/gojob-logo.png" valign="middle" width="100" /></a> </td><td>
|
||||
<a href="http://www.leogistics.com" target="_blank"><img src="https://nestjs.com/img/leogistics-logo.jpeg" width="150" valign="middle" /></td><td>
|
||||
<a href="http://www.meetdandy.com" target="_blank"><img src="https://nestjs.com/img/dandy-wide-logo.png" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td></tr></table>
|
||||
<a href="https://careers.meetdandy.com/?gh_src=063ba61e3us" target="_blank"><img src="https://nestjs.com/img/dandy-roles-logo.svg" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td>
|
||||
<td><a href="https://www.tinystacks.com" target="_blank"><img src="https://nestjs.com/img/tinystacks-logo.png#1" width="140" valign="middle" /></td></tr></table>
|
||||
|
||||
#### Sponsors
|
||||
|
||||
@@ -108,6 +112,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://www.bystored.com/" target="_blank"><img src="https://nestjs.com/img/stored-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://studyclerk.com/pay-for-research-paper" target="_blank"><img src="https://nestjs.com/img/studyclerk-logo.png" width="125" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://xyndata.com" target="_blank"><img src="https://nestjs.com/img/xyndata-logo.png" width="125" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
5
SECURITY.md
Normal file
5
SECURITY.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report security issues to `support@nestjs.com`.
|
||||
@@ -3,7 +3,8 @@ import * as redisStore from 'cache-manager-redis-store';
|
||||
import { MultiStoreController } from './multi-store.controller';
|
||||
|
||||
@Module({
|
||||
imports: [CacheModule.register([
|
||||
imports: [
|
||||
CacheModule.register([
|
||||
{
|
||||
store: 'memory',
|
||||
max: 100,
|
||||
@@ -14,10 +15,10 @@ import { MultiStoreController } from './multi-store.controller';
|
||||
host: 'localhost',
|
||||
port: 6379,
|
||||
db: 0,
|
||||
ttl: 600
|
||||
}
|
||||
],
|
||||
)],
|
||||
ttl: 600,
|
||||
},
|
||||
]),
|
||||
],
|
||||
controllers: [MultiStoreController],
|
||||
})
|
||||
export class MultiStoreModule {}
|
||||
|
||||
@@ -43,7 +43,7 @@ describe('Express Cors', () => {
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the first config`, async () => {
|
||||
it(`should add cors headers based on the first config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.expect('access-control-allow-origin', 'example.com')
|
||||
@@ -53,7 +53,7 @@ describe('Express Cors', () => {
|
||||
.expect('content-length', '0');
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the second config`, async () => {
|
||||
it(`should add cors headers based on the second config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.options('/')
|
||||
.expect('access-control-allow-origin', 'sample.com')
|
||||
@@ -91,7 +91,7 @@ describe('Express Cors', () => {
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the first config`, async () => {
|
||||
it(`should add cors headers based on the first config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.expect('access-control-allow-origin', 'example.com')
|
||||
@@ -101,7 +101,7 @@ describe('Express Cors', () => {
|
||||
.expect('content-length', '0');
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the second config`, async () => {
|
||||
it(`should add cors headers based on the second config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.options('/')
|
||||
.expect('access-control-allow-origin', 'sample.com')
|
||||
|
||||
@@ -43,7 +43,7 @@ describe('Fastify Cors', () => {
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the first config`, async () => {
|
||||
it(`should add cors headers based on the first config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.expect('access-control-allow-origin', 'example.com')
|
||||
@@ -53,7 +53,7 @@ describe('Fastify Cors', () => {
|
||||
.expect('content-length', '0');
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the second config`, async () => {
|
||||
it(`should add cors headers based on the second config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.options('/')
|
||||
.expect('access-control-allow-origin', 'sample.com')
|
||||
@@ -91,7 +91,7 @@ describe('Fastify Cors', () => {
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the first config`, async () => {
|
||||
it(`should add cors headers based on the first config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.expect('access-control-allow-origin', 'example.com')
|
||||
@@ -101,7 +101,7 @@ describe('Fastify Cors', () => {
|
||||
.expect('content-length', '0');
|
||||
});
|
||||
|
||||
it(`Should add cors headers based on the second config`, async () => {
|
||||
it(`should add cors headers based on the second config`, async () => {
|
||||
return request(app.getHttpServer())
|
||||
.options('/')
|
||||
.expect('access-control-allow-origin', 'sample.com')
|
||||
@@ -147,6 +147,7 @@ describe('Fastify Cors', () => {
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
describe('Application Options', () => {
|
||||
before(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
|
||||
@@ -23,7 +23,7 @@ services:
|
||||
- "9001:9001"
|
||||
restart: always
|
||||
mysql:
|
||||
image: mysql:5.7.34
|
||||
image: mysql:8.0.27
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
MYSQL_DATABASE: test
|
||||
@@ -48,7 +48,7 @@ services:
|
||||
zookeeper:
|
||||
container_name: test-zookeeper
|
||||
hostname: zookeeper
|
||||
image: confluentinc/cp-zookeeper:6.2.0
|
||||
image: confluentinc/cp-zookeeper:6.2.1
|
||||
ports:
|
||||
- "2181:2181"
|
||||
environment:
|
||||
@@ -57,7 +57,7 @@ services:
|
||||
kafka:
|
||||
container_name: test-kafka
|
||||
hostname: kafka
|
||||
image: confluentinc/cp-kafka:6.2.0
|
||||
image: confluentinc/cp-kafka:7.0.0
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
|
||||
@@ -30,28 +30,16 @@ describe('GraphQL Pipes', () => {
|
||||
errors: [
|
||||
{
|
||||
extensions: {
|
||||
code: 'INTERNAL_SERVER_ERROR',
|
||||
exception: {
|
||||
message: 'Bad Request Exception',
|
||||
name: 'BadRequestException',
|
||||
response: {
|
||||
message: [
|
||||
'description must be longer than or equal to 30 characters',
|
||||
],
|
||||
error: 'Bad Request',
|
||||
statusCode: 400,
|
||||
},
|
||||
status: 400,
|
||||
code: 'BAD_USER_INPUT',
|
||||
response: {
|
||||
error: 'Bad Request',
|
||||
message: [
|
||||
'description must be longer than or equal to 30 characters',
|
||||
],
|
||||
statusCode: 400,
|
||||
},
|
||||
},
|
||||
locations: [
|
||||
{
|
||||
column: 3,
|
||||
line: 2,
|
||||
},
|
||||
],
|
||||
message: 'Bad Request Exception',
|
||||
path: ['addRecipe'],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NotFoundException, UseGuards, UseInterceptors } from '@nestjs/common';
|
||||
import { Args, Mutation, Query, Resolver, Subscription } from '@nestjs/graphql';
|
||||
import { PubSub } from 'apollo-server-express';
|
||||
import { PubSub } from 'graphql-subscriptions';
|
||||
import { AuthGuard } from '../common/guards/auth.guard';
|
||||
import { DataInterceptor } from '../common/interceptors/data.interceptor';
|
||||
import { NewRecipeInput } from './dto/new-recipe.input';
|
||||
|
||||
@@ -25,6 +25,11 @@ class TestController {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('test/test')
|
||||
testTest() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('test2')
|
||||
test2() {
|
||||
return RETURN_VALUE;
|
||||
@@ -85,6 +90,12 @@ describe('Exclude middleware (fastify)', () => {
|
||||
return request(app.getHttpServer()).get('/test').expect(200, RETURN_VALUE);
|
||||
});
|
||||
|
||||
it(`should not exclude "/test/test" endpoint`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/test/test')
|
||||
.expect(200, MIDDLEWARE_VALUE);
|
||||
});
|
||||
|
||||
it(`should not exclude "/test2" endpoint`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/test2')
|
||||
|
||||
@@ -5,17 +5,21 @@ import {
|
||||
Injectable,
|
||||
MiddlewareConsumer,
|
||||
Module,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
import { Response } from 'express';
|
||||
|
||||
const INCLUDED_VALUE = 'test_included';
|
||||
const RETURN_VALUE = 'test';
|
||||
const WILDCARD_VALUE = 'test_wildcard';
|
||||
|
||||
@Injectable()
|
||||
class Middleware {
|
||||
use(req, res, next) {
|
||||
res.send(RETURN_VALUE);
|
||||
res.send(WILDCARD_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +27,7 @@ class Middleware {
|
||||
class TestController {
|
||||
@Get('test')
|
||||
test() {
|
||||
return 'test';
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +37,11 @@ class TestController {
|
||||
})
|
||||
class TestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(Middleware).forRoutes('*');
|
||||
consumer
|
||||
.apply((req, res: Response, next) => res.status(201).end(INCLUDED_VALUE))
|
||||
.forRoutes({ path: 'tests/included', method: RequestMethod.POST })
|
||||
.apply(Middleware)
|
||||
.forRoutes('*');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +59,27 @@ describe('Middleware (class)', () => {
|
||||
});
|
||||
|
||||
it(`forRoutes(*)`, () => {
|
||||
return request(app.getHttpServer()).get('/hello').expect(200, RETURN_VALUE);
|
||||
return request(app.getHttpServer())
|
||||
.get('/hello')
|
||||
.expect(200, WILDCARD_VALUE);
|
||||
});
|
||||
|
||||
it(`/test forRoutes(*)`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/test')
|
||||
.expect(200, WILDCARD_VALUE);
|
||||
});
|
||||
|
||||
it(`GET forRoutes(POST tests/included)`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/tests/included')
|
||||
.expect(200, WILDCARD_VALUE);
|
||||
});
|
||||
|
||||
it(`POST forRoutes(POST tests/included)`, () => {
|
||||
return request(app.getHttpServer())
|
||||
.post('/tests/included')
|
||||
.expect(201, INCLUDED_VALUE);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { Controller, Get, MiddlewareConsumer, Module } from '@nestjs/common';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
MiddlewareConsumer,
|
||||
Module,
|
||||
Query,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
@@ -7,35 +14,70 @@ import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const INCLUDED_VALUE = 'test_included';
|
||||
const QUERY_VALUE = 'test_query';
|
||||
const REQ_URL_VALUE = 'test_req_url';
|
||||
const RETURN_VALUE = 'test';
|
||||
const SCOPED_VALUE = 'test_scoped';
|
||||
const WILDCARD_VALUE = 'test_wildcard';
|
||||
|
||||
@Controller()
|
||||
class TestController {
|
||||
@Get('express_style_wildcard/wildcard_nested')
|
||||
express_style_wildcard() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('test')
|
||||
test() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('query')
|
||||
query() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/wildcard_nested')
|
||||
wildcard_nested() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/included')
|
||||
included() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Controller(QUERY_VALUE)
|
||||
class TestQueryController {
|
||||
@Get()
|
||||
[QUERY_VALUE](@Query('test') test: string) {
|
||||
return test;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController],
|
||||
controllers: [TestController, TestQueryController],
|
||||
})
|
||||
class TestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res, next) => res.end(INCLUDED_VALUE))
|
||||
.forRoutes({ path: 'tests/included', method: RequestMethod.POST })
|
||||
.apply((req, res, next) => res.end(`${REQ_URL_VALUE}${req.url}`))
|
||||
.forRoutes('req/url/')
|
||||
.apply((req, res, next) => res.end(WILDCARD_VALUE))
|
||||
.forRoutes('tests/(.*)')
|
||||
.forRoutes('express_style_wildcard/*', 'tests/(.*)')
|
||||
.apply((req, res, next) => res.end(QUERY_VALUE))
|
||||
.forRoutes('query')
|
||||
.apply((req, res, next) => next())
|
||||
.forRoutes(TestQueryController)
|
||||
.apply((req, res, next) => res.end(SCOPED_VALUE))
|
||||
.forRoutes(TestController)
|
||||
.apply((req, res, next) => res.end(RETURN_VALUE))
|
||||
.exclude({ path: QUERY_VALUE, method: -1 })
|
||||
.forRoutes('(.*)');
|
||||
}
|
||||
}
|
||||
@@ -53,7 +95,7 @@ describe('Middleware (FastifyAdapter)', () => {
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`forRoutes(*)`, () => {
|
||||
it(`forRoutes((.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
@@ -71,15 +113,78 @@ describe('Middleware (FastifyAdapter)', () => {
|
||||
.then(({ payload }) => expect(payload).to.be.eql(SCOPED_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(tests/*)`, () => {
|
||||
it(`query?test=${QUERY_VALUE} forRoutes(query)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/wildcard',
|
||||
url: '/query',
|
||||
query: {
|
||||
test: QUERY_VALUE,
|
||||
},
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
it(`${QUERY_VALUE}?test=${QUERY_VALUE} forRoutes(${QUERY_VALUE})`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: QUERY_VALUE,
|
||||
query: {
|
||||
test: QUERY_VALUE,
|
||||
},
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(tests/(.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(express_style_wildcard/*)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/express_style_wildcard/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(req/url/)`, () => {
|
||||
const reqUrl = '/test';
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: `/req/url${reqUrl}`,
|
||||
})
|
||||
.then(({ payload }) =>
|
||||
expect(payload).to.be.eql(`${REQ_URL_VALUE}${reqUrl}`),
|
||||
);
|
||||
});
|
||||
|
||||
it(`GET forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`POST forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'POST',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(INCLUDED_VALUE));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -16,7 +16,8 @@ class TestInjectable
|
||||
OnModuleInit,
|
||||
OnModuleDestroy,
|
||||
OnApplicationShutdown,
|
||||
BeforeApplicationShutdown {
|
||||
BeforeApplicationShutdown
|
||||
{
|
||||
onApplicationBootstrap = Sinon.spy();
|
||||
beforeApplicationShutdown = Sinon.spy();
|
||||
onApplicationShutdown = Sinon.spy();
|
||||
|
||||
@@ -10,7 +10,8 @@ const SIGNAL_TO_LISTEN = process.argv[3];
|
||||
|
||||
@Injectable()
|
||||
class TestInjectable
|
||||
implements OnApplicationShutdown, BeforeApplicationShutdown {
|
||||
implements OnApplicationShutdown, BeforeApplicationShutdown
|
||||
{
|
||||
beforeApplicationShutdown(signal: string) {
|
||||
console.log('beforeApplicationShutdown ' + signal);
|
||||
}
|
||||
|
||||
@@ -14,9 +14,8 @@ describe('Core Injectables', () => {
|
||||
});
|
||||
|
||||
it('should provide ApplicationConfig as core injectable', () => {
|
||||
const applicationConfig = testingModule.get<ApplicationConfig>(
|
||||
ApplicationConfig,
|
||||
);
|
||||
const applicationConfig =
|
||||
testingModule.get<ApplicationConfig>(ApplicationConfig);
|
||||
|
||||
applicationConfig.setGlobalPrefix('/api');
|
||||
|
||||
|
||||
46
integration/microservices/e2e/mqtt-record-builder.spec.ts
Normal file
46
integration/microservices/e2e/mqtt-record-builder.spec.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { Transport } from '@nestjs/microservices';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { MqttController } from '../src/mqtt/mqtt.controller';
|
||||
|
||||
describe('MQTT transport', () => {
|
||||
let server;
|
||||
let app: INestApplication;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
controllers: [MqttController],
|
||||
}).compile();
|
||||
|
||||
app = module.createNestApplication();
|
||||
server = app.getHttpAdapter().getInstance();
|
||||
|
||||
app.connectMicroservice({
|
||||
transport: Transport.MQTT,
|
||||
options: {
|
||||
url: 'mqtt://0.0.0.0:1883',
|
||||
subscribeOptions: {
|
||||
qos: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.startAllMicroservices();
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`/POST (setting packet options with "RecordBuilder")`, () => {
|
||||
const payload = { items: [1, 2, 3] };
|
||||
return request(server)
|
||||
.post('/record-builder-duplex')
|
||||
.send(payload)
|
||||
.expect(200, {
|
||||
data: payload,
|
||||
qos: 1,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
@@ -96,6 +96,19 @@ describe('NATS transport', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it(`/POST (sending headers with "RecordBuilder")`, () => {
|
||||
const payload = { items: [1, 2, 3] };
|
||||
return request(server)
|
||||
.post('/record-builder-duplex')
|
||||
.send(payload)
|
||||
.expect(200, {
|
||||
data: payload,
|
||||
headers: {
|
||||
['x-version']: '1.0.0',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -89,6 +89,20 @@ describe('RabbitMQ transport', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it(`/POST (sending options with "RecordBuilder")`, () => {
|
||||
const payload = { items: [1, 2, 3] };
|
||||
return request(server)
|
||||
.post('/record-builder-duplex')
|
||||
.send(payload)
|
||||
.expect(200, {
|
||||
data: payload,
|
||||
headers: {
|
||||
['x-version']: '1.0.0',
|
||||
},
|
||||
priority: 3,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -59,14 +59,15 @@ class ClientOptionService implements ClientsModuleOptionsFactory {
|
||||
name: 'USE_CLASS_CLIENT',
|
||||
useClass: ClientOptionService,
|
||||
inject: [ConfigService],
|
||||
}, {
|
||||
},
|
||||
{
|
||||
imports: [ConfigModule],
|
||||
inject: [ConfigService],
|
||||
name: 'CUSTOM_PROXY_CLIENT',
|
||||
useFactory: (config: ConfigService) => ({
|
||||
customClass: ErrorHandlingProxy
|
||||
})
|
||||
}
|
||||
customClass: ErrorHandlingProxy,
|
||||
}),
|
||||
},
|
||||
]),
|
||||
],
|
||||
controllers: [AppController],
|
||||
|
||||
@@ -14,23 +14,21 @@ export class DisconnectedClientController {
|
||||
@Post()
|
||||
call(@Body() options): Observable<number> {
|
||||
const client = ClientProxyFactory.create(options);
|
||||
return client
|
||||
.send<number, number[]>({ cmd: 'none' }, [1, 2, 3])
|
||||
.pipe(
|
||||
/*tap(
|
||||
return client.send<number, number[]>({ cmd: 'none' }, [1, 2, 3]).pipe(
|
||||
/*tap(
|
||||
console.log.bind(console, 'data'),
|
||||
console.error.bind(console, 'error'),
|
||||
),*/
|
||||
catchError(error => {
|
||||
const { code } = error || { code: 'CONN_ERR' };
|
||||
return throwError(() =>
|
||||
code === 'ECONNREFUSED' ||
|
||||
code === 'CONN_ERR' ||
|
||||
code === 'CONNECTION_REFUSED'
|
||||
? new RequestTimeoutException('ECONNREFUSED')
|
||||
: new InternalServerErrorException(),
|
||||
);
|
||||
}),
|
||||
);
|
||||
catchError(error => {
|
||||
const { code } = error || { code: 'CONN_ERR' };
|
||||
return throwError(() =>
|
||||
code === 'ECONNREFUSED' ||
|
||||
code === 'CONN_ERR' ||
|
||||
code === 'CONNECTION_REFUSED'
|
||||
? new RequestTimeoutException('ECONNREFUSED')
|
||||
: new InternalServerErrorException(),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ const explicitPartitioner = () => {
|
||||
|
||||
@Controller()
|
||||
export class KafkaConcurrentController
|
||||
implements OnModuleInit, OnModuleDestroy {
|
||||
implements OnModuleInit, OnModuleDestroy
|
||||
{
|
||||
protected readonly logger = new Logger(KafkaConcurrentController.name);
|
||||
|
||||
@Client({
|
||||
|
||||
@@ -2,8 +2,12 @@ import { Body, Controller, HttpCode, Post, Query } from '@nestjs/common';
|
||||
import {
|
||||
Client,
|
||||
ClientProxy,
|
||||
Ctx,
|
||||
EventPattern,
|
||||
MessagePattern,
|
||||
MqttContext,
|
||||
MqttRecordBuilder,
|
||||
Payload,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { from, lastValueFrom, Observable, of } from 'rxjs';
|
||||
@@ -32,7 +36,7 @@ export class MqttController {
|
||||
@HttpCode(200)
|
||||
async stream(@Body() data: number[]) {
|
||||
const result = lastValueFrom(
|
||||
await this.client
|
||||
this.client
|
||||
.send<number>({ cmd: 'streaming' }, data)
|
||||
.pipe(scan((a, b) => a + b, 0)),
|
||||
);
|
||||
@@ -86,6 +90,25 @@ export class MqttController {
|
||||
return this.client.send<number>('wildcard-message2/test/test', data);
|
||||
}
|
||||
|
||||
@Post('record-builder-duplex')
|
||||
@HttpCode(200)
|
||||
useRecordBuilderDuplex(@Body() data: Record<string, any>) {
|
||||
const record = new MqttRecordBuilder(data).setQoS(2).build();
|
||||
return this.client.send('record-builder-duplex', record);
|
||||
}
|
||||
|
||||
@MessagePattern('record-builder-duplex')
|
||||
handleRecordBuilderDuplex(
|
||||
@Payload() data: Record<string, any>,
|
||||
@Ctx() context: MqttContext,
|
||||
) {
|
||||
const { qos } = context.getPacket();
|
||||
return {
|
||||
data,
|
||||
qos,
|
||||
};
|
||||
}
|
||||
|
||||
@MessagePattern('wildcard-message/#')
|
||||
wildcardMessageHandler(data: number[]): number {
|
||||
if ((data as any).response) {
|
||||
|
||||
@@ -6,10 +6,12 @@ import {
|
||||
EventPattern,
|
||||
MessagePattern,
|
||||
NatsContext,
|
||||
NatsRecordBuilder,
|
||||
Payload,
|
||||
RpcException,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import * as nats from 'nats';
|
||||
import { from, lastValueFrom, Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, scan } from 'rxjs/operators';
|
||||
import { NatsService } from './nats.service';
|
||||
@@ -62,6 +64,28 @@ export class NatsController {
|
||||
.reduce(async (a, b) => (await a) && b);
|
||||
}
|
||||
|
||||
@Post('record-builder-duplex')
|
||||
@HttpCode(200)
|
||||
useRecordBuilderDuplex(@Body() data: Record<string, any>) {
|
||||
const headers = nats.headers();
|
||||
headers.set('x-version', '1.0.0');
|
||||
const record = new NatsRecordBuilder(data).setHeaders(headers).build();
|
||||
return this.client.send('record-builder-duplex', record);
|
||||
}
|
||||
|
||||
@MessagePattern('record-builder-duplex')
|
||||
handleRecordBuilderDuplex(
|
||||
@Payload() data: Record<string, any>,
|
||||
@Ctx() context: NatsContext,
|
||||
) {
|
||||
return {
|
||||
data,
|
||||
headers: {
|
||||
['x-version']: context.getHeaders().get('x-version'),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@MessagePattern('math.*')
|
||||
sum(@Payload() data: number[], @Ctx() context: NatsContext): number {
|
||||
return (data || []).reduce((a, b) => a + b);
|
||||
|
||||
@@ -2,8 +2,12 @@ import { Body, Controller, HttpCode, Post, Query } from '@nestjs/common';
|
||||
import {
|
||||
ClientProxy,
|
||||
ClientProxyFactory,
|
||||
Ctx,
|
||||
EventPattern,
|
||||
MessagePattern,
|
||||
Payload,
|
||||
RmqContext,
|
||||
RmqRecordBuilder,
|
||||
Transport,
|
||||
} from '@nestjs/microservices';
|
||||
import { from, lastValueFrom, Observable, of } from 'rxjs';
|
||||
@@ -57,6 +61,34 @@ export class RMQController {
|
||||
.reduce(async (a, b) => (await a) && b);
|
||||
}
|
||||
|
||||
@Post('record-builder-duplex')
|
||||
@HttpCode(200)
|
||||
useRecordBuilderDuplex(@Body() data: Record<string, any>) {
|
||||
const record = new RmqRecordBuilder(data)
|
||||
.setOptions({
|
||||
headers: {
|
||||
['x-version']: '1.0.0',
|
||||
},
|
||||
priority: 3,
|
||||
})
|
||||
.build();
|
||||
|
||||
return this.client.send('record-builder-duplex', record);
|
||||
}
|
||||
|
||||
@MessagePattern('record-builder-duplex')
|
||||
handleRecordBuilderDuplex(
|
||||
@Payload() data: Record<string, any>,
|
||||
@Ctx() context: RmqContext,
|
||||
) {
|
||||
const originalMessage = context.getMessage();
|
||||
return {
|
||||
data,
|
||||
headers: originalMessage.properties.headers,
|
||||
priority: originalMessage.properties.priority,
|
||||
};
|
||||
}
|
||||
|
||||
@MessagePattern({ cmd: 'sum' })
|
||||
sum(data: number[]): number {
|
||||
return (data || []).reduce((a, b) => a + b);
|
||||
|
||||
@@ -2,7 +2,11 @@ import { INestApplication } from '@nestjs/common';
|
||||
import { RequestMethod } from '@nestjs/common/enums/request-method.enum';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import {
|
||||
AppModule,
|
||||
MIDDLEWARE_PARAM_VALUE,
|
||||
MIDDLEWARE_VALUE,
|
||||
} from '../src/app.module';
|
||||
|
||||
describe('Global prefix', () => {
|
||||
let server;
|
||||
@@ -28,21 +32,29 @@ describe('Global prefix', () => {
|
||||
});
|
||||
|
||||
it(`should exclude the path as string`, async () => {
|
||||
app.setGlobalPrefix('/api/v1', { exclude: ['/test'] });
|
||||
app.setGlobalPrefix('/api/v1', { exclude: ['/test', '/middleware'] });
|
||||
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
|
||||
await request(server).get('/test').expect(200);
|
||||
await request(server).post('/test').expect(201);
|
||||
|
||||
await request(server).get('/api/v1/test').expect(404);
|
||||
await request(server).post('/api/v1/test').expect(404);
|
||||
|
||||
await request(server).get('/middleware').expect(200, MIDDLEWARE_VALUE);
|
||||
await request(server).post('/middleware').expect(201, MIDDLEWARE_VALUE);
|
||||
|
||||
await request(server).get('/api/v1/middleware').expect(404);
|
||||
await request(server).post('/api/v1/middleware').expect(404);
|
||||
});
|
||||
|
||||
it(`should exclude the path as RouteInfo`, async () => {
|
||||
app.setGlobalPrefix('/api/v1', {
|
||||
exclude: [{ path: '/health', method: RequestMethod.GET }],
|
||||
exclude: [
|
||||
{ path: '/health', method: RequestMethod.GET },
|
||||
{ path: '/middleware', method: RequestMethod.POST },
|
||||
],
|
||||
});
|
||||
|
||||
server = app.getHttpServer();
|
||||
@@ -50,7 +62,15 @@ describe('Global prefix', () => {
|
||||
|
||||
await request(server).get('/health').expect(200);
|
||||
|
||||
await request(server).get('/middleware').expect(404);
|
||||
await request(server).post('/middleware').expect(201, MIDDLEWARE_VALUE);
|
||||
|
||||
await request(server).get('/api/v1/health').expect(404);
|
||||
|
||||
await request(server)
|
||||
.get('/api/v1/middleware')
|
||||
.expect(200, MIDDLEWARE_VALUE);
|
||||
await request(server).post('/api/v1/middleware').expect(404);
|
||||
});
|
||||
|
||||
it(`should only exclude the GET RequestMethod`, async () => {
|
||||
@@ -82,12 +102,22 @@ describe('Global prefix', () => {
|
||||
});
|
||||
|
||||
it(`should exclude the path with route param`, async () => {
|
||||
app.setGlobalPrefix('/api/v1', { exclude: ['/hello/:name'] });
|
||||
app.setGlobalPrefix('/api/v1', {
|
||||
exclude: ['/hello/:name', '/middleware/:name'],
|
||||
});
|
||||
|
||||
server = app.getHttpServer();
|
||||
await app.init();
|
||||
|
||||
await request(server).get('/hello/foo').expect(200);
|
||||
|
||||
await request(server)
|
||||
.get('/middleware/foo')
|
||||
.expect(200, MIDDLEWARE_PARAM_VALUE);
|
||||
|
||||
await request(server)
|
||||
.get('/api/v1/middleware/foo')
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
||||
@@ -1,7 +1,22 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
|
||||
export const MIDDLEWARE_VALUE = 'middleware';
|
||||
export const MIDDLEWARE_PARAM_VALUE = 'middleware_param';
|
||||
|
||||
@Module({
|
||||
controllers: [AppController],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res, next) => res.end(MIDDLEWARE_VALUE))
|
||||
.forRoutes({ path: MIDDLEWARE_VALUE, method: RequestMethod.GET })
|
||||
.apply((req, res, next) => res.status(201).end(MIDDLEWARE_VALUE))
|
||||
.forRoutes({ path: MIDDLEWARE_VALUE, method: RequestMethod.POST })
|
||||
.apply((req, res, next) => res.end(MIDDLEWARE_PARAM_VALUE))
|
||||
.forRoutes({ path: MIDDLEWARE_VALUE + '/*', method: RequestMethod.GET })
|
||||
.apply((req, res, next) => res.status(201).end(MIDDLEWARE_PARAM_VALUE))
|
||||
.forRoutes({ path: MIDDLEWARE_VALUE + '/*', method: RequestMethod.POST });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { ExpressAdapter, NestExpressApplication } from '@nestjs/platform-express';
|
||||
import {
|
||||
ExpressAdapter,
|
||||
NestExpressApplication,
|
||||
} from '@nestjs/platform-express';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { readFileSync } from 'fs';
|
||||
@@ -24,7 +27,7 @@ describe('Express FileSend', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/file/stream/')
|
||||
.expect(200)
|
||||
.expect((res) => {
|
||||
.expect(res => {
|
||||
expect(res.body.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
});
|
||||
@@ -32,7 +35,7 @@ describe('Express FileSend', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/file/buffer')
|
||||
.expect(200)
|
||||
.expect((res) => {
|
||||
.expect(res => {
|
||||
expect(res.body.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
});
|
||||
@@ -46,8 +49,18 @@ describe('Express FileSend', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/file/rxjs/stream/')
|
||||
.expect(200)
|
||||
.expect((res) => {
|
||||
.expect(res => {
|
||||
expect(res.body.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
});
|
||||
});
|
||||
it('should return a file with correct content type and disposition', async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/file/with/headers')
|
||||
.expect(200)
|
||||
.expect('Content-Type', 'text/markdown')
|
||||
.expect('Content-Disposition', 'attachment; filename="Readme.md"')
|
||||
.expect(res => {
|
||||
expect(res.text).to.be.eq(readmeString);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { readFileSync } from 'fs';
|
||||
@@ -20,20 +23,24 @@ describe('Fastify FileSend', () => {
|
||||
});
|
||||
|
||||
it('should return a file from a stream', async () => {
|
||||
return app.inject({
|
||||
method: 'GET',
|
||||
url: '/file/stream'
|
||||
}).then(({ payload }) => {
|
||||
expect(payload.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/file/stream',
|
||||
})
|
||||
.then(({ payload }) => {
|
||||
expect(payload.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
});
|
||||
it('should return a file from a buffer', async () => {
|
||||
return app.inject({
|
||||
method: 'GET',
|
||||
url: '/file/buffer',
|
||||
}).then(({ payload }) => {
|
||||
expect(payload.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/file/buffer',
|
||||
})
|
||||
.then(({ payload }) => {
|
||||
expect(payload.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
});
|
||||
/**
|
||||
* It seems that Fastify has a similar issue as Kamil initially pointed out
|
||||
@@ -41,19 +48,23 @@ describe('Fastify FileSend', () => {
|
||||
* that the `NonFile` test is a failed case for fastify, hence the skip.
|
||||
*/
|
||||
it.skip('should not stream a non-file', async () => {
|
||||
return app.inject({
|
||||
url: '/non-file/pipe-method',
|
||||
method: 'get'
|
||||
}).then(({ payload }) => {
|
||||
expect(payload).to.be.eq({ value: 'Hello world' });
|
||||
});
|
||||
return app
|
||||
.inject({
|
||||
url: '/non-file/pipe-method',
|
||||
method: 'get',
|
||||
})
|
||||
.then(({ payload }) => {
|
||||
expect(payload).to.be.eq({ value: 'Hello world' });
|
||||
});
|
||||
});
|
||||
it('should return a file from an RxJS stream', async () => {
|
||||
return app.inject({
|
||||
method: 'GET',
|
||||
url: '/file/rxjs/stream'
|
||||
}).then(({ payload }) => {
|
||||
expect(payload.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/file/rxjs/stream',
|
||||
})
|
||||
.then(({ payload }) => {
|
||||
expect(payload.toString()).to.be.eq(readmeString);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -26,4 +26,9 @@ export class AppController {
|
||||
getRxJSFile(): Observable<StreamableFile> {
|
||||
return this.appService.getRxJSFile();
|
||||
}
|
||||
}
|
||||
|
||||
@Get('file/with/headers')
|
||||
getFileWithHeaders(): StreamableFile {
|
||||
return this.appService.getFileWithHeaders();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ import { AppService } from './app.service';
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule {}
|
||||
export class AppModule {}
|
||||
|
||||
@@ -23,4 +23,14 @@ export class AppService {
|
||||
getRxJSFile(): Observable<StreamableFile> {
|
||||
return of(this.getReadStream());
|
||||
}
|
||||
|
||||
getFileWithHeaders(): StreamableFile {
|
||||
return new StreamableFile(
|
||||
createReadStream(join(process.cwd(), 'Readme.md')),
|
||||
{
|
||||
type: 'text/markdown',
|
||||
disposition: 'attachment; filename="Readme.md"',
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@ export class NonFile {
|
||||
pipe() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
673
integration/versioning/e2e/header-versioning-fastify.spec.ts
Normal file
673
integration/versioning/e2e/header-versioning-fastify.spec.ts
Normal file
@@ -0,0 +1,673 @@
|
||||
import { INestApplication, VersioningType } from '@nestjs/common';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe('Header Versioning (fastify)', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
// ======================================================================== //
|
||||
describe('without global default version', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app.enableVersioning({
|
||||
type: VersioningType.HEADER,
|
||||
header: 'X-API-Version',
|
||||
});
|
||||
await app.init();
|
||||
await app.getHttpAdapter().getInstance().ready();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================== //
|
||||
describe('with the global default version: "1"', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app.enableVersioning({
|
||||
type: VersioningType.HEADER,
|
||||
header: 'X-API-Version',
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
await app.getHttpAdapter().getInstance().ready();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/foo/bar').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,282 +3,661 @@ import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe('Versioning', () => {
|
||||
describe('Header Versioning', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
// ======================================================================== //
|
||||
describe('without global default version', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.HEADER,
|
||||
header: 'X-API-Version',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.HEADER,
|
||||
header: 'X-API-Version',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
// ======================================================================== //
|
||||
describe('with the global default version: "1"', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.HEADER,
|
||||
header: 'X-API-Version',
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/foo/bar').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
'X-API-Version': '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override-partial').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
673
integration/versioning/e2e/media-type-versioning-fastify.spec.ts
Normal file
673
integration/versioning/e2e/media-type-versioning-fastify.spec.ts
Normal file
@@ -0,0 +1,673 @@
|
||||
import { INestApplication, VersioningType } from '@nestjs/common';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe('Media Type Versioning (fastify)', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
// ======================================================================== //
|
||||
describe('without global default version', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app.enableVersioning({
|
||||
type: VersioningType.MEDIA_TYPE,
|
||||
key: 'v=',
|
||||
});
|
||||
await app.init();
|
||||
await app.getHttpAdapter().getInstance().ready();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================== //
|
||||
describe('with the global default version: "1"', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app.enableVersioning({
|
||||
type: VersioningType.MEDIA_TYPE,
|
||||
key: 'v=',
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
await app.getHttpAdapter().getInstance().ready();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/foo/bar').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,282 +3,661 @@ import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe('Versioning', () => {
|
||||
describe('Media Type Versioning', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
// ======================================================================== //
|
||||
describe('without global default version', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.MEDIA_TYPE,
|
||||
key: 'v=',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.MEDIA_TYPE,
|
||||
key: 'v=',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
// ======================================================================== //
|
||||
describe('with the global default version: "1"', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.MEDIA_TYPE,
|
||||
key: 'v=',
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: '',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/param/hello')
|
||||
.set({
|
||||
Accept: '',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/multiple')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/foo/bar').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=1',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=2',
|
||||
})
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json;v=3',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.set({
|
||||
Accept: 'application/json',
|
||||
})
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Header', () => {
|
||||
return request(app.getHttpServer()).get('/override-partial').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
365
integration/versioning/e2e/uri-versioning-fastify.spec.ts
Normal file
365
integration/versioning/e2e/uri-versioning-fastify.spec.ts
Normal file
@@ -0,0 +1,365 @@
|
||||
import { INestApplication, VersioningType } from '@nestjs/common';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
} from '@nestjs/platform-fastify';
|
||||
import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe('URI Versioning (fastify)', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
// ======================================================================== //
|
||||
describe('without global default version', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app.enableVersioning({
|
||||
type: VersioningType.URI,
|
||||
});
|
||||
await app.init();
|
||||
await app.getHttpAdapter().getInstance().ready();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1')
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2')
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/param/hello').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/param/hello').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/multiple').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/override').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v3/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer()).get('/v1/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer()).get('/v2/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
// ======================================================================== //
|
||||
describe('with the global default version: "1"', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication<NestFastifyApplication>(
|
||||
new FastifyAdapter(),
|
||||
);
|
||||
app.enableVersioning({
|
||||
type: VersioningType.URI,
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
await app.getHttpAdapter().getInstance().ready();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1')
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2')
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/param/hello').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/param/hello').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/multiple').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/override').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v3/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer()).get('/v2/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/foo/bar').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,153 +3,353 @@ import { Test } from '@nestjs/testing';
|
||||
import * as request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
|
||||
describe('Versioning', () => {
|
||||
describe('URI Versioning', () => {
|
||||
let app: INestApplication;
|
||||
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
// ======================================================================== //
|
||||
describe('without global default version', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.URI,
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/')
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.URI,
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/')
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/')
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/')
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/').expect(404);
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/param/hello').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/param/hello').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/multiple').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/override').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v3/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer()).get('/v1/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer()).get('/v2/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
// ======================================================================== //
|
||||
describe('with the global default version: "1"', () => {
|
||||
before(async () => {
|
||||
const moduleRef = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
app.enableVersioning({
|
||||
type: VersioningType.URI,
|
||||
defaultVersion: '1',
|
||||
});
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
describe('GET /', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1')
|
||||
.expect(200)
|
||||
.expect('Hello World V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2')
|
||||
.expect(200)
|
||||
.expect('Hello World V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/param/hello').expect(404);
|
||||
describe('GET /:param', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V1!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/param/hello')
|
||||
.expect(200)
|
||||
.expect('Parameter V2!');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/param/hello').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/param/hello').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/param/hello').expect(404);
|
||||
});
|
||||
});
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
describe('GET /multiple', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/multiple').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/multiple')
|
||||
.expect(200)
|
||||
.expect('Multiple Versions 1 or 2');
|
||||
describe('GET /neutral', () => {
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/multiple').expect(404);
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/override').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/multiple').expect(404);
|
||||
});
|
||||
});
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
describe('GET /neutral', () => {
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/neutral')
|
||||
.expect(200)
|
||||
.expect('Neutral');
|
||||
});
|
||||
});
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
describe('GET /override', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 1');
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v3/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override')
|
||||
.expect(200)
|
||||
.expect('Override Version 2');
|
||||
describe('GET /foo/bar', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/foo/bar')
|
||||
.expect(200)
|
||||
.expect('Hello FooBar!');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer()).get('/v2/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/foo/bar').expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/foo/bar').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer()).get('/v3/override').expect(404);
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/override').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /override-partial', () => {
|
||||
it('V1', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v1/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 1');
|
||||
});
|
||||
|
||||
it('V2', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v2/override-partial')
|
||||
.expect(200)
|
||||
.expect('Override Partial Version 2');
|
||||
});
|
||||
|
||||
it('V3', () => {
|
||||
return request(app.getHttpServer())
|
||||
.get('/v3/override-partial')
|
||||
.expect(404);
|
||||
});
|
||||
|
||||
it('No Version', () => {
|
||||
return request(app.getHttpServer()).get('/override-partial').expect(404);
|
||||
});
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { AppV1Controller } from './app-v1.controller';
|
||||
import { AppV2Controller } from './app-v2.controller';
|
||||
import { MultipleVersionController } from './multiple.controller';
|
||||
import { NoVersioningController } from './no-versioning.controller';
|
||||
import { VersionNeutralController } from './neutral.controller';
|
||||
import { OverrideController } from './override.controller';
|
||||
import { OverridePartialController } from './override-partial.controller';
|
||||
@@ -12,6 +13,7 @@ import { OverridePartialController } from './override-partial.controller';
|
||||
AppV1Controller,
|
||||
AppV2Controller,
|
||||
MultipleVersionController,
|
||||
NoVersioningController,
|
||||
VersionNeutralController,
|
||||
OverrideController,
|
||||
OverridePartialController,
|
||||
|
||||
9
integration/versioning/src/no-versioning.controller.ts
Normal file
9
integration/versioning/src/no-versioning.controller.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
|
||||
@Controller('foo')
|
||||
export class NoVersioningController {
|
||||
@Get('/bar')
|
||||
helloFoo() {
|
||||
return 'Hello FooBar!';
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Controller, Get, Version } from '@nestjs/common';
|
||||
|
||||
@Controller({
|
||||
version: '1'
|
||||
version: '1',
|
||||
})
|
||||
export class OverridePartialController {
|
||||
@Get('/override-partial')
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "8.0.3"
|
||||
"version": "8.2.0"
|
||||
}
|
||||
|
||||
4875
package-lock.json
generated
4875
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
124
package.json
124
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/core",
|
||||
"version": "8.0.0-alpha.1",
|
||||
"version": "8.0.6",
|
||||
"description": "Modern, fast, powerful node.js web framework",
|
||||
"homepage": "https://nestjs.com",
|
||||
"repository": {
|
||||
@@ -34,7 +34,7 @@
|
||||
"lint:packages": "eslint 'packages/**/**.ts' --ignore-pattern 'packages/**/*.spec.ts'",
|
||||
"lint:spec": "eslint 'packages/**/**.spec.ts' -c '.eslintrc.spec.js'",
|
||||
"prerelease": "gulp copy-misc && gulp build --dist node_modules/@nestjs",
|
||||
"publish": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --force-publish --access public --exact -m \"chore(@nestjs) publish %s release\"",
|
||||
"publish": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --conventional-commits --force-publish --access public --exact -m \"chore(@nestjs) publish %s release\"",
|
||||
"publish:beta": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=beta --access public -m \"chore(@nestjs) publish %s release\"",
|
||||
"publish:next": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=next --access public --skip-git -m \"chore(@nestjs) publish %s release\"",
|
||||
"publish:rc": "npm run prerelease && npm run build:prod && ./node_modules/.bin/lerna publish --npm-tag=rc --access public -m \"chore(@nestjs) publish %s release\"",
|
||||
@@ -53,81 +53,81 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxtjs/opencollective": "0.3.2",
|
||||
"axios": "0.21.1",
|
||||
"axios": "0.24.0",
|
||||
"class-transformer": "0.4.0",
|
||||
"class-validator": "0.13.1",
|
||||
"cli-color": "2.0.0",
|
||||
"cli-color": "2.0.1",
|
||||
"cors": "2.8.5",
|
||||
"express": "4.17.1",
|
||||
"fast-json-stringify": "2.7.7",
|
||||
"fast-safe-stringify": "2.0.8",
|
||||
"fast-json-stringify": "2.7.11",
|
||||
"fast-safe-stringify": "2.1.1",
|
||||
"graphql-subscriptions": "1.2.1",
|
||||
"iterare": "1.2.1",
|
||||
"object-hash": "2.2.0",
|
||||
"path-to-regexp": "3.2.0",
|
||||
"reflect-metadata": "0.1.13",
|
||||
"rxjs": "7.2.0",
|
||||
"socket.io": "4.1.3",
|
||||
"tslib": "2.3.0",
|
||||
"rxjs": "7.4.0",
|
||||
"socket.io": "4.3.1",
|
||||
"tslib": "2.3.1",
|
||||
"uuid": "8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@codechecks/client": "0.1.11",
|
||||
"@commitlint/cli": "12.1.4",
|
||||
"@commitlint/config-angular": "12.1.4",
|
||||
"@grpc/grpc-js": "1.3.5",
|
||||
"@grpc/proto-loader": "0.6.4",
|
||||
"@nestjs/graphql": "7.11.0",
|
||||
"@nestjs/mongoose": "8.0.0",
|
||||
"@nestjs/typeorm": "8.0.1",
|
||||
"@types/amqplib": "0.8.1",
|
||||
"@codechecks/client": "0.1.12",
|
||||
"@commitlint/cli": "14.1.0",
|
||||
"@commitlint/config-angular": "14.1.0",
|
||||
"@grpc/grpc-js": "1.4.3",
|
||||
"@grpc/proto-loader": "0.6.6",
|
||||
"@nestjs/graphql": "9.1.1",
|
||||
"@nestjs/mongoose": "9.0.1",
|
||||
"@nestjs/typeorm": "8.0.2",
|
||||
"@types/amqplib": "0.8.2",
|
||||
"@types/bytes": "3.1.1",
|
||||
"@types/cache-manager": "3.4.2",
|
||||
"@types/chai": "4.2.21",
|
||||
"@types/chai": "4.2.22",
|
||||
"@types/chai-as-promised": "7.1.4",
|
||||
"@types/cors": "2.8.12",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/gulp": "4.0.9",
|
||||
"@types/http-errors": "1.8.1",
|
||||
"@types/mocha": "8.2.3",
|
||||
"@types/mongoose": "5.11.97",
|
||||
"@types/node": "15.14.0",
|
||||
"@types/redis": "2.8.31",
|
||||
"@types/mocha": "9.0.0",
|
||||
"@types/node": "16.11.6",
|
||||
"@types/redis": "2.8.32",
|
||||
"@types/reflect-metadata": "0.1.0",
|
||||
"@types/sinon": "10.0.2",
|
||||
"@types/sinon": "10.0.6",
|
||||
"@types/socket.io": "3.0.2",
|
||||
"@types/ws": "7.4.6",
|
||||
"@typescript-eslint/eslint-plugin": "4.28.3",
|
||||
"@typescript-eslint/parser": "4.28.3",
|
||||
"amqp-connection-manager": "3.2.2",
|
||||
"@types/ws": "8.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "4.33.0",
|
||||
"@typescript-eslint/parser": "4.33.0",
|
||||
"amqp-connection-manager": "3.7.0",
|
||||
"amqplib": "0.8.0",
|
||||
"apollo-server-express": "2.25.2",
|
||||
"artillery": "1.7.6",
|
||||
"awesome-typescript-loader": "5.2.1",
|
||||
"apollo-server-core": "3.5.0",
|
||||
"apollo-server-express": "3.5.0",
|
||||
"artillery": "1.7.9",
|
||||
"body-parser": "1.19.0",
|
||||
"bytes": "3.1.0",
|
||||
"cache-manager": "3.4.4",
|
||||
"cache-manager-redis-store": "2.0.0",
|
||||
"chai": "4.3.4",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"clang-format": "1.5.0",
|
||||
"clang-format": "1.6.0",
|
||||
"commitlint-circle": "1.0.0",
|
||||
"concurrently": "6.2.0",
|
||||
"concurrently": "6.3.0",
|
||||
"conventional-changelog": "3.1.24",
|
||||
"core-js": "3.15.2",
|
||||
"core-js": "3.19.1",
|
||||
"coveralls": "3.1.1",
|
||||
"delete-empty": "3.0.0",
|
||||
"engine.io-client": "5.1.2",
|
||||
"eslint": "7.30.0",
|
||||
"engine.io-client": "6.0.2",
|
||||
"eslint": "7.32.0",
|
||||
"eslint-config-prettier": "8.3.0",
|
||||
"eslint-plugin-import": "2.23.4",
|
||||
"eslint-plugin-import": "2.25.2",
|
||||
"eventsource": "1.1.0",
|
||||
"fancy-log": "1.3.3",
|
||||
"fastify": "3.19.1",
|
||||
"fastify": "3.23.1",
|
||||
"fastify-cors": "6.0.2",
|
||||
"fastify-formbody": "5.0.0",
|
||||
"fastify-multipart": "4.0.7",
|
||||
"fastify-static": "4.2.2",
|
||||
"graphql": "15.5.1",
|
||||
"fastify-formbody": "5.1.0",
|
||||
"fastify-multipart": "5.1.0",
|
||||
"fastify-static": "4.5.0",
|
||||
"graphql": "15.7.2",
|
||||
"graphql-tools": "7.0.5",
|
||||
"gulp": "4.0.2",
|
||||
"gulp-clang-format": "1.0.27",
|
||||
@@ -136,39 +136,39 @@
|
||||
"gulp-typescript": "5.0.1",
|
||||
"gulp-watch": "5.0.1",
|
||||
"http-errors": "1.8.0",
|
||||
"husky": "7.0.1",
|
||||
"imports-loader": "3.0.0",
|
||||
"husky": "7.0.4",
|
||||
"imports-loader": "3.1.1",
|
||||
"json-loader": "0.5.7",
|
||||
"kafkajs": "1.15.0",
|
||||
"lerna": "2.11.0",
|
||||
"light-my-request": "4.4.1",
|
||||
"lint-staged": "11.0.1",
|
||||
"light-my-request": "4.6.0",
|
||||
"lint-staged": "11.2.6",
|
||||
"markdown-table": "2.0.0",
|
||||
"merge-graphql-schemas": "1.7.8",
|
||||
"middie": "5.3.0",
|
||||
"mocha": "9.0.2",
|
||||
"mongoose": "5.13.2",
|
||||
"mocha": "9.1.3",
|
||||
"mongoose": "6.0.12",
|
||||
"mqtt": "4.2.8",
|
||||
"multer": "1.4.2",
|
||||
"mysql": "2.18.1",
|
||||
"nats": "2.1.0",
|
||||
"nodemon": "2.0.12",
|
||||
"multer": "1.4.3",
|
||||
"mysql2": "2.3.2",
|
||||
"nats": "2.3.0",
|
||||
"nodemon": "2.0.14",
|
||||
"nyc": "15.1.0",
|
||||
"point-of-view": "4.15.1",
|
||||
"prettier": "2.3.2",
|
||||
"point-of-view": "4.15.2",
|
||||
"prettier": "2.4.1",
|
||||
"redis": "3.1.2",
|
||||
"rxjs-compat": "6.6.7",
|
||||
"sinon": "11.1.1",
|
||||
"sinon": "12.0.1",
|
||||
"sinon-chai": "3.7.0",
|
||||
"socket.io-client": "4.1.3",
|
||||
"subscriptions-transport-ws": "0.9.19",
|
||||
"supertest": "6.1.3",
|
||||
"ts-morph": "11.0.3",
|
||||
"ts-node": "10.1.0",
|
||||
"typeorm": "0.2.34",
|
||||
"socket.io-client": "4.3.2",
|
||||
"subscriptions-transport-ws": "0.11.0",
|
||||
"supertest": "6.1.6",
|
||||
"ts-morph": "12.2.0",
|
||||
"ts-node": "10.4.0",
|
||||
"typeorm": "0.2.38",
|
||||
"typescript": "4.3.5",
|
||||
"wrk": "1.2.1",
|
||||
"ws": "7.5.3"
|
||||
"ws": "7.5.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13.0"
|
||||
|
||||
18
packages/common/CHANGELOG.md
Normal file
18
packages/common/CHANGELOG.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
<a name="8.2.0"></a>
|
||||
# [8.2.0](https://github.com/nestjs/nest/compare/v8.1.2...v8.2.0) (2021-11-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update dependency axios to v0.24.0 ([fc77e4f](https://github.com/nestjs/nest/commit/fc77e4f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **common:** add the ability to set some extra metadata about returned files ([5100573](https://github.com/nestjs/nest/commit/5100573))
|
||||
* **common:** allow to swap out class-validator and class-transformer ([2a1cc62](https://github.com/nestjs/nest/commit/2a1cc62))
|
||||
@@ -67,8 +67,11 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
|
||||
<table style="text-align:center;"><tr><td>
|
||||
<a href="https://careers.labster.com/departments/platform" target="_blank"><img src="https://nestjs.com/img/labster-logo.png" width="170" valign="middle" /></a></td><td>
|
||||
<a href="https://weld.so/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="150" valign="middle" /></a></td><td>
|
||||
<a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td></tr></table>
|
||||
<a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="150" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td></</tr></table>
|
||||
|
||||
#### Silver Sponsors
|
||||
|
||||
@@ -76,8 +79,9 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<a href="https://neoteric.eu/" target="_blank"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" valign="middle" /></a> </td><td>
|
||||
<a href="http://gojob.com" target="_blank"><img src="http://nestjs.com/img/gojob-logo.png" valign="middle" width="100" /></a> </td><td>
|
||||
<a href="http://www.leogistics.com" target="_blank"><img src="https://nestjs.com/img/leogistics-logo.jpeg" width="150" valign="middle" /></td><td>
|
||||
<a href="http://www.meetdandy.com" target="_blank"><img src="https://nestjs.com/img/dandy-wide-logo.png" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td></tr></table>
|
||||
<a href="https://careers.meetdandy.com/?gh_src=063ba61e3us" target="_blank"><img src="https://nestjs.com/img/dandy-roles-logo.svg" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td>
|
||||
<td><a href="https://www.tinystacks.com" target="_blank"><img src="https://nestjs.com/img/tinystacks-logo.png#1" width="140" valign="middle" /></td></tr></table>
|
||||
|
||||
#### Sponsors
|
||||
|
||||
@@ -108,6 +112,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://www.bystored.com/" target="_blank"><img src="https://nestjs.com/img/stored-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://studyclerk.com/pay-for-research-paper" target="_blank"><img src="https://nestjs.com/img/studyclerk-logo.png" width="125" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://xyndata.com" target="_blank"><img src="https://nestjs.com/img/xyndata-logo.png" width="125" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
2
packages/common/cache/cache.module.ts
vendored
2
packages/common/cache/cache.module.ts
vendored
@@ -30,6 +30,7 @@ export class CacheModule {
|
||||
static register(options: CacheModuleOptions = {}): DynamicModule {
|
||||
return {
|
||||
module: CacheModule,
|
||||
global: options.isGlobal,
|
||||
providers: [{ provide: CACHE_MODULE_OPTIONS, useValue: options }],
|
||||
};
|
||||
}
|
||||
@@ -45,6 +46,7 @@ export class CacheModule {
|
||||
static registerAsync(options: CacheModuleAsyncOptions): DynamicModule {
|
||||
return {
|
||||
module: CacheModule,
|
||||
global: options.isGlobal,
|
||||
imports: options.imports,
|
||||
providers: [
|
||||
...this.createAsyncProviders(options),
|
||||
|
||||
@@ -38,7 +38,8 @@ export class CacheInterceptor implements NestInterceptor {
|
||||
next: CallHandler,
|
||||
): Promise<Observable<any>> {
|
||||
const key = this.trackBy(context);
|
||||
const ttlValueOrFactory = this.reflector.get(CACHE_TTL_METADATA, context.getHandler()) ?? null;
|
||||
const ttlValueOrFactory =
|
||||
this.reflector.get(CACHE_TTL_METADATA, context.getHandler()) ?? null;
|
||||
|
||||
if (!key) {
|
||||
return next.handle();
|
||||
|
||||
@@ -31,7 +31,7 @@ export interface CacheStore {
|
||||
*
|
||||
* @param key cache key
|
||||
*/
|
||||
del(key: string): void | Promise<void>;
|
||||
del?(key: string): void | Promise<void>;
|
||||
}
|
||||
|
||||
export interface CacheStoreSetOptions<T> {
|
||||
@@ -52,7 +52,7 @@ export interface CacheStoreFactory {
|
||||
* Return a configured cache store.
|
||||
*
|
||||
* @param args Cache manager options received from `CacheModule.register()`
|
||||
* or `CacheModule.registerAcync()`
|
||||
* or `CacheModule.registerAsync()`
|
||||
*/
|
||||
create(args: LiteralObject): CacheStore;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ export interface CacheManagerOptions {
|
||||
* [Different stores](https://docs.nestjs.com/techniques/caching#different-stores)
|
||||
* for more info.
|
||||
*/
|
||||
store?: string | CacheStoreFactory;
|
||||
store?: string | CacheStoreFactory | CacheStore;
|
||||
/**
|
||||
* Time to live - amount of time in seconds that a response is cached before it
|
||||
* is deleted. Subsequent request will call through the route handler and refresh
|
||||
|
||||
@@ -2,6 +2,10 @@ import { ModuleMetadata, Provider, Type } from '../../interfaces';
|
||||
import { CacheManagerOptions } from './cache-manager.interface';
|
||||
|
||||
export interface CacheModuleOptions extends CacheManagerOptions {
|
||||
/**
|
||||
* If "true', register `CacheModule` as a global module.
|
||||
*/
|
||||
isGlobal?: boolean;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
@@ -48,4 +52,8 @@ export interface CacheModuleAsyncOptions
|
||||
*/
|
||||
inject?: any[];
|
||||
extraProviders?: Provider[];
|
||||
/**
|
||||
* If "true', register `CacheModule` as a global module.
|
||||
*/
|
||||
isGlobal?: boolean;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export type ParamDecoratorEnhancer = ParameterDecorator;
|
||||
export function createParamDecorator<
|
||||
FactoryData = any,
|
||||
FactoryInput = any,
|
||||
FactoryOutput = any
|
||||
FactoryOutput = any,
|
||||
>(
|
||||
factory: CustomParamFactory<FactoryData, FactoryInput, FactoryOutput>,
|
||||
enhancers: ParamDecoratorEnhancer[] = [],
|
||||
@@ -25,36 +25,37 @@ export function createParamDecorator<
|
||||
) => ParameterDecorator {
|
||||
const paramtype = uuid();
|
||||
return (
|
||||
data?,
|
||||
...pipes: (Type<PipeTransform> | PipeTransform | FactoryData)[]
|
||||
): ParameterDecorator => (target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
data?,
|
||||
...pipes: (Type<PipeTransform> | PipeTransform | FactoryData)[]
|
||||
): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
|
||||
const isPipe = (pipe: any) =>
|
||||
pipe &&
|
||||
((isFunction(pipe) &&
|
||||
pipe.prototype &&
|
||||
isFunction(pipe.prototype.transform)) ||
|
||||
isFunction(pipe.transform));
|
||||
const isPipe = (pipe: any) =>
|
||||
pipe &&
|
||||
((isFunction(pipe) &&
|
||||
pipe.prototype &&
|
||||
isFunction(pipe.prototype.transform)) ||
|
||||
isFunction(pipe.transform));
|
||||
|
||||
const hasParamData = isNil(data) || !isPipe(data);
|
||||
const paramData = hasParamData ? (data as any) : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
const hasParamData = isNil(data) || !isPipe(data);
|
||||
const paramData = hasParamData ? (data as any) : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignCustomParameterMetadata(
|
||||
args,
|
||||
paramtype,
|
||||
index,
|
||||
factory,
|
||||
paramData,
|
||||
...(paramPipes as PipeTransform[]),
|
||||
),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
enhancers.forEach(fn => fn(target, key, index));
|
||||
};
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignCustomParameterMetadata(
|
||||
args,
|
||||
paramtype,
|
||||
index,
|
||||
factory,
|
||||
paramData,
|
||||
...(paramPipes as PipeTransform[]),
|
||||
),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
enhancers.forEach(fn => fn(target, key, index));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ export const RequestMapping = (
|
||||
};
|
||||
};
|
||||
|
||||
const createMappingDecorator = (method: RequestMethod) => (
|
||||
path?: string | string[],
|
||||
): MethodDecorator => {
|
||||
return RequestMapping({
|
||||
[PATH_METADATA]: path,
|
||||
[METHOD_METADATA]: method,
|
||||
});
|
||||
};
|
||||
const createMappingDecorator =
|
||||
(method: RequestMethod) =>
|
||||
(path?: string | string[]): MethodDecorator => {
|
||||
return RequestMapping({
|
||||
[PATH_METADATA]: path,
|
||||
[METHOD_METADATA]: method,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Route handler (method) Decorator. Routes HTTP POST requests to the specified path.
|
||||
|
||||
@@ -45,40 +45,44 @@ export function assignMetadata<TParamtype = any, TArgs = any>(
|
||||
}
|
||||
|
||||
function createRouteParamDecorator(paramtype: RouteParamtypes) {
|
||||
return (data?: ParamData): ParameterDecorator => (target, key, index) => {
|
||||
return (data?: ParamData): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignMetadata<RouteParamtypes, Record<number, RouteParamMetadata>>(
|
||||
args,
|
||||
paramtype,
|
||||
index,
|
||||
data,
|
||||
),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const createPipesRouteParamDecorator =
|
||||
(paramtype: RouteParamtypes) =>
|
||||
(
|
||||
data?: any,
|
||||
...pipes: (Type<PipeTransform> | PipeTransform)[]
|
||||
): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
const hasParamData = isNil(data) || isString(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignMetadata<RouteParamtypes, Record<number, RouteParamMetadata>>(
|
||||
args,
|
||||
paramtype,
|
||||
index,
|
||||
data,
|
||||
),
|
||||
assignMetadata(args, paramtype, index, paramData, ...paramPipes),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const createPipesRouteParamDecorator = (paramtype: RouteParamtypes) => (
|
||||
data?: any,
|
||||
...pipes: (Type<PipeTransform> | PipeTransform)[]
|
||||
): ParameterDecorator => (target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(ROUTE_ARGS_METADATA, target.constructor, key) || {};
|
||||
const hasParamData = isNil(data) || isString(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
|
||||
Reflect.defineMetadata(
|
||||
ROUTE_ARGS_METADATA,
|
||||
assignMetadata(args, paramtype, index, paramData, ...paramPipes),
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Route handler parameter decorator. Extracts the `Request`
|
||||
@@ -106,25 +110,22 @@ export const Request: () => ParameterDecorator = createRouteParamDecorator(
|
||||
*/
|
||||
export const Response: (
|
||||
options?: ResponseDecoratorOptions,
|
||||
) => ParameterDecorator = (options?: ResponseDecoratorOptions) => (
|
||||
target,
|
||||
key,
|
||||
index,
|
||||
) => {
|
||||
if (options?.passthrough) {
|
||||
Reflect.defineMetadata(
|
||||
RESPONSE_PASSTHROUGH_METADATA,
|
||||
options?.passthrough,
|
||||
target.constructor,
|
||||
) => ParameterDecorator =
|
||||
(options?: ResponseDecoratorOptions) => (target, key, index) => {
|
||||
if (options?.passthrough) {
|
||||
Reflect.defineMetadata(
|
||||
RESPONSE_PASSTHROUGH_METADATA,
|
||||
options?.passthrough,
|
||||
target.constructor,
|
||||
key,
|
||||
);
|
||||
}
|
||||
return createRouteParamDecorator(RouteParamtypes.RESPONSE)()(
|
||||
target,
|
||||
key,
|
||||
index,
|
||||
);
|
||||
}
|
||||
return createRouteParamDecorator(RouteParamtypes.RESPONSE)()(
|
||||
target,
|
||||
key,
|
||||
index,
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Route handler parameter decorator. Extracts reference to the `Next` function
|
||||
@@ -320,9 +321,8 @@ export function UploadedFiles(
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export const Headers: (
|
||||
property?: string,
|
||||
) => ParameterDecorator = createRouteParamDecorator(RouteParamtypes.HEADERS);
|
||||
export const Headers: (property?: string) => ParameterDecorator =
|
||||
createRouteParamDecorator(RouteParamtypes.HEADERS);
|
||||
|
||||
/**
|
||||
* Route handler parameter decorator. Extracts the `query`
|
||||
|
||||
@@ -39,6 +39,7 @@ export enum HttpStatus {
|
||||
MISDIRECTED = 421,
|
||||
UNPROCESSABLE_ENTITY = 422,
|
||||
FAILED_DEPENDENCY = 424,
|
||||
PRECONDITION_REQUIRED = 428,
|
||||
TOO_MANY_REQUESTS = 429,
|
||||
INTERNAL_SERVER_ERROR = 500,
|
||||
NOT_IMPLEMENTED = 501,
|
||||
|
||||
@@ -16,7 +16,7 @@ export class ImATeapotException extends HttpException {
|
||||
* Instantiate an `ImATeapotException` Exception.
|
||||
*
|
||||
* @example
|
||||
* `throw new BadGatewayException()`
|
||||
* `throw new ImATeapotException()`
|
||||
*
|
||||
* @usageNotes
|
||||
* The HTTP response status code will be 418.
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Readable } from 'stream';
|
||||
import { StreamableFileOptions } from './streamable-options.interface';
|
||||
|
||||
export class StreamableFile {
|
||||
private readonly stream: Readable;
|
||||
|
||||
constructor(buffer: Buffer);
|
||||
constructor(readable: Readable);
|
||||
constructor(bufferOrReadStream: Buffer | Readable) {
|
||||
constructor(buffer: Buffer, options?: StreamableFileOptions);
|
||||
constructor(readable: Readable, options?: StreamableFileOptions);
|
||||
constructor(
|
||||
bufferOrReadStream: Buffer | Readable,
|
||||
readonly options: StreamableFileOptions = {},
|
||||
) {
|
||||
if (Buffer.isBuffer(bufferOrReadStream)) {
|
||||
this.stream = new Readable();
|
||||
this.stream.push(bufferOrReadStream);
|
||||
@@ -21,4 +25,10 @@ export class StreamableFile {
|
||||
getStream(): Readable {
|
||||
return this.stream;
|
||||
}
|
||||
|
||||
getHeaders() {
|
||||
const { type = 'application/octet-stream', disposition = null } =
|
||||
this.options;
|
||||
return { type, disposition };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface StreamableFileOptions {
|
||||
type?: string;
|
||||
disposition?: string;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Nest @common
|
||||
* Copyright(c) 2017 - 2020 Kamil Mysliwiec
|
||||
* Copyright(c) 2017 - 2021 Kamil Mysliwiec
|
||||
* https://nestjs.com
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
14
packages/common/interfaces/external/transformer-package.interface.ts
vendored
Normal file
14
packages/common/interfaces/external/transformer-package.interface.ts
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Type } from '../type.interface';
|
||||
import { ClassTransformOptions } from './class-transform-options.interface';
|
||||
|
||||
export interface TransformerPackage {
|
||||
plainToClass<T>(
|
||||
cls: Type<T>,
|
||||
plain: unknown,
|
||||
options?: ClassTransformOptions,
|
||||
): T | T[];
|
||||
classToPlain(
|
||||
object: unknown,
|
||||
options?: ClassTransformOptions,
|
||||
): Record<string, any> | Record<string, any>[];
|
||||
}
|
||||
9
packages/common/interfaces/external/validator-package.interface.ts
vendored
Normal file
9
packages/common/interfaces/external/validator-package.interface.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ValidationError } from './validation-error.interface';
|
||||
import { ValidatorOptions } from './validator-options.interface';
|
||||
|
||||
export interface ValidatorPackage {
|
||||
validate(
|
||||
object: unknown,
|
||||
validatorOptions?: ValidatorOptions,
|
||||
): ValidationError[] | Promise<ValidationError[]>;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
CorsOptionsDelegate,
|
||||
} from '../../interfaces/external/cors-options.interface';
|
||||
import { NestApplicationOptions } from '../../interfaces/nest-application-options.interface';
|
||||
import { VersioningOptions, VersionValue } from '../version-options.interface';
|
||||
|
||||
export type ErrorHandler<TRequest = any, TResponse = any> = (
|
||||
error: any,
|
||||
@@ -73,4 +74,13 @@ export interface HttpServer<TRequest = any, TResponse = any> {
|
||||
close(): any;
|
||||
getType(): string;
|
||||
init?(): Promise<void>;
|
||||
applyVersionFilter?(
|
||||
handler: Function,
|
||||
version: VersionValue,
|
||||
versioningOptions: VersioningOptions,
|
||||
): <TRequest extends Record<string, any> = any, TResponse = any>(
|
||||
req: TRequest,
|
||||
res: TResponse,
|
||||
next: () => void,
|
||||
) => any;
|
||||
}
|
||||
|
||||
@@ -55,10 +55,16 @@ export interface MediaTypeVersioningOptions {
|
||||
key: string;
|
||||
}
|
||||
|
||||
interface VersioningCommonOptions {
|
||||
/**
|
||||
* The default version to be used as a fallback when you did not provide some
|
||||
* version to `@Controller()` nor `@Version()`.
|
||||
*/
|
||||
defaultVersion?: VersionOptions['version'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
export type VersioningOptions =
|
||||
| HeaderVersioningOptions
|
||||
| UriVersioningOptions
|
||||
| MediaTypeVersioningOptions;
|
||||
export type VersioningOptions = VersioningCommonOptions &
|
||||
(HeaderVersioningOptions | UriVersioningOptions | MediaTypeVersioningOptions);
|
||||
|
||||
@@ -8,7 +8,7 @@ export interface WsMessageHandler<T = string> {
|
||||
export interface WebSocketAdapter<
|
||||
TServer = any,
|
||||
TClient = any,
|
||||
TOptions = any
|
||||
TOptions = any,
|
||||
> {
|
||||
create(port: number, options?: TOptions): TServer;
|
||||
bindClientConnect(server: TServer, callback: Function): any;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nestjs/common",
|
||||
"version": "8.0.3",
|
||||
"version": "8.2.0",
|
||||
"description": "Nest - modern, fast, powerful node.js web framework (@common)",
|
||||
"author": "Kamil Mysliwiec",
|
||||
"homepage": "https://nestjs.com",
|
||||
@@ -17,9 +17,9 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"axios": "0.21.1",
|
||||
"axios": "0.24.0",
|
||||
"iterare": "1.2.1",
|
||||
"tslib": "2.3.0",
|
||||
"tslib": "2.3.1",
|
||||
"uuid": "8.3.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Injectable } from '../decorators/core/injectable.decorator';
|
||||
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ArgumentMetadata,
|
||||
PipeTransform,
|
||||
} from '../interfaces/features/pipe-transform.interface';
|
||||
import { isNil } from '../utils/shared.utils';
|
||||
|
||||
/**
|
||||
@@ -11,13 +14,14 @@ import { isNil } from '../utils/shared.utils';
|
||||
*/
|
||||
@Injectable()
|
||||
export class DefaultValuePipe<T = any, R = any>
|
||||
implements PipeTransform<T, T | R> {
|
||||
implements PipeTransform<T, T | R>
|
||||
{
|
||||
constructor(private readonly defaultValue: R) {}
|
||||
|
||||
transform(value?: T, _metadata?: ArgumentMetadata): T | R {
|
||||
if (
|
||||
isNil(value) ||
|
||||
(typeof value === 'number' && isNaN((value as unknown) as number))
|
||||
(typeof value === 'number' && isNaN(value as unknown as number))
|
||||
) {
|
||||
return this.defaultValue;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,10 @@ import { Injectable } from '../decorators/core/injectable.decorator';
|
||||
import { Optional } from '../decorators/core/optional.decorator';
|
||||
import { HttpStatus } from '../enums/http-status.enum';
|
||||
import { Type } from '../interfaces';
|
||||
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ArgumentMetadata,
|
||||
PipeTransform,
|
||||
} from '../interfaces/features/pipe-transform.interface';
|
||||
import { HttpErrorByCode } from '../utils/http-error-by-code.util';
|
||||
import { isNil, isString } from '../utils/shared.utils';
|
||||
import { ValidationPipe, ValidationPipeOptions } from './validation.pipe';
|
||||
@@ -40,10 +43,8 @@ export class ParseArrayPipe implements PipeTransform {
|
||||
...options,
|
||||
});
|
||||
|
||||
const {
|
||||
exceptionFactory,
|
||||
errorHttpStatusCode = HttpStatus.BAD_REQUEST,
|
||||
} = options;
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
this.exceptionFactory =
|
||||
exceptionFactory ||
|
||||
(error => new HttpErrorByCode[errorHttpStatusCode](error));
|
||||
@@ -82,10 +83,15 @@ export class ParseArrayPipe implements PipeTransform {
|
||||
type: 'query',
|
||||
};
|
||||
|
||||
const toClassInstance = (item: any) => {
|
||||
const isExpectedTypePrimitive = this.isExpectedTypePrimitive();
|
||||
const toClassInstance = (item: any, index?: number) => {
|
||||
try {
|
||||
item = JSON.parse(item);
|
||||
} catch {}
|
||||
|
||||
if (isExpectedTypePrimitive) {
|
||||
return this.validatePrimitive(item, index);
|
||||
}
|
||||
return this.validationPipe.transform(item, validationMetadata);
|
||||
};
|
||||
if (this.options.stopAtFirstError === false) {
|
||||
@@ -99,8 +105,8 @@ export class ParseArrayPipe implements PipeTransform {
|
||||
targetArray[i] = await toClassInstance(targetArray[i]);
|
||||
} catch (err) {
|
||||
let message: string[] | unknown;
|
||||
if (err.getResponse) {
|
||||
const response = err.getResponse();
|
||||
if ((err as any).getResponse) {
|
||||
const response = (err as any).getResponse();
|
||||
if (Array.isArray(response.message)) {
|
||||
message = response.message.map(
|
||||
(item: string) => `[${i}] ${item}`,
|
||||
@@ -124,4 +130,36 @@ export class ParseArrayPipe implements PipeTransform {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected isExpectedTypePrimitive(): boolean {
|
||||
return [Boolean, Number, String].includes(this.options.items as any);
|
||||
}
|
||||
|
||||
protected validatePrimitive(originalValue: any, index?: number) {
|
||||
if (this.options.items === Number) {
|
||||
const value =
|
||||
originalValue !== null && originalValue !== '' ? +originalValue : NaN;
|
||||
if (isNaN(value)) {
|
||||
throw this.exceptionFactory(
|
||||
`${
|
||||
typeof index !== 'undefined' ? `[${index}] ` : ''
|
||||
}item must be a number`,
|
||||
);
|
||||
}
|
||||
return value;
|
||||
} else if (this.options.items === String) {
|
||||
if (typeof originalValue !== 'string') {
|
||||
return `${originalValue}`;
|
||||
}
|
||||
} else if (this.options.items === Boolean) {
|
||||
if (typeof originalValue !== 'boolean') {
|
||||
throw this.exceptionFactory(
|
||||
`${
|
||||
typeof index !== 'undefined' ? `[${index}] ` : ''
|
||||
}item must be a boolean value`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return originalValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Injectable } from '../decorators/core/injectable.decorator';
|
||||
import { Optional } from '../decorators/core/optional.decorator';
|
||||
import { HttpStatus } from '../enums/http-status.enum';
|
||||
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ArgumentMetadata,
|
||||
PipeTransform,
|
||||
} from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
@@ -21,15 +24,14 @@ export interface ParseBoolPipeOptions {
|
||||
*/
|
||||
@Injectable()
|
||||
export class ParseBoolPipe
|
||||
implements PipeTransform<string | boolean, Promise<boolean>> {
|
||||
implements PipeTransform<string | boolean, Promise<boolean>>
|
||||
{
|
||||
protected exceptionFactory: (error: string) => any;
|
||||
|
||||
constructor(@Optional() options?: ParseBoolPipeOptions) {
|
||||
options = options || {};
|
||||
const {
|
||||
exceptionFactory,
|
||||
errorHttpStatusCode = HttpStatus.BAD_REQUEST,
|
||||
} = options;
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
this.exceptionFactory =
|
||||
exceptionFactory ||
|
||||
(error => new HttpErrorByCode[errorHttpStatusCode](error));
|
||||
|
||||
@@ -31,10 +31,8 @@ export class ParseEnumPipe<T = any> implements PipeTransform<T> {
|
||||
);
|
||||
}
|
||||
options = options || {};
|
||||
const {
|
||||
exceptionFactory,
|
||||
errorHttpStatusCode = HttpStatus.BAD_REQUEST,
|
||||
} = options;
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
|
||||
this.exceptionFactory =
|
||||
exceptionFactory ||
|
||||
|
||||
@@ -23,10 +23,8 @@ export class ParseFloatPipe implements PipeTransform<string> {
|
||||
|
||||
constructor(@Optional() options?: ParseFloatPipeOptions) {
|
||||
options = options || {};
|
||||
const {
|
||||
exceptionFactory,
|
||||
errorHttpStatusCode = HttpStatus.BAD_REQUEST,
|
||||
} = options;
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
|
||||
this.exceptionFactory =
|
||||
exceptionFactory ||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Injectable } from '../decorators/core/injectable.decorator';
|
||||
import { Optional } from '../decorators/core/optional.decorator';
|
||||
import { HttpStatus } from '../enums/http-status.enum';
|
||||
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ArgumentMetadata,
|
||||
PipeTransform,
|
||||
} from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
@@ -25,10 +28,8 @@ export class ParseIntPipe implements PipeTransform<string> {
|
||||
|
||||
constructor(@Optional() options?: ParseIntPipeOptions) {
|
||||
options = options || {};
|
||||
const {
|
||||
exceptionFactory,
|
||||
errorHttpStatusCode = HttpStatus.BAD_REQUEST,
|
||||
} = options;
|
||||
const { exceptionFactory, errorHttpStatusCode = HttpStatus.BAD_REQUEST } =
|
||||
options;
|
||||
|
||||
this.exceptionFactory =
|
||||
exceptionFactory ||
|
||||
@@ -45,7 +46,7 @@ export class ParseIntPipe implements PipeTransform<string> {
|
||||
async transform(value: string, metadata: ArgumentMetadata): Promise<number> {
|
||||
const isNumeric =
|
||||
['string', 'number'].includes(typeof value) &&
|
||||
!isNaN(parseFloat(value)) &&
|
||||
/^-?\d+$/.test(value) &&
|
||||
isFinite(value as any);
|
||||
if (!isNumeric) {
|
||||
throw this.exceptionFactory(
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Injectable } from '../decorators/core/injectable.decorator';
|
||||
import { Optional } from '../decorators/core/optional.decorator';
|
||||
import { HttpStatus } from '../enums/http-status.enum';
|
||||
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ArgumentMetadata,
|
||||
PipeTransform,
|
||||
} from '../interfaces/features/pipe-transform.interface';
|
||||
import {
|
||||
ErrorHttpStatusCode,
|
||||
HttpErrorByCode,
|
||||
|
||||
@@ -3,9 +3,14 @@ import { Optional } from '../decorators';
|
||||
import { Injectable } from '../decorators/core';
|
||||
import { HttpStatus } from '../enums/http-status.enum';
|
||||
import { ClassTransformOptions } from '../interfaces/external/class-transform-options.interface';
|
||||
import { TransformerPackage } from '../interfaces/external/transformer-package.interface';
|
||||
import { ValidationError } from '../interfaces/external/validation-error.interface';
|
||||
import { ValidatorOptions } from '../interfaces/external/validator-options.interface';
|
||||
import { ArgumentMetadata, PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import { ValidatorPackage } from '../interfaces/external/validator-package.interface';
|
||||
import {
|
||||
ArgumentMetadata,
|
||||
PipeTransform,
|
||||
} from '../interfaces/features/pipe-transform.interface';
|
||||
import { Type } from '../interfaces/type.interface';
|
||||
import {
|
||||
ErrorHttpStatusCode,
|
||||
@@ -22,10 +27,12 @@ export interface ValidationPipeOptions extends ValidatorOptions {
|
||||
exceptionFactory?: (errors: ValidationError[]) => any;
|
||||
validateCustomDecorators?: boolean;
|
||||
expectedType?: Type<any>;
|
||||
validatorPackage?: ValidatorPackage;
|
||||
transformerPackage?: TransformerPackage;
|
||||
}
|
||||
|
||||
let classValidator: any = {};
|
||||
let classTransformer: any = {};
|
||||
let classValidator: ValidatorPackage = {} as any;
|
||||
let classTransformer: TransformerPackage = {} as any;
|
||||
|
||||
@Injectable()
|
||||
export class ValidationPipe implements PipeTransform<any> {
|
||||
@@ -60,19 +67,29 @@ export class ValidationPipe implements PipeTransform<any> {
|
||||
this.exceptionFactory =
|
||||
options.exceptionFactory || this.createExceptionFactory();
|
||||
|
||||
classValidator = this.loadValidator();
|
||||
classTransformer = this.loadTransformer();
|
||||
classValidator = this.loadValidator(options.validatorPackage);
|
||||
classTransformer = this.loadTransformer(options.transformerPackage);
|
||||
}
|
||||
|
||||
protected loadValidator() {
|
||||
return loadPackage('class-validator', 'ValidationPipe', () =>
|
||||
require('class-validator'),
|
||||
protected loadValidator(
|
||||
validatorPackage?: ValidatorPackage,
|
||||
): ValidatorPackage {
|
||||
return (
|
||||
validatorPackage ??
|
||||
loadPackage('class-validator', 'ValidationPipe', () =>
|
||||
require('class-validator'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected loadTransformer() {
|
||||
return loadPackage('class-transformer', 'ValidationPipe', () =>
|
||||
require('class-transformer'),
|
||||
protected loadTransformer(
|
||||
transformerPackage?: TransformerPackage,
|
||||
): TransformerPackage {
|
||||
return (
|
||||
transformerPackage ??
|
||||
loadPackage('class-transformer', 'ValidationPipe', () =>
|
||||
require('class-transformer'),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -111,7 +128,7 @@ export class ValidationPipe implements PipeTransform<any> {
|
||||
entity = { constructor: metatype };
|
||||
}
|
||||
|
||||
const errors = await classValidator.validate(entity, this.validatorOptions);
|
||||
const errors = await this.validate(entity, this.validatorOptions);
|
||||
if (errors.length > 0) {
|
||||
throw await this.exceptionFactory(errors);
|
||||
}
|
||||
@@ -185,6 +202,13 @@ export class ValidationPipe implements PipeTransform<any> {
|
||||
return ['number', 'boolean', 'string'].includes(typeof value);
|
||||
}
|
||||
|
||||
protected validate(
|
||||
object: object,
|
||||
validatorOptions?: ValidatorOptions,
|
||||
): Promise<ValidationError[]> | ValidationError[] {
|
||||
return classValidator.validate(object, validatorOptions);
|
||||
}
|
||||
|
||||
protected flattenValidationErrors(
|
||||
validationErrors: ValidationError[],
|
||||
): string[] {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { Inject, Injectable, Optional } from '../decorators/core';
|
||||
import { StreamableFile } from '../file-stream';
|
||||
import { CallHandler, ExecutionContext, NestInterceptor } from '../interfaces';
|
||||
import { ClassTransformOptions } from '../interfaces/external/class-transform-options.interface';
|
||||
import { TransformerPackage } from '../interfaces/external/transformer-package.interface';
|
||||
import { loadPackage } from '../utils/load-package.util';
|
||||
import { isObject } from '../utils/shared.utils';
|
||||
import { CLASS_SERIALIZER_OPTIONS } from './class-serializer.constants';
|
||||
|
||||
let classTransformer: any = {};
|
||||
let classTransformer: TransformerPackage = {} as any;
|
||||
|
||||
export interface PlainLiteralObject {
|
||||
[key: string]: any;
|
||||
@@ -18,18 +20,27 @@ export interface PlainLiteralObject {
|
||||
// between core and common packages
|
||||
const REFLECTOR = 'Reflector';
|
||||
|
||||
export interface ClassSerializerInterceptorOptions
|
||||
extends ClassTransformOptions {
|
||||
transformerPackage?: TransformerPackage;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ClassSerializerInterceptor implements NestInterceptor {
|
||||
constructor(
|
||||
@Inject(REFLECTOR) protected readonly reflector: any,
|
||||
@Optional() protected readonly defaultOptions: ClassTransformOptions = {},
|
||||
@Optional()
|
||||
protected readonly defaultOptions: ClassSerializerInterceptorOptions = {},
|
||||
) {
|
||||
classTransformer = loadPackage(
|
||||
'class-transformer',
|
||||
'ClassSerializerInterceptor',
|
||||
() => require('class-transformer'),
|
||||
);
|
||||
require('class-transformer');
|
||||
classTransformer =
|
||||
defaultOptions?.transformerPackage ??
|
||||
loadPackage('class-transformer', 'ClassSerializerInterceptor', () =>
|
||||
require('class-transformer'),
|
||||
);
|
||||
|
||||
if (!defaultOptions?.transformerPackage) {
|
||||
require('class-transformer');
|
||||
}
|
||||
}
|
||||
|
||||
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
|
||||
@@ -47,18 +58,19 @@ export class ClassSerializerInterceptor implements NestInterceptor {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes responses that are non-null objects nor streamable files.
|
||||
*/
|
||||
serialize(
|
||||
response: PlainLiteralObject | Array<PlainLiteralObject>,
|
||||
options: ClassTransformOptions,
|
||||
): PlainLiteralObject | PlainLiteralObject[] {
|
||||
const isArray = Array.isArray(response);
|
||||
if (!isObject(response) && !isArray) {
|
||||
): PlainLiteralObject | Array<PlainLiteralObject> {
|
||||
if (!isObject(response) || response instanceof StreamableFile) {
|
||||
return response;
|
||||
}
|
||||
return isArray
|
||||
? (response as PlainLiteralObject[]).map(item =>
|
||||
this.transformToPlain(item, options),
|
||||
)
|
||||
|
||||
return Array.isArray(response)
|
||||
? response.map(item => this.transformToPlain(item, options))
|
||||
: this.transformToPlain(response, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ const DEFAULT_LOG_LEVELS: LogLevel[] = [
|
||||
@Injectable()
|
||||
export class ConsoleLogger implements LoggerService {
|
||||
private static lastTimestampAt?: number;
|
||||
private originalContext?: string;
|
||||
|
||||
constructor();
|
||||
constructor(context: string);
|
||||
@@ -40,6 +41,9 @@ export class ConsoleLogger implements LoggerService {
|
||||
if (!options.logLevels) {
|
||||
options.logLevels = DEFAULT_LOG_LEVELS;
|
||||
}
|
||||
if (context) {
|
||||
this.originalContext = context;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,6 +150,13 @@ export class ConsoleLogger implements LoggerService {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the logger context to the value that was passed in the constructor.
|
||||
*/
|
||||
resetContext() {
|
||||
this.context = this.originalContext;
|
||||
}
|
||||
|
||||
isLevelEnabled(level: LogLevel): boolean {
|
||||
const logLevels = this.options?.logLevels;
|
||||
return isLogLevelEnabled(level, logLevels);
|
||||
|
||||
@@ -150,7 +150,7 @@ export class Logger implements LoggerService {
|
||||
optionalParams = this.context
|
||||
? optionalParams.concat(this.context)
|
||||
: optionalParams;
|
||||
this.localInstance?.debug(message, ...optionalParams);
|
||||
this.localInstance?.debug?.(message, ...optionalParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +163,7 @@ export class Logger implements LoggerService {
|
||||
optionalParams = this.context
|
||||
? optionalParams.concat(this.context)
|
||||
: optionalParams;
|
||||
this.localInstance?.verbose(message, ...optionalParams);
|
||||
this.localInstance?.verbose?.(message, ...optionalParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,7 +208,7 @@ export class Logger implements LoggerService {
|
||||
static debug(message: any, ...optionalParams: [...any, string?]): void;
|
||||
@Logger.WrapBuffer
|
||||
static debug(message: any, ...optionalParams: any[]) {
|
||||
this.staticInstanceRef?.debug(message, ...optionalParams);
|
||||
this.staticInstanceRef?.debug?.(message, ...optionalParams);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,7 +218,7 @@ export class Logger implements LoggerService {
|
||||
static verbose(message: any, ...optionalParams: [...any, string?]): void;
|
||||
@Logger.WrapBuffer
|
||||
static verbose(message: any, ...optionalParams: any[]) {
|
||||
this.staticInstanceRef?.verbose(message, ...optionalParams);
|
||||
this.staticInstanceRef?.verbose?.(message, ...optionalParams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -93,6 +93,58 @@ describe('ParseArrayPipe', () => {
|
||||
await target.transform('1.2.3', {} as ArgumentMetadata),
|
||||
).to.be.deep.equal(['1', '2', '3']);
|
||||
});
|
||||
|
||||
describe('and type is specified', () => {
|
||||
it('should parse & validate the array', async () => {
|
||||
target = new ParseArrayPipe({ separator: '.', items: Number });
|
||||
|
||||
expect(
|
||||
await target.transform('1.2.3', {} as ArgumentMetadata),
|
||||
).to.be.deep.equal([1, 2, 3]);
|
||||
|
||||
target = new ParseArrayPipe({ separator: '.', items: Number });
|
||||
|
||||
try {
|
||||
await target.transform('1.2.a.null.3', {} as ArgumentMetadata);
|
||||
throw null;
|
||||
} catch (err) {
|
||||
expect(err).to.be.instanceOf(BadRequestException);
|
||||
expect(err.getResponse().message).to.deep.equal(
|
||||
'[2] item must be a number',
|
||||
);
|
||||
}
|
||||
|
||||
target = new ParseArrayPipe({ separator: '.', items: Boolean });
|
||||
|
||||
try {
|
||||
await target.transform('1.2.a.null.3', {} as ArgumentMetadata);
|
||||
throw null;
|
||||
} catch (err) {
|
||||
expect(err).to.be.instanceOf(BadRequestException);
|
||||
expect(err.getResponse().message).to.deep.equal(
|
||||
'[0] item must be a boolean value',
|
||||
);
|
||||
}
|
||||
|
||||
target = new ParseArrayPipe({
|
||||
separator: '.',
|
||||
items: Number,
|
||||
stopAtFirstError: false,
|
||||
});
|
||||
|
||||
try {
|
||||
await target.transform('1.2.a.b.null.3', {} as ArgumentMetadata);
|
||||
throw null;
|
||||
} catch (err) {
|
||||
expect(err).to.be.instanceOf(BadRequestException);
|
||||
expect(err.getResponse().message).to.deep.equal([
|
||||
'[2] item must be a number',
|
||||
'[3] item must be a number',
|
||||
'[4] item must be a number',
|
||||
]);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when items type is determined', () => {
|
||||
@@ -113,6 +165,21 @@ describe('ParseArrayPipe', () => {
|
||||
items.forEach(item => {
|
||||
expect(item).to.be.instanceOf(ArrItem);
|
||||
});
|
||||
|
||||
target = new ParseArrayPipe({ items: Number });
|
||||
expect(
|
||||
await target.transform('1,2,3', {} as ArgumentMetadata),
|
||||
).to.deep.equal([1, 2, 3]);
|
||||
|
||||
target = new ParseArrayPipe({ items: String });
|
||||
expect(
|
||||
await target.transform('1,2,3', {} as ArgumentMetadata),
|
||||
).to.deep.equal(['1', '2', '3']);
|
||||
|
||||
target = new ParseArrayPipe({ items: Boolean });
|
||||
expect(
|
||||
await target.transform('true,false', {} as ArgumentMetadata),
|
||||
).to.deep.equal([true, false]);
|
||||
});
|
||||
describe('when "stopAtFirstError" is explicitly turned off', () => {
|
||||
it('should validate each item and concat errors', async () => {
|
||||
|
||||
@@ -25,6 +25,12 @@ describe('ParseIntPipe', () => {
|
||||
parseInt(num, 10),
|
||||
);
|
||||
});
|
||||
it('should return negative number', async () => {
|
||||
const num = '-3';
|
||||
expect(await target.transform(num, {} as ArgumentMetadata)).to.equal(
|
||||
-3,
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('when validation fails', () => {
|
||||
it('should throw an error', async () => {
|
||||
@@ -32,6 +38,11 @@ describe('ParseIntPipe', () => {
|
||||
target.transform('123abc', {} as ArgumentMetadata),
|
||||
).to.be.rejectedWith(CustomTestError);
|
||||
});
|
||||
it('should throw an error when number has wrong number encoding', async () => {
|
||||
return expect(
|
||||
target.transform('0xFF', {} as ArgumentMetadata),
|
||||
).to.be.rejectedWith(CustomTestError);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect } from 'chai';
|
||||
import 'reflect-metadata';
|
||||
import * as sinon from 'sinon';
|
||||
import { Logger, LoggerService } from '../../services';
|
||||
import { ConsoleLogger, Logger, LoggerService } from '../../services';
|
||||
|
||||
describe('Logger', () => {
|
||||
describe('[static methods]', () => {
|
||||
@@ -134,6 +134,9 @@ describe('Logger', () => {
|
||||
expect(processStderrWriteSpy.secondCall.firstArg).to.equal(
|
||||
stacktrace + '\n',
|
||||
);
|
||||
expect(processStderrWriteSpy.secondCall.firstArg).to.not.include(
|
||||
context,
|
||||
);
|
||||
});
|
||||
|
||||
it('should print multiple 2 errors and one stacktrace to the console', () => {
|
||||
@@ -237,6 +240,24 @@ describe('Logger', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ConsoleLogger', () => {
|
||||
it('should allow setting and resetting of context', () => {
|
||||
const logger = new ConsoleLogger();
|
||||
expect(logger['context']).to.be.undefined;
|
||||
logger.setContext('context');
|
||||
expect(logger['context']).to.equal('context');
|
||||
logger.resetContext();
|
||||
expect(logger['context']).to.be.undefined;
|
||||
|
||||
const loggerWithContext = new ConsoleLogger('context');
|
||||
expect(loggerWithContext['context']).to.equal('context');
|
||||
loggerWithContext.setContext('other');
|
||||
expect(loggerWithContext['context']).to.equal('other');
|
||||
loggerWithContext.resetContext();
|
||||
expect(loggerWithContext['context']).to.equal('context');
|
||||
});
|
||||
});
|
||||
|
||||
describe('[instance methods]', () => {
|
||||
describe('when the default logger is used', () => {
|
||||
const logger = new Logger();
|
||||
|
||||
@@ -14,6 +14,7 @@ export function loadPackage(
|
||||
return loaderFn ? loaderFn() : require(packageName);
|
||||
} catch (e) {
|
||||
logger.error(MISSING_REQUIRED_DEPENDENCY(packageName, context));
|
||||
Logger.flush();
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
12
packages/core/CHANGELOG.md
Normal file
12
packages/core/CHANGELOG.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
<a name="8.2.0"></a>
|
||||
# [8.2.0](https://github.com/nestjs/nest/compare/v8.1.2...v8.2.0) (2021-11-08)
|
||||
|
||||
|
||||
|
||||
|
||||
**Note:** Version bump only for package @nestjs/core
|
||||
@@ -67,8 +67,11 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
|
||||
<table style="text-align:center;"><tr><td>
|
||||
<a href="https://careers.labster.com/departments/platform" target="_blank"><img src="https://nestjs.com/img/labster-logo.png" width="170" valign="middle" /></a></td><td>
|
||||
<a href="https://weld.so/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="150" valign="middle" /></a></td><td>
|
||||
<a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td></tr></table>
|
||||
<a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="150" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
|
||||
<td>
|
||||
<a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td></</tr></table>
|
||||
|
||||
#### Silver Sponsors
|
||||
|
||||
@@ -76,8 +79,9 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<a href="https://neoteric.eu/" target="_blank"><img src="https://nestjs.com/img/neoteric-cut.png" width="120" valign="middle" /></a> </td><td>
|
||||
<a href="http://gojob.com" target="_blank"><img src="http://nestjs.com/img/gojob-logo.png" valign="middle" width="100" /></a> </td><td>
|
||||
<a href="http://www.leogistics.com" target="_blank"><img src="https://nestjs.com/img/leogistics-logo.jpeg" width="150" valign="middle" /></td><td>
|
||||
<a href="http://www.meetdandy.com" target="_blank"><img src="https://nestjs.com/img/dandy-wide-logo.png" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td></tr></table>
|
||||
<a href="https://careers.meetdandy.com/?gh_src=063ba61e3us" target="_blank"><img src="https://nestjs.com/img/dandy-roles-logo.svg" width="150" valign="middle" /></td><td>
|
||||
<a href="https://www.castlecraft.in" target="_blank"><img src="https://nestjs.com/img/castlecraft-logo.png" width="150" valign="middle" /></td>
|
||||
<td><a href="https://www.tinystacks.com" target="_blank"><img src="https://nestjs.com/img/tinystacks-logo.png#1" width="140" valign="middle" /></td></tr></table>
|
||||
|
||||
#### Sponsors
|
||||
|
||||
@@ -108,6 +112,7 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
|
||||
<td align="center" valign="middle"><a href="https://www.bystored.com/" target="_blank"><img src="https://nestjs.com/img/stored-logo.svg" width="110" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://studyclerk.com/pay-for-research-paper" target="_blank"><img src="https://nestjs.com/img/studyclerk-logo.png" width="125" valign="middle" /></a></td><td align="center" valign="middle"><a href="https://xyndata.com" target="_blank"><img src="https://nestjs.com/img/xyndata-logo.png" width="125" valign="middle" /></a></td></tr><tr>
|
||||
<td align="center" valign="middle"><a href="https://www.anonymistic.com/" target="_blank"><img src="https://nestjs.com/img/anonymistic-logo.png" width="125" valign="middle" /></a></td>
|
||||
<td align="center" valign="middle"><a href="https://www.naologic.com/" target="_blank"><img src="https://nestjs.com/img/naologic-logo.svg" width="125" valign="middle" /></a></td>
|
||||
</tr></table>
|
||||
|
||||
## Backers
|
||||
|
||||
@@ -12,11 +12,12 @@ import { NestApplicationOptions } from '@nestjs/common/interfaces/nest-applicati
|
||||
export abstract class AbstractHttpAdapter<
|
||||
TServer = any,
|
||||
TRequest = any,
|
||||
TResponse = any
|
||||
> implements HttpServer<TRequest, TResponse> {
|
||||
TResponse = any,
|
||||
> implements HttpServer<TRequest, TResponse>
|
||||
{
|
||||
protected httpServer: TServer;
|
||||
|
||||
constructor(protected readonly instance: any) {}
|
||||
constructor(protected instance?: any) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
public async init() {}
|
||||
@@ -87,6 +88,10 @@ export abstract class AbstractHttpAdapter<
|
||||
this.httpServer = httpServer;
|
||||
}
|
||||
|
||||
public setInstance<T = any>(instance: T) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
public getInstance<T = any>(): T {
|
||||
return this.instance as T;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ export class ApplicationConfig {
|
||||
private globalGuards: Array<CanActivate> = [];
|
||||
private versioningOptions: VersioningOptions;
|
||||
private readonly globalRequestPipes: InstanceWrapper<PipeTransform>[] = [];
|
||||
private readonly globalRequestFilters: InstanceWrapper<ExceptionFilter>[] = [];
|
||||
private readonly globalRequestInterceptors: InstanceWrapper<NestInterceptor>[] = [];
|
||||
private readonly globalRequestFilters: InstanceWrapper<ExceptionFilter>[] =
|
||||
[];
|
||||
private readonly globalRequestInterceptors: InstanceWrapper<NestInterceptor>[] =
|
||||
[];
|
||||
private readonly globalRequestGuards: InstanceWrapper<CanActivate>[] = [];
|
||||
|
||||
constructor(private ioAdapter: WebSocketAdapter | null = null) {}
|
||||
|
||||
@@ -54,7 +54,8 @@ export class ExternalExceptionFilterContext extends BaseExceptionFilterContext {
|
||||
if (contextId === STATIC_CONTEXT && !inquirerId) {
|
||||
return globalFilters;
|
||||
}
|
||||
const scopedFilterWrappers = this.config.getGlobalRequestFilters() as InstanceWrapper[];
|
||||
const scopedFilterWrappers =
|
||||
this.config.getGlobalRequestFilters() as InstanceWrapper[];
|
||||
const scopedFilters = iterate(scopedFilterWrappers)
|
||||
.map(wrapper => wrapper.getInstanceByContextId(contextId, inquirerId))
|
||||
.filter(host => !!host)
|
||||
|
||||
@@ -101,7 +101,8 @@ export class GuardsContextCreator extends ContextCreator {
|
||||
if (contextId === STATIC_CONTEXT && !inquirerId) {
|
||||
return globalGuards;
|
||||
}
|
||||
const scopedGuardWrappers = this.config.getGlobalRequestGuards() as InstanceWrapper[];
|
||||
const scopedGuardWrappers =
|
||||
this.config.getGlobalRequestGuards() as InstanceWrapper[];
|
||||
const scopedGuards = iterate(scopedGuardWrappers)
|
||||
.map(wrapper => wrapper.getInstanceByContextId(contextId, inquirerId))
|
||||
.filter(host => !!host)
|
||||
|
||||
@@ -328,11 +328,11 @@ export class ExternalContextCreator {
|
||||
: this.pipesConsumer.apply(value, { metatype, type, data }, pipes);
|
||||
}
|
||||
|
||||
public async transformToResult(resultOrDeffered: any) {
|
||||
if (resultOrDeffered && isFunction(resultOrDeffered.subscribe)) {
|
||||
return lastValueFrom(resultOrDeffered);
|
||||
public async transformToResult(resultOrDeferred: any) {
|
||||
if (resultOrDeferred && isFunction(resultOrDeferred.subscribe)) {
|
||||
return lastValueFrom(resultOrDeferred);
|
||||
}
|
||||
return resultOrDeffered;
|
||||
return resultOrDeferred;
|
||||
}
|
||||
|
||||
public createGuardsFn<TContext extends string = ContextType>(
|
||||
|
||||
@@ -20,7 +20,7 @@ export type HandlerResponseBasicFn = <TResult, TResponse>(
|
||||
export type HandleSseResponseFn = <
|
||||
TResult extends Observable<unknown> = any,
|
||||
TResponse extends HeaderStream = any,
|
||||
TRequest extends IncomingMessage = any
|
||||
TRequest extends IncomingMessage = any,
|
||||
>(
|
||||
result: TResult,
|
||||
res: TResponse,
|
||||
@@ -43,7 +43,7 @@ export interface HandlerMetadata {
|
||||
|
||||
export class HandlerMetadataStorage<
|
||||
TValue = HandlerMetadata,
|
||||
TKey extends Type<unknown> = any
|
||||
TKey extends Type<unknown> = any,
|
||||
> {
|
||||
private readonly [HANDLER_METADATA_SYMBOL] = new Map<string, TValue>();
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { AbstractHttpAdapter } from '../adapters/http-adapter';
|
||||
* @publicApi
|
||||
*/
|
||||
export class HttpAdapterHost<
|
||||
T extends AbstractHttpAdapter = AbstractHttpAdapter
|
||||
T extends AbstractHttpAdapter = AbstractHttpAdapter,
|
||||
> {
|
||||
private _httpAdapter?: T;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ function callOperator(
|
||||
.filter(instance => !isNil(instance))
|
||||
.filter(hasBeforeApplicationShutdownHook)
|
||||
.map(async instance =>
|
||||
((instance as any) as BeforeApplicationShutdown).beforeApplicationShutdown(
|
||||
(instance as any as BeforeApplicationShutdown).beforeApplicationShutdown(
|
||||
signal,
|
||||
),
|
||||
)
|
||||
@@ -52,7 +52,12 @@ export async function callBeforeAppShutdownHook(
|
||||
): Promise<void> {
|
||||
const providers = module.getNonAliasProviders();
|
||||
const [_, moduleClassHost] = providers.shift();
|
||||
const instances = [...module.controllers, ...providers];
|
||||
const instances = [
|
||||
...module.controllers,
|
||||
...providers,
|
||||
...module.injectables,
|
||||
...module.middlewares,
|
||||
];
|
||||
|
||||
const nonTransientInstances = getNonTransientInstances(instances);
|
||||
await Promise.all(callOperator(nonTransientInstances, signal));
|
||||
@@ -65,8 +70,8 @@ export async function callBeforeAppShutdownHook(
|
||||
hasBeforeApplicationShutdownHook(moduleClassInstance) &&
|
||||
moduleClassHost.isDependencyTreeStatic()
|
||||
) {
|
||||
await (moduleClassInstance as BeforeApplicationShutdown).beforeApplicationShutdown(
|
||||
signal,
|
||||
);
|
||||
await (
|
||||
moduleClassInstance as BeforeApplicationShutdown
|
||||
).beforeApplicationShutdown(signal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ function callOperator(instances: InstanceWrapper[]): Promise<any>[] {
|
||||
.filter(instance => !isNil(instance))
|
||||
.filter(hasOnAppBootstrapHook)
|
||||
.map(async instance =>
|
||||
((instance as any) as OnApplicationBootstrap).onApplicationBootstrap(),
|
||||
(instance as any as OnApplicationBootstrap).onApplicationBootstrap(),
|
||||
)
|
||||
.toArray();
|
||||
}
|
||||
@@ -62,6 +62,8 @@ export async function callModuleBootstrapHook(module: Module): Promise<any> {
|
||||
hasOnAppBootstrapHook(moduleClassInstance) &&
|
||||
moduleClassHost.isDependencyTreeStatic()
|
||||
) {
|
||||
await (moduleClassInstance as OnApplicationBootstrap).onApplicationBootstrap();
|
||||
await (
|
||||
moduleClassInstance as OnApplicationBootstrap
|
||||
).onApplicationBootstrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,7 @@ function callOperator(
|
||||
.filter(instance => !isNil(instance))
|
||||
.filter(hasOnAppShutdownHook)
|
||||
.map(async instance =>
|
||||
((instance as any) as OnApplicationShutdown).onApplicationShutdown(
|
||||
signal,
|
||||
),
|
||||
(instance as any as OnApplicationShutdown).onApplicationShutdown(signal),
|
||||
)
|
||||
.toArray();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user