Compare commits
368 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa6e96731a | ||
|
|
f59dfda878 | ||
|
|
e15c62a8d8 | ||
|
|
f97c123ddb | ||
|
|
7fd287f004 | ||
|
|
f0bbdf561d | ||
|
|
a9c6bcc63f | ||
|
|
e1fc695d24 | ||
|
|
525e436b9d | ||
|
|
a98f972bef | ||
|
|
1c2fdfee37 | ||
|
|
8102086400 | ||
|
|
0366729a95 | ||
|
|
352d2af366 | ||
|
|
9b8c4039f0 | ||
|
|
262b647855 | ||
|
|
03017046f7 | ||
|
|
28d2671ddb | ||
|
|
86da1612da | ||
|
|
919465c9b6 | ||
|
|
b84ed74496 | ||
|
|
dc86c78bd1 | ||
|
|
45b38cc836 | ||
|
|
186532ef2d | ||
|
|
77858c5558 | ||
|
|
e9a98ffe3d | ||
|
|
2c06dd6f18 | ||
|
|
881d686233 | ||
|
|
a7deaafbc7 | ||
|
|
7c698f0b35 | ||
|
|
09a8c94392 | ||
|
|
35b9ded76e | ||
|
|
85c10b9d3f | ||
|
|
2675942c58 | ||
|
|
b3ad310f6f | ||
|
|
d41385b592 | ||
|
|
dfbab3919d | ||
|
|
e5c607164e | ||
|
|
49d1e91a64 | ||
|
|
19ea640705 | ||
|
|
f2d814813f | ||
|
|
f99ebf5f37 | ||
|
|
ef2c0cdd67 | ||
|
|
d658af7407 | ||
|
|
0f8f15f31c | ||
|
|
600467035a | ||
|
|
d25aee1313 | ||
|
|
0cc2a3aab7 | ||
|
|
75e6b9fb74 | ||
|
|
6e8a65fa7f | ||
|
|
01dce6b09a | ||
|
|
ceeed729c6 | ||
|
|
7f35af5bd2 | ||
|
|
c603195004 | ||
|
|
bac35e06c8 | ||
|
|
7add9cad87 | ||
|
|
16dae9b081 | ||
|
|
9f52f36c18 | ||
|
|
621d87fdb7 | ||
|
|
871e709076 | ||
|
|
1e3ae5d445 | ||
|
|
a344c1f89e | ||
|
|
ee742530d9 | ||
|
|
f102f4c873 | ||
|
|
eebeeee6b7 | ||
|
|
18842fd56f | ||
|
|
ea1e75b355 | ||
|
|
34ed51a0db | ||
|
|
4ce4bb92bb | ||
|
|
75ed86eafb | ||
|
|
a4bcfb4737 | ||
|
|
bfd3be403e | ||
|
|
bfd75229c1 | ||
|
|
91172b82d9 | ||
|
|
c9f416713a | ||
|
|
11eb4208e6 | ||
|
|
fbd387a30c | ||
|
|
018e2405f2 | ||
|
|
c631f1ef15 | ||
|
|
3ce4f97de7 | ||
|
|
77ad2c02ce | ||
|
|
ecf5a29e19 | ||
|
|
ec8632a3e9 | ||
|
|
98f91e24c1 | ||
|
|
49c5a1e1be | ||
|
|
9a00412049 | ||
|
|
03fd49bb29 | ||
|
|
8b607b9463 | ||
|
|
e3472171a5 | ||
|
|
5f1c6a4571 | ||
|
|
d05f00c0a8 | ||
|
|
0715bb7a02 | ||
|
|
00d1ddff0b | ||
|
|
0f99de91ae | ||
|
|
9cff223033 | ||
|
|
1d6021dd36 | ||
|
|
c4df5d8d04 | ||
|
|
9019f1cf27 | ||
|
|
d92b7efe00 | ||
|
|
daea45eeb2 | ||
|
|
8dcc5ebe23 | ||
|
|
d36138361d | ||
|
|
831b0d4bcd | ||
|
|
5d9fcd22be | ||
|
|
1c51ab403b | ||
|
|
c3c9e89302 | ||
|
|
e842c9f224 | ||
|
|
abeb0c5d14 | ||
|
|
18d1a685a9 | ||
|
|
9255050eee | ||
|
|
915f5fa479 | ||
|
|
24dcac6978 | ||
|
|
adef11ba8e | ||
|
|
4233caa909 | ||
|
|
8f5cad91d4 | ||
|
|
ac5121beda | ||
|
|
5460fbb484 | ||
|
|
ad71e15290 | ||
|
|
4aba0d31f6 | ||
|
|
19ad91709e | ||
|
|
74efbad6d0 | ||
|
|
0fd6a4d5e3 | ||
|
|
1c12da5495 | ||
|
|
c4c90477c5 | ||
|
|
a9aaeec047 | ||
|
|
8420f6ddb8 | ||
|
|
3a1ea75a55 | ||
|
|
b23c2cdc36 | ||
|
|
12c081b830 | ||
|
|
11492dcfbd | ||
|
|
de874ca20e | ||
|
|
92ab9c3867 | ||
|
|
12c1b7331b | ||
|
|
c98788425d | ||
|
|
a279fb90af | ||
|
|
4f868ad2ac | ||
|
|
522da1a3d7 | ||
|
|
e767f51182 | ||
|
|
3479686f44 | ||
|
|
fafab00edc | ||
|
|
fe7a3c3a85 | ||
|
|
252c9b11fe | ||
|
|
9ddc85dbe3 | ||
|
|
ee07fc3b3f | ||
|
|
18c6981958 | ||
|
|
f85b0efc33 | ||
|
|
da8925ab51 | ||
|
|
23f85d6c27 | ||
|
|
58d566983a | ||
|
|
6b59d21e2d | ||
|
|
f2b2e5a414 | ||
|
|
862e54b453 | ||
|
|
32983cb454 | ||
|
|
47c3c947ef | ||
|
|
20e7c16237 | ||
|
|
c512b7a29e | ||
|
|
5870251839 | ||
|
|
457015ae5b | ||
|
|
a19c480c19 | ||
|
|
2f397f0e99 | ||
|
|
c081599547 | ||
|
|
e3876b387e | ||
|
|
937e4061d6 | ||
|
|
3312b4316b | ||
|
|
6653f31b27 | ||
|
|
e109813b67 | ||
|
|
4384ce0514 | ||
|
|
a1d8008cb5 | ||
|
|
919e9f637d | ||
|
|
d2f2e4b315 | ||
|
|
c91de5134e | ||
|
|
8fa479a991 | ||
|
|
6d93450ae0 | ||
|
|
c089980fca | ||
|
|
f4cf751b96 | ||
|
|
46b8103b5f | ||
|
|
9fc06a2279 | ||
|
|
731bf5451d | ||
|
|
e660b7b89d | ||
|
|
046587d025 | ||
|
|
2dd578a2db | ||
|
|
afd6e3f914 | ||
|
|
e183fb4afb | ||
|
|
aa008866cc | ||
|
|
b388a50352 | ||
|
|
fa78180768 | ||
|
|
f8e9d75afd | ||
|
|
797618e338 | ||
|
|
52d569e47e | ||
|
|
f85ae04953 | ||
|
|
2fc6c07133 | ||
|
|
feba2b6ea9 | ||
|
|
51d91c3c9d | ||
|
|
a5d3d02275 | ||
|
|
5fcd1d5b23 | ||
|
|
a808d3c120 | ||
|
|
8fc8800088 | ||
|
|
4d1c997a56 | ||
|
|
90d96552be | ||
|
|
7c4e9c81a0 | ||
|
|
40a6c7d0aa | ||
|
|
60b9f444c0 | ||
|
|
4d95e31013 | ||
|
|
eb4097be96 | ||
|
|
f1c000e8f1 | ||
|
|
13b7e6ab0b | ||
|
|
6ac61768d9 | ||
|
|
f4f6fd91a9 | ||
|
|
8f653d9eda | ||
|
|
291e8b904f | ||
|
|
6f37571dab | ||
|
|
4e6f82910b | ||
|
|
5fc4cbbdb2 | ||
|
|
dc05944074 | ||
|
|
e2490b9528 | ||
|
|
3c62425418 | ||
|
|
c29735fab8 | ||
|
|
8a5596f9b6 | ||
|
|
1457ec8635 | ||
|
|
71be602fbd | ||
|
|
6a539a30ee | ||
|
|
df2c1dd6da | ||
|
|
3d17eae8b8 | ||
|
|
3db0f77463 | ||
|
|
93c03ea36e | ||
|
|
fa7ac116f7 | ||
|
|
c2e69b5de8 | ||
|
|
f280035fa7 | ||
|
|
48f762cb7a | ||
|
|
f3f85b6831 | ||
|
|
cfdfb69c45 | ||
|
|
9e405aa8b8 | ||
|
|
853254df2c | ||
|
|
350a98da5f | ||
|
|
3473cec6d4 | ||
|
|
baeefff47a | ||
|
|
bdc560a1d4 | ||
|
|
5b4413dd87 | ||
|
|
cf448a801e | ||
|
|
c4f6f78dde | ||
|
|
9e9c63d896 | ||
|
|
e45822407f | ||
|
|
ac4f9f3702 | ||
|
|
b6adb749ce | ||
|
|
ea566b2c3a | ||
|
|
87eefafb22 | ||
|
|
6056ed85d9 | ||
|
|
8fef7b7407 | ||
|
|
25cdbbbf53 | ||
|
|
db2c28d014 | ||
|
|
39e089bac2 | ||
|
|
17853ee542 | ||
|
|
9dd420c313 | ||
|
|
4d930541d9 | ||
|
|
eaf4862915 | ||
|
|
3bcfda462d | ||
|
|
ef362299c6 | ||
|
|
d64cf5323a | ||
|
|
aa560d229e | ||
|
|
6ff9fd9196 | ||
|
|
99b5876c36 | ||
|
|
62dc284abe | ||
|
|
c0dc8f4d02 | ||
|
|
505c2cb9e6 | ||
|
|
5165bd1b20 | ||
|
|
86335620c1 | ||
|
|
e637a4908a | ||
|
|
e8874ff573 | ||
|
|
2cc9f302da | ||
|
|
ad06a9f005 | ||
|
|
5105ed4650 | ||
|
|
25782cd292 | ||
|
|
c28ecb6187 | ||
|
|
5a46cc0438 | ||
|
|
3040fd5d03 | ||
|
|
fa0fa21444 | ||
|
|
61560a3e63 | ||
|
|
2a6fab08a0 | ||
|
|
74e3776286 | ||
|
|
99f146e54b | ||
|
|
f5829db520 | ||
|
|
db611a1888 | ||
|
|
862b21ce9c | ||
|
|
3fb73272fa | ||
|
|
b2f1a654af | ||
|
|
6b9fb74163 | ||
|
|
be4ac2ceb6 | ||
|
|
810da1b490 | ||
|
|
41df687a96 | ||
|
|
805e2cf4b1 | ||
|
|
06686a4c8b | ||
|
|
f79dad995a | ||
|
|
c95e0cc9c3 | ||
|
|
db203e8a6f | ||
|
|
2ff4fcfe2f | ||
|
|
c5941bf703 | ||
|
|
cd8914f285 | ||
|
|
9f835f42f7 | ||
|
|
dba9e4333d | ||
|
|
20eb67b27e | ||
|
|
0bffe867b9 | ||
|
|
fbc23ebd63 | ||
|
|
a4975d10cf | ||
|
|
f9e7d168b8 | ||
|
|
554a91a2eb | ||
|
|
273f72076f | ||
|
|
e704aca0ed | ||
|
|
29b5b311cb | ||
|
|
caea4d96f7 | ||
|
|
89b0f96536 | ||
|
|
ebf3f5d803 | ||
|
|
8b1008488f | ||
|
|
994cba856b | ||
|
|
1e92fe3b76 | ||
|
|
76c5a00eec | ||
|
|
927db971b9 | ||
|
|
93213387de | ||
|
|
4c00ddd741 | ||
|
|
b6cc8b1904 | ||
|
|
15fe99ed56 | ||
|
|
5fe42c1204 | ||
|
|
285d76d3b2 | ||
|
|
c261e5c987 | ||
|
|
0f027bd2c8 | ||
|
|
962b521ade | ||
|
|
3936039c38 | ||
|
|
5c219f1e60 | ||
|
|
294bcd2de3 | ||
|
|
a131cf8502 | ||
|
|
961c73b23c | ||
|
|
8c5a67cd28 | ||
|
|
6be7bc48a2 | ||
|
|
5a8ee866ba | ||
|
|
4320589461 | ||
|
|
05f6a09ae1 | ||
|
|
723904bdf5 | ||
|
|
83bcd441b0 | ||
|
|
ee97985859 | ||
|
|
8d98843573 | ||
|
|
5441e59ac1 | ||
|
|
af11aafd46 | ||
|
|
25fafd92f4 | ||
|
|
e49da74a53 | ||
|
|
827bcf3afe | ||
|
|
46b40881bc | ||
|
|
ff1572b37a | ||
|
|
5cf84a699b | ||
|
|
1ed6dd1d39 | ||
|
|
c99b1fc9db | ||
|
|
18b3f32abb | ||
|
|
f9889367a6 | ||
|
|
2b2c9f1040 | ||
|
|
a8f5db494d | ||
|
|
468d03b51e | ||
|
|
f1c458fe12 | ||
|
|
f434845f53 | ||
|
|
8e7d397965 | ||
|
|
15de5ff1ab | ||
|
|
cefb5c18ce | ||
|
|
99f3f83335 | ||
|
|
fb41714083 | ||
|
|
18a8d7cdd9 | ||
|
|
3e267be382 | ||
|
|
b7dadba616 | ||
|
|
aa85d1d47e | ||
|
|
44197a760c | ||
|
|
f6354d2dd5 | ||
|
|
c9c995eafb |
@@ -309,7 +309,8 @@
|
||||
"profile": "https://github.com/Zeko369",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -625,7 +626,8 @@
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/17050715?v=4",
|
||||
"profile": "https://cloudnweb.dev/",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -970,7 +972,9 @@
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/3496193?v=4",
|
||||
"profile": "https://twitter.com/dillonraphael",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"test",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1547,7 +1551,8 @@
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/244174?v=4",
|
||||
"profile": "https://github.com/piotrski",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2005,7 +2010,8 @@
|
||||
"profile": "http://aleksandra.codes",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -2962,7 +2968,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12092?v=4",
|
||||
"profile": "http://zackhobson.com/",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -3008,8 +3015,836 @@
|
||||
"profile": "https://github.com/s-r-x",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hashimwarren",
|
||||
"name": "Hashim Warren",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6027587?v=4",
|
||||
"profile": "https://github.com/hashimwarren",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "damilolarandolph",
|
||||
"name": "Damilola Randolph",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/43427949?v=4",
|
||||
"profile": "https://damilolarandolph.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mwcampbell",
|
||||
"name": "Matt Campbell",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/214820?v=4",
|
||||
"profile": "https://github.com/mwcampbell",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ratson",
|
||||
"name": "(◕ᴥ◕)",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2682937?v=4",
|
||||
"profile": "https://github.com/ratson",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "maciejmyslinski",
|
||||
"name": "Mat Milbury",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11421186?v=4",
|
||||
"profile": "maciejmyslinski.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "andreasasprou",
|
||||
"name": "Andreas Asprou",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/8077469?v=4",
|
||||
"profile": "https://andreas.fyi",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kotx",
|
||||
"name": "Kot",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/33439542?v=4",
|
||||
"profile": "https://github.com/kotx",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "isaka1022",
|
||||
"name": "Amane",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/28589716?v=4",
|
||||
"profile": "https://github.com/isaka1022",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fuzzthink",
|
||||
"name": "John Leung",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20699?v=4",
|
||||
"profile": "johnleung.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "bcye",
|
||||
"name": "Bruce",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/29666239?v=4",
|
||||
"profile": "roettgers.co",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "emilygracekz",
|
||||
"name": "Emily",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/57361805?v=4",
|
||||
"profile": "https://github.com/emilygracekz",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "npverni",
|
||||
"name": "Nathan Verni",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3537?v=4",
|
||||
"profile": "https://github.com/npverni",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "davyengone",
|
||||
"name": "Davy Engone",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4896002?v=4",
|
||||
"profile": "https://davyengone.io",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Fedeorlandau",
|
||||
"name": "Federico Joel Orlandau",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/10283686?v=4",
|
||||
"profile": "https://fedeorlandau.dev/",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "johnmurphy01",
|
||||
"name": "John Murphy",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2939548?v=4",
|
||||
"profile": "https://github.com/johnmurphy01",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "martinsaxa",
|
||||
"name": "martinsaxa",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/33789474?v=4",
|
||||
"profile": "https://github.com/martinsaxa",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ajwgeek",
|
||||
"name": "Austin Walhof",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2135600?v=4",
|
||||
"profile": "https://github.com/ajwgeek",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "g3offrey",
|
||||
"name": "Geoffrey",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11151445?v=4",
|
||||
"profile": "g3offrey.dev",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "keevan",
|
||||
"name": "Kevin Pham",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9924643?v=4",
|
||||
"profile": "https://github.com/keevan",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kimngan-bui",
|
||||
"name": "kimngan-bui",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20723478?v=4",
|
||||
"profile": "https://github.com/kimngan-bui",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "9j",
|
||||
"name": "Bahk Chanhee",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/11691670?v=4",
|
||||
"profile": "world.hey.com/bach",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Vandivier",
|
||||
"name": "John Vandivier",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5559355?v=4",
|
||||
"profile": "http://www.afterecon.com/",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "namirsab",
|
||||
"name": "Namir",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6980777?v=4",
|
||||
"profile": "http://namirsab.github.io",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "scttcper",
|
||||
"name": "Scott Cooper",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1400464?v=4",
|
||||
"profile": "https://twitter.com/scttcper",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Abduttayyeb",
|
||||
"name": "Abduttayyeb M.r",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/55306260?v=4",
|
||||
"profile": "abduttayyeb.github.io",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "maybebored",
|
||||
"name": "Mayuran",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20951181?v=4",
|
||||
"profile": "https://github.com/maybebored",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "MuckHub",
|
||||
"name": "Aleksei Vesselko",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/54979136?v=4",
|
||||
"profile": "https://github.com/MuckHub",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "p-siriphanthong",
|
||||
"name": "Punn Siriphanthong",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/29949429?v=4",
|
||||
"profile": "https://p-siriphanthong.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "shawn-fetanat",
|
||||
"name": "Shawn Fetanat",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/83679827?v=4",
|
||||
"profile": "https://my-portfolio-292eb.web.app",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mochi-sann",
|
||||
"name": "Moyuru",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/44772513?v=4",
|
||||
"profile": "https://github.com/mochi-sann",
|
||||
"contributions": [
|
||||
"code",
|
||||
"test",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "camsloanftc",
|
||||
"name": "Cam Sloan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/16295659?v=4",
|
||||
"profile": "https://github.com/camsloanftc",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sitek94",
|
||||
"name": "Maciek Sitkowski",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/58401630?v=4",
|
||||
"profile": "https://macieksitkowski.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "vivek7405",
|
||||
"name": "Vivek",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/24492244?v=4",
|
||||
"profile": "https://github.com/vivek7405",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cj",
|
||||
"name": "CJ Lazell",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1819?v=4",
|
||||
"profile": "http://cj.io",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "RobertBroersma",
|
||||
"name": "Robert",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/4519828?v=4",
|
||||
"profile": "robertbroersma.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cbejensen",
|
||||
"name": "Christian Jensen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12374723?v=4",
|
||||
"profile": "https://christianjensen.netlify.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dvnrsn",
|
||||
"name": "Devin Rasmussen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/9112811?v=4",
|
||||
"profile": "https://github.com/dvnrsn",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "devtombiz",
|
||||
"name": "Thomas Brenneur",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/23282613?v=4",
|
||||
"profile": "www.linkedin.com/in/devtom",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lucasvazq",
|
||||
"name": "Lucas Vazquez",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/38964964?v=4",
|
||||
"profile": "https://lucasvazq.github.io/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "chrisj-back2work",
|
||||
"name": "Chris Johnson",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/68551954?v=4",
|
||||
"profile": "https://github.com/chrisj-back2work",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "thisdotrob",
|
||||
"name": "Rob Stevenson",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12902589?v=4",
|
||||
"profile": "https://github.com/thisdotrob",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lovethebomb",
|
||||
"name": "Lucas Heymès",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1363056?v=4",
|
||||
"profile": "www.lucas.computer",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "NorfeldtAbtion",
|
||||
"name": "Lasse Norfeldt",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/53769763?v=4",
|
||||
"profile": "https://github.com/NorfeldtAbtion",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "netwarex",
|
||||
"name": "Péter Nyári",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6048614?v=4",
|
||||
"profile": "https://nyaripeter.hu/",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "5minpause",
|
||||
"name": "Holger Frohloff",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/84148?v=4",
|
||||
"profile": "https://www.holgerfrohloff.de",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "basilk76",
|
||||
"name": "Basil Khan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/45275512?v=4",
|
||||
"profile": "https://github.com/basilk76",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "danestves",
|
||||
"name": "Daniel Esteves",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/31737273?v=4",
|
||||
"profile": "https://danestves.com/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "coryhouse",
|
||||
"name": "Cory House",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1688997?v=4",
|
||||
"profile": "http://www.bitnative.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rockmanvnx6",
|
||||
"name": "Austin (Thang Pham)",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/16440123?v=4",
|
||||
"profile": "https://auspham.dev/",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "noxify",
|
||||
"name": "Marcus Reinhardt",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/521777?v=4",
|
||||
"profile": "https://jammeryhq.com",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "davidchristie",
|
||||
"name": "David Christie",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/12044333?v=4",
|
||||
"profile": "https://github.com/davidchristie",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ajanth97",
|
||||
"name": "Ajanth",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/50458502?v=4",
|
||||
"profile": "https://github.com/ajanth97",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "divpreet",
|
||||
"name": "Div",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2805650?v=4",
|
||||
"profile": "https://github.com/divpreet",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "david-arteaga",
|
||||
"name": "David Arteaga",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7199015?v=4",
|
||||
"profile": "https://github.com/david-arteaga",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "MukulKolpe",
|
||||
"name": "Mukul Kolpe",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/78664749?v=4",
|
||||
"profile": "https://github.com/MukulKolpe",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "skotchpine",
|
||||
"name": "tyler",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/13043909?v=4",
|
||||
"profile": "https://github.com/skotchpine",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "SofianeDjellouli",
|
||||
"name": "Sofiane Djellouli",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/38258952?v=4",
|
||||
"profile": "https://github.com/SofianeDjellouli",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kreako",
|
||||
"name": "kreako",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/65113001?v=4",
|
||||
"profile": "https://github.com/kreako",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sarahdayan",
|
||||
"name": "Sarah Dayan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5370675?v=4",
|
||||
"profile": "https://sarahdayan.dev",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "c-ciobanu",
|
||||
"name": "Cristi Ciobanu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/33382714?v=4",
|
||||
"profile": "https://github.com/c-ciobanu",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "arpitdalal",
|
||||
"name": "Arpit Dalal",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/61059807?v=4",
|
||||
"profile": "https://arpitdalal.dev",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "robertrisch",
|
||||
"name": "robertrisch",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/73828816?v=4",
|
||||
"profile": "https://github.com/robertrisch",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dineshgadge",
|
||||
"name": "Dinesh Gadge",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/186976?v=4",
|
||||
"profile": "https://github.com/dineshgadge",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "maltekiessling",
|
||||
"name": "Malte Kießling",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/30420110?v=4",
|
||||
"profile": "https://github.com/maltekiessling",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ospfranco",
|
||||
"name": "Oscar Franco",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1634213?v=4",
|
||||
"profile": "ospfranco.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Nfinished",
|
||||
"name": "Adam Trager",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1719791?v=4",
|
||||
"profile": "adamtrager.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "shellord",
|
||||
"name": "saheenshoukath",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2632896?v=4",
|
||||
"profile": "https://saheen.codes",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "husnuljahneer",
|
||||
"name": "Husnul Jahneer",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/54552763?v=4",
|
||||
"profile": "https://jahneer.me",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ReykCS",
|
||||
"name": "Reyk",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/40463716?v=4",
|
||||
"profile": "https://github.com/ReykCS",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Lokprakash-babu",
|
||||
"name": "Lokprakash Babu",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/60031382?v=4",
|
||||
"profile": "https://github.com/Lokprakash-babu",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "eai04191",
|
||||
"name": "eai04191",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3516343?v=4",
|
||||
"profile": "https://mizle.net",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "numanaral",
|
||||
"name": "Numan",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/25233323?v=4",
|
||||
"profile": "https://numanaral.github.io/?ref=github",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jscyo",
|
||||
"name": "Joel Coutinho",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6310783?v=4",
|
||||
"profile": "https://github.com/jscyo",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "davidbarker",
|
||||
"name": "David Barker",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1597139?v=4",
|
||||
"profile": "https://github.com/davidbarker",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "timfee",
|
||||
"name": "Tim Feeley",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3246342?v=4",
|
||||
"profile": "http://www.timfeeley.com/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Caslus",
|
||||
"name": "lucas philippe",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22855640?v=4",
|
||||
"profile": "https://github.com/Caslus",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "the-bayer",
|
||||
"name": "Blake Bayer",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/94391693?v=4",
|
||||
"profile": "https://github.com/the-bayer",
|
||||
"contributions": [
|
||||
"code",
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rmassie",
|
||||
"name": "R Massie",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7375518?v=4",
|
||||
"profile": "https://github.com/rmassie",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "paulm17",
|
||||
"name": "Paul",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/387463?v=4",
|
||||
"profile": "https://github.com/paulm17",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "minho42",
|
||||
"name": "Min ho Kim",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15278512?v=4",
|
||||
"profile": "https://minho42.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "webdeb",
|
||||
"name": "webdeb",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/14992140?v=4",
|
||||
"profile": "https://github.com/webdeb",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "iDavidB",
|
||||
"name": "David",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/32268383?v=4",
|
||||
"profile": "https://github.com/iDavidB",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jakedee",
|
||||
"name": "Jake Dowie",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5058625?v=4",
|
||||
"profile": "https://jdlt.co.uk",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "datner",
|
||||
"name": "Datner",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22598347?v=4",
|
||||
"profile": "https://github.com/datner",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "remlse",
|
||||
"name": "remlse",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/54984957?v=4",
|
||||
"profile": "https://github.com/remlse",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "sergous",
|
||||
"name": "Sergei Smirnov",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/545151?v=4",
|
||||
"profile": "https://github.com/sergous",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Trancever",
|
||||
"name": "Dawid Urbaniak",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/18584155?v=4",
|
||||
"profile": "https://twitter.com/trensik",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "SerekKiri",
|
||||
"name": "Kacper Potyrała",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/29735836?v=4",
|
||||
"profile": "kiri.dev",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "iojcde",
|
||||
"name": "Jeeho Ahn",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/31413538?v=4",
|
||||
"profile": "jcde.xyz",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"tool"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
@@ -48,6 +48,8 @@ eslint.config.*
|
||||
/nextjs/packages/next-codemod/**/*.js
|
||||
/nextjs/packages/next-codemod/**/*.d.ts
|
||||
/nextjs/packages/next-env/**/*.d.ts
|
||||
/nextjs/packages/next/build/swc/tests/fixture/**
|
||||
/nextjs/test/integration/async-modules/**
|
||||
/nextjs/test/integration/eslint/**
|
||||
/nextjs/test/integration/babel/**
|
||||
/nextjs/test-timings.json
|
||||
|
||||
10
.eslintrc.js
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
parser: "babel-eslint",
|
||||
parser: "@babel/eslint-parser",
|
||||
env: {
|
||||
browser: true,
|
||||
commonjs: true,
|
||||
@@ -8,10 +8,18 @@ module.exports = {
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
requireConfigFile: false,
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
babelOptions: {
|
||||
presets: ["@babel/preset-env", "@babel/preset-react"],
|
||||
caller: {
|
||||
// Eslint supports top level await when a parser for it is included. We enable the parser by default for Babel.
|
||||
supportsTopLevelAwait: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: ["import", "unicorn", "simple-import-sort"],
|
||||
extends: ["react-app"],
|
||||
|
||||
4
.github/CODEOWNERS
vendored
@@ -1,8 +1,8 @@
|
||||
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
|
||||
|
||||
* @flybayer
|
||||
* @beerose
|
||||
|
||||
# packages/cli/**/* @aem, @flybayer
|
||||
# packages/generator/**/* @aem @flybayer
|
||||
packages/generator/templates**/* @flybayer
|
||||
# packages/generator/templates**/* @flybayer
|
||||
# packages/installer/**/* @aem @flybayer
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -16,4 +16,4 @@ Closes: ?
|
||||
## Feature Checklist
|
||||
|
||||
- [ ] Integration test added (see [test docs](https://blitzjs.com/docs/contributing#running-tests) if needed)
|
||||
- [ ] Documentation added/updated (submit PR to [blitzjs.com repo](https://github.com/blitz-js/blitzjs.com))
|
||||
- [ ] Documentation added/updated (submit PR to [blitzjs.com repo `canary` branch](https://github.com/blitz-js/blitzjs.com/tree/canary))
|
||||
|
||||
4
.github/workflows/compressed.yml
vendored
@@ -15,6 +15,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
- name: Count size
|
||||
uses: preactjs/compressed-size-action@v2
|
||||
with:
|
||||
|
||||
100
.github/workflows/main.yml
vendored
@@ -30,9 +30,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v14-
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
env:
|
||||
@@ -41,8 +41,8 @@ jobs:
|
||||
run: yarn manypkg check
|
||||
env:
|
||||
CI: true
|
||||
- name: Build next.js
|
||||
run: yarn build:nextjs
|
||||
- name: Build packages
|
||||
run: yarn build
|
||||
env:
|
||||
CI: true
|
||||
- name: yarn lint
|
||||
@@ -54,7 +54,7 @@ jobs:
|
||||
name: Build
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -74,9 +74,9 @@ jobs:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
${{ runner.os }}-${{ runner.node_version}}-yarn-v14-
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
- name: Build Packages
|
||||
run: yarn build
|
||||
@@ -91,13 +91,17 @@ jobs:
|
||||
needs: build-linux
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
- name: Setup kernel to increase watchers
|
||||
if: runner.os == 'Linux'
|
||||
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
@@ -106,19 +110,51 @@ jobs:
|
||||
env:
|
||||
CI: true
|
||||
|
||||
testNextPackages:
|
||||
name: Next - Test Packages
|
||||
defaults:
|
||||
run:
|
||||
working-directory: nextjs
|
||||
needs: build-linux
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
- name: Setup kernel to increase watchers
|
||||
if: runner.os == 'Linux'
|
||||
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
- name: Test Next Packages
|
||||
run: yarn testonly:packages
|
||||
env:
|
||||
CI: true
|
||||
|
||||
testBlitzExamples:
|
||||
timeout-minutes: 30
|
||||
name: Blitz - Test Example Apps (ubuntu-latest)
|
||||
needs: build-linux
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
DEBUG: blitz:session
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
# Needed to get cypress binary
|
||||
- run: yarn cypress install
|
||||
- name: Install sass
|
||||
@@ -136,7 +172,7 @@ jobs:
|
||||
name: Blitz - Test Example Apps (windows-latest)
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -156,9 +192,9 @@ jobs:
|
||||
# path: |
|
||||
# ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
# **/node_modules
|
||||
# key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
# key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-${{ hashFiles('yarn.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
# ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
- name: Build Packages
|
||||
run: yarn build
|
||||
@@ -179,14 +215,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-linux
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
id: restore-build
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- run: ./check-pre-compiled.sh
|
||||
- run: ./scripts/check-pre-compiled.sh
|
||||
|
||||
testUnit:
|
||||
name: Nextjs - Test Unit
|
||||
@@ -196,7 +232,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-linux
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
steps:
|
||||
@@ -212,7 +248,7 @@ jobs:
|
||||
needs: build-linux
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
steps:
|
||||
@@ -221,6 +257,10 @@ jobs:
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
|
||||
# TODO: remove after we fix watchpack watching too much
|
||||
- name: Setup kernel to increase watchers
|
||||
@@ -233,7 +273,7 @@ jobs:
|
||||
name: Blitz - Test Integration (Windows)
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
steps:
|
||||
@@ -255,9 +295,9 @@ jobs:
|
||||
# path: |
|
||||
# ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
# **/node_modules
|
||||
# key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
# key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-${{ hashFiles('yarn.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
# ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
- name: Build Packages
|
||||
run: yarn build
|
||||
@@ -271,7 +311,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-linux
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
strategy:
|
||||
@@ -284,7 +324,10 @@ jobs:
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ runner.os }}-${{ github.sha }}
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "14"
|
||||
# TODO: remove after we fix watchpack watching too much
|
||||
- name: Setup kernel to increase watchers
|
||||
if: runner.os == 'Linux'
|
||||
@@ -295,7 +338,7 @@ jobs:
|
||||
name: Nextjs - Test Integration (Windows)
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
steps:
|
||||
@@ -317,9 +360,9 @@ jobs:
|
||||
# path: |
|
||||
# ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
# **/node_modules
|
||||
# key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-${{ hashFiles('yarn.lock') }}
|
||||
# key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-${{ hashFiles('yarn.lock') }}
|
||||
# restore-keys: |
|
||||
# ${{ runner.os }}-${{ runner.node_version}}-yarn-v13-
|
||||
# ${{ runner.os }}-${{ runner.node_version}}-yarn-v14-
|
||||
- run: yarn install --frozen-lockfile --check-files
|
||||
- name: Build Packages
|
||||
run: yarn build
|
||||
@@ -334,7 +377,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-linux
|
||||
env:
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
NEXT_TEST_JOB: 1
|
||||
HEADLESS: true
|
||||
TEST_ELECTRON: 1
|
||||
@@ -362,6 +405,7 @@ jobs:
|
||||
testIntegrationBlitzWin,
|
||||
testUnit,
|
||||
testBlitzPackages,
|
||||
testNextPackages,
|
||||
testBlitzExamples,
|
||||
testBlitzExamplesWin,
|
||||
]
|
||||
@@ -378,7 +422,7 @@ jobs:
|
||||
env:
|
||||
HEADLESS: true
|
||||
BROWSER_NAME: "firefox"
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
steps:
|
||||
- uses: actions/cache@v2
|
||||
id: restore-build
|
||||
@@ -397,7 +441,7 @@ jobs:
|
||||
env:
|
||||
BROWSERSTACK: true
|
||||
BROWSER_NAME: "safari"
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
SKIP_LOCAL_SELENIUM_SERVER: true
|
||||
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
|
||||
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
|
||||
@@ -420,7 +464,7 @@ jobs:
|
||||
BROWSERSTACK: true
|
||||
LEGACY_SAFARI: true
|
||||
BROWSERNAME: "safari"
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
BLITZ_TELEMETRY_DISABLED: 1
|
||||
SKIP_LOCAL_SELENIUM_SERVER: true
|
||||
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
|
||||
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
|
||||
|
||||
3
.gitignore
vendored
@@ -30,4 +30,7 @@ examples/auth2
|
||||
db.sqlite-journal
|
||||
test/integration/**/db.json
|
||||
test/**/*/out
|
||||
test/**/blitz-env.d.ts
|
||||
examples/**/blitz-env.d.ts
|
||||
.blitz**
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
# Minimal config. version is the only required field.
|
||||
version = 1
|
||||
merge.automerge_label = "0 - <(^_^)> - merge it! ✌️"
|
||||
approve.auto_approve_usernames = ["flybayer", "depfu"]
|
||||
approve.auto_approve_usernames = ["flybayer", "beerose", "depfu"]
|
||||
|
||||
@@ -1 +1 @@
|
||||
12.20.0
|
||||
14.18.1
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
|
||||
## Notes For Core Team
|
||||
|
||||
### To Publish a new NPM Package under `@blitzjs/` namespace
|
||||
|
||||
1. cd into the package directory
|
||||
2. Run `npm publish --tag danger --access public`
|
||||
- `--access public` is required because scoped packages are set to private by default
|
||||
|
||||
### Syncing Next.js Fork
|
||||
|
||||
1. Run `yarn push-nextjs`
|
||||
@@ -19,11 +25,12 @@
|
||||
6. Resolve all merge conflicts and complete merge
|
||||
7. Run `yarn` and make sure all builds complete
|
||||
8. Run `yarn lint` and fix any issues
|
||||
9. `git push`
|
||||
4. Run `yarn pull next-nextjs`
|
||||
9. Commit all changes to finish merge
|
||||
10. `git push`
|
||||
4. Run `yarn pull-nextjs`
|
||||
5. Run `yarn`
|
||||
6. Run `yarn manypkg check` and optionally `yarn manypkg fix` to fix any issues
|
||||
7. Under `nextjs/`, run `./check-pre-compiled.sh` and commit the changes
|
||||
7. Under `nextjs/`, run `./scripts/check-pre-compiled.sh` and commit the changes
|
||||
8. Run `yarn build:nextjs`
|
||||
9. Run `yarn lint` - fix any issues
|
||||
10. Run `yarn build` - fix any issues
|
||||
@@ -33,3 +40,52 @@
|
||||
14. Any doc updates needed?
|
||||
15. Merge PR
|
||||
16. `yarn push-nextjs`
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
##### yarn lint - Failed to load parser
|
||||
|
||||
Caused by invalid version of `@babel/eslint-parser`. `7.13.14` is a working version. I think it may be an incompatibility between this version and the version of eslint?
|
||||
|
||||
- change version of eslint-parser
|
||||
- run `yarn --check-files`
|
||||
- run `./scripts/check-pre-compiled.sh` from `./nextjs/`
|
||||
- run `yarn build:nextjs` from root
|
||||
- Try linting again
|
||||
|
||||
```
|
||||
~/c/blitz> yarn lint
|
||||
yarn run v1.22.10
|
||||
$ eslint --ext ".js,.ts,.tsx" .
|
||||
|
||||
Oops! Something went wrong! :(
|
||||
|
||||
ESLint: 7.21.0
|
||||
|
||||
Error: Failed to load parser './parser.js' declared in 'examples/auth/.eslintrc.js » eslint-config-blitz » eslint-config-next': Cannot find module '@babel/parser'
|
||||
at webpackEmptyContext (/Users/b/c/blitz/nextjs/packages/next/dist/compiled/babel/bundle.js:1:33258)
|
||||
at Object.73139 (/Users/b/c/blitz/nextjs/packages/next/dist/compiled/babel/bundle.js:2194:783181)
|
||||
at __nccwpck_require__ (/Users/b/c/blitz/nextjs/packages/next/dist/compiled/babel/bundle.js:2194:1065271)
|
||||
at Object.eslintParser (/Users/b/c/blitz/nextjs/packages/next/dist/compiled/babel/bundle.js:1:43676)
|
||||
at Object.<anonymous> (/Users/b/c/blitz/nextjs/packages/next/dist/compiled/babel/eslint-parser.js:1:100)
|
||||
at Module._compile (/Users/b/c/blitz/node_modules/v8-compile-cache/v8-compile-cache.js:192:30)
|
||||
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
|
||||
at Module.load (internal/modules/cjs/loader.js:863:32)
|
||||
at Function.Module._load (internal/modules/cjs/loader.js:708:14)
|
||||
at Module.require (internal/modules/cjs/loader.js:887:19)
|
||||
error Command failed with exit code 2.
|
||||
```
|
||||
|
||||
##### Failed to compile - LICENSE
|
||||
|
||||
This error occurs sometimes when you import code from packages/next/build/utils.ts into some other code like config-shared.ts. Solution is to move the code into another file.
|
||||
|
||||
```
|
||||
Failed to compile.
|
||||
../../../packages/next/dist/compiled/webpack/LICENSE
|
||||
Module parse failed: Unexpected token (1:10)
|
||||
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See webpack.js.org/concepts#loaders
|
||||
> Copyright JS Foundation and other contributors
|
||||
|
|
||||
| Permission is hereby granted, free of charge, to any person obtaining
|
||||
```
|
||||
|
||||
213
README.md
@@ -6,7 +6,7 @@
|
||||
<img alt="" src="https://img.shields.io/badge/Join%20our%20community-6700EB.svg?style=for-the-badge&labelColor=000000&logoWidth=20&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQ9SURBVHgB7d3dVdtAEIbhcSpICUoH0IEogQqSVBBSAU4FSSpIOoAORAfQgSghHXzZ1U/YcMD4R9rZmf2ec3y448LyiNf27iLiGIAmPLrweC9Un3DhrzG6EarLNP09nlwJ1SOZ/lQr5N80/S/p2QMVCBf5N17XCfm1Y/rBHqjAG9PPHvBsz+mf9WAP+HLA9M/YA14cOP2payH7jpj+VCtk1wnTP+vj7xCy6cTpn7EHLMLp059iD1iD8eveJbVCNsSLheX1YA/YgOWnf8YeKB3Wmf7Ud6Fy4f/FHmtpxbl3YlC4MJ/Cj0bWdwPnPbARg+L0S54XQHS32WwuxClzd4CM0z9rPfeAuTtA5ulPXYQ7wZ04Y+oOoDD9KZc9YOoOoDj9s4dwFzgXR6w1wIPoOvPWA9buAHEJ173o3gWiy3AnuBUHLEbgmYwvAk1/wuM8vAgexThzbwPDkx7/DHwVXfFOxP2GmsKd4Ab6zPeAyU8CI7AHFmH2BRCBPXAyk18GzUrqAXCTiR4ssyj0VFw/oCU8+e+RZ33AWz6KMaYbIIWxB+JSLs1bsbkeMN0AqakHvoku9oA2sAfqBvbAQdw0QArsgb25aYBUQT3QgT2gB+yBuqGcHij2UCqXDZACe2Anlw2QYg/QAOyBuoE98CL3DZDCuK4/rh/Q7oGL6U+TOvcNkJoijN8X1C48+T+g75eQDrAH/qmqAVJgDwyqaoAUe4AGYA/UDZX3QLUNkEIZPRCd5+6BahsgVUgPROwBTSijB7jpVAvGHriHvmw9wAZ4BpX1ABvgmakHtPcbRuwBTWAPULgAV9D/jKDY9YRvwvgEaurD44uQHvAol7qBW7WKluVtIHiUS7GyvA0s6CiXDnxrpQfsgbqBS7GKk/2jYHCrVlGyfxTMrVo0ALdq1Q3sgSKofh0M9oA61a+D2QM0AHugbmAPqClmSRjK2apVVQ8UsySsoK1aHdgDesCtWnUDeyCrIpeFg1u3sylyWTi3btMA7IG6gT2wuuK3hoE9sKrit4YVslWLPaAN7IG6ocKt2zmY2h4O9sDiTG0PZw/QANy6XTewBxZj9ogYVHy025LMHhEz9cBn0We6B0yfERReBLfhx0/R1YQHPx/QBPbA0VwcEwf2wNFcHBPHHjiem3MC2QPHcXdSaJjA+KfgTPQ8hhfjBzHC40mhlzJ+Xq9lK4a4PCs43AVaGTed5mZq+iOXZwWHi3AnOj2wFWNcnxYe7gTxLtBKHuamP/J+Wnh8a5irB7ZC5Yk9gPX1QuXC+usHWqGyhYvUYR0a7zboUOFCNVhnk0krZAOW7wFOvzXhom2xnEbIHizTA1wEYhWW6YFGyC6c1gOcfg9wfA80Qj7g8B7g9HuCww+haIR8wf49wOn3Cvv9k8tGyC/s7gFOv3fY3QONkH+v9MBWqB7PeqDn9FcIT//kcitUn6kHOu/T/xfWzlQy3dEHhwAAAABJRU5ErkJggg==">
|
||||
</a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-319-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-408-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||
<a aria-label="License" href="https://github.com/blitz-js/blitz/blob/canary/LICENSE">
|
||||
<img alt="" src="https://img.shields.io/npm/l/blitz.svg?style=for-the-badge&labelColor=000000&color=blue">
|
||||
@@ -22,7 +22,7 @@
|
||||
<h1 align="center">The Fullstack React Framework</h1>
|
||||
|
||||
<h5 align="center">"Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails</h3>
|
||||
<h3 align="center"><a href="https://blitzjs.com" target="_blank">Read the Documentation</a></h3>
|
||||
<h3 align="center"><a href="https://blitzjs.com/docs/get-started" target="_blank">Read the Documentation</a></h3>
|
||||
<br>
|
||||
|
||||
“Zero-API” data layer **lets you import server code directly into your React components** instead of having to manually add API endpoints and do client-side fetching and caching.
|
||||
@@ -107,18 +107,21 @@ Your financial contributions help ensure Blitz continues to be developed and mai
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><a aria-label="Andreas Asprou" href="https://andreas.fyi">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/andreas.jpg" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="Robert Malko" href="https://github.com/malkomalko">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/rob_blitz.jpg" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="Digas" href="https://digsas.com">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/digsas.svg" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="userTrack" href="https://www.usertrack.net/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/usertrack.png" width="40px"/>
|
||||
</a></td>
|
||||
<td>
|
||||
<a aria-label="Andreas Asprou" href="https://andreas.fyi">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/andreas.jpg" width="40px"/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a aria-label="MeetKai" href="https://meetkai.com/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/meetkai.png" width="40px"/>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a aria-label="JDLT" href="https://jdlt.co.uk/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/jdlt.png" width="40px"/>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
@@ -132,11 +135,15 @@ Your financial contributions help ensure Blitz continues to be developed and mai
|
||||
</a></td>
|
||||
<td><a aria-label="RIT" href="https://rit-inc.co.jp/?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2021">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/rit_logo.png" width="200px">
|
||||
</a></td>
|
||||
<td><a aria-label="Boostry" href="https://boostry.co.jp/?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2021">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/boostry.svg" width="200px">
|
||||
</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
### 🥈 Silver Sponsors
|
||||
|
||||
<table>
|
||||
@@ -145,11 +152,6 @@ Your financial contributions help ensure Blitz continues to be developed and mai
|
||||
<a aria-label="Fauna" href="https://dashboard.fauna.com/accounts/register?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2020">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/Fauna_Logo_Blue.png" width="300px">
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a aria-label="GraphCMS" href="https://graphcms.com/?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2021">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/graphcms.png" width="300px">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -174,6 +176,8 @@ Your financial contributions help ensure Blitz continues to be developed and mai
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://twitter.com/flybayer"><img src="https://avatars3.githubusercontent.com/u/8813276?v=4" width="100px;" alt=""/><br /><sub><b>Brandon Bayer</b></sub></a><br />Creator</td>
|
||||
<td align="center"><a href="http://aleksandra.codes"><img src="https://avatars.githubusercontent.com/u/9019397?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksandra Sikora</b></sub></a><br />Lead Maintainer</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
@@ -209,22 +213,6 @@ _Issue triage, pull request triage, community encouragement and moderation, etc_
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="http://jeremyliberman.com/"><img src="https://avatars3.githubusercontent.com/u/2754163?v=4" width="100px;" alt=""/><br /><sub><b>Jeremy Liberman</b></td>
|
||||
<td align="center"><a href="https://twitter.com/nitaking_"><img src="https://avatars2.githubusercontent.com/u/10850034?v=4" width="100px;" alt=""/><br /><sub><b>Satoshi Nitawaki</b></sub></a></td>
|
||||
<td align="center"><a href="https://github.com/engelkes-finstreet"><img src="https://avatars0.githubusercontent.com/u/36962022?s=460&u=34cfc4a3d6da0a87026f6068c371779c68daa3a2&v=4" width="100px;" alt=""/><br /><sub><b>Patrick Engelkes</b></sub></a></td>
|
||||
<td align="center"><a href="https://twitter.com/myrondavis"><img src="https://avatars2.githubusercontent.com/u/1430136?v=4" width="100px;" alt=""/><br /><sub><b>Myron Davis</b></sub></a></td>
|
||||
<td align="center"><a href="https://twitter.com/NaReto1125_"><img src="https://avatars.githubusercontent.com/reo777" width="100px;" alt=""/><br /><sub><b>Reo Ishiyama</b></sub></a></td>
|
||||
<td align="center">
|
||||
<a href="https://kevinlangleyjr.com">
|
||||
<img
|
||||
src="https://avatars.githubusercontent.com/u/877634?v=4"
|
||||
width="100px;"
|
||||
alt=""
|
||||
/><br />
|
||||
<sub>
|
||||
<b>Kevin Langley Jr.</b>
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://mina.ca">
|
||||
<img src="https://avatars.githubusercontent.com/mabadir" width="100px;" alt="Mina Abadir avatar" /><br />
|
||||
@@ -233,8 +221,6 @@ _Issue triage, pull request triage, community encouragement and moderation, etc_
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://builtforfifty.com">
|
||||
<img src="https://avatars.githubusercontent.com/abuuzayr" width="100px;" alt="Abu Uzayr avatar" /><br />
|
||||
@@ -243,6 +229,30 @@ _Issue triage, pull request triage, community encouragement and moderation, etc_
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://damilolarandolph.com/">
|
||||
<img src="https://avatars.githubusercontent.com/damilolarandolph" width="100px;" alt="Damilola Randolph avatar" /><br />
|
||||
<sub>
|
||||
<b>Damilola Randolph</b>
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://www.saheen.me/">
|
||||
<img src="https://avatars.githubusercontent.com/shellord" width="100px;" alt="Saheen Shoukath avatar" /><br />
|
||||
<sub>
|
||||
<b>Saheen Shoukath</b>
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://jahneer.me">
|
||||
<img src="https://avatars.githubusercontent.com/husnuljahneer" width="100px;" alt="Husnul Jahneer avatar" /><br />
|
||||
<sub>
|
||||
<b>Husnul Jahneer</b>
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
@@ -297,7 +307,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/sonnypgs"><img src="https://avatars3.githubusercontent.com/u/1431300?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sonny</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sonnypgs" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Zeko369"><img src="https://avatars3.githubusercontent.com/u/3064377?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fran Zekan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Zeko369" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Zeko369" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Zeko369"><img src="https://avatars3.githubusercontent.com/u/3064377?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fran Zekan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Zeko369" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Zeko369" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Zeko369" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="http://twitter.com/JanBaykara"><img src="https://avatars2.githubusercontent.com/u/237556?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jan Baykara</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=janbaykara" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://mikeattara.com"><img src="https://avatars1.githubusercontent.com/u/31483629?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike Perry Y Attara</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mikeattara" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://devanthe.dev"><img src="https://avatars0.githubusercontent.com/u/354652?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Devan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=DevanB" title="Documentation">📖</a></td>
|
||||
@@ -338,7 +348,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="http://anteprimorac.com.hr"><img src="https://avatars0.githubusercontent.com/u/972083?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ante Primorac</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=anteprimorac" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=anteprimorac" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://mykalmachon.dev"><img src="https://avatars1.githubusercontent.com/u/7844994?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mykal Machon</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MykalMachon" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://jamiedavenport.dev"><img src="https://avatars2.githubusercontent.com/u/1329874?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jamie Davenport</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jamiedavenport" title="Code">💻</a> <a href="#maintenance-jamiedavenport" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://cloudnweb.dev/"><img src="https://avatars0.githubusercontent.com/u/17050715?v=4?s=100" width="100px;" alt=""/><br /><sub><b>GaneshMani</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ganeshmani" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://cloudnweb.dev/"><img src="https://avatars0.githubusercontent.com/u/17050715?v=4?s=100" width="100px;" alt=""/><br /><sub><b>GaneshMani</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ganeshmani" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=ganeshmani" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://ramonmorcillo.com"><img src="https://avatars3.githubusercontent.com/u/31936665?v=4?s=100" width="100px;" alt=""/><br /><sub><b>reymon359</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=reymon359" title="Code">💻</a></td>
|
||||
@@ -387,7 +397,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/jschepmans"><img src="https://avatars2.githubusercontent.com/u/5782977?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johan Schepmans</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jschepmans" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/dillonraphael"><img src="https://avatars0.githubusercontent.com/u/3496193?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dillon Raphael</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/dillonraphael"><img src="https://avatars0.githubusercontent.com/u/3496193?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dillon Raphael</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/clgeoio"><img src="https://avatars2.githubusercontent.com/u/37571416?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cody G</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=clgeoio" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=clgeoio" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/madflow"><img src="https://avatars0.githubusercontent.com/u/183248?v=4?s=100" width="100px;" alt=""/><br /><sub><b>madflow</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=madflow" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/nitaking_"><img src="https://avatars2.githubusercontent.com/u/10850034?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Satoshi Nitawaki</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nitaking" title="Code">💻</a> <a href="#maintenance-nitaking" title="Maintenance">🚧</a> <a href="#question-nitaking" title="Answering Questions">💬</a> <a href="https://github.com/blitz-js/blitz/commits?author=nitaking" title="Documentation">📖</a></td>
|
||||
@@ -467,7 +477,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://chriswray.dev/"><img src="https://avatars0.githubusercontent.com/u/53663762?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christopher Wray</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cwray-tech" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/piotrski"><img src="https://avatars0.githubusercontent.com/u/244174?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piotrek Tomczewski</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=piotrski" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/piotrski"><img src="https://avatars0.githubusercontent.com/u/244174?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piotrek Tomczewski</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=piotrski" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=piotrski" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://raph.site"><img src="https://avatars3.githubusercontent.com/u/1575946?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Raphaël Huchet</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kattcorp.com"><img src="https://avatars1.githubusercontent.com/u/459267?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Johansson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=KATT" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://davidmazza.com"><img src="https://avatars0.githubusercontent.com/u/120893?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Mazza</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dmzza" title="Code">💻</a></td>
|
||||
@@ -530,7 +540,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://brianypliu.com"><img src="https://avatars.githubusercontent.com/u/3888780?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Brian Liu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=LBrian" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://aleksandra.codes"><img src="https://avatars.githubusercontent.com/u/9019397?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksandra Sikora</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://aleksandra.codes"><img src="https://avatars.githubusercontent.com/u/9019397?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksandra Sikora</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://juanm04.com"><img src="https://avatars.githubusercontent.com/u/16712703?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JuanM04</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=JuanM04" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=JuanM04" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=JuanM04" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/arenddeboer"><img src="https://avatars.githubusercontent.com/u/7022204?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arend de Boer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arenddeboer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/fmilani"><img src="https://avatars.githubusercontent.com/u/1580375?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Felipe Milani</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fmilani" title="Documentation">📖</a></td>
|
||||
@@ -661,14 +671,129 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://github.com/bravo-kernel"><img src="https://avatars.githubusercontent.com/u/230500?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bravo-kernel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bravo-kernel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://samholmes.net"><img src="https://avatars.githubusercontent.com/u/8385528?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sam Holmes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sam3d" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://doncicuto.medium.com"><img src="https://avatars.githubusercontent.com/u/30386061?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Miguel Cabrerizo</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doncicuto" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=doncicuto" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://zackhobson.com/"><img src="https://avatars.githubusercontent.com/u/12092?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zack Hobson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=zenhob" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://zackhobson.com/"><img src="https://avatars.githubusercontent.com/u/12092?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zack Hobson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=zenhob" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=zenhob" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.mokhtar.dev"><img src="https://avatars.githubusercontent.com/u/13026820?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mokhtar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=m5r" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kenkuan"><img src="https://avatars.githubusercontent.com/u/1924968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ken Kuan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kenkuan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/meehawk"><img src="https://avatars.githubusercontent.com/u/80167324?v=4?s=100" width="100px;" alt=""/><br /><sub><b>meehawk</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=meehawk" title="Code">💻</a></td>
|
||||
<td align="center"><a href="rahulravindran.in"><img src="https://avatars.githubusercontent.com/u/10168946?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rahul Ravindran</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ravindranrahul" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/s-r-x"><img src="https://avatars.githubusercontent.com/u/41614937?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ilya</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/s-r-x"><img src="https://avatars.githubusercontent.com/u/41614937?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ilya</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/hashimwarren"><img src="https://avatars.githubusercontent.com/u/6027587?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hashim Warren</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hashimwarren" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://damilolarandolph.com"><img src="https://avatars.githubusercontent.com/u/43427949?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Damilola Randolph</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=damilolarandolph" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/mwcampbell"><img src="https://avatars.githubusercontent.com/u/214820?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt Campbell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mwcampbell" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ratson"><img src="https://avatars.githubusercontent.com/u/2682937?v=4?s=100" width="100px;" alt=""/><br /><sub><b>(◕ᴥ◕)</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ratson" title="Code">💻</a></td>
|
||||
<td align="center"><a href="maciejmyslinski.com"><img src="https://avatars.githubusercontent.com/u/11421186?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mat Milbury</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maciejmyslinski" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://andreas.fyi"><img src="https://avatars.githubusercontent.com/u/8077469?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andreas Asprou</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=andreasasprou" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=andreasasprou" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/kotx"><img src="https://avatars.githubusercontent.com/u/33439542?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kot</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kotx" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=kotx" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=kotx" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/isaka1022"><img src="https://avatars.githubusercontent.com/u/28589716?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amane</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=isaka1022" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="johnleung.com"><img src="https://avatars.githubusercontent.com/u/20699?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Leung</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fuzzthink" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="roettgers.co"><img src="https://avatars.githubusercontent.com/u/29666239?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bruce</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bcye" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/emilygracekz"><img src="https://avatars.githubusercontent.com/u/57361805?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Emily</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=emilygracekz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/npverni"><img src="https://avatars.githubusercontent.com/u/3537?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nathan Verni</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=npverni" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://davyengone.io"><img src="https://avatars.githubusercontent.com/u/4896002?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Davy Engone</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davyengone" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://fedeorlandau.dev/"><img src="https://avatars.githubusercontent.com/u/10283686?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Federico Joel Orlandau</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Fedeorlandau" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Fedeorlandau" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/johnmurphy01"><img src="https://avatars.githubusercontent.com/u/2939548?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Murphy</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=johnmurphy01" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=johnmurphy01" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/martinsaxa"><img src="https://avatars.githubusercontent.com/u/33789474?v=4?s=100" width="100px;" alt=""/><br /><sub><b>martinsaxa</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=martinsaxa" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ajwgeek"><img src="https://avatars.githubusercontent.com/u/2135600?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austin Walhof</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ajwgeek" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="g3offrey.dev"><img src="https://avatars.githubusercontent.com/u/11151445?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Geoffrey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=g3offrey" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=g3offrey" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=g3offrey" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/keevan"><img src="https://avatars.githubusercontent.com/u/9924643?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Pham</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=keevan" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/kimngan-bui"><img src="https://avatars.githubusercontent.com/u/20723478?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kimngan-bui</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kimngan-bui" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="world.hey.com/bach"><img src="https://avatars.githubusercontent.com/u/11691670?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bahk Chanhee</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=9j" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.afterecon.com/"><img src="https://avatars.githubusercontent.com/u/5559355?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Vandivier</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Vandivier" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Vandivier" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=Vandivier" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://namirsab.github.io"><img src="https://avatars.githubusercontent.com/u/6980777?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Namir</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=namirsab" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=namirsab" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=namirsab" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://twitter.com/scttcper"><img src="https://avatars.githubusercontent.com/u/1400464?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Scott Cooper</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=scttcper" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="abduttayyeb.github.io"><img src="https://avatars.githubusercontent.com/u/55306260?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Abduttayyeb M.r</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Abduttayyeb" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/maybebored"><img src="https://avatars.githubusercontent.com/u/20951181?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mayuran</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maybebored" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/MuckHub"><img src="https://avatars.githubusercontent.com/u/54979136?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksei Vesselko</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MuckHub" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://p-siriphanthong.github.io/"><img src="https://avatars.githubusercontent.com/u/29949429?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Punn Siriphanthong</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=p-siriphanthong" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://my-portfolio-292eb.web.app"><img src="https://avatars.githubusercontent.com/u/83679827?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shawn Fetanat</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=shawn-fetanat" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/mochi-sann"><img src="https://avatars.githubusercontent.com/u/44772513?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Moyuru</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mochi-sann" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=mochi-sann" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=mochi-sann" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/camsloanftc"><img src="https://avatars.githubusercontent.com/u/16295659?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cam Sloan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=camsloanftc" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://macieksitkowski.com"><img src="https://avatars.githubusercontent.com/u/58401630?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maciek Sitkowski</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sitek94" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/vivek7405"><img src="https://avatars.githubusercontent.com/u/24492244?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vivek</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=vivek7405" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=vivek7405" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://cj.io"><img src="https://avatars.githubusercontent.com/u/1819?v=4?s=100" width="100px;" alt=""/><br /><sub><b>CJ Lazell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="robertbroersma.com"><img src="https://avatars.githubusercontent.com/u/4519828?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=RobertBroersma" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://christianjensen.netlify.com"><img src="https://avatars.githubusercontent.com/u/12374723?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christian Jensen</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cbejensen" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/dvnrsn"><img src="https://avatars.githubusercontent.com/u/9112811?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Devin Rasmussen</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dvnrsn" title="Code">💻</a></td>
|
||||
<td align="center"><a href="www.linkedin.com/in/devtom"><img src="https://avatars.githubusercontent.com/u/23282613?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Thomas Brenneur</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=devtombiz" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=devtombiz" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=devtombiz" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://lucasvazq.github.io/"><img src="https://avatars.githubusercontent.com/u/38964964?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lucas Vazquez</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lucasvazq" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chrisj-back2work"><img src="https://avatars.githubusercontent.com/u/68551954?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Johnson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chrisj-back2work" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/thisdotrob"><img src="https://avatars.githubusercontent.com/u/12902589?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rob Stevenson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=thisdotrob" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.lucas.computer"><img src="https://avatars.githubusercontent.com/u/1363056?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lucas Heymès</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lovethebomb" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=lovethebomb" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/NorfeldtAbtion"><img src="https://avatars.githubusercontent.com/u/53769763?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lasse Norfeldt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=NorfeldtAbtion" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://nyaripeter.hu/"><img src="https://avatars.githubusercontent.com/u/6048614?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Péter Nyári</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=netwarex" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=netwarex" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.holgerfrohloff.de"><img src="https://avatars.githubusercontent.com/u/84148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Holger Frohloff</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=5minpause" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/basilk76"><img src="https://avatars.githubusercontent.com/u/45275512?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Basil Khan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=basilk76" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://danestves.com/"><img src="https://avatars.githubusercontent.com/u/31737273?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Esteves</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=danestves" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.bitnative.com"><img src="https://avatars.githubusercontent.com/u/1688997?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cory House</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=coryhouse" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://auspham.dev/"><img src="https://avatars.githubusercontent.com/u/16440123?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austin (Thang Pham)</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rockmanvnx6" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://jammeryhq.com"><img src="https://avatars.githubusercontent.com/u/521777?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Marcus Reinhardt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=noxify" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=noxify" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/davidchristie"><img src="https://avatars.githubusercontent.com/u/12044333?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Christie</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davidchristie" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/ajanth97"><img src="https://avatars.githubusercontent.com/u/50458502?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ajanth</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ajanth97" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/divpreet"><img src="https://avatars.githubusercontent.com/u/2805650?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Div</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=divpreet" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/david-arteaga"><img src="https://avatars.githubusercontent.com/u/7199015?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Arteaga</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=david-arteaga" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/MukulKolpe"><img src="https://avatars.githubusercontent.com/u/78664749?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mukul Kolpe</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MukulKolpe" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/skotchpine"><img src="https://avatars.githubusercontent.com/u/13043909?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tyler</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=skotchpine" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/SofianeDjellouli"><img src="https://avatars.githubusercontent.com/u/38258952?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sofiane Djellouli</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=SofianeDjellouli" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/kreako"><img src="https://avatars.githubusercontent.com/u/65113001?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kreako</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kreako" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://sarahdayan.dev"><img src="https://avatars.githubusercontent.com/u/5370675?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sarah Dayan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sarahdayan" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/c-ciobanu"><img src="https://avatars.githubusercontent.com/u/33382714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cristi Ciobanu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=c-ciobanu" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://arpitdalal.dev"><img src="https://avatars.githubusercontent.com/u/61059807?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arpit Dalal</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arpitdalal" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/robertrisch"><img src="https://avatars.githubusercontent.com/u/73828816?v=4?s=100" width="100px;" alt=""/><br /><sub><b>robertrisch</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robertrisch" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/dineshgadge"><img src="https://avatars.githubusercontent.com/u/186976?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dinesh Gadge</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dineshgadge" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/maltekiessling"><img src="https://avatars.githubusercontent.com/u/30420110?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Malte Kießling</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maltekiessling" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="ospfranco.com"><img src="https://avatars.githubusercontent.com/u/1634213?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Oscar Franco</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ospfranco" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="adamtrager.com"><img src="https://avatars.githubusercontent.com/u/1719791?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adam Trager</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Nfinished" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://saheen.codes"><img src="https://avatars.githubusercontent.com/u/2632896?v=4?s=100" width="100px;" alt=""/><br /><sub><b>saheenshoukath</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=shellord" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://jahneer.me"><img src="https://avatars.githubusercontent.com/u/54552763?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Husnul Jahneer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=husnuljahneer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/ReykCS"><img src="https://avatars.githubusercontent.com/u/40463716?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Reyk</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ReykCS" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Lokprakash-babu"><img src="https://avatars.githubusercontent.com/u/60031382?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lokprakash Babu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Lokprakash-babu" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://mizle.net"><img src="https://avatars.githubusercontent.com/u/3516343?v=4?s=100" width="100px;" alt=""/><br /><sub><b>eai04191</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=eai04191" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://numanaral.github.io/?ref=github"><img src="https://avatars.githubusercontent.com/u/25233323?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Numan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=numanaral" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/jscyo"><img src="https://avatars.githubusercontent.com/u/6310783?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joel Coutinho</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jscyo" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/davidbarker"><img src="https://avatars.githubusercontent.com/u/1597139?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Barker</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davidbarker" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.timfeeley.com/"><img src="https://avatars.githubusercontent.com/u/3246342?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tim Feeley</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=timfee" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Caslus"><img src="https://avatars.githubusercontent.com/u/22855640?v=4?s=100" width="100px;" alt=""/><br /><sub><b>lucas philippe</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Caslus" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/the-bayer"><img src="https://avatars.githubusercontent.com/u/94391693?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Blake Bayer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=the-bayer" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=the-bayer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/rmassie"><img src="https://avatars.githubusercontent.com/u/7375518?v=4?s=100" width="100px;" alt=""/><br /><sub><b>R Massie</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rmassie" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/paulm17"><img src="https://avatars.githubusercontent.com/u/387463?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=paulm17" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://minho42.com"><img src="https://avatars.githubusercontent.com/u/15278512?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Min ho Kim</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=minho42" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/webdeb"><img src="https://avatars.githubusercontent.com/u/14992140?v=4?s=100" width="100px;" alt=""/><br /><sub><b>webdeb</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=webdeb" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/iDavidB"><img src="https://avatars.githubusercontent.com/u/32268383?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=iDavidB" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=iDavidB" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=iDavidB" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://jdlt.co.uk"><img src="https://avatars.githubusercontent.com/u/5058625?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jake Dowie</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jakedee" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/datner"><img src="https://avatars.githubusercontent.com/u/22598347?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Datner</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=datner" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=datner" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=datner" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/remlse"><img src="https://avatars.githubusercontent.com/u/54984957?v=4?s=100" width="100px;" alt=""/><br /><sub><b>remlse</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=remlse" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/sergous"><img src="https://avatars.githubusercontent.com/u/545151?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sergei Smirnov</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sergous" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/trensik"><img src="https://avatars.githubusercontent.com/u/18584155?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dawid Urbaniak</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Trancever" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Trancever" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="kiri.dev"><img src="https://avatars.githubusercontent.com/u/29735836?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kacper Potyrała</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=SerekKiri" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="jcde.xyz"><img src="https://avatars.githubusercontent.com/u/31413538?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeeho Ahn</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=iojcde" title="Documentation">📖</a> <a href="#tool-iojcde" title="Tools">🔧</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -6,5 +6,5 @@ TODO
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Email Brandon Bayer at b@bayer.ws to report a vulnerablity, and he will follow up with you asap.
|
||||
Email Brandon Bayer at b@bayer.ws to report a vulnerability, and he will follow up with you asap.
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 20 KiB |
1
assets/boostry.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 143.5 42.09"><defs><style>.cls-1{fill:none;}.cls-2{fill:#d71526;}</style></defs><title>アセット 15</title><g id="レイヤー_2" data-name="レイヤー 2"><g id="レイヤー_1-2" data-name="レイヤー 1"><path d="M21.87,20A13.2,13.2,0,0,1,34.92,6.83c6.44,0,10.88,4.74,10.88,11a13.21,13.21,0,0,1-13,13.21C26.31,31.05,21.87,26.32,21.87,20Zm20.22-2.1c0-4.34-2.9-7.71-7.27-7.71-5.17,0-9.25,4.51-9.25,9.71,0,4.34,2.91,7.71,7.28,7.71A9.52,9.52,0,0,0,42.09,17.94Z"/><path d="M47.67,20a13.2,13.2,0,0,1,13-13.21c6.44,0,10.88,4.74,10.88,11a13.21,13.21,0,0,1-13,13.21C52.11,31.05,47.67,26.32,47.67,20Zm20.22-2.1c0-4.34-2.9-7.71-7.27-7.71-5.17,0-9.25,4.51-9.25,9.71,0,4.34,2.91,7.71,7.28,7.71C63.85,27.65,67.89,23.14,67.89,17.94Z"/><path d="M72.84,24.81a9.7,9.7,0,0,0,6.41,3c2.4,0,4.07-1.4,4.07-3.57,0-1.57-.94-2.64-3.3-3.87l-1.37-.71a6.56,6.56,0,0,1-4.07-6.14c0-3.9,3.2-6.7,7.47-6.7A12.23,12.23,0,0,1,88.57,8.9l-.68,3.51-.23-.18A10.16,10.16,0,0,0,82,10c-2.2,0-3.84,1.4-3.84,3.3,0,1.17.57,2.37,2.51,3.34l1.33.67C85.46,19.07,87,21,87,24c0,4.3-3.11,7.1-7.61,7.1a11.56,11.56,0,0,1-7.45-2.8l.71-3.65Z"/><path d="M106.27,10.63h-5.85l-3.91,20H92.94l3.91-20H91l.66-3.37h15.32Z"/><path d="M115,21.54l5.27,9.08h-4.14l-5.3-9.74-1.91,9.74h-3.57L109.9,7.26h4.77c4.67,0,7.68,2.54,7.68,6.47S119.44,20.74,115,21.54Zm-3.84-2.37h1.33c3.51,0,6.18-2.17,6.18-5.07,0-2.3-1.7-3.7-4.44-3.7h-1.37Z"/><line class="cls-1" x1="72.32" y1="24.47" x2="72.69" y2="24.81"/><path d="M15.4,16.76l-.76-.31.78-.27C19,15,21.06,12.35,21.06,9.23c0-3.92-3.19-6.65-7.75-6.65H6L.5,30.62H9c5.94,0,10.42-3.48,10.42-8.08A6,6,0,0,0,15.4,16.76ZM8.93,5.68H12.3c2.94,0,4.77,1.55,4.77,4,0,3-2.58,5.18-6,5.18H7.13ZM9.1,27.52H4.75L6.59,18h3.82c3.05,0,5,1.7,5,4.32C15.43,25.34,12.76,27.52,9.1,27.52Z"/><polygon class="cls-2" points="134.09 25.12 132.58 21.09 132.54 20.97 132.49 20.86 127.39 7.26 123.39 7.26 130.13 25.3 121.55 42.09 125.56 42.09 131.87 29.85 131.93 29.73 131.98 29.61 134.06 25.58 134.12 25.47 134.18 25.35 134.14 25.24 134.09 25.12"/><polygon points="139.5 7.26 132.65 20.76 132.65 20.76 132.54 20.98 132.58 21.09 134.09 25.12 134.14 25.24 134.18 25.35 143.5 7.26 139.5 7.26"/><rect class="cls-1" width="143" height="42"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -1,24 +0,0 @@
|
||||
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path d="M79.4831 1.95572C70.2813 -0.81923 55.2811 -0.617415 46.1549 2.4098L18.6125 11.5167C9.48627 14.5313 9.38542 19.7784 18.3856 23.1588L49.9743 35.028C58.9744 38.4084 73.6217 38.194 82.5084 34.5487L110.883 22.9192C119.782 19.2739 119.53 14.0267 110.316 11.2518L79.4831 1.95572Z" fill="url(#paint0_linear)"/>
|
||||
<path d="M84.235 38.6101C75.3357 42.2554 68.0625 53.1029 68.0625 62.727V113.635C68.0625 123.259 74.9071 127.245 83.2644 122.489L109.282 107.706C117.639 102.951 124.912 91.208 125.442 81.6092L127.837 37.8281C128.366 28.2167 121.509 23.3479 112.609 26.9932L84.235 38.6101Z" fill="url(#paint1_linear)"/>
|
||||
<path d="M0.0071345 37.8409C-0.257575 28.2295 6.877 23.1211 15.8771 26.5015L47.4658 38.3707C56.466 41.7511 63.8274 52.3842 63.8274 62.0082V112.916C63.8274 122.54 56.882 126.715 48.386 122.212L17.0998 105.6C8.60392 101.085 1.44415 89.5306 1.16683 79.9192L0.0071345 37.8409Z" fill="url(#paint2_linear)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="63.9326" y1="0" x2="63.9326" y2="124.497" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#036EB8"/>
|
||||
<stop offset="1" stop-color="#469196"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="63.9326" y1="0" x2="63.9326" y2="124.497" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#036EB8"/>
|
||||
<stop offset="1" stop-color="#469196"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear" x1="63.9326" y1="0" x2="63.9326" y2="124.497" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#036EB8"/>
|
||||
<stop offset="1" stop-color="#469196"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0">
|
||||
<rect width="128" height="128" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 78 KiB |
BIN
assets/jdlt.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
assets/meetkai.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 1.8 MiB |
|
Before Width: | Height: | Size: 30 KiB |
@@ -25,7 +25,7 @@ export const LoginForm = (props: LoginFormProps) => {
|
||||
try {
|
||||
await loginMutation(values)
|
||||
props.onSuccess?.()
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
if (error instanceof AuthenticationError) {
|
||||
return {[FORM_ERROR]: "Sorry, those credentials are invalid"}
|
||||
} else {
|
||||
|
||||
@@ -24,7 +24,7 @@ export const SignupForm = (props: SignupFormProps) => {
|
||||
try {
|
||||
await signupMutation(values)
|
||||
props.onSuccess?.()
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
if (error.code === "P2002" && error.meta?.target?.includes("email")) {
|
||||
// This error comes from Prisma
|
||||
return {email: "This email is already being used"}
|
||||
|
||||
@@ -8,8 +8,8 @@ beforeEach(async () => {
|
||||
})
|
||||
|
||||
const generatedToken = "plain-token"
|
||||
jest.mock("@blitzjs/core/server", () => ({
|
||||
...jest.requireActual<object>("@blitzjs/core/server")!,
|
||||
jest.mock("next/stdlib-server", () => ({
|
||||
...jest.requireActual<object>("next/stdlib-server")!,
|
||||
generateToken: () => generatedToken,
|
||||
}))
|
||||
jest.mock("preview-email", () => jest.fn())
|
||||
|
||||
@@ -30,7 +30,7 @@ const ResetPasswordPage: BlitzPage = () => {
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await resetPasswordMutation(values)
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
if (error.name === "ResetPasswordError") {
|
||||
return {
|
||||
[FORM_ERROR]: error.message,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {useSession, useRouter, useMutation, Head} from "blitz"
|
||||
import {useSession, useRouter, useMutation, Head, BlitzLayout} from "blitz"
|
||||
import logout from "app/auth/mutations/logout"
|
||||
|
||||
export default function Layout({title, children}: {title?: string; children: React.ReactNode}) {
|
||||
const Layout: BlitzLayout<{title?: string}> = ({title, children}) => {
|
||||
const session = useSession({suspense: false})
|
||||
const router = useRouter()
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
@@ -16,8 +16,8 @@ export default function Layout({title, children}: {title?: string; children: Rea
|
||||
{session.userId && (
|
||||
<button
|
||||
onClick={async () => {
|
||||
router.push("/")
|
||||
await logoutMutation()
|
||||
router.push("/")
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
@@ -28,3 +28,5 @@ export default function Layout({title, children}: {title?: string; children: Rea
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {render} from "test/utils"
|
||||
import Home from "./index"
|
||||
|
||||
jest.mock("@blitzjs/core", () => ({
|
||||
...jest.requireActual<object>("@blitzjs/core")!,
|
||||
jest.mock("next/data-client", () => ({
|
||||
...jest.requireActual<object>("next/data-client")!,
|
||||
useQuery: () => [
|
||||
{
|
||||
id: 1,
|
||||
@@ -24,4 +24,4 @@ test("renders blitz documentation link", () => {
|
||||
const element = getByText(/powered by blitz/i)
|
||||
// @ts-ignore
|
||||
expect(element).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,12 +6,14 @@ import {
|
||||
useRouterQuery,
|
||||
useMutation,
|
||||
invoke,
|
||||
Image,
|
||||
useQuery,
|
||||
BlitzPage,
|
||||
} from "blitz"
|
||||
import getUser from "app/users/queries/getUser"
|
||||
import trackView from "app/users/mutations/trackView"
|
||||
import Layout from "app/core/layouts/Layout"
|
||||
import logo from "public/logo.png"
|
||||
|
||||
import {Routes} from ".blitz"
|
||||
|
||||
@@ -88,7 +90,7 @@ const Home: BlitzPage = () => (
|
||||
|
||||
<main>
|
||||
<div className="logo">
|
||||
<img src="/logo.png" alt="blitz.js" />
|
||||
<Image src={logo} alt="blitz.js" width={400} height={200} />
|
||||
</div>
|
||||
|
||||
<Suspense fallback={"Loading..."}>
|
||||
|
||||
@@ -45,7 +45,7 @@ export const EditProject = () => {
|
||||
})
|
||||
await setQueryData(updated)
|
||||
router.push(`/projects/${updated.id}`)
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error(error)
|
||||
return {
|
||||
[FORM_ERROR]: error.toString(),
|
||||
|
||||
@@ -24,7 +24,7 @@ const NewProjectPage: BlitzPage = () => {
|
||||
try {
|
||||
const project = await createProjectMutation(values)
|
||||
router.push(Routes.ShowProjectPage({projectId: project.id}))
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
console.error(error)
|
||||
return {
|
||||
[FORM_ERROR]: error.toString(),
|
||||
|
||||
@@ -23,7 +23,7 @@ export const getServerSideProps: GetServerSideProps = async ({req, res}) => {
|
||||
{res, req},
|
||||
)
|
||||
return {props: {user}}
|
||||
} catch (error) {
|
||||
} catch (error: any) {
|
||||
if (error.name === "NotFoundError") {
|
||||
res.statusCode = 404
|
||||
res.end()
|
||||
|
||||
13
examples/auth/app/queries/users/currentUserQuery.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import {Ctx} from "blitz"
|
||||
import db from "db"
|
||||
|
||||
export default async function currentUserQuery(_ = null, {session}: Ctx) {
|
||||
if (!session.userId) return null
|
||||
|
||||
const user = await db.user.findFirst({
|
||||
where: {id: session.userId},
|
||||
select: {id: true, name: true, email: true, role: true},
|
||||
})
|
||||
|
||||
return user
|
||||
}
|
||||
@@ -16,6 +16,9 @@ module.exports = withBundleAnalyzer({
|
||||
cli: {
|
||||
clearConsoleOnBlitzDev: false,
|
||||
},
|
||||
codegen: {
|
||||
templateDir: "./my-templates",
|
||||
},
|
||||
log: {
|
||||
// level: "trace",
|
||||
},
|
||||
|
||||
@@ -23,6 +23,7 @@ describe("index page", () => {
|
||||
|
||||
cy.location("pathname").should("equal", "/")
|
||||
cy.contains("button", "Logout")
|
||||
cy.wait(1000)
|
||||
})
|
||||
|
||||
it("allows the user to log in", () => {
|
||||
@@ -42,6 +43,7 @@ describe("index page", () => {
|
||||
cy.location("pathname").should("equal", "/")
|
||||
cy.wait(1000)
|
||||
cy.contains("button", "Logout")
|
||||
cy.wait(1000)
|
||||
})
|
||||
|
||||
it("allows the user to logout", () => {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
* and then export it. That way you can import here and anywhere else
|
||||
* and use it straight away.
|
||||
*/
|
||||
import previewEmail from "preview-email"
|
||||
|
||||
type ResetPasswordMailer = {
|
||||
to: string
|
||||
@@ -38,6 +37,7 @@ export function forgotPasswordMailer({to, token}: ResetPasswordMailer) {
|
||||
throw new Error("No production email implementation in mailers/forgotPasswordMailer")
|
||||
} else {
|
||||
// Preview email in the browser
|
||||
const previewEmail = (await import("preview-email")).default
|
||||
await previewEmail(msg)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"dev": "blitz dev",
|
||||
"build": "blitz build",
|
||||
"start": "blitz start",
|
||||
"console": "blitz console",
|
||||
"studio": "blitz prisma studio",
|
||||
"lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .",
|
||||
"analyze": "cross-env ANALYZE=true blitz build",
|
||||
@@ -29,7 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.39.0-canary.0",
|
||||
"blitz": "0.45.4",
|
||||
"final-form": "4.20.1",
|
||||
"passport-auth0": "1.4.0",
|
||||
"passport-github2": "0.1.12",
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
"downlevelIteration": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"exclude": ["node_modules", "cypress"],
|
||||
"exclude": ["node_modules", "cypress", "test"],
|
||||
"include": ["**/*.ts", "**/*.tsx"]
|
||||
}
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
module.exports = {
|
||||
parser: "@typescript-eslint/parser",
|
||||
env: {
|
||||
es2020: true,
|
||||
},
|
||||
extends: ["react-app", "plugin:jsx-a11y/recommended"],
|
||||
plugins: ["@typescript-eslint", "jsx-a11y"],
|
||||
rules: {
|
||||
"import/no-anonymous-default-export": "error",
|
||||
"import/no-webpack-loader-syntax": "off",
|
||||
"react/react-in-jsx-scope": "off", // React is always in scope with Blitz
|
||||
"jsx-a11y/anchor-is-valid": "off", //Doesn't play well with Blitz/Next <Link> usage
|
||||
},
|
||||
extends: "blitz",
|
||||
}
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import {ReactNode} from "react"
|
||||
import {Head} from "blitz"
|
||||
import {Head, BlitzLayout} from "blitz"
|
||||
|
||||
type LayoutProps = {
|
||||
title?: string
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const Layout = ({title, children}: LayoutProps) => {
|
||||
const Layout: BlitzLayout<{title?: string}> = ({title, children}) => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import {Link, BlitzPage, useMutation} from "blitz"
|
||||
import {Link, BlitzPage, useMutation, Image} from "blitz"
|
||||
import Layout from "app/layouts/Layout"
|
||||
import logout from "app/auth/mutations/logout"
|
||||
import {useCurrentUser} from "app/hooks/useCurrentUser"
|
||||
import {Suspense} from "react"
|
||||
import logo from "public/logo.png"
|
||||
|
||||
/*
|
||||
* This file is just for a pleasant getting started page for your new app.
|
||||
@@ -54,7 +55,7 @@ const Home: BlitzPage = () => {
|
||||
<div className="container">
|
||||
<main>
|
||||
<div className="logo">
|
||||
<img src="/logo.png" alt="blitz.js" />
|
||||
<Image src={logo} alt="blitz.js" />
|
||||
</div>
|
||||
<p>
|
||||
<strong>Congrats!</strong> Your app is ready, including user sign-up and log-in.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// These reference imports provide type definitions for things like styled-jsx and css modules
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/types/global" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
@@ -4,8 +4,7 @@
|
||||
* This seed function is executed when you run `blitz db seed`.
|
||||
*
|
||||
* Probably you want to use a library like https://chancejs.com
|
||||
* or https://github.com/Marak/Faker.js to easily generate
|
||||
* realistic data.
|
||||
* to easily generate realistic data.
|
||||
*/
|
||||
const seed = async () => {
|
||||
// for (let i = 0; i < 5; i++) {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.39.0-canary.0",
|
||||
"blitz": "0.45.4",
|
||||
"final-form": "4.20.1",
|
||||
"prisma": "2.24.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import blitz from "blitz/custom-server"
|
||||
import {createServer} from "http"
|
||||
import {parse} from "url"
|
||||
import {log} from "@blitzjs/display"
|
||||
import {log} from "next/dist/server/lib/logging"
|
||||
|
||||
const {PORT = "3000"} = process.env
|
||||
const dev = process.env.NODE_ENV !== "production"
|
||||
|
||||
@@ -19,5 +19,5 @@
|
||||
"tsBuildInfoFile": ".tsbuildinfo"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
"include": ["blitz-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
||||
|
||||
11
examples/cypress/.editorconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
# https://EditorConfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
3
examples/cypress/.env
Normal file
@@ -0,0 +1,3 @@
|
||||
# This env file should be checked into source control
|
||||
# This is the place for default values for all environments
|
||||
# Values in `.env.local` and `.env.production` will override these values
|
||||
3
examples/cypress/.eslintrc.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
extends: ["blitz"],
|
||||
}
|
||||
56
examples/cypress/.gitignore
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
# dependencies
|
||||
node_modules
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
.pnp.*
|
||||
.npm
|
||||
web_modules/
|
||||
|
||||
# blitz
|
||||
/.blitz/
|
||||
/.next/
|
||||
*.sqlite
|
||||
*.sqlite-journal
|
||||
.now
|
||||
.blitz**
|
||||
blitz-log.log
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
.envrc
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Testing
|
||||
.coverage
|
||||
*.lcov
|
||||
.nyc_output
|
||||
lib-cov
|
||||
|
||||
# Caches
|
||||
*.tsbuildinfo
|
||||
.eslintcache
|
||||
.node_repl_history
|
||||
.yarn-integrity
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
7
examples/cypress/.npmrc
Normal file
@@ -0,0 +1,7 @@
|
||||
save-exact=true
|
||||
legacy-peer-deps=true
|
||||
|
||||
public-hoist-pattern[]=next
|
||||
public-hoist-pattern[]=secure-password
|
||||
public-hoist-pattern[]=*jest*
|
||||
public-hoist-pattern[]=@testing-library/*
|
||||
9
examples/cypress/.prettierignore
Normal file
@@ -0,0 +1,9 @@
|
||||
.gitkeep
|
||||
.env*
|
||||
*.ico
|
||||
*.lock
|
||||
db/migrations
|
||||
.next
|
||||
.blitz
|
||||
.yarn
|
||||
.pnp*
|
||||
25
examples/cypress/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# **cypress**
|
||||
|
||||
This is an example [Cypress](https://www.cypress.io/) integration.
|
||||
|
||||
## Getting Started
|
||||
|
||||
Migrate the database:
|
||||
|
||||
```
|
||||
blitz prisma migrate dev
|
||||
```
|
||||
|
||||
Run e2e tests:
|
||||
|
||||
```
|
||||
yarn test:e2e
|
||||
```
|
||||
|
||||
Open Cypress dashboard:
|
||||
|
||||
```
|
||||
yarn cypress:open
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
49
examples/cypress/app/auth/components/LoginForm.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { AuthenticationError, Link, useMutation } from "blitz"
|
||||
import { LabeledTextField } from "app/core/components/LabeledTextField"
|
||||
import { Form, FORM_ERROR } from "app/core/components/Form"
|
||||
import login from "app/auth/mutations/login"
|
||||
import { Login } from "app/auth/validations"
|
||||
|
||||
type LoginFormProps = {
|
||||
onSuccess?: () => void
|
||||
}
|
||||
|
||||
export const LoginForm = (props: LoginFormProps) => {
|
||||
const [loginMutation] = useMutation(login)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Login</h1>
|
||||
|
||||
<Form
|
||||
submitText="Login"
|
||||
schema={Login}
|
||||
initialValues={{ email: "", password: "" }}
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await loginMutation(values)
|
||||
props.onSuccess?.()
|
||||
} catch (error: any) {
|
||||
if (error instanceof AuthenticationError) {
|
||||
return { [FORM_ERROR]: "Sorry, those credentials are invalid" }
|
||||
} else {
|
||||
return {
|
||||
[FORM_ERROR]:
|
||||
"Sorry, we had an unexpected error. Please try again. - " + error.toString(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LabeledTextField name="email" label="Email" placeholder="Email" />
|
||||
<LabeledTextField name="password" label="Password" placeholder="Password" type="password" />
|
||||
</Form>
|
||||
|
||||
<div style={{ marginTop: "1rem" }}>
|
||||
Or <Link href="signup">Sign Up</Link>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginForm
|
||||
43
examples/cypress/app/auth/components/SignupForm.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { useMutation } from "blitz"
|
||||
import { LabeledTextField } from "app/core/components/LabeledTextField"
|
||||
import { Form, FORM_ERROR } from "app/core/components/Form"
|
||||
import signup from "app/auth/mutations/signup"
|
||||
import { Signup } from "app/auth/validations"
|
||||
|
||||
type SignupFormProps = {
|
||||
onSuccess?: () => void
|
||||
}
|
||||
|
||||
export const SignupForm = (props: SignupFormProps) => {
|
||||
const [signupMutation] = useMutation(signup)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Create an Account</h1>
|
||||
|
||||
<Form
|
||||
submitText="Create Account"
|
||||
schema={Signup}
|
||||
initialValues={{ email: "", password: "" }}
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await signupMutation(values)
|
||||
props.onSuccess?.()
|
||||
} catch (error: any) {
|
||||
if (error.code === "P2002" && error.meta?.target?.includes("email")) {
|
||||
// This error comes from Prisma
|
||||
return { email: "This email is already being used" }
|
||||
} else {
|
||||
return { [FORM_ERROR]: error.toString() }
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LabeledTextField name="email" label="Email" placeholder="Email" />
|
||||
<LabeledTextField name="password" label="Password" placeholder="Password" type="password" />
|
||||
</Form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignupForm
|
||||
23
examples/cypress/app/auth/mutations/changePassword.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { NotFoundError, SecurePassword, resolver } from "blitz"
|
||||
import db from "db"
|
||||
import { authenticateUser } from "./login"
|
||||
import { ChangePassword } from "../validations"
|
||||
|
||||
export default resolver.pipe(
|
||||
resolver.zod(ChangePassword),
|
||||
resolver.authorize(),
|
||||
async ({ currentPassword, newPassword }, ctx) => {
|
||||
const user = await db.user.findFirst({ where: { id: ctx.session.userId! } })
|
||||
if (!user) throw new NotFoundError()
|
||||
|
||||
await authenticateUser(user.email, currentPassword)
|
||||
|
||||
const hashedPassword = await SecurePassword.hash(newPassword.trim())
|
||||
await db.user.update({
|
||||
where: { id: user.id },
|
||||
data: { hashedPassword },
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
)
|
||||
56
examples/cypress/app/auth/mutations/forgotPassword.test.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { hash256, Ctx } from "blitz"
|
||||
import forgotPassword from "./forgotPassword"
|
||||
import db from "db"
|
||||
import previewEmail from "preview-email"
|
||||
|
||||
beforeEach(async () => {
|
||||
await db.$reset()
|
||||
})
|
||||
|
||||
const generatedToken = "plain-token"
|
||||
jest.mock("next/stdlib-server", () => ({
|
||||
...jest.requireActual<object>("next/stdlib-server")!,
|
||||
generateToken: () => generatedToken,
|
||||
}))
|
||||
jest.mock("preview-email", () => jest.fn())
|
||||
|
||||
describe("forgotPassword mutation", () => {
|
||||
it("does not throw error if user doesn't exist", async () => {
|
||||
await expect(forgotPassword({ email: "no-user@email.com" }, {} as Ctx)).resolves.not.toThrow()
|
||||
})
|
||||
|
||||
it("works correctly", async () => {
|
||||
// Create test user
|
||||
const user = await db.user.create({
|
||||
data: {
|
||||
email: "user@example.com",
|
||||
tokens: {
|
||||
// Create old token to ensure it's deleted
|
||||
create: {
|
||||
type: "RESET_PASSWORD",
|
||||
hashedToken: "token",
|
||||
expiresAt: new Date(),
|
||||
sentTo: "user@example.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
include: { tokens: true },
|
||||
})
|
||||
|
||||
// Invoke the mutation
|
||||
await forgotPassword({ email: user.email }, {} as Ctx)
|
||||
|
||||
const tokens = await db.token.findMany({ where: { userId: user.id } })
|
||||
const token = tokens[0]
|
||||
|
||||
// delete's existing tokens
|
||||
expect(tokens.length).toBe(1)
|
||||
|
||||
expect(token.id).not.toBe(user.tokens[0].id)
|
||||
expect(token.type).toBe("RESET_PASSWORD")
|
||||
expect(token.sentTo).toBe(user.email)
|
||||
expect(token.hashedToken).toBe(hash256(generatedToken))
|
||||
expect(token.expiresAt > new Date()).toBe(true)
|
||||
expect(previewEmail).toBeCalled()
|
||||
})
|
||||
})
|
||||
41
examples/cypress/app/auth/mutations/forgotPassword.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { resolver, generateToken, hash256 } from "blitz"
|
||||
import db from "db"
|
||||
import { forgotPasswordMailer } from "mailers/forgotPasswordMailer"
|
||||
import { ForgotPassword } from "../validations"
|
||||
|
||||
const RESET_PASSWORD_TOKEN_EXPIRATION_IN_HOURS = 4
|
||||
|
||||
export default resolver.pipe(resolver.zod(ForgotPassword), async ({ email }) => {
|
||||
// 1. Get the user
|
||||
const user = await db.user.findFirst({ where: { email: email.toLowerCase() } })
|
||||
|
||||
// 2. Generate the token and expiration date.
|
||||
const token = generateToken()
|
||||
const hashedToken = hash256(token)
|
||||
const expiresAt = new Date()
|
||||
expiresAt.setHours(expiresAt.getHours() + RESET_PASSWORD_TOKEN_EXPIRATION_IN_HOURS)
|
||||
|
||||
// 3. If user with this email was found
|
||||
if (user) {
|
||||
// 4. Delete any existing password reset tokens
|
||||
await db.token.deleteMany({ where: { type: "RESET_PASSWORD", userId: user.id } })
|
||||
// 5. Save this new token in the database.
|
||||
await db.token.create({
|
||||
data: {
|
||||
user: { connect: { id: user.id } },
|
||||
type: "RESET_PASSWORD",
|
||||
expiresAt,
|
||||
hashedToken,
|
||||
sentTo: user.email,
|
||||
},
|
||||
})
|
||||
// 6. Send the email
|
||||
await forgotPasswordMailer({ to: user.email, token }).send()
|
||||
} else {
|
||||
// 7. If no user found wait the same time so attackers can't tell the difference
|
||||
await new Promise((resolve) => setTimeout(resolve, 750))
|
||||
}
|
||||
|
||||
// 8. Return the same result whether a password reset email was sent or not
|
||||
return
|
||||
})
|
||||
31
examples/cypress/app/auth/mutations/login.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { resolver, SecurePassword, AuthenticationError } from "blitz"
|
||||
import db from "db"
|
||||
import { Login } from "../validations"
|
||||
import { Role } from "types"
|
||||
|
||||
export const authenticateUser = async (rawEmail: string, rawPassword: string) => {
|
||||
const email = rawEmail.toLowerCase().trim()
|
||||
const password = rawPassword.trim()
|
||||
const user = await db.user.findFirst({ where: { email } })
|
||||
if (!user) throw new AuthenticationError()
|
||||
|
||||
const result = await SecurePassword.verify(user.hashedPassword, password)
|
||||
|
||||
if (result === SecurePassword.VALID_NEEDS_REHASH) {
|
||||
// Upgrade hashed password with a more secure hash
|
||||
const improvedHash = await SecurePassword.hash(password)
|
||||
await db.user.update({ where: { id: user.id }, data: { hashedPassword: improvedHash } })
|
||||
}
|
||||
|
||||
const { hashedPassword, ...rest } = user
|
||||
return rest
|
||||
}
|
||||
|
||||
export default resolver.pipe(resolver.zod(Login), async ({ email, password }, ctx) => {
|
||||
// This throws an error if credentials are invalid
|
||||
const user = await authenticateUser(email, password)
|
||||
|
||||
await ctx.session.$create({ userId: user.id, role: user.role as Role })
|
||||
|
||||
return user
|
||||
})
|
||||
5
examples/cypress/app/auth/mutations/logout.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Ctx } from "blitz"
|
||||
|
||||
export default async function logout(_: any, ctx: Ctx) {
|
||||
return await ctx.session.$revoke()
|
||||
}
|
||||
82
examples/cypress/app/auth/mutations/resetPassword.test.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import resetPassword from "./resetPassword"
|
||||
import db from "db"
|
||||
import { hash256, SecurePassword } from "blitz"
|
||||
|
||||
beforeEach(async () => {
|
||||
await db.$reset()
|
||||
})
|
||||
|
||||
const mockCtx: any = {
|
||||
session: {
|
||||
$create: jest.fn,
|
||||
},
|
||||
}
|
||||
|
||||
describe("resetPassword mutation", () => {
|
||||
it("works correctly", async () => {
|
||||
expect(true).toBe(true)
|
||||
|
||||
// Create test user
|
||||
const goodToken = "randomPasswordResetToken"
|
||||
const expiredToken = "expiredRandomPasswordResetToken"
|
||||
const future = new Date()
|
||||
future.setHours(future.getHours() + 4)
|
||||
const past = new Date()
|
||||
past.setHours(past.getHours() - 4)
|
||||
|
||||
const user = await db.user.create({
|
||||
data: {
|
||||
email: "user@example.com",
|
||||
tokens: {
|
||||
// Create old token to ensure it's deleted
|
||||
create: [
|
||||
{
|
||||
type: "RESET_PASSWORD",
|
||||
hashedToken: hash256(expiredToken),
|
||||
expiresAt: past,
|
||||
sentTo: "user@example.com",
|
||||
},
|
||||
{
|
||||
type: "RESET_PASSWORD",
|
||||
hashedToken: hash256(goodToken),
|
||||
expiresAt: future,
|
||||
sentTo: "user@example.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
include: { tokens: true },
|
||||
})
|
||||
|
||||
const newPassword = "newPassword"
|
||||
|
||||
// Non-existent token
|
||||
await expect(
|
||||
resetPassword({ token: "no-token", password: "", passwordConfirmation: "" }, mockCtx)
|
||||
).rejects.toThrowError()
|
||||
|
||||
// Expired token
|
||||
await expect(
|
||||
resetPassword(
|
||||
{ token: expiredToken, password: newPassword, passwordConfirmation: newPassword },
|
||||
mockCtx
|
||||
)
|
||||
).rejects.toThrowError()
|
||||
|
||||
// Good token
|
||||
await resetPassword(
|
||||
{ token: goodToken, password: newPassword, passwordConfirmation: newPassword },
|
||||
mockCtx
|
||||
)
|
||||
|
||||
// Delete's the token
|
||||
const numberOfTokens = await db.token.count({ where: { userId: user.id } })
|
||||
expect(numberOfTokens).toBe(0)
|
||||
|
||||
// Updates user's password
|
||||
const updatedUser = await db.user.findFirst({ where: { id: user.id } })
|
||||
expect(await SecurePassword.verify(updatedUser!.hashedPassword, newPassword)).toBe(
|
||||
SecurePassword.VALID
|
||||
)
|
||||
})
|
||||
})
|
||||
47
examples/cypress/app/auth/mutations/resetPassword.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { resolver, SecurePassword, hash256 } from "blitz"
|
||||
import db from "db"
|
||||
import { ResetPassword } from "../validations"
|
||||
import login from "./login"
|
||||
|
||||
export class ResetPasswordError extends Error {
|
||||
name = "ResetPasswordError"
|
||||
message = "Reset password link is invalid or it has expired."
|
||||
}
|
||||
|
||||
export default resolver.pipe(resolver.zod(ResetPassword), async ({ password, token }, ctx) => {
|
||||
// 1. Try to find this token in the database
|
||||
const hashedToken = hash256(token)
|
||||
const possibleToken = await db.token.findFirst({
|
||||
where: { hashedToken, type: "RESET_PASSWORD" },
|
||||
include: { user: true },
|
||||
})
|
||||
|
||||
// 2. If token not found, error
|
||||
if (!possibleToken) {
|
||||
throw new ResetPasswordError()
|
||||
}
|
||||
const savedToken = possibleToken
|
||||
|
||||
// 3. Delete token so it can't be used again
|
||||
await db.token.delete({ where: { id: savedToken.id } })
|
||||
|
||||
// 4. If token has expired, error
|
||||
if (savedToken.expiresAt < new Date()) {
|
||||
throw new ResetPasswordError()
|
||||
}
|
||||
|
||||
// 5. Since token is valid, now we can update the user's password
|
||||
const hashedPassword = await SecurePassword.hash(password.trim())
|
||||
const user = await db.user.update({
|
||||
where: { id: savedToken.userId },
|
||||
data: { hashedPassword },
|
||||
})
|
||||
|
||||
// 6. Revoke all existing login sessions for this user
|
||||
await db.session.deleteMany({ where: { userId: user.id } })
|
||||
|
||||
// 7. Now log the user in with the new credentials
|
||||
await login({ email: user.email, password }, ctx)
|
||||
|
||||
return true
|
||||
})
|
||||
15
examples/cypress/app/auth/mutations/signup.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { resolver, SecurePassword } from "blitz"
|
||||
import db from "db"
|
||||
import { Signup } from "app/auth/validations"
|
||||
import { Role } from "types"
|
||||
|
||||
export default resolver.pipe(resolver.zod(Signup), async ({ email, password }, ctx) => {
|
||||
const hashedPassword = await SecurePassword.hash(password.trim())
|
||||
const user = await db.user.create({
|
||||
data: { email: email.toLowerCase().trim(), hashedPassword, role: "USER" },
|
||||
select: { id: true, name: true, email: true, role: true },
|
||||
})
|
||||
|
||||
await ctx.session.$create({ userId: user.id, role: user.role as Role })
|
||||
return user
|
||||
})
|
||||
48
examples/cypress/app/auth/pages/forgot-password.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { BlitzPage, useMutation } from "blitz"
|
||||
import Layout from "app/core/layouts/Layout"
|
||||
import { LabeledTextField } from "app/core/components/LabeledTextField"
|
||||
import { Form, FORM_ERROR } from "app/core/components/Form"
|
||||
import { ForgotPassword } from "app/auth/validations"
|
||||
import forgotPassword from "app/auth/mutations/forgotPassword"
|
||||
|
||||
const ForgotPasswordPage: BlitzPage = () => {
|
||||
const [forgotPasswordMutation, { isSuccess }] = useMutation(forgotPassword)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Forgot your password?</h1>
|
||||
|
||||
{isSuccess ? (
|
||||
<div>
|
||||
<h2>Request Submitted</h2>
|
||||
<p>
|
||||
If your email is in our system, you will receive instructions to reset your password
|
||||
shortly.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<Form
|
||||
submitText="Send Reset Password Instructions"
|
||||
schema={ForgotPassword}
|
||||
initialValues={{ email: "" }}
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await forgotPasswordMutation(values)
|
||||
} catch (error: any) {
|
||||
return {
|
||||
[FORM_ERROR]: "Sorry, we had an unexpected error. Please try again.",
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LabeledTextField name="email" label="Email" placeholder="Email" />
|
||||
</Form>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ForgotPasswordPage.redirectAuthenticatedTo = "/"
|
||||
ForgotPasswordPage.getLayout = (page) => <Layout title="Forgot Your Password?">{page}</Layout>
|
||||
|
||||
export default ForgotPasswordPage
|
||||
23
examples/cypress/app/auth/pages/login.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { useRouter, BlitzPage } from "blitz"
|
||||
import Layout from "app/core/layouts/Layout"
|
||||
import { LoginForm } from "app/auth/components/LoginForm"
|
||||
|
||||
const LoginPage: BlitzPage = () => {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<LoginForm
|
||||
onSuccess={() => {
|
||||
const next = router.query.next ? decodeURIComponent(router.query.next as string) : "/"
|
||||
router.push(next)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
LoginPage.redirectAuthenticatedTo = "/"
|
||||
LoginPage.getLayout = (page) => <Layout title="Log In">{page}</Layout>
|
||||
|
||||
export default LoginPage
|
||||
61
examples/cypress/app/auth/pages/reset-password.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { BlitzPage, useRouterQuery, Link, useMutation } from "blitz"
|
||||
import Layout from "app/core/layouts/Layout"
|
||||
import { LabeledTextField } from "app/core/components/LabeledTextField"
|
||||
import { Form, FORM_ERROR } from "app/core/components/Form"
|
||||
import { ResetPassword } from "app/auth/validations"
|
||||
import resetPassword from "app/auth/mutations/resetPassword"
|
||||
|
||||
import { Routes } from ".blitz"
|
||||
|
||||
const ResetPasswordPage: BlitzPage = () => {
|
||||
const query = useRouterQuery()
|
||||
const [resetPasswordMutation, { isSuccess }] = useMutation(resetPassword)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Set a New Password</h1>
|
||||
|
||||
{isSuccess ? (
|
||||
<div>
|
||||
<h2>Password Reset Successfully</h2>
|
||||
<p>
|
||||
Go to the <Link href={Routes.Home()}>homepage</Link>
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<Form
|
||||
submitText="Reset Password"
|
||||
schema={ResetPassword}
|
||||
initialValues={{ password: "", passwordConfirmation: "", token: query.token as string }}
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await resetPasswordMutation(values)
|
||||
} catch (error: any) {
|
||||
if (error.name === "ResetPasswordError") {
|
||||
return {
|
||||
[FORM_ERROR]: error.message,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
[FORM_ERROR]: "Sorry, we had an unexpected error. Please try again.",
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<LabeledTextField name="password" label="New Password" type="password" />
|
||||
<LabeledTextField
|
||||
name="passwordConfirmation"
|
||||
label="Confirm New Password"
|
||||
type="password"
|
||||
/>
|
||||
</Form>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ResetPasswordPage.redirectAuthenticatedTo = "/"
|
||||
ResetPasswordPage.getLayout = (page) => <Layout title="Reset Your Password">{page}</Layout>
|
||||
|
||||
export default ResetPasswordPage
|
||||
20
examples/cypress/app/auth/pages/signup.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { useRouter, BlitzPage } from "blitz"
|
||||
import Layout from "app/core/layouts/Layout"
|
||||
import { SignupForm } from "app/auth/components/SignupForm"
|
||||
|
||||
import { Routes } from ".blitz"
|
||||
|
||||
const SignupPage: BlitzPage = () => {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<SignupForm onSuccess={() => router.push(Routes.Home())} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
SignupPage.redirectAuthenticatedTo = "/"
|
||||
SignupPage.getLayout = (page) => <Layout title="Sign Up">{page}</Layout>
|
||||
|
||||
export default SignupPage
|
||||
33
examples/cypress/app/auth/validations.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { z } from "zod"
|
||||
|
||||
const password = z.string().min(10).max(100)
|
||||
|
||||
export const Signup = z.object({
|
||||
email: z.string().email(),
|
||||
password,
|
||||
})
|
||||
|
||||
export const Login = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string(),
|
||||
})
|
||||
|
||||
export const ForgotPassword = z.object({
|
||||
email: z.string().email(),
|
||||
})
|
||||
|
||||
export const ResetPassword = z
|
||||
.object({
|
||||
password: password,
|
||||
passwordConfirmation: password,
|
||||
token: z.string(),
|
||||
})
|
||||
.refine((data) => data.password === data.passwordConfirmation, {
|
||||
message: "Passwords don't match",
|
||||
path: ["passwordConfirmation"], // set the path of the error
|
||||
})
|
||||
|
||||
export const ChangePassword = z.object({
|
||||
currentPassword: z.string(),
|
||||
newPassword: password,
|
||||
})
|
||||
53
examples/cypress/app/core/components/Form.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import { ReactNode, PropsWithoutRef } from "react"
|
||||
import { Form as FinalForm, FormProps as FinalFormProps } from "react-final-form"
|
||||
import { z } from "zod"
|
||||
import { validateZodSchema } from "blitz"
|
||||
export { FORM_ERROR } from "final-form"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
/** All your form fields */
|
||||
children?: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
submitText?: string
|
||||
schema?: S
|
||||
onSubmit: FinalFormProps<z.infer<S>>["onSubmit"]
|
||||
initialValues?: FinalFormProps<z.infer<S>>["initialValues"]
|
||||
}
|
||||
|
||||
export function Form<S extends z.ZodType<any, any>>({
|
||||
children,
|
||||
submitText,
|
||||
schema,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
...props
|
||||
}: FormProps<S>) {
|
||||
return (
|
||||
<FinalForm
|
||||
initialValues={initialValues}
|
||||
validate={validateZodSchema(schema)}
|
||||
onSubmit={onSubmit}
|
||||
render={({ handleSubmit, submitting, submitError }) => (
|
||||
<form onSubmit={handleSubmit} className="form" {...props}>
|
||||
{/* Form fields supplied as children are rendered here */}
|
||||
{children}
|
||||
|
||||
{submitError && (
|
||||
<div role="alert" style={{ color: "red" }}>
|
||||
{submitError}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{submitText && (
|
||||
<button type="submit" disabled={submitting}>
|
||||
{submitText}
|
||||
</button>
|
||||
)}
|
||||
</form>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Form
|
||||
49
examples/cypress/app/core/components/LabeledTextField.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { forwardRef, ComponentPropsWithoutRef, PropsWithoutRef } from "react"
|
||||
import { useField, UseFieldConfig } from "react-final-form"
|
||||
|
||||
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
type?: "text" | "password" | "email" | "number"
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
fieldProps?: UseFieldConfig<string>
|
||||
}
|
||||
|
||||
export const LabeledTextField = forwardRef<HTMLInputElement, LabeledTextFieldProps>(
|
||||
({ name, label, outerProps, fieldProps, labelProps, ...props }, ref) => {
|
||||
const {
|
||||
input,
|
||||
meta: { touched, error, submitError, submitting },
|
||||
} = useField(name, {
|
||||
parse:
|
||||
props.type === "number"
|
||||
? (Number as any)
|
||||
: // Converting `""` to `null` ensures empty values will be set to null in the DB
|
||||
(v) => (v === "" ? null : v),
|
||||
...fieldProps,
|
||||
})
|
||||
|
||||
const normalizedError = Array.isArray(error) ? error.join(", ") : error || submitError
|
||||
|
||||
return (
|
||||
<div {...outerProps}>
|
||||
<label {...labelProps}>
|
||||
{label}
|
||||
<input {...input} disabled={submitting} {...props} ref={ref} />
|
||||
</label>
|
||||
|
||||
{touched && normalizedError && (
|
||||
<div role="alert" style={{ color: "red" }}>
|
||||
{normalizedError}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export default LabeledTextField
|
||||
7
examples/cypress/app/core/hooks/useCurrentUser.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { useQuery } from "blitz"
|
||||
import getCurrentUser from "app/users/queries/getCurrentUser"
|
||||
|
||||
export const useCurrentUser = () => {
|
||||
const [user] = useQuery(getCurrentUser, null)
|
||||
return user
|
||||
}
|
||||
22
examples/cypress/app/core/layouts/Layout.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ReactNode } from "react"
|
||||
import { Head } from "blitz"
|
||||
|
||||
type LayoutProps = {
|
||||
title?: string
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const Layout = ({ title, children }: LayoutProps) => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{title || "cypress"}</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
{children}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Layout
|
||||
19
examples/cypress/app/pages/404.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Head, ErrorComponent } from "blitz"
|
||||
|
||||
// ------------------------------------------------------
|
||||
// This page is rendered if a route match is not found
|
||||
// ------------------------------------------------------
|
||||
export default function Page404() {
|
||||
const statusCode = 404
|
||||
const title = "This page could not be found"
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>
|
||||
{statusCode}: {title}
|
||||
</title>
|
||||
</Head>
|
||||
<ErrorComponent statusCode={statusCode} title={title} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
40
examples/cypress/app/pages/_app.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
AppProps,
|
||||
ErrorBoundary,
|
||||
ErrorComponent,
|
||||
AuthenticationError,
|
||||
AuthorizationError,
|
||||
ErrorFallbackProps,
|
||||
useQueryErrorResetBoundary,
|
||||
} from "blitz"
|
||||
import LoginForm from "app/auth/components/LoginForm"
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
const getLayout = Component.getLayout || ((page) => page)
|
||||
|
||||
return (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={RootErrorFallback}
|
||||
onReset={useQueryErrorResetBoundary().reset}
|
||||
>
|
||||
{getLayout(<Component {...pageProps} />)}
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
function RootErrorFallback({ error, resetErrorBoundary }: ErrorFallbackProps) {
|
||||
if (error instanceof AuthenticationError) {
|
||||
return <LoginForm onSuccess={resetErrorBoundary} />
|
||||
} else if (error instanceof AuthorizationError) {
|
||||
return (
|
||||
<ErrorComponent
|
||||
statusCode={error.statusCode}
|
||||
title="Sorry, you are not authorized to access this"
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<ErrorComponent statusCode={error.statusCode || 400} title={error.message || error.name} />
|
||||
)
|
||||
}
|
||||
}
|
||||
23
examples/cypress/app/pages/_document.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Document, Html, DocumentHead, Main, BlitzScript /*DocumentContext*/ } from "blitz"
|
||||
|
||||
class MyDocument extends Document {
|
||||
// Only uncomment if you need to customize this behaviour
|
||||
// static async getInitialProps(ctx: DocumentContext) {
|
||||
// const initialProps = await Document.getInitialProps(ctx)
|
||||
// return {...initialProps}
|
||||
// }
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Html lang="en">
|
||||
<DocumentHead />
|
||||
<body>
|
||||
<Main />
|
||||
<BlitzScript />
|
||||
</body>
|
||||
</Html>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default MyDocument
|
||||
27
examples/cypress/app/pages/index.test.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { render } from "test/utils"
|
||||
import Home from "./index"
|
||||
|
||||
jest.mock("next/data-client", () => ({
|
||||
...jest.requireActual<object>("next/data-client")!,
|
||||
useQuery: () => [
|
||||
{
|
||||
id: 1,
|
||||
name: "User",
|
||||
email: "user@email.com",
|
||||
role: "user",
|
||||
},
|
||||
],
|
||||
}))
|
||||
|
||||
test("renders blitz documentation link", () => {
|
||||
// This is an example of how to ensure a specific item is in the document
|
||||
// But it's disabled by default (by test.skip) so the test doesn't fail
|
||||
// when you remove the the default content from the page
|
||||
|
||||
// This is an example on how to mock api hooks when testing
|
||||
|
||||
const { getByText } = render(<Home />)
|
||||
const element = getByText(/powered by blitz/i)
|
||||
// @ts-ignore
|
||||
expect(element).toBeInTheDocument()
|
||||
})
|
||||
274
examples/cypress/app/pages/index.tsx
Normal file
@@ -0,0 +1,274 @@
|
||||
import { Suspense } from "react"
|
||||
import { Image, Link, BlitzPage, useMutation } from "blitz"
|
||||
import Layout from "app/core/layouts/Layout"
|
||||
import { useCurrentUser } from "app/core/hooks/useCurrentUser"
|
||||
import logout from "app/auth/mutations/logout"
|
||||
import logo from "public/logo.png"
|
||||
|
||||
import { Routes } from ".blitz"
|
||||
|
||||
/*
|
||||
* This file is just for a pleasant getting started page for your new app.
|
||||
* You can delete everything in here and start from scratch if you like.
|
||||
*/
|
||||
|
||||
const UserInfo = () => {
|
||||
const currentUser = useCurrentUser()
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
|
||||
if (currentUser) {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
className="button small"
|
||||
onClick={async () => {
|
||||
await logoutMutation()
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
<div>
|
||||
User id: <code>{currentUser.id}</code>
|
||||
<br />
|
||||
User role: <code>{currentUser.role}</code>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<>
|
||||
<Link href={Routes.SignupPage()}>
|
||||
<a className="button small">
|
||||
<strong>Sign Up</strong>
|
||||
</a>
|
||||
</Link>
|
||||
<Link href={Routes.LoginPage()}>
|
||||
<a className="button small">
|
||||
<strong>Login</strong>
|
||||
</a>
|
||||
</Link>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Home: BlitzPage = () => {
|
||||
return (
|
||||
<div className="container">
|
||||
<main>
|
||||
<div className="logo">
|
||||
<Image src={logo} alt="blitzjs" />
|
||||
</div>
|
||||
<p>
|
||||
<strong>Congrats!</strong> Your app is ready, including user sign-up and log-in.
|
||||
</p>
|
||||
<div className="buttons" style={{ marginTop: "1rem", marginBottom: "1rem" }}>
|
||||
<Suspense fallback="Loading...">
|
||||
<UserInfo />
|
||||
</Suspense>
|
||||
</div>
|
||||
<p>
|
||||
<strong>
|
||||
To add a new model to your app, <br />
|
||||
run the following in your terminal:
|
||||
</strong>
|
||||
</p>
|
||||
<pre>
|
||||
<code>blitz generate all project name:string</code>
|
||||
</pre>
|
||||
<div style={{ marginBottom: "1rem" }}>(And select Yes to run prisma migrate)</div>
|
||||
<div>
|
||||
<p>
|
||||
Then <strong>restart the server</strong>
|
||||
</p>
|
||||
<pre>
|
||||
<code>Ctrl + c</code>
|
||||
</pre>
|
||||
<pre>
|
||||
<code>blitz dev</code>
|
||||
</pre>
|
||||
<p>
|
||||
and go to{" "}
|
||||
<Link href="/projects">
|
||||
<a>/projects</a>
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
<div className="buttons" style={{ marginTop: "5rem" }}>
|
||||
<a
|
||||
className="button"
|
||||
href="https://blitzjs.com/docs/getting-started?utm_source=blitz-new&utm_medium=app-template&utm_campaign=blitz-new"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</a>
|
||||
<a
|
||||
className="button-outline"
|
||||
href="https://github.com/blitz-js/blitz"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Github Repo
|
||||
</a>
|
||||
<a
|
||||
className="button-outline"
|
||||
href="https://discord.blitzjs.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Discord Community
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<a
|
||||
href="https://blitzjs.com?utm_source=blitz-new&utm_medium=app-template&utm_campaign=blitz-new"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Powered by Blitz.js
|
||||
</a>
|
||||
</footer>
|
||||
|
||||
<style jsx global>{`
|
||||
@import url("https://fonts.googleapis.com/css2?family=Libre+Franklin:wght@300;700&display=swap");
|
||||
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: "Libre Franklin", -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 5rem 0;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
main p {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #45009d;
|
||||
}
|
||||
|
||||
footer a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #f4f4f4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.logo img {
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-gap: 0.5rem;
|
||||
}
|
||||
.button {
|
||||
font-size: 1rem;
|
||||
background-color: #6700eb;
|
||||
padding: 1rem 2rem;
|
||||
color: #f4f4f4;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button.small {
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #45009d;
|
||||
}
|
||||
|
||||
.button-outline {
|
||||
border: 2px solid #6700eb;
|
||||
padding: 1rem 2rem;
|
||||
color: #6700eb;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.button-outline:hover {
|
||||
border-color: #45009d;
|
||||
color: #45009d;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
text-align: center;
|
||||
}
|
||||
code {
|
||||
font-size: 0.9rem;
|
||||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
|
||||
Bitstream Vera Sans Mono, Courier New, monospace;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
|
||||
max-width: 800px;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.grid {
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Home.suppressFirstRenderFlicker = true
|
||||
Home.getLayout = (page) => <Layout title="Home">{page}</Layout>
|
||||
|
||||
export default Home
|
||||
13
examples/cypress/app/users/queries/getCurrentUser.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Ctx } from "blitz"
|
||||
import db from "db"
|
||||
|
||||
export default async function getCurrentUser(_ = null, { session }: Ctx) {
|
||||
if (!session.userId) return null
|
||||
|
||||
const user = await db.user.findFirst({
|
||||
where: { id: session.userId },
|
||||
select: { id: true, name: true, email: true, role: true },
|
||||
})
|
||||
|
||||
return user
|
||||
}
|
||||
4
examples/cypress/babel.config.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
presets: ["blitz/babel"],
|
||||
plugins: [],
|
||||
}
|
||||
19
examples/cypress/blitz.config.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { BlitzConfig, sessionMiddleware, simpleRolesIsAuthorized } from "blitz"
|
||||
|
||||
const config: BlitzConfig = {
|
||||
middleware: [
|
||||
sessionMiddleware({
|
||||
cookiePrefix: "cypress-example",
|
||||
isAuthorized: simpleRolesIsAuthorized,
|
||||
}),
|
||||
],
|
||||
/* Uncomment this to customize the webpack config
|
||||
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
||||
// Note: we provide webpack above so you should not `require` it
|
||||
// Perform customizations to webpack config
|
||||
// Important: return the modified config
|
||||
return config
|
||||
},
|
||||
*/
|
||||
}
|
||||
module.exports = config
|
||||
11
examples/cypress/cypress.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3099",
|
||||
"integrationFolder": "test/e2e",
|
||||
"fixturesFolder": false,
|
||||
"nodeVersion": "system",
|
||||
"defaultCommandTimeout": 12000,
|
||||
"pageLoadTimeout": 120000,
|
||||
"ignoreTestFiles": ["tsconfig.json"],
|
||||
"chromeWebSecurity": false,
|
||||
"video": false
|
||||
}
|
||||
10
examples/cypress/cypress/.eslintrc.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
plugins: ["cypress"],
|
||||
env: {
|
||||
"cypress/globals": true,
|
||||
},
|
||||
extends: ["plugin:cypress/recommended"],
|
||||
rules: {
|
||||
"cypress/no-unnecessary-waiting": "off",
|
||||
},
|
||||
}
|
||||
22
examples/cypress/cypress/global.d.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
declare namespace Cypress {
|
||||
export interface Chainable {
|
||||
// task for totally resetting the database
|
||||
task(event: "db:reset", options?: Partial<Loggable & Timeoutable>): Chainable<boolean>
|
||||
// task for deleting db data without dropping tables
|
||||
task(event: "db:clear", options?: Partial<Loggable & Timeoutable>): Chainable<boolean>
|
||||
// task for seeding db with essential data for tests
|
||||
task(event: "db:seed", options?: Partial<Loggable & Timeoutable>): Chainable<boolean>
|
||||
|
||||
// task for creating a new factory
|
||||
task(
|
||||
event: "factory",
|
||||
args: { name: string; attrs?: any },
|
||||
options?: Partial<Loggable & Timeoutable>
|
||||
): Chainable<any>
|
||||
|
||||
/**
|
||||
* Logs-in user by using API request
|
||||
*/
|
||||
login({ email: string, password: string }): Chainable<Response>
|
||||
}
|
||||
}
|
||||
55
examples/cypress/cypress/plugins/index.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
process.env.NODE_ENV = "test"
|
||||
|
||||
import { loadEnvConfig } from "@blitzjs/env"
|
||||
loadEnvConfig()
|
||||
|
||||
import "./register-ts-paths"
|
||||
import db from "db"
|
||||
import seed from "db/seeds"
|
||||
import { factory } from "test/factories"
|
||||
|
||||
let dbSetup = false
|
||||
|
||||
const pluginConfig: Cypress.PluginConfig = (on, _config) => {
|
||||
on("task", {
|
||||
factory,
|
||||
"db:reset": async () => {
|
||||
if (!dbSetup) {
|
||||
try {
|
||||
// Only need to do this once at startup
|
||||
console.log("Resetting database...")
|
||||
await db.$reset()
|
||||
console.log("Database reset.")
|
||||
dbSetup = true
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw new Error("Failed to set up database in cypress/plugins/index.ts")
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
// for Postgres
|
||||
// "db:clear": () => {
|
||||
// Delete all data without dropping tables, so migration isn't required
|
||||
// await db.$executeRaw`
|
||||
// do
|
||||
// $$
|
||||
// declare
|
||||
// l_stmt text;
|
||||
// begin
|
||||
// select 'truncate ' || string_agg(format('%I.%I', schemaname, tablename), ',')
|
||||
// into l_stmt from pg_tables
|
||||
// where schemaname in ('public');
|
||||
// execute l_stmt;
|
||||
// end;
|
||||
// $$
|
||||
// `
|
||||
// return true
|
||||
// },
|
||||
"db:seed": async () => {
|
||||
await seed()
|
||||
return true
|
||||
},
|
||||
})
|
||||
}
|
||||
export default pluginConfig
|
||||
2
examples/cypress/cypress/plugins/register-ts-paths.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// @ts-ignore
|
||||
require("tsconfig-paths").register()
|
||||
10
examples/cypress/cypress/support/commands.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import "@testing-library/cypress/add-commands"
|
||||
|
||||
Cypress.Commands.add("login", ({ email, password }) => {
|
||||
return cy.request("POST", `/api/rpc/login`, {
|
||||
params: {
|
||||
email,
|
||||
password,
|
||||
},
|
||||
})
|
||||
})
|
||||
24
examples/cypress/cypress/support/index.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
import "./commands"
|
||||
|
||||
before(() => {
|
||||
cy.task("db:reset")
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
// you can clear the database here
|
||||
cy.task("db:seed")
|
||||
})
|
||||
10
examples/cypress/cypress/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["cypress", "@types/testing-library__cypress"],
|
||||
"isolatedModules": false,
|
||||
"tsBuildInfoFile": ".tsbuildinfo.test"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
7
examples/cypress/db/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { enhancePrisma } from "blitz"
|
||||
import { PrismaClient } from "@prisma/client"
|
||||
|
||||
const EnhancedPrisma = enhancePrisma(PrismaClient)
|
||||
|
||||
export * from "@prisma/client"
|
||||
export default new EnhancedPrisma()
|
||||
@@ -0,0 +1,47 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
"name" TEXT,
|
||||
"email" TEXT NOT NULL,
|
||||
"hashedPassword" TEXT,
|
||||
"role" TEXT NOT NULL DEFAULT 'USER'
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Session" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
"expiresAt" DATETIME,
|
||||
"handle" TEXT NOT NULL,
|
||||
"hashedSessionToken" TEXT,
|
||||
"antiCSRFToken" TEXT,
|
||||
"publicData" TEXT,
|
||||
"privateData" TEXT,
|
||||
"userId" INTEGER,
|
||||
FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Token" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL,
|
||||
"hashedToken" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"expiresAt" DATETIME NOT NULL,
|
||||
"sentTo" TEXT NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User.email_unique" ON "User"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Session.handle_unique" ON "Session"("handle");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Token.hashedToken_type_unique" ON "Token"("hashedToken", "type");
|
||||
3
examples/cypress/db/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (i.e. Git)
|
||||
provider = "sqlite"
|
||||
65
examples/cypress/db/schema.prisma
Normal file
@@ -0,0 +1,65 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = "file:./db.sqlite"
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
name String?
|
||||
email String @unique
|
||||
hashedPassword String?
|
||||
role String @default("USER")
|
||||
|
||||
tokens Token[]
|
||||
sessions Session[]
|
||||
}
|
||||
|
||||
model Session {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
expiresAt DateTime?
|
||||
handle String @unique
|
||||
hashedSessionToken String?
|
||||
antiCSRFToken String?
|
||||
publicData String?
|
||||
privateData String?
|
||||
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
userId Int?
|
||||
}
|
||||
|
||||
model Token {
|
||||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
hashedToken String
|
||||
type String
|
||||
// See note below about TokenType enum
|
||||
// type TokenType
|
||||
expiresAt DateTime
|
||||
sentTo String
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId Int
|
||||
|
||||
@@unique([hashedToken, type])
|
||||
}
|
||||
|
||||
// NOTE: It's highly recommended to use an enum for the token type
|
||||
// but enums only work in Postgres.
|
||||
// See: https://blitzjs.com/docs/database-overview#switch-to-postgre-sql
|
||||
// enum TokenType {
|
||||
// RESET_PASSWORD
|
||||
// }
|
||||
15
examples/cypress/db/seeds.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// import db from "./index"
|
||||
|
||||
/*
|
||||
* This seed function is executed when you run `blitz db seed`.
|
||||
*
|
||||
* Probably you want to use a library like https://chancejs.com
|
||||
* to easily generate realistic data.
|
||||
*/
|
||||
const seed = async () => {
|
||||
// for (let i = 0; i < 5; i++) {
|
||||
// await db.project.create({ data: { name: "Project " + i } })
|
||||
// }
|
||||
}
|
||||
|
||||
export default seed
|
||||
7
examples/cypress/jest.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type { Config } from "@jest/types"
|
||||
|
||||
const config: Config.InitialOptions = {
|
||||
preset: "blitz",
|
||||
}
|
||||
|
||||
export default config
|
||||
45
examples/cypress/mailers/forgotPasswordMailer.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/* TODO - You need to add a mailer integration in `integrations/` and import here.
|
||||
*
|
||||
* The integration file can be very simple. Instantiate the email client
|
||||
* and then export it. That way you can import here and anywhere else
|
||||
* and use it straight away.
|
||||
*/
|
||||
|
||||
type ResetPasswordMailer = {
|
||||
to: string
|
||||
token: string
|
||||
}
|
||||
|
||||
export function forgotPasswordMailer({ to, token }: ResetPasswordMailer) {
|
||||
// In production, set APP_ORIGIN to your production server origin
|
||||
const origin = process.env.APP_ORIGIN || process.env.BLITZ_DEV_SERVER_ORIGIN
|
||||
const resetUrl = `${origin}/reset-password?token=${token}`
|
||||
|
||||
const msg = {
|
||||
from: "TODO@example.com",
|
||||
to,
|
||||
subject: "Your Password Reset Instructions",
|
||||
html: `
|
||||
<h1>Reset Your Password</h1>
|
||||
<h3>NOTE: You must set up a production email integration in mailers/forgotPasswordMailer.ts</h3>
|
||||
|
||||
<a href="${resetUrl}">
|
||||
Click here to set a new password
|
||||
</a>
|
||||
`,
|
||||
}
|
||||
|
||||
return {
|
||||
async send() {
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
// TODO - send the production email, like this:
|
||||
// await postmark.sendEmail(msg)
|
||||
throw new Error("No production email implementation in mailers/forgotPasswordMailer")
|
||||
} else {
|
||||
// Preview email in the browser
|
||||
const previewEmail = (await import("preview-email")).default
|
||||
await previewEmail(msg)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
62
examples/cypress/package.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "@examples/cypress",
|
||||
"version": "0.41.1",
|
||||
"scripts": {
|
||||
"dev": "blitz dev",
|
||||
"build": "blitz build",
|
||||
"start": "blitz start",
|
||||
"studio": "blitz prisma studio",
|
||||
"lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .",
|
||||
"cy:open": "cypress open",
|
||||
"cy:run": "cypress run",
|
||||
"test:server": "blitz prisma migrate deploy && blitz build && blitz start -p 3099",
|
||||
"test:e2e": "cross-env NODE_ENV=test start-server-and-test test:server http://localhost:3099 cy:run",
|
||||
"test:jest": "jest --passWithNoTests",
|
||||
"test": "blitz codegen && prisma generate && yarn test:jest && yarn test:e2e"
|
||||
},
|
||||
"prisma": {
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 100
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,tsx}": [
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "tsc && lint-staged && pretty-quick --staged",
|
||||
"pre-push": "npm run lint && npm run test"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.24.1",
|
||||
"blitz": "0.45.4",
|
||||
"final-form": "4.20.1",
|
||||
"react": "0.0.0-experimental-6a589ad71",
|
||||
"react-dom": "0.0.0-experimental-6a589ad71",
|
||||
"react-final-form": "6.5.2",
|
||||
"zod": "3.10.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/cypress": "8.0.1",
|
||||
"@types/preview-email": "2.0.0",
|
||||
"@types/react": "17.0.2",
|
||||
"@types/testing-library__cypress": "5.0.9",
|
||||
"chance": "1.1.8",
|
||||
"cross-env": "7.0.3",
|
||||
"cypress": "6.2.1",
|
||||
"eslint": "7.21.0",
|
||||
"husky": "5.1.2",
|
||||
"lint-staged": "10.5.4",
|
||||
"prettier": "2.2.1",
|
||||
"pretty-quick": "3.1.0",
|
||||
"preview-email": "3.0.3",
|
||||
"prisma": "2.24.1",
|
||||
"start-server-and-test": "1.11.7"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
BIN
examples/cypress/public/favicon.ico
Executable file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
examples/cypress/public/logo.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
3
examples/cypress/test/e2e/.eslintrc.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
extends: ["../../cypress/.eslintrc.js"],
|
||||
}
|
||||
35
examples/cypress/test/e2e/login.e2e.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { User } from "test/factories"
|
||||
|
||||
describe("Login", () => {
|
||||
describe("with an email that doesnt exist", () => {
|
||||
it("shows an error", () => {
|
||||
const email = "nowayshouldIexist@example.com"
|
||||
const password = "test1234"
|
||||
|
||||
cy.visit("/login").wait(100)
|
||||
|
||||
cy.findByLabelText(/email/i).type(email)
|
||||
cy.findByLabelText(/password/i).type(password)
|
||||
cy.findAllByRole("button", { name: /login/i }).click()
|
||||
|
||||
cy.findByText(/invalid/i).should("exist")
|
||||
})
|
||||
})
|
||||
|
||||
describe("with valid credentials", () => {
|
||||
it("logs in", () => {
|
||||
const attrs = { password: "superstrongpassword" }
|
||||
|
||||
cy.visit("/login").wait(100)
|
||||
|
||||
cy.task("factory", { name: "user", attrs }).then((user: User) => {
|
||||
cy.findByLabelText(/email/i).type(user.email)
|
||||
cy.findByLabelText(/password/i).type(attrs.password)
|
||||
cy.findAllByRole("button", { name: /login/i }).click()
|
||||
|
||||
cy.location("pathname").should("equal", "/")
|
||||
cy.findByText(/logout/i).should("exist")
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
14
examples/cypress/test/e2e/signup.e2e.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
describe("Signup", () => {
|
||||
it("creates new account", () => {
|
||||
const attrs = { email: "blitz@example.com", password: "superstrongpassword" }
|
||||
|
||||
cy.visit("/signup").wait(100)
|
||||
|
||||
cy.findByLabelText(/email/i).type(attrs.email)
|
||||
cy.findByLabelText(/password/i).type(attrs.password)
|
||||
cy.findAllByRole("button", { name: /create account/i }).click()
|
||||
|
||||
cy.location("pathname").should("equal", "/")
|
||||
cy.findByText(/logout/i).should("exist")
|
||||
})
|
||||
})
|
||||