1
0
mirror of synced 2026-02-08 06:00:13 -05:00

Compare commits

...

79 Commits

Author SHA1 Message Date
Brandon Bayer
767926b34a change db in auth example 2021-01-01 17:30:19 -05:00
Brandon Bayer
c700ee4b9a Change log message from "alpha software" to "beta software" (patch) 2021-01-01 16:54:26 -05:00
Brandon Bayer
da2916fccf (newapp) Update a few dependencies including React to 0.0.0-experimental-3310209d0 (#1662)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2021-01-01 21:48:43 +00:00
Steffan Harris
59c839c65f Remove unnecessary log message about git core.excludesFiles (patch) (#1663)
* Removed build console message about core.excludesFiles

* Update parse-chokidar-rules-from-gitignore.ts

Co-authored-by: Brandon Bayer <b@bayer.ws>
2021-01-01 21:29:35 +00:00
Brandon Bayer
1341b10e57 Upgrade all dependencies (patch) (#1657) 2020-12-31 18:56:34 -05:00
Kevin Østerkilde
da678523d8 (newapp) Change Final Form <LabeledTextField/> to properly parse numbers (#1658)
See https://github.com/blitz-js/blitz/issues/1636
2020-12-31 16:46:48 -05:00
depfu[bot]
34145212ad Upgrade Node.js to version 12.20.0 (#1655)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2020-12-30 22:37:59 +00:00
Brandon Bayer
e4fd4a8990 fix a false duplicate error with .coverage directory in your project (#1654)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-30 21:13:18 +00:00
Brandon Bayer
682664bd0c Improve error message from useQuery for case of incorrect resolver location (patch) (#1653)
* improve error message for useQuery

* tweak
2020-12-30 20:54:46 +00:00
Alex Johansson
384b847b39 Remove unused packages from @blitzjs/server (patch) (#1634)
* Remove unused packages from `packages/server`

* lodash-es

Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-29 23:25:13 +00:00
Alex Johansson
db0cddf5ed Remove pretty-ms dependency (move code into core) (patch) (#1628)
* Remove `pretty-ms` dep

* naïve prettyMs-fn

* use `Date.now` shorthand

* fmt negative numbers as well

Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-29 23:08:34 +00:00
Simon Knott
01754dcbbd Fix bug preventing imports from files/libraries ending in "pages" or "api" (patch) (#1649)
* Add regression example

* Dont rewrite file-imports that end in /pages or /api

Only import directory imports (where import "someDir/pages" actually means "someDir/pages/index.js").

Closes #1646

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-29 22:52:28 +00:00
Alex Johansson
387ffc6a80 Remove implicit auto-build with blitz start --production. blitz build now a pre-requisite (major) (#1623)
* Remove auto-build

* remove `folder-hash` dep

* build before start

Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-29 22:35:45 +00:00
Arjun Dubey
303fad2853 Fix blitz db commands showing incorrect error (patch) (#1648)
* update db.ts

* updated db.ts

* Update packages/cli/src/commands/db.ts

Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-29 22:18:49 +00:00
Alex Johansson
a1227ee37a Remove unused packages from core (patch) (#1630)
* Remove unused packages from `core`

* update lockfile

* lodash-es

Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-29 21:41:51 +00:00
Brandon Bayer
b31e1ac245 Add @timReynolds as a contributor 2020-12-29 16:20:46 -05:00
Brandon Bayer
4e79196222 Add @phillipkregg as a contributor 2020-12-29 16:16:42 -05:00
Brandon Bayer
9b57078d31 bump yarn.lock
(ignore)
2020-12-23 14:22:30 -05:00
Brandon Bayer
cb80788734 v0.28.0-canary.1 2020-12-23 14:21:42 -05:00
depfu[bot]
845d171721 Upgrade next: 10.0.3 → 10.0.4 (patch) (#1644)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-23 14:18:16 -05:00
Alex Johansson
5f57f3c9ea only use node-fetch (#1642)
next.js bundles it

Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-23 19:17:19 +00:00
Brandon Bayer
96a0fffa00 fix broken css module imports (#1645)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-23 18:50:59 +00:00
Alex Johansson
6d71a60154 Remove unsued dep node-fetch (#1632)
Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-23 18:22:19 +00:00
Alex Johansson
dd5a6b8273 Remove unused packages from file-pipeline (#1631)
Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-23 18:05:42 +00:00
Alex Johansson
a3452937c3 remove hasha dependency (#1627)
Co-authored-by: Brandon Bayer <b@bayer.ws>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-12-23 17:47:58 +00:00
Brandon Bayer
6826920184 update codeowners again
(ignore)
2020-12-23 12:29:30 -05:00
Brandon Bayer
0dc9feeb1e update codeowners
(ignore)
2020-12-23 12:23:15 -05:00
Alex Johansson
12b5161918 Remove unused packages from @blitzjs/installer (patch) (#1633)
Co-authored-by: Brandon Bayer <b@bayer.ws>
2020-12-23 12:17:22 -05:00
Brandon Bayer
e72b602600 Fix CI windows example test and other CI maintenance (#1639) 2020-12-23 11:46:04 -05:00
Brandon Bayer
a271fe9267 Change all agnosticSource tests to not run on windows (#1643)
(meta)
2020-12-22 18:51:15 -05:00
Alex Johansson
75758f8130 Timeout example testing after 20mins (#1640)
(meta)
2020-12-22 18:36:15 -05:00
Brandon Bayer
d48161d203 improve release script patch
(meta)
2020-12-22 13:55:56 -05:00
Reo Ishiyama
1682ce0474 Added Reo as L1 Maintainer to the README (#1637)
(meta)
2020-12-22 13:53:43 -05:00
Alex Johansson
bc7970690c Skip flaky windows packages test (#1635)
(meta)
2020-12-22 13:49:40 -05:00
Brandon Bayer
d9c5299436 v0.28.0-canary.0 2020-12-17 16:24:02 -05:00
Brandon Bayer
bc829d6bd4 update release patch auto categorize allcontributors
(meta)
2020-12-17 16:20:36 -05:00
allcontributors[bot]
ec71d2ad0d docs: add chanand as a contributor (#1621)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-12-17 16:17:48 -05:00
chanand
b18393bcab Fix: allow numbers and underscore in names for blitz generate model (#1618)
(patch)
2020-12-17 16:15:27 -05:00
allcontributors[bot]
2eb26617bc docs: add arjundubey-cr as a contributor (#1620)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-17 16:12:04 -05:00
Arjun Dubey
95988755ed Fix bug where cancelling blitz install still outputs success message (#1616)
(patch)
2020-12-17 16:11:50 -05:00
allcontributors[bot]
87ad97ce2b docs: add Kosai106 as a contributor (#1619)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-17 16:09:45 -05:00
Kevin Østerkilde
a58685229f Add missing exports for LinkProps, ImageProps, and ErrorProps (#1613)
Co-authored-by: Brandon Bayer <b@bayer.ws> (patch)
2020-12-17 16:09:31 -05:00
Brandon Bayer
2ad5b68eab Dylan Brookes retires from core team
(meta)
2020-12-17 13:09:10 -05:00
allcontributors[bot]
8ac511aba3 docs: add jackbravo as a contributor (#1614)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-16 11:05:06 -05:00
Steffan Harris
12d93c7532 Removed unstable_ prefix from session middleware (#1607)
(major)
2020-12-15 17:17:18 -05:00
Brandon Bayer
e53f1b21bc fix render logo
(ignore)
2020-12-15 11:42:46 -05:00
Brandon Bayer
b0a4bed5e3 update render logo
(ignore)
2020-12-15 11:40:25 -05:00
Brandon Bayer
a4a672645c update render link
(ignore)
2020-12-14 16:46:47 -05:00
Brandon Bayer
88f9b4b5e5 fix readme logo size
(ignore)
2020-12-14 16:42:12 -05:00
Brandon Bayer
b62dce39dd add Render.com as a Bronze Sponsor!
(meta)
2020-12-14 16:39:48 -05:00
allcontributors[bot]
2b9b79ca2d docs: add mattfwood as a contributor (#1601)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-12 17:26:43 -05:00
Matt Wood
aba8492fc0 Minor typo fix in chakra recipe explanation (#1597)
(recipe)
2020-12-12 17:26:31 -05:00
dependabot[bot]
34f5b08101 Bump ini from 1.3.5 to 1.3.8 (#1599)
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)
(meta)
Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-12-12 17:24:37 -05:00
Brandon Bayer
322fc6d0a9 fix readme
(ignore)
2020-12-12 11:30:24 -05:00
Brandon Bayer
34ee44e0bf Add Andreas Asprou as a seedling sponsor
(meta)
2020-12-12 11:26:02 -05:00
Brandon Bayer
4517a675a5 Fix bug where "db" in a path name will break client side imports (patch) (#1594) 2020-12-10 19:01:28 -05:00
Brandon Bayer
6ce248f694 (newapp) Change prisma version to be pinned to a minor version (#1595) 2020-12-10 18:54:42 -05:00
allcontributors[bot]
e68eb6d118 docs: add beeplin as a contributor (#1593)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-10 17:51:50 -05:00
tundera
ab81073003 Add Reflexjs recipe (#1585)
Co-authored-by: Brandon Bayer <b@bayer.ws> (recipe)
2020-12-10 17:48:18 -05:00
tundera
78410abe82 Fix and improve Theme UI recipe (#1583)
Co-authored-by: Brandon Bayer <b@bayer.ws> (recipe)
2020-12-10 17:43:20 -05:00
allcontributors[bot]
7d76f646d0 docs: add rayandrews as a contributor (#1592)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-10 17:35:36 -05:00
allcontributors[bot]
e97e964099 docs: add AkifumiSato as a contributor (#1591)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-10 17:33:38 -05:00
Akifumi Sato
fa358cd328 Remove error stack from console output on testing (#1540)
Co-authored-by: Brandon Bayer <b@bayer.ws> (meta)
2020-12-10 17:31:28 -05:00
Ray Andrew
5360a839d8 Add blitz routes command to see all routes (#1478)
Co-authored-by: Brandon Bayer <b@bayer.ws>
2020-12-10 17:28:25 -05:00
Brandon Bayer
a7493258eb Add G2i as sponsor
(meta)
2020-12-08 18:17:46 -05:00
Brandon Bayer
909f3b3392 fix theme-ui recipe
(ignore)
2020-12-05 19:15:23 -05:00
Brandon Bayer
688b05df78 v0.27.0 2020-12-05 19:07:30 -05:00
allcontributors[bot]
ec301dc22e docs: add markylaing as a contributor (#1578)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-05 18:55:35 -05:00
markylaing
df5271c1f0 Change passport adapter to accept an array of objects with authenticate options for each strategy (#1564)
Co-authored-by: Brandon Bayer <b@bayer.ws> (major)
2020-12-05 18:54:29 -05:00
allcontributors[bot]
bad2e3758e docs: add tundera as a contributor (#1577)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-05 18:45:53 -05:00
tundera
23b36b83f8 Add Theme UI recipe (including MDX!) (#1366)
Co-authored-by: Brandon Bayer <b@bayer.ws> (recipe)
2020-12-05 18:44:25 -05:00
allcontributors[bot]
94d9daf215 docs: add Khaledgarbaya as a contributor (#1576)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> (meta)
2020-12-05 18:32:34 -05:00
Khaled Garbaya
aae261c589 Fix blitz generate folder names to always be kebab-case (#1554)
(patch)
2020-12-05 18:31:20 -05:00
Brandon Bayer
4e3261d776 Fix module not found issues by moving isomorphic resolver imports behind experimental flag (#1574)
* move resolver isomorphic imports into an experimental flag

* maybe fix flaky windows test

* fix store test (patch)
2020-12-05 17:29:44 -05:00
Brandon Bayer
74083f704c v0.27.0-canary.3 2020-12-03 18:57:56 -05:00
Brandon Bayer
68e1abf727 add missing dependency
(ignore)
2020-12-03 18:54:53 -05:00
Brandon Bayer
1d3ca10164 v0.27.0-canary.2 2020-12-03 18:48:42 -05:00
Brandon Bayer
0c1cd9cc3f Fix broken blitz install (#1571) 2020-12-03 18:46:49 -05:00
depfu[bot]
e186f86389 Upgrade next.js: 10.0.2 → 10.0.3 (patch) (#1568)
Co-authored-by: depfu[bot] <23717796+depfu[bot]@users.noreply.github.com>
2020-12-02 09:37:37 -05:00
137 changed files with 6610 additions and 6115 deletions

View File

@@ -1302,7 +1302,8 @@
"avatar_url": "https://avatars1.githubusercontent.com/u/6379824?v=4",
"profile": "https://oesterkilde.dk/",
"contributions": [
"doc"
"doc",
"code"
]
},
{
@@ -1576,7 +1577,8 @@
"avatar_url": "https://avatars1.githubusercontent.com/u/4437323?v=4",
"profile": "https://github.com/rayandrews",
"contributions": [
"code"
"code",
"doc"
]
},
{
@@ -1641,6 +1643,106 @@
"contributions": [
"doc"
]
},
{
"login": "Khaledgarbaya",
"name": "Khaled Garbaya",
"avatar_url": "https://avatars1.githubusercontent.com/u/1156093?v=4",
"profile": "https://khaledgarbaya.net",
"contributions": [
"code"
]
},
{
"login": "tundera",
"name": "tundera",
"avatar_url": "https://avatars0.githubusercontent.com/u/61833561?v=4",
"profile": "https://tundera.dev",
"contributions": [
"code"
]
},
{
"login": "markylaing",
"name": "markylaing",
"avatar_url": "https://avatars2.githubusercontent.com/u/41469221?v=4",
"profile": "https://github.com/markylaing",
"contributions": [
"code",
"doc"
]
},
{
"login": "AkifumiSato",
"name": "Akifumi Sato",
"avatar_url": "https://avatars2.githubusercontent.com/u/25711332?v=4",
"profile": "https://akfm.dev/",
"contributions": [
"code"
]
},
{
"login": "beeplin",
"name": "Beep LIN",
"avatar_url": "https://avatars3.githubusercontent.com/u/13058150?v=4",
"profile": "https://github.com/beeplin",
"contributions": [
"code"
]
},
{
"login": "mattfwood",
"name": "Matt Wood",
"avatar_url": "https://avatars1.githubusercontent.com/u/22530815?v=4",
"profile": "https://mattwood.tech/",
"contributions": [
"code"
]
},
{
"login": "jackbravo",
"name": "Joaquin Bravo Contreras",
"avatar_url": "https://avatars1.githubusercontent.com/u/15214?v=4",
"profile": "http://joaquin.axai.mx",
"contributions": [
"code"
]
},
{
"login": "arjundubey-cr",
"name": "Arjun Dubey",
"avatar_url": "https://avatars0.githubusercontent.com/u/40758425?v=4",
"profile": "https://github.com/arjundubey-cr",
"contributions": [
"code"
]
},
{
"login": "chanand",
"name": "chanand",
"avatar_url": "https://avatars0.githubusercontent.com/u/1317789?v=4",
"profile": "https://github.com/chanand",
"contributions": [
"code"
]
},
{
"login": "phillipkregg",
"name": "phillipkregg",
"avatar_url": "https://avatars0.githubusercontent.com/u/1066044?v=4",
"profile": "https://github.com/phillipkregg",
"contributions": [
"doc"
]
},
{
"login": "timReynolds",
"name": "Tim Reynolds",
"avatar_url": "https://avatars1.githubusercontent.com/u/168870?v=4",
"profile": "http://timothyreynolds.co.uk",
"contributions": [
"doc"
]
}
],
"contributorsPerLine": 7,

View File

@@ -30,7 +30,7 @@ module.exports = {
// note you must disable the base rule as it can report incorrect errors
"no-redeclare": "off",
"@typescript-eslint/no-redeclare": ["error"],
"simple-import-sort/sort": [
"simple-import-sort/imports": [
"warn",
{
groups: [

6
.github/CODEOWNERS vendored
View File

@@ -2,7 +2,7 @@
* @flybayer
packages/cli/**/* @aem
packages/generator/**/* @aem
packages/cli/**/* @aem, @flybayer
packages/generator/**/* @aem @flybayer
packages/generator/templates**/* @flybayer
packages/installer/**/* @aem
packages/installer/**/* @aem @flybayer

View File

@@ -1,4 +1,4 @@
name: Compressed Size
name: CI
on:
pull_request:
@@ -6,14 +6,15 @@ on:
jobs:
build:
name: Compressed Size
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node and Yarn
uses: actions/setup-node@v1
uses: actions/setup-node@v2
with:
node-version: "12.x"
node-version: "14"
- name: Install dependencies
run: |
yarn && yarn build

View File

@@ -1,4 +1,4 @@
name: Continuous Integration
name: CI
on:
push:
@@ -17,9 +17,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v2
with:
node-version: "12.16.1"
node-version: "14"
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
@@ -32,9 +32,9 @@ jobs:
**/node_modules
/home/runner/.cache/Cypress
C:\Users\runneradmin\AppData\Local\Cypress\Cache
key: ${{ runner.os }}-yarn-v4-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v4-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-v4-
${{ runner.os }}-${{ runner.node_version}}-yarn-v4-
- name: Install dependencies
run: yarn install --frozen-lockfile --silent
env:
@@ -44,17 +44,18 @@ jobs:
env:
CI: true
build_and_test_pkgs:
name: Build & Test Packages
name: Packages Tests
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node_version: [12, 14]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v2
with:
node-version: "12.16.1"
node-version: ${{ matrix.node_version }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
@@ -66,9 +67,9 @@ jobs:
${{ steps.yarn-cache-dir-path.outputs.dir }}
/home/runner/.cache/Cypress
C:\Users\runneradmin\AppData\Local\Cypress\Cache
key: ${{ runner.os }}-yarn-v4-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v4-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-v4-
${{ runner.os }}-${{ runner.node_version}}-yarn-v4-
- name: Install dependencies
run: yarn install --frozen-lockfile --silent
env:
@@ -85,17 +86,19 @@ jobs:
env:
CI: true
build_and_test_examples:
name: Build & Test Examples
timeout-minutes: 30
name: Example Apps Tests
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node_version: [12, 14]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
uses: actions/setup-node@v2
with:
node-version: "12.16.1"
node-version: ${{ matrix.node_version }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
@@ -107,9 +110,9 @@ jobs:
${{ steps.yarn-cache-dir-path.outputs.dir }}
/home/runner/.cache/Cypress
C:\Users\runneradmin\AppData\Local\Cypress\Cache
key: ${{ runner.os }}-yarn-v4-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v4-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-v4-
${{ runner.os }}-${{ runner.node_version}}-yarn-v4-
- name: Install dependencies
run: yarn install --frozen-lockfile --silent
env:

2
.gitignore vendored
View File

@@ -22,3 +22,5 @@ dist
.blitz-cli-cache
.vscode
.tsbuildinfo
.nvmrc
**/.test*

View File

@@ -1 +1 @@
12.16.1
12.20.0

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-173-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-184-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">
@@ -128,13 +128,17 @@ Your financial contributions help ensure Blitz continues to be developed and mai
### 🌱 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">
<img alt="" src="https://reactbricks.com/reactbricks_icon.svg" width="30px"/>
</a>
<a aria-label="Andreas Asprou" href="https://andreas.fyi">
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/andreas.jpg" 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 aria-label="Render.com" href="https://render.com?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2020">
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/canary/assets/render-logo-color2.png" width="110px">
</a>
### 🥈 Silver Sponsors
@@ -145,9 +149,11 @@ Your financial contributions help ensure Blitz continues to be developed and mai
### 🏆 Gold Sponsors
<a aria-label="Your Company" href="#">
<img alt="" src="https://dummyimage.com/1000x330/efe8ff/000000.png&text=Your+Logo+Here" width="300px">
<div>
<a aria-label="G2i" href="http://g2i.co/sign-up?utm_source=blitz&utm_medium=referral&utm_campaign=blitz2020">
<img alt="" src="https://files-5oz00y7xp.vercel.app/G2i_Logo_wwords.png" width="160px">
</a>
</div>
### 💎 Diamond Sponsors
@@ -163,7 +169,6 @@ Your financial contributions help ensure Blitz continues to be developed and mai
<table>
<tr>
<td align="center"><a href="https://twitter.com/flybayer"><img src="https://avatars3.githubusercontent.com/u/8813276?v=4" width="100px;" alt=""/><br /><sub><b>Brandon Bayer</b></sub></a><br />Creator</td>
<td align="center"><a href="https://merelinguist.now.sh"><img src="https://avatars3.githubusercontent.com/u/24858006?v=4" width="100px;" alt=""/><br /><sub><b>Dylan Brookes</b></sub></a><br />Friendly Generalist</td>
</tr>
</table>
<!-- markdownlint-enable -->
@@ -211,6 +216,7 @@ _Issue triage, pull request triage, community encouragement and moderation, etc_
<td align="center"><a href="https://twitter.com/jdavenport97"><img src="https://avatars2.githubusercontent.com/u/1329874?v=4" width="100px;" alt=""/><br /><sub><b>Jamie Davenport</b></sub></a></td>
<td align="center"><a href="https://twitter.com/myrondavis"><img src="https://avatars2.githubusercontent.com/u/1430136?v=4" width="100px;" alt=""/><br /><sub><b>Myron Davis</b></sub></a></td>
<td align="center"><a href="https://flavioander.com/"><img src="https://avatars2.githubusercontent.com/u/14948074?s=460&u=31d7ea58b5c5cd9f724d684ed578f68896c4af71&v=4" width="100px;" alt=""/><br /><sub><b>Flavio Andrade</b></sub></a></td>
<td align="center"><a href="https://twitter.com/NaReto1125_"><img src="https://avatars.githubusercontent.com/reo777" width="100px;" alt=""/><br /><sub><b>Reo Ishiyama</b></sub></a></td>
</tr>
</table>
<!-- markdownlint-enable -->
@@ -401,7 +407,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
<tr>
<td align="center"><a href="https://github.com/aericson"><img src="https://avatars3.githubusercontent.com/u/692542?v=4" width="100px;" alt=""/><br /><sub><b>André Ericson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aericson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=aericson" title="Documentation">📖</a></td>
<td align="center"><a href="http://Cajotafer.com"><img src="https://avatars2.githubusercontent.com/u/41461969?v=4" width="100px;" alt=""/><br /><sub><b>Carlos Fernández</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cajotafer" title="Documentation">📖</a></td>
<td align="center"><a href="https://oesterkilde.dk/"><img src="https://avatars1.githubusercontent.com/u/6379824?v=4" width="100px;" alt=""/><br /><sub><b>Kevin Østerkilde</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Kosai106" title="Documentation">📖</a></td>
<td align="center"><a href="https://oesterkilde.dk/"><img src="https://avatars1.githubusercontent.com/u/6379824?v=4" width="100px;" alt=""/><br /><sub><b>Kevin Østerkilde</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Kosai106" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Kosai106" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/aaronfulkerson"><img src="https://avatars0.githubusercontent.com/u/31112737?v=4" width="100px;" alt=""/><br /><sub><b>aaronfulkerson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aaronfulkerson" title="Code">💻</a> <a href="#question-aaronfulkerson" title="Answering Questions">💬</a></td>
<td align="center"><a href="https://github.com/alexnaiman"><img src="https://avatars3.githubusercontent.com/u/25799714?v=4" width="100px;" alt=""/><br /><sub><b>Alexandru Naiman</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=alexnaiman" title="Code">💻</a></td>
<td align="center"><a href="https://davidlutta.github.io/portfolio/"><img src="https://avatars2.githubusercontent.com/u/14890315?v=4" width="100px;" alt=""/><br /><sub><b>David Ezekiel Lutta</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davidlutta" title="Code">💻</a></td>
@@ -439,7 +445,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
<td align="center"><a href="http://raph.site"><img src="https://avatars3.githubusercontent.com/u/1575946?v=4" width="100px;" alt=""/><br /><sub><b>Raphaël Huchet</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Code">💻</a></td>
<td align="center"><a href="http://kattcorp.com"><img src="https://avatars1.githubusercontent.com/u/459267?v=4" width="100px;" alt=""/><br /><sub><b>Alex Johansson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=KATT" title="Code">💻</a></td>
<td align="center"><a href="http://davidmazza.com"><img src="https://avatars0.githubusercontent.com/u/120893?v=4" width="100px;" alt=""/><br /><sub><b>David Mazza</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dmzza" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/rayandrews"><img src="https://avatars1.githubusercontent.com/u/4437323?v=4" width="100px;" alt=""/><br /><sub><b>Ray Andrew</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rayandrews" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/rayandrews"><img src="https://avatars1.githubusercontent.com/u/4437323?v=4" width="100px;" alt=""/><br /><sub><b>Ray Andrew</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rayandrews" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=rayandrews" title="Documentation">📖</a></td>
<td align="center"><a href="http://Dal.Design"><img src="https://avatars3.githubusercontent.com/u/43112535?v=4" width="100px;" alt=""/><br /><sub><b>Abdullah Mzaien</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Mzaien" title="Code">💻</a></td>
<td align="center"><a href="http://kwao.io"><img src="https://avatars2.githubusercontent.com/u/8839514?v=4" width="100px;" alt=""/><br /><sub><b>William Kwao</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=williamkwao" title="Documentation">📖</a></td>
</tr>
@@ -449,6 +455,21 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
<td align="center"><a href="http://jonstuebe.com"><img src="https://avatars0.githubusercontent.com/u/156722?v=4" width="100px;" alt=""/><br /><sub><b>Jon Stuebe</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jonstuebe" title="Code">💻</a></td>
<td align="center"><a href="https://ugogo.dev"><img src="https://avatars2.githubusercontent.com/u/5040476?v=4" width="100px;" alt=""/><br /><sub><b>Ugo Onali</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ugogo" title="Documentation">📖</a></td>
<td align="center"><a href="https://saintmalik.me"><img src="https://avatars1.githubusercontent.com/u/37118134?v=4" width="100px;" alt=""/><br /><sub><b>SaintMalik</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=saintmalik" title="Documentation">📖</a></td>
<td align="center"><a href="https://khaledgarbaya.net"><img src="https://avatars1.githubusercontent.com/u/1156093?v=4" width="100px;" alt=""/><br /><sub><b>Khaled Garbaya</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Khaledgarbaya" title="Code">💻</a></td>
<td align="center"><a href="https://tundera.dev"><img src="https://avatars0.githubusercontent.com/u/61833561?v=4" width="100px;" alt=""/><br /><sub><b>tundera</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tundera" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/markylaing"><img src="https://avatars2.githubusercontent.com/u/41469221?v=4" width="100px;" alt=""/><br /><sub><b>markylaing</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=markylaing" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=markylaing" title="Documentation">📖</a></td>
<td align="center"><a href="https://akfm.dev/"><img src="https://avatars2.githubusercontent.com/u/25711332?v=4" width="100px;" alt=""/><br /><sub><b>Akifumi Sato</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=AkifumiSato" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/beeplin"><img src="https://avatars3.githubusercontent.com/u/13058150?v=4" width="100px;" alt=""/><br /><sub><b>Beep LIN</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=beeplin" title="Code">💻</a></td>
<td align="center"><a href="https://mattwood.tech/"><img src="https://avatars1.githubusercontent.com/u/22530815?v=4" width="100px;" alt=""/><br /><sub><b>Matt Wood</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mattfwood" title="Code">💻</a></td>
<td align="center"><a href="http://joaquin.axai.mx"><img src="https://avatars1.githubusercontent.com/u/15214?v=4" width="100px;" alt=""/><br /><sub><b>Joaquin Bravo Contreras</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jackbravo" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/arjundubey-cr"><img src="https://avatars0.githubusercontent.com/u/40758425?v=4" width="100px;" alt=""/><br /><sub><b>Arjun Dubey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arjundubey-cr" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/chanand"><img src="https://avatars0.githubusercontent.com/u/1317789?v=4" width="100px;" alt=""/><br /><sub><b>chanand</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chanand" title="Code">💻</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/phillipkregg"><img src="https://avatars0.githubusercontent.com/u/1066044?v=4" width="100px;" alt=""/><br /><sub><b>phillipkregg</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=phillipkregg" title="Documentation">📖</a></td>
<td align="center"><a href="http://timothyreynolds.co.uk"><img src="https://avatars1.githubusercontent.com/u/168870?v=4" width="100px;" alt=""/><br /><sub><b>Tim Reynolds</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=timReynolds" title="Documentation">📖</a></td>
</tr>
</table>

BIN
assets/andreas.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -23,109 +23,115 @@ assert(process.env.AUTH0_CLIENT_SECRET, "You must provide the AUTH0_CLIENT_SECRE
export default passportAuth({
successRedirectUrl: "/",
authenticateOptions: {scope: "openid email profile"}, //used for Auth0Strategy - without an empty profile is returned
strategies: [
new TwitterStrategy(
{
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL:
process.env.NODE_ENV === "production"
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/twitter/callback"
: "http://localhost:3000/api/auth/twitter/callback",
includeEmail: true,
},
async function (_token, _tokenSecret, profile, done) {
const email = profile.emails && profile.emails[0]?.value
{
strategy: new TwitterStrategy(
{
consumerKey: process.env.TWITTER_CONSUMER_KEY,
consumerSecret: process.env.TWITTER_CONSUMER_SECRET,
callbackURL:
process.env.NODE_ENV === "production"
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/twitter/callback"
: "http://localhost:3000/api/auth/twitter/callback",
includeEmail: true,
},
async function (_token, _tokenSecret, profile, done) {
const email = profile.emails && profile.emails[0]?.value
if (!email) {
// This can happen if you haven't enabled email access in your twitter app permissions
return done(new Error("Twitter OAuth response doesn't have email."))
}
if (!email) {
// This can happen if you haven't enabled email access in your twitter app permissions
return done(new Error("Twitter OAuth response doesn't have email."))
}
const user = await db.user.upsert({
where: {email},
create: {
email,
name: profile.displayName,
},
update: {email},
})
const user = await db.user.upsert({
where: {email},
create: {
email,
name: profile.displayName,
},
update: {email},
})
const publicData = {userId: user.id, roles: [user.role], source: "twitter"}
done(null, {publicData})
},
),
new GitHubStrategy(
{
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL:
process.env.NODE_ENV === "production"
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/github/callback"
: "http://localhost:3000/api/auth/github/callback",
},
async function (_token, _tokenSecret, profile, done) {
const email = profile.emails && profile.emails[0]?.value
const publicData = {userId: user.id, roles: [user.role], source: "twitter"}
done(null, {publicData})
},
),
},
{
strategy: new GitHubStrategy(
{
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL:
process.env.NODE_ENV === "production"
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/github/callback"
: "http://localhost:3000/api/auth/github/callback",
},
async function (_token, _tokenSecret, profile, done) {
const email = profile.emails && profile.emails[0]?.value
if (!email) {
// This can happen if you haven't enabled email access in your twitter app permissions
return done(new Error("Twitter OAuth response doesn't have email."))
}
if (!email) {
// This can happen if you haven't enabled email access in your twitter app permissions
return done(new Error("Twitter OAuth response doesn't have email."))
}
const user = await db.user.upsert({
where: {email},
create: {
email,
name: profile.displayName,
},
update: {email},
})
const user = await db.user.upsert({
where: {email},
create: {
email,
name: profile.displayName,
},
update: {email},
})
const publicData = {
userId: user.id,
roles: [user.role],
source: "github",
githubUsername: profile.username,
}
done(null, {publicData})
},
),
new Auth0Strategy(
{
domain: process.env.AUTH0_DOMAIN,
clientID: process.env.AUTH0_CLIENT_ID,
clientSecret: process.env.AUTH0_CLIENT_SECRET,
callbackURL:
process.env.NODE_ENV === "production"
? "https://auth-example-flybayer.blitzjs.vercel.app/api/auth/auth0/callback"
: "http://localhost:3000/api/auth/auth0/callback",
},
async function (_token, _tokenSecret, extraParams, profile, done) {
const email = profile.emails && profile.emails[0]?.value
const publicData = {
userId: user.id,
roles: [user.role],
source: "github",
githubUsername: profile.username,
}
done(null, {publicData})
},
),
},
{
authenticateOptions: {scope: "openid email profile"},
strategy: 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."))
}
if (!email) {
// This can happen if you haven't enabled email access in your twitter app permissions
return done(new Error("Auth0 response doesn't have email."))
}
const user = await db.user.upsert({
where: {email},
create: {
email,
name: profile.displayName,
},
update: {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})
},
),
const publicData = {
userId: user.id,
roles: [user.role],
source: "auth0",
githubUsername: profile.username,
}
done(undefined, {publicData})
},
),
},
],
})

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.findFirst({where: {email}})
const user = await db().user.findFirst({where: {email}})
if (!user || !user.hashedPassword) throw new AuthenticationError()
@@ -28,7 +28,7 @@ export const authenticateUser = async (email: string, password: string) => {
case SecurePassword.VALID_NEEDS_REHASH:
// Upgrade hashed password with a more secure hash
const improvedHash = await hashPassword(password)
await db.user.update({where: {id: user.id}, data: {hashedPassword: improvedHash}})
await db().user.update({where: {id: user.id}, data: {hashedPassword: improvedHash}})
break
default:
throw new AuthenticationError()

View File

@@ -14,7 +14,7 @@ export default async function signup(input: SignupInputType, {session}: Ctx) {
const {email, password} = SignupInput.parse(input)
const hashedPassword = await hashPassword(password)
const user = await db.user.create({
const user = await db().user.create({
data: {email, hashedPassword, role: "user"},
select: {id: true, name: true, email: true, role: true},
})

View File

@@ -4,7 +4,7 @@ import db from "db"
export default async function getCurrentUser(_ = null, ctx: Ctx) {
if (!ctx.session.userId) return null
const user = await db.user.findFirst({
const user = await db().user.findFirst({
where: {id: ctx.session.userId},
select: {id: true, name: true, email: true, role: true},
})

View File

@@ -8,7 +8,7 @@ type GetUserInput = {
export default async function getUser({where}: GetUserInput, ctx: Ctx) {
ctx.session.authorize()
const user = await db.user.findFirst({where})
const user = await db().user.findFirst({where})
if (!user) throw new NotFoundError(`User with id ${where.id} does not exist`)

View File

@@ -6,14 +6,14 @@ type GetUsersInput = Pick<FindManyUserArgs, "where" | "orderBy" | "skip" | "take
export default async function getUsers({where, orderBy, skip = 0, take}: GetUsersInput, ctx: Ctx) {
ctx.session.authorize()
const users = await db.user.findMany({
const users = await db().user.findMany({
where,
orderBy,
take,
skip,
})
const count = await db.user.count()
const count = await db().user.count()
const hasMore = typeof take === "number" ? skip + take < count : false
const nextPage = hasMore ? {take, skip: skip + take!} : null

View File

@@ -1,4 +1,4 @@
const {sessionMiddleware, unstable_simpleRolesIsAuthorized} = require("@blitzjs/server")
const {sessionMiddleware, simpleRolesIsAuthorized} = require("@blitzjs/server")
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
})
@@ -6,13 +6,16 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({
module.exports = withBundleAnalyzer({
middleware: [
sessionMiddleware({
unstable_isAuthorized: unstable_simpleRolesIsAuthorized,
isAuthorized: simpleRolesIsAuthorized,
sessionExpiryMinutes: 4,
}),
],
log: {
level: "trace",
},
experimental: {
isomorphicResolverImports: true,
},
/*
webpack: (config, {buildId, dev, isServer, defaultLoaders, webpack}) => {
// Note: we provide webpack above so you should not `require` it

View File

@@ -1,15 +1,7 @@
import {PrismaClient} from "@prisma/client"
export * from "@prisma/client"
let prisma: PrismaClient
if (process.env.NODE_ENV === "production") {
prisma = new PrismaClient()
} else {
// Ensure the prisma instance is re-used during hot-reloading
// Otherwise, a new client will be created on every reload
globalThis["prisma"] = globalThis["prisma"] || new PrismaClient()
prisma = globalThis["prisma"]
export default function db(): PrismaClient {
globalThis.prisma = globalThis.prisma || new PrismaClient()
return globalThis.prisma
}
export default prisma

View File

@@ -1,6 +1,6 @@
{
"name": "@examples/auth",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"scripts": {
"start": "blitz start",
"studio": "blitz db studio",
@@ -11,7 +11,7 @@
"cy:run": "cypress run",
"test": "prisma generate && yarn test:jest && yarn test:e2e",
"test:jest": "jest",
"test:server": "blitz db migrate && blitz start --production -p 3099",
"test:server": "blitz db migrate && blitz build && blitz start --production -p 3099",
"test:e2e": "cross-env NODE_ENV=test start-server-and-test test:server http://localhost:3099 cy:run"
},
"browserslist": [
@@ -40,53 +40,53 @@
"dependencies": {
"@prisma/cli": "2.12.0",
"@prisma/client": "2.12.0",
"blitz": "0.27.0-canary.1",
"blitz": "0.28.0-canary.1",
"final-form": "4.20.1",
"passport-auth0": "1.3.3",
"passport-github2": "0.1.11",
"passport-auth0": "1.4.0",
"passport-github2": "0.1.12",
"passport-twitter": "1.0.4",
"react": "0.0.0-experimental-4ead6b530",
"react-dom": "0.0.0-experimental-4ead6b530",
"react-error-boundary": "2.3.1",
"react-final-form": "6.5.1",
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0",
"react-error-boundary": "3.1.0",
"react-final-form": "6.5.2",
"secure-password": "4.0.0",
"zod": "1.10.0"
"zod": "1.11.11"
},
"devDependencies": {
"@cypress/skip-test": "2.5.0",
"@cypress/skip-test": "2.5.1",
"@next/bundle-analyzer": "latest",
"@testing-library/jest-dom": "5.11.4",
"@testing-library/react": "11.1.0",
"@testing-library/react-hooks": "3.4.2",
"@types/jest": "26.0.14",
"@testing-library/jest-dom": "5.11.8",
"@testing-library/react": "11.2.2",
"@testing-library/react-hooks": "3.7.0",
"@types/jest": "26.0.19",
"@types/passport-auth0": "1.0.4",
"@types/passport-github2": "1.2.4",
"@types/passport-twitter": "1.0.36",
"@types/react": "16.9.38",
"@types/react": "17.0.0",
"@types/secure-password": "3.1.0",
"@typescript-eslint/eslint-plugin": "2.34.1-alpha.2",
"@typescript-eslint/parser": "2.34.1-alpha.2",
"@typescript-eslint/eslint-plugin": "4.11.1",
"@typescript-eslint/parser": "4.11.1",
"babel-eslint": "10.1.0",
"cross-env": "latest",
"cypress": "4.11.0",
"eslint": "7.6.0",
"eslint-config-react-app": "5.2.1",
"eslint-plugin-cypress": "2.11.1",
"cross-env": "7.0.3",
"cypress": "6.2.0",
"eslint": "7.16.0",
"eslint-config-react-app": "6.0.0",
"eslint-plugin-cypress": "2.11.2",
"eslint-plugin-flowtype": "5.2.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jsx-a11y": "6.3.1",
"eslint-plugin-react": "7.20.5",
"eslint-plugin-react-hooks": "4.0.8",
"husky": "4.2.5",
"jest": "26.5.3",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"husky": "4.3.6",
"jest": "26.6.3",
"jest-environment-jsdom-fourteen": "1.0.1",
"jest-watch-typeahead": "0.6.1",
"lint-staged": "10.2.13",
"prettier": "2.0.5",
"pretty-quick": "2.0.1",
"start-server-and-test": "1.11.2",
"ts-jest": "26.4.1",
"typescript": "3.9.5"
"lint-staged": "10.5.3",
"prettier": "2.2.1",
"pretty-quick": "3.1.0",
"start-server-and-test": "1.11.7",
"ts-jest": "26.4.4",
"typescript": "4.1.3"
},
"private": true
}

View File

@@ -1,4 +1,4 @@
const { sessionMiddleware, unstable_simpleRolesIsAuthorized } = require("@blitzjs/server")
const { sessionMiddleware, simpleRolesIsAuthorized } = require("@blitzjs/server")
const { GraphQLClient, gql } = require("graphql-request")
const graphQLClient = new GraphQLClient("https://graphql.fauna.com/graphql", {
@@ -20,7 +20,7 @@ const normalizeSession = (faunaSession) => {
module.exports = {
middleware: [
sessionMiddleware({
unstable_isAuthorized: unstable_simpleRolesIsAuthorized,
isAuthorized: simpleRolesIsAuthorized,
getSession: async (handle) => {
const { findSessionByHandle: session } = await graphQLClient.request(
gql`

View File

@@ -1,6 +1,6 @@
{
"name": "@examples/fauna",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"scripts": {
"start": "blitz start",
"studio": "blitz db studio",
@@ -27,44 +27,44 @@
]
},
"dependencies": {
"blitz": "0.27.0-canary.1",
"blitz": "0.28.0-canary.1",
"final-form": "4.20.1",
"graphql": "15.3.0",
"graphql-request": "3.1.0",
"react": "0.0.0-experimental-4ead6b530",
"react-dom": "0.0.0-experimental-4ead6b530",
"react-error-boundary": "2.3.1",
"react-final-form": "6.5.1",
"graphql": "15.4.0",
"graphql-request": "3.4.0",
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0",
"react-error-boundary": "3.1.0",
"react-final-form": "6.5.2",
"secure-password": "4.0.0",
"zod": "1.10.0"
"zod": "1.11.11"
},
"devDependencies": {
"@testing-library/jest-dom": "5.11.4",
"@testing-library/react": "11.1.0",
"@testing-library/react-hooks": "3.4.2",
"@types/jest": "26.0.14",
"@types/react": "16.9.38",
"@testing-library/jest-dom": "5.11.8",
"@testing-library/react": "11.2.2",
"@testing-library/react-hooks": "3.7.0",
"@types/jest": "26.0.19",
"@types/react": "17.0.0",
"@types/secure-password": "3.1.0",
"@typescript-eslint/eslint-plugin": "2.34.1-alpha.2",
"@typescript-eslint/parser": "2.34.1-alpha.2",
"@typescript-eslint/eslint-plugin": "4.11.1",
"@typescript-eslint/parser": "4.11.1",
"babel-eslint": "10.1.0",
"eslint": "7.6.0",
"eslint-config-react-app": "5.2.1",
"eslint": "7.16.0",
"eslint-config-react-app": "6.0.0",
"eslint-plugin-flowtype": "5.2.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jsx-a11y": "6.3.1",
"eslint-plugin-react": "7.20.5",
"eslint-plugin-react-hooks": "4.0.8",
"husky": "4.2.5",
"jest": "26.5.3",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"husky": "4.3.6",
"jest": "26.6.3",
"jest-environment-jsdom-fourteen": "1.0.1",
"jest-watch-typeahead": "0.6.1",
"lint-staged": "10.2.13",
"prettier": "2.0.5",
"pretty-quick": "2.0.1",
"start-server-and-test": "1.11.2",
"ts-jest": "26.4.1",
"typescript": "3.9.5"
"lint-staged": "10.5.3",
"prettier": "2.2.1",
"pretty-quick": "3.1.0",
"start-server-and-test": "1.11.7",
"ts-jest": "26.4.4",
"typescript": "4.1.3"
},
"private": true
}

View File

@@ -1,6 +1,6 @@
{
"name": "no-prisma",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"scripts": {
"start": "blitz start",
"build": "blitz build",
@@ -26,29 +26,29 @@
]
},
"dependencies": {
"blitz": "0.27.0-canary.1",
"knex": "0.21.2",
"react": "0.0.0-experimental-4ead6b530",
"react-dom": "0.0.0-experimental-4ead6b530",
"blitz": "0.28.0-canary.1",
"knex": "0.21.15",
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0",
"sqlite3": "5.0.0"
},
"devDependencies": {
"@types/react": "16.9.43",
"@typescript-eslint/eslint-plugin": "2.34.1-alpha.2",
"@typescript-eslint/parser": "2.34.1-alpha.2",
"@types/react": "17.0.0",
"@typescript-eslint/eslint-plugin": "4.11.1",
"@typescript-eslint/parser": "4.11.1",
"babel-eslint": "10.1.0",
"eslint": "7.6.0",
"eslint-config-react-app": "5.2.1",
"eslint": "7.16.0",
"eslint-config-react-app": "6.0.0",
"eslint-plugin-flowtype": "5.2.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jsx-a11y": "6.3.1",
"eslint-plugin-react": "7.20.5",
"eslint-plugin-react-hooks": "4.0.8",
"husky": "4.2.5",
"lint-staged": "10.2.13",
"prettier": "2.0.5",
"pretty-quick": "2.0.1",
"typescript": "3.9.6"
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"husky": "4.3.6",
"lint-staged": "10.5.3",
"prettier": "2.2.1",
"pretty-quick": "3.1.0",
"typescript": "4.1.3"
},
"private": true
}

View File

@@ -1,6 +1,6 @@
{
"name": "@examples/plain-js",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"scripts": {
"start": "blitz start",
"build": "blitz db migrate && blitz build",
@@ -31,27 +31,26 @@
"dependencies": {
"@prisma/cli": "2.12.0",
"@prisma/client": "2.12.0",
"blitz": "0.27.0-canary.1",
"react": "0.0.0-experimental-4ead6b530",
"react-dom": "0.0.0-experimental-4ead6b530"
"blitz": "0.28.0-canary.1",
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0"
},
"devDependencies": {
"@types/react": "16.9.35",
"@typescript-eslint/eslint-plugin": "2.31.0",
"@typescript-eslint/parser": "2.31.0",
"@typescript-eslint/eslint-plugin": "4.11.1",
"@typescript-eslint/parser": "4.11.1",
"babel-eslint": "10.1.0",
"eslint": "7.6.0",
"eslint-config-react-app": "5.2.1",
"eslint": "7.16.0",
"eslint-config-react-app": "6.0.0",
"eslint-plugin-flowtype": "5.2.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jsx-a11y": "6.3.1",
"eslint-plugin-react": "7.20.5",
"eslint-plugin-react-hooks": "4.0.8",
"husky": "4.2.5",
"lint-staged": "10.2.2",
"prettier": "2.0.5",
"pretty-quick": "2.0.1",
"typescript": "3.9.2"
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"husky": "4.3.6",
"lint-staged": "10.5.3",
"prettier": "2.2.1",
"pretty-quick": "3.1.0",
"typescript": "4.1.3"
},
"private": true
}

View File

@@ -1483,7 +1483,6 @@
expand-tilde "2.0.2"
fast-glob "3.2.2"
flush-write-stream "2.0.0"
folder-hash "3.3.1"
from2 "2.3.0"
gulp-if "3.0.0"
hasha "5.2.0"
@@ -4943,15 +4942,6 @@ flush-write-stream@^1.0.0, flush-write-stream@^1.0.2:
inherits "^2.0.3"
readable-stream "^2.3.6"
folder-hash@3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/folder-hash/-/folder-hash-3.3.1.tgz#72ca3593a43c3873e27a8edce2423f30f8ee6096"
integrity sha512-M5Rxur/jgIWfr0gbJBRY9aMLXCieM6Gy1xB/KqC2Nd4ZvxZJAccWvg+7SmbfALntmYj51wHWzcE4cqgXQPWaBA==
dependencies:
debug "^4.1.1"
graceful-fs "~4.2.0"
minimatch "~3.0.4"
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"

View File

@@ -0,0 +1,4 @@
/* integration test for scss modules */
.red {
border: 2px solid red;
}

View File

@@ -1,9 +1,11 @@
import {Link} from "blitz"
import styles from "./index.module.scss"
function StoreAdminPage() {
return (
<div>
<h1>Store Admin</h1>
<h1 className={styles.red}>Store Admin</h1>
<div>
<p>
<Link href="/admin/products">

View File

@@ -0,0 +1,5 @@
// this file acts as a regression test for #1646
export function getMeSomeQualityHumor() {
return "https://xkcd.com/" + Math.floor(Math.random() * 2402)
}

View File

@@ -4,6 +4,10 @@ import getProducts, {averagePrice} from "../../queries/getProducts"
import {Product} from "db"
import superjson from "superjson"
// regression test for #1646
import {getMeSomeQualityHumor} from "../../api"
console.log("Attention! Must read: " + getMeSomeQualityHumor())
type StaticProps = {
dataString: string
}

View File

@@ -1,25 +1,25 @@
#!/usr/bin/env node
if (process.platform !== "win32") {
const glob = require("glob")
const fs = require("fs")
const glob = require("glob")
const fs = require("fs")
glob("./.next/static/chunks/**/*", {nodir: true}, (err, matches) => {
if (err) {
throw err
}
const offenders = []
for (const match of matches) {
const content = fs.readFileSync(match).toString()
if (content.includes("this line should not be included in the frontend bundle")) {
offenders.push(match)
glob("./.next/static/chunks/**/*", {nodir: true}, (err, matches) => {
if (err) {
throw err
}
}
if (offenders.length > 0) {
console.error(`tree-shaking failed: ${offenders} includes the forbidden words.`)
process.exit(1)
}
})
const offenders = []
for (const match of matches) {
const content = fs.readFileSync(match).toString()
if (content.includes("this line should not be included in the frontend bundle")) {
offenders.push(match)
}
}
if (offenders.length > 0) {
console.error(`tree-shaking failed: ${offenders} includes the forbidden words.`)
process.exit(1)
}
})
}

View File

@@ -5,6 +5,9 @@ module.exports = {
return next()
},
],
experimental: {
isomorphicResolverImports: true,
},
// webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
// // Note: we provide webpack above so you should not `require` it
// // Perform customizations to webpack config

View File

@@ -3,6 +3,15 @@ describe("products#index page", () => {
cy.visit("/products")
cy.contains("h1", "Products")
})
it("Logs the XKCD (Regression #1646)", () => {
cy.visit("/products", {
onBeforeLoad(win) {
cy.stub(win.console, "log").as("consoleLog")
},
})
cy.get("@consoleLog").should("be.calledWithMatch", /Attention! Must read: .*/)
})
})
describe("products#show page", () => {

View File

@@ -1,13 +1,14 @@
{
"name": "@examples/store",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"private": true,
"scripts": {
"build": "blitz db migrate && blitz build",
"cy:open": "cypress open",
"cy:run": "cypress run",
"test:server": "blitz db migrate && blitz db seed && blitz start --production -p 3099",
"test": "./assert-tree-shaking-works.js && start-server-and-test test:server http://localhost:3099 cy:run"
"test:server": "blitz db migrate && blitz db seed && blitz build && blitz start --production -p 3099",
"test": "cross-env NODE_ENV=test start-server-and-test test:server http://localhost:3099 cy:run",
"posttest": "node assert-tree-shaking-works.js"
},
"prisma": {
"schema": "db/schema.prisma"
@@ -21,19 +22,19 @@
"dependencies": {
"@prisma/cli": "2.12.0",
"@prisma/client": "2.12.0",
"blitz": "0.27.0-canary.1",
"final-form": "4.19.1",
"react": "0.0.0-experimental-4ead6b530",
"react-dom": "0.0.0-experimental-4ead6b530",
"react-error-boundary": "2.3.1",
"react-final-form": "6.4.0",
"typescript": "3.8.3"
"blitz": "0.28.0-canary.1",
"final-form": "4.20.1",
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0",
"react-error-boundary": "3.1.0",
"react-final-form": "6.5.2",
"typescript": "4.1.3"
},
"devDependencies": {
"@types/react": "16.9.34",
"cypress": "4.11.0",
"eslint-plugin-cypress": "2.10.3",
"sass": "1.29.0",
"start-server-and-test": "1.11.2"
"@types/react": "17.0.0",
"cypress": "6.2.0",
"eslint-plugin-cypress": "2.11.2",
"sass": "1.32.0",
"start-server-and-test": "1.11.7"
}
}

8
examples/store/types.d.ts vendored Normal file
View File

@@ -0,0 +1,8 @@
declare module "*.scss" {
const content: {[className: string]: string}
export default content
}
declare module "*.css" {
const content: {[className: string]: string}
export default content
}

View File

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

View File

@@ -13,7 +13,7 @@
]
},
"engines": {
"node": ">= 10.13.0"
"node": ">=12.20.0"
},
"scripts": {
"postinstall": "npm rebuild husky && patch-package",
@@ -39,105 +39,106 @@
"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"
},
"resolutions": {},
"devDependencies": {
"@rollup/pluginutils": "3.0.8",
"@testing-library/jest-dom": "5.5.0",
"@testing-library/react": "10.0.3",
"@testing-library/react-hooks": "3.3.0",
"@rollup/pluginutils": "4.1.0",
"@testing-library/jest-dom": "5.11.8",
"@testing-library/react": "11.2.2",
"@testing-library/react-hooks": "3.7.0",
"@types/b64-lite": "1.3.0",
"@types/cookie": "0.4.0",
"@types/cookie-session": "2.0.41",
"@types/cookie-session": "2.0.42",
"@types/cross-spawn": "6.0.2",
"@types/debug": "4.1.5",
"@types/detect-port": "1.3.0",
"@types/diff": "4.0.2",
"@types/dotenv-flow": "3.0.1",
"@types/diff": "5.0.0",
"@types/dotenv-flow": "3.1.0",
"@types/flush-write-stream": "1.0.0",
"@types/from2": "2.3.0",
"@types/fs-extra": "8.1.0",
"@types/fs-extra": "9.0.6",
"@types/fs-readdir-recursive": "1.0.0",
"@types/gulp-if": "0.0.33",
"@types/ink-spinner": "3.0.0",
"@types/jest": "25.1.3",
"@types/jest": "26.0.19",
"@types/jsonwebtoken": "8.5.0",
"@types/lodash": "4.14.150",
"@types/lodash": "4.14.166",
"@types/mem-fs": "1.1.2",
"@types/mem-fs-editor": "5.1.1",
"@types/mem-fs-editor": "7.0.0",
"@types/merge-stream": "1.1.2",
"@types/mock-fs": "4.10.0",
"@types/node": "13.13.2",
"@types/mock-fs": "4.13.0",
"@types/node": "14.14.17",
"@types/node-fetch": "2.5.7",
"@types/parallel-transform": "1.1.0",
"@types/passport": "1.0.4",
"@types/passport": "1.0.5",
"@types/pluralize": "0.0.29",
"@types/prettier": "2.0.0",
"@types/prettier": "2.1.6",
"@types/pump": "1.1.0",
"@types/pumpify": "1.4.1",
"@types/react": "16.9.34",
"@types/readable-stream": "2.3.5",
"@types/react": "17.0.0",
"@types/react-dom": "17.0.0",
"@types/readable-stream": "2.3.9",
"@types/rimraf": "3.0.0",
"@types/tar": "4.0.3",
"@types/tar": "4.0.4",
"@types/test-listen": "1.1.0",
"@types/through2": "2.0.34",
"@types/through2": "2.0.36",
"@types/vinyl": "2.0.4",
"@types/vinyl-fs": "2.4.11",
"@types/webpack": "4.41.13",
"@typescript-eslint/eslint-plugin": "4.3.1-alpha.1",
"@typescript-eslint/parser": "4.3.1-alpha.1",
"@types/webpack": "4.41.25",
"@typescript-eslint/eslint-plugin": "4.11.1",
"@typescript-eslint/parser": "4.11.1",
"@wessberg/cjs-to-esm-transformer": "0.0.22",
"@wessberg/rollup-plugin-ts": "1.3.3",
"@wessberg/rollup-plugin-ts": "1.3.8",
"babel-eslint": "10.x",
"babel-jest": "26.3.0",
"babel-jest": "26.6.3",
"concurrently": "5.3.0",
"cpy-cli": "3.1.1",
"cross-env": "7.0.2",
"debug": "4.1.1",
"yalc": "1.0.0-pre.47",
"delay": "4.3.0",
"directory-tree": "2.2.4",
"eslint": "7.7.0",
"eslint-config-react-app": "5.2.1",
"eslint-plugin-es": "mysticatea/eslint-plugin-es",
"cross-env": "7.0.3",
"debug": "4.3.1",
"delay": "4.4.0",
"directory-tree": "2.2.5",
"eslint": "7.16.0",
"eslint-config-react-app": "6.0.0",
"eslint-plugin-es": "4.1.0",
"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",
"eslint-plugin-prettier": "3.1.4",
"eslint-plugin-react": "7.20.6",
"eslint-plugin-react-hooks": "4.1.0",
"eslint-plugin-simple-import-sort": "5.0.3",
"eslint-plugin-unicorn": "21.0.0",
"husky": "4.2.5",
"isomorphic-unfetch": "3.0.0",
"jest": "24.9.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-prettier": "3.3.0",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"eslint-plugin-simple-import-sort": "7.0.0",
"eslint-plugin-unicorn": "25.0.1",
"husky": "4.3.6",
"jest": "26.6.3",
"jest-environment-jsdom-sixteen": "1.0.3",
"lerna": "3.22.1",
"lint-staged": "10.2.13",
"lint-staged": "10.5.3",
"mock-fs": "4.13.0",
"nock": "12.0.3",
"nock": "13.0.5",
"npm-run-all": "4.1.5",
"patch-package": "6.2.2",
"postinstall-postinstall": "2.1.0",
"prettier": "2.1.1",
"pretty-quick": "2.0.1",
"prompt": "1.0.0",
"react-test-renderer": "16.13.1",
"release": "6.1.0",
"prettier": "2.2.1",
"pretty-quick": "3.1.0",
"prompt": "1.1.0",
"react-test-renderer": "17.0.1",
"release": "6.3.0",
"rimraf": "3.0.2",
"rollup": "2.26.8",
"rollup": "2.35.1",
"rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-json": "4.0.0",
"rollup-plugin-node-polyfills": "0.2.1",
"rollup-plugin-node-resolve": "5.2.0",
"rollup-plugin-peer-deps-external": "2.2.3",
"semver": "7.3.2",
"rollup-plugin-peer-deps-external": "2.2.4",
"semver": "7.3.4",
"stdout-stderr": "0.1.13",
"test-listen": "1.1.0",
"ts-jest": "24.3.0",
"tsdx": "0.13.3",
"tslib": "1.11.1",
"typescript": "4.0.3",
"wait-on": "4.0.2"
"ts-jest": "26.4.4",
"tsdx": "0.14.1",
"tslib": "2.0.3",
"typescript": "4.1.3",
"wait-on": "5.2.1",
"yalc": "1.0.0-pre.49"
},
"husky": {
"hooks": {
@@ -151,11 +152,5 @@
"eslint --fix"
]
},
"resolutions": {
"jest": "24.9.0",
"@types/react": "16.9.34",
"@types/react-dom": "16.9.8",
"ts-jest": "24.3.0"
},
"version": "0.0.0"
}

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.27.0-canary.1",
"version": "0.28.0-canary.1",
"license": "MIT",
"scripts": {
"clean": "rimraf dist",
@@ -40,16 +40,16 @@
"url": "https://github.com/blitz-js/blitz"
},
"dependencies": {
"@blitzjs/cli": "0.27.0-canary.1",
"@blitzjs/config": "0.27.0-canary.1",
"@blitzjs/core": "0.27.0-canary.1",
"@blitzjs/display": "0.27.0-canary.1",
"@blitzjs/generator": "0.27.0-canary.1",
"@blitzjs/installer": "0.27.0-canary.1",
"@blitzjs/server": "0.27.0-canary.1",
"envinfo": "7.7.2",
"os-name": "3.1.0",
"pkg-dir": "4.2.0",
"@blitzjs/cli": "0.28.0-canary.1",
"@blitzjs/config": "0.28.0-canary.1",
"@blitzjs/core": "0.28.0-canary.1",
"@blitzjs/display": "0.28.0-canary.1",
"@blitzjs/generator": "0.28.0-canary.1",
"@blitzjs/installer": "0.28.0-canary.1",
"@blitzjs/server": "0.28.0-canary.1",
"envinfo": "7.7.3",
"os-name": "4.0.0",
"pkg-dir": "5.0.0",
"resolve-from": "5.0.0"
},
"keywords": [

View File

@@ -10,7 +10,7 @@ async function main() {
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:
`You are using beta software - if you have any problems, please open an issue here:
https://github.com/blitz-js/blitz/issues/new/choose\n`,
),
)

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/cli",
"description": "Blitz.js CLI",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"license": "MIT",
"scripts": {
"b": "./bin/run",
@@ -30,42 +30,42 @@
"/lib"
],
"dependencies": {
"@blitzjs/display": "0.27.0-canary.1",
"@blitzjs/repl": "0.27.0-canary.1",
"@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",
"@blitzjs/display": "0.28.0-canary.1",
"@blitzjs/repl": "0.28.0-canary.1",
"@oclif/command": "1.8.0",
"@oclif/config": "1.17.0",
"@oclif/plugin-autocomplete": "0.3.0",
"@oclif/plugin-help": "3.2.1",
"@oclif/plugin-not-found": "1.2.4",
"@prisma/sdk": "2.12.0",
"@salesforce/lazy-require": "0.3.2",
"camelcase": "6.0.0",
"chalk": "4.0.0",
"@salesforce/lazy-require": "0.3.3",
"camelcase": "6.2.0",
"chalk": "4.1.0",
"cross-spawn": "7.0.3",
"dotenv-expand": "5.1.0",
"dotenv-flow": "3.2.0",
"enquirer": "2.3.4",
"got": "11.1.3",
"enquirer": "2.3.6",
"got": "11.8.1",
"has-yarn": "2.1.0",
"hasbin": "1.2.3",
"minimist": "1.2.5",
"p-event": "4.2.0",
"pkg-dir": "4.2.0",
"pkg-dir": "5.0.0",
"pluralize": "8.0.0",
"rimraf": "3.0.2",
"tar": "6.0.2",
"ts-node": "8.9.0",
"tar": "6.0.5",
"ts-node": "9.1.1",
"tsconfig-paths": "3.9.0",
"v8-compile-cache": "2.1.1"
"v8-compile-cache": "2.2.0"
},
"devDependencies": {
"@blitzjs/generator": "0.27.0-canary.1",
"@blitzjs/installer": "0.27.0-canary.1",
"@blitzjs/server": "0.27.0-canary.1",
"@oclif/dev-cli": "1.22.2",
"@oclif/test": "1.2.5",
"@blitzjs/generator": "0.28.0-canary.1",
"@blitzjs/installer": "0.28.0-canary.1",
"@blitzjs/server": "0.28.0-canary.1",
"@oclif/dev-cli": "1.26.0",
"@oclif/test": "1.2.8",
"@prisma/cli": "2.12.0",
"nock": "13.0.0-beta.3",
"nock": "13.0.5",
"stdout-stderr": "0.1.13"
},
"jest": {

View File

@@ -9,10 +9,8 @@ const runPrisma = async (args: string[], silent = false) => {
if (!prismaBin) {
try {
prismaBin = await getPrismaBin()
} catch {
throw new Error(
"Oops, we can't find Prisma Client. Please make sure it's installed in your project",
)
} catch (err) {
throw err
}
}

View File

@@ -0,0 +1,76 @@
import {Command, flags} from "@oclif/command"
import {ServerConfig} from "@blitzjs/server"
import {log, table as Table} from "@blitzjs/display"
export class Routes extends Command {
static description = "Display all Blitz URL Routes"
static aliases = ["r"]
static flags = {
help: flags.help({char: "h"}),
}
getColor(type: string) {
switch (type) {
case "rpc":
return "magenta"
case "api":
return "blue"
default:
return "green"
}
}
async run() {
const config: ServerConfig = {
rootFolder: process.cwd(),
}
this.parse(Routes)
try {
const {routes} = await import("@blitzjs/server")
const routesResult = await routes(config)
log.newline()
const table = new Table({
columns: [
{name: "HTTP", alignment: "center"},
{name: "Source File", alignment: "left"},
{name: "URI", alignment: "left"},
{name: "Type", alignment: "center"},
],
sort: (q, r) => {
// Sort pages to the top
if (q.Type === "PAGE" && r.Type !== "PAGE") {
return -1
}
if (q.Type !== "PAGE" && r.Type === "PAGE") {
return 1
}
if (q.Type > r.Type) {
return 1
}
if (q.Type < r.Type) {
return -1
}
return 0
},
})
routesResult.forEach(({path, uri, verb, type}: any) => {
table.addRow(
{
[table.table.columns[0].name]: verb.toUpperCase(),
[table.table.columns[1].name]: path,
[table.table.columns[2].name]: uri,
[table.table.columns[3].name]: type.toUpperCase(),
},
{color: this.getColor(type)},
)
})
console.log(table.render())
} catch (err) {
console.error(err)
process.exit(1)
}
}
}

View File

@@ -7,6 +7,7 @@ import fetch from "node-fetch"
import nock from "nock"
import rimraf from "rimraf"
import {stdout} from "stdout-stderr"
import pkgDir from "pkg-dir"
jest.setTimeout(120 * 1000)
const blitzCliPackageJson = require("../../package.json")
@@ -34,6 +35,15 @@ jest.mock("enquirer", () => {
})
})
const tempDir = path.join(__dirname, ".test")
beforeEach(() => {
fs.mkdirSync(tempDir)
})
afterEach(() => {
rimraf.sync(tempDir)
})
describe("`new` command", () => {
describe("when scaffolding new project", () => {
beforeEach(() => {
@@ -45,7 +55,7 @@ describe("`new` command", () => {
stdout.stop()
})
jest.setTimeout(120 * 1000)
jest.setTimeout(200 * 1000)
function makeTempDir() {
const tmpDirPath = path.join(os.tmpdir(), "blitzjs-test-")
@@ -112,11 +122,24 @@ describe("`new` command", () => {
)
testIfNotWindows("performs all steps on a full install", async () => {
const tempDir = makeTempDir()
await whileStayingInCWD(() => New.run([tempDir]))
rimraf.sync(tempDir)
const currentBlitzWorkspaceVersion = require(path.join(
await pkgDir(__dirname),
"package.json",
)).version
expect(getStepsFromOutput()).toStrictEqual([`cd ${tempDir}`, "blitz start"])
jest.mock("@blitzjs/generator/src/utils/get-blitz-dependency-version", () => {
return jest.fn().mockImplementation(() => {
return {
value: currentBlitzWorkspaceVersion,
fallback: false,
}
})
})
const newAppDir = fs.mkdtempSync(path.join(tempDir, "full-install-"))
await whileStayingInCWD(() => New.run([newAppDir, "--skip-upgrade"]))
expect(getStepsFromOutput()).toStrictEqual([`cd ${newAppDir}`, "blitz start"])
})
it("fetches latest version from template", async () => {

View File

@@ -0,0 +1,17 @@
import {Routes} from "../../src/commands/routes"
const routes = jest.fn(() => {
return []
})
jest.mock("@blitzjs/server", () => ({routes}))
describe("Routes command", () => {
beforeEach(() => {
jest.clearAllMocks()
})
it("runs the routes script", async () => {
await Routes.run([])
expect(routes).toBeCalled()
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/config",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"description": "Loads the blitz app config",
"license": "MIT",
"scripts": {

View File

@@ -1,17 +1,26 @@
import {existsSync} from "fs"
import {PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER} from "next/constants"
import {join} from "path"
import pkgDir from "pkg-dir"
const configFiles = ["blitz.config.js", "next.config.js"]
export interface BlitzConfig extends Record<string, unknown> {
target?: string
experimental?: {
isomorphicResolverImports?: boolean
}
}
/**
* @param {boolean | undefined} reload - reimport config files to reset global cache
*/
export const getConfig = (reload?: boolean): Record<string, unknown> => {
export const getConfig = (reload?: boolean): BlitzConfig => {
if (global.blitzConfig && Object.keys(global.blitzConfig).length > 0 && !reload) {
return global.blitzConfig
}
const {PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER} = require("next/constants")
let blitzConfig = {}
const projectRoot = pkgDir.sync() || process.cwd()

View File

@@ -1,14 +1,13 @@
{
"name": "@blitzjs/core",
"description": "Blitz.js core functionality",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"license": "MIT",
"scripts": {
"clean": "rimraf dist",
"wait:display": "wait-on ../display/dist/packages/display/src/index.d.ts",
"predev": "yarn wait:display",
"dev": "tsdx watch --verbose",
"prebuild": "yarn predev",
"build": "tsdx build",
"test": "tsdx test --env=jest-environment-jsdom-sixteen",
"test:watch": "tsdx test --watch --env=jest-environment-jsdom-sixteen"
@@ -41,17 +40,15 @@
"url": "https://github.com/blitz-js/blitz"
},
"dependencies": {
"@blitzjs/display": "0.28.0-canary.1",
"b64-lite": "1.4.0",
"bad-behavior": "1.0.1",
"cookie-session": "1.4.0",
"deepmerge": "4.2.2",
"lodash": "^4.17.19",
"lodash-es": "^4.17.15",
"lodash": "^4.17.20",
"lodash-es": "^4.17.20",
"passport": "0.4.1",
"pretty-ms": "6.0.1",
"react-query": "2.5.12",
"superjson": "1.3.0",
"url": "0.11.0"
"superjson": "1.4.1"
},
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922"
}

View File

@@ -14,6 +14,7 @@ export {passportAuth} from "./passport-adapter"
export {getIsomorphicEnhancedResolver} from "./rpc"
export {useMutation} from "./use-mutation"
export {invoke, invokeWithMiddleware} from "./invoke"
export {
getAllMiddlewareForModule,
handleRequestWithMiddleware,
@@ -44,11 +45,11 @@ export {
export {default as Head} from "next/head"
export {default as Link} from "next/link"
export {default as Link, LinkProps} from "next/link"
export {default as Router} from "next/router"
export {default as Image} from "next/image"
export {default as Image, ImageProps} from "next/image"
export {
default as Document,
@@ -62,7 +63,7 @@ export {
export {default as dynamic} from "next/dynamic"
export {default as ErrorComponent} from "next/error"
export {default as ErrorComponent, ErrorProps} from "next/error"
export {default as getConfig} from "next/config"
@@ -77,3 +78,4 @@ export type BlitzPage<P = {}, IP = P> = NextPage<P, IP> & {
getLayout?: (component: JSX.Element) => JSX.Element
}
export {isLocalhost} from "./utils/index"
export {prettyMs} from "./utils/pretty-ms"

View File

@@ -1,6 +1,6 @@
import delay from "delay"
import http, {IncomingMessage, ServerResponse} from "http"
import fetch from "isomorphic-unfetch"
import fetch from "node-fetch"
import listen from "test-listen"
import {invokeWithMiddleware} from "./invoke"
import {EnhancedResolver} from "./types"

View File

@@ -1,5 +1,4 @@
import {baseLogger, chalk, log as displayLog} from "@blitzjs/display"
import prettyMs from "pretty-ms"
import {getAllMiddlewareForModule, handleRequestWithMiddleware} from "./middleware"
import {
EnhancedResolver,
@@ -12,6 +11,7 @@ import {
Resolver,
} from "./types"
import {isClient} from "./utils"
import {prettyMs} from "./utils/pretty-ms"
export function invoke<T extends QueryFn, TInput = FirstParam<T>, TResult = PromiseReturnType<T>>(
queryFn: T,
@@ -56,12 +56,12 @@ export async function invokeWithMiddleware<TInput, TResult>(
displayLog.newline()
try {
log.info(chalk.dim("Starting with input:"), params)
const startTime = new Date().getTime()
const startTime = Date.now()
const result = await enhancedResolver(params, res.blitzCtx)
const duration = prettyMs(new Date().getTime() - startTime)
log.info(chalk.dim("Finished", "in", duration))
const duration = Date.now() - startTime
log.info(chalk.dim(`Finished in ${prettyMs(duration)}`))
displayLog.newline()
res.blitzResult = result

View File

@@ -1,6 +1,6 @@
import http from "http"
import fetch from "isomorphic-unfetch"
import {apiResolver} from "next/dist/next-server/server/api-utils"
import fetch from "node-fetch"
import listen from "test-listen"
import {BlitzApiRequest, BlitzApiResponse} from "."
import {handleRequestWithMiddleware} from "./middleware"
@@ -65,7 +65,6 @@ describe("handleRequestWithMiddleware", () => {
})
})
// Failing on windows for unknown reason
it("middleware can throw", async () => {
console.log = jest.fn()
console.error = jest.fn()
@@ -106,7 +105,7 @@ describe("handleRequestWithMiddleware", () => {
async function mockServer(middleware: Middleware[], callback: (url: string) => Promise<void>) {
const apiEndpoint = async (req: BlitzApiRequest, res: BlitzApiResponse) => {
try {
await handleRequestWithMiddleware(req, res, middleware)
await handleRequestWithMiddleware(req, res, middleware, {stackPrintOnError: false})
} catch (err) {
res.status(500)
} finally {

View File

@@ -39,7 +39,13 @@ export async function handleRequestWithMiddleware(
req: BlitzApiRequest | IncomingMessage,
res: BlitzApiResponse | ServerResponse,
middleware: Middleware | Middleware[],
{throwOnError = true}: {throwOnError?: boolean} = {},
{
throwOnError = true,
stackPrintOnError = true,
}: {
throwOnError?: boolean
stackPrintOnError?: boolean
} = {},
) {
if (!(res as MiddlewareResponse).blitzCtx) {
;(res as MiddlewareResponse).blitzCtx = {}
@@ -78,7 +84,11 @@ export async function handleRequestWithMiddleware(
if (error._clearStack) {
delete error.stack
}
baseLogger().prettyError(error)
if (stackPrintOnError) {
baseLogger().prettyError(error)
} else {
baseLogger().prettyError(error, true, false, false)
}
log.newline()
if (throwOnError) throw error
}

View File

@@ -51,13 +51,18 @@ export function passportAuth(config: BlitzPassportConfig) {
"No Passport strategies found! Please add at least one strategy.",
)
const strategy = config.strategies.find((strategy) => strategy.name === req.query.auth[0])
assert(strategy, `A passport strategy was not found for: ${req.query.auth[0]}`)
const blitzStrategy = config.strategies.find(
({strategy}) => strategy.name === req.query.auth[0],
)
assert(blitzStrategy, `A passport strategy was not found for: ${req.query.auth[0]}`)
const {strategy, authenticateOptions} = blitzStrategy
passport.use(strategy)
const strategyName = strategy.name as string
if (req.query.auth.length === 1) {
log.info(`Starting authentication via ${strategy.name}...`)
log.info(`Starting authentication via ${strategyName}...`)
if (req.query.redirectUrl) {
middleware.push(async (req, res, next) => {
const session = res.blitzCtx.session as SessionContext
@@ -67,33 +72,33 @@ export function passportAuth(config: BlitzPassportConfig) {
})
}
middleware.push(
connectMiddleware(passport.authenticate(strategy.name, {...config.authenticateOptions})),
connectMiddleware(passport.authenticate(strategyName, {...authenticateOptions})),
)
} else if (req.query.auth[1] === "callback") {
log.info(`Processing callback for ${strategy.name}...`)
log.info(`Processing callback for ${strategyName}...`)
middleware.push(
connectMiddleware((req, res, next) => {
const session = (res as any).blitzCtx.session as SessionContext
assert(session, "Missing Blitz sessionMiddleware!")
passport.authenticate(strategy.name, async (err: any, result: unknown) => {
passport.authenticate(strategyName, async (err: any, result: unknown) => {
try {
let error = err
if (!error) {
if (result === false) {
log.warning(
`Login via ${strategy.name} failed - usually this means the user did not authenticate properly with the provider`,
`Login via ${strategyName} failed - usually this means the user did not authenticate properly with the provider`,
)
error = `Login failed`
}
assert(
typeof result === "object" && result !== null,
`Your '${strategy.name}' passport verify callback returned empty data. Ensure you call 'done(null, {publicData: {userId: 1, roles: ['myRole']}})')`,
`Your '${strategyName}' passport verify callback returned empty data. Ensure you call 'done(null, {publicData: {userId: 1, roles: ['myRole']}})')`,
)
assert(
(result as any).publicData,
`'publicData' is missing from your '${strategy.name}' passport verify callback. Ensure you call 'done(null, {publicData: {userId: 1, roles: ['myRole']}})')`,
`'publicData' is missing from your '${strategyName}' passport verify callback. Ensure you call 'done(null, {publicData: {userId: 1, roles: ['myRole']}})')`,
)
}

View File

@@ -24,7 +24,7 @@ export type SessionConfig = {
createSession: (session: SessionModel) => Promise<SessionModel>
updateSession: (handle: string, session: Partial<SessionModel>) => Promise<SessionModel>
deleteSession: (handle: string) => Promise<SessionModel>
unstable_isAuthorized: (userRoles: string[], input?: any) => boolean
isAuthorized: (userRoles: string[], input?: any) => boolean
}
export interface SessionContextBase {

View File

@@ -81,11 +81,15 @@ export type ConnectMiddleware = (
next: (error?: Error) => void,
) => void
export type BlitzPassportStrategy = {
authenticateOptions?: AuthenticateOptions
strategy: Strategy
}
export type BlitzPassportConfig = {
successRedirectUrl?: string
errorRedirectUrl?: string
authenticateOptions?: AuthenticateOptions
strategies: Required<Strategy>[]
strategies: BlitzPassportStrategy[]
secureProxy?: boolean
}

View File

@@ -0,0 +1,20 @@
import {prettyMs} from "./pretty-ms"
describe("prettyMs", () => {
it("returns pretty strings", () => {
// ms
expect(prettyMs(0)).toMatchInlineSnapshot(`"0ms"`)
expect(prettyMs(200)).toMatchInlineSnapshot(`"200ms"`)
// seconds
expect(prettyMs(1000)).toMatchInlineSnapshot(`"1s"`)
expect(prettyMs(1000)).toMatchInlineSnapshot(`"1s"`)
expect(prettyMs(1600)).toMatchInlineSnapshot(`"1.6s"`)
expect(prettyMs(1500)).toMatchInlineSnapshot(`"1.5s"`)
expect(prettyMs(1666)).toMatchInlineSnapshot(`"1.7s"`)
// negative
expect(prettyMs(-1)).toMatchInlineSnapshot(`"-1ms"`)
expect(prettyMs(-2000)).toMatchInlineSnapshot(`"-2s"`)
})
})

View File

@@ -0,0 +1,20 @@
function round(num: number, decimalPlaces: number) {
const p = Math.pow(10, decimalPlaces)
const m = num * p * (1 + Number.EPSILON)
return Math.round(m) / p
}
/**
* Formats milliseconds to a string
* If more than 1s, it'll return seconds instead
* @example
* prettyMs(100) // -> `100ms`
* prettyMs(1200) // -> `1.2s`
* @param ms
*/
export function prettyMs(ms: number): string {
if (Math.abs(ms) >= 1000) {
return `${round(ms / 1000, 1)}s`
}
return `${ms}ms`
}

View File

@@ -50,7 +50,7 @@ export const validateQueryFn = <TInput, TResult>(
) => {
if (!isEnhancedResolverRpcClient(queryFn) && isNotInUserTestEnvironment()) {
throw new Error(
`It looks like you are trying to use Blitz's useQuery to fetch from third-party APIs. To do that, import useQuery directly from "react-query"`,
`Either the file path to your resolver is incorrect (must be in a "queries" or "mutations" folder that isn't nested inside "pages" or "api") or you are trying to use Blitz's useQuery to fetch from third-party APIs (to do that, import useQuery directly from "react-query")`,
)
}
}

View File

@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`useMutation useMutation calls the resolver with the argument shouldn't work with regular functions 1`] = `"It looks like you are trying to use Blitz's useQuery to fetch from third-party APIs. To do that, import useQuery directly from \\"react-query\\""`;
exports[`useMutation useMutation calls the resolver with the argument shouldn't work with regular functions 1`] = `"Either the file path to your resolver is incorrect (must be in a \\"queries\\" or \\"mutations\\" folder that isn't nested inside \\"pages\\" or \\"api\\") or you are trying to use Blitz's useQuery to fetch from third-party APIs (to do that, import useQuery directly from \\"react-query\\")"`;

View File

@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`useQuery a "query" that converts the string parameter to uppercase shouldn't work with regular functions 1`] = `"It looks like you are trying to use Blitz's useQuery to fetch from third-party APIs. To do that, import useQuery directly from \\"react-query\\""`;
exports[`useQuery a "query" that converts the string parameter to uppercase shouldn't work with regular functions 1`] = `"Either the file path to your resolver is incorrect (must be in a \\"queries\\" or \\"mutations\\" folder that isn't nested inside \\"pages\\" or \\"api\\") or you are trying to use Blitz's useQuery to fetch from third-party APIs (to do that, import useQuery directly from \\"react-query\\")"`;

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/display",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"description": "Display package for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",
@@ -9,7 +9,6 @@
"wait:config": "wait-on ../config/dist/packages/config/src/index.d.ts",
"predev": "yarn wait:config",
"dev": "tsdx watch --verbose",
"prebuild": "yarn predev",
"build": "tsdx build",
"test": "tsdx test",
"test:watch": "tsdx test --watch"
@@ -34,8 +33,10 @@
"url": "git+https://github.com/blitz-js/blitz.git"
},
"dependencies": {
"chalk": "4.0.0",
"ora": "4.0.4",
"tslog": "2.9.1"
"@blitzjs/display": "0.28.0-canary.1",
"chalk": "4.1.0",
"console-table-printer": "2.7.5",
"ora": "5.2.0",
"tslog": "3.0.3"
}
}

View File

@@ -1,5 +1,6 @@
import {getConfig} from "@blitzjs/config"
import c from "chalk"
import {Table} from "console-table-printer"
import ora from "ora"
import readline from "readline"
import {Logger} from "tslog"
@@ -23,6 +24,7 @@ const getLogConfig = (): LogConfig => {
return defaultConfig
}
export const table = Table
export const chalk = c
// const blitzTrueBrandColor = '6700AB'
@@ -220,4 +222,5 @@ export const log = {
variable,
info,
debug,
Table,
}

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/file-pipeline",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"description": "Display package for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",
@@ -8,7 +8,6 @@
"wait:display": "wait-on ../display/dist/packages/display/src/index.d.ts",
"predev": "yarn wait:display",
"dev": "tsdx watch --verbose",
"prebuild": "yarn predev",
"build": "tsdx build",
"test": "tsdx test",
"test:watch": "tsdx test --watch"
@@ -33,20 +32,19 @@
"url": "git+https://github.com/blitz-js/blitz.git"
},
"dependencies": {
"chalk": "4.0.0",
"chokidar": "3.4.2",
"@blitzjs/display": "0.28.0-canary.1",
"chalk": "4.1.0",
"chokidar": "3.4.3",
"flush-write-stream": "2.0.0",
"from2": "2.3.0",
"fs-extra": "9.0.0",
"fs-extra": "9.0.1",
"gulp-if": "3.0.0",
"merge-stream": "2.0.0",
"ora": "4.0.4",
"parallel-transform": "1.2.0",
"pump": "3.0.0",
"pumpify": "2.0.1",
"slash": "3.0.0",
"through2": "3.0.1",
"vinyl": "2.2.0",
"through2": "4.0.2",
"vinyl": "2.2.1",
"vinyl-file": "3.0.0",
"vinyl-fs": "3.0.3"
}

View File

@@ -11,7 +11,7 @@ import {through} from "./streams"
export function createDisplay() {
let lastEvent: Event<any> = {type: INIT, payload: null}
let spinner = log.spinner("Preparing for launch").start()
let spinner = log.spinner("Compiling").start()
const stream = through({objectMode: true}, (event: Event<File>, _, next) => {
switch (event.type) {
@@ -30,7 +30,7 @@ export function createDisplay() {
}
case READY: {
spinner.succeed(chalk.green.bold("Prepped for launch"))
spinner.succeed(chalk.green.bold("Compiled"))
break
}
}

View File

@@ -3,8 +3,16 @@ import {resolve} from "path"
import {testStreamItems} from "../../test-utils"
import {agnosticSource} from "."
const debug = require("debug")("blitz:test:agnostic-source")
const cwd = resolve(__dirname, "fixtures")
/**
* FIXME temporarily disabled as the test is flaky on windows
* @link https://github.com/blitz-js/blitz/pull/1635
*/
const testIfNotWindows = process.platform === "win32" ? test.skip : test
function logItem(fileOrString: {path: string} | string) {
if (typeof fileOrString === "string") {
return fileOrString
@@ -13,17 +21,13 @@ function logItem(fileOrString: {path: string} | string) {
}
describe("agnosticSource", () => {
afterEach(() => {
try {
if (fs.existsSync(resolve(cwd, "three"))) {
fs.unlinkSync(resolve(cwd, "three"))
}
} catch {
// Ignore any errors like ENOENT: no such file or directory
beforeEach(() => {
if (fs.existsSync(resolve(cwd, "three"))) {
fs.unlinkSync(resolve(cwd, "three"))
}
})
test("when watching = false", (done) => {
testIfNotWindows("when watching = false", (done) => {
const expected = [resolve(cwd, "one"), resolve(cwd, "two")]
const {stream} = agnosticSource({ignore: [], include: ["**/*"], cwd, watch: false})
const log: any[] = []
@@ -37,7 +41,7 @@ describe("agnosticSource", () => {
})
})
test("when watching = true", async () => {
testIfNotWindows("when watching = true", async () => {
const expected = [resolve(cwd, "one"), resolve(cwd, "two"), "ready", resolve(cwd, "three")]
const {stream, close} = agnosticSource({ignore: [], include: ["**/*"], cwd, watch: true})
@@ -51,23 +55,24 @@ describe("agnosticSource", () => {
await close()
})
test("include a folder that doesn't exist", (done) => {
console.log("Starting test: include a folder doesn't exist")
testIfNotWindows("include a folder that doesn't exist", (done) => {
debug("Starting test: include a folder doesn't exist")
const expected = [resolve(cwd, "one"), resolve(cwd, "two")]
console.log("expected", expected)
debug("expected", expected)
const {stream} = agnosticSource({
ignore: [],
include: ["**/*", "folder-that-doesnt-exist/"],
cwd,
watch: false,
})
console.log("started stream")
debug("started stream")
const log: any[] = []
stream.on("data", (data) => {
debug("got data", data)
if (data === "ready") {
console.log("stream ready")
debug("stream ready")
stream.end()
console.log("stream ended")
debug("stream ended")
expect(log).toEqual(expected)
return done()
}
@@ -75,7 +80,7 @@ describe("agnosticSource", () => {
})
})
test("ignore a file", (done) => {
testIfNotWindows("ignore a file", (done) => {
const expected = [resolve(cwd, "one")]
const {stream} = agnosticSource({ignore: ["two"], include: ["**/*"], cwd, watch: false})
const log: any[] = []

View File

@@ -0,0 +1,118 @@
import path from "path"
import File from "vinyl"
import {RouteCacheEntry, RouteCacheInterface, RouteType, RouteVerb} from "../types"
export class RouteCache implements RouteCacheInterface {
static singleton: RouteCache | null = null
routeCache: Record<string, RouteCacheEntry> = {}
lengthOfHTTPErrorURI = 4
normalizePath(input: string) {
if (path.sep === path.posix.sep) return input
return input.split(path.sep).join(path.posix.sep)
}
getUrifromPath(path: string) {
const findStr = "/pages"
const findStrIdx = path.indexOf(findStr)
const uri = path.substring(findStrIdx + findStr.length, path.lastIndexOf("."))
const uriWithoutIndex = uri.replace("/index", "")
return uriWithoutIndex.length > 0 ? uriWithoutIndex : "/"
}
getVerb(type: RouteType): RouteVerb {
switch (type) {
case "api":
return "*"
case "rpc":
return "post"
default:
return "get"
}
}
isErrorCode(uri: string) {
if (uri.length === this.lengthOfHTTPErrorURI) {
// need better way to check HTTP error code
const regex = /^[1-5][0-9][0-9]$/
return regex.test(uri.substring(1))
}
return false
}
add(file: File, type: RouteType) {
if (this.routeCache[file.orginalRelative]) return
const uri = this.getUrifromPath(this.normalizePath(file.path))
const isErrorCode = this.isErrorCode(uri)
if (!isErrorCode) {
this.routeCache[file.originalRelative] = {
path: file.originalRelative,
uri,
verb: this.getVerb(type),
type,
}
}
}
delete(file: File) {
delete this.routeCache[file.originalRelative]
}
filterByPath(filterFn: (givenPath: string) => boolean) {
const found = []
for (let path in this.routeCache) {
if (filterFn(path)) {
found.push(this.routeCache[path])
}
}
return found
}
filter(filterFn: (entry: RouteCacheEntry) => boolean) {
let found = []
for (let path in this.routeCache) {
if (filterFn(this.routeCache[path])) {
found.push(this.routeCache[path])
}
}
return found
}
get(): Record<string, RouteCacheEntry>
get(key: string): RouteCacheEntry
get(key?: string) {
if (key) return this.routeCache[key]
return this.routeCache
}
set(key: string, value: RouteCacheEntry) {
this.routeCache[key] = {
...value,
path: value.path ?? "-",
}
}
toString() {
return JSON.stringify(this.routeCache, null, 2)
}
toArray() {
return Object.values(this.routeCache)
}
static create() {
if (RouteCache.singleton) return RouteCache.singleton
RouteCache.singleton = new RouteCache()
return RouteCache.singleton
}
}
/**
* Provides a route cache of the files running through the stream
*/
export function createRouteCache() {
const cache = RouteCache.create()
return {cache}
}

View File

@@ -11,7 +11,7 @@ const defaultSaveCache = debounce((filePath: string, data: object) => {
return writeFile(filePath, Buffer.from(JSON.stringify(data, null, 2)))
.then(() => {})
.catch(() => {})
}, 500)
}, 500) as (filePath: string, data: object) => Promise<void>
const defaultReadCache = (filePath: string) => {
// We need to do sync file reading here as this cache

View File

@@ -1,5 +1,6 @@
export {transformFiles} from "./transform-files"
export {Stage, PipelineItem} from "./types"
export {Stage, PipelineItem, RouteCacheEntry} from "./types"
export * from "./events"
export {transform} from "./transform"
export {FileCache} from "./helpers/file-cache"
export {RouteCache} from "./helpers/route-cache"

View File

@@ -6,6 +6,7 @@ import {agnosticSource} from "./helpers/agnostic-source"
import {createEnrichFiles} from "./helpers/enrich-files"
import {createFileCache, FileCache} from "./helpers/file-cache"
import {createIdleHandler} from "./helpers/idle-handler"
import {createRouteCache, RouteCache} from "./helpers/route-cache"
import {createWorkOptimizer} from "./helpers/work-optimizer"
import {createWrite} from "./helpers/writer"
import {pipeline, through} from "./streams"
@@ -14,13 +15,19 @@ export function isSourceFile(file: File) {
return file.hash?.indexOf(":") === -1
}
export function isPageFile(file: File) {
return file.path
}
function createStageArgs(
config: StageConfig,
input: Writable,
bus: Writable,
cache: FileCache,
fileCache: FileCache,
routeCache: RouteCache,
): StageArgs {
const getInputCache = () => cache
const getInputCache = () => fileCache
const getRouteCache = () => routeCache
function processNewFile(file: File) {
if (!file.stat) {
@@ -54,6 +61,7 @@ function createStageArgs(
input,
bus,
getInputCache,
getRouteCache,
processNewFile,
processNewChildFile,
}
@@ -79,10 +87,11 @@ export function createPipeline(
const optimizer = createWorkOptimizer(config.src, config.dest)
const enrichFiles = createEnrichFiles()
const srcCache = createFileCache(isSourceFile)
const routeCache = createRouteCache()
const idleHandler = createIdleHandler(bus)
// Send this object to every stage
const api = createStageArgs(config, input, bus, srcCache.cache)
const api = createStageArgs(config, input, bus, srcCache.cache, routeCache.cache)
// Initialize each stage
const initializedStages = stages.map((stage) => stage(api))

View File

@@ -8,7 +8,7 @@ export function testStreamItems(
expected: any[],
logger: (a: any) => any = defaultLogger,
) {
return new Promise((done) => {
return new Promise<void>((done) => {
const log: string[] = []
const st = pipeline(

View File

@@ -3,6 +3,15 @@ import File from "vinyl"
export type FileCacheEntry = {path: string}
export type RouteType = "page" | "rpc" | "api"
export type RouteVerb = "get" | "post" | "patch" | "head" | "delete" | "*"
export type RouteCacheEntry = {
path: string
uri: string
verb: string
type: RouteType
}
abstract class AbstractFileCache {
static create: () => AbstractFileCache
}
@@ -16,6 +25,22 @@ export interface FileCacheInterface extends AbstractFileCache {
toPaths: () => string[]
}
export interface RouteCacheInterface extends AbstractFileCache {
delete(file: File): void
add(file: File, type: RouteType): void
get(): Record<string, RouteCacheEntry>
get(key: string): RouteCacheEntry
set(key: string, value: RouteCacheEntry): void
filterByPath: (filterFn: (a: string) => boolean) => RouteCacheEntry[]
filter: (filterFn: (a: RouteCacheEntry) => boolean) => RouteCacheEntry[]
toString: () => string
toArray: () => RouteCacheEntry[]
}
export type EventedFile = {
event: "add" | "change" | "unlink" | "unlinkDir"
hash: string
@@ -45,6 +70,7 @@ export type StageArgs = {
input: Writable
bus: Writable
getInputCache: () => FileCacheInterface
getRouteCache: () => RouteCacheInterface
processNewFile: (file: File) => void
processNewChildFile: (a: {
parent: EventedFile

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/generator",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"description": "File generation for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",
@@ -34,25 +34,24 @@
"url": "git+https://github.com/blitz-js/blitz.git"
},
"dependencies": {
"@babel/core": "7.9.0",
"@babel/plugin-transform-typescript": "7.9.4",
"@blitzjs/display": "0.27.0-canary.1",
"@types/jscodeshift": "0.7.1",
"chalk": "4.0.0",
"@babel/core": "7.12.10",
"@babel/plugin-transform-typescript": "7.12.1",
"@blitzjs/display": "0.28.0-canary.1",
"@types/jscodeshift": "0.7.2",
"chalk": "4.1.0",
"cross-spawn": "7.0.3",
"diff": "4.0.2",
"enquirer": "2.3.5",
"fs-extra": "9.0.0",
"diff": "5.0.0",
"enquirer": "2.3.6",
"fs-extra": "9.0.1",
"fs-readdir-recursive": "1.1.0",
"got": "11.1.3",
"jscodeshift": "0.10.0",
"mem-fs": "1.1.3",
"mem-fs-editor": "6.0.0",
"node-fetch": "2.6.1",
"got": "11.8.1",
"jscodeshift": "0.11.0",
"mem-fs": "1.2.0",
"mem-fs-editor": "8.0.0",
"pluralize": "8.0.0",
"recast": "0.19.1",
"recast": "0.20.4",
"username": "5.1.0",
"vinyl": "2.2.0"
"vinyl": "2.2.1"
},
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922"
}

View File

@@ -146,7 +146,7 @@ export abstract class Generator<
if (!this.options.destinationRoot) this.options.destinationRoot = process.cwd()
}
abstract async getTemplateValues(): Promise<any>
abstract getTemplateValues(): Promise<any>
abstract getTargetDirectory(): string
@@ -292,7 +292,7 @@ export abstract class Generator<
}
})
} else {
await new Promise((resolve, reject) => {
await new Promise<void>((resolve, reject) => {
const conflictChecker = new ConflictChecker({
dryRun: this.options.dryRun,
})

View File

@@ -8,6 +8,10 @@ import {Generator, GeneratorOptions} from "../generator"
import {fetchLatestVersionsFor} from "../utils/fetch-latest-version-for"
import {getBlitzDependencyVersion} from "../utils/get-blitz-dependency-version"
function assert(condition: any, message: string): asserts condition {
if (!condition) throw new Error(message)
}
export interface AppGeneratorOptions extends GeneratorOptions {
appName: string
useTs: boolean
@@ -46,7 +50,10 @@ export class AppGenerator extends Generator<AppGeneratorOptions> {
// eslint-disable-next-line require-await
async preCommit() {
this.fs.move(this.destinationPath("gitignore"), this.destinationPath(".gitignore"))
const pkg = this.fs.readJSON(this.destinationPath("package.json"))
const pkg = this.fs.readJSON(this.destinationPath("package.json")) as
| Record<string, any>
| undefined
assert(pkg, "couldn't find package.json")
const ext = this.options.useTs ? "tsx" : "js"
let type: string
@@ -120,7 +127,7 @@ export class AppGenerator extends Generator<AppGeneratorOptions> {
if (!fallbackUsed && !this.options.skipInstall) {
spinner.succeed()
await new Promise((resolve) => {
await new Promise<void>((resolve) => {
const logFlag = this.options.yarn ? "--json" : "--loglevel=error"
const cp = spawn(this.options.yarn ? "yarn" : "npm", ["install", logFlag], {
stdio: ["inherit", "pipe", "pipe"],

View File

@@ -1,5 +1,6 @@
import {join} from "path"
import {Generator, GeneratorOptions} from "../generator"
import {camelCaseToKebabCase} from "../utils/kebab-case"
export interface FormGeneratorOptions extends GeneratorOptions {
ModelName: string
@@ -45,7 +46,7 @@ export class FormGenerator extends Generator<FormGeneratorOptions> {
}
getTargetDirectory() {
const context = this.options.context ? `${this.options.context}/` : ""
const context = this.options.context ? `${camelCaseToKebabCase(this.options.context)}/` : ""
return `app/${context}${this.options.modelNames}/components`
}
}

View File

@@ -1,5 +1,6 @@
import {join} from "path"
import {Generator, GeneratorOptions} from "../generator"
import {camelCaseToKebabCase} from "../utils/kebab-case"
export interface MutationGeneratorOptions extends GeneratorOptions {
ModelName: string
@@ -45,7 +46,7 @@ export class MutationGenerator extends Generator<MutationGeneratorOptions> {
}
getTargetDirectory() {
const context = this.options.context ? `${this.options.context}/` : ""
const context = this.options.context ? `${camelCaseToKebabCase(this.options.context)}/` : ""
return `app/${context}${this.options.modelNames}/mutations`
}
}

View File

@@ -1,5 +1,6 @@
import {join} from "path"
import {Generator, GeneratorOptions} from "../generator"
import {camelCaseToKebabCase} from "../utils/kebab-case"
export interface QueriesGeneratorOptions extends GeneratorOptions {
ModelName: string
@@ -45,7 +46,7 @@ export class QueriesGenerator extends Generator<QueriesGeneratorOptions> {
}
getTargetDirectory() {
const context = this.options.context ? `${this.options.context}/` : ""
const context = this.options.context ? `${camelCaseToKebabCase(this.options.context)}/` : ""
return `app/${context}${this.options.modelNames}/queries`
}
}

View File

@@ -1,5 +1,6 @@
import {join} from "path"
import {Generator, GeneratorOptions} from "../generator"
import {camelCaseToKebabCase} from "../utils/kebab-case"
export interface QueryGeneratorOptions extends GeneratorOptions {
rawInput: string
@@ -17,7 +18,7 @@ export class QueryGenerator extends Generator<QueryGeneratorOptions> {
}
getTargetDirectory() {
const context = this.options.context ? `${this.options.context}` : ""
const context = this.options.context ? `${camelCaseToKebabCase(this.options.context)}` : ""
return `app/${context}/queries`
}
}

View File

@@ -96,7 +96,7 @@ export class Field {
break
}
}
if (!/^[A-Za-z]*$/.test(fieldName)) {
if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(fieldName)) {
// modelName should be just alpha characters at this point, validate
throw new Error(
`[Field.parse]: received unknown special character in field name: ${fieldName}`,

View File

@@ -16,7 +16,9 @@ export const LabeledTextField = React.forwardRef<HTMLInputElement, LabeledTextFi
const {
input,
meta: {touched, error, submitError, submitting},
} = useField(name)
} = useField(name, {
parse: props.type === "number" ? Number : undefined
})
const normalizedError = Array.isArray(error) ? error.join(", ") : error || submitError

View File

@@ -1,9 +1,9 @@
const { sessionMiddleware, unstable_simpleRolesIsAuthorized } = require("@blitzjs/server")
const { sessionMiddleware, simpleRolesIsAuthorized } = require("@blitzjs/server")
module.exports = {
middleware: [
sessionMiddleware({
unstable_isAuthorized: unstable_simpleRolesIsAuthorized,
isAuthorized: simpleRolesIsAuthorized,
}),
],
/* Uncomment this to customize the webpack config

View File

@@ -31,12 +31,12 @@
]
},
"dependencies": {
"@prisma/cli": "2.x",
"@prisma/client": "2.x",
"@prisma/cli": "~2.12",
"@prisma/client": "~2.12",
"blitz": "canary",
"react": "0.0.0-experimental-4ead6b530",
"react-dom": "0.0.0-experimental-4ead6b530",
"react-error-boundary": "2.x",
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0",
"react-error-boundary": "3.x",
"secure-password": "4.x",
"typescript": "4.x",
"zod": "1.x"
@@ -46,13 +46,13 @@
"@testing-library/react": "11.x",
"@testing-library/react-hooks": "3.x",
"@types/jest": "26.x",
"@types/react": "16.x",
"@types/react": "17.x",
"@types/secure-password": "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",
"eslint-config-react-app": "6.x",
"eslint-plugin-flowtype": "5.x",
"eslint-plugin-import": "2.x",
"eslint-plugin-jsx-a11y": "6.x",
@@ -62,7 +62,7 @@
"jest": "26.x",
"jest-environment-jsdom-fourteen": "1.x",
"jest-watch-typeahead": "0.x",
"react-test-renderer": "16.x",
"react-test-renderer": "17.x",
"lint-staged": "10.x",
"prettier": "2.x",
"pretty-quick": "3.x",

View File

@@ -46,6 +46,22 @@ describe("Field model", () => {
expect(Field.parse("name").toString()).toMatchInlineSnapshot(`"name String"`)
})
it("allow number characters in model name", () => {
expect(Field.parse("name2").toString()).toMatchInlineSnapshot(`"name2 String"`)
})
it("allow underscore characters in model name", () => {
expect(Field.parse("first_name").toString()).toMatchInlineSnapshot(`"first_name String"`)
})
it("disallows number as a first character in model name", () => {
expect(() => Field.parse("2first").toString()).toThrow()
})
it("disallows underscore as a first character in model name", () => {
expect(() => Field.parse("_first").toString()).toThrow()
})
it("disallows special characters in model name", () => {
expect(() => Field.parse("app-user:int")).toThrow()
})

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/installer",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"description": "Package installation for the Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz#readme",
"license": "MIT",
@@ -34,25 +34,23 @@
"url": "git+https://github.com/blitz-js/blitz.git"
},
"dependencies": {
"@babel/core": "7.9.0",
"@babel/plugin-transform-typescript": "7.9.4",
"@blitzjs/config": "0.27.0-canary.1",
"@blitzjs/display": "0.27.0-canary.1",
"@blitzjs/generator": "0.27.0-canary.1",
"@types/jscodeshift": "0.7.1",
"chokidar": "3.4.2",
"@babel/core": "7.12.10",
"@babel/plugin-transform-typescript": "7.12.1",
"@blitzjs/config": "0.28.0-canary.1",
"@blitzjs/display": "0.28.0-canary.1",
"@blitzjs/generator": "0.28.0-canary.1",
"@types/jscodeshift": "0.7.2",
"cross-spawn": "7.0.3",
"diff": "4.0.2",
"enquirer": "2.3.5",
"fs-extra": "9.0.0",
"globby": "11.0.0",
"ink": "3.0.7",
"ink-link": "2.0.0",
"diff": "5.0.0",
"enquirer": "2.3.6",
"fs-extra": "9.0.1",
"globby": "11.0.1",
"ink": "3.0.8",
"ink-spinner": "4.0.1",
"jscodeshift": "0.10.0",
"react": "0.0.0-experimental-4ead6b530",
"recast": "0.19.1",
"ts-node": "8.9.1"
"jscodeshift": "0.11.0",
"react": "0.0.0-experimental-3310209d0",
"recast": "0.20.4",
"ts-node": "9.1.1"
},
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922"
}

View File

@@ -29,13 +29,12 @@ export class RecipeExecutor<Options extends RecipeMeta> {
<RecipeRenderer cliArgs={cliArgs} steps={this.steps} recipeMeta={this.options} />,
)
await waitUntilExit()
log.info(
`\n🎉 The recipe for ${this.options.name} completed successfully! Its functionality is now fully configured in your Blitz app.\n`,
)
} catch (e) {
log.error(e)
return
}
log.info(
`\n🎉 The recipe for ${this.options.name} completed successfully! Its functionality is now fully configured in your Blitz app.\n`,
)
}
}

View File

@@ -3,6 +3,8 @@ import * as fs from "fs-extra"
jest.mock("fs-extra")
const testIfNotWindows = process.platform === "win32" ? test.skip : test
describe("path utils", () => {
it("returns proper file paths in a TS project", () => {
fs.existsSync.mockReturnValue(true)
@@ -15,7 +17,7 @@ describe("path utils", () => {
})
// SKIP test because the fs mock is failing on windows
it.skip("returns proper file paths in a JS project", () => {
testIfNotWindows("returns proper file paths in a JS project", () => {
fs.existsSync.mockReturnValue(false)
expect(paths.document()).toBe("app/pages/_document.js")
expect(paths.app()).toBe("app/pages/_app.js")

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/repl",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"description": "Repl package for Blitz CLI",
"homepage": "https://github.com/blitz-js/blitz/packages/repl/#readme",
"license": "MIT",
@@ -31,9 +31,9 @@
"url": "git+https://github.com/blitz-js/blitz.git"
},
"dependencies": {
"chokidar": "3.4.2",
"globby": "11.0.0",
"pkg-dir": "4.2.0",
"chokidar": "3.4.3",
"globby": "11.0.1",
"pkg-dir": "5.0.0",
"progress": "^2.0.3"
},
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922",

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/server",
"description": "Blitz.js server functionality",
"version": "0.27.0-canary.1",
"version": "0.28.0-canary.1",
"license": "MIT",
"bin": {
"next-patched": "./bin/next-patched"
@@ -17,7 +17,6 @@
"wait:config": "wait-on ../config/dist/packages/config/src/index.d.ts",
"predev": "yarn wait:config && yarn wait:file-pipeline && yarn wait:core",
"dev": "tsdx watch --verbose",
"prebuild": "yarn predev",
"build": "tsdx build",
"test": "tsdx test"
},
@@ -35,45 +34,39 @@
]
},
"dependencies": {
"@blitzjs/file-pipeline": "0.27.0-canary.1",
"@blitzjs/file-pipeline": "0.28.0-canary.1",
"b64-lite": "1.4.0",
"cookie": "0.4.1",
"cross-spawn": "7.0.3",
"date-fns": "2.14.0",
"date-fns": "2.16.1",
"detect-port": "1.3.0",
"expand-tilde": "2.0.2",
"fast-glob": "3.2.2",
"fast-glob": "3.2.4",
"flush-write-stream": "2.0.0",
"folder-hash": "3.3.1",
"from2": "2.3.0",
"gulp-if": "3.0.0",
"hasha": "5.2.0",
"jsonwebtoken": "8.5.1",
"lodash": "^4.17.19",
"lodash-es": "^4.17.15",
"merge-stream": "2.0.0",
"nanoid": "3.1.10",
"next": "10.0.2",
"null-loader": "4.0.0",
"ora": "4.0.4",
"lodash": "^4.17.20",
"lodash-es": "^4.17.20",
"nanoid": "3.1.20",
"next": "10.0.4",
"null-loader": "4.0.1",
"ora": "5.2.0",
"parallel-transform": "1.2.0",
"parse-gitignore": "1.0.1",
"pirates": "4.0.1",
"pkg-dir": "4.2.0",
"pretty-ms": "6.0.1",
"pkg-dir": "5.0.0",
"pumpify": "2.0.1",
"readable-stream": "3.6.0",
"resolve-cwd": "3.0.0",
"slash": "3.0.0",
"superjson": "1.3.0",
"through2": "3.0.1",
"vinyl": "2.2.0",
"vinyl-file": "3.0.0",
"vinyl-fs": "3.0.3"
"superjson": "1.4.1",
"through2": "4.0.2",
"vinyl": "2.2.1"
},
"devDependencies": {
"@blitzjs/core": "0.27.0-canary.1",
"next-transpile-modules": "3.2.0"
"@blitzjs/core": "0.28.0-canary.1",
"next-transpile-modules": "6.0.0"
},
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922"
}

View File

@@ -1,34 +0,0 @@
import {hashElement} from "folder-hash"
import {pathExists, readFile, writeFile} from "fs-extra"
import {resolve} from "path"
export async function getInputArtefactsHash() {
const options = {
algo: "md5",
folders: {
exclude: [".*", "node_modules", "cypress", "test", "tests", "spec", "specs"],
},
}
const tree = await hashElement(".", options)
return tree.hash
}
export async function alreadyBuilt(buildFolder: string = ".blitz/caches") {
const hashStore = resolve(buildFolder, "last-build")
if (!(await pathExists(hashStore))) return false
try {
const buffer = await readFile(hashStore)
const hash = await getInputArtefactsHash()
const read = buffer.toString().replace("\n", "")
return read === hash
} catch (err) {
return false
}
}
export async function saveBuild(buildFolder: string = ".blitz/caches") {
const hashStore = resolve(buildFolder, "last-build")
const hash = await getInputArtefactsHash()
await writeFile(hashStore, hash)
}

View File

@@ -1,6 +1,5 @@
import {copy, pathExists, remove} from "fs-extra"
import {resolve} from "path"
import {saveBuild} from "./build-hash"
import {normalize, ServerConfig} from "./config"
import {nextBuild} from "./next-utils"
import {configureStages} from "./stages"
@@ -39,6 +38,4 @@ export async function build(config: ServerConfig) {
if (await pathExists(buildNextFolder)) {
await copy(buildNextFolder, rootNextFolder)
}
await saveBuild(buildFolder)
}

View File

@@ -11,6 +11,7 @@ export type ServerConfig = {
rootFolder: string
buildFolder?: string
devFolder?: string
routeFolder?: string
clean?: boolean
// -
isTypescript?: boolean
@@ -29,6 +30,7 @@ export type ServerConfig = {
type NormalizedConfig = ServerConfig & {
buildFolder: string
devFolder: string
routeFolder: string
clean?: boolean
// -
isTypescript: boolean
@@ -49,6 +51,7 @@ const defaults = {
// -
buildFolder: ".blitz/caches/build",
devFolder: ".blitz/caches/dev",
routeFolder: ".blitz/caches/routes",
// -
writeManifestFile: true,
// -
@@ -68,6 +71,7 @@ const defaults = {
"**/.now/**/*",
"**/*.pnp.js",
"coverage/**/*",
".coverage/**/*",
"dist/**/*",
"**/node_modules/**/*",
"cypress/**/*",
@@ -94,6 +98,7 @@ export async function normalize(config: ServerConfig): Promise<NormalizedConfig>
rootFolder,
buildFolder: resolve(rootFolder, config.buildFolder ?? defaults.buildFolder),
devFolder: resolve(rootFolder, config.devFolder ?? defaults.devFolder),
routeFolder: resolve(rootFolder, config.routeFolder ?? defaults.routeFolder),
// -
isTypescript: config.isTypescript ?? (await getIsTypescript(rootFolder)),
watch: config.watch ?? env === "dev",

View File

@@ -1,3 +0,0 @@
declare module "folder-hash" {
export function hashElement(s: string, options: any): any
}

View File

@@ -2,6 +2,7 @@ export {withBlitz} from "./with-blitz"
export {build} from "./build"
export {dev} from "./dev"
export {prod} from "./prod"
export {routes} from "./routes"
export {normalize, ServerConfig} from "./config"
export {resolveBinAsync} from "./resolve-bin-async"
export {ManifestLoader} from "./manifest-loader"

View File

@@ -59,7 +59,7 @@ export async function nextStartDev(
const transform = createOutputTransformer(manifest, devFolder).stream
const {spawnCommand, spawnEnv, availablePort} = await createCommandAndPort(config, "dev")
return new Promise((res, rej) => {
return new Promise<void>((res, rej) => {
if (config.port && availablePort !== config.port) {
log.error(`Couldn't start server on port ${config.port} because it's already in use`)
rej("")
@@ -79,7 +79,7 @@ export async function nextStartDev(
}
export function nextBuild(nextBin: string, cwd: string) {
return new Promise((res, rej) => {
return new Promise<void>((res, rej) => {
spawn(nextBin, ["build"], {
cwd,
stdio: "inherit",
@@ -94,7 +94,7 @@ export function nextBuild(nextBin: string, cwd: string) {
export async function nextStart(nextBin: string, cwd: string, config: ServerConfig) {
const {spawnCommand, spawnEnv, availablePort} = await createCommandAndPort(config, "start")
return new Promise((res, rej) => {
return new Promise<void>((res, rej) => {
if (config.port && availablePort !== config.port) {
log.error(`Couldn't start server on port ${config.port} because it's already in use`)
rej("")

View File

@@ -19,7 +19,7 @@ function globalGitIgnore() {
stdio: "pipe",
})
if (!(configResult.status === 0)) {
log.warning("Git config core.excludesFile is unset. Inferring .gitignore file locations.")
// Git config core.excludesFile is unset. Inferring .gitignore file locations.
return null
}

View File

@@ -1,12 +1,13 @@
import {build} from "./build"
import {alreadyBuilt} from "./build-hash"
import {log} from "@blitzjs/display"
import * as fs from "fs"
import {normalize, ServerConfig} from "./config"
import {nextStart} from "./next-utils"
export async function prod(config: ServerConfig) {
const {buildFolder, nextBin} = await normalize(config)
if (!(await alreadyBuilt(buildFolder))) {
await build(config)
if (!fs.existsSync(buildFolder)) {
log.error("Build folder not found, make sure to run `blitz build` before starting")
process.exit(1)
}
await nextStart(nextBin, buildFolder, config)
}

View File

@@ -0,0 +1,39 @@
import {getConfig} from "@blitzjs/config"
import type {RouteCache, RouteCacheEntry} from "@blitzjs/file-pipeline"
import {normalize, ServerConfig} from "./config"
import {configureRouteStages} from "./stages"
function defaultSitemapFunction(_: RouteCache): RouteCacheEntry[] {
return []
}
export async function routes(config: ServerConfig) {
const {
rootFolder,
routeFolder,
transformFiles,
ignore,
include,
isTypescript,
writeManifestFile,
} = await normalize({...config, env: "dev"})
const {sitemap = defaultSitemapFunction} = getConfig() as Record<string, unknown> & {
sitemap: typeof defaultSitemapFunction
}
const stages = configureRouteStages({writeManifestFile, isTypescript})
const {routeCache} = (await transformFiles(rootFolder, stages, routeFolder, {
ignore,
include,
watch: false,
clean: true,
})) as {routeCache: RouteCache}
sitemap(routeCache).forEach((sitemap_) => {
routeCache.set(sitemap_.uri, sitemap_)
})
return Object.values(routeCache.get())
}

View File

@@ -4,10 +4,10 @@ import {
EnhancedResolver,
handleRequestWithMiddleware,
Middleware,
prettyMs,
} from "@blitzjs/core"
import {baseLogger, log as displayLog} from "@blitzjs/display"
import chalk from "chalk"
import prettyMs from "pretty-ms"
import {deserialize, serialize} from "superjson"
const rpcMiddleware = <TInput, TResult>(
@@ -40,14 +40,14 @@ const rpcMiddleware = <TInput, TResult>(
try {
const data = deserialize({json: req.body.params, meta: req.body.meta?.params}) as TInput
log.info(chalk.dim("Starting with input:"), data)
const startTime = new Date().getTime()
log.info(chalk.dim("Starting with input:"), data ? data : JSON.stringify(data))
const startTime = Date.now()
const result = await resolver(data, res.blitzCtx)
const duration = prettyMs(new Date().getTime() - startTime)
log.debug(chalk.dim("Result:"), result)
log.info(chalk.dim("Finished", "in", duration))
const duration = Date.now() - startTime
log.debug(chalk.dim("Result:"), result ? result : JSON.stringify(result))
log.info(chalk.dim(`Finished in ${prettyMs(duration)}ms`))
displayLog.newline()
res.blitzResult = result

View File

@@ -3,6 +3,7 @@ import {createStageManifest} from "./manifest"
import {createStagePages} from "./pages"
import {createStageRelative} from "./relative"
import {createStageRewriteImports} from "./rewrite-imports"
import {createStageRoutes} from "./routes"
import {createStageRpc} from "./rpc"
type StagesConfig = {writeManifestFile: boolean; isTypescript: boolean}
@@ -18,3 +19,9 @@ export const configureStages = (config: StagesConfig) => [
createStageConfig,
createStageManifest(config.writeManifestFile),
]
export const configureRouteStages = (config: StagesConfig) => [
createStagePages,
createStageRpc(config.isTypescript),
createStageRoutes,
]

View File

@@ -102,6 +102,8 @@ export const createStagePages: Stage = ({config, bus, getInputCache}) => {
)
}
file.originalPath = file.path
file.originalRelative = file.relative
file.path = apiTransformer(pagesTransformer(file.path))
return file

View File

@@ -1,4 +1,5 @@
import {Stage, transform} from "@blitzjs/file-pipeline"
import fastGlob from "fast-glob"
import path from "path"
const isJavaScriptFile = (filepath: string) => filepath.match(/\.(ts|tsx|js|jsx)$/)
@@ -19,7 +20,7 @@ export const createStageRewriteImports: Stage = ({config: {cwd}}) => {
const contents = filecontents.toString()
const newContents = replaceImports(contents)
const newContents = replaceImports(contents, cwd)
file.contents = Buffer.from(newContents)
return file
@@ -30,32 +31,53 @@ export const createStageRewriteImports: Stage = ({config: {cwd}}) => {
export const patternImport = /(import.*?["'])(.+?)(["'])/gs
export function replaceImports(content: string) {
export function replaceImports(content: string, cwd: string) {
return content.replace(patternImport, (...args) => {
const [, start, resource, end] = args as string[]
const [original, start, resource, end] = args as string[]
return start + rewriteImportOrigin(resource) + end
if (resource.startsWith("@")) {
return original
}
return start + rewriteImportOrigin(resource, cwd) + end
})
}
export function rewriteImportOrigin(origin: string): string {
/**
* Check wether `someDir/api` links to `someDir/api.js` or `someDir/api/index.js`.
*/
function getImportType(absoluteOrigin: string, cwd: string) {
const foundFiles = fastGlob.sync(
// if absoluteOrigin is a file import,
// we'll find a matching file.
//
[absoluteOrigin + ".[jt]s", absoluteOrigin + ".[jt]sx"],
{
cwd,
},
)
return foundFiles.length > 0 ? "file" : "directory"
}
export function rewriteImportOrigin(origin: string, cwd: string): string {
const parts = origin.split("/")
if (parts.indexOf("pages") === parts.length - 1 || parts.indexOf("api") === parts.length - 1) {
if (getImportType(origin, cwd) === "file") {
return origin
}
}
// If it's an import from a page, say from app/pages/mypage,
// we'll rewrite that import to pages/mypage.
if (parts.includes("pages")) {
if (parts[0] === "app") {
parts.splice(0, 1)
}
parts.splice(0, parts.indexOf("pages"))
}
// If it's an import from an API Route, say from app/users/api/myRoute,
// we'll rewrite it to pages/api/myRoute.
if (parts.includes("api")) {
if (parts.indexOf("api") === parts.length - 1) {
parts.push("index")
}
parts.splice(0, parts.indexOf("api"), "pages")
}

View File

@@ -87,6 +87,7 @@ describe("rewrite-imports", () => {
{
path: normalize("/projects/blitz/blitz/app/pages/index.tsx"),
contents: `
import styles from "app/pages/index.module.css"
export function someFunction() { return "foo"; }
export default function Index() { return <p>Hello World</p> }
`,
@@ -105,6 +106,7 @@ describe("rewrite-imports", () => {
{
path: normalize("/projects/blitz/blitz/app/pages/index.tsx"),
contents: `
import styles from "pages/index.module.css"
export function someFunction() { return "foo"; }
export default function Index() { return <p>Hello World</p> }
`,
@@ -123,6 +125,30 @@ describe("rewrite-imports", () => {
)
})
describe("an import from app/admin/pages/admin/index", () => {
it(
"is rewritten to pages/admin/index",
makeTest({
input: [
{
path: normalize("/projects/blitz/blitz/app/admin/pages/admin/index.tsx"),
contents: `
import styles from "app/admin/pages/admin/index.module.scss"
`,
},
],
expectedOutput: [
{
path: normalize("/projects/blitz/blitz/app/admin/pages/admin/index.tsx"),
contents: `
import styles from "pages/admin/index.module.scss"
`,
},
],
}),
)
})
describe("an import from app/users/api/getUser", () => {
it(
"is rewritten to pages/api/getUser",

Some files were not shown because too many files have changed in this diff Show More