Compare commits
1084 Commits
@blitzjs/c
...
all-contri
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f53ba8f459 | ||
|
|
db4922ae79 | ||
|
|
e7bdafc2c5 | ||
|
|
241a62e465 | ||
|
|
5118be3ddd | ||
|
|
eebe8bcdfb | ||
|
|
e4983c6f2e | ||
|
|
3d3bb20365 | ||
|
|
77f9e60a9c | ||
|
|
66111f74bf | ||
|
|
c2bb7728b2 | ||
|
|
d5c2fa15e0 | ||
|
|
f93208e75f | ||
|
|
660c7fbb5e | ||
|
|
bcb88c72ea | ||
|
|
b81a3dd314 | ||
|
|
51bdaa118a | ||
|
|
59cf61a26a | ||
|
|
876eb8327f | ||
|
|
018e462ce8 | ||
|
|
74cde8a871 | ||
|
|
bc9f0e9d85 | ||
|
|
683c251693 | ||
|
|
1d02efb21d | ||
|
|
f35da93d6d | ||
|
|
cd2e29b286 | ||
|
|
82e4f7fd95 | ||
|
|
99e64fa2e0 | ||
|
|
9b0dd2ccaa | ||
|
|
0235395e54 | ||
|
|
67ba766a87 | ||
|
|
85216555fc | ||
|
|
25ebbc919b | ||
|
|
312dc3a1a9 | ||
|
|
f31d2a9770 | ||
|
|
0199605d07 | ||
|
|
092775a3f2 | ||
|
|
aea6c88b1e | ||
|
|
846194a5b1 | ||
|
|
814ed2d59a | ||
|
|
41106588ff | ||
|
|
6f50d77756 | ||
|
|
99bf898cdc | ||
|
|
4ef7d81018 | ||
|
|
37ce99a37a | ||
|
|
2f3be902e4 | ||
|
|
968f1d0cb9 | ||
|
|
0b103bccca | ||
|
|
406b643f94 | ||
|
|
33c7bec41f | ||
|
|
3d827c8506 | ||
|
|
b04c6d7469 | ||
|
|
242e2eadee | ||
|
|
08303d337b | ||
|
|
be861c7919 | ||
|
|
092045e807 | ||
|
|
1e0f17c93a | ||
|
|
310079b3bc | ||
|
|
a81252aeb4 | ||
|
|
cc58c72d94 | ||
|
|
2162e1c6b4 | ||
|
|
d46d860338 | ||
|
|
c65360de09 | ||
|
|
9873fc22de | ||
|
|
e6954fbca8 | ||
|
|
048ba5f5cb | ||
|
|
bd1063a965 | ||
|
|
ae6b22f4f0 | ||
|
|
f45d2d5ee3 | ||
|
|
7bc8a249b4 | ||
|
|
742ff71a97 | ||
|
|
9291ae3b38 | ||
|
|
5a5656078b | ||
|
|
ea815e83fa | ||
|
|
869c00c950 | ||
|
|
a670693e9d | ||
|
|
5de91ad57b | ||
|
|
31899458de | ||
|
|
dce462ba53 | ||
|
|
5ebed4b05d | ||
|
|
13353793af | ||
|
|
3583a59aa8 | ||
|
|
1c5aee7c67 | ||
|
|
c87883dbe8 | ||
|
|
7d84561690 | ||
|
|
3f43ffd4fe | ||
|
|
1ac2092129 | ||
|
|
579807ff20 | ||
|
|
566e8be3c3 | ||
|
|
1b9eb77964 | ||
|
|
9f24ba10b2 | ||
|
|
f5237c31c4 | ||
|
|
3ddb3870b9 | ||
|
|
763252a5ed | ||
|
|
6a37f32322 | ||
|
|
48e27be1a7 | ||
|
|
90df4e8409 | ||
|
|
3b46d96ec8 | ||
|
|
13c5a9b802 | ||
|
|
e6ddebadf5 | ||
|
|
1bb4cf33ff | ||
|
|
36dfbe42f5 | ||
|
|
6c06f0b62c | ||
|
|
a83536be21 | ||
|
|
07f9e26827 | ||
|
|
c5e6221ebb | ||
|
|
2b0fe98cf5 | ||
|
|
58386ffe2c | ||
|
|
23fc27027a | ||
|
|
e4c00094e5 | ||
|
|
a357fd0445 | ||
|
|
c43967984b | ||
|
|
e47d947dc0 | ||
|
|
ffb54ec064 | ||
|
|
08abc33494 | ||
|
|
34722f952c | ||
|
|
4003b8ac01 | ||
|
|
160b5fc062 | ||
|
|
b722c39f79 | ||
|
|
8da7bd7cd4 | ||
|
|
712cb172eb | ||
|
|
d623d8cc33 | ||
|
|
5ca38ca6d8 | ||
|
|
db0128c971 | ||
|
|
856aa53843 | ||
|
|
f9c3f82b27 | ||
|
|
97d5f396de | ||
|
|
760fba77ab | ||
|
|
f83ce0bd72 | ||
|
|
7425952616 | ||
|
|
7fac0134b3 | ||
|
|
df46939fe3 | ||
|
|
9e88b11496 | ||
|
|
c427ae23d4 | ||
|
|
cb849c5ba9 | ||
|
|
6e777dd72a | ||
|
|
80ab4876f2 | ||
|
|
cd0bf1f970 | ||
|
|
5f5a5c8ef7 | ||
|
|
9a1e0d0de7 | ||
|
|
fb44203510 | ||
|
|
010057b34c | ||
|
|
575e862ae3 | ||
|
|
aed6b8875a | ||
|
|
10b6f859fd | ||
|
|
9ac856c0ee | ||
|
|
1ff7f36482 | ||
|
|
df150da37e | ||
|
|
eb7409c0b3 | ||
|
|
1411a1d366 | ||
|
|
ec95cb40de | ||
|
|
b502d7ea1e | ||
|
|
74bf2a9e4c | ||
|
|
1ee637c367 | ||
|
|
c08771b57e | ||
|
|
8a468e4f79 | ||
|
|
23a33f1c3d | ||
|
|
b3767861a2 | ||
|
|
65acfff0ff | ||
|
|
ab3fc26409 | ||
|
|
7b7039e0e3 | ||
|
|
e93f24452c | ||
|
|
63c9375331 | ||
|
|
adfb486004 | ||
|
|
5828736369 | ||
|
|
40a93ee62d | ||
|
|
8fa82c7661 | ||
|
|
141003df89 | ||
|
|
6ef7b8a2de | ||
|
|
6ade33b849 | ||
|
|
02d3aa8259 | ||
|
|
1ae2bb3ee3 | ||
|
|
d84c73d2bb | ||
|
|
89b55971f1 | ||
|
|
fd1856bc7b | ||
|
|
e6dbbababb | ||
|
|
3e2b5ddc8e | ||
|
|
1b974a0371 | ||
|
|
8bf9667a15 | ||
|
|
94bd4c166c | ||
|
|
4ad9f9bdc9 | ||
|
|
13e1526ef5 | ||
|
|
ab3021a371 | ||
|
|
3e506c1dce | ||
|
|
85356ca8e8 | ||
|
|
530ce851e4 | ||
|
|
d953ef795a | ||
|
|
7fcb0945a2 | ||
|
|
ab4670c21b | ||
|
|
1ae7bf77b2 | ||
|
|
63e3fe1ccb | ||
|
|
280a2b5c4f | ||
|
|
bf2734d907 | ||
|
|
07341c14d3 | ||
|
|
e150b67cf4 | ||
|
|
1a1722168c | ||
|
|
7f266b0c98 | ||
|
|
6e92a2dfde | ||
|
|
66cd1ec650 | ||
|
|
7c4916324e | ||
|
|
d747e34853 | ||
|
|
3afab440c8 | ||
|
|
e576e6332c | ||
|
|
60d0c9d0bf | ||
|
|
8f800d388b | ||
|
|
0fb3163ed5 | ||
|
|
a64cf7d62a | ||
|
|
ac78d9a6e1 | ||
|
|
46035af2b3 | ||
|
|
3ee531f221 | ||
|
|
294be124f2 | ||
|
|
b1b8b5f15e | ||
|
|
4f1d80f970 | ||
|
|
622016f4b7 | ||
|
|
ceb0262540 | ||
|
|
8e9f2d097e | ||
|
|
155dfaa4da | ||
|
|
ec0273f09d | ||
|
|
7a80f2be2f | ||
|
|
0821c019bd | ||
|
|
f6cc8d152e | ||
|
|
2921cb5a85 | ||
|
|
017c1ff813 | ||
|
|
eabe54c8ec | ||
|
|
ba14973ad3 | ||
|
|
e29786ba24 | ||
|
|
71e3e48f69 | ||
|
|
c0ef559eae | ||
|
|
60a338b730 | ||
|
|
b4039ff9af | ||
|
|
f51a0de5dc | ||
|
|
5a006fa89f | ||
|
|
1ecaa5ea76 | ||
|
|
5d0eb4e44e | ||
|
|
1756d57a39 | ||
|
|
2cf1b63895 | ||
|
|
b0c2a58a83 | ||
|
|
188b8d8ae8 | ||
|
|
fbd5f2815f | ||
|
|
898f39bf8e | ||
|
|
91f5056b9d | ||
|
|
a00a529387 | ||
|
|
b5d564fab8 | ||
|
|
be19dbccf8 | ||
|
|
b21df113a8 | ||
|
|
4e0abb6ca6 | ||
|
|
9cbec551f8 | ||
|
|
7531cf66f7 | ||
|
|
cf0d77e010 | ||
|
|
713f20d494 | ||
|
|
19293c1efb | ||
|
|
2466a6b98c | ||
|
|
de8e0a6808 | ||
|
|
8b9252c697 | ||
|
|
12c0f72243 | ||
|
|
5e43599338 | ||
|
|
1bf5bf0492 | ||
|
|
ff9f70daa8 | ||
|
|
89676e4ba8 | ||
|
|
679efef951 | ||
|
|
bcd9e8dbc9 | ||
|
|
8b0fa91233 | ||
|
|
e55e90c345 | ||
|
|
4e81c97b2b | ||
|
|
16b414bd3d | ||
|
|
8798c9fb3d | ||
|
|
9f91767246 | ||
|
|
a6878b35d0 | ||
|
|
39c3b27038 | ||
|
|
5cc54ab981 | ||
|
|
91034216a5 | ||
|
|
2c78ead4cd | ||
|
|
a0cf98bc47 | ||
|
|
6898ead0a5 | ||
|
|
c7843e8077 | ||
|
|
370486291a | ||
|
|
e26e04c603 | ||
|
|
1fa7d17587 | ||
|
|
27bc2e49c4 | ||
|
|
18beb6fb1d | ||
|
|
5f68bda686 | ||
|
|
81ec5c8528 | ||
|
|
0d0c808cc3 | ||
|
|
097a2196f3 | ||
|
|
c592b04c18 | ||
|
|
b0d61dc4f1 | ||
|
|
f5d7ab9005 | ||
|
|
26cc39322a | ||
|
|
9441dfc1f7 | ||
|
|
4231c9c97f | ||
|
|
9a72648ff8 | ||
|
|
2059009c1b | ||
|
|
44e32f0206 | ||
|
|
924d431c0d | ||
|
|
3ee9dd8bea | ||
|
|
fc6817520e | ||
|
|
b53ad3ea4e | ||
|
|
a999408fed | ||
|
|
984a10abef | ||
|
|
1a7274e5a6 | ||
|
|
3e9810e91a | ||
|
|
6aa2c5d471 | ||
|
|
3433411a01 | ||
|
|
1177e5c9f6 | ||
|
|
ca5b91c340 | ||
|
|
ba0aeae3e5 | ||
|
|
24162830ae | ||
|
|
d0015e3f88 | ||
|
|
6b2788923e | ||
|
|
3b5aa9006d | ||
|
|
8637ed63ba | ||
|
|
f78781c63b | ||
|
|
dc6ffed270 | ||
|
|
2686e1c2ea | ||
|
|
59c7fb9b01 | ||
|
|
b6b877e851 | ||
|
|
90a7624489 | ||
|
|
ade63c53fd | ||
|
|
08e6cd3d2e | ||
|
|
6839b55d1d | ||
|
|
528a7ec18b | ||
|
|
9a3f1a1241 | ||
|
|
10c1e0cfea | ||
|
|
68162b406c | ||
|
|
4cc80b8529 | ||
|
|
0ae3bd4afa | ||
|
|
2207889c6d | ||
|
|
338b390a78 | ||
|
|
c173b9d09d | ||
|
|
e1120a0449 | ||
|
|
b4551323c8 | ||
|
|
50a276f582 | ||
|
|
63a078be27 | ||
|
|
16ab5675e2 | ||
|
|
7509aca08d | ||
|
|
5320bc5211 | ||
|
|
d32a39993c | ||
|
|
5795eefaab | ||
|
|
28e6a0032a | ||
|
|
96fea67112 | ||
|
|
9005c58349 | ||
|
|
dea9200f9d | ||
|
|
b6e72cc5f5 | ||
|
|
5165793a4e | ||
|
|
1fe2653b4f | ||
|
|
740b57798f | ||
|
|
07cf6d6e26 | ||
|
|
21896944f9 | ||
|
|
62a5408e6e | ||
|
|
e1e82cb630 | ||
|
|
81c13df956 | ||
|
|
65acdc971c | ||
|
|
eb1c88ee1a | ||
|
|
d0fdb7b1f3 | ||
|
|
724c6921da | ||
|
|
31ecd58857 | ||
|
|
aee33f0354 | ||
|
|
baf3fb9b4f | ||
|
|
437ce18170 | ||
|
|
167abce895 | ||
|
|
ed23307267 | ||
|
|
436bd4e306 | ||
|
|
8ee9df51fd | ||
|
|
a421212e63 | ||
|
|
10c3b248e9 | ||
|
|
b5da9c2822 | ||
|
|
509110b1ea | ||
|
|
852fdc6016 | ||
|
|
69449ca6b9 | ||
|
|
35ff20bc78 | ||
|
|
000cf2d4bf | ||
|
|
20f1d99e7c | ||
|
|
960e225f0c | ||
|
|
d8449d4458 | ||
|
|
50e20b812c | ||
|
|
fa8616f8a3 | ||
|
|
362352379d | ||
|
|
580e2724ff | ||
|
|
19c3f13de9 | ||
|
|
53f3fbf7c7 | ||
|
|
7426fc5794 | ||
|
|
089ca908ed | ||
|
|
820c678533 | ||
|
|
abd0bbd7cf | ||
|
|
af68b9aa0a | ||
|
|
4ce2161ec7 | ||
|
|
2d9338a613 | ||
|
|
9e39c4229b | ||
|
|
ea58cc336b | ||
|
|
323bb28cc3 | ||
|
|
7f232be90f | ||
|
|
60d48c6f83 | ||
|
|
0753dae8ca | ||
|
|
d70cf53f16 | ||
|
|
c4589bd9fe | ||
|
|
33b888e1ea | ||
|
|
fa8ab60870 | ||
|
|
7f8609bbea | ||
|
|
927c3ac6a5 | ||
|
|
2e7f191a31 | ||
|
|
2da0508964 | ||
|
|
02d0d06b84 | ||
|
|
4eb00cfdc6 | ||
|
|
389921d0da | ||
|
|
09ab9cc9fc | ||
|
|
c0efe8c411 | ||
|
|
26626ced9f | ||
|
|
d7d733c5a4 | ||
|
|
82fd604be4 | ||
|
|
342782fe12 | ||
|
|
a45235ef58 | ||
|
|
440ed3d81a | ||
|
|
fc9da2ace1 | ||
|
|
9a6fc37b7d | ||
|
|
3ac4303dad | ||
|
|
93f4768535 | ||
|
|
a24b78e654 | ||
|
|
843dbc2c66 | ||
|
|
9e75a75049 | ||
|
|
df3349e403 | ||
|
|
396613aee3 | ||
|
|
06859d6bdb | ||
|
|
d4cb65277b | ||
|
|
8b2a50d288 | ||
|
|
10146f6723 | ||
|
|
5294166ea7 | ||
|
|
fbfc2c86e0 | ||
|
|
1cee5ead28 | ||
|
|
eba7be8626 | ||
|
|
8d699f5a6b | ||
|
|
35b5f12395 | ||
|
|
2d8fb4b135 | ||
|
|
9bb5730793 | ||
|
|
8bc416d8ae | ||
|
|
48250d04ac | ||
|
|
8ecdc3253d | ||
|
|
58900eb9eb | ||
|
|
9c04a9d5e4 | ||
|
|
c6f47729b4 | ||
|
|
7a1b4b40d1 | ||
|
|
0f70020312 | ||
|
|
24ef56ca18 | ||
|
|
3d85f365db | ||
|
|
eaa1a88318 | ||
|
|
11e82686d9 | ||
|
|
25f96d0ca6 | ||
|
|
4c5bb19766 | ||
|
|
57a798af34 | ||
|
|
b3814fc7c0 | ||
|
|
09fc2e10d6 | ||
|
|
a3fcc3d7b3 | ||
|
|
8ae42c5d97 | ||
|
|
832820c97c | ||
|
|
5ec2f8ca5c | ||
|
|
581e2fa807 | ||
|
|
b8e2e10288 | ||
|
|
15c7b76b51 | ||
|
|
86c7281c46 | ||
|
|
57fb819152 | ||
|
|
acdcdbafb1 | ||
|
|
dd2d759d35 | ||
|
|
3494e07d67 | ||
|
|
32a3a3f97a | ||
|
|
4386d2cb80 | ||
|
|
f82e905c8e | ||
|
|
775d62702f | ||
|
|
f1ec0f8c46 | ||
|
|
247bb8227e | ||
|
|
339ebcab7a | ||
|
|
fe384f546b | ||
|
|
278fa74e1b | ||
|
|
8587e4618b | ||
|
|
62fb3978b2 | ||
|
|
f0573ac033 | ||
|
|
799f7b2916 | ||
|
|
1b2c5a35ef | ||
|
|
ce49a2da51 | ||
|
|
3d4a15efd7 | ||
|
|
9eb85f61ed | ||
|
|
f0775cbbb9 | ||
|
|
25e9b2645e | ||
|
|
2ace6c728b | ||
|
|
da7f542122 | ||
|
|
8d0da90367 | ||
|
|
24f55ab085 | ||
|
|
ea63de0d21 | ||
|
|
2230842648 | ||
|
|
ad77e2cdd9 | ||
|
|
439d12694b | ||
|
|
6a951c9d3c | ||
|
|
f185138712 | ||
|
|
bf13f61046 | ||
|
|
c3d4882151 | ||
|
|
56f4e6efec | ||
|
|
a175fd2f26 | ||
|
|
7975373551 | ||
|
|
73502e3a9a | ||
|
|
b04a76a6dc | ||
|
|
c05b43a4dd | ||
|
|
e99462b8ff | ||
|
|
201ea1eb25 | ||
|
|
9c9c42309a | ||
|
|
baf4907912 | ||
|
|
bc1e695ca8 | ||
|
|
3f6b9ef1ad | ||
|
|
a5410053e1 | ||
|
|
798eb7a394 | ||
|
|
cda8313cfd | ||
|
|
462e22a745 | ||
|
|
3215b32b32 | ||
|
|
c64256ca26 | ||
|
|
6459d24bce | ||
|
|
15d00bc8de | ||
|
|
643e6a1701 | ||
|
|
09932642f9 | ||
|
|
b3a5ab20d4 | ||
|
|
9c387e11be | ||
|
|
96013f4a9c | ||
|
|
a5a8f4268a | ||
|
|
f398efa76c | ||
|
|
b34c0d77b9 | ||
|
|
922cba40f3 | ||
|
|
451dcb7e45 | ||
|
|
3b316448a7 | ||
|
|
280755c83a | ||
|
|
b94a55f9ce | ||
|
|
3ab8951764 | ||
|
|
83f01434c4 | ||
|
|
e7dcf1c898 | ||
|
|
533f97c1c8 | ||
|
|
d9fb0dde48 | ||
|
|
077644ec76 | ||
|
|
21060b410b | ||
|
|
f53a560b84 | ||
|
|
7bdc524de4 | ||
|
|
36ffb7c93a | ||
|
|
ce9d2aa8dc | ||
|
|
05dad27f35 | ||
|
|
1700343f11 | ||
|
|
2a0ab59f0f | ||
|
|
c057bfd531 | ||
|
|
855363b2c7 | ||
|
|
c8a5304d3c | ||
|
|
3aa919e825 | ||
|
|
4181efb75c | ||
|
|
7b7b3383ed | ||
|
|
e1b1fcb6b5 | ||
|
|
d3b9fce0bd | ||
|
|
5d0531d35a | ||
|
|
0f6ea26560 | ||
|
|
5c434e3b3e | ||
|
|
b5f0cb2ae7 | ||
|
|
02219a22e7 | ||
|
|
c80f28b588 | ||
|
|
4daa44442f | ||
|
|
0bd1b6fefc | ||
|
|
0f279082c4 | ||
|
|
cde418ffae | ||
|
|
9e681c6363 | ||
|
|
2b4aa6fb2e | ||
|
|
c11ffe82b0 | ||
|
|
0296f3c5c3 | ||
|
|
279557459d | ||
|
|
3b64d994f7 | ||
|
|
50e7a8f1fe | ||
|
|
f3ad5fde7c | ||
|
|
129fd02ce1 | ||
|
|
b622847184 | ||
|
|
c743e82451 | ||
|
|
ee91ef2972 | ||
|
|
a7195f44b3 | ||
|
|
b1c8cf6e00 | ||
|
|
227f5da7ba | ||
|
|
dc9c9756ae | ||
|
|
9aebf5129d | ||
|
|
c23aba87b6 | ||
|
|
fcd572a5e4 | ||
|
|
a8e352ce17 | ||
|
|
e69a7b6166 | ||
|
|
b66b655154 | ||
|
|
b900095313 | ||
|
|
4f7fc78e59 | ||
|
|
eaf1e0c340 | ||
|
|
8786b2034b | ||
|
|
7ec2a22b64 | ||
|
|
1429b510bd | ||
|
|
b16d6b8e5a | ||
|
|
2c5bc8dbf4 | ||
|
|
25904c8d55 | ||
|
|
eb7f668d52 | ||
|
|
f223f84f02 | ||
|
|
46185f8832 | ||
|
|
e543e8a892 | ||
|
|
a7ae0fbc0c | ||
|
|
3317ab74c2 | ||
|
|
3f265c8f5b | ||
|
|
0e647ddfac | ||
|
|
1c064e56b2 | ||
|
|
e63fe53dc6 | ||
|
|
6858fe4101 | ||
|
|
f5b7b25611 | ||
|
|
b2407ebdea | ||
|
|
caefccfda1 | ||
|
|
4f5c09f32c | ||
|
|
1c0d7e1d5b | ||
|
|
ed27152c51 | ||
|
|
95bbbfc4e7 | ||
|
|
c17e161f80 | ||
|
|
7456d62171 | ||
|
|
9eb5bb4584 | ||
|
|
17d9895070 | ||
|
|
b7bc20574a | ||
|
|
5dbe2af6ed | ||
|
|
a1e41101cc | ||
|
|
3e04881e96 | ||
|
|
ee6e492185 | ||
|
|
ec613d4549 | ||
|
|
717548af26 | ||
|
|
287b72726e | ||
|
|
d76fc7494c | ||
|
|
33e28877e9 | ||
|
|
114ae77bec | ||
|
|
4cf74b19b5 | ||
|
|
96b12eabe3 | ||
|
|
d51b92bbec | ||
|
|
5e4227181b | ||
|
|
7761f63534 | ||
|
|
f1881993dd | ||
|
|
7cfc586667 | ||
|
|
19e4620c23 | ||
|
|
3a407b7c08 | ||
|
|
6eb07b688f | ||
|
|
c147048e6d | ||
|
|
750cba1b19 | ||
|
|
ffaba32b12 | ||
|
|
dedad9e55a | ||
|
|
ea91de84c0 | ||
|
|
944ec4576b | ||
|
|
96b8f69464 | ||
|
|
17a43b8001 | ||
|
|
cbce0c7ac1 | ||
|
|
0117198864 | ||
|
|
150d320e7f | ||
|
|
290702e7be | ||
|
|
75a7feabf9 | ||
|
|
603e5cbaf2 | ||
|
|
3c52246478 | ||
|
|
3acf590e1c | ||
|
|
060cfac2f8 | ||
|
|
3e5d2f4c6f | ||
|
|
623c4b37fc | ||
|
|
6e85653f82 | ||
|
|
8e5e2b3cbd | ||
|
|
094df2a7bb | ||
|
|
47155fbec3 | ||
|
|
96ef3fe6b7 | ||
|
|
6cd9d9496c | ||
|
|
223ab891db | ||
|
|
25c5e05ea3 | ||
|
|
aad5ab772f | ||
|
|
4651ae021a | ||
|
|
8abcc8e78c | ||
|
|
44532424a9 | ||
|
|
bea6fdc0ec | ||
|
|
b6b110fd10 | ||
|
|
3339b131e1 | ||
|
|
58d1bcf2f9 | ||
|
|
c5008e263a | ||
|
|
ef451feb6a | ||
|
|
2bf589d4f8 | ||
|
|
fd8a29f9cd | ||
|
|
f0517e072d | ||
|
|
6cd3abe6ea | ||
|
|
2d8e33151f | ||
|
|
307f373b42 | ||
|
|
45cbd02370 | ||
|
|
cddba4ef7a | ||
|
|
4988dd7a00 | ||
|
|
ea61978d08 | ||
|
|
a11c1d4191 | ||
|
|
4ac78002ff | ||
|
|
10bb5873cf | ||
|
|
ac30c9f39b | ||
|
|
a5d3f9a493 | ||
|
|
2461caa685 | ||
|
|
1d16593dce | ||
|
|
3790e2cf17 | ||
|
|
92c0f85c82 | ||
|
|
2f2496fa00 | ||
|
|
e12d17b6c1 | ||
|
|
0153bd1444 | ||
|
|
230c363409 | ||
|
|
14a09e1e03 | ||
|
|
229272f772 | ||
|
|
f450692e65 | ||
|
|
d4654c8837 | ||
|
|
85fcebadd5 | ||
|
|
a7fd429e20 | ||
|
|
e688267f3f | ||
|
|
c8043d93d4 | ||
|
|
2c9e8e1318 | ||
|
|
386a7fdbe5 | ||
|
|
1b02b5fb39 | ||
|
|
ff097bd67b | ||
|
|
5a6f73b140 | ||
|
|
aa64c5e467 | ||
|
|
74487a37d5 | ||
|
|
50a2bd1db7 | ||
|
|
d1c2d44f94 | ||
|
|
26ebf8ce48 | ||
|
|
2063a1878f | ||
|
|
6911a2c60e | ||
|
|
a44dea27ac | ||
|
|
21f29d23ec | ||
|
|
83fbd5827b | ||
|
|
3b595320aa | ||
|
|
e10f1253db | ||
|
|
b7331375df | ||
|
|
b249ce04a6 | ||
|
|
aa5eb90952 | ||
|
|
6819da290b | ||
|
|
fd1cd78a05 | ||
|
|
2b79c3f3bd | ||
|
|
e9ae33700c | ||
|
|
bec4a65d36 | ||
|
|
b7a8667003 | ||
|
|
e6ddb8603f | ||
|
|
d72f2839d7 | ||
|
|
7ec6244884 | ||
|
|
3892b23dfd | ||
|
|
a6c018b93d | ||
|
|
32d05e2447 | ||
|
|
b08de105ef | ||
|
|
b0120d718d | ||
|
|
f8c0f122b9 | ||
|
|
bfd4642955 | ||
|
|
2fb9abce86 | ||
|
|
a406c82607 | ||
|
|
ae15456576 | ||
|
|
99b4cd628c | ||
|
|
2552a99e6d | ||
|
|
a2b94603a0 | ||
|
|
e846560b3b | ||
|
|
fb298bb0c0 | ||
|
|
b417a6da83 | ||
|
|
c3f0609b0d | ||
|
|
6e1b8d63e4 | ||
|
|
1774d816a8 | ||
|
|
c16f8e65f3 | ||
|
|
54b716ef23 | ||
|
|
1e0cd973e0 | ||
|
|
d1d3c97303 | ||
|
|
3f428e3cb3 | ||
|
|
44c48839e0 | ||
|
|
79d9619c3d | ||
|
|
7b0a483c7b | ||
|
|
a33005e7c5 | ||
|
|
cec8b6130d | ||
|
|
9340d8dec9 | ||
|
|
d29e62965f | ||
|
|
9531593463 | ||
|
|
6fabfc41ba | ||
|
|
dd97061ac1 | ||
|
|
86ace11282 | ||
|
|
75816d11fd | ||
|
|
612c09f9b3 | ||
|
|
303ce52757 | ||
|
|
9e663e1c37 | ||
|
|
268f8bb4c0 | ||
|
|
01c016ab7b | ||
|
|
746eb7508c | ||
|
|
aeed847926 | ||
|
|
3bcc1de895 | ||
|
|
6f3ef059af | ||
|
|
523ce93402 | ||
|
|
e8f68a5c19 | ||
|
|
d5aa2b77e8 | ||
|
|
a36d943e05 | ||
|
|
7459f691ae | ||
|
|
08e351dcc1 | ||
|
|
ae3c530d8f | ||
|
|
79f1d23604 | ||
|
|
07a97ba992 | ||
|
|
4eb17f088a | ||
|
|
07312c1162 | ||
|
|
f519f159cf | ||
|
|
badd5adaf0 | ||
|
|
15f30d394c | ||
|
|
c2b85a747e | ||
|
|
cb028a6e3e | ||
|
|
192f79e064 | ||
|
|
a8d152ba87 | ||
|
|
875f99a20c | ||
|
|
c73bdc7487 | ||
|
|
040deeed32 | ||
|
|
9c670ef77d | ||
|
|
7db98c3636 | ||
|
|
08195b04e6 | ||
|
|
cdf8cc4a9f | ||
|
|
0c3b8dd17a | ||
|
|
fd624213b3 | ||
|
|
9d91117b97 | ||
|
|
8cd670296e | ||
|
|
14df845e16 | ||
|
|
7b6b024388 | ||
|
|
d736ea11f3 | ||
|
|
9a67da5993 | ||
|
|
ba981694ad | ||
|
|
1eebdb54c6 | ||
|
|
fe1f4b0785 | ||
|
|
63921f3e23 | ||
|
|
69b02ffb54 | ||
|
|
86eec51d24 | ||
|
|
d59c0a4fd3 | ||
|
|
852e32a484 | ||
|
|
052300f09d | ||
|
|
d2f94ff0cb | ||
|
|
262a228cd9 | ||
|
|
9bf36b0421 | ||
|
|
73d2251168 | ||
|
|
2d52ceec7f | ||
|
|
c8527d93f9 | ||
|
|
5a69c49976 | ||
|
|
49044611eb | ||
|
|
2997fcc17d | ||
|
|
6f1900c5e6 | ||
|
|
a342d62cb5 | ||
|
|
5c89d7feb9 | ||
|
|
92cf7b599f | ||
|
|
47d16202c3 | ||
|
|
5fb24faa1a | ||
|
|
815b351f4a | ||
|
|
b7528b2058 | ||
|
|
6af0eb7ea5 | ||
|
|
dcc9c4ddc9 | ||
|
|
e7982a1132 | ||
|
|
64eccf8bb4 | ||
|
|
caad5b44f1 | ||
|
|
4b4d65cb7e | ||
|
|
55fdaa0530 | ||
|
|
fb3893a8d4 | ||
|
|
ca5d6ee0aa | ||
|
|
f17820f81d | ||
|
|
ab6f60571a | ||
|
|
5f3d5dd7a3 | ||
|
|
8b8143d2c2 | ||
|
|
8b6a51f8f1 | ||
|
|
0c23a7873c | ||
|
|
0fa28d20c4 | ||
|
|
97132996b8 | ||
|
|
96ac63d3a4 | ||
|
|
132601f0c2 | ||
|
|
c47d15a09f | ||
|
|
0892137370 | ||
|
|
797060c068 | ||
|
|
1c7134c272 | ||
|
|
2638ec73b3 | ||
|
|
3c4db0453e | ||
|
|
d824459190 | ||
|
|
5da2eae6e1 | ||
|
|
73f6be0814 | ||
|
|
2dfa86556d | ||
|
|
7097150c2d | ||
|
|
84a8ac7512 | ||
|
|
ef48721625 | ||
|
|
a54b48190c | ||
|
|
ff5cab07fc | ||
|
|
02ccc7db0e | ||
|
|
9de79ba621 | ||
|
|
dfac941a80 | ||
|
|
f3f17a2452 | ||
|
|
aa6d0e0dc0 | ||
|
|
4b0b1b8c66 | ||
|
|
7e72dd3ccd | ||
|
|
0aa16e25ae | ||
|
|
9e5d58ddbd | ||
|
|
edd673f54c | ||
|
|
6cccbe3487 | ||
|
|
92069cfef8 | ||
|
|
b16424592f | ||
|
|
92c4a4bfc8 | ||
|
|
ffd87a80af | ||
|
|
9c54cfaef1 | ||
|
|
fd2e9d2988 | ||
|
|
3cc4476a98 | ||
|
|
1a45b2d394 | ||
|
|
bac7f21295 | ||
|
|
9755466f9b | ||
|
|
3a85e83b56 | ||
|
|
4e49239f53 | ||
|
|
f0a56ff2fe | ||
|
|
2a71e3441d | ||
|
|
63cacbb73c | ||
|
|
219d12aaa2 | ||
|
|
b1321c77e1 | ||
|
|
f7685b4abb | ||
|
|
cf215b4a12 | ||
|
|
32f0a76b18 | ||
|
|
e9e8841f07 | ||
|
|
d6b29a2f71 | ||
|
|
af338d99e4 | ||
|
|
bd63e4cab0 | ||
|
|
e387936cb0 | ||
|
|
0650252c53 | ||
|
|
76cfb8c076 | ||
|
|
6273ffd255 | ||
|
|
6e447f1f44 | ||
|
|
4c4721250a | ||
|
|
6852cfc208 | ||
|
|
da488ccf33 | ||
|
|
36d0ae8587 | ||
|
|
8bcaf62641 | ||
|
|
820d191a63 | ||
|
|
45842d48ad | ||
|
|
67ed16429d | ||
|
|
45cb96f9f1 | ||
|
|
9063758292 | ||
|
|
2a892ba4d0 | ||
|
|
73b3920a53 | ||
|
|
fae90065df | ||
|
|
fc762c15fc | ||
|
|
cc10b71f9d | ||
|
|
998d227832 | ||
|
|
35c150a46a | ||
|
|
920716a0d8 | ||
|
|
39675d1da8 | ||
|
|
dd20c0ac6c | ||
|
|
2ea1e7b522 | ||
|
|
44c3ea22e2 | ||
|
|
f4760776ee | ||
|
|
65bb7e8e84 | ||
|
|
8547585cc7 | ||
|
|
16b810e0c3 | ||
|
|
8d38c6c225 | ||
|
|
c00e78cbc7 | ||
|
|
11325ba136 | ||
|
|
477094d042 | ||
|
|
2c91340539 | ||
|
|
4c42176ec9 | ||
|
|
6564a268f6 | ||
|
|
9c66a2938e | ||
|
|
27e314821d | ||
|
|
bf4b90943b | ||
|
|
3b5f7bc6c8 | ||
|
|
0659b37d77 | ||
|
|
67950db948 | ||
|
|
45a09911a4 | ||
|
|
e89127358f | ||
|
|
cf94dc866d | ||
|
|
bd3841b43b | ||
|
|
50dd2dcc4e | ||
|
|
6443184f0f | ||
|
|
9f8a7afd17 | ||
|
|
5d3afb0230 | ||
|
|
9dfc5c53ed | ||
|
|
ba540bb546 | ||
|
|
b70296a7a2 | ||
|
|
36c0acdb92 | ||
|
|
549115af97 | ||
|
|
a4d6fe139e | ||
|
|
9010566895 | ||
|
|
167fc251fd | ||
|
|
4bcc2efbec | ||
|
|
4c1eed6248 | ||
|
|
36b4f101f9 | ||
|
|
9209c934ee | ||
|
|
ecd1118ce5 | ||
|
|
29820ac964 | ||
|
|
93dcd6d884 | ||
|
|
6f66e5bd72 | ||
|
|
df76a4b2ab | ||
|
|
b9391305b0 | ||
|
|
9e1ce7dda0 | ||
|
|
d956da624f | ||
|
|
4b29564f12 | ||
|
|
227c1204c2 | ||
|
|
1ca88afcef | ||
|
|
bb4272bbe6 | ||
|
|
b749884ddc | ||
|
|
0b18df1390 | ||
|
|
256387cbbd | ||
|
|
f80071913d | ||
|
|
c05afe8bf6 | ||
|
|
95713e627b | ||
|
|
4184a4fe5d | ||
|
|
5933b6189e | ||
|
|
2d545688cb | ||
|
|
c3dee2271e | ||
|
|
93865f4431 | ||
|
|
be1c57b345 | ||
|
|
5d22f9b2cc | ||
|
|
1ea4398216 | ||
|
|
bb93ed8843 | ||
|
|
e2eed221e0 | ||
|
|
6719104cb3 | ||
|
|
d103345b77 | ||
|
|
ae99dc4a55 | ||
|
|
4658f616f1 | ||
|
|
48861cbf25 | ||
|
|
c82de5cfd0 | ||
|
|
64185b884d | ||
|
|
9bdc4350f9 | ||
|
|
81735c4dec | ||
|
|
53eab985fd | ||
|
|
e16d66a4c5 | ||
|
|
bc3aa30929 | ||
|
|
9d8edb6ead | ||
|
|
25ff55291a | ||
|
|
2a9ac48a72 | ||
|
|
925098534f | ||
|
|
277c704be8 | ||
|
|
046b2ed300 | ||
|
|
ef579daf1c | ||
|
|
e44785bcff | ||
|
|
72697f25f9 | ||
|
|
fa6067eee7 | ||
|
|
6879be005e | ||
|
|
52e93a608b | ||
|
|
bce5a4bd37 | ||
|
|
1dad620368 | ||
|
|
f09b968e27 | ||
|
|
7f81d6291d | ||
|
|
f48a776e99 | ||
|
|
3e63287fa2 | ||
|
|
828c8d2f23 | ||
|
|
d8c2f696b1 | ||
|
|
4f21628365 | ||
|
|
0521b595fe | ||
|
|
f0159a05ae | ||
|
|
4a1e7e361f | ||
|
|
b1f620a579 | ||
|
|
dfbcb5bf67 | ||
|
|
0677a16e75 | ||
|
|
968b507570 | ||
|
|
e773b26f5f | ||
|
|
54e4759791 | ||
|
|
df0e5d3539 | ||
|
|
32944666f4 | ||
|
|
b5e0d7afed | ||
|
|
4bb86dc8b8 | ||
|
|
93a5fb057e | ||
|
|
3c044fd4d0 | ||
|
|
b430c87b65 | ||
|
|
903644b628 | ||
|
|
d26be24cb3 | ||
|
|
949e7eb83f | ||
|
|
97bb455cc4 | ||
|
|
cdb5ff2133 | ||
|
|
b1aee93e2d | ||
|
|
667566e341 | ||
|
|
c51443bf5d | ||
|
|
ab4a3d2748 | ||
|
|
6d6a689557 | ||
|
|
16c2031d2a | ||
|
|
590b20f12e | ||
|
|
c82c0b3689 | ||
|
|
18d38d79e7 | ||
|
|
4113124ec4 | ||
|
|
8f6d0e03ac | ||
|
|
c48fd8925b | ||
|
|
66af983955 | ||
|
|
55b735086c | ||
|
|
4e64784749 | ||
|
|
3ee2ef0b42 | ||
|
|
eaa6fc8802 | ||
|
|
ef6bf61c5b | ||
|
|
5f5b589a7f | ||
|
|
82ae27841c | ||
|
|
8623d5a817 | ||
|
|
250c49c7bd | ||
|
|
7739c3e951 | ||
|
|
8a7f7931f4 | ||
|
|
6579e85a96 | ||
|
|
1195f5225e | ||
|
|
9b206a9831 | ||
|
|
dae1db73e9 | ||
|
|
d63f59d2fa | ||
|
|
bbf9cb0d2b | ||
|
|
a44b1d93c1 | ||
|
|
3dab930a75 | ||
|
|
939fad20f6 | ||
|
|
2e06ef8637 | ||
|
|
12ab14bc57 | ||
|
|
45000493e0 |
1365
.all-contributorsrc
Normal file
1365
.all-contributorsrc
Normal file
File diff suppressed because it is too large
Load Diff
45
.eslintrc.js
Normal file
45
.eslintrc.js
Normal file
@@ -0,0 +1,45 @@
|
||||
module.exports = {
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
sourceType: "module",
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
project: `./tsconfig.json`,
|
||||
},
|
||||
plugins: ["@typescript-eslint", "import", "unicorn"],
|
||||
extends: ["react-app"],
|
||||
rules: {
|
||||
"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
|
||||
"import/first": "off",
|
||||
"import/no-default-export": "error",
|
||||
"require-await": "error",
|
||||
"no-async-promise-executor": "error",
|
||||
"unicorn/filename-case": [
|
||||
"error",
|
||||
{
|
||||
case: "kebabCase",
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-floating-promises": "error",
|
||||
// note you must disable the base rule as it can report incorrect errors
|
||||
"no-use-before-define": "off",
|
||||
"@typescript-eslint/no-use-before-define": ["error"],
|
||||
// note you must disable the base rule as it can report incorrect errors
|
||||
"no-redeclare": "off",
|
||||
"@typescript-eslint/no-redeclare": ["error"],
|
||||
},
|
||||
ignorePatterns: ["packages/cli/", "packages/generator/templates", ".eslintrc.js"],
|
||||
overrides: [
|
||||
{
|
||||
files: ["examples/**", "packages/gui/**", "recipes/**"],
|
||||
rules: {
|
||||
"import/no-default-export": "off",
|
||||
"unicorn/filename-case": "off",
|
||||
"@typescript-eslint/no-floating-promises": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text=auto eol=lf
|
||||
11
.github/CODEOWNERS
vendored
Normal file
11
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
|
||||
|
||||
* @flybayer
|
||||
*.md @merelinguist
|
||||
|
||||
packages/server/**/* @ryardley
|
||||
packages/file-pipeline/**/* @ryardley
|
||||
packages/cli/**/* @aem
|
||||
packages/generator/**/* @aem
|
||||
packages/generator/templates**/* @flybayer
|
||||
packages/installer/**/* @aem
|
||||
4
.github/FUNDING.yml
vendored
Normal file
4
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
github: blitz-js
|
||||
custom: ["https://paypal.me/thebayers"]
|
||||
open_collective: blitzjs
|
||||
patreon: flybayer
|
||||
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Something is not working right. Or error messages are unclear.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
### What is the problem?
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
1.
|
||||
|
||||
### Versions
|
||||
|
||||
```
|
||||
output of `blitz --version --verbose`
|
||||
```
|
||||
|
||||
### Other
|
||||
|
||||
Please include applicable logs and screenshots that show your problem.
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Question or Discussion
|
||||
url: https://github.com/blitz-js/blitz/discussions/new
|
||||
about: Ask questions and discuss with other community members
|
||||
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Feature/change request
|
||||
about: Something new or better!
|
||||
title: ""
|
||||
labels: ""
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
### What do you want and why?
|
||||
|
||||
The more information the better!
|
||||
|
||||
### Possible implementation(s)
|
||||
|
||||
How might we do this?
|
||||
|
||||
### Additional context
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
10
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
Closes: ??
|
||||
|
||||
### What are the changes and their implications?
|
||||
|
||||
### Checklist
|
||||
|
||||
- [ ] Tests added for changes
|
||||
- [ ] PR submitted to [blitzjs.com](https://github.com/blitz-js/blitzjs.com) for any user facing changes
|
||||
|
||||
<!-- IMPORTANT: Make sure to check the "Allow edits from maintainers" box below this window -->
|
||||
18
.github/checkInstallTime.js
vendored
Executable file
18
.github/checkInstallTime.js
vendored
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require("fs")
|
||||
const yarnOut = fs.readFileSync(0, {encoding: "utf8"})
|
||||
|
||||
const [installTimeString] = /(?<=^Done in )\d+\.\d+(?=s\.$)/m.exec(yarnOut)
|
||||
const installTime = Number(installTimeString)
|
||||
|
||||
console.log(`Install time: ${installTime}s`)
|
||||
|
||||
if (installTime < 30) {
|
||||
console.log("We're below 30 secs. That's awesome!")
|
||||
} else if (installTime < 50) {
|
||||
console.log("We're below 50 secs. That's fine!")
|
||||
} else {
|
||||
console.log("We're above 50 secs. That's not great!")
|
||||
process.exit(1)
|
||||
}
|
||||
25
.github/workflows/compressed.yml
vendored
Normal file
25
.github/workflows/compressed.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Compressed Size
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master, canary]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node and Yarn
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "12.x"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn && yarn build
|
||||
env:
|
||||
CI: true
|
||||
- name: Count size
|
||||
uses: preactjs/compressed-size-action@v2
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
127
.github/workflows/main.yml
vendored
Normal file
127
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
name: Continuous Integration
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- canary
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- canary
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "12.16.1"
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: Cache node_modules
|
||||
id: yarn-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
**/node_modules
|
||||
/home/runner/.cache/Cypress
|
||||
C:\Users\runneradmin\AppData\Local\Cypress\Cache
|
||||
key: ${{ runner.os }}-yarn-v3-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-v3-
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
env:
|
||||
CI: true
|
||||
- name: yarn lint
|
||||
run: yarn lint
|
||||
env:
|
||||
CI: true
|
||||
build_and_test_pkgs:
|
||||
name: Build & Test Packages
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "12.16.1"
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: Cache node_modules
|
||||
id: yarn-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
/home/runner/.cache/Cypress
|
||||
C:\Users\runneradmin\AppData\Local\Cypress\Cache
|
||||
key: ${{ runner.os }}-yarn-v2-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-v2-
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
env:
|
||||
CI: true
|
||||
- name: Setup kernel to increase watchers
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
- name: Build packages
|
||||
run: yarn build
|
||||
env:
|
||||
CI: true
|
||||
- name: Test Blitz Packages
|
||||
run: yarn testonly:packages
|
||||
env:
|
||||
CI: true
|
||||
build_and_test_examples:
|
||||
name: Build & Test Examples
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "12.16.1"
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
- name: Cache node_modules
|
||||
id: yarn-cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
/home/runner/.cache/Cypress
|
||||
C:\Users\runneradmin\AppData\Local\Cypress\Cache
|
||||
key: ${{ runner.os }}-yarn-v2-${{ hashFiles('yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-v2-
|
||||
- name: Install dependencies
|
||||
run: yarn install --frozen-lockfile --silent
|
||||
env:
|
||||
CI: true
|
||||
- name: Setup kernel to increase watchers
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
- name: Build packages
|
||||
run: yarn build
|
||||
env:
|
||||
CI: true
|
||||
- name: Test examples
|
||||
run: yarn testonly:examples
|
||||
env:
|
||||
CI: true
|
||||
22
.gitignore
vendored
Normal file
22
.gitignore
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
.log
|
||||
.DS_Store
|
||||
.jest-*
|
||||
lib
|
||||
node_modules
|
||||
reports
|
||||
*.log
|
||||
.nyc_output
|
||||
**/coverage
|
||||
.yarn
|
||||
.yarnrc
|
||||
tsconfig.tsbuildinfo
|
||||
.blitz
|
||||
.next
|
||||
dist
|
||||
.now
|
||||
# local env files
|
||||
**/.env.local
|
||||
**/.env.*.local
|
||||
**/.envrc
|
||||
.blitz-*
|
||||
.blitz-cli-cache
|
||||
1
.node-version
Normal file
1
.node-version
Normal file
@@ -0,0 +1 @@
|
||||
12.16.1
|
||||
16
.npmignore
Normal file
16
.npmignore
Normal file
@@ -0,0 +1,16 @@
|
||||
.DS_Store
|
||||
.prettierrc
|
||||
.nyc_output
|
||||
.travis.yml
|
||||
coverage
|
||||
coverage.lcov
|
||||
bench
|
||||
docs
|
||||
src
|
||||
examples
|
||||
babel.config.js
|
||||
test
|
||||
CONTRIBUTING.md
|
||||
CODE_OF_CONDUCT.md
|
||||
*.ts
|
||||
!*.d.ts
|
||||
21
.prettierignore
Normal file
21
.prettierignore
Normal file
@@ -0,0 +1,21 @@
|
||||
**/migrations/**
|
||||
.blitz
|
||||
.next
|
||||
.log
|
||||
.DS_Store
|
||||
.jest-*
|
||||
lib
|
||||
node_modules
|
||||
reports
|
||||
*.log
|
||||
**/.env*
|
||||
.nyc_output
|
||||
**/coverage
|
||||
.yarn
|
||||
.yarnrc
|
||||
tsconfig.tsbuildinfo
|
||||
dist
|
||||
bin
|
||||
!packages/blitz/src/bin
|
||||
packages/generator/templates/**
|
||||
.github/ISSUE_TEMPLATE/bug_report.md
|
||||
3
CODE_OF_CONDUCT.md
Normal file
3
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# The Blitz Community Code of Conduct
|
||||
|
||||
[Read the Code of Conduct at Blitzjs.com](https://blitzjs.com/docs/code-of-conduct)
|
||||
3
CONTRIBUTING.md
Normal file
3
CONTRIBUTING.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Contributing
|
||||
|
||||
[Read the Contributing Guide at Blitzjs.com](https://blitzjs.com/docs/contributing)
|
||||
11
GOVERNANCE.md
Normal file
11
GOVERNANCE.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# Blitz.js Governance
|
||||
|
||||
_From Brandon Bayer (@flybayer), the creator:_
|
||||
|
||||
Currently at this very early stage it's basically a [BDFL situation](https://opensource.guide/leadership-and-governance/#what-are-some-of-the-common-governance-structures-for-open-source-projects), with me having the final say in decisions.
|
||||
|
||||
However we will move away from BDFL to something that looks more like Ember.js. It's extremely important to me (Brandon) that Blitz.js is a long-term, sustainable, and community-run project.
|
||||
|
||||
I would love some mentorship from people with experience in large open-source projects on making this transition.
|
||||
|
||||
Also, it's possible I will create one or more business around Blitz, perhaps similar to how Taylor Otwell has around Laravel, but Blitz itself will always remain a separate community-run project.
|
||||
1
MAINTAINERS.md
Normal file
1
MAINTAINERS.md
Normal file
@@ -0,0 +1 @@
|
||||
This document has moved here: https://blitzjs.com/docs/maintainers
|
||||
3
MANIFESTO.md
Normal file
3
MANIFESTO.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Manifesto
|
||||
|
||||
[The Manifesto has been moved to Blitzjs.com](https://blitzjs.com/docs/manifesto)
|
||||
124
MEETING_NOTES.md
Normal file
124
MEETING_NOTES.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# 2020-08-17 Blitz Contributor Call
|
||||
|
||||
- Attending: Brandon Bayer, Adam Markon, Kellen Mace, Myron Davis, Dwight Watson
|
||||
- Brandon:
|
||||
- Auth out, set up by default in canary release
|
||||
- Need to work on a potential CSRF bug
|
||||
- Next major release will include auth by default and allow you to choose your form library
|
||||
- Next auth features are email confirmation
|
||||
- After that, logging and plugins are next
|
||||
- Adam:
|
||||
- Overhauled the recipe infrastructure. Now using jscodeshift instead of recast
|
||||
- Added support for conditional JSX in templates
|
||||
- Going to work on custom templates next
|
||||
- Dwight
|
||||
- Has been opening issues for problems
|
||||
- Made a few PRs for some issues
|
||||
|
||||
# 2020-07-07 Blitz Contributor Call
|
||||
|
||||
- Attending: Brandon Bayer, Robert Rosenburg, Jeremy Liberman
|
||||
- Brandon:
|
||||
- Finishing up session managment code
|
||||
- Waiting for review of session managment code from Rishabh
|
||||
- Will be working on actual auth code (vs session management) like password hashing, password reset, social login, etc.
|
||||
- Benefits of our session managment vs rails
|
||||
- Don’t have to redirect to login page
|
||||
- Using top level error component that catches authentication errors
|
||||
- You can login from anywhere, during sign up
|
||||
- Robert:
|
||||
- Waiting on Kirstina’s website designs. Desktop design is finished, but she's working on mobile design
|
||||
- Code snippet / sandbox of blitz code for the website
|
||||
|
||||
# 2020-06-23 Blitz Contributor Call
|
||||
|
||||
- Attending: Brandon Bayer, Robert Rosenberg, Justin Hall, Adam Markon
|
||||
- Brandon:
|
||||
- Server side session management code is mostly set up. Still need to integrate client side of RPC calls to expose session information
|
||||
- Identity verification/Oauth integrations still need to be firmed up
|
||||
- Once auth is wrapped up we should be ready to start on plugins
|
||||
- Adam:
|
||||
- Been experimenting with smart page generation based on the current schema model
|
||||
- MDX installer recipes
|
||||
- Robert:
|
||||
- Waiting on designs from Kristina
|
||||
- Prism component from theme ui customization? If not try and grab source code from docusaurus line highlighting component
|
||||
- Justin:
|
||||
- Updated the tutorial
|
||||
- Helped with various bug fixes
|
||||
|
||||
# 2020-06-17 Blitz Contributor Call
|
||||
|
||||
- Attending: Brandon Bayer, Fran Zekan, Sigurd Wahl
|
||||
- Brandon:
|
||||
- Spent the past week implementing HTTP middlware which is now released!
|
||||
- Now working on implementing session management!
|
||||
- Fran:
|
||||
- Finishing up the PR for adding `blitz db seed`
|
||||
- Sigurd:
|
||||
- New to the community, slowly learning the codebase
|
||||
- Exicited to get a first PR in here sometime soon :)
|
||||
|
||||
# 2020-06-09 Blitz Contributor Call
|
||||
|
||||
- Attending: Brandon Bayer, Rudi Yardley, Fran Zekan, Adam Markon, Robert Rosenberg, Kristina Matuska
|
||||
- Brandon:
|
||||
- blitzjs.com published, docs + marketing site v0.1 live
|
||||
- For now most of the docs copied from react-query and Next, we should eventually clean them up so they're stylistically similar to ours, but really easy to start
|
||||
- HTTP middleware is almost done, just fixing a few edge cases
|
||||
- Authentication is up next after that, translating pseudocode into actual code
|
||||
- Kristina:
|
||||
- Homepage design mostly wrapped up right now, have to finish up mobile and light mode and then ready to move on to the rest of the docs
|
||||
- Syntax highlighting, we can customize colors
|
||||
- Sidebar inspiration from tailwindcss
|
||||
- Robert:
|
||||
- Decided to wait to convert existing components to theme UI until the final design is done
|
||||
- More docs content:
|
||||
- More guides
|
||||
- Improve the tutorial to incorporate relationship generation
|
||||
- Add branches for canary and master
|
||||
- If you add a feature you can add your documentation to the canary branch
|
||||
- Adam:
|
||||
- blitz generate model finished!
|
||||
- Installer rewrite complete
|
||||
- At similar place to what Gatsby has for installing stuff
|
||||
- Next up:
|
||||
- Support gatsby MDX recipes
|
||||
- Make all code generators aware of actual model attributes
|
||||
- Fran:
|
||||
- Working on a package for getting the blitz config anywhere - getConfig()
|
||||
- Prevent app from "warming" the server when deployed as server rather than serverless
|
||||
- Testing examples - e2e with cypress and unit tests with Jest so we can link to a testing setup in the docs/getting started guide
|
||||
- Rudi:
|
||||
- Extracted out the @blitzjs/file-pipeline (previously synchronizer)
|
||||
- Extracted out the @blitzjs/display package
|
||||
- Working on various Next.js compatibility issues
|
||||
- Debugging a bug in blitz start where it gets stuck at \_manifest.json
|
||||
|
||||
# 2020-05-26 Blitz Contributor Call
|
||||
|
||||
- Attending: Brandon Bayer, Robert Rosenberg, Adam Markon, Simon Debbarma
|
||||
- Brandon:
|
||||
- Kitze livestream last week went great — recording on youtube
|
||||
- Codebase walkthrough yesterday went great — recording on youtube
|
||||
- Website overhaul, installed Theme UI
|
||||
- Adam:
|
||||
- Opened PR for Prisma model generation from the CLI
|
||||
- Working on Installer stuff and prepping for integration with Gatsby recipes
|
||||
- Simon
|
||||
- Working on custom illustrations for the web
|
||||
- Robert
|
||||
- Misc work on website
|
||||
- Website
|
||||
- Most website components are owned by us now instead of docusaurus, we'll need to be weary of api updates and any other important component updates
|
||||
- Make sidebar like tailwind docs sidebar
|
||||
- Dark theme needs to be fixed
|
||||
- Theme switcher inconsistent
|
||||
- Live code sandbox examples
|
||||
- Code comparison between blitz and rails
|
||||
- Auth
|
||||
- Rishabh continuing to work on pseudo code for the session management library
|
||||
- Brandon planning to build http middleware support this week
|
||||
- CLI
|
||||
- Adam working on new features, including generating prisma models and making existing templates aware of actual model attributes
|
||||
- Plugin ideas / discussion once recipes are farther along. Will post an RFC for plugins at some point
|
||||
414
README.md
414
README.md
@@ -1,2 +1,412 @@
|
||||
# blitz
|
||||
Framework for building monolithic, full-stack, serverless React apps with zero data-fetching and zero client-side state management
|
||||
[](https://blitzjs.com)
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<p align="center">
|
||||
<a aria-label="Join our Slack Community" href="https://slack.blitzjs.com">
|
||||
<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-142-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">
|
||||
</a>
|
||||
<a aria-label="NPM version" href="https://www.npmjs.com/package/blitz">
|
||||
<img alt="" src="https://img.shields.io/npm/v/blitz.svg?style=for-the-badge&labelColor=000000&color=E65528">
|
||||
</a>
|
||||
</p>
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<br>
|
||||
|
||||
<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">Makes you far more productive than you ever dreamed was possible 😉</h3>
|
||||
<h3 align="center"><a href="https://blitzjs.com" 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.
|
||||
|
||||
Includes everything you need for production apps. **Everything end-to-end from the database to the frontend.**
|
||||
|
||||
Blitz brings back the **simplicity and conventions** of server-rendered frameworks like Ruby on Rails while preserving everything we love about React and client-side rendering!
|
||||
|
||||
<br>
|
||||
|
||||
### Quick Start
|
||||
|
||||
You need Node.js 12 or newer
|
||||
|
||||
#### Install Blitz
|
||||
|
||||
Run `npm install -g blitz` or `yarn global add blitz`
|
||||
|
||||
_You can alternatively use [`npx`](https://www.npmjs.com/package/npx)_
|
||||
|
||||
#### Create a New App
|
||||
|
||||
1. `blitz new myAppName`
|
||||
2. `cd myAppName`
|
||||
3. `blitz start`
|
||||
4. View your baby app at http://localhost:3000
|
||||
|
||||
<br><br>
|
||||
|
||||

|
||||
|
||||
<br><br>
|
||||
|
||||
**Features:**<br>
|
||||
⚡️ Built on Next.js<br>
|
||||
⚡️ Don't have to build an API for client-side rendering<br>
|
||||
⚡️ Client-side rendering, Server-side rendering, and fully static pages all in the same app<br>
|
||||
⚡️ Full Typescript support with static, end-to-end typing (no code generation step needed like with GraphQL)<br>
|
||||
⚡️ React Concurrent Mode enabled<br>
|
||||
⚡️ Database/ORM agnostic, but Prisma 2 is default<br>
|
||||
⚡️ CLI with code scaffolding, Rails-style console REPL, etc<br>
|
||||
⚡️ GraphQL Ready<br>
|
||||
⚡️ Deploy serverless or serverful<br>
|
||||
⚡️ Highly secure authentication <br>
|
||||
⚡️ Authorization you can use on both server and client<br>
|
||||
⚡️ Recipes for easily adding libraries like Tailwind, CSS-in-JS, etc.<br>
|
||||
|
||||
**Other key features coming:**<br>
|
||||
⚡️ Model validation you can use on both server and client<br>
|
||||
⚡️ React native support<br>
|
||||
⚡️ GUI so you don't have to use the CLI<br>
|
||||
|
||||
<br>
|
||||
|
||||
### The Foundational Principles
|
||||
|
||||
1. Fullstack & Monolithic
|
||||
2. API Not Required
|
||||
3. Convention over Configuration
|
||||
4. Loose Opinions
|
||||
5. Easy to Start, Easy to Scale
|
||||
6. Stability
|
||||
7. Community over Code
|
||||
|
||||
[The Blitz Manifesto](https://blitzjs.com/docs/manifesto) explains these principles in detail.
|
||||
|
||||
<br>
|
||||
|
||||
### What is Blitz Designed For?
|
||||
|
||||
Blitz is designed for tiny to large database-backed applications that have one or more graphical user interfaces.
|
||||
|
||||
While we currently only support web, we are pursuing the dream of a single monolithic application that runs on web and mobile with maximum code sharing and minimal boilerplate.
|
||||
|
||||
<br>
|
||||
|
||||
## Welcome to the Blitz Community 👋
|
||||
|
||||
The Blitz community is warm, safe, diverse, inclusive, and fun! LGBTQ+, women, and minorities are especially welcome. Please read our [Code of Conduct](https://blitzjs.com/docs/code-of-conduct).
|
||||
|
||||
[Join our Slack Community](https://slack.blitzjs.com) where we help each other build Blitz apps. It's also where we collaborate on building Blitz itself.
|
||||
|
||||
For questions and longer form discussions, [post in our forum](https://github.com/blitz-js/blitz/discussions).
|
||||
|
||||
There's still a lot of work to do, so you are especially invited to join us in building Blitz! A good place to start is [The Contributing Guide](https://blitzjs.com/docs/contributing).
|
||||
|
||||
<br>
|
||||
|
||||
## Financial Contributors
|
||||
|
||||
Your financial contributions help ensure Blitz continues to be developed and maintained! We have monthly sponsorship options starting at $5/month.
|
||||
|
||||
👉 View options and contribute at [GitHub Sponsors](https://github.com/sponsors/blitz-js), [PayPal](https://paypal.me/thebayers), or [Open Collective](https://opencollective.com/blitzjs)
|
||||
|
||||
### 🌱 Seedling Sponsors
|
||||
|
||||
<a aria-label="React Bricks" href="https://reactbricks.com/?utm_source=blitzjs&utm_medium=sponsorship&utm_campaign=blitzjs_sponsorship">
|
||||
<img alt="" src="https://reactbricks.com/reactbricks_icon.svg" width="30px">
|
||||
</a>
|
||||
|
||||
### 🥉 Bronze Sponsors
|
||||
|
||||
<a aria-label="Your Company" href="#">
|
||||
<img alt="" src="https://dummyimage.com/1000x330/efe8ff/000000.png&text=Your+Logo+Here" width="100px">
|
||||
</a>
|
||||
|
||||
### 🥈 Silver Sponsors
|
||||
|
||||
<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="200px">
|
||||
</a>
|
||||
|
||||
### 🏆 Gold Sponsors
|
||||
|
||||
<a aria-label="Your Company" href="#">
|
||||
<img alt="" src="https://dummyimage.com/1000x330/efe8ff/000000.png&text=Your+Logo+Here" width="300px">
|
||||
</a>
|
||||
|
||||
### 💎 Diamond Sponsors
|
||||
|
||||
<a aria-label="Your Company" href="#">
|
||||
<img alt="" src="https://dummyimage.com/1000x330/efe8ff/000000.png&text=Your+Logo+Here" width="400px">
|
||||
</a>
|
||||
|
||||
<br>
|
||||
|
||||
## Core Team ✨
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
<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="https://medium.com/@ryardley"><img src="https://avatars0.githubusercontent.com/u/1256409?v=4" width="100px;" alt=""/><br /><sub><b>Rudi Yardley</b></sub></a><br />Node.js Wizard</td>
|
||||
<td align="center"><a href="https://merelinguist.now.sh"><img src="https://avatars3.githubusercontent.com/u/24858006?v=4" width="100px;" alt=""/><br /><sub><b>Dylan Brookes</b></sub></a><br />Friendly Generalist</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## Maintainers (Level 2) ✨
|
||||
|
||||
_Code ownership, pull request approvals and merging, etc_ (see [MAINTAINERS.md](./MAINTAINERS.md))
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/aem"><img src="https://avatars0.githubusercontent.com/u/1909883?v=4" width="100px;" alt=""/><br /><sub><b>Adam Markon</b></sub></a><br />CLI</td>
|
||||
<td align="center"><a href="http://robdrosenberg.com"><img src="https://avatars0.githubusercontent.com/u/20813991?v=4" width="100px;" alt=""/><br /><sub><b>Robert Rosenberg</b></sub></a><br />Website/Docs</td>
|
||||
<td align="center"><a href="http://simonknott.de"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4" width="100px;" alt=""/><br /><sub><b>Simon Knott</b></sub></a><br />SuperJSON</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<br>
|
||||
|
||||
## Maintainers (Level 1) ✨
|
||||
|
||||
_Issue triage, pull request triage, community encouragement and moderation, etc_ (see [MAINTAINERS.md](./MAINTAINERS.md))
|
||||
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/LoriKarikari"><img src="https://avatars1.githubusercontent.com/u/7902980?v=4" width="100px;" alt=""/><br /><sub><b>Lori Karikari</b></sub></a></td>
|
||||
<td align="center"><a href="https://corey-brown.com"><img src="https://avatars1.githubusercontent.com/u/12791148?v=4" width="100px;" alt=""/><br /><sub><b>Corey Brown</b></sub></a></td>
|
||||
<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="http://jagascript.com"><img src="https://avatars0.githubusercontent.com/u/4562878?v=4" width="100px;" alt=""/><br /><sub><b>Jaga Santagostino</b></sub></a></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://twitter.com/sandulat"><img src="https://avatars2.githubusercontent.com/u/7345874?v=4" width="100px;" alt=""/><br /><sub><b>Alexandru Stratulat</b></sub></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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/jdavenport97"><img src="https://avatars2.githubusercontent.com/u/1329874?v=4" width="100px;" alt=""/><br /><sub><b>Jamie Davenport</b></sub></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## Contributors ✨
|
||||
|
||||
Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<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 /><a href="https://github.com/blitz-js/blitz/commits?author=flybayer" title="Code">💻</a> <a href="#content-flybayer" title="Content">🖋</a> <a href="#ideas-flybayer" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aflybayer" title="Reviewed Pull Requests">👀</a></td>
|
||||
<td align="center"><a href="https://medium.com/@ryardley"><img src="https://avatars0.githubusercontent.com/u/1256409?v=4" width="100px;" alt=""/><br /><sub><b>Rudi Yardley</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ryardley" title="Code">💻</a> <a href="#ideas-ryardley" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aryardley" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=ryardley" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://merelinguist.me"><img src="https://avatars3.githubusercontent.com/u/24858006?v=4" width="100px;" alt=""/><br /><sub><b>Dylan Brookes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=merelinguist" title="Code">💻</a> <a href="#ideas-merelinguist" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Amerelinguist" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=merelinguist" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=merelinguist" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/aem"><img src="https://avatars0.githubusercontent.com/u/1909883?v=4" width="100px;" alt=""/><br /><sub><b>Adam Markon</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aem" title="Code">💻</a> <a href="#ideas-aem" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aaem" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=aem" title="Tests">⚠️</a> <a href="#maintenance-aem" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://corey-brown.com"><img src="https://avatars1.githubusercontent.com/u/12791148?v=4" width="100px;" alt=""/><br /><sub><b>Corey Brown</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=coreybrown89" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Acoreybrown89" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-coreybrown89" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/LoriKarikari"><img src="https://avatars1.githubusercontent.com/u/7902980?v=4" width="100px;" alt=""/><br /><sub><b>Lori Karikari</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=LoriKarikari" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3ALoriKarikari" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-LoriKarikari" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=LoriKarikari" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/GeggsElias"><img src="https://avatars3.githubusercontent.com/u/22719177?v=4" width="100px;" alt=""/><br /><sub><b>Elias Johansson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=eliasjohansson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aeliasjohansson" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-eliasjohansson" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://fabulas.io"><img src="https://avatars1.githubusercontent.com/u/14793389?v=4" width="100px;" alt=""/><br /><sub><b>Michael Edelman </b></sub></a><br /><a href="#infra-medelman17" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/blitz-js/blitz/commits?author=medelman17" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.geistinteractive.com"><img src="https://avatars2.githubusercontent.com/u/316792?v=4" width="100px;" alt=""/><br /><sub><b>Todd Geist</b></sub></a><br /><a href="#financial-toddgeist" title="Financial">💵</a> <a href="https://github.com/blitz-js/blitz/commits?author=toddgeist" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://robdrosenberg.com"><img src="https://avatars0.githubusercontent.com/u/20813991?v=4" width="100px;" alt=""/><br /><sub><b>Robert Rosenberg</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robdrosenberg" title="Code">💻</a> <a href="#maintenance-robdrosenberg" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=robdrosenberg" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/quirk0o"><img src="https://avatars3.githubusercontent.com/u/5123725?v=4" width="100px;" alt=""/><br /><sub><b>Beata Obrok</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=quirk0o" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/tsawan"><img src="https://avatars3.githubusercontent.com/u/3263082?v=4" width="100px;" alt=""/><br /><sub><b>Tahir Awan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tsawan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://raluce.com"><img src="https://avatars1.githubusercontent.com/u/2454632?v=4" width="100px;" alt=""/><br /><sub><b>Camilo Gonzalez</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=camilo86" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://da.nielkempner.com"><img src="https://avatars3.githubusercontent.com/u/2532112?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Kempner</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dkempner" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://gielcobben.com"><img src="https://avatars0.githubusercontent.com/u/2663212?v=4" width="100px;" alt=""/><br /><sub><b>Giel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gielcobben" title="Code">💻</a></td>
|
||||
<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></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MrLeebo" title="Code">💻</a> <a href="#maintenance-MrLeebo" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=MrLeebo" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://jimthedev.com"><img src="https://avatars0.githubusercontent.com/u/108938?v=4" width="100px;" alt=""/><br /><sub><b>Jim Cummins</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jimthedev" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kristinamatuska.com/"><img src="https://media-exp1.licdn.com/dms/image/C5603AQHVPAjV21gw9g/profile-displayphoto-shrink_200_200/0?e=1591228800&v=beta&t=0MlbmiYhNvGv1xjLD_fOhOFjVDZ7ltNwfGNeJ4DHedQ" width="100px;" alt=""/><br /><sub><b>Kristina Matuška</b></sub></a><br /><a href="#design" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/jasonblalock"><img src="https://avatars0.githubusercontent.com/u/5899929?v=4" width="100px;" alt=""/><br /><sub><b>Jason Blalock</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jasonblalock" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/aej11a"><img src="https://avatars2.githubusercontent.com/u/10066422?v=4" width="100px;" alt=""/><br /><sub><b>aej11a</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aej11a" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/marcoseoane"><img src="https://avatars0.githubusercontent.com/u/28088807?v=4" width="100px;" alt=""/><br /><sub><b>marcoseoane</b></sub></a><br /><a href="#ideas-marcoseoane" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/rishabhpoddar"><img src="https://avatars2.githubusercontent.com/u/2976287?v=4" width="100px;" alt=""/><br /><sub><b>Rishabh Poddar</b></sub></a><br /><a href="#ideas-rishabhpoddar" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/lorenzorapetti"><img src="https://avatars1.githubusercontent.com/u/2632174?v=4" width="100px;" alt=""/><br /><sub><b>Lorenzo Rapetti</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lorenzorapetti" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/wKovacs64"><img src="https://avatars1.githubusercontent.com/u/1288694?v=4" width="100px;" alt=""/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=wKovacs64" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=wKovacs64" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/sijad"><img src="https://avatars3.githubusercontent.com/u/7693001?v=4" width="100px;" alt=""/><br /><sub><b>Sajjad Hashemian</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sijad" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ETLopes"><img src="https://avatars3.githubusercontent.com/u/34959471?v=4" width="100px;" alt=""/><br /><sub><b>Eduardo Lopes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ETLopes" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mattleff"><img src="https://avatars0.githubusercontent.com/u/120155?v=4" width="100px;" alt=""/><br /><sub><b>Matthew Leffler</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mattleff" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://hew.tools"><img src="https://avatars0.githubusercontent.com/u/3103241?v=4" width="100px;" alt=""/><br /><sub><b>Matt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hew" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/sonnypgs"><img src="https://avatars3.githubusercontent.com/u/1431300?v=4" 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" 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="http://twitter.com/JanBaykara"><img src="https://avatars2.githubusercontent.com/u/237556?v=4" 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" 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" 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>
|
||||
<td align="center"><a href="https://github.com/jclancy93"><img src="https://avatars2.githubusercontent.com/u/7850202?v=4" width="100px;" alt=""/><br /><sub><b>Jack Clancy</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jclancy93" title="Code">💻</a> <a href="#maintenance-jclancy93" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/ntgussoni"><img src="https://avatars0.githubusercontent.com/u/10161067?v=4" width="100px;" alt=""/><br /><sub><b>Nicolas Torres</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Antgussoni" title="Reviewed Pull Requests">👀</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://simonknott.de"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4" width="100px;" alt=""/><br /><sub><b>Simon Knott</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Tests">⚠️</a> <a href="#maintenance-Skn0tt" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="http://jagascript.com"><img src="https://avatars0.githubusercontent.com/u/4562878?v=4" width="100px;" alt=""/><br /><sub><b>Jaga Santagostino</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kandros" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=kandros" title="Documentation">📖</a> <a href="#maintenance-kandros" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="http://www.joaoportela.com"><img src="https://avatars0.githubusercontent.com/u/1010018?v=4" width="100px;" alt=""/><br /><sub><b>João Portela</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jportela" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://dajin.dev"><img src="https://avatars0.githubusercontent.com/u/7122182?v=4" width="100px;" alt=""/><br /><sub><b>Da-Jin Chu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dajinchu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://shinyaigeek.dev/"><img src="https://avatars1.githubusercontent.com/u/42742053?v=4" width="100px;" alt=""/><br /><sub><b>Shinobu Hayashi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Shinyaigeek" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://karankiri.com"><img src="https://avatars2.githubusercontent.com/u/19989161?v=4" width="100px;" alt=""/><br /><sub><b>Karan Kiri</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=karankiri" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/fullmetalengineer"><img src="https://avatars2.githubusercontent.com/u/5294903?v=4" width="100px;" alt=""/><br /><sub><b>Alan Long</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fullmetalengineer" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://codingsh.xyz"><img src="https://avatars2.githubusercontent.com/u/57037080?v=4" width="100px;" alt=""/><br /><sub><b>codingsh</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=developerfred" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://twitter.com/peaonunes"><img src="https://avatars0.githubusercontent.com/u/3356720?v=4" width="100px;" alt=""/><br /><sub><b>Rafael Nunes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Apeaonunes" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=peaonunes" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://simonpeterdebbarma.com"><img src="https://avatars3.githubusercontent.com/u/31207418?v=4" width="100px;" alt=""/><br /><sub><b>Simon Debbarma</b></sub></a><br /><a href="#design-0ww" title="Design">🎨</a> <a href="#maintenance-0ww" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=0ww" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/0xflotus"><img src="https://avatars3.githubusercontent.com/u/26602940?v=4" width="100px;" alt=""/><br /><sub><b>0xflotus</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=0xflotus" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=0xflotus" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://dev.to/tmns"><img src="https://avatars3.githubusercontent.com/u/35785003?v=4" width="100px;" alt=""/><br /><sub><b>tmns</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tmns" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=tmns" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://jruharris.com"><img src="https://avatars1.githubusercontent.com/u/8636691?v=4" width="100px;" alt=""/><br /><sub><b>Jru Harris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=harris1717" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/ivandevp"><img src="https://avatars3.githubusercontent.com/u/9284690?v=4" width="100px;" alt=""/><br /><sub><b>Ivan Medina</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ivandevp" title="Code">💻</a> <a href="#maintenance-ivandevp" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.dwightwatson.com"><img src="https://avatars3.githubusercontent.com/u/1100408?v=4" width="100px;" alt=""/><br /><sub><b>Dwight Watson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dwightwatson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dwightwatson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://is2ei.com/"><img src="https://avatars3.githubusercontent.com/u/3948353?v=4" width="100px;" alt=""/><br /><sub><b>Horie Issei</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=is2ei" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/lednhatkhanh"><img src="https://avatars2.githubusercontent.com/u/9303093?v=4" width="100px;" alt=""/><br /><sub><b>Nhat Khanh</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lednhatkhanh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://builtforfifty.com"><img src="https://avatars1.githubusercontent.com/u/19371989?v=4" width="100px;" alt=""/><br /><sub><b>Abu Uzayr</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=abuuzayr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nabi009"><img src="https://avatars0.githubusercontent.com/u/3170831?v=4" width="100px;" alt=""/><br /><sub><b>Nabiullah elham</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nabi009" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://lachlanjc.com"><img src="https://avatars1.githubusercontent.com/u/5074763?v=4" width="100px;" alt=""/><br /><sub><b>Lachlan Campbell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lachlanjc" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://enzoferey.com"><img src="https://avatars1.githubusercontent.com/u/10673347?v=4" width="100px;" alt=""/><br /><sub><b>Enzo Ferey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=enzoferey" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/pgrimaud"><img src="https://avatars1.githubusercontent.com/u/1866496?v=4" width="100px;" alt=""/><br /><sub><b>Pierre Grimaud</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pgrimaud" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://pixelmord.github.io"><img src="https://avatars2.githubusercontent.com/u/224168?v=4" width="100px;" alt=""/><br /><sub><b>Andreas Adam</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pixelmord" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://kevo.dev"><img src="https://avatars3.githubusercontent.com/u/15717067?v=4" width="100px;" alt=""/><br /><sub><b>Kevin Tovar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kevotovar" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://anteprimorac.com.hr"><img src="https://avatars0.githubusercontent.com/u/972083?v=4" 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" 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" 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" 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>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://ramonmorcillo.com"><img src="https://avatars3.githubusercontent.com/u/31936665?v=4" 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>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/gregory-vasquez-96413b184/"><img src="https://avatars1.githubusercontent.com/u/36422346?v=4" width="100px;" alt=""/><br /><sub><b>gvasquez11</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gvasquez11" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/josemiguelo"><img src="https://avatars1.githubusercontent.com/u/15330034?v=4" width="100px;" alt=""/><br /><sub><b> José Miguel Ochoa</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=josemiguelo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/osirvent"><img src="https://avatars2.githubusercontent.com/u/5927133?v=4" width="100px;" alt=""/><br /><sub><b>Oscar Sirvent</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=osirvent" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=osirvent" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/donni106"><img src="https://avatars0.githubusercontent.com/u/1942953?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Molnar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=donni106" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=donni106" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/exclipy"><img src="https://avatars1.githubusercontent.com/u/508799?v=4" width="100px;" alt=""/><br /><sub><b>Kevin Wu Won</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=exclipy" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/tehnuge"><img src="https://avatars1.githubusercontent.com/u/1928236?v=4" width="100px;" alt=""/><br /><sub><b>John Duong</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tehnuge" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://noahfleischmann.com"><img src="https://avatars0.githubusercontent.com/u/23707137?v=4" width="100px;" alt=""/><br /><sub><b>Noah Fleischmann</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fnoah" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/toshi1127"><img src="https://avatars3.githubusercontent.com/u/32378535?v=4" width="100px;" alt=""/><br /><sub><b>Matsumoto Toshi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=toshi1127" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=toshi1127" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/simonedelmann"><img src="https://avatars2.githubusercontent.com/u/2821076?v=4" width="100px;" alt=""/><br /><sub><b>Simon Edelmann</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=simonedelmann" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://shaun.church"><img src="https://avatars3.githubusercontent.com/u/571764?v=4" width="100px;" alt=""/><br /><sub><b>Shaun Church</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=shaunchurch" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=shaunchurch" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://styfle.dev"><img src="https://avatars1.githubusercontent.com/u/229881?v=4" width="100px;" alt=""/><br /><sub><b>Steven</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=styfle" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/SigurdMW"><img src="https://avatars3.githubusercontent.com/u/6359003?v=4" width="100px;" alt=""/><br /><sub><b>Sigurd Moland Wahl</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=SigurdMW" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://brianandrews.dev/"><img src="https://avatars1.githubusercontent.com/u/6384100?v=4" width="100px;" alt=""/><br /><sub><b>Brian Andrews</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sbardian" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://garrisonsnelling.com"><img src="https://avatars0.githubusercontent.com/u/5100597?v=4" width="100px;" alt=""/><br /><sub><b>Garrison Snelling</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=garrisons" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/tylangesmith"><img src="https://avatars1.githubusercontent.com/u/22609577?v=4" width="100px;" alt=""/><br /><sub><b>Ty Lange-Smith</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tylangesmith" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://rubenmoya.dev"><img src="https://avatars3.githubusercontent.com/u/905225?v=4" width="100px;" alt=""/><br /><sub><b>Rubén Moya</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rubenmoya" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=rubenmoya" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/robertgrzonka"><img src="https://avatars0.githubusercontent.com/u/35585466?v=4" width="100px;" alt=""/><br /><sub><b>robertgrzonka</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robertgrzonka" title="Code">💻</a> <a href="#infra-robertgrzonka" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/agoxlea"><img src="https://avatars3.githubusercontent.com/u/1240841?v=4" width="100px;" alt=""/><br /><sub><b>Alex Orr</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=agoxlea" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://christse.io"><img src="https://avatars1.githubusercontent.com/u/250450?v=4" width="100px;" alt=""/><br /><sub><b>Chris Tse</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chris-tse" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://twitter.com/nettofarah"><img src="https://avatars1.githubusercontent.com/u/270688?v=4" width="100px;" alt=""/><br /><sub><b>Netto Farah</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nettofarah" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/rohanjulka19"><img src="https://avatars0.githubusercontent.com/u/19673968?v=4" width="100px;" alt=""/><br /><sub><b>Rohan Julka</b></sub></a><br /><a href="#infra-rohanjulka19" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://www.ivansantos.me"><img src="https://avatars3.githubusercontent.com/u/301291?v=4" width="100px;" alt=""/><br /><sub><b>Ivan Santos</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pragmaticivan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://able.bio"><img src="https://avatars0.githubusercontent.com/u/12991390?v=4" width="100px;" alt=""/><br /><sub><b>Soumyajit Pathak</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=drenther" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.sebastiankurpiel.com"><img src="https://avatars2.githubusercontent.com/u/16307737?v=4" width="100px;" alt=""/><br /><sub><b>Sebastian Kurpiel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=SebastianKurp" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/scisteffan"><img src="https://avatars2.githubusercontent.com/u/2676185?v=4" width="100px;" alt=""/><br /><sub><b>Steffan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=scisteffan" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=scisteffan" title="Documentation">📖</a> <a href="#financial-scisteffan" title="Financial">💵</a></td>
|
||||
<td align="center"><a href="https://github.com/kripod"><img src="https://avatars3.githubusercontent.com/u/14854048?v=4" width="100px;" alt=""/><br /><sub><b>Kristóf Poduszló</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kripod" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Weilbyte"><img src="https://avatars1.githubusercontent.com/u/43392677?v=4" width="100px;" alt=""/><br /><sub><b>Weilbyte</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Weilbyte" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Weilbyte" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://ricardotrejos.tech"><img src="https://avatars1.githubusercontent.com/u/8602086?v=4" width="100px;" alt=""/><br /><sub><b>Ricardo Trejos</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cardotrejos" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=cardotrejos" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://gkaragkiaouris.tech/"><img src="https://avatars0.githubusercontent.com/u/8822835?v=4" width="100px;" alt=""/><br /><sub><b>George Karagkiaouris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=karaggeorge" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=karaggeorge" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/brady-pascoe-3bba6b13a/"><img src="https://avatars0.githubusercontent.com/u/18705892?v=4" width="100px;" alt=""/><br /><sub><b>Brady Pascoe</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bpas247" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.yeahcoach.com"><img src="https://avatars1.githubusercontent.com/u/761766?v=4" width="100px;" alt=""/><br /><sub><b>Jirka Svoboda</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=svobik7" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/alan2207"><img src="https://avatars3.githubusercontent.com/u/12713315?v=4" width="100px;" alt=""/><br /><sub><b>Alan Alickovic</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=alan2207" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=alan2207" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://yngve.hoiseth.net"><img src="https://avatars0.githubusercontent.com/u/8469540?v=4" width="100px;" alt=""/><br /><sub><b>Yngve Høiseth</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=yhoiseth" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/bruno_crosier"><img src="https://avatars1.githubusercontent.com/u/18399089?v=4" width="100px;" alt=""/><br /><sub><b>Bruno Crosier</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=brunocrosier" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/jschepmans"><img src="https://avatars2.githubusercontent.com/u/5782977?v=4" 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" 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://github.com/clgeoio"><img src="https://avatars2.githubusercontent.com/u/37571416?v=4" 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" 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" 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>
|
||||
<td align="center"><a href="https://github.com/sirmyron"><img src="https://avatars2.githubusercontent.com/u/1430136?v=4" width="100px;" alt=""/><br /><sub><b>sirmyron</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sirmyron" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/engelkes-finstreet"><img src="https://avatars1.githubusercontent.com/u/36962022?v=4" width="100px;" alt=""/><br /><sub><b>engelkes-finstreet</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=engelkes-finstreet" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=engelkes-finstreet" title="Code">💻</a> <a href="#maintenance-engelkes-finstreet" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://twitter.com/pixelscommander"><img src="https://avatars2.githubusercontent.com/u/810671?v=4" width="100px;" alt=""/><br /><sub><b>Denis Radin</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3APixelsCommander" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=PixelsCommander" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=PixelsCommander" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/xiaoyu-tamu"><img src="https://avatars3.githubusercontent.com/u/33362998?v=4" width="100px;" alt=""/><br /><sub><b>Michael Li</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=xiaoyu-tamu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/yuta0801"><img src="https://avatars2.githubusercontent.com/u/21266306?v=4" width="100px;" alt=""/><br /><sub><b>yuta0801</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=yuta0801" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Obii-bit"><img src="https://avatars2.githubusercontent.com/u/67339820?v=4" width="100px;" alt=""/><br /><sub><b>Obadja Ris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Obii-bit" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://jfelix.info"><img src="https://avatars2.githubusercontent.com/u/21092519?v=4" width="100px;" alt=""/><br /><sub><b>Jose Felix </b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=JoseRFelix" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/johncantrell97"><img src="https://avatars3.githubusercontent.com/u/41305919?v=4" width="100px;" alt=""/><br /><sub><b>John Cantrell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=johncantrell97" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kwuang.me"><img src="https://avatars1.githubusercontent.com/u/10319942?v=4" width="100px;" alt=""/><br /><sub><b>Kwuang Tang</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cktang88" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/johnletey"><img src="https://avatars1.githubusercontent.com/u/62398724?v=4" width="100px;" alt=""/><br /><sub><b>John Letey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=johnletey" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ditorojuan"><img src="https://avatars0.githubusercontent.com/u/22530892?v=4" width="100px;" alt=""/><br /><sub><b>Juan Di Toro</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ditorojuan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/taylorcjohnson"><img src="https://avatars0.githubusercontent.com/u/10552296?v=4" width="100px;" alt=""/><br /><sub><b>Taylor Johnson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=taylorcjohnson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=taylorcjohnson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/tsriram"><img src="https://avatars3.githubusercontent.com/u/450559?v=4" width="100px;" alt=""/><br /><sub><b>Sriram Thiagarajan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tsriram" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://sergiodxa.com"><img src="https://avatars2.githubusercontent.com/u/1312018?v=4" width="100px;" alt=""/><br /><sub><b>Sergio Xalambrí</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sergiodxa" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/doeixd"><img src="https://avatars3.githubusercontent.com/u/13461122?v=4" width="100px;" alt=""/><br /><sub><b>Patrick G</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doeixd" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://avinash.com.np"><img src="https://avatars3.githubusercontent.com/u/513457?v=4" width="100px;" alt=""/><br /><sub><b>अभिनाश (Avinash)</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hardfire" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://enricoschaaf.com"><img src="https://avatars1.githubusercontent.com/u/54645197?v=4" width="100px;" alt=""/><br /><sub><b>Enrico Schaaf</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=enricoschaaf" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kitze.io"><img src="https://avatars0.githubusercontent.com/u/1160594?v=4" width="100px;" alt=""/><br /><sub><b>Kitze</b></sub></a><br /><a href="#ideas-kitze" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/drmas"><img src="https://avatars3.githubusercontent.com/u/644440?v=4" width="100px;" alt=""/><br /><sub><b>Mohamed Shaban</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=drmas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jorisre"><img src="https://avatars1.githubusercontent.com/u/7545547?v=4" width="100px;" alt=""/><br /><sub><b>Joris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jorisre" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Kamshak"><img src="https://avatars3.githubusercontent.com/u/337968?v=4" width="100px;" alt=""/><br /><sub><b>Valentin Funk</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Kamshak" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://lukebennett.com"><img src="https://avatars1.githubusercontent.com/u/135390?v=4" width="100px;" alt=""/><br /><sub><b>Luke Bennett</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lukebennett" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://haseebmajid.dev"><img src="https://avatars0.githubusercontent.com/u/998807?v=4" width="100px;" alt=""/><br /><sub><b>Haseeb Majid</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hmajid2301" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/phillippschmedt"><img src="https://avatars0.githubusercontent.com/u/16028406?v=4" width="100px;" alt=""/><br /><sub><b>Phillipp Schmedt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=phillippschmedt" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://haspar.us"><img src="https://avatars0.githubusercontent.com/u/15332326?v=4" width="100px;" alt=""/><br /><sub><b>Piotr Monwid-Olechnowicz</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hasparus" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://mizchi.dev"><img src="https://avatars2.githubusercontent.com/u/73962?v=4" width="100px;" alt=""/><br /><sub><b>Kotaro Chikuba</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mizchi" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=mizchi" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/konradkalemba"><img src="https://avatars0.githubusercontent.com/u/8682104?v=4" width="100px;" alt=""/><br /><sub><b>Konrad Kalemba</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=konradkalemba" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Alucard17"><img src="https://avatars1.githubusercontent.com/u/26205172?v=4" width="100px;" alt=""/><br /><sub><b>Alucard17</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Alucard17" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Dohxis"><img src="https://avatars2.githubusercontent.com/u/8768909?v=4" width="100px;" alt=""/><br /><sub><b>Domantas Mauruča</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Dohxis" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=Dohxis" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://sandulat.com/"><img src="https://avatars0.githubusercontent.com/u/7345874?v=4" width="100px;" alt=""/><br /><sub><b>Stratulat Alexandru</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sandulat" title="Code">💻</a> <a href="#maintenance-sandulat" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/aericson"><img src="https://avatars3.githubusercontent.com/u/692542?v=4" width="100px;" alt=""/><br /><sub><b>André Ericson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aericson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=aericson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://Cajotafer.com"><img src="https://avatars2.githubusercontent.com/u/41461969?v=4" width="100px;" alt=""/><br /><sub><b>Carlos Fernández</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cajotafer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://oesterkilde.dk/"><img src="https://avatars1.githubusercontent.com/u/6379824?v=4" width="100px;" alt=""/><br /><sub><b>Kevin Østerkilde</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Kosai106" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/aaronfulkerson"><img src="https://avatars0.githubusercontent.com/u/31112737?v=4" width="100px;" alt=""/><br /><sub><b>aaronfulkerson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aaronfulkerson" title="Code">💻</a> <a href="#question-aaronfulkerson" title="Answering Questions">💬</a></td>
|
||||
<td align="center"><a href="https://github.com/alexnaiman"><img src="https://avatars3.githubusercontent.com/u/25799714?v=4" width="100px;" alt=""/><br /><sub><b>Alexandru Naiman</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=alexnaiman" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://davidlutta.github.io/portfolio/"><img src="https://avatars2.githubusercontent.com/u/14890315?v=4" width="100px;" alt=""/><br /><sub><b>David Ezekiel Lutta</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davidlutta" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/wanjuntham"><img src="https://avatars1.githubusercontent.com/u/49380551?v=4" width="100px;" alt=""/><br /><sub><b>wanjuntham</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=wanjuntham" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://www.nahuelchaves.xyz"><img src="https://avatars3.githubusercontent.com/u/96837?v=4" width="100px;" alt=""/><br /><sub><b>Victor Nahuel Chaves</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nahue" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/peter50216"><img src="https://avatars3.githubusercontent.com/u/891109?v=4" width="100px;" alt=""/><br /><sub><b>Peter Shih</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=peter50216" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
3
__mocks__/fs.js
Normal file
3
__mocks__/fs.js
Normal file
@@ -0,0 +1,3 @@
|
||||
const {fs} = require("memfs")
|
||||
|
||||
module.exports = fs
|
||||
BIN
assets/Fauna_Logo_Blue.png
Normal file
BIN
assets/Fauna_Logo_Blue.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
4
examples/auth/.babelrc.js
Normal file
4
examples/auth/.babelrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
presets: ["next/babel"],
|
||||
plugins: [],
|
||||
}
|
||||
15
examples/auth/.eslintrc.js
Normal file
15
examples/auth/.eslintrc.js
Normal file
@@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
es2020: true,
|
||||
"cypress/globals": true,
|
||||
},
|
||||
extends: ["react-app", "plugin:jsx-a11y/recommended"],
|
||||
plugins: ["jsx-a11y", "cypress"],
|
||||
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
|
||||
"jsx-a11y/label-has-associated-control": "off", //Doesn't play well with form libraries
|
||||
},
|
||||
}
|
||||
57
examples/auth/.gitignore
vendored
Normal file
57
examples/auth/.gitignore
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# dependencies
|
||||
node_modules
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.pnp.*
|
||||
.npm
|
||||
web_modules/
|
||||
|
||||
# blitz
|
||||
/.blitz/
|
||||
/.next/
|
||||
*.sqlite
|
||||
.now
|
||||
.blitz-console-history
|
||||
blitz-log.log
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
# local env files
|
||||
.env
|
||||
.envrc
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# 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
|
||||
|
||||
.vercel
|
||||
1
examples/auth/.npmrc
Normal file
1
examples/auth/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
save-exact=true
|
||||
5
examples/auth/.prettierignore
Normal file
5
examples/auth/.prettierignore
Normal file
@@ -0,0 +1,5 @@
|
||||
.gitkeep
|
||||
.env*
|
||||
*.ico
|
||||
*.lock
|
||||
db/migrations
|
||||
2
examples/auth/.vercelignore
Normal file
2
examples/auth/.vercelignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.blitz
|
||||
*.sqlite
|
||||
26
examples/auth/README.md
Normal file
26
examples/auth/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# auth
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Add this code to db/schema.prisma:
|
||||
|
||||
```
|
||||
model Project {
|
||||
id Int @default(autoincrement()) @id
|
||||
name String
|
||||
}
|
||||
```
|
||||
|
||||
2. DB migrate
|
||||
|
||||
```
|
||||
blitz db migrate
|
||||
```
|
||||
|
||||
3. Start the dev server
|
||||
|
||||
```
|
||||
blitz start
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
131
examples/auth/app/api/auth/[...auth].ts
Normal file
131
examples/auth/app/api/auth/[...auth].ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import {passportAuth} from "blitz"
|
||||
import db from "db"
|
||||
import {Strategy as TwitterStrategy} from "passport-twitter"
|
||||
import {Strategy as GitHubStrategy} from "passport-github2"
|
||||
import {Strategy as Auth0Strategy} from "passport-auth0"
|
||||
|
||||
function assert(condition: any, message: string): asserts condition {
|
||||
if (!condition) throw new Error(message)
|
||||
}
|
||||
|
||||
// These aren't required, but this is a good practice to ensure you have the env vars you need
|
||||
assert(process.env.TWITTER_CONSUMER_KEY, "You must provide the TWITTER_CONSUMER_KEY env variable")
|
||||
assert(
|
||||
process.env.TWITTER_CONSUMER_SECRET,
|
||||
"You must provide the TWITTER_CONSUMER_SECRET env variable",
|
||||
)
|
||||
assert(process.env.GITHUB_CLIENT_ID, "You must provide the GITHUB_CLIENT_ID env variable")
|
||||
assert(process.env.GITHUB_CLIENT_SECRET, "You must provide the GITHUB_CLIENT_SECRET env variable")
|
||||
|
||||
assert(process.env.AUTH0_DOMAIN, "You must provide the AUTH0_DOMAIN env variable")
|
||||
assert(process.env.AUTH0_CLIENT_ID, "You must provide the AUTH0_CLIENT_ID env variable")
|
||||
assert(process.env.AUTH0_CLIENT_SECRET, "You must provide the AUTH0_CLIENT_SECRET env variable")
|
||||
|
||||
export default passportAuth({
|
||||
successRedirectUrl: "/",
|
||||
authenticateOptions: {scope: "openid email profile"}, //used for Auth0Strategy - without an empty profile is returned
|
||||
strategies: [
|
||||
new TwitterStrategy(
|
||||
{
|
||||
consumerKey: process.env.TWITTER_CONSUMER_KEY,
|
||||
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
|
||||
callbackURL:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/twitter/callback"
|
||||
: "http://localhost:3000/api/auth/twitter/callback",
|
||||
includeEmail: true,
|
||||
},
|
||||
async function (_token, _tokenSecret, profile, done) {
|
||||
const email = profile.emails && profile.emails[0]?.value
|
||||
|
||||
if (!email) {
|
||||
// This can happen if you haven't enabled email access in your twitter app permissions
|
||||
return done(new Error("Twitter OAuth response doesn't have email."))
|
||||
}
|
||||
|
||||
const user = await db.user.upsert({
|
||||
where: {email},
|
||||
create: {
|
||||
email,
|
||||
name: profile.displayName,
|
||||
},
|
||||
update: {email},
|
||||
})
|
||||
|
||||
const publicData = {userId: user.id, roles: [user.role], source: "twitter"}
|
||||
done(null, {publicData})
|
||||
},
|
||||
),
|
||||
new GitHubStrategy(
|
||||
{
|
||||
clientID: process.env.GITHUB_CLIENT_ID,
|
||||
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
||||
callbackURL:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/github/callback"
|
||||
: "http://localhost:3000/api/auth/github/callback",
|
||||
},
|
||||
async function (_token, _tokenSecret, profile, done) {
|
||||
const email = profile.emails && profile.emails[0]?.value
|
||||
|
||||
if (!email) {
|
||||
// This can happen if you haven't enabled email access in your twitter app permissions
|
||||
return done(new Error("Twitter OAuth response doesn't have email."))
|
||||
}
|
||||
|
||||
const user = await db.user.upsert({
|
||||
where: {email},
|
||||
create: {
|
||||
email,
|
||||
name: profile.displayName,
|
||||
},
|
||||
update: {email},
|
||||
})
|
||||
|
||||
const publicData = {
|
||||
userId: user.id,
|
||||
roles: [user.role],
|
||||
source: "github",
|
||||
githubUsername: profile.username,
|
||||
}
|
||||
done(null, {publicData})
|
||||
},
|
||||
),
|
||||
new Auth0Strategy(
|
||||
{
|
||||
domain: process.env.AUTH0_DOMAIN,
|
||||
clientID: process.env.AUTH0_CLIENT_ID,
|
||||
clientSecret: process.env.AUTH0_CLIENT_SECRET,
|
||||
callbackURL:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/auth0/callback"
|
||||
: "http://localhost:3000/api/auth/auth0/callback",
|
||||
},
|
||||
async function (_token, _tokenSecret, extraParams, profile, done) {
|
||||
const email = profile.emails && profile.emails[0]?.value
|
||||
|
||||
if (!email) {
|
||||
// This can happen if you haven't enabled email access in your twitter app permissions
|
||||
return done(new Error("GitHub OAuth response doesn't have email."))
|
||||
}
|
||||
|
||||
const user = await db.user.upsert({
|
||||
where: {email},
|
||||
create: {
|
||||
email,
|
||||
name: profile.displayName,
|
||||
},
|
||||
update: {email},
|
||||
})
|
||||
|
||||
const publicData = {
|
||||
userId: user.id,
|
||||
roles: [user.role],
|
||||
source: "auth0",
|
||||
githubUsername: profile.username,
|
||||
}
|
||||
done(undefined, {publicData})
|
||||
},
|
||||
),
|
||||
],
|
||||
})
|
||||
39
examples/auth/app/auth/auth-utils.ts
Normal file
39
examples/auth/app/auth/auth-utils.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import {AuthenticationError} from "blitz"
|
||||
import SecurePassword from "secure-password"
|
||||
import db from "db"
|
||||
|
||||
const SP = new SecurePassword()
|
||||
|
||||
export const hashPassword = async (password: string) => {
|
||||
const hashedBuffer = await SP.hash(Buffer.from(password))
|
||||
return hashedBuffer.toString("base64")
|
||||
}
|
||||
export const verifyPassword = async (hashedPassword: string, password: string) => {
|
||||
try {
|
||||
return await SP.verify(Buffer.from(password), Buffer.from(hashedPassword, "base64"))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const authenticateUser = async (email: string, password: string) => {
|
||||
const user = await db.user.findOne({where: {email}})
|
||||
|
||||
if (!user || !user.hashedPassword) throw new AuthenticationError()
|
||||
|
||||
switch (await verifyPassword(user.hashedPassword, password)) {
|
||||
case SecurePassword.VALID:
|
||||
break
|
||||
case SecurePassword.VALID_NEEDS_REHASH:
|
||||
// Upgrade hashed password with a more secure hash
|
||||
const improvedHash = await hashPassword(password)
|
||||
await db.user.update({where: {id: user.id}, data: {hashedPassword: improvedHash}})
|
||||
break
|
||||
default:
|
||||
throw new AuthenticationError()
|
||||
}
|
||||
|
||||
const {hashedPassword, ...rest} = user
|
||||
return rest
|
||||
}
|
||||
46
examples/auth/app/auth/components/LoginForm.tsx
Normal file
46
examples/auth/app/auth/components/LoginForm.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import {Link, useMutation} from "blitz"
|
||||
import {LabeledTextField} from "app/components/LabeledTextField"
|
||||
import {Form, FORM_ERROR} from "app/components/Form"
|
||||
import login from "app/auth/mutations/login"
|
||||
import {LoginInput} from "app/auth/validations"
|
||||
|
||||
type LoginFormProps = {
|
||||
onSuccess?: () => void
|
||||
}
|
||||
|
||||
export const LoginForm = (props: LoginFormProps) => {
|
||||
const [loginMutation] = useMutation(login)
|
||||
return (
|
||||
<div>
|
||||
<h1>Login</h1>
|
||||
<Form
|
||||
submitText="Log In"
|
||||
schema={LoginInput}
|
||||
initialValues={{email: undefined, password: undefined}}
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await loginMutation(values)
|
||||
props.onSuccess && props.onSuccess()
|
||||
} catch (error) {
|
||||
if (error.name === "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
|
||||
15
examples/auth/app/auth/mutations/login.ts
Normal file
15
examples/auth/app/auth/mutations/login.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {Ctx} from "blitz"
|
||||
import {authenticateUser} from "app/auth/auth-utils"
|
||||
import {LoginInput, LoginInputType} from "../validations"
|
||||
|
||||
export default async function login(input: LoginInputType, {session}: Ctx) {
|
||||
// This throws an error if input is invalid
|
||||
const {email, password} = LoginInput.parse(input)
|
||||
|
||||
// This throws an error if credentials are invalid
|
||||
const user = await authenticateUser(email, password)
|
||||
|
||||
await session.create({userId: user.id, roles: [user.role]})
|
||||
|
||||
return user
|
||||
}
|
||||
5
examples/auth/app/auth/mutations/logout.ts
Normal file
5
examples/auth/app/auth/mutations/logout.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import {Ctx} from "blitz"
|
||||
|
||||
export default async function logout(_: any, {session}: Ctx) {
|
||||
return await session.revoke()
|
||||
}
|
||||
19
examples/auth/app/auth/mutations/signup.ts
Normal file
19
examples/auth/app/auth/mutations/signup.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import {Ctx} from "blitz"
|
||||
import db from "db"
|
||||
import {hashPassword} from "app/auth/auth-utils"
|
||||
import {SignupInput, SignupInputType} from "app/auth/validations"
|
||||
|
||||
export default async function signup(input: SignupInputType, {session}: Ctx) {
|
||||
// This throws an error if input is invalid
|
||||
const {email, password} = SignupInput.parse(input)
|
||||
|
||||
const hashedPassword = await hashPassword(password)
|
||||
const user = await db.user.create({
|
||||
data: {email, hashedPassword, role: "user"},
|
||||
select: {id: true, name: true, email: true, role: true},
|
||||
})
|
||||
|
||||
await session.create({userId: user.id, roles: [user.role]})
|
||||
|
||||
return user
|
||||
}
|
||||
21
examples/auth/app/auth/pages/login.tsx
Normal file
21
examples/auth/app/auth/pages/login.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import {Head, useRouter, BlitzPage} from "blitz"
|
||||
import {LoginForm} from "app/auth/components/LoginForm"
|
||||
|
||||
const SignupPage: BlitzPage = () => {
|
||||
const router = useRouter()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Log In</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<div>
|
||||
<LoginForm onSuccess={() => router.push("/")} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignupPage
|
||||
54
examples/auth/app/auth/pages/signup.tsx
Normal file
54
examples/auth/app/auth/pages/signup.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import {Head, useRouter, BlitzPage, useMutation} from "blitz"
|
||||
import {Form, FORM_ERROR} from "app/components/Form"
|
||||
import {LabeledTextField} from "app/components/LabeledTextField"
|
||||
import signup from "app/auth/mutations/signup"
|
||||
import {SignupInput} from "app/auth/validations"
|
||||
|
||||
const SignupPage: BlitzPage = () => {
|
||||
const router = useRouter()
|
||||
const [signupMutation] = useMutation(signup)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Sign Up</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<div>
|
||||
<h1>Create an Account</h1>
|
||||
|
||||
<Form
|
||||
submitText="Create Account"
|
||||
schema={SignupInput}
|
||||
onSubmit={async (values) => {
|
||||
try {
|
||||
await signupMutation(values)
|
||||
router.push("/")
|
||||
} catch (error) {
|
||||
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]:
|
||||
"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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignupPage
|
||||
13
examples/auth/app/auth/validations.ts
Normal file
13
examples/auth/app/auth/validations.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import * as z from "zod"
|
||||
|
||||
export const SignupInput = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string().min(10).max(100),
|
||||
})
|
||||
export type SignupInputType = z.infer<typeof SignupInput>
|
||||
|
||||
export const LoginInput = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string(),
|
||||
})
|
||||
export type LoginInputType = z.infer<typeof LoginInput>
|
||||
0
examples/auth/app/components/.keep
Normal file
0
examples/auth/app/components/.keep
Normal file
62
examples/auth/app/components/Form.tsx
Normal file
62
examples/auth/app/components/Form.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import {ReactNode, PropsWithoutRef} from "react"
|
||||
import {Form as FinalForm, FormProps as FinalFormProps} from "react-final-form"
|
||||
import * as z from "zod"
|
||||
export {FORM_ERROR} from "final-form"
|
||||
|
||||
type FormProps<S extends z.ZodType<any, any>> = {
|
||||
/** All your form fields */
|
||||
children: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
submitText: string
|
||||
onSubmit: FinalFormProps<z.infer<S>>["onSubmit"]
|
||||
initialValues?: FinalFormProps<z.infer<S>>["initialValues"]
|
||||
schema?: S
|
||||
} & Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit">
|
||||
|
||||
export function Form<S extends z.ZodType<any, any>>({
|
||||
children,
|
||||
submitText,
|
||||
schema,
|
||||
initialValues,
|
||||
onSubmit,
|
||||
...props
|
||||
}: FormProps<S>) {
|
||||
return (
|
||||
<FinalForm
|
||||
initialValues={initialValues}
|
||||
validate={(values) => {
|
||||
if (!schema) return
|
||||
try {
|
||||
schema.parse(values)
|
||||
} catch (error) {
|
||||
return error.formErrors.fieldErrors
|
||||
}
|
||||
}}
|
||||
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>
|
||||
)}
|
||||
|
||||
<button type="submit" disabled={submitting}>
|
||||
{submitText}
|
||||
</button>
|
||||
|
||||
<style global jsx>{`
|
||||
.form > * + * {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
`}</style>
|
||||
</form>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Form
|
||||
55
examples/auth/app/components/LabeledTextField.tsx
Normal file
55
examples/auth/app/components/LabeledTextField.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import {forwardRef, PropsWithoutRef} from "react"
|
||||
import {useField} 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"]>
|
||||
}
|
||||
|
||||
export const LabeledTextField = forwardRef<HTMLInputElement, LabeledTextFieldProps>(
|
||||
({name, label, outerProps, ...props}, ref) => {
|
||||
const {
|
||||
input,
|
||||
meta: {touched, error, submitError, submitting},
|
||||
} = useField(name)
|
||||
|
||||
return (
|
||||
<div {...outerProps}>
|
||||
<label>
|
||||
{label}
|
||||
<input {...input} disabled={submitting} {...props} ref={ref} />
|
||||
</label>
|
||||
|
||||
{touched && (error || submitError) && (
|
||||
<div role="alert" style={{color: "red"}}>
|
||||
{error || submitError}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<style jsx>{`
|
||||
label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
font-size: 1rem;
|
||||
}
|
||||
input {
|
||||
font-size: 1rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 3px;
|
||||
border: 1px solid purple;
|
||||
appearance: none;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
export default LabeledTextField
|
||||
10
examples/auth/app/hooks/useCurrentUser.ts
Normal file
10
examples/auth/app/hooks/useCurrentUser.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import {useQuery, useSession} from "blitz"
|
||||
import getCurrentUser from "app/users/queries/getCurrentUser"
|
||||
|
||||
export const useCurrentUser = () => {
|
||||
// We wouldn't have to useSession() here, but doing so improves perf on initial
|
||||
// load since we can skip the getCurrentUser() request.
|
||||
const session = useSession()
|
||||
const [user] = useQuery(getCurrentUser, null, {enabled: !!session.userId})
|
||||
return session.userId ? user : null
|
||||
}
|
||||
0
examples/auth/app/layouts/.keep
Normal file
0
examples/auth/app/layouts/.keep
Normal file
23
examples/auth/app/layouts/Layout.tsx
Normal file
23
examples/auth/app/layouts/Layout.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import {useSession, useRouter, useMutation} from "blitz"
|
||||
import logout from "app/auth/mutations/logout"
|
||||
|
||||
export default function Layout({children}: {children: React.ReactNode}) {
|
||||
const session = useSession()
|
||||
const router = useRouter()
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
return (
|
||||
<div>
|
||||
{session.userId && (
|
||||
<button
|
||||
onClick={async () => {
|
||||
router.push("/")
|
||||
await logoutMutation()
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
)}
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
19
examples/auth/app/pages/404.tsx
Normal file
19
examples/auth/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} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
42
examples/auth/app/pages/_app.tsx
Normal file
42
examples/auth/app/pages/_app.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
import {AppProps, ErrorComponent, useRouter} from "blitz"
|
||||
import {ErrorBoundary} from "react-error-boundary"
|
||||
import {queryCache} from "react-query"
|
||||
import LoginForm from "app/auth/components/LoginForm"
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window["DEBUG_BLITZ"] = 1
|
||||
}
|
||||
|
||||
export default function App({Component, pageProps}: AppProps) {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<ErrorBoundary
|
||||
FallbackComponent={RootErrorFallback}
|
||||
resetKeys={[router.asPath]}
|
||||
onReset={() => {
|
||||
// This ensures the Blitz useQuery hooks will automatically refetch
|
||||
// data any time you reset the error boundary
|
||||
queryCache.resetErrorBoundaries()
|
||||
}}
|
||||
>
|
||||
<Component {...pageProps} />
|
||||
</ErrorBoundary>
|
||||
)
|
||||
}
|
||||
|
||||
function RootErrorFallback({error, resetErrorBoundary}) {
|
||||
if (error.name === "AuthenticationError") {
|
||||
return <LoginForm onSuccess={resetErrorBoundary} />
|
||||
} else if (error.name === "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/auth/app/pages/_document.tsx
Normal file
23
examples/auth/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
|
||||
243
examples/auth/app/pages/index.tsx
Normal file
243
examples/auth/app/pages/index.tsx
Normal file
@@ -0,0 +1,243 @@
|
||||
import {Suspense} from "react"
|
||||
import {Head, Link, useSession, useRouterQuery, useMutation, invoke} from "blitz"
|
||||
import getUser from "app/users/queries/getUser"
|
||||
import trackView from "app/users/mutations/trackView"
|
||||
import Layout from "app/layouts/Layout"
|
||||
import {useCurrentUser} from "app/hooks/useCurrentUser"
|
||||
// import getUsers from "app/users/queries/getUsers"
|
||||
|
||||
const CurrentUserInfo = () => {
|
||||
const currentUser = useCurrentUser()
|
||||
|
||||
return <pre>{JSON.stringify(currentUser, null, 2)}</pre>
|
||||
}
|
||||
|
||||
// const Users = () => {
|
||||
// const [users] = useQuery(getUsers, {})
|
||||
//
|
||||
// return <pre style={{maxWidth: "30rem"}}>{JSON.stringify(users, null, 2)}</pre>
|
||||
// }
|
||||
|
||||
const UserStuff = () => {
|
||||
const session = useSession()
|
||||
const query = useRouterQuery()
|
||||
const [trackViewMutation] = useMutation(trackView)
|
||||
|
||||
if (session.isLoading) return <div>Loading...</div>
|
||||
|
||||
console.log(session.views)
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!session.userId && (
|
||||
<>
|
||||
<div style={{marginTop: "1rem"}}>
|
||||
<Link href="/signup">Sign Up</Link>
|
||||
</div>
|
||||
<div>
|
||||
<Link href="/login">Log In</Link>
|
||||
</div>
|
||||
<a href="/api/auth/twitter" style={{display: "block"}}>
|
||||
Login with Twitter
|
||||
</a>
|
||||
<a href="/api/auth/github" style={{display: "block"}}>
|
||||
Login with Github
|
||||
</a>
|
||||
{query.authError && <div style={{color: "red"}}>{query.authError}</div>}
|
||||
</>
|
||||
)}
|
||||
<pre>{JSON.stringify(session, null, 2)}</pre>
|
||||
<Suspense fallback="Loading...">
|
||||
<CurrentUserInfo />
|
||||
</Suspense>
|
||||
{/*
|
||||
<Suspense fallback="Loading...">
|
||||
<Users />
|
||||
</Suspense>
|
||||
*/}
|
||||
<button
|
||||
onClick={async () => {
|
||||
try {
|
||||
const user = await invoke(getUser, {where: {id: session.userId as number}})
|
||||
alert(JSON.stringify(user))
|
||||
} catch (error) {
|
||||
alert("error: " + JSON.stringify(error))
|
||||
}
|
||||
}}
|
||||
>
|
||||
Get user
|
||||
</button>
|
||||
<button
|
||||
onClick={async () => {
|
||||
try {
|
||||
await trackViewMutation()
|
||||
} catch (error) {
|
||||
alert("error: " + error)
|
||||
console.log(error)
|
||||
}
|
||||
}}
|
||||
>
|
||||
Track view
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Home = () => (
|
||||
<Layout>
|
||||
<div className="container">
|
||||
<Head>
|
||||
<title>auth</title>
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<main>
|
||||
<div className="logo">
|
||||
<img src="/logo.png" alt="blitz.js" />
|
||||
</div>
|
||||
|
||||
<UserStuff />
|
||||
</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>{`
|
||||
.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;
|
||||
}
|
||||
|
||||
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-template-columns: 1fr 1fr 1fr;
|
||||
grid-gap: 0.5rem;
|
||||
margin-top: 6rem;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background-color: #6700eb;
|
||||
padding: 1rem 2rem;
|
||||
color: #f4f4f4;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a.button:hover {
|
||||
background-color: #45009d;
|
||||
}
|
||||
|
||||
a.button-outline {
|
||||
border: 2px solid #6700eb;
|
||||
padding: 1rem 2rem;
|
||||
color: #6700eb;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a.button-outline:hover {
|
||||
border-color: #45009d;
|
||||
color: #45009d;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #fafafa;
|
||||
border-radius: 5px;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
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>
|
||||
|
||||
<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;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default Home
|
||||
86
examples/auth/app/pages/ssr.tsx
Normal file
86
examples/auth/app/pages/ssr.tsx
Normal file
@@ -0,0 +1,86 @@
|
||||
import {FC} from "react"
|
||||
import {getSessionContext} from "@blitzjs/server"
|
||||
import {
|
||||
invokeWithMiddleware,
|
||||
useRouter,
|
||||
GetServerSideProps,
|
||||
PromiseReturnType,
|
||||
ErrorComponent as ErrorPage,
|
||||
useMutation,
|
||||
} from "blitz"
|
||||
import getUser from "app/users/queries/getUser"
|
||||
import logout from "app/auth/mutations/logout"
|
||||
import path from "path"
|
||||
|
||||
type PageProps = {
|
||||
user?: PromiseReturnType<typeof getUser>
|
||||
error?: {
|
||||
statusCode: number
|
||||
message: string
|
||||
}
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps<PageProps> = async ({req, res}) => {
|
||||
// Ensure these files are not eliminated by trace-based tree-shaking (like Vercel)
|
||||
// https://github.com/blitz-js/blitz/issues/794
|
||||
path.resolve("next.config.js")
|
||||
path.resolve("blitz.config.js")
|
||||
path.resolve(".next/__db.js")
|
||||
// End anti-tree-shaking
|
||||
|
||||
const session = await getSessionContext(req, res)
|
||||
console.log("Session id:", session.userId)
|
||||
try {
|
||||
const user = await invokeWithMiddleware(
|
||||
getUser,
|
||||
{where: {id: Number(session.userId)}},
|
||||
{res, req},
|
||||
)
|
||||
return {props: {user}}
|
||||
} catch (error) {
|
||||
if (error.name === "NotFoundError") {
|
||||
res.statusCode = 404
|
||||
res.end()
|
||||
return {props: {}}
|
||||
} else if (error.name === "AuthenticationError") {
|
||||
res.writeHead(302, {location: "/login"}).end()
|
||||
return {props: {}}
|
||||
} else if (error.name === "AuthorizationError") {
|
||||
return {
|
||||
props: {
|
||||
error: {
|
||||
statusCode: error.statusCode,
|
||||
message: "Sorry, you are not authorized to access this",
|
||||
},
|
||||
},
|
||||
}
|
||||
} else {
|
||||
return {props: {error: {statusCode: error.statusCode || 500, message: error.message}}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Test: FC<PageProps> = ({user, error}: PageProps) => {
|
||||
const router = useRouter()
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
|
||||
if (error) {
|
||||
return <ErrorPage statusCode={error.statusCode} title={error.message} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>Logged in user id: {user?.id}</div>
|
||||
<button
|
||||
onClick={async () => {
|
||||
await logoutMutation()
|
||||
router.push("/")
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Test
|
||||
9
examples/auth/app/users/mutations/trackView.ts
Normal file
9
examples/auth/app/users/mutations/trackView.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import {Ctx} from "blitz"
|
||||
|
||||
export default async function trackView(_ = null, {session}: Ctx) {
|
||||
const currentViews = session.publicData.views || 0
|
||||
await session.setPublicData({views: currentViews + 1})
|
||||
await session.setPrivateData({views: currentViews + 1})
|
||||
|
||||
return
|
||||
}
|
||||
13
examples/auth/app/users/queries/getCurrentUser.ts
Normal file
13
examples/auth/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, ctx: Ctx) {
|
||||
if (!ctx.session.userId) return null
|
||||
|
||||
const user = await db.user.findOne({
|
||||
where: {id: ctx.session.userId},
|
||||
select: {id: true, name: true, email: true, role: true},
|
||||
})
|
||||
|
||||
return user
|
||||
}
|
||||
19
examples/auth/app/users/queries/getUser.ts
Normal file
19
examples/auth/app/users/queries/getUser.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import {Ctx, NotFoundError} from "blitz"
|
||||
import db, {FindOneUserArgs} from "db"
|
||||
|
||||
type GetUserInput = {
|
||||
where: FindOneUserArgs["where"]
|
||||
}
|
||||
|
||||
export default async function getUser({where}: GetUserInput, ctx: Ctx) {
|
||||
ctx.session.authorize()
|
||||
console.log(ctx.session.userId)
|
||||
|
||||
const user = await db.user.findOne({where})
|
||||
|
||||
if (!user) throw new NotFoundError(`User with id ${where.id} does not exist`)
|
||||
|
||||
const {hashedPassword, ...rest} = user
|
||||
|
||||
return rest
|
||||
}
|
||||
28
examples/auth/app/users/queries/getUsers.ts
Normal file
28
examples/auth/app/users/queries/getUsers.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import {Ctx} from "blitz"
|
||||
import db, {FindManyUserArgs} from "db"
|
||||
|
||||
type GetUsersInput = {
|
||||
where?: FindManyUserArgs["where"]
|
||||
orderBy?: FindManyUserArgs["orderBy"]
|
||||
cursor?: FindManyUserArgs["cursor"]
|
||||
take?: FindManyUserArgs["take"]
|
||||
skip?: FindManyUserArgs["skip"]
|
||||
}
|
||||
|
||||
export default async function getUsers(
|
||||
{where, orderBy, cursor, take, skip}: GetUsersInput,
|
||||
ctx: Ctx,
|
||||
) {
|
||||
ctx.session.authorize(["admin", "user"])
|
||||
|
||||
const users = await db.user.findMany({
|
||||
where,
|
||||
select: {id: true},
|
||||
orderBy,
|
||||
cursor,
|
||||
take,
|
||||
skip,
|
||||
})
|
||||
|
||||
return users
|
||||
}
|
||||
26
examples/auth/blitz.config.js
Normal file
26
examples/auth/blitz.config.js
Normal file
@@ -0,0 +1,26 @@
|
||||
const {sessionMiddleware, unstable_simpleRolesIsAuthorized} = require("@blitzjs/server")
|
||||
const withBundleAnalyzer = require("@next/bundle-analyzer")({
|
||||
enabled: process.env.ANALYZE === "true",
|
||||
})
|
||||
|
||||
module.exports = withBundleAnalyzer({
|
||||
middleware: [
|
||||
sessionMiddleware({
|
||||
unstable_isAuthorized: unstable_simpleRolesIsAuthorized,
|
||||
sessionExpiryMinutes: 4,
|
||||
}),
|
||||
],
|
||||
/*
|
||||
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
|
||||
},
|
||||
webpackDevMiddleware: (config) => {
|
||||
// Perform customizations to webpack dev middleware config
|
||||
// Important: return the modified config
|
||||
return config
|
||||
},
|
||||
*/
|
||||
})
|
||||
5
examples/auth/cypress.json
Normal file
5
examples/auth/cypress.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3099",
|
||||
"defaultCommandTimeout": 10000,
|
||||
"video": false
|
||||
}
|
||||
5
examples/auth/cypress/fixtures/example.json
Normal file
5
examples/auth/cypress/fixtures/example.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
||||
8
examples/auth/cypress/index.d.ts
vendored
Normal file
8
examples/auth/cypress/index.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/// <reference types="Cypress" />
|
||||
/// <reference types="@cypress/skip-test" />
|
||||
|
||||
declare namespace Cypress {
|
||||
interface Chainable {
|
||||
signup(user: {email: string; password: string}): void
|
||||
}
|
||||
}
|
||||
69
examples/auth/cypress/integration/index.test.ts
Normal file
69
examples/auth/cypress/integration/index.test.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import {createRandomUser} from "../support/helpers"
|
||||
|
||||
describe("index page", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/")
|
||||
})
|
||||
|
||||
it("goes to the signup page", () => {
|
||||
cy.contains("a", "Sign Up").click()
|
||||
cy.location("pathname").should("equal", "/signup")
|
||||
})
|
||||
|
||||
it("goes to the login page", () => {
|
||||
cy.contains("a", "Log In").click()
|
||||
cy.location("pathname").should("equal", "/login")
|
||||
})
|
||||
|
||||
it("allows the user to signup", () => {
|
||||
const user = createRandomUser()
|
||||
|
||||
cy.signup(user)
|
||||
|
||||
cy.location("pathname").should("equal", "/")
|
||||
cy.contains("button", "Logout")
|
||||
})
|
||||
|
||||
it("allows the user to log in", () => {
|
||||
const user = createRandomUser()
|
||||
|
||||
cy.signup(user)
|
||||
|
||||
cy.contains("button", "Logout").click()
|
||||
cy.contains("a", "Log In").click()
|
||||
|
||||
cy.contains("Email").find("input").type(user.email)
|
||||
cy.contains("Password").find("input").type(user.password)
|
||||
cy.contains("button", "Log In").click()
|
||||
|
||||
cy.location("pathname").should("equal", "/")
|
||||
cy.contains("button", "Logout")
|
||||
})
|
||||
|
||||
it("allows the user to logout", () => {
|
||||
const user = createRandomUser()
|
||||
|
||||
cy.signup(user)
|
||||
|
||||
cy.contains("button", "Logout").click()
|
||||
|
||||
cy.location("pathname").should("equal", "/")
|
||||
cy.contains("a", "Log In")
|
||||
})
|
||||
|
||||
it("tracks anonymous sessions", () => {
|
||||
// TODO - why does this fail on windows??
|
||||
cy.skipOn("windows")
|
||||
const user = createRandomUser()
|
||||
|
||||
cy.contains("button", "Track view").click()
|
||||
cy.contains("button", "Track view").click()
|
||||
cy.contains('"views": 2')
|
||||
|
||||
cy.signup(user)
|
||||
|
||||
cy.contains('"views": 2')
|
||||
})
|
||||
})
|
||||
|
||||
export {}
|
||||
22
examples/auth/cypress/plugins/index.ts
Normal file
22
examples/auth/cypress/plugins/index.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
//@ts-ignore
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
19
examples/auth/cypress/support/commands.ts
Normal file
19
examples/auth/cypress/support/commands.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
|
||||
Cypress.Commands.add("signup", ({email, password}) => {
|
||||
cy.contains("a", "Sign Up").click()
|
||||
|
||||
cy.contains("Email").find("input").type(email)
|
||||
cy.contains("Password").find("input").type(password)
|
||||
cy.contains("button", "Create Account").click()
|
||||
})
|
||||
7
examples/auth/cypress/support/helpers.ts
Normal file
7
examples/auth/cypress/support/helpers.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export const createRandomUser = () => {
|
||||
const random = Math.round(Math.random() * 100000).toString()
|
||||
const email = `test_${random}@example.com`
|
||||
const password = `password_${random}`
|
||||
|
||||
return {email, password}
|
||||
}
|
||||
26
examples/auth/cypress/support/index.ts
Normal file
26
examples/auth/cypress/support/index.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
// ***********************************************************
|
||||
// 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.js using ES2015 syntax:
|
||||
import "./commands"
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
Cypress.Screenshot.defaults({
|
||||
screenshotOnRunFailure: false,
|
||||
})
|
||||
|
||||
require("@cypress/skip-test/support")
|
||||
15
examples/auth/db/index.ts
Normal file
15
examples/auth/db/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {PrismaClient} from "@prisma/client"
|
||||
export * from "@prisma/client"
|
||||
|
||||
let prisma: PrismaClient
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
prisma = new PrismaClient()
|
||||
} else {
|
||||
// Ensure the prisma instance is re-used during hot-reloading
|
||||
// Otherwise, a new client will be created on every reload
|
||||
globalThis["prisma"] = globalThis["prisma"] || new PrismaClient()
|
||||
prisma = globalThis["prisma"]
|
||||
}
|
||||
|
||||
export default prisma
|
||||
0
examples/auth/db/migrations/.keep
Normal file
0
examples/auth/db/migrations/.keep
Normal file
82
examples/auth/db/migrations/20200704211726/README.md
Normal file
82
examples/auth/db/migrations/20200704211726/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Migration `20200704211726`
|
||||
|
||||
This migration has been generated by Brandon Bayer at 7/4/2020, 9:17:26 PM.
|
||||
You can check out the [state of the schema](./schema.prisma) after the migration.
|
||||
|
||||
## Database Steps
|
||||
|
||||
```sql
|
||||
PRAGMA foreign_keys=OFF;
|
||||
|
||||
CREATE TABLE "quaint"."User" (
|
||||
"createdAt" DATE NOT NULL DEFAULT CURRENT_TIMESTAMP ,"email" TEXT NOT NULL ,"hashedPassword" TEXT NOT NULL ,"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"name" TEXT ,"role" TEXT NOT NULL ,"updatedAt" DATE NOT NULL )
|
||||
|
||||
CREATE TABLE "quaint"."Session" (
|
||||
"antiCSRFToken" TEXT ,"createdAt" DATE NOT NULL DEFAULT CURRENT_TIMESTAMP ,"expiresAt" DATE ,"handle" TEXT NOT NULL ,"hashedSessionToken" TEXT ,"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"privateData" TEXT ,"publicData" TEXT ,"updatedAt" DATE NOT NULL ,"userId" INTEGER ,FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE)
|
||||
|
||||
CREATE UNIQUE INDEX "quaint"."User.email" ON "User"("email")
|
||||
|
||||
CREATE UNIQUE INDEX "quaint"."Session.handle" ON "Session"("handle")
|
||||
|
||||
PRAGMA "quaint".foreign_key_check;
|
||||
|
||||
PRAGMA foreign_keys=ON;
|
||||
```
|
||||
|
||||
## Changes
|
||||
|
||||
```diff
|
||||
diff --git schema.prisma schema.prisma
|
||||
migration ..20200704211726
|
||||
--- datamodel.dml
|
||||
+++ datamodel.dml
|
||||
@@ -1,0 +1,46 @@
|
||||
+// This is your Prisma schema file,
|
||||
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
+
|
||||
+datasource sqlite {
|
||||
+ provider = "sqlite"
|
||||
+ url = "***"
|
||||
+}
|
||||
+
|
||||
+// SQLite is easy to start with, but if you use Postgres in production
|
||||
+// you should also use it in development with the following:
|
||||
+//datasource postgresql {
|
||||
+// provider = "postgresql"
|
||||
+// url = "***"
|
||||
+//}
|
||||
+
|
||||
+generator client {
|
||||
+ provider = "prisma-client-js"
|
||||
+}
|
||||
+
|
||||
+
|
||||
+// --------------------------------------
|
||||
+
|
||||
+model User {
|
||||
+ id Int @default(autoincrement()) @id
|
||||
+ createdAt DateTime @default(now())
|
||||
+ updatedAt DateTime @updatedAt
|
||||
+ name String?
|
||||
+ email String @unique
|
||||
+ hashedPassword String
|
||||
+ role String
|
||||
+ sessions Session[]
|
||||
+}
|
||||
+
|
||||
+model Session {
|
||||
+ id Int @default(autoincrement()) @id
|
||||
+ createdAt DateTime @default(now())
|
||||
+ updatedAt DateTime @updatedAt
|
||||
+ expiresAt DateTime?
|
||||
+ handle String @unique
|
||||
+ user User? @relation(fields: [userId], references: [id])
|
||||
+ userId Int?
|
||||
+ hashedSessionToken String?
|
||||
+ antiCSRFToken String?
|
||||
+ publicData String?
|
||||
+ privateData String?
|
||||
+}
|
||||
```
|
||||
|
||||
|
||||
46
examples/auth/db/migrations/20200704211726/schema.prisma
Normal file
46
examples/auth/db/migrations/20200704211726/schema.prisma
Normal file
@@ -0,0 +1,46 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
datasource sqlite {
|
||||
provider = "sqlite"
|
||||
url = "***"
|
||||
}
|
||||
|
||||
// SQLite is easy to start with, but if you use Postgres in production
|
||||
// you should also use it in development with the following:
|
||||
//datasource postgresql {
|
||||
// provider = "postgresql"
|
||||
// url = "***"
|
||||
//}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
model User {
|
||||
id Int @default(autoincrement()) @id
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
name String?
|
||||
email String @unique
|
||||
hashedPassword String
|
||||
role String
|
||||
sessions Session[]
|
||||
}
|
||||
|
||||
model Session {
|
||||
id Int @default(autoincrement()) @id
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
expiresAt DateTime?
|
||||
handle String @unique
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
userId Int?
|
||||
hashedSessionToken String?
|
||||
antiCSRFToken String?
|
||||
publicData String?
|
||||
privateData String?
|
||||
}
|
||||
373
examples/auth/db/migrations/20200704211726/steps.json
Normal file
373
examples/auth/db/migrations/20200704211726/steps.json
Normal file
@@ -0,0 +1,373 @@
|
||||
{
|
||||
"version": "0.3.14-fixed",
|
||||
"steps": [
|
||||
{
|
||||
"tag": "CreateSource",
|
||||
"source": "sqlite"
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Source",
|
||||
"source": "sqlite"
|
||||
},
|
||||
"argument": "provider",
|
||||
"value": "\"sqlite\""
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Source",
|
||||
"source": "sqlite"
|
||||
},
|
||||
"argument": "url",
|
||||
"value": "\"file:./db.sqlite\""
|
||||
},
|
||||
{
|
||||
"tag": "CreateModel",
|
||||
"model": "User"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "id",
|
||||
"type": "Int",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "id"
|
||||
},
|
||||
"directive": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Directive",
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "id"
|
||||
},
|
||||
"directive": "default"
|
||||
},
|
||||
"argument": "",
|
||||
"value": "autoincrement()"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "id"
|
||||
},
|
||||
"directive": "id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "createdAt",
|
||||
"type": "DateTime",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "createdAt"
|
||||
},
|
||||
"directive": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Directive",
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "createdAt"
|
||||
},
|
||||
"directive": "default"
|
||||
},
|
||||
"argument": "",
|
||||
"value": "now()"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "updatedAt",
|
||||
"type": "DateTime",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "updatedAt"
|
||||
},
|
||||
"directive": "updatedAt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "name",
|
||||
"type": "String",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "email",
|
||||
"type": "String",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "email"
|
||||
},
|
||||
"directive": "unique"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "hashedPassword",
|
||||
"type": "String",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "role",
|
||||
"type": "String",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "User",
|
||||
"field": "sessions",
|
||||
"type": "Session",
|
||||
"arity": "List"
|
||||
},
|
||||
{
|
||||
"tag": "CreateModel",
|
||||
"model": "Session"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "id",
|
||||
"type": "Int",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "id"
|
||||
},
|
||||
"directive": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Directive",
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "id"
|
||||
},
|
||||
"directive": "default"
|
||||
},
|
||||
"argument": "",
|
||||
"value": "autoincrement()"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "id"
|
||||
},
|
||||
"directive": "id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "createdAt",
|
||||
"type": "DateTime",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "createdAt"
|
||||
},
|
||||
"directive": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Directive",
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "createdAt"
|
||||
},
|
||||
"directive": "default"
|
||||
},
|
||||
"argument": "",
|
||||
"value": "now()"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "updatedAt",
|
||||
"type": "DateTime",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "updatedAt"
|
||||
},
|
||||
"directive": "updatedAt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "expiresAt",
|
||||
"type": "DateTime",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "handle",
|
||||
"type": "String",
|
||||
"arity": "Required"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "handle"
|
||||
},
|
||||
"directive": "unique"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "user",
|
||||
"type": "User",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "user"
|
||||
},
|
||||
"directive": "relation"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Directive",
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "user"
|
||||
},
|
||||
"directive": "relation"
|
||||
},
|
||||
"argument": "fields",
|
||||
"value": "[userId]"
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Directive",
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "Session",
|
||||
"field": "user"
|
||||
},
|
||||
"directive": "relation"
|
||||
},
|
||||
"argument": "references",
|
||||
"value": "[id]"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "userId",
|
||||
"type": "Int",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "hashedSessionToken",
|
||||
"type": "String",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "antiCSRFToken",
|
||||
"type": "String",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "publicData",
|
||||
"type": "String",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateField",
|
||||
"model": "Session",
|
||||
"field": "privateData",
|
||||
"type": "String",
|
||||
"arity": "Optional"
|
||||
}
|
||||
]
|
||||
}
|
||||
66
examples/auth/db/migrations/20200711145940/README.md
Normal file
66
examples/auth/db/migrations/20200711145940/README.md
Normal file
@@ -0,0 +1,66 @@
|
||||
# Migration `20200711145940`
|
||||
|
||||
This migration has been generated by Brandon Bayer at 7/11/2020, 2:59:40 PM.
|
||||
You can check out the [state of the schema](./schema.prisma) after the migration.
|
||||
|
||||
## Database Steps
|
||||
|
||||
```sql
|
||||
PRAGMA foreign_keys=OFF;
|
||||
|
||||
CREATE TABLE "quaint"."new_User" (
|
||||
"createdAt" DATE NOT NULL DEFAULT CURRENT_TIMESTAMP ,"email" TEXT NOT NULL ,"hashedPassword" TEXT ,"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"name" TEXT ,"role" TEXT NOT NULL DEFAULT 'user' ,"updatedAt" DATE NOT NULL )
|
||||
|
||||
INSERT INTO "quaint"."new_User" ("createdAt", "email", "hashedPassword", "id", "name", "role", "updatedAt") SELECT "createdAt", "email", "hashedPassword", "id", "name", "role", "updatedAt" FROM "quaint"."User"
|
||||
|
||||
PRAGMA foreign_keys=off;
|
||||
DROP TABLE "quaint"."User";;
|
||||
PRAGMA foreign_keys=on
|
||||
|
||||
ALTER TABLE "quaint"."new_User" RENAME TO "User";
|
||||
|
||||
CREATE UNIQUE INDEX "quaint"."User.email" ON "User"("email")
|
||||
|
||||
PRAGMA "quaint".foreign_key_check;
|
||||
|
||||
PRAGMA foreign_keys=ON;
|
||||
```
|
||||
|
||||
## Changes
|
||||
|
||||
```diff
|
||||
diff --git schema.prisma schema.prisma
|
||||
migration 20200704211726..20200711145940
|
||||
--- datamodel.dml
|
||||
+++ datamodel.dml
|
||||
@@ -2,16 +2,16 @@
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
datasource sqlite {
|
||||
provider = "sqlite"
|
||||
- url = "***"
|
||||
+ url = "***"
|
||||
}
|
||||
// SQLite is easy to start with, but if you use Postgres in production
|
||||
// you should also use it in development with the following:
|
||||
//datasource postgresql {
|
||||
// provider = "postgresql"
|
||||
-// url = "***"
|
||||
+// url = "***"
|
||||
//}
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
@@ -25,10 +25,10 @@
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
name String?
|
||||
email String @unique
|
||||
- hashedPassword String
|
||||
- role String
|
||||
+ hashedPassword String?
|
||||
+ role String @default("user")
|
||||
sessions Session[]
|
||||
}
|
||||
model Session {
|
||||
```
|
||||
|
||||
|
||||
46
examples/auth/db/migrations/20200711145940/schema.prisma
Normal file
46
examples/auth/db/migrations/20200711145940/schema.prisma
Normal file
@@ -0,0 +1,46 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
datasource sqlite {
|
||||
provider = "sqlite"
|
||||
url = "***"
|
||||
}
|
||||
|
||||
// SQLite is easy to start with, but if you use Postgres in production
|
||||
// you should also use it in development with the following:
|
||||
//datasource postgresql {
|
||||
// provider = "postgresql"
|
||||
// url = "***"
|
||||
//}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
model User {
|
||||
id Int @default(autoincrement()) @id
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
name String?
|
||||
email String @unique
|
||||
hashedPassword String?
|
||||
role String @default("user")
|
||||
sessions Session[]
|
||||
}
|
||||
|
||||
model Session {
|
||||
id Int @default(autoincrement()) @id
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
expiresAt DateTime?
|
||||
handle String @unique
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
userId Int?
|
||||
hashedSessionToken String?
|
||||
antiCSRFToken String?
|
||||
publicData String?
|
||||
privateData String?
|
||||
}
|
||||
36
examples/auth/db/migrations/20200711145940/steps.json
Normal file
36
examples/auth/db/migrations/20200711145940/steps.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"version": "0.3.14-fixed",
|
||||
"steps": [
|
||||
{
|
||||
"tag": "UpdateField",
|
||||
"model": "User",
|
||||
"field": "hashedPassword",
|
||||
"arity": "Optional"
|
||||
},
|
||||
{
|
||||
"tag": "CreateDirective",
|
||||
"location": {
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "role"
|
||||
},
|
||||
"directive": "default"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tag": "CreateArgument",
|
||||
"location": {
|
||||
"tag": "Directive",
|
||||
"path": {
|
||||
"tag": "Field",
|
||||
"model": "User",
|
||||
"field": "role"
|
||||
},
|
||||
"directive": "default"
|
||||
},
|
||||
"argument": "",
|
||||
"value": "\"user\""
|
||||
}
|
||||
]
|
||||
}
|
||||
4
examples/auth/db/migrations/migrate.lock
Normal file
4
examples/auth/db/migrations/migrate.lock
Normal file
@@ -0,0 +1,4 @@
|
||||
# Prisma Migrate lockfile v1
|
||||
|
||||
20200704211726
|
||||
20200711145940
|
||||
45
examples/auth/db/schema.prisma
Normal file
45
examples/auth/db/schema.prisma
Normal file
@@ -0,0 +1,45 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
datasource sqlite {
|
||||
provider = "sqlite"
|
||||
url = "file:./db.sqlite"
|
||||
}
|
||||
|
||||
// SQLite is easy to start with, but if you use Postgres in production
|
||||
// you should also use it in development with the following:
|
||||
//datasource postgresql {
|
||||
// provider = "postgresql"
|
||||
// url = env("DATABASE_URL")
|
||||
//}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
// --------------------------------------
|
||||
|
||||
model User {
|
||||
id Int @default(autoincrement()) @id
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
name String?
|
||||
email String @unique
|
||||
hashedPassword String?
|
||||
role String @default("user")
|
||||
sessions Session[]
|
||||
}
|
||||
|
||||
model Session {
|
||||
id Int @default(autoincrement()) @id
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
expiresAt DateTime?
|
||||
handle String @unique
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
userId Int?
|
||||
hashedSessionToken String?
|
||||
antiCSRFToken String?
|
||||
publicData String?
|
||||
privateData String?
|
||||
}
|
||||
0
examples/auth/integrations/.keep
Normal file
0
examples/auth/integrations/.keep
Normal file
82
examples/auth/package.json
Normal file
82
examples/auth/package.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"name": "@examples/auth",
|
||||
"version": "0.24.2",
|
||||
"scripts": {
|
||||
"start": "blitz start",
|
||||
"studio": "blitz db studio",
|
||||
"build": "blitz build",
|
||||
"lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .",
|
||||
"analyze": "cross-env ANALYZE=true blitz build",
|
||||
"cy:open": "cypress open",
|
||||
"cy:run": "cypress run",
|
||||
"test:start": "blitz db migrate && blitz start --production -p 3099",
|
||||
"test": "cross-env NODE_ENV=test start-server-and-test test:start http://localhost:3099 cy:run"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults"
|
||||
],
|
||||
"prisma": {
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"printWidth": 100,
|
||||
"bracketSpacing": false,
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged && pretty-quick --staged",
|
||||
"pre-push": "blitz test"
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,ts,tsx}": [
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/cli": "2.8.0",
|
||||
"@prisma/client": "2.8.0",
|
||||
"blitz": "0.24.2",
|
||||
"final-form": "4.20.1",
|
||||
"passport-auth0": "1.3.3",
|
||||
"passport-github2": "0.1.11",
|
||||
"passport-twitter": "1.0.4",
|
||||
"react": "0.0.0-experimental-7f28234f8",
|
||||
"react-dom": "0.0.0-experimental-7f28234f8",
|
||||
"react-error-boundary": "2.3.1",
|
||||
"react-final-form": "6.5.1",
|
||||
"secure-password": "4.0.0",
|
||||
"zod": "1.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@cypress/skip-test": "2.5.0",
|
||||
"@next/bundle-analyzer": "latest",
|
||||
"@types/passport-auth0": "1.0.4",
|
||||
"@types/passport-github2": "1.2.4",
|
||||
"@types/passport-twitter": "1.0.36",
|
||||
"@types/react": "16.9.38",
|
||||
"@types/secure-password": "3.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "2.34.1-alpha.2",
|
||||
"@typescript-eslint/parser": "2.34.1-alpha.2",
|
||||
"babel-eslint": "10.1.0",
|
||||
"cross-env": "latest",
|
||||
"cypress": "4.11.0",
|
||||
"eslint": "7.6.0",
|
||||
"eslint-config-react-app": "5.2.1",
|
||||
"eslint-plugin-cypress": "2.11.1",
|
||||
"eslint-plugin-flowtype": "5.2.0",
|
||||
"eslint-plugin-import": "2.22.0",
|
||||
"eslint-plugin-jsx-a11y": "6.3.1",
|
||||
"eslint-plugin-react": "7.20.5",
|
||||
"eslint-plugin-react-hooks": "4.0.8",
|
||||
"husky": "4.2.5",
|
||||
"lint-staged": "10.2.13",
|
||||
"prettier": "2.0.5",
|
||||
"pretty-quick": "2.0.1",
|
||||
"start-server-and-test": "1.11.2",
|
||||
"typescript": "3.9.5"
|
||||
},
|
||||
"private": true
|
||||
}
|
||||
BIN
examples/auth/public/favicon.ico
Executable file
BIN
examples/auth/public/favicon.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 556 B |
BIN
examples/auth/public/logo.png
Normal file
BIN
examples/auth/public/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
21
examples/auth/tsconfig.json
Normal file
21
examples/auth/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"baseUrl": "./",
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"strictNullChecks": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
||||
12
examples/auth/types.ts
Normal file
12
examples/auth/types.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import {DefaultCtx, SessionContext, DefaultPublicData} from "blitz"
|
||||
import {User} from "db"
|
||||
|
||||
declare module "blitz" {
|
||||
export interface Ctx extends DefaultCtx {
|
||||
session: SessionContext
|
||||
}
|
||||
export interface PublicData extends DefaultPublicData {
|
||||
userId: User["id"]
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
0
examples/auth/utils/.keep
Normal file
0
examples/auth/utils/.keep
Normal file
4
examples/no-prisma/.babelrc.js
Normal file
4
examples/no-prisma/.babelrc.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
presets: ["next/babel"],
|
||||
plugins: [],
|
||||
}
|
||||
13
examples/no-prisma/.eslintrc.js
Normal file
13
examples/no-prisma/.eslintrc.js
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
es2020: true,
|
||||
},
|
||||
extends: ["react-app", "plugin:jsx-a11y/recommended"],
|
||||
plugins: ["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
|
||||
},
|
||||
}
|
||||
55
examples/no-prisma/.gitignore
vendored
Normal file
55
examples/no-prisma/.gitignore
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
# dependencies
|
||||
node_modules
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.pnp.*
|
||||
.npm
|
||||
web_modules/
|
||||
|
||||
# blitz
|
||||
/.blitz/
|
||||
/.next/
|
||||
*.sqlite
|
||||
.now
|
||||
.blitz-console-history
|
||||
blitz-log.log
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
|
||||
# local env files
|
||||
.env
|
||||
.envrc
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
# 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
|
||||
1
examples/no-prisma/.npmrc
Normal file
1
examples/no-prisma/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
save-exact=true
|
||||
5
examples/no-prisma/.prettierignore
Normal file
5
examples/no-prisma/.prettierignore
Normal file
@@ -0,0 +1,5 @@
|
||||
.gitkeep
|
||||
.env*
|
||||
*.ico
|
||||
*.lock
|
||||
db/migrations
|
||||
26
examples/no-prisma/README.md
Normal file
26
examples/no-prisma/README.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# no-prisma
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Add this code to db/schema.prisma:
|
||||
|
||||
```
|
||||
model Project {
|
||||
id Int @default(autoincrement()) @id
|
||||
name String
|
||||
}
|
||||
```
|
||||
|
||||
2. DB migrate
|
||||
|
||||
```
|
||||
blitz db migrate
|
||||
```
|
||||
|
||||
3. Start the dev server
|
||||
|
||||
```
|
||||
blitz start
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
0
examples/no-prisma/app/components/.keep
Normal file
0
examples/no-prisma/app/components/.keep
Normal file
0
examples/no-prisma/app/layouts/.keep
Normal file
0
examples/no-prisma/app/layouts/.keep
Normal file
6
examples/no-prisma/app/mutations/addGIF.ts
Normal file
6
examples/no-prisma/app/mutations/addGIF.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import db from "db"
|
||||
import { GIFModel } from "db/GIFModel"
|
||||
|
||||
export default async function addGIF(url: string) {
|
||||
await db<GIFModel>("gifs").insert({ url })
|
||||
}
|
||||
6
examples/no-prisma/app/mutations/addRating.ts
Normal file
6
examples/no-prisma/app/mutations/addRating.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import RatingModel from "db/RatingModel"
|
||||
import db from "db"
|
||||
|
||||
export default async function addRating(rating: RatingModel) {
|
||||
await db<RatingModel>("ratings").insert(rating)
|
||||
}
|
||||
5
examples/no-prisma/app/pages/_app.tsx
Normal file
5
examples/no-prisma/app/pages/_app.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { AppProps } from "blitz"
|
||||
|
||||
export default function MyApp({ Component, pageProps }: AppProps) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
23
examples/no-prisma/app/pages/_document.tsx
Normal file
23
examples/no-prisma/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
|
||||
32
examples/no-prisma/app/pages/index.module.css
Normal file
32
examples/no-prisma/app/pages/index.module.css
Normal file
@@ -0,0 +1,32 @@
|
||||
.main {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.gif_list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.gif_list > li {
|
||||
border: solid black 1px;
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
margin: 20px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.gif_list > li > img {
|
||||
border-radius: 10px;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.gif_list > li > span {
|
||||
margin-left: 5px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.gif_list > li > span > select {
|
||||
float: right;
|
||||
}
|
||||
81
examples/no-prisma/app/pages/index.tsx
Normal file
81
examples/no-prisma/app/pages/index.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Suspense, useState } from "react"
|
||||
import { useQuery } from "blitz"
|
||||
import getGIFs from "app/queries/getGIFs"
|
||||
import addRating from "app/mutations/addRating"
|
||||
import addGIF from "app/mutations/addGIF"
|
||||
import styles from "./index.module.css"
|
||||
|
||||
function GIFRater() {
|
||||
const [gifs, gifsQuery] = useQuery(getGIFs, {})
|
||||
|
||||
const [gifTitle, setGifTitle] = useState<string>()
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<h1>The best GIFs of all time:</h1>
|
||||
|
||||
<form>
|
||||
<input
|
||||
onChange={(evt) => setGifTitle(evt.target.value)}
|
||||
placeholder="Submit another GIF"
|
||||
type="url"
|
||||
></input>
|
||||
<button
|
||||
type="submit"
|
||||
onClick={async (evt) => {
|
||||
evt.preventDefault()
|
||||
await addGIF(gifTitle)
|
||||
await gifsQuery.refetch()
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<ul className={styles.gif_list}>
|
||||
{gifs.map((gif) => (
|
||||
<li key={gif.url}>
|
||||
<img src={gif.url} alt="GIF" />
|
||||
<span>
|
||||
Rating: {gif.rating.toFixed(1)}
|
||||
<select
|
||||
placeholder="Change"
|
||||
defaultValue="title"
|
||||
onBlur={async (evt) => {
|
||||
const rating = +evt.target.value as 1 | 2 | 3 | 4 | 5
|
||||
evt.target.value = "title"
|
||||
|
||||
await addRating({
|
||||
gif_url: gif.url,
|
||||
rating,
|
||||
})
|
||||
|
||||
await gifsQuery.refetch()
|
||||
}}
|
||||
>
|
||||
<option disabled value="title">
|
||||
Add Rating
|
||||
</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
</select>
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<Suspense fallback="Loading ...">
|
||||
<GIFRater />
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home
|
||||
10
examples/no-prisma/app/queries/getGIFs.ts
Normal file
10
examples/no-prisma/app/queries/getGIFs.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import db from "db"
|
||||
import { GIFModel } from "db/GIFModel"
|
||||
|
||||
export default async function getGIFs(): Promise<{ url: string; rating: number }[]> {
|
||||
return await db<GIFModel>("gifs")
|
||||
.select("url")
|
||||
.leftJoin("ratings", "ratings.gif_url", "gifs.url")
|
||||
.groupBy("url")
|
||||
.avg("rating as rating")
|
||||
}
|
||||
13
examples/no-prisma/blitz.config.js
Normal file
13
examples/no-prisma/blitz.config.js
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
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
|
||||
},
|
||||
webpackDevMiddleware: (config) => {
|
||||
// Perform customizations to webpack dev middleware config
|
||||
// Important: return the modified config
|
||||
return config
|
||||
},
|
||||
}
|
||||
3
examples/no-prisma/db/GIFModel.ts
Normal file
3
examples/no-prisma/db/GIFModel.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface GIFModel {
|
||||
url: string
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user