1
0
mirror of synced 2026-02-03 18:01:02 -05:00

Compare commits

...

78 Commits

Author SHA1 Message Date
Brandon Bayer
15a349e3a4 v0.23.2 2020-09-28 17:26:52 -04:00
Luke Bennett
51c1192574 Use npm for husky pre-push hook instead of yarn (#1179)
(newapp)
2020-09-28 17:25:26 -04:00
Brandon Bayer
f79a0cdb4c v0.23.1 2020-09-28 17:19:57 -04:00
Brandon Bayer
f3eabbde4e allow publishing on branch 2020-09-28 17:17:12 -04:00
Brandon Bayer
0261672219 Disable automatic query request cancellation (#1177)
(patch)
2020-09-28 17:16:34 -04:00
Brandon Bayer
9e88b11496 v0.23.0 2020-09-22 19:28:46 -04:00
Ricardo Trejos
c427ae23d4 Add a timeout to the "retrieving freshest dependencies" step for blitz new(#1132)
(patch)
2020-09-21 20:58:32 -04:00
Enrico Schaaf
cb849c5ba9 Fix blitz autocomplete adding alpha warning message to the shell config (#1122)
(patch)
2020-09-21 19:35:34 -04:00
अभिनाश (Avinash)
6e777dd72a add lint rule to prevent Object.fromEntries in core package (#1129)
(meta)
2020-09-21 19:34:16 -04:00
Brandon Bayer
80ab4876f2 Improve error message for missing SESSION_SECRET_KEY (#1136)
(patch)
2020-09-21 16:00:59 -04:00
Brandon Bayer
cd0bf1f970 (newapp) Change signup & login to lowerCase emails before saving and verifying (#1135) 2020-09-21 14:56:38 -04:00
allcontributors[bot]
5f5a5c8ef7 docs: add enricoschaaf as a contributor (#1128)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-19 22:27:51 -04:00
Enrico Schaaf
9a1e0d0de7 Update Taiwind recipe to opt in to future Tailwind CSS changes (#1118)
(recipe)
2020-09-19 22:27:34 -04:00
Brandon Bayer
fb44203510 v0.22.3-canary.0 2020-09-19 22:01:38 -04:00
Brandon Bayer
010057b34c Fix ES5 compatibility (#1124)
(patch)
2020-09-19 21:10:50 -04:00
Brandon Bayer
575e862ae3 Remove prisma client generation from blitz in favor of new package.json schema config (Requires Prisma 2.7.0+ & new field in pkg.json)) (#1121)
(major)
2020-09-19 19:30:03 -04:00
Satoshi Nitawaki
aed6b8875a Fix slack channel name in MAINTAINERS.md (#1117)
(meta)
2020-09-19 10:59:40 -04:00
Satoshi Nitawaki
10b6f859fd Fix blitz new spewing out all the database migration logs (#1116)
(patch)
2020-09-19 10:54:26 -04:00
Brandon Bayer
9ac856c0ee Update @cardotrejos as a contributor 2020-09-19 10:50:09 -04:00
अभिनाश (Avinash)
1ff7f36482 Enable automatic network request cancelation for queries/mutations (#1092)
Co-authored-by: Brandon Bayer <b@bayer.ws> (minor)
2020-09-19 10:47:58 -04:00
Brandon Bayer
df150da37e Fix cli cache file to be in temp directory instead of project directory (#1087)
(patch)
2020-09-19 10:45:37 -04:00
Bhanu Teja Pachipulusu
eb7409c0b3 Add --force flag for blitz db reset command (#1107)
(minor)
2020-09-19 10:44:22 -04:00
Brandon Bayer
1411a1d366 🎉 Add Satoshi Nitawaki as L1 Maintainer (#1119)
(meta)
2020-09-19 10:35:59 -04:00
allcontributors[bot]
ec95cb40de docs: add hardfire as a contributor (#1113)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-18 18:15:07 -04:00
Brandon Bayer
b502d7ea1e Add dotenv-flow to jest config for new apps (#1112)
(newapp)
2020-09-18 18:08:03 -04:00
allcontributors[bot]
74bf2a9e4c docs: add doeixd as a contributor (#1109)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-18 15:36:03 -04:00
Brandon Bayer
1ee637c367 Revert "add dotenv-flow to jest setup file for new apps"
This reverts commit 23a33f1c3d.
2020-09-18 15:15:41 -04:00
Brandon Bayer
c08771b57e Revert "move it to jest config"
This reverts commit 8a468e4f79.
2020-09-18 15:15:01 -04:00
Brandon Bayer
8a468e4f79 move it to jest config 2020-09-18 15:14:31 -04:00
Brandon Bayer
23a33f1c3d add dotenv-flow to jest setup file for new apps 2020-09-18 15:12:37 -04:00
Brandon Bayer
b3767861a2 Fix inability to have a /test page (#1111)
(patch)
2020-09-18 13:46:56 -04:00
Patrick G
65acfff0ff Add test, tests, spec, specs to build hash ignore list (#1102)
Co-authored-by: Brandon Bayer <b@bayer.ws> (patch)
2020-09-18 11:23:45 -04:00
Brandon Bayer
ab3fc26409 Add @sergiodxa as a contributor 2020-09-18 11:11:05 -04:00
Brandon Bayer
7b7039e0e3 bump CI cache key
(ignore)
2020-09-18 11:05:04 -04:00
engelkes-finstreet
e93f24452c Fix blitz generate pages to use kebab-case for all url paths (#1089)
(patch)
2020-09-18 10:21:00 -04:00
Brandon Bayer
63c9375331 add "recipe" and "newapp" type to release patch
(meta)
2020-09-18 10:01:57 -04:00
Brandon Bayer
adfb486004 Tweaks to new app template pkg scripts: add tsc to pre-commit and lint to pre-push (#1104)
(minor)
2020-09-18 09:58:04 -04:00
Brandon Bayer
5828736369 Improve Recipe for Render.com (#1108)
(recipe)
2020-09-18 09:53:25 -04:00
Brandon Bayer
40a93ee62d Add @tsriram as a contributor 2020-09-18 09:52:42 -04:00
Brandon Bayer
8fa82c7661 Revert "Tweaks to new app template pkg scripts: add tsc to pre-commit and lint to pre-push"
This reverts commit 141003df89.
2020-09-17 16:46:01 -04:00
Brandon Bayer
141003df89 Tweaks to new app template pkg scripts: add tsc to pre-commit and lint to pre-push 2020-09-17 16:44:10 -04:00
Brandon Bayer
6ef7b8a2de Improve rendering of errors in generated Final Form <LabeledTextField> (#1095)
(patch)
2020-09-16 17:09:06 -04:00
allcontributors[bot]
6ade33b849 docs: add taylorcjohnson as a contributor (#1093)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-16 09:23:56 -04:00
Taylor Johnson
02d3aa8259 Change the new app schema provider to be just sqlite instead of an array (#1091)
(patch)
2020-09-16 09:23:11 -04:00
Brandon Bayer
1ae2bb3ee3 v0.22.2-canary.0 2020-09-14 22:07:30 -04:00
Brandon Bayer
d84c73d2bb Add @ditorojuan as a contributor 2020-09-14 22:00:56 -04:00
Brandon Bayer
89b55971f1 Add @johnletey as a contributor 2020-09-14 22:00:37 -04:00
Brandon Bayer
fd1856bc7b Add @cktang88 as a contributor 2020-09-14 21:59:28 -04:00
Brandon Bayer
e6dbbababb Add @johncantrell97 as a contributor 2020-09-14 21:59:19 -04:00
Brandon Bayer
3e2b5ddc8e Add @JoseRFelix as a contributor 2020-09-14 21:59:03 -04:00
Brandon Bayer
1b974a0371 Add @obii-bit as a contributor 2020-09-14 21:58:20 -04:00
engelkes-finstreet
8bf9667a15 Fix blitz generate query does not preserve plurality (#1083)
(patch)
2020-09-14 21:50:03 -04:00
yuta0801
94bd4c166c Fix an incorrect error message in blitz start (#1064) 2020-09-14 20:26:55 -04:00
allcontributors[bot]
4ad9f9bdc9 docs: add yuta0801 as a contributor (#1086)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-14 20:25:47 -04:00
yuta0801
13e1526ef5 Add --inspect flag to enable Node.js inspector (#1063)
(minor)
2020-09-14 20:25:36 -04:00
Brandon Bayer
ab3021a371 Significantly improve CLI performance: reduce execute time from 1700ms -> 900ms (#1057)
(patch)
2020-09-14 20:15:50 -04:00
allcontributors[bot]
3e506c1dce docs: add xiaoyu-tamu as a contributor (#1085)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (patch)
2020-09-14 20:13:27 -04:00
Michael Li
85356ca8e8 Fix type error for useQuery/usePaginatedQuery options object (#1059)
(patch)
2020-09-14 20:13:00 -04:00
Brandon Bayer
530ce851e4 Add React Bricks as Seedling Sponsor!
(meta)
2020-09-14 12:13:07 -04:00
Brandon Bayer
d953ef795a v0.22.1 2020-09-12 14:03:09 -04:00
Brandon Bayer
7fcb0945a2 Fix bug in default _app.tsx where Links inside ErrorBoundary don't work (#1054)
(patch)
2020-09-12 13:54:49 -04:00
Brandon Bayer
ab4670c21b v0.22.0 2020-09-11 17:48:30 -04:00
Brandon Bayer
1ae7bf77b2 Tiny tweak to Layout component in new apps (#1051)
(minor)
2020-09-11 17:46:35 -04:00
Brandon Bayer
63e3fe1ccb Add link to signup page to login form for new apps (#1050)
(minor)
2020-09-11 17:03:14 -04:00
Jirka Svoboda
280a2b5c4f refactor(server): Added isTypescript explicit flag, config refactored (#1014)
Co-authored-by: Rudi Yardley <contact@rudiyardley.com> (meta)
2020-09-11 11:16:45 -04:00
Brandon Bayer
bf2734d907 v0.21.2-canary.2 2020-09-11 11:10:32 -04:00
Sigurd Moland Wahl
07341c14d3 Fix bug where test files would cause blitz build to fail (#1045)
(patch)
2020-09-11 11:07:46 -04:00
allcontributors[bot]
e150b67cf4 docs: add PixelsCommander as a contributor (#1048)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-11 11:04:47 -04:00
Denis Radin
1a1722168c Add secureProxy option the the Passport.js adapter (#1033)
(minor)
2020-09-11 11:04:33 -04:00
dependabot[bot]
7f266b0c98 Bump node-fetch from 2.6.0 to 2.6.1 in /packages/generator (#1042)
Bumps [node-fetch](https://github.com/bitinn/node-fetch) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/bitinn/node-fetch/releases)
- [Changelog](https://github.com/node-fetch/node-fetch/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/bitinn/node-fetch/compare/v2.6.0...v2.6.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (meta)
2020-09-11 09:35:50 -04:00
engelkes-finstreet
6e92a2dfde Update dependencies in new app template (#1036)
(patch)
2020-09-10 22:17:43 -04:00
Ante Primorac
66cd1ec650 Fix: export AppProps as a generic type (#1034)
(patch)
2020-09-10 22:16:51 -04:00
allcontributors[bot]
7c4916324e docs: add engelkes-finstreet as a contributor (#1041)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-10 22:12:32 -04:00
engelkes-finstreet
d747e34853 Add ability to set custom authenticateOptions for the Passport.js adapter (#1024)
(minor)
2020-09-10 22:10:37 -04:00
Brandon Bayer
3afab440c8 Add @sirmyron as a contributor 2020-09-10 22:05:04 -04:00
allcontributors[bot]
e576e6332c docs: add nitaking as a contributor (#1040)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-09-10 22:03:49 -04:00
Satoshi Nitawaki
60d0c9d0bf Enable passing extra prisma args to blitz db migrate(#1012)
(minor)
2020-09-10 22:03:34 -04:00
Brandon Bayer
8f800d388b Fix UnhandledPromiseRejectionWarning from useQuery during static pre-rendering (#1038)
(patch)
2020-09-10 09:59:38 -04:00
91 changed files with 1060 additions and 530 deletions

View File

@@ -357,7 +357,7 @@
]
},
{
"login": "skn0tt",
"login": "Skn0tt",
"name": "Simon Knott",
"avatar_url": "https://avatars1.githubusercontent.com/u/14912729?v=4",
"profile": "http://simonknott.de",
@@ -565,15 +565,6 @@
"code"
]
},
{
"login": "jletey",
"name": "John Letey",
"avatar_url": "https://avatars1.githubusercontent.com/u/62398724?v=4",
"profile": "https://github.com/jletey",
"contributions": [
"code"
]
},
{
"login": "pixelmord",
"name": "Andreas Adam",
@@ -896,7 +887,8 @@
"avatar_url": "https://avatars1.githubusercontent.com/u/8602086?v=4",
"profile": "http://ricardotrejos.tech",
"contributions": [
"code"
"code",
"doc"
]
},
{
@@ -990,6 +982,174 @@
"contributions": [
"doc"
]
},
{
"login": "nitaking",
"name": "Satoshi Nitawaki",
"avatar_url": "https://avatars2.githubusercontent.com/u/10850034?v=4",
"profile": "https://twitter.com/nitaking_",
"contributions": [
"code",
"maintenance",
"question"
]
},
{
"login": "sirmyron",
"name": "sirmyron",
"avatar_url": "https://avatars2.githubusercontent.com/u/1430136?v=4",
"profile": "https://github.com/sirmyron",
"contributions": [
"doc"
]
},
{
"login": "engelkes-finstreet",
"name": "engelkes-finstreet",
"avatar_url": "https://avatars1.githubusercontent.com/u/36962022?v=4",
"profile": "https://github.com/engelkes-finstreet",
"contributions": [
"code",
"doc"
]
},
{
"login": "PixelsCommander",
"name": "Denis Radin",
"avatar_url": "https://avatars2.githubusercontent.com/u/810671?v=4",
"profile": "http://twitter.com/pixelscommander",
"contributions": [
"review",
"code",
"doc"
]
},
{
"login": "xiaoyu-tamu",
"name": "Michael Li",
"avatar_url": "https://avatars3.githubusercontent.com/u/33362998?v=4",
"profile": "https://github.com/xiaoyu-tamu",
"contributions": [
"code"
]
},
{
"login": "yuta0801",
"name": "yuta0801",
"avatar_url": "https://avatars2.githubusercontent.com/u/21266306?v=4",
"profile": "https://github.com/yuta0801",
"contributions": [
"code"
]
},
{
"login": "Obii-bit",
"name": "Obadja Ris",
"avatar_url": "https://avatars2.githubusercontent.com/u/67339820?v=4",
"profile": "https://github.com/Obii-bit",
"contributions": [
"doc"
]
},
{
"login": "JoseRFelix",
"name": "Jose Felix ",
"avatar_url": "https://avatars2.githubusercontent.com/u/21092519?v=4",
"profile": "http://jfelix.info",
"contributions": [
"code"
]
},
{
"login": "johncantrell97",
"name": "John Cantrell",
"avatar_url": "https://avatars3.githubusercontent.com/u/41305919?v=4",
"profile": "https://github.com/johncantrell97",
"contributions": [
"code"
]
},
{
"login": "cktang88",
"name": "Kwuang Tang",
"avatar_url": "https://avatars1.githubusercontent.com/u/10319942?v=4",
"profile": "http://kwuang.me",
"contributions": [
"code"
]
},
{
"login": "johnletey",
"name": "John Letey",
"avatar_url": "https://avatars1.githubusercontent.com/u/62398724?v=4",
"profile": "https://github.com/johnletey",
"contributions": [
"code"
]
},
{
"login": "ditorojuan",
"name": "Juan Di Toro",
"avatar_url": "https://avatars0.githubusercontent.com/u/22530892?v=4",
"profile": "https://github.com/ditorojuan",
"contributions": [
"code"
]
},
{
"login": "taylorcjohnson",
"name": "Taylor Johnson",
"avatar_url": "https://avatars0.githubusercontent.com/u/10552296?v=4",
"profile": "https://github.com/taylorcjohnson",
"contributions": [
"code",
"doc"
]
},
{
"login": "tsriram",
"name": "Sriram Thiagarajan",
"avatar_url": "https://avatars3.githubusercontent.com/u/450559?v=4",
"profile": "https://twitter.com/tsriram",
"contributions": [
"doc"
]
},
{
"login": "sergiodxa",
"name": "Sergio Xalambrí",
"avatar_url": "https://avatars2.githubusercontent.com/u/1312018?v=4",
"profile": "https://sergiodxa.com",
"contributions": [
"doc"
]
},
{
"login": "doeixd",
"name": "Patrick G",
"avatar_url": "https://avatars3.githubusercontent.com/u/13461122?v=4",
"profile": "https://github.com/doeixd",
"contributions": [
"code"
]
},
{
"login": "hardfire",
"name": "अभिनाश (Avinash)",
"avatar_url": "https://avatars3.githubusercontent.com/u/513457?v=4",
"profile": "http://avinash.com.np",
"contributions": [
"code"
]
},
{
"login": "enricoschaaf",
"name": "Enrico Schaaf",
"avatar_url": "https://avatars1.githubusercontent.com/u/54645197?v=4",
"profile": "http://enricoschaaf.com",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

View File

@@ -32,9 +32,9 @@ jobs:
**/node_modules
/home/runner/.cache/Cypress
C:\Users\runneradmin\AppData\Local\Cypress\Cache
key: ${{ runner.os }}-yarn-v2-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-yarn-v3-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-v2-
${{ runner.os }}-yarn-v3-
- name: Install dependencies
run: yarn install --frozen-lockfile --silent
env:

1
.gitignore vendored
View File

@@ -19,3 +19,4 @@ dist
**/.env.*.local
**/.envrc
.blitz-*
.blitz-cli-cache

View File

@@ -52,7 +52,7 @@ Some especially important points:
## Slack
- All `#-*` channels are for Blitz users
- All `#dev-*` channels are for Blitz internal development
- All `#contributor-*` channels are for Blitz internal development
If someone that's not a maintainer post in the wrong area, that's fine. Don't tell them they posted in the wrong place. But as a maintainer, you should for sure post in the right channel :)

View File

@@ -6,7 +6,7 @@
<img alt="" src="https://img.shields.io/badge/Join%20our%20community-6700EB.svg?style=for-the-badge&labelColor=000000&logoWidth=20&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQ9SURBVHgB7d3dVdtAEIbhcSpICUoH0IEogQqSVBBSAU4FSSpIOoAORAfQgSghHXzZ1U/YcMD4R9rZmf2ec3y448LyiNf27iLiGIAmPLrweC9Un3DhrzG6EarLNP09nlwJ1SOZ/lQr5N80/S/p2QMVCBf5N17XCfm1Y/rBHqjAG9PPHvBsz+mf9WAP+HLA9M/YA14cOP2payH7jpj+VCtk1wnTP+vj7xCy6cTpn7EHLMLp059iD1iD8eveJbVCNsSLheX1YA/YgOWnf8YeKB3Wmf7Ud6Fy4f/FHmtpxbl3YlC4MJ/Cj0bWdwPnPbARg+L0S54XQHS32WwuxClzd4CM0z9rPfeAuTtA5ulPXYQ7wZ04Y+oOoDD9KZc9YOoOoDj9s4dwFzgXR6w1wIPoOvPWA9buAHEJ173o3gWiy3AnuBUHLEbgmYwvAk1/wuM8vAgexThzbwPDkx7/DHwVXfFOxP2GmsKd4Ab6zPeAyU8CI7AHFmH2BRCBPXAyk18GzUrqAXCTiR4ssyj0VFw/oCU8+e+RZ33AWz6KMaYbIIWxB+JSLs1bsbkeMN0AqakHvoku9oA2sAfqBvbAQdw0QArsgb25aYBUQT3QgT2gB+yBuqGcHij2UCqXDZACe2Anlw2QYg/QAOyBuoE98CL3DZDCuK4/rh/Q7oGL6U+TOvcNkJoijN8X1C48+T+g75eQDrAH/qmqAVJgDwyqaoAUe4AGYA/UDZX3QLUNkEIZPRCd5+6BahsgVUgPROwBTSijB7jpVAvGHriHvmw9wAZ4BpX1ABvgmakHtPcbRuwBTWAPULgAV9D/jKDY9YRvwvgEaurD44uQHvAol7qBW7WKluVtIHiUS7GyvA0s6CiXDnxrpQfsgbqBS7GKk/2jYHCrVlGyfxTMrVo0ALdq1Q3sgSKofh0M9oA61a+D2QM0AHugbmAPqClmSRjK2apVVQ8UsySsoK1aHdgDesCtWnUDeyCrIpeFg1u3sylyWTi3btMA7IG6gT2wuuK3hoE9sKrit4YVslWLPaAN7IG6ocKt2zmY2h4O9sDiTG0PZw/QANy6XTewBxZj9ogYVHy025LMHhEz9cBn0We6B0yfERReBLfhx0/R1YQHPx/QBPbA0VwcEwf2wNFcHBPHHjiem3MC2QPHcXdSaJjA+KfgTPQ8hhfjBzHC40mhlzJ+Xq9lK4a4PCs43AVaGTed5mZq+iOXZwWHi3AnOj2wFWNcnxYe7gTxLtBKHuamP/J+Wnh8a5irB7ZC5Yk9gPX1QuXC+usHWqGyhYvUYR0a7zboUOFCNVhnk0krZAOW7wFOvzXhom2xnEbIHizTA1wEYhWW6YFGyC6c1gOcfg9wfA80Qj7g8B7g9HuCww+haIR8wf49wOn3Cvv9k8tGyC/s7gFOv3fY3QONkH+v9MBWqB7PeqDn9FcIT//kcitUn6kHOu/T/xfWzlQy3dEHhwAAAABJRU5ErkJggg==">
</a>
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-103-17BB8A.svg?style=for-the-badge&labelColor=000000"></a>
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-120-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">
@@ -116,23 +116,35 @@ Your financial contributions help ensure Blitz continues to be developed and mai
👉 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="175px">
<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>
@@ -188,6 +200,7 @@ _Issue triage, pull request triage, community encouragement and moderation, etc_
</tr>
<tr>
<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></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>
</tr>
</table>
<!-- markdownlint-enable -->
@@ -250,7 +263,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
<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></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://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>
@@ -278,70 +291,92 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
</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://github.com/jletey"><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=jletey" 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></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="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>
<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://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>
<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="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>
<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="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>
<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="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>
<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></td>
<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://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>
<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></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></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="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=engelkes-finstreet" title="Documentation">📖</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>
</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!

View File

@@ -2,6 +2,7 @@ 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)
@@ -16,8 +17,13 @@ assert(
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(
{
@@ -85,5 +91,41 @@ export default passportAuth({
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})
},
),
],
})

View File

@@ -1,4 +1,5 @@
import React from "react"
import {Link} from "blitz"
import {LabeledTextField} from "app/components/LabeledTextField"
import {Form, FORM_ERROR} from "app/components/Form"
import login from "app/auth/mutations/login"
@@ -12,7 +13,6 @@ export const LoginForm = (props: LoginFormProps) => {
return (
<div>
<h1>Login</h1>
<Form<LoginInputType>
submitText="Log In"
schema={LoginInput}
@@ -36,6 +36,9 @@ export const LoginForm = (props: LoginFormProps) => {
<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>
)
}

View File

@@ -1,12 +1,14 @@
import {AppProps, ErrorComponent} from "blitz"
import {AppProps, ErrorComponent, useRouter} from "blitz"
import {ErrorBoundary} from "react-error-boundary"
import {queryCache} from "react-query"
import LoginForm from "app/auth/components/LoginForm"
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

View File

@@ -15,7 +15,7 @@ export default async function getUsers(
{where, orderBy, cursor, take, skip}: GetUsersInput,
ctx: {session?: SessionContext} = {},
) {
ctx.session?.authorize(["admin"])
ctx.session!.authorize(["admin"])
const users = await db.user.findMany({
where,

View File

@@ -1,6 +1,6 @@
{
"name": "@examples/auth",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"scripts": {
"start": "blitz start",
"studio": "blitz db studio",
@@ -35,8 +35,9 @@
"dependencies": {
"@prisma/cli": "2.4.1",
"@prisma/client": "2.4.1",
"blitz": "0.21.2-canary.1",
"blitz": "0.23.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",
@@ -49,6 +50,7 @@
"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",

View File

@@ -1,6 +1,6 @@
{
"name": "no-prisma",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"scripts": {
"start": "blitz start",
"build": "blitz build",
@@ -26,7 +26,7 @@
]
},
"dependencies": {
"blitz": "0.21.2-canary.1",
"blitz": "0.23.2",
"knex": "0.21.2",
"react": "0.0.0-experimental-7f28234f8",
"react-dom": "0.0.0-experimental-7f28234f8",

View File

@@ -1,6 +1,6 @@
{
"name": "@examples/plain-js",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"scripts": {
"start": "blitz start",
"build": "blitz db migrate && blitz build",
@@ -31,7 +31,7 @@
"dependencies": {
"@prisma/cli": "2.4.1",
"@prisma/client": "2.4.1",
"blitz": "0.21.2-canary.1",
"blitz": "0.23.2",
"react": "0.0.0-experimental-7f28234f8",
"react-dom": "0.0.0-experimental-7f28234f8"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@examples/store",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"private": true,
"scripts": {
"build": "blitz db migrate && blitz build",
@@ -18,7 +18,7 @@
"dependencies": {
"@prisma/cli": "2.4.1",
"@prisma/client": "2.4.1",
"blitz": "0.21.2-canary.1",
"blitz": "0.23.2",
"final-form": "4.19.1",
"react": "0.0.0-experimental-7f28234f8",
"react-dom": "0.0.0-experimental-7f28234f8",

View File

@@ -1,6 +1,6 @@
{
"name": "tailwind",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"scripts": {
"build": "blitz db migrate && blitz build",
"lint": "eslint --ignore-path .gitignore --ext .js,.ts,.tsx .",
@@ -30,7 +30,7 @@
"dependencies": {
"@prisma/cli": "2.4.1",
"@prisma/client": "2.4.1",
"blitz": "0.21.2-canary.1",
"blitz": "0.23.2",
"react": "0.0.0-experimental-7f28234f8",
"react-dom": "0.0.0-experimental-7f28234f8",
"typescript": "3.8.3"

View File

@@ -1,5 +1,5 @@
{
"version": "0.21.2-canary.1",
"version": "0.23.2",
"packages": ["packages/*"],
"npmClient": "yarn",
"useWorkspaces": true,

View File

@@ -34,7 +34,7 @@
"prepack": "cpy README.md packages/blitz/",
"postpack": "rimraf packages/blitz/README.md",
"publish-canary": "yarn run publish-prep && lerna publish --force-publish --preid canary --pre-dist-tag canary",
"publish-latest": "yarn run publish-prep && lerna publish --force-publish",
"publish-latest": "yarn run publish-prep && lerna publish --force-publish --allow-branch v*",
"publish-danger": "lerna publish --canary --pre-dist-tag danger --preid danger.$(git rev-parse --short HEAD) --allow-branch * --force-publish",
"danger:push-all": "git push --no-verify && git push --no-verify --tags"
},
@@ -94,6 +94,8 @@
"directory-tree": "2.2.4",
"eslint": "7.7.0",
"eslint-config-react-app": "5.2.1",
"eslint-plugin-es": "mysticatea/eslint-plugin-es",
"eslint-plugin-es5": "1.5.0",
"eslint-plugin-flowtype": "5.2.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jsx-a11y": "6.3.1",

View File

@@ -1,7 +1,7 @@
{
"name": "blitz",
"description": "Blitz is a Rails-like framework for monolithic, full-stack React apps — built on Next.js",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"license": "MIT",
"scripts": {
"clean": "rimraf dist",
@@ -39,11 +39,11 @@
"url": "https://github.com/blitz-js/blitz"
},
"dependencies": {
"@blitzjs/cli": "0.21.2-canary.1",
"@blitzjs/core": "0.21.2-canary.1",
"@blitzjs/generator": "0.21.2-canary.1",
"@blitzjs/installer": "0.21.2-canary.1",
"@blitzjs/server": "0.21.2-canary.1",
"@blitzjs/cli": "0.23.2",
"@blitzjs/core": "0.23.2",
"@blitzjs/generator": "0.23.2",
"@blitzjs/installer": "0.23.2",
"@blitzjs/server": "0.23.2",
"envinfo": "7.7.2",
"os-name": "3.1.0",
"pkg-dir": "4.2.0",

View File

@@ -5,12 +5,16 @@ import chalk from "chalk"
import {parseSemver} from "../utils/parse-semver"
async function main() {
console.log(
chalk.yellow(
`You are using alpha software - if you have any problems, please open an issue here:
https://github.com/blitz-js/blitz/issues/new/choose\n`,
),
)
const options = require("minimist")(process.argv.slice(2))
if (options._[0] !== "autocomplete:script" || Object.keys(options).length > 1) {
console.log(
chalk.yellow(
`You are using alpha software - if you have any problems, please open an issue here:
https://github.com/blitz-js/blitz/issues/new/choose\n`,
),
)
}
if (parseSemver(process.version).major < 12) {
console.log(
@@ -37,7 +41,6 @@ async function main() {
const cli = require(cliPkgPath)
const options = require("minimist")(process.argv.slice(2))
const hasVersionFlag = options._.length === 0 && (options.v || options.version)
const hasVerboseFlag = options._.length === 0 && (options.V || options.verbose)

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/cli",
"description": "Blitz.js CLI",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"license": "MIT",
"scripts": {
"b": "./bin/run",
@@ -30,14 +30,15 @@
"/lib"
],
"dependencies": {
"@blitzjs/display": "0.21.2-canary.1",
"@blitzjs/repl": "0.21.2-canary.1",
"@blitzjs/display": "0.23.2",
"@blitzjs/repl": "0.23.2",
"@oclif/command": "1.5.20",
"@oclif/config": "1.15.1",
"@oclif/plugin-autocomplete": "0.2.0",
"@oclif/plugin-help": "2.2.3",
"@oclif/plugin-not-found": "1.2.3",
"@prisma/sdk": "2.6.0",
"@salesforce/lazy-require": "0.3.2",
"camelcase": "6.0.0",
"chalk": "4.0.0",
"cross-spawn": "7.0.3",
@@ -54,12 +55,13 @@
"rimraf": "3.0.2",
"tar": "6.0.2",
"ts-node": "8.9.0",
"tsconfig-paths": "3.9.0"
"tsconfig-paths": "3.9.0",
"v8-compile-cache": "2.1.1"
},
"devDependencies": {
"@blitzjs/generator": "0.21.2-canary.1",
"@blitzjs/installer": "0.21.2-canary.1",
"@blitzjs/server": "0.21.2-canary.1",
"@blitzjs/generator": "0.23.2",
"@blitzjs/installer": "0.23.2",
"@blitzjs/server": "0.23.2",
"@oclif/dev-cli": "1.22.2",
"@oclif/test": "1.2.5",
"@prisma/cli": "2.4.1",

View File

@@ -1,6 +1,4 @@
import {Command} from "@oclif/command"
import {build} from "@blitzjs/server"
import {runPrismaGeneration} from "./db"
export class Build extends Command {
static description = "Create a production build"
@@ -12,7 +10,7 @@ export class Build extends Command {
}
try {
await build(config, runPrismaGeneration({silent: true, failSilently: true}))
await require("@blitzjs/server").build(config)
} catch (err) {
console.error(err)
process.exit(1) // clean up?

View File

@@ -1,16 +1,7 @@
import {runRepl} from "@blitzjs/repl"
import {Command} from "@oclif/command"
import path from "path"
import fs from "fs"
import pkgDir from "pkg-dir"
import {log} from "@blitzjs/display"
import chalk from "chalk"
import {setupTsnode} from "../utils/setup-ts-node"
import {runPrismaGeneration} from "./db"
const projectRoot = pkgDir.sync() || process.cwd()
const isTypescript = fs.existsSync(path.join(projectRoot, "tsconfig.json"))
const projectRoot = require("pkg-dir").sync() || process.cwd()
const isTypescript = require("fs").existsSync(require("path").join(projectRoot, "tsconfig.json"))
export class Console extends Command {
static description = "Run the Blitz console REPL"
@@ -22,19 +13,17 @@ export class Console extends Command {
}
async run() {
const {log} = require("@blitzjs/display")
const chalk = require("chalk")
log.branded("You have entered the Blitz console")
console.log(chalk.yellow("Tips: - Exit by typing .exit or pressing Ctrl-D"))
console.log(chalk.yellow(" - Use your db like this: await db.project.findMany()"))
console.log(chalk.yellow(" - Use your queries/mutations like this: await getProjects({})"))
const spinner = log.spinner("Loading your code").start()
if (isTypescript) {
setupTsnode()
require("../utils/setup-ts-node").setupTsnode()
}
await runPrismaGeneration({silent: true, failSilently: true})
spinner.succeed()
runRepl(Console.replOptions)
require("@blitzjs/repl").runRepl(Console.replOptions)
}
}

View File

@@ -1,17 +1,7 @@
import {resolveBinAsync} from "@blitzjs/server"
import {log} from "@blitzjs/display"
import {Command, flags} from "@oclif/command"
import chalk from "chalk"
import {spawn} from "cross-spawn"
import {prompt} from "enquirer"
import * as fs from "fs"
import * as path from "path"
import {promisify} from "util"
import {projectRoot} from "../utils/get-project-root"
import pEvent from "p-event"
import {getConfig, getSchema} from "@prisma/sdk"
import {log} from "@blitzjs/display"
const getPrismaBin = () => resolveBinAsync("@prisma/cli", "prisma")
const getPrismaBin = () => require("@blitzjs/server").resolveBinAsync("@prisma/cli", "prisma")
let prismaBin: string
let schemaArg: string
@@ -26,11 +16,11 @@ const runPrisma = async (args: string[], silent = false) => {
}
}
const cp = spawn(prismaBin, args, {
const cp = require("cross-spawn").spawn(prismaBin, args, {
stdio: silent ? "ignore" : "inherit",
env: process.env,
})
const code = await pEvent(cp, "exit", {rejectionEvents: []})
const code = await require("p-event")(cp, "exit", {rejectionEvents: []})
return code === 0
}
@@ -69,16 +59,17 @@ const runMigrateUp = async ({silent = false} = {}) => {
return runPrismaGeneration({silent})
}
export const runMigrate = async (name?: string) => {
export const runMigrate = async (flags: object = {}) => {
if (process.env.NODE_ENV === "production") {
return runMigrateUp()
}
// @ts-ignore escape:TS7053
const nestedFlags = Object.keys(flags).map((key) => [`--${key}`, flags[key]])
const options = ([] as string[]).concat(...nestedFlags)
const silent = Boolean(name)
const args = ["migrate", "save", schemaArg, "--create-db", "--experimental"]
if (name) {
args.push("--name", name)
}
const silent = options.includes("--name")
const args = ["migrate", "save", schemaArg, "--create-db", "--experimental", ...options]
const success = await runPrisma(args, silent)
@@ -131,8 +122,12 @@ export async function resetMysql(connectionString: string, db: any): Promise<voi
export async function resetSqlite(connectionString: string): Promise<void> {
const relativePath = connectionString.replace(/^file:/, "").replace(/^(?:\.\.[\\/])+/, "")
const dbPath = path.join(projectRoot, "db", relativePath)
const unlink = promisify(fs.unlink)
const dbPath = require("path").join(
require("../utils/get-project-root").projectRoot,
"db",
relativePath,
)
const unlink = require("util").promisify(require("fs").unlink)
try {
// delete database from folder
await unlink(dbPath)
@@ -156,17 +151,21 @@ export function getDbName(connectionString: string): string {
export class Db extends Command {
static description = `Run database commands
${chalk.bold("migrate")} Run any needed migrations via Prisma 2 and generate Prisma Client.
${require("chalk").bold(
"migrate",
)} Run any needed migrations via Prisma 2 and generate Prisma Client.
${chalk.bold(
${require("chalk").bold(
"introspect",
)} Will introspect the database defined in db/schema.prisma and automatically generate a complete schema.prisma file for you. Lastly, it'll generate Prisma Client.
${chalk.bold(
${require("chalk").bold(
"studio",
)} Open the Prisma Studio UI at http://localhost:5555 so you can easily see and change data in your database.
${chalk.bold("reset")} Reset the database and run a fresh migration via Prisma 2.
${require("chalk").bold(
"reset",
)} Reset the database and run a fresh migration via Prisma 2. You can also pass --force to skip all the user prompts.
`
static args = [
@@ -182,21 +181,25 @@ ${chalk.bold("reset")} Reset the database and run a fresh migration via Prisma
help: flags.help({char: "h"}),
// Used by `new` command to perform the initial migration
name: flags.string({hidden: true}),
// Used by `reset` command to skip the confirmation prompt
force: flags.boolean({char: "f", hidden: true}),
}
static strict = false
async run() {
const {args, flags} = this.parse(Db)
const command = args["command"]
// Needs to happen at run-time since the `new` command needs to change the cwd before running
const schemaPath = path.join(process.cwd(), "db", "schema.prisma")
const schemaPath = require("path").join(process.cwd(), "db", "schema.prisma")
schemaArg = `--schema=${schemaPath}`
if (command === "migrate" || command === "m") {
try {
return await runMigrate(flags.name)
return await runMigrate(flags)
} catch (error) {
if (flags.name) {
if (Object.keys(flags).length > 0) {
throw error
} else {
process.exit(1)
@@ -214,41 +217,45 @@ ${chalk.bold("reset")} Reset the database and run a fresh migration via Prisma
}
if (command === "reset") {
const spinner = log.spinner("Loading your database").start()
await runPrismaGeneration({silent: true, failSilently: true})
spinner.succeed()
const forceSkipConfirmation = flags.force
const {confirm} = await prompt<{confirm: string}>({
type: "confirm",
name: "confirm",
message: "Are you sure you want to reset your database and erase ALL data?",
})
if (!forceSkipConfirmation) {
const {confirm} = await require("enquirer").prompt({
type: "confirm",
name: "confirm",
message: "Are you sure you want to reset your database and erase ALL data?",
})
if (!confirm) {
return
if (!confirm) {
return
}
}
log.progress("Resetting your database...")
const {projectRoot} = require("../utils/get-project-root")
const prismaClientPath = require.resolve("@prisma/client", {paths: [projectRoot]})
const {PrismaClient} = require(prismaClientPath)
const db = new PrismaClient()
const schemaPath = path.join(projectRoot, "db/schema.prisma")
const datamodel = await getSchema(schemaPath)
const config = await getConfig({datamodel})
const schemaPath = require("path").join(projectRoot, "db/schema.prisma")
const datamodel = await require("@prisma/sdk").getSchema(schemaPath)
const config = await require("@prisma/sdk").getConfig({datamodel})
const dataSource = config.datasources[0]
const providerType = dataSource.activeProvider
const connectionString = dataSource.url.value
if (providerType === "postgresql") {
resetPostgres(connectionString, db)
await resetPostgres(connectionString, db)
return
} else if (providerType === "mysql") {
resetMysql(connectionString, db)
await resetMysql(connectionString, db)
return
} else if (providerType === "sqlite") {
resetSqlite(connectionString)
await resetSqlite(connectionString)
return
} else {
this.log("Could not find a valid database configuration")
log.error("Could not find a valid database configuration")
return
}
return
}
if (command === "help") {

View File

@@ -1,9 +1,6 @@
import {Command} from "../command"
import {flags} from "@oclif/command"
import * as fs from "fs"
import * as path from "path"
import enquirer from "enquirer"
import _pluralize from "pluralize"
import {log} from "@blitzjs/display"
import {
PageGenerator,
MutationGenerator,
@@ -13,15 +10,13 @@ import {
QueryGenerator,
} from "@blitzjs/generator"
import {PromptAbortedError} from "../errors/prompt-aborted"
import {log} from "@blitzjs/display"
import camelCase from "camelcase"
import pkgDir from "pkg-dir"
const debug = require("debug")("blitz:generate")
const pascalCase = (str: string) => camelCase(str, {pascalCase: true})
const projectRoot = pkgDir.sync() || process.cwd()
const isTypescript = fs.existsSync(path.join(projectRoot, "tsconfig.json"))
const pascalCase = (str: string) => require("camelcase")(str, {pascalCase: true})
const getIsTypescript = () =>
require("fs").existsSync(
require("path").join(require("../utils/get-project-root").projectRoot, "tsconfig.json"),
)
enum ResourceType {
All = "all",
@@ -46,18 +41,18 @@ interface Args {
}
function pluralize(input: string): string {
return _pluralize.isPlural(input) ? input : _pluralize.plural(input)
return require("pluralize").isPlural(input) ? input : require("pluralize").plural(input)
}
function singular(input: string): string {
return _pluralize.isSingular(input) ? input : _pluralize.singular(input)
return require("pluralize").isSingular(input) ? input : require("pluralize").singular(input)
}
function modelName(input: string = "") {
return camelCase(singular(input))
return require("camelcase")(singular(input))
}
function modelNames(input: string = "") {
return camelCase(pluralize(input))
return require("camelcase")(pluralize(input))
}
function ModelName(input: string = "") {
return pascalCase(singular(input))
@@ -157,31 +152,33 @@ export class Generate extends Command {
]
async promptForTargetDirectory(paths: string[]): Promise<string> {
return enquirer
.prompt<{directory: string}>({
return require("enquirer")
.prompt({
name: "directory",
type: "select",
message: "Please select a target directory:",
choices: paths,
})
.then((resp) => resp.directory)
.then((resp: any) => resp.directory)
}
async genericConfirmPrompt(message: string): Promise<boolean> {
return enquirer
.prompt<{continue: string}>({
return require("enquirer")
.prompt({
name: "continue",
type: "select",
message: message,
choices: ["Yes", "No"],
})
.then((resp) => resp.continue === "Yes")
.then((resp: any) => resp.continue === "Yes")
}
async handleNoContext(message: string): Promise<void> {
const shouldCreateNewRoot = await this.genericConfirmPrompt(message)
if (!shouldCreateNewRoot) {
log.error("Could not determine proper location for files. Aborting.")
require("@blitzjs/display").log.error(
"Could not determine proper location for files. Aborting.",
)
this.exit(0)
}
}
@@ -192,7 +189,7 @@ export class Generate extends Command {
if (modelSegments.length > 1) {
return {
model: modelSegments[modelSegments.length - 1],
context: path.join(...modelSegments.slice(0, modelSegments.length - 1)),
context: require("path").join(...modelSegments.slice(0, modelSegments.length - 1)),
}
}
@@ -201,7 +198,7 @@ export class Generate extends Command {
return {
model: modelName,
context: path.join(...contextSegments),
context: require("path").join(...contextSegments),
}
}
@@ -222,7 +219,7 @@ export class Generate extends Command {
const generators = generatorMap[args.type]
for (const GeneratorClass of generators) {
const generator = new GeneratorClass({
destinationRoot: path.resolve(),
destinationRoot: require("path").resolve(),
extraArgs: argv.slice(2).filter((arg) => !arg.startsWith("-")),
modelName: singularRootContext,
modelNames: modelNames(singularRootContext),
@@ -232,9 +229,10 @@ export class Generate extends Command {
parentModels: modelNames(flags.parent),
ParentModel: ModelName(flags.parent),
ParentModels: ModelNames(flags.parent),
rawInput: model,
dryRun: flags["dry-run"],
context: context,
useTs: isTypescript,
useTs: getIsTypescript(),
})
await generator.run()
}

View File

@@ -1,22 +1,14 @@
import {Command} from "../command"
import * as path from "path"
import {RecipeExecutor} from "@blitzjs/installer"
import _got from "got"
import type {RecipeExecutor} from "@blitzjs/installer"
import {log} from "@blitzjs/display"
import {dedent} from "../utils/dedent"
import {Stream} from "stream"
import {promisify} from "util"
import tar from "tar"
import {mkdirSync, readFileSync, existsSync} from "fs-extra"
import rimraf from "rimraf"
import spawn from "cross-spawn"
import * as os from "os"
import {setupTsnode} from "../utils/setup-ts-node"
const pipeline = promisify(Stream.pipeline)
async function got(url: string) {
return _got(url).catch((e) => Boolean(console.error(e)) || e)
return require("got")(url).catch((e: any) => Boolean(console.error(e)) || e)
}
async function gotJSON(url: string) {
@@ -28,7 +20,7 @@ async function isUrlValid(url: string) {
}
function requireJSON(file: string) {
return JSON.parse(readFileSync(file).toString("utf-8"))
return JSON.parse(require("fs-extra").readFileSync(file).toString("utf-8"))
}
const GH_ROOT = "https://github.com/"
@@ -115,10 +107,13 @@ export class Install extends Command {
defaultBranch: string,
subdirectory?: string,
): Promise<string> {
const recipeDir = path.join(os.tmpdir(), `blitz-recipe-${repoFullName.replace("/", "-")}`)
const recipeDir = require("path").join(
require("os").tmpdir(),
`blitz-recipe-${repoFullName.replace("/", "-")}`,
)
// clean up from previous run in case of error
rimraf.sync(recipeDir)
mkdirSync(recipeDir)
require("rimraf").sync(recipeDir)
require("fs-extra").mkdirSync(recipeDir)
process.chdir(recipeDir)
const repoName = repoFullName.split("/")[1]
@@ -127,8 +122,8 @@ export class Install extends Command {
const extractPath = subdirectory ? [`${repoName}-${defaultBranch}/${subdirectory}`] : undefined
const depth = subdirectory ? subdirectory.split("/").length + 1 : 1
await pipeline(
_got.stream(`${CODE_ROOT}${repoFullName}/tar.gz/${defaultBranch}`),
tar.extract({strip: depth}, extractPath),
require("got").stream(`${CODE_ROOT}${repoFullName}/tar.gz/${defaultBranch}`),
require("tar").extract({strip: depth}, extractPath),
)
return recipeDir
@@ -149,9 +144,11 @@ export class Install extends Command {
}
async run() {
setupTsnode()
require("../utils/setup-ts-node").setupTsnode()
const {args} = this.parse(Install)
const pkgManager = existsSync(path.resolve("yarn.lock")) ? "yarn" : "npm"
const pkgManager = require("fs-extra").existsSync(require("path").resolve("yarn.lock"))
? "yarn"
: "npm"
const originalCwd = process.cwd()
const recipeInfo = this.normalizeRecipePath(args.recipe)
@@ -178,21 +175,21 @@ export class Install extends Command {
spinner = log.spinner("Installing package.json dependencies").start()
await new Promise((resolve) => {
const installProcess = spawn(pkgManager, ["install"])
const installProcess = require("cross-spawn")(pkgManager, ["install"])
installProcess.on("exit", resolve)
})
spinner.stop()
const recipePackageMain = requireJSON("./package.json").main
const recipeEntry = path.resolve(recipePackageMain)
const recipeEntry = require("path").resolve(recipePackageMain)
process.chdir(originalCwd)
await this.installRecipeAtPath(recipeEntry)
rimraf.sync(recipeRepoPath)
require("rimraf").sync(recipeRepoPath)
}
} else {
await this.installRecipeAtPath(path.resolve(args.recipe))
await this.installRecipeAtPath(require("path").resolve(args.recipe))
}
}
}

View File

@@ -1,14 +1,11 @@
import * as path from "path"
import {flags} from "@oclif/command"
import {Command} from "../command"
import {AppGenerator, AppGeneratorOptions} from "@blitzjs/generator"
import type {AppGeneratorOptions} from "@blitzjs/generator"
import chalk from "chalk"
import hasbin from "hasbin"
import {log} from "@blitzjs/display"
const debug = require("debug")("blitz:new")
import {PromptAbortedError} from "../errors/prompt-aborted"
import {Db} from "./db"
export interface Flags {
ts: boolean
@@ -60,8 +57,8 @@ export class New extends Command {
debug("flags: ", flags)
try {
const destinationRoot = path.resolve(args.name)
const appName = path.basename(destinationRoot)
const destinationRoot = require("path").resolve(args.name)
const appName = require("path").basename(destinationRoot)
const formChoices: Array<{name: AppGeneratorOptions["form"]; message?: string}> = [
{name: "React Final Form", message: "React Final Form (recommended)"},
@@ -78,7 +75,7 @@ export class New extends Command {
const {"dry-run": dryRun, "skip-install": skipInstall, npm} = flags
const generator = new AppGenerator({
const generator = new (require("@blitzjs/generator").AppGenerator)({
destinationRoot,
appName,
dryRun,
@@ -105,7 +102,7 @@ export class New extends Command {
try {
// Required in order for DATABASE_URL to be available
require("dotenv-expand")(require("dotenv-flow").config({silent: true}))
await Db.run(["migrate", "--name", "Initial Migration"])
await require("./db").Db.run(["migrate", "--name", "Initial Migration"])
spinner.succeed()
} catch {
spinner.fail()

View File

@@ -1,12 +1,5 @@
import {dev, prod} from "@blitzjs/server"
import {Command, flags} from "@oclif/command"
import fs from "fs"
import path from "path"
import pkgDir from "pkg-dir"
import {runPrismaGeneration} from "./db"
const projectRoot = pkgDir.sync() || process.cwd()
const isTypescript = fs.existsSync(path.join(projectRoot, "tsconfig.json"))
export class Start extends Command {
static description = "Start a development server"
@@ -24,24 +17,26 @@ export class Start extends Command {
char: "H",
description: "Set server hostname",
}),
inspect: flags.boolean({
description: "Enable the Node.js inspector",
}),
}
async run() {
const {flags} = this.parse(Start)
const config = {
rootFolder: process.cwd(),
port: flags.port,
hostname: flags.hostname,
isTypescript,
inspect: flags.inspect,
}
try {
if (flags.production) {
await prod(config, runPrismaGeneration({silent: true, failSilently: true}))
await prod(config)
} else {
await dev(config, runPrismaGeneration({silent: true, failSilently: true}))
await dev(config)
}
} catch (err) {
console.error(err)

View File

@@ -1,6 +1,5 @@
import {spawn} from "cross-spawn"
import {Command} from "@oclif/command"
import hasYarn from "has-yarn"
export class Test extends Command {
static description = "Run project tests"
@@ -20,7 +19,7 @@ export class Test extends Command {
if (watch) {
watchMode = watch === "watch" || watch === "w"
}
const packageManager = hasYarn() ? "yarn" : "npm"
const packageManager = require("has-yarn")() ? "yarn" : "npm"
if (watchMode) spawn(packageManager, ["test:watch"], {stdio: "inherit"})
else spawn(packageManager, ["test"], {stdio: "inherit"})

View File

@@ -1,3 +1,7 @@
require("v8-compile-cache")
const cacheFile = require("path").join(__dirname, ".blitzjs-cli-cache")
const lazyLoad = require("@salesforce/lazy-require").default.create(cacheFile)
lazyLoad.start()
import {run as oclifRun} from "@oclif/command"
// Load the .env environment variable so it's available for all commands

View File

@@ -37,30 +37,11 @@ jest.mock(
}),
)
jest.mock(
"../../src/commands/db",
jest.fn(() => {
return {
runPrismaGeneration: jest.fn(),
}
}),
)
describe("Console command", () => {
beforeEach(() => {
jest.resetAllMocks()
})
it("runs PrismaGeneration", async () => {
await Console.prototype.run()
expect(db.runPrismaGeneration).toHaveBeenCalled()
})
it("runs PrismaGeneration with silent allowed", async () => {
await Console.prototype.run()
expect(db.runPrismaGeneration).toHaveBeenCalledWith({silent: true, failSilently: true})
})
it("runs repl", async () => {
await Console.prototype.run()
expect(repl.runRepl).toHaveBeenCalled()

View File

@@ -17,6 +17,7 @@ let migrateSaveParams: any[]
let migrateUpDevParams: any[]
let migrateUpProdParams: any[]
let migrateSaveWithNameParams: any[]
let migrateSaveWithUnknownParams: any[]
beforeAll(async () => {
schemaArg = `--schema=${path.join(process.cwd(), "db", "schema.prisma")}`
prismaBin = await resolveBinAsync("@prisma/cli", "prisma")
@@ -41,6 +42,11 @@ beforeAll(async () => {
["migrate", "save", schemaArg, "--create-db", "--experimental", "--name", "name"],
{stdio: "ignore", env: process.env},
]
migrateSaveWithUnknownParams = [
prismaBin,
["migrate", "save", schemaArg, "--create-db", "--experimental"],
{stdio: "inherit", env: process.env},
]
})
describe("Db command", () => {
@@ -76,6 +82,13 @@ describe("Db command", () => {
expect(onSpy).toHaveBeenCalledTimes(3)
}
function expectDbMigrateWithUnknownFlag() {
expect(spawn).toBeCalledWith(...migrateSaveWithUnknownParams)
expect(spawn).toHaveBeenCalledTimes(3)
expect(onSpy).toHaveBeenCalledTimes(3)
}
it("runs db help when no command given", async () => {
// When running the help command oclif exits with code 0
// Unfortantely it treats this as an exception and throws accordingly
@@ -137,6 +150,18 @@ describe("Db command", () => {
expectProductionDbMigrateOutcome()
})
it("runs db migrate silently with the right args when name flag is used", async () => {
await Db.run(["migrate", "--name", "name"])
expectDbMigrateWithNameOutcome()
})
it("runs db migrate. (with unknown flags)", async () => {
await Db.run(["migrate", "--hoge", "aaa"])
expectDbMigrateWithUnknownFlag()
})
it("runs db introspect", async () => {
await Db.run(["introspect"])
@@ -164,10 +189,4 @@ describe("Db command", () => {
expect(spawn.mock.calls.length).toBe(0)
})
it("runs db migrate silently with the right args when name flag is used", async () => {
await Db.run(["migrate", "--name", "name"])
expectDbMigrateWithNameOutcome()
})
})

View File

@@ -10,6 +10,7 @@
"sourceMap": false,
"esModuleInterop": true,
"types": [],
"noEmit": false,
"lib": ["dom", "dom.iterable", "ES2018"]
},
"include": ["src/**/*", "types"],

View File

@@ -7,7 +7,7 @@
"config"
],
"author": "Fran Zekan <zekan.fran369@gmail.com>",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"license": "MIT",
"scripts": {
"clean": "rimraf dist",

View File

@@ -0,0 +1,17 @@
module.exports = {
extends: ["../../.eslintrc.js"],
plugins: ["es5", "es"],
rules: {
"es5/no-for-of": "error",
"es/no-object-fromentries": "error",
"es5/no-generators": "error",
"es5/no-typeof-symbol": "error",
"es5/no-es6-methods": "error",
"es5/no-es6-static-methods": [
"error",
{
exceptMethods: ["Object.assign"],
},
],
},
}

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/core",
"description": "Blitz.js core functionality",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"license": "MIT",
"scripts": {
"clean": "rimraf dist",
@@ -40,11 +40,13 @@
"url": "https://github.com/blitz-js/blitz"
},
"dependencies": {
"@blitzjs/config": "0.21.2-canary.1",
"@blitzjs/display": "0.21.2-canary.1",
"@blitzjs/config": "0.23.2",
"@blitzjs/display": "0.23.2",
"bad-behavior": "1.0.1",
"cookie-session": "1.4.0",
"deepmerge": "4.2.2",
"lodash": "^4.17.19",
"lodash-es": "^4.17.15",
"passport": "0.4.1",
"pretty-ms": "6.0.1",
"react-query": "2.5.11",

View File

@@ -1,4 +1,4 @@
import {NextPage, NextComponentType} from "next"
import {NextPage, NextComponentType, NextPageContext} from "next"
import {AppProps as NextAppProps} from "next/app"
export * from "./use-query"
@@ -49,10 +49,10 @@ export {default as dynamic} from "next/dynamic"
export {default as ErrorComponent} from "next/error"
export type BlitzComponentType = NextComponentType
export type BlitzComponentType<C = NextPageContext, IP = {}, P = {}> = NextComponentType<C, IP, P>
export interface AppProps extends NextAppProps {
Component: BlitzComponentType & {
export interface AppProps<P = {}> extends NextAppProps<P> {
Component: BlitzComponentType<NextPageContext, any, P> & {
getLayout?: (component: JSX.Element) => JSX.Element
}
}

View File

@@ -1,10 +1,14 @@
/* eslint-disable es5/no-for-of -- file only used on the server */
/* eslint-disable es5/no-es6-methods -- file only used on the server */
import {BlitzApiRequest, BlitzApiResponse} from "."
import {IncomingMessage, ServerResponse} from "http"
import {EnhancedResolverModule} from "./rpc"
import {getConfig} from "@blitzjs/config"
import {log} from "@blitzjs/display"
export interface MiddlewareRequest extends BlitzApiRequest {}
export interface MiddlewareRequest extends BlitzApiRequest {
protocol?: string
}
export interface MiddlewareResponse extends BlitzApiResponse {
/**
* This will be passed as the second argument to Blitz queries/mutations.

View File

@@ -1,4 +1,6 @@
import {BlitzApiRequest, BlitzApiResponse} from "."
/* eslint-disable es5/no-for-of -- file only used on the server */
/* eslint-disable es5/no-es6-methods -- file only used on the server */
import {BlitzApiRequest, BlitzApiResponse, ConnectMiddleware} from "."
import {
getAllMiddlewareForModule,
handleRequestWithMiddleware,
@@ -7,14 +9,17 @@ import {
} from "./middleware"
import {SessionContext, PublicData} from "./supertokens"
import {log} from "@blitzjs/display"
import passport, {Strategy} from "passport"
import passport, {AuthenticateOptions, Strategy} from "passport"
import cookieSession from "cookie-session"
import {isLocalhost} from "./utils/index"
import {secureProxyMiddleware} from "./secure-proxy-middleware"
export type BlitzPassportConfig = {
successRedirectUrl?: string
errorRedirectUrl?: string
authenticateOptions?: AuthenticateOptions
strategies: Required<Strategy>[]
secureProxy?: boolean
}
export type VerifyCallbackResult = {
@@ -34,19 +39,23 @@ const INTERNAL_REDIRECT_URL_KEY = "_redirectUrl"
export function passportAuth(config: BlitzPassportConfig) {
return async function authHandler(req: BlitzApiRequest, res: BlitzApiResponse) {
const cookieSessionMiddleware = cookieSession({
secret: process.env.SESSION_SECRET_KEY || "default-dev-secret",
secure: process.env.NODE_ENV === "production" && !isLocalhost(req),
})
const passportMiddleware = passport.initialize()
const middleware: Middleware[] = [
// TODO - fix TS type - shouldn't need `any` here
connectMiddleware(
cookieSession({
secret: process.env.SESSION_SECRET_KEY || "default-dev-secret",
secure: process.env.NODE_ENV === "production" && !isLocalhost(req),
}) as any,
),
// TODO - fix TS type - shouldn't need `any` here
connectMiddleware(passport.initialize() as any),
connectMiddleware(cookieSessionMiddleware as ConnectMiddleware),
connectMiddleware(passportMiddleware as ConnectMiddleware),
connectMiddleware(passport.session()),
]
if (config.secureProxy) {
middleware.push(secureProxyMiddleware)
}
if (!req.query.auth.length) {
return res.status(404).end()
}
@@ -71,7 +80,9 @@ export function passportAuth(config: BlitzPassportConfig) {
return next()
})
}
middleware.push(connectMiddleware(passport.authenticate(strategy.name)))
middleware.push(
connectMiddleware(passport.authenticate(strategy.name, {...config.authenticateOptions})),
)
} else if (req.query.auth[1] === "callback") {
log.info(`Processing callback for ${strategy.name}...`)
middleware.push(

View File

@@ -19,7 +19,7 @@ type Options = {
resultOfGetFetchMore?: any
}
export async function executeRpcCall(url: string, params: any, opts: Options = {}) {
export function executeRpcCall(url: string, params: any, opts: Options = {}) {
if (typeof window === "undefined") return
const headers: Record<string, any> = {
@@ -46,56 +46,70 @@ export async function executeRpcCall(url: string, params: any, opts: Options = {
serialized = serialize(params)
}
const result = await window.fetch(url, {
method: "POST",
headers,
credentials: "include",
redirect: "follow",
body: JSON.stringify({
// TODO remove `|| null` once superjson allows `undefined`
params: serialized.json || null,
meta: {
params: serialized.meta,
},
}),
})
// Create a new AbortController instance for this request
const controller = new AbortController()
if (result.headers) {
for (const [name] of result.headers.entries()) {
if (name.toLowerCase() === HEADER_PUBLIC_DATA_TOKEN) publicDataStore.updateState()
if (name.toLowerCase() === HEADER_SESSION_REVOKED) publicDataStore.clear()
if (name.toLowerCase() === HEADER_CSRF_ERROR) {
throw new CSRFTokenMismatchError()
const promise: CancellablePromise<any> = window
.fetch(url, {
method: "POST",
headers,
credentials: "include",
redirect: "follow",
body: JSON.stringify({
// TODO remove `|| null` once superjson allows `undefined`
params: serialized.json || null,
meta: {
params: serialized.meta,
},
}),
signal: controller.signal,
})
.then(async (result) => {
if (result.headers) {
if (result.headers.get(HEADER_PUBLIC_DATA_TOKEN)) {
publicDataStore.updateState()
}
if (result.headers.get(HEADER_SESSION_REVOKED)) {
publicDataStore.clear()
}
if (result.headers.get(HEADER_CSRF_ERROR)) {
throw new CSRFTokenMismatchError()
}
}
}
}
let payload
try {
payload = await result.json()
} catch (error) {
throw new Error(`Failed to parse json from request to ${url}`)
}
let payload
try {
payload = await result.json()
} catch (error) {
throw new Error(`Failed to parse json from request to ${url}`)
}
if (payload.error) {
const error = deserializeError(payload.error)
// We don't clear the publicDataStore for anonymous users
if (error.name === "AuthenticationError" && publicDataStore.getData().userId) {
publicDataStore.clear()
}
throw error
} else {
const data =
payload.result === undefined
? undefined
: deserialize({json: payload.result, meta: payload.meta?.result})
if (payload.error) {
const error = deserializeError(payload.error)
// We don't clear the publicDataStore for anonymous users
if (error.name === "AuthenticationError" && publicDataStore.getData().userId) {
publicDataStore.clear()
}
throw error
} else {
const data =
payload.result === undefined
? undefined
: deserialize({json: payload.result, meta: payload.meta?.result})
if (!opts.fromQueryHook) {
const queryKey = getQueryKey(url, params)
queryCache.setQueryData(queryKey, data)
}
return data
}
if (!opts.fromQueryHook) {
const queryKey = getQueryKey(url, params)
queryCache.setQueryData(queryKey, data)
}
return data
}
})
// Disable react-query request cancellation for now
// Having too many weird bugs with it enabled
// promise.cancel = () => controller.abort()
return promise
}
executeRpcCall.warm = (url: string) => {
@@ -113,13 +127,18 @@ interface ResolverEnhancement {
apiUrl: string
}
}
interface CancellablePromise<T> extends Promise<T> {
cancel?: Function
}
export interface RpcFunction {
(params: any, opts: any): Promise<any>
(params: any, opts: any): CancellablePromise<any>
}
export interface EnhancedRpcFunction extends RpcFunction, ResolverEnhancement {}
export interface EnhancedResolverModule extends ResolverEnhancement {
(input: any, ctx: Record<string, any>): Promise<unknown>
(input: any, ctx: Record<string, any>): CancellablePromise<unknown>
middleware?: Middleware[]
}

View File

@@ -0,0 +1,54 @@
// @ts-ignore
import {Request} from "express"
import {secureProxyMiddleware} from "./secure-proxy-middleware"
import {Socket} from "net"
// @ts-ignore
let reqSecure: Request = {
connection: new Socket(),
method: "GET",
url: "/stuff?q=thing",
headers: {
"x-forwarded-proto": "https",
},
}
// @ts-ignore
let reqHttp: Request = {
connection: new Socket(),
method: "GET",
url: "/stuff?q=thing",
headers: {
"x-forwarded-proto": "http",
},
}
// @ts-ignore
let reqNoHeader: Request = {
connection: new Socket(),
method: "GET",
url: "/stuff?q=thing",
}
const res = {}
describe("secure proxy middleware", () => {
it("should set https protocol if X-Forwarded-Proto is https", () => {
// @ts-ignore
secureProxyMiddleware(reqSecure, res, () => null)
expect(reqSecure.protocol).toEqual("https")
})
it("should set http protocol if X-Forwarded-Proto is absent", () => {
// @ts-ignore
secureProxyMiddleware(reqNoHeader, res, () => null)
expect(reqNoHeader.protocol).toEqual("http")
})
it("should set http protocol if X-Forwarded-Proto is http", () => {
// @ts-ignore
secureProxyMiddleware(reqHttp, res, () => null)
expect(reqHttp.protocol).toEqual("http")
})
})

View File

@@ -0,0 +1,23 @@
import {Middleware, MiddlewareRequest, MiddlewareResponse} from "middleware"
export const secureProxyMiddleware: Middleware = function (
req: MiddlewareRequest,
_res: MiddlewareResponse,
next: (error?: Error) => void,
) {
req.protocol = getProtocol(req)
next()
}
function getProtocol(req: MiddlewareRequest) {
// @ts-ignore
// For some reason there is no encrypted on socket while it is expected
if (req.connection.encrypted) {
return "https"
}
const forwardedProto = req.headers && (req.headers["x-forwarded-proto"] as string)
if (forwardedProto) {
return forwardedProto.split(/\s*,\s*/)[0]
}
return "http"
}

View File

@@ -3,7 +3,7 @@ import {
InfiniteQueryResult,
InfiniteQueryOptions,
} from "react-query"
import {useIsDevPrerender, emptyQueryFn, retryFunction} from "./use-query"
import {emptyQueryFn, retryFunction} from "./use-query"
import {PromiseReturnType, InferUnaryParam, QueryFn} from "./types"
import {getQueryCacheFunctions, QueryCacheFunctions, getInfiniteQueryKey} from "./utils/query-cache"
import {EnhancedRpcFunction} from "./rpc"
@@ -14,6 +14,8 @@ type RestQueryResult<T extends QueryFn> = Omit<
> &
QueryCacheFunctions<PromiseReturnType<T>[]>
const isServer = typeof window === "undefined"
export function useInfiniteQuery<T extends QueryFn>(
queryFn: T,
params: InferUnaryParam<T> | (() => InferUnaryParam<T>),
@@ -29,9 +31,7 @@ export function useInfiniteQuery<T extends QueryFn>(
)
}
const queryRpcFn = useIsDevPrerender()
? emptyQueryFn
: ((queryFn as unknown) as EnhancedRpcFunction)
const queryRpcFn = isServer ? emptyQueryFn : ((queryFn as unknown) as EnhancedRpcFunction)
const queryKey = getInfiniteQueryKey(queryFn, params)

View File

@@ -3,7 +3,7 @@ import {
PaginatedQueryResult,
QueryOptions,
} from "react-query"
import {useIsDevPrerender, emptyQueryFn, retryFunction} from "./use-query"
import {emptyQueryFn, retryFunction} from "./use-query"
import {PromiseReturnType, InferUnaryParam, QueryFn} from "./types"
import {QueryCacheFunctions, getQueryCacheFunctions, getQueryKey} from "./utils/query-cache"
import {EnhancedRpcFunction} from "./rpc"
@@ -14,10 +14,12 @@ type RestQueryResult<T extends QueryFn> = Omit<
> &
QueryCacheFunctions<PromiseReturnType<T>>
const isServer = typeof window === "undefined"
export function usePaginatedQuery<T extends QueryFn>(
queryFn: T,
params: InferUnaryParam<T> | (() => InferUnaryParam<T>),
options?: QueryOptions<PaginatedQueryResult<PromiseReturnType<T>>>,
options?: QueryOptions<PromiseReturnType<T>>,
): [PromiseReturnType<T>, RestQueryResult<T>] {
if (typeof queryFn === "undefined") {
throw new Error("usePaginatedQuery is missing the first argument - it must be a query function")
@@ -29,9 +31,7 @@ export function usePaginatedQuery<T extends QueryFn>(
)
}
const queryRpcFn = useIsDevPrerender()
? emptyQueryFn
: ((queryFn as unknown) as EnhancedRpcFunction)
const queryRpcFn = isServer ? emptyQueryFn : ((queryFn as unknown) as EnhancedRpcFunction)
const queryKey = getQueryKey(queryFn, params)

View File

@@ -1,5 +1,6 @@
import {useRouter} from "next/router"
import {useRouterQuery} from "./use-router-query"
import {fromPairs} from "lodash"
type ParsedUrlQueryValue = string | string[] | undefined
@@ -31,7 +32,7 @@ function areQueryValuesEqual(value1: ParsedUrlQueryValue, value2: ParsedUrlQuery
}
export function extractRouterParams(routerQuery: ParsedUrlQuery, query: ParsedUrlQuery) {
return Object.fromEntries(
return fromPairs(
Object.entries(routerQuery).filter(
([key, value]) =>
typeof query[key] === "undefined" || !areQueryValuesEqual(value, query[key]),
@@ -51,9 +52,9 @@ export function useParams(returnType?: "string" | "number" | "array") {
if (returnType === "string") {
const params: Record<string, string> = {}
for (const [key, value] of Object.entries(rawParams)) {
if (typeof value === "string") {
params[key] = value
for (const key in rawParams) {
if (typeof rawParams[key] === "string") {
params[key] = rawParams[key] as string
}
}
return params
@@ -61,9 +62,9 @@ export function useParams(returnType?: "string" | "number" | "array") {
if (returnType === "number") {
const params: Record<string, number> = {}
for (const [key, value] of Object.entries(rawParams)) {
if (value) {
params[key] = Number(value)
for (const key in rawParams) {
if (rawParams[key]) {
params[key] = Number(rawParams[key])
}
}
return params
@@ -71,9 +72,9 @@ export function useParams(returnType?: "string" | "number" | "array") {
if (returnType === "array") {
const params: Record<string, Array<string | undefined>> = {}
for (const [key, value] of Object.entries(rawParams)) {
if (Array.isArray(value)) {
params[key] = value
for (const key in rawParams) {
if (Array.isArray(rawParams[key])) {
params[key] = rawParams[key] as Array<string | undefined>
}
}
return params

View File

@@ -19,17 +19,6 @@ export const emptyQueryFn: EnhancedRpcFunction = (() => {
const isServer = typeof window === "undefined"
// NOTE - this is only for use inside useQuery
export const useIsDevPrerender = () => {
if (process.env.NODE_ENV === "production") {
return false
} else {
// useQuery is only for client-side data fetching, so if it's running on the
// server, it's for pre-render
return isServer
}
}
export const retryFunction = (failureCount: number, error: any) => {
if (process.env.NODE_ENV !== "production") return false
@@ -42,7 +31,7 @@ export const retryFunction = (failureCount: number, error: any) => {
export function useQuery<T extends QueryFn>(
queryFn: T,
params: InferUnaryParam<T> | (() => InferUnaryParam<T>),
options?: QueryOptions<QueryResult<PromiseReturnType<T>>>,
options?: QueryOptions<PromiseReturnType<T>>,
): [PromiseReturnType<T>, RestQueryResult<T>] {
if (typeof queryFn === "undefined") {
throw new Error("useQuery is missing the first argument - it must be a query function")
@@ -54,9 +43,7 @@ export function useQuery<T extends QueryFn>(
)
}
const queryRpcFn = useIsDevPrerender()
? emptyQueryFn
: ((queryFn as unknown) as EnhancedRpcFunction)
const queryRpcFn = isServer ? emptyQueryFn : ((queryFn as unknown) as EnhancedRpcFunction)
const queryKey = getQueryKey(queryFn, params)

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/display",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "Display package for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/file-pipeline",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "Display package for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",

View File

@@ -1,11 +1,10 @@
import {pipe} from "../streams"
import {createPipeline} from "../pipeline"
import {pathExists, ensureDir, remove} from "fs-extra"
import {through} from "../streams"
import {createDisplay} from "../display"
import {READY, ERROR_THROWN} from "../events"
import {Stage} from "../types"
import {ensureDir, pathExists, remove} from "fs-extra"
import {Transform} from "stream"
import {createDisplay} from "../display"
import {ERROR_THROWN, READY} from "../events"
import {createPipeline} from "../pipeline"
import {pipe, through} from "../streams"
import {Stage} from "../types"
type FSStreamer = {stream: NodeJS.ReadWriteStream}
@@ -17,7 +16,6 @@ type SynchronizeFilesOptions = {
source?: FSStreamer
writer?: FSStreamer
noclean?: boolean
isTypescript?: boolean
}
const defaultBus = through.obj()
@@ -42,7 +40,6 @@ export async function transformFiles(
source,
writer,
noclean = false,
isTypescript = true,
} = options
// HACK: cleaning the dev folder on every restart means we do more work than necessary
@@ -59,7 +56,6 @@ export async function transformFiles(
include,
ignore,
watch,
isTypescript,
}
const fileTransformPipeline = createPipeline(config, stages, bus, source, writer)

View File

@@ -1,6 +1,6 @@
import {Writable} from "stream"
import {FileCache} from "./helpers/file-cache"
import File from "vinyl"
import {FileCache} from "./helpers/file-cache"
export type EventedFile = {
event: "add" | "change" | "unlink" | "unlinkDir"
@@ -21,7 +21,6 @@ export type StageConfig = {
include: string[]
ignore: string[]
watch: boolean
isTypescript: boolean
}
/**

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/generator",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "File generation for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",
@@ -36,7 +36,7 @@
"dependencies": {
"@babel/core": "7.9.0",
"@babel/plugin-transform-typescript": "7.9.4",
"@blitzjs/display": "0.21.2-canary.1",
"@blitzjs/display": "0.23.2",
"@types/jscodeshift": "0.7.1",
"chalk": "4.0.0",
"cross-spawn": "7.0.3",
@@ -48,7 +48,7 @@
"jscodeshift": "0.10.0",
"mem-fs": "1.1.3",
"mem-fs-editor": "6.0.0",
"node-fetch": "2.6.0",
"node-fetch": "2.6.1",
"pluralize": "8.0.0",
"recast": "0.19.1",
"username": "5.1.0",

View File

@@ -1,5 +1,6 @@
import {Generator, GeneratorOptions} from "../generator"
import {join} from "path"
import {camelCaseToKebabCase} from "../utils/kebab-case"
export interface PageGeneratorOptions extends GeneratorOptions {
ModelName: string
@@ -51,9 +52,10 @@ export class PageGenerator extends Generator<PageGeneratorOptions> {
}
getTargetDirectory() {
const kebabCaseModelName = camelCaseToKebabCase(this.options.modelNames)
const parent = this.options.parentModels
? `${this.options.parentModels}/__parentModelParam__/`
: ""
return `app/${this.getModelNamesPath()}/pages/${parent}${this.options.modelNames}`
return `app/${this.getModelNamesPath()}/pages/${parent}${kebabCaseModelName}`
}
}

View File

@@ -2,7 +2,7 @@ import {Generator, GeneratorOptions} from "../generator"
import {join} from "path"
export interface QueryGeneratorOptions extends GeneratorOptions {
modelName: string
rawInput: string
}
export class QueryGenerator extends Generator<QueryGeneratorOptions> {
@@ -12,7 +12,7 @@ export class QueryGenerator extends Generator<QueryGeneratorOptions> {
// eslint-disable-next-line require-await
async getTemplateValues() {
return {
modelName: this.options.modelName,
rawInput: this.options.rawInput,
}
}

View File

@@ -0,0 +1,3 @@
export function camelCaseToKebabCase(transformString: string) {
return transformString.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase()
}

View File

@@ -6,6 +6,7 @@ type NpmDepResponse = {versions: Record<string, PackageInformation>}
export const fetchAllVersions = async (dependency: string) => {
const res = await got(`https://registry.npmjs.org/${dependency}`, {
retry: {limit: 3},
timeout: 3000,
responseType: "json",
}).json<NpmDepResponse>()
return Object.keys(res.versions)
@@ -16,6 +17,7 @@ type NpmDistTagsResponse = {latest: string; canary: string}
export const fetchDistTags = async (dependency: string) => {
const res = await got(`https://registry.npmjs.org/-/package/${dependency}/dist-tags`, {
retry: {limit: 3},
timeout: 3000,
responseType: "json",
}).json<NpmDistTagsResponse>()
return res

View File

@@ -1,7 +1,8 @@
# This env file should NOT be checked into source control
# This is the place for values that changed for every developer
# SQLite is ready to go out of the box, but you can switch to Postgres easily
# by swapping the DATABASE_URL.
# SQLite is ready to go out of the box, but you can switch to Postgres
# by first changing the provider from "sqlite" to "postgres" in the Prisma
# schema file and by second swapping the DATABASE_URL below.
DATABASE_URL="file:./db.sqlite"
# DATABASE_URL=postgresql://__username__@localhost:5432/__name__

View File

@@ -1,6 +1,7 @@
# THIS FILE SHOULD NOT BE CHECKED INTO YOUR VERSION CONTROL SYSTEM
# SQLite is ready to go out of the box, but you can switch to Postgres easily
# by swapping the DATABASE_URL.
# SQLite is ready to go out of the box, but you can switch to Postgres
# by first changing the provider from "sqlite" to "postgres" in the Prisma
# schema file and by second swapping the DATABASE_URL below.
DATABASE_URL="file:./db_test.sqlite"
# DATABASE_URL=postgresql://__username__@localhost:5432/__name___test

View File

@@ -18,6 +18,8 @@ export const LabeledTextField = React.forwardRef<HTMLInputElement, LabeledTextFi
meta: {touched, error, submitError, submitting},
} = useField(name)
const normalizedError = Array.isArray(error) ? error.join(", ") : error || submitError
return (
<div {...outerProps}>
<label>
@@ -25,9 +27,9 @@ export const LabeledTextField = React.forwardRef<HTMLInputElement, LabeledTextFi
<input {...input} disabled={submitting} {...props} ref={ref} />
</label>
{touched && (error || submitError) && (
{touched && normalizedError && (
<div role="alert" style={{color: "red"}}>
{error || submitError}
{normalizedError}
</div>
)}

View File

@@ -18,7 +18,7 @@ export const verifyPassword = async (hashedPassword: string, password: string) =
}
export const authenticateUser = async (email: string, password: string) => {
const user = await db.user.findOne({ where: { email } })
const user = await db.user.findOne({ where: { email: email.toLowerCase() } })
if (!user || !user.hashedPassword) throw new AuthenticationError()

View File

@@ -1,4 +1,5 @@
import React from "react"
import { Link } from "blitz"
import { LabeledTextField } from "app/components/LabeledTextField"
import { Form, FORM_ERROR } from "app/components/Form"
import login from "app/auth/mutations/login"
@@ -36,6 +37,10 @@ export const LoginForm = (props: LoginFormProps) => {
<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>
)
}

View File

@@ -12,7 +12,7 @@ export default async function signup(
const hashedPassword = await hashPassword(password)
const user = await db.user.create({
data: { email, hashedPassword, role: "user" },
data: { email: email.toLowerCase(), hashedPassword, role: "user" },
select: { id: true, name: true, email: true, role: true },
})

View File

@@ -6,15 +6,17 @@ type LayoutProps = {
children: ReactNode
}
const Layout = ({ title, children }: LayoutProps) => (
<>
<Head>
<title>{title || "__name__"}</title>
<link rel="icon" href="/favicon.ico" />
</Head>
const Layout = ({ title, children }: LayoutProps) => {
return (
<>
<Head>
<title>{title || "__name__"}</title>
<link rel="icon" href="/favicon.ico" />
</Head>
{children}
</>
)
{children}
</>
)
}
export default Layout

View File

@@ -1,14 +1,16 @@
import { AppProps, ErrorComponent } from "blitz"
import { AppProps, ErrorComponent, useRouter } from "blitz"
import { ErrorBoundary, FallbackProps } from "react-error-boundary"
import { queryCache } from "react-query"
import LoginForm from "app/auth/components/LoginForm"
export default function App({ Component, pageProps }: AppProps) {
const getLayout = Component.getLayout || ((page) => page)
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

View File

@@ -2,7 +2,7 @@
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = ["sqlite", "postgres"]
provider = "sqlite"
url = env("DATABASE_URL")
}

View File

@@ -12,14 +12,17 @@
"browserslist": [
"defaults"
],
"prisma": {
"schema": "db/schema.prisma"
},
"prettier": {
"semi": false,
"printWidth": 100
},
"husky": {
"hooks": {
"pre-commit": "lint-staged && pretty-quick --staged",
"pre-push": "blitz test"
"pre-commit": "tsc && lint-staged && pretty-quick --staged",
"pre-push": "npm lint && npm test"
}
},
"lint-staged": {
@@ -39,13 +42,13 @@
},
"devDependencies": {
"@testing-library/jest-dom": "5.x",
"@testing-library/react": "10.x",
"@testing-library/react": "11.x",
"@testing-library/react-hooks": "3.x",
"@types/jest": "26.x",
"@types/react": "16.x",
"@types/secure-password": "3.x",
"@typescript-eslint/eslint-plugin": "3.x",
"@typescript-eslint/parser": "3.x",
"@typescript-eslint/eslint-plugin": "4.x",
"@typescript-eslint/parser": "4.x",
"babel-eslint": "10.x",
"eslint": "7.x",
"eslint-config-react-app": "5.x",
@@ -61,8 +64,8 @@
"react-test-renderer": "16.x",
"lint-staged": "10.x",
"prettier": "2.x",
"pretty-quick": "2.x",
"typescript": "3.x",
"pretty-quick": "3.x",
"typescript": "4.x",
"ts-jest": "26.x"
},
"private": true

View File

@@ -3,3 +3,4 @@
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom/extend-expect"
require("dotenv-flow").config({ silent: true })

View File

@@ -1,6 +0,0 @@
import {SessionContext} from "blitz"
import db from "db"
export default async function __modelName__(__, ctx: {session?: SessionContext} = {}) {
return ctx
}

View File

@@ -0,0 +1,6 @@
import {SessionContext} from "blitz"
import db from "db"
export default async function __rawInput__(__, ctx: {session?: SessionContext} = {}) {
return ctx
}

View File

@@ -0,0 +1,31 @@
import {camelCaseToKebabCase} from "../../src/utils/kebab-case"
describe("kebabCase utility function", () => {
describe("transform a camelCase string to kebab case", () => {
it("works for 2 word camelCase", () => {
const result = camelCaseToKebabCase("testResult")
expect(result).toBe("test-result")
})
it("works for multiple camelCase words", () => {
const result = camelCaseToKebabCase("longTestStringResult")
expect(result).toBe("long-test-string-result")
})
})
describe("do not transform strings that are not camelCase", () => {
it("does not modify a kebabCase string", () => {
const result = camelCaseToKebabCase("test-result")
expect(result).toBe("test-result")
})
it("does not modify single word string", () => {
const result = camelCaseToKebabCase("testresult")
expect(result).toBe("testresult")
})
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/installer",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "Package installation for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",
@@ -36,8 +36,8 @@
"dependencies": {
"@babel/core": "7.9.0",
"@babel/plugin-transform-typescript": "7.9.4",
"@blitzjs/display": "0.21.2-canary.1",
"@blitzjs/generator": "0.21.2-canary.1",
"@blitzjs/display": "0.23.2",
"@blitzjs/generator": "0.23.2",
"@types/jscodeshift": "0.7.1",
"chokidar": "3.4.2",
"cross-spawn": "7.0.3",

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/repl",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "Repl package for Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz/packages/repl/#readme",
"license": "MIT",

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/server",
"description": "Blitz.js server functionality",
"version": "0.21.2-canary.1",
"version": "0.23.2",
"license": "MIT",
"bin": {
"next-patched": "./bin/next-patched"
@@ -29,9 +29,9 @@
"module": "dist/server.esm.js",
"types": "dist/packages/server/src/index.d.ts",
"dependencies": {
"@blitzjs/config": "0.21.2-canary.1",
"@blitzjs/display": "0.21.2-canary.1",
"@blitzjs/file-pipeline": "0.21.2-canary.1",
"@blitzjs/config": "0.23.2",
"@blitzjs/display": "0.23.2",
"@blitzjs/file-pipeline": "0.23.2",
"b64-lite": "1.4.0",
"cookie": "0.4.1",
"cross-spawn": "7.0.3",
@@ -44,7 +44,8 @@
"gulp-if": "3.0.0",
"hasha": "5.2.0",
"jsonwebtoken": "8.5.1",
"lodash": "4.17.19",
"lodash": "^4.17.19",
"lodash-es": "^4.17.15",
"merge-stream": "2.0.0",
"nanoid": "3.1.10",
"next": "9.5.3",
@@ -66,7 +67,7 @@
"vinyl-fs": "3.0.3"
},
"devDependencies": {
"@blitzjs/core": "0.21.2-canary.1",
"@blitzjs/core": "0.23.2",
"next-transpile-modules": "3.2.0"
},
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922"

View File

@@ -16,6 +16,10 @@ export async function getInputArtefactsHash() {
".profile.d",
".cache",
".config",
"test",
"tests",
"spec",
"specs",
],
},
}

View File

@@ -1,8 +1,8 @@
import {move, pathExists, remove} from "fs-extra"
import {resolve} from "path"
import {move, remove, pathExists} from "fs-extra"
import {ServerConfig, normalize} from "./config"
import {nextBuild} from "./next-utils"
import {saveBuild} from "./build-hash"
import {normalize, ServerConfig} from "./config"
import {nextBuild} from "./next-utils"
import {configureStages} from "./stages"
export async function build(
@@ -18,19 +18,19 @@ export async function build(
include,
watch,
isTypescript,
...stageConfig
writeManifestFile,
} = await normalize(config)
const src = rootFolder
const stages = configureStages(stageConfig)
const dest = buildFolder
const options = {
ignore,
include,
watch,
isTypescript,
}
await Promise.all([transformFiles(src, stages, dest, options), readyForNextBuild])
const stages = configureStages({isTypescript, writeManifestFile})
await Promise.all([
transformFiles(rootFolder, stages, buildFolder, {
ignore,
include,
watch,
}),
readyForNextBuild,
])
await nextBuild(nextBin, buildFolder)

View File

@@ -1,36 +1,55 @@
import {resolve} from "path"
import {resolveBinAsync} from "./resolve-bin-async"
import {transformFiles} from "@blitzjs/file-pipeline"
import {promises} from "fs"
import {join, resolve} from "path"
import {parseChokidarRulesFromGitignore} from "./parse-chokidar-rules-from-gitignore"
import {resolveBinAsync} from "./resolve-bin-async"
type Synchronizer = typeof transformFiles
type ServerEnvironment = "dev" | "prod"
export type ServerConfig = {
rootFolder: string
buildFolder?: string
devFolder?: string
// -
isTypescript?: boolean
watch?: boolean
// -
transformFiles?: Synchronizer
writeManifestFile?: boolean
// -
port?: number
hostname?: string
interceptNextErrors?: boolean
devFolder?: string
buildFolder?: string
writeManifestFile?: boolean
watch?: boolean
transformFiles?: Synchronizer
isTypescript?: boolean
inspect?: boolean
//
env?: ServerEnvironment
}
type NormalizedConfig = Omit<ServerConfig, "interceptNextErrors"> & {
ignore: string[]
include: string[]
nextBin: string
devFolder: string
type NormalizedConfig = ServerConfig & {
buildFolder: string
devFolder: string
// -
isTypescript: boolean
watch: boolean
// -
transformFiles: Synchronizer
writeManifestFile: boolean
watch: boolean
isTypescript: boolean
// -
ignore: string[]
include: string[]
// -
nextBin: string
env: ServerEnvironment
}
const defaults = {
env: "prod" as ServerEnvironment,
// -
buildFolder: ".blitz/caches/build",
devFolder: ".blitz/caches/dev",
// -
writeManifestFile: true,
// -
ignoredPaths: [
"./build/**/*",
"./.blitz-*/**/*",
@@ -50,29 +69,56 @@ const defaults = {
"dist/**/*",
"node_modules/**/*",
"cypress/**/*",
"test/**/*",
"tests/**/*",
"spec/**/*",
"specs/**/*",
"**/*.test.*",
"**/*.spec.*",
],
includePaths: ["**/*"],
devFolder: ".blitz/caches/dev",
buildFolder: ".blitz/caches/build",
nextBinPatched: "./node_modules/.bin/next-patched",
writeManifestFile: true,
}
export async function normalize(config: ServerConfig): Promise<NormalizedConfig> {
const nextBinOrig = await resolveBinAsync("next")
const nextBinPatched = await resolveBinAsync("@blitzjs/server", "next-patched")
const git = parseChokidarRulesFromGitignore(resolve(process.cwd(), config.rootFolder))
const rootFolder = resolve(process.cwd(), config.rootFolder)
const git = parseChokidarRulesFromGitignore(rootFolder)
const env = config.env || defaults.env
return {
...config,
buildFolder: resolve(config.rootFolder, config.buildFolder ?? defaults.buildFolder),
devFolder: resolve(config.rootFolder, config.devFolder ?? defaults.devFolder),
env,
// -
rootFolder,
buildFolder: resolve(rootFolder, config.buildFolder ?? defaults.buildFolder),
devFolder: resolve(rootFolder, config.devFolder ?? defaults.devFolder),
// -
isTypescript: config.isTypescript ?? (await getIsTypescript(rootFolder)),
watch: config.watch ?? env === "dev",
// -
transformFiles: config.transformFiles ?? transformFiles,
writeManifestFile: config.writeManifestFile ?? defaults.writeManifestFile,
// -
ignore: defaults.ignoredPaths.concat(git.ignoredPaths),
include: defaults.includePaths.concat(git.includePaths),
nextBin: resolve(config.rootFolder, config.interceptNextErrors ? nextBinPatched : nextBinOrig),
transformFiles: config.transformFiles ?? transformFiles,
watch: config.watch ?? false,
writeManifestFile: config.writeManifestFile ?? defaults.writeManifestFile,
isTypescript: config.isTypescript ?? true,
// -
nextBin: await getNextBin(rootFolder, env === "dev"),
}
}
async function getNextBin(rootFolder: string, usePatched: boolean = false): Promise<string> {
// do not await for both bin-pkg because just one is used at a time
const nextBinPkg = usePatched ? "@blitzjs/server" : "next"
const nextBinExec = usePatched ? "next-patched" : undefined
const nextBin = await resolveBinAsync(nextBinPkg, nextBinExec)
return resolve(rootFolder, nextBin)
}
async function getIsTypescript(rootFolder: string): Promise<boolean> {
try {
await promises.access(join(rootFolder, "tsconfig.json"))
return true
} catch {
return false
}
}

View File

@@ -1,14 +1,9 @@
import {resolve} from "path"
import {ServerConfig, normalize} from "./config"
import {normalize, ServerConfig} from "./config"
import {nextStartDev} from "./next-utils"
import {configureStages} from "./stages"
export async function dev(
{watch = true, ...config}: ServerConfig,
readyForNextDev: Promise<any> = Promise.resolve(),
) {
export async function dev(config: ServerConfig, readyForNextDev: Promise<any> = Promise.resolve()) {
const {
//
rootFolder,
transformFiles,
nextBin,
@@ -16,27 +11,21 @@ export async function dev(
ignore,
include,
isTypescript,
...stagesConfig
} = await normalize({
...config,
interceptNextErrors: true,
})
const src = resolve(rootFolder)
const stages = configureStages(stagesConfig)
const dest = resolve(rootFolder, devFolder)
const options = {
ignore,
include,
writeManifestFile,
watch,
isTypescript,
}
} = await normalize({...config, env: "dev"})
const stages = configureStages({writeManifestFile, isTypescript})
const [{manifest}] = await Promise.all([
transformFiles(src, stages, dest, options),
transformFiles(rootFolder, stages, devFolder, {
ignore,
include,
watch,
}),
// Ensure next does not start until parallel processing completes
readyForNextDev,
])
await nextStartDev(nextBin, dest, manifest, devFolder, config)
await nextStartDev(nextBin, devFolder, manifest, devFolder, config)
}

View File

@@ -32,6 +32,7 @@ function createOutputTransformer(manifest: Manifest, devFolder: string) {
async function createCommandAndPort(config: ServerConfig, command: string) {
let spawnCommand: string[] = [command]
let spawnEnv: NodeJS.ProcessEnv = process.env
let availablePort: number
availablePort = await detect({port: config.port ? config.port : 3000})
@@ -41,7 +42,11 @@ async function createCommandAndPort(config: ServerConfig, command: string) {
spawnCommand = spawnCommand.concat(["-H", `${config.hostname}`])
}
return {spawnCommand, availablePort}
if (config.inspect) {
spawnEnv = {...spawnEnv, NODE_OPTIONS: "--inspect"}
}
return {spawnCommand, spawnEnv, availablePort}
}
export async function nextStartDev(
@@ -52,7 +57,7 @@ export async function nextStartDev(
config: ServerConfig,
) {
const transform = createOutputTransformer(manifest, devFolder).stream
const {spawnCommand, availablePort} = await createCommandAndPort(config, "dev")
const {spawnCommand, spawnEnv, availablePort} = await createCommandAndPort(config, "dev")
return new Promise((res, rej) => {
if (config.port && availablePort !== config.port) {
@@ -61,6 +66,7 @@ export async function nextStartDev(
} else {
spawn(nextBin, spawnCommand, {
cwd,
env: spawnEnv,
stdio: [process.stdin, transform.pipe(process.stdout), transform.pipe(process.stderr)],
})
.on("exit", (code: number) => {
@@ -86,7 +92,7 @@ export function nextBuild(nextBin: string, cwd: string) {
}
export async function nextStart(nextBin: string, cwd: string, config: ServerConfig) {
const {spawnCommand, availablePort} = await createCommandAndPort(config, "start")
const {spawnCommand, spawnEnv, availablePort} = await createCommandAndPort(config, "start")
return new Promise((res, rej) => {
if (config.port && availablePort !== config.port) {
@@ -95,10 +101,11 @@ export async function nextStart(nextBin: string, cwd: string, config: ServerConf
} else {
spawn(nextBin, spawnCommand, {
cwd,
env: spawnEnv,
stdio: "inherit",
})
.on("exit", (code: number) => {
code === 0 ? res() : rej(`'next build' failed with status code: ${code}`)
code === 0 ? res() : rej(`'next start' failed with status code: ${code}`)
})
.on("error", (err) => {
console.error(err)

View File

@@ -1,16 +1,18 @@
import {createStageRelative} from "./relative"
import {createStagePages} from "./pages"
import {createStageRpc} from "./rpc"
import {createStageConfig} from "./config"
import {createStageManifest} from "./manifest"
import {createStagePages} from "./pages"
import {createStageRelative} from "./relative"
import {createStageRpc} from "./rpc"
type StagesConfig = {writeManifestFile: boolean; isTypescript: boolean}
// These create pipeline stages that are run as the business rules for Blitz
// Read this folders README for more information
export const configureStages = (config: {writeManifestFile: boolean}) => [
export const configureStages = (config: StagesConfig) => [
// Order is important
createStageRelative,
createStagePages,
createStageRpc,
createStageRpc(config.isTypescript),
createStageConfig,
createStageManifest(config.writeManifestFile),
]

View File

@@ -5,7 +5,7 @@ import {handleErrors, DuplicatePathError} from "./errors"
import flow from "lodash/flow"
export function pagesPathTransformer(path: string) {
const regex = /(?:[\\/]?app[\\/].*?[\\/]?)(pages[\\/].+(?<!test)\.(m?[tj]sx?|mdx))$/
const regex = /(?:[\\/]?app[\\/].*?[\\/]?)(pages[\\/].+(?<!\.test)\.(m?[tj]sx?|mdx))$/
return (regex.exec(path) || [])[1] || path
}

View File

@@ -68,6 +68,11 @@ describe("createPagesPathTransformer", () => {
input: normalize("/User/foo/bar/app/users/pages/one/two/three.tsx"),
expected: normalize("pages/one/two/three.tsx"),
},
{
name: "Transforms app/pages/test.tsx",
input: normalize("app/pages/test.tsx"),
expected: normalize("pages/test.tsx"),
},
]
tests.forEach(({name, input, expected}) => {

View File

@@ -59,51 +59,52 @@ export const config = {
/**
* Returns a Stage that manages generating the internal RPC commands and handlers
*/
export const createStageRpc: Stage = function configure({config: {src, isTypescript = true}}) {
const fileTransformer = absolutePathTransform(src)
export const createStageRpc = (isTypescript = true): Stage =>
function configure({config: {src}}) {
const fileTransformer = absolutePathTransform(src)
const getResolverPath = fileTransformer(resolverPath)
const getApiHandlerPath = fileTransformer(apiHandlerPath)
const getResolverPath = fileTransformer(resolverPath)
const getApiHandlerPath = fileTransformer(apiHandlerPath)
const stream = transform.file((file, {next, push}) => {
if (!isResolverPath(file.path)) {
return file
}
const stream = transform.file((file, {next, push}) => {
if (!isResolverPath(file.path)) {
return file
}
const originalPath = resolutionPath(src, file.path)
const resolverImportPath = resolverPath(originalPath)
const {resolverType, resolverName} = extractTemplateVars(resolverImportPath)
const originalPath = resolutionPath(src, file.path)
const resolverImportPath = resolverPath(originalPath)
const {resolverType, resolverName} = extractTemplateVars(resolverImportPath)
// Original function -> _resolvers path
push(
new File({
path: getResolverPath(file.path),
contents: file.contents,
hash: file.hash + ":1",
}),
)
// Original function -> _resolvers path
push(
new File({
path: getResolverPath(file.path),
contents: file.contents,
hash: file.hash + ":1",
}),
)
// File API route handler
push(
new File({
path: getApiHandlerPath(file.path),
contents: Buffer.from(apiHandlerTemplate(originalPath, isTypescript)),
hash: file.hash + ":2",
}),
)
// File API route handler
push(
new File({
path: getApiHandlerPath(file.path),
contents: Buffer.from(apiHandlerTemplate(originalPath, isTypescript)),
hash: file.hash + ":2",
}),
)
// Isomorphic client
const isomorphicHandlerFile = file.clone()
isomorphicHandlerFile.contents = Buffer.from(
isomorhicHandlerTemplate(resolverImportPath, resolverName, resolverType, isTypescript),
)
push(isomorphicHandlerFile)
// Isomorphic client
const isomorphicHandlerFile = file.clone()
isomorphicHandlerFile.contents = Buffer.from(
isomorhicHandlerTemplate(resolverImportPath, resolverName, resolverType, isTypescript),
)
push(isomorphicHandlerFile)
return next()
})
return next()
})
return {stream}
}
return {stream}
}
function removeExt(filePath: string) {
return filePath.replace(/[.][^./\s]+$/, "")

View File

@@ -1,7 +1,6 @@
import {StageConfig, StageArgs} from "@blitzjs/file-pipeline/dist/packages/file-pipeline/src/types"
import {FileCache} from "@blitzjs/file-pipeline"
import {through, pipeline} from "../streams"
import {StageArgs, StageConfig} from "@blitzjs/file-pipeline/dist/packages/file-pipeline/src/types"
import {pipeline, through} from "../streams"
export function mockStageArgs(a: {entries?: string[]; cwd?: string}): StageArgs {
const config: StageConfig = {
@@ -11,7 +10,6 @@ export function mockStageArgs(a: {entries?: string[]; cwd?: string}): StageArgs
include: [],
src: "",
watch: false,
isTypescript: true,
}
return {
getInputCache() {

View File

@@ -310,11 +310,11 @@ export const getSessionSecretKey = () => {
if (process.env.NODE_ENV === "production") {
assert(
process.env.SESSION_SECRET_KEY,
"You must provide the SESSION_SECRET_KEY environment variable in production. This used to sign and verify JWTs.",
"You must provide the SESSION_SECRET_KEY environment variable in production. This used to sign and verify tokens. It should be 32 chars long.",
)
assert(
process.env.SESSION_SECRET_KEY.length >= 32,
"The SESSION_SECRET_KEY environment variable must be at least 32 bytes for sufficent JWT security",
"The SESSION_SECRET_KEY environment variable must be at least 32 bytes for sufficent token security",
)
return process.env.SESSION_SECRET_KEY

View File

@@ -1,8 +1,8 @@
diff --git a/node_modules/release/bin/release.js b/node_modules/release/bin/release.js
index a5ab985..ce9475a 100755
index a5ab985..e324528 100755
--- a/node_modules/release/bin/release.js
+++ b/node_modules/release/bin/release.js
@@ -52,25 +52,37 @@ let githubConnection;
@@ -52,25 +52,49 @@ let githubConnection;
let repoDetails;
const changeTypes = [
@@ -44,6 +44,18 @@ index a5ab985..ce9475a 100755
+ description: 'backwards-compatible bug fix',
+ },
+ {
+ handle: 'newapp',
+ name: 'New App Template',
+ pluralName: '⚡️ Changes to the New App Template',
+ description: 'change to new app template',
+ },
+ {
+ handle: 'recipe',
+ name: 'Recipe',
+ pluralName: '👩‍🍳 Recipes',
+ description: 'change to a recipe',
+ },
+ {
+ handle: 'example',
+ name: 'Example App',
+ pluralName: '👀 Changes to Example Apps',

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/recipe-chakra",
"private": true,
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "The Blitz Recipe for installing Chakra UI",
"main": "index.ts",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"@blitzjs/installer": "0.21.2-canary.1",
"@blitzjs/installer": "0.23.2",
"jscodeshift": "0.10.0"
},
"devDependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/recipe-emotion",
"private": true,
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "The Blitz Recipe for installing Emotion",
"main": "index.ts",
"scripts": {
@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"@blitzjs/installer": "0.21.2-canary.1",
"@blitzjs/installer": "0.23.2",
"jscodeshift": "0.10.0"
},
"devDependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/recipe-material-ui",
"private": true,
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "The Blitz Recipe for installing Material-UI",
"main": "index.ts",
"scripts": {
@@ -23,7 +23,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"@blitzjs/installer": "0.21.2-canary.1",
"@blitzjs/installer": "0.23.2",
"jscodeshift": "0.10.0"
},
"devDependencies": {

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/recipe-render",
"private": true,
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "The Blitz Recipe for adding render.yaml",
"main": "index.ts",
"scripts": {
@@ -22,6 +22,6 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"@blitzjs/installer": "0.21.2-canary.1"
"@blitzjs/installer": "0.23.2"
}
}

View File

@@ -3,9 +3,12 @@ services:
name: blitzapp
env: node
plan: starter
buildCommand: yarn; blitz db migrate; blitz build
startCommand: blitz start --production -H 0.0.0.0
buildCommand: yarn --frozen-lockfile --prod=false; blitz db migrate; blitz build
# If you have an out of memory error, change startCommand to "yarn next start"
startCommand: blitz start --production
envVars:
# ⚠️ You must set SESSION_SECRET_KEY env var through the UI.
# Add this env name, then a "generate" button will appear in the value box
- key: NODE_ENV
value: production
- key: DATABASE_URL

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/recipe-tailwind",
"private": true,
"version": "0.21.2-canary.1",
"version": "0.23.2",
"description": "The Blitz Recipe for installing Tailwind CSS",
"main": "index.ts",
"scripts": {
@@ -22,7 +22,7 @@
},
"homepage": "https://github.com/blitz-js/blitz#readme",
"dependencies": {
"@blitzjs/installer": "0.21.2-canary.1",
"@blitzjs/installer": "0.23.2",
"jscodeshift": "0.10.0"
},
"devDependencies": {

View File

@@ -1,4 +1,5 @@
module.exports = {
future: "all",
purge: ["{app,pages}/**/*.{js,jsx,ts,tsx}"],
theme: {},
variants: {},

View File

@@ -20,6 +20,7 @@
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"jsx": "react",
"esModuleInterop": true
"esModuleInterop": true,
"noEmit": true
}
}

View File

@@ -3649,6 +3649,14 @@
estree-walker "^2.0.1"
picomatch "^2.2.2"
"@salesforce/lazy-require@0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@salesforce/lazy-require/-/lazy-require-0.3.2.tgz#0d3b5a697e639a4b2357c9b18d6dd883a620c57c"
integrity sha512-T1M9mcf9CYBihe4kYwnOuuGS32Eg4mjqZbto5gXJi1qQxmG/zdrQ6pv5zHD8nfbZb1d1hQzTW0y+cCvwcWV6qw==
dependencies:
debug "^3.2.6"
tslib "^1.10.0"
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
@@ -4191,6 +4199,14 @@
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
"@types/passport-auth0@1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@types/passport-auth0/-/passport-auth0-1.0.4.tgz#f92c357a3a2a6fa5f10744555a45c5e9a6e36469"
integrity sha512-Qq1YRz1kuhFMHn43btY/RZ3pxV84ogOwhDfPWVcgGqgHYRWf5rTtV3tvcwPRFFh3Z72JkJhQ/9bbxnTFoV2ytg==
dependencies:
"@types/express" "*"
"@types/passport" "*"
"@types/passport-github2@1.2.4":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@types/passport-github2/-/passport-github2-1.2.4.tgz#f56c386d1fe6435e359430e57adc1747a627bd86"
@@ -8457,6 +8473,18 @@ eslint-plugin-cypress@2.11.1:
dependencies:
globals "^11.12.0"
eslint-plugin-es5@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-es5/-/eslint-plugin-es5-1.5.0.tgz#aab19af3d4798f7924bba309bc4f87087280fbba"
integrity sha512-Qxmfo7v2B7SGAEURJo0dpBweFf+JU15kSyALfiB2rXWcBuJ96r6X9kFHXFnhdopPHCaHjoQs1xQPUJVbGMb1AA==
eslint-plugin-es@mysticatea/eslint-plugin-es:
version "3.0.1"
resolved "https://codeload.github.com/mysticatea/eslint-plugin-es/tar.gz/5a90374a2e19fb7247e3140b277a42ec693276c1"
dependencies:
eslint-utils "^2.0.0"
regexpp "^3.0.0"
eslint-plugin-flowtype@5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-5.2.0.tgz#a4bef5dc18f9b2bdb41569a4ab05d73805a3d261"
@@ -12581,6 +12609,11 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
lodash-es@^4.17.15:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@@ -13672,6 +13705,11 @@ node-fetch@2.6.0, node-fetch@^2.1.1, node-fetch@^2.2.0, node-fetch@^2.3.0, node-
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-fetch@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
node-gyp-build@^4.2.0:
version "4.2.2"
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.2.tgz#3f44b65adaafd42fb6c3d81afd630e45c847eb66"
@@ -14642,6 +14680,15 @@ pascalcase@^0.1.1:
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
passport-auth0@1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/passport-auth0/-/passport-auth0-1.3.3.tgz#d377f9aea2f6e89af0318a6364a847e80966bb88"
integrity sha512-rcjT0fV6HnJuSb8REwREl42/K5LpGK+doekDgEQbtT/pNwLAjfobSMiQ3RbTP1CkiEcDVRucGucuDSfgqHX/Vg==
dependencies:
passport-oauth "^1.0.0"
passport-oauth2 "^1.5.0"
request "^2.88.0"
passport-github2@0.1.11:
version "0.1.11"
resolved "https://registry.yarnpkg.com/passport-github2/-/passport-github2-0.1.11.tgz#c92b56f3c38a44e766aac7e9e7c1384c5e93c999"
@@ -14658,7 +14705,7 @@ passport-oauth1@1.x.x:
passport-strategy "1.x.x"
utils-merge "1.x.x"
passport-oauth2@1.x.x:
passport-oauth2@1.x.x, passport-oauth2@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108"
integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==
@@ -14669,6 +14716,14 @@ passport-oauth2@1.x.x:
uid2 "0.0.x"
utils-merge "1.x.x"
passport-oauth@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-oauth/-/passport-oauth-1.0.0.tgz#90aff63387540f02089af28cdad39ea7f80d77df"
integrity sha1-kK/2M4dUDwIImvKM2tOep/gNd98=
dependencies:
passport-oauth1 "1.x.x"
passport-oauth2 "1.x.x"
passport-strategy@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
@@ -18482,7 +18537,7 @@ tslib@1.11.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
tslib@^1, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
tslib@^1, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
version "1.13.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
@@ -18950,7 +19005,7 @@ uuid@^7.0.2, uuid@^7.0.3:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
v8-compile-cache@^2.0.3:
v8-compile-cache@2.1.1, v8-compile-cache@^2.0.3:
version "2.1.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745"
integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==