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

Compare commits

...

51 Commits

Author SHA1 Message Date
github-actions[bot]
99b054a44a Version Packages (alpha) (#3645)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-08-01 13:11:24 +02:00
Aleksandra
54db8a46dd Comment out version check until it's fixed & fix missing value in pkg manager options (#3647) 2022-08-01 13:01:56 +02:00
Blitz.js Bot
6125eb7837 (meta) added @tommywong-dev as contributor 2022-08-01 05:08:00 -04:00
Dillon Raphael
62bf12b5c6 Update how cli checks if isInternalBlitzMonorepoDevelopment for codegen (#3644)
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-08-01 11:03:19 +02:00
github-actions[bot]
8e4580a446 Version Packages (alpha) (#3642)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-07-30 21:03:36 +02:00
Fran Zekan
f52ca398ee Upgrade React-Query to V4 (#3557) 2022-07-30 20:59:38 +02:00
github-actions[bot]
922bc276d9 Version Packages (alpha) (#3638)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-07-29 19:58:38 +02:00
Dillon Raphael
365e67094c Fixes db seed command (#3639)
* require db.default in db runSeed cli command
2022-07-29 19:51:23 +02:00
Dillon Raphael
31d7a6f413 Adds rootDir prefix to tsconfig alias module name mapper (#3634)
Co-authored-by: beerose <alexsandra.sikora@gmail.com>
2022-07-29 11:36:43 +02:00
github-actions[bot]
8726b16bb9 Version Packages (alpha) (#3632) 2022-07-28 20:06:17 +02:00
Dillon Raphael
240f378b54 passes the correct arguments to runCommandFromBin in blitz cli index (#3631) 2022-07-28 19:57:08 +02:00
github-actions[bot]
d6655f0178 Version Packages (alpha) (#3630)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dillon Raphael <dillon@creatorsneverdie.com>
2022-07-28 16:23:15 +02:00
Blitz.js Bot
001c174cbf (meta) updated @dillonraphael contributions 2022-07-28 10:18:55 -04:00
Dillon Raphael
1d863f352a Fix APP_ENV not being set before running loadEnvConfig (#3629)
* rearanges the order of setting --env before loading envConfig
2022-07-28 16:16:19 +02:00
Blitz.js Bot
a36110171a (meta) added @sherryxiao1988 as contributor 2022-07-27 13:29:50 -04:00
github-actions[bot]
37b5e35e22 Version Packages (alpha) (#3622)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-07-27 18:51:31 +02:00
beerose
3b213a35b0 Add missing changesets 2022-07-27 18:46:06 +02:00
Marcus Reinhardt
809f6019be Remove debug print (#3616)
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-27 18:44:51 +02:00
Aleksandra
a51b1e85e1 Export router-context from blitz-next (#3621) 2022-07-27 18:23:28 +02:00
Blitz.js Bot
a948dbb7b8 (meta) added @ryanwashburne as contributor 2022-07-27 11:08:20 -04:00
github-actions[bot]
4b91c429ca Version Packages (alpha) (#3588)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-07-26 17:09:46 +02:00
Aleksandra
6ab9db7802 Infer result type in the api handler (#3610) 2022-07-26 17:04:39 +02:00
Blitz.js Bot
d3e6b02ad4 (meta) updated @iojcde contributions 2022-07-26 05:21:37 -04:00
Jeeho Ahn
813365da61 (meta) add @iojcde as contributor (#3606) 2022-07-26 11:21:32 +02:00
Blitz.js Bot
6559c25f71 (meta) added @saadaltabari as contributor 2022-07-25 09:08:44 -04:00
saadaltabari
83b355900b Truncate error messages in passportAuth redirectUri (#3596)
Co-authored-by: Fran Zekan <zekan.fran369@gmail.com>
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-25 15:08:40 +02:00
Fran Zekan
c721c104db Hook up react-query fetch cancellation (#3590)
Co-authored-by: beerose <alexsandra.sikora@gmail.com>
2022-07-25 14:57:42 +02:00
Fran Zekan
7e538ba451 Import ErrorComponent as DefaultErrorComponent (#3589)
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-25 11:33:38 +02:00
Dillon Raphael
8e00605a86 Codemod: update the error messages based on if it's a babel parse error or an unexpected error (#3593) 2022-07-25 11:15:28 +02:00
Dillon Raphael
dcdcd04055 Various codemod fixes (#3576)
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-22 20:55:33 +02:00
Fran Zekan
e339e2fd0a Hoist up react-query (#3585)
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-22 20:35:37 +02:00
Brandon Bayer
37e1ec4abc Update README.md messaging (#3577)
* Update README.md

* Update pnpm lock

Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-22 20:23:02 +02:00
github-actions[bot]
718a194891 Version Packages (alpha) (#3583)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-07-22 20:06:49 +02:00
Fran Zekan
0f18c68d63 Fix prefetching, again... (#3578)
Co-authored-by: beerose <alexsandra.sikora@gmail.com>
2022-07-22 18:08:12 +02:00
Aleksandra
3511d5b69b [temporary fix] skip version check until internal issues are resolved (#3584) 2022-07-22 17:05:40 +02:00
Aleksandra
716e188d13 Fix queries/mutations lookup on Windows (#3581) 2022-07-22 16:16:01 +02:00
github-actions[bot]
57a53fa3c2 Version Packages (alpha) (#3561)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-07-20 14:34:36 +02:00
Fran Zekan
abb1ad5d1c Don't throw error on a missing app/api folder when running codemod (#3568)
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-20 08:26:14 +02:00
Brandon Bayer
7096083038 Update CODEOWNERS 2022-07-19 18:29:15 +02:00
Ante Primorac
0ac6e17122 fix blitz not loading custom server (#3564)
* fix blitz not loading custom server
2022-07-19 00:42:14 +02:00
Brandon Bayer
8bcb471a53 Fix auth issue where session token and publicData cookie were updated unnecessarily, leading to potential user logout (#3556)
* fix auth issue where session token and public data token was updated unnecessarily
2022-07-19 00:19:55 +02:00
Brandon Bayer
abe2afccdf Fix a long-standing issue with occasional blitz auth flakiness (#3554)
* fix cookie set bug
2022-07-19 00:06:38 +02:00
Fran Zekan
d9fc5d8e26 Fix queryClient not working the same in SSP and SP (#3563)
Co-authored-by: beerose <alexsandra.sikora@gmail.com>
2022-07-18 17:14:53 +02:00
Aleksandra
3f20a47405 Fix delete session type (#3560) 2022-07-18 12:58:03 +02:00
github-actions[bot]
72addbbeed Version Packages (alpha) (#3540)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-07-18 11:29:22 +02:00
Fran Zekan
1c809094fd Fix Page.authenticate not working for layout components (#3547)
Co-authored-by: Aleksandra <alexsandra.sikora@gmail.com>
2022-07-18 10:39:07 +02:00
Fran Zekan
54a66a95dc Show all blitz packages when running blitz version command (#3553)
Co-authored-by: beerose <alexsandra.sikora@gmail.com>
2022-07-18 10:03:44 +02:00
Fran Zekan
8d9ea00e1d Fix prefetching multiple queries causes only the last one to be passed to page (#3551) 2022-07-17 19:28:45 +02:00
Fran Zekan
ab4d9de70f Don't try to copy RPC API endpoint in templates that don't have it (#3545)
* Don't try to copy RPC API endpoint in templates that don't have it
2022-07-17 18:08:08 +02:00
Fran Zekan
8f166a5db0 Check for new versions when running CLI (#3465)
* Simple function to call new on every cli invocation to update blitz

* Fix printing of how to

* Catch network errors

* Cleanup

* Loop through all locally installed and packages and check if an update is needed

* cache checkForLatestVersion so it runs only on every 24 hours

* make update message pretty

* uncomment shouldUpdate boolean

* run checkLatestVersion on dev command and new

* Dont run in our monorepo + small changes

* Create curly-seas-serve.md

Co-authored-by: Dillon Raphael <dillon@creatorsneverdie.com>
2022-07-17 01:01:52 +02:00
Datner
df7cee84ad fix(blitz-rpc): fix 6th pipe resolver not returning resolved value (#3537)
Co-authored-by: beerose <alexsandra.sikora@gmail.com>
2022-07-15 12:18:00 +02:00
107 changed files with 2189 additions and 856 deletions

View File

@@ -970,7 +970,8 @@
"avatar_url": "https://avatars0.githubusercontent.com/u/3496193?v=4",
"profile": "https://twitter.com/dillonraphael",
"contributions": [
"code"
"code",
"doc"
]
},
{
@@ -3590,6 +3591,54 @@
"contributions": [
"doc"
]
},
{
"login": "saadaltabari",
"name": "saadaltabari",
"avatar_url": "https://avatars.githubusercontent.com/u/29986512?v=4",
"profile": "https://github.com/saadaltabari",
"contributions": [
"doc",
"code"
]
},
{
"login": "iojcde",
"name": "Jeeho Ahn",
"avatar_url": "https://avatars.githubusercontent.com/u/31413538?v=4",
"profile": "https://github.com/iojcde",
"contributions": [
"doc",
"tool",
"code"
]
},
{
"login": "ryanwashburne",
"name": "Ryan Washburne",
"avatar_url": "https://avatars.githubusercontent.com/u/12566087?v=4",
"profile": "https://linkedin.com/in/ryanwashburne",
"contributions": [
"doc"
]
},
{
"login": "sherryxiao1988",
"name": "Shundan Xiao",
"avatar_url": "https://avatars.githubusercontent.com/u/1202426?v=4",
"profile": "https://github.com/sherryxiao1988",
"contributions": [
"doc"
]
},
{
"login": "tommywong-dev",
"name": "tommywong-dev",
"avatar_url": "https://avatars.githubusercontent.com/u/79971095?v=4",
"profile": "https://github.com/tommywong-dev",
"contributions": [
"doc"
]
}
],
"contributorsPerLine": 7,

View File

@@ -0,0 +1,6 @@
---
"blitz": minor
"@blitzjs/auth": patch
---
Truncate errors from `api/auth/<strategy>/callback` request to 100 characters before passing them to the `?authError=` query parameter

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Fixes the db seed command so that the database can disconnect after running the seed file.

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/codemod": patch
---
These are various changes to will make the codemod more dynamic and work with a larger variety of codebases. These fixes are implemented to make the codemod work with flightdeck.

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/rpc": patch
---
Pass `signal` from useQuery to Blitz internal rpc client to be able to cancel queries on unmount

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Check for new versions when running CLI

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/auth": patch
---
Update `deleteSession` return type — allow undefined values

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/next": patch
---
Export router-context from browser entrypoint

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Fix APP_ENV not being set before loading env config

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/next": patch
---
Allow prefetching multiple queries in gSSP and gSP

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Add missing value to "skip" option when choosing a package manager during new app scaffolding

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Show all blitz packages when running `blitz version` command

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Fix blitz codegen to work with monorepos

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Improve codemod utilities

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/generator": patch
---
Don't try to copy RPC API endpoint in templates that don't have it

View File

@@ -0,0 +1,10 @@
---
"@blitzjs/auth": patch
"blitz": patch
---
Fix a long-standing issue with occasional blitz auth flakiness
This bug would sometimes cause users to be logged out or to experience an CSRFTokenMismatchError. This bug, when encountered, usually by lots of setPublicData or session.create calls, would not set the cookie headers correctly resulting in cookies being set to a previous state or in a possibly undefined state.
There are no security concerns as far as I can tell.

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/generator": patch
---
Add hoist pattern entry for react-query in new app templates

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Temporarily skip version check

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/rpc": patch
---
Fix pipe resolver return type

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
Passes the correct arguments (without flags) to any bin command ran with the blitz cli

View File

@@ -23,10 +23,16 @@
"changesets": [
"big-phones-bow",
"breezy-cameras-double",
"breezy-moose-behave",
"bright-mangos-run",
"calm-carpets-deny",
"calm-nails-wait",
"clean-walls-wink",
"cool-doors-invent",
"cool-horses-check",
"curly-seas-serve",
"dirty-monkeys-greet",
"dirty-planets-chew",
"eleven-humans-sort",
"empty-berries-rule",
"empty-turkeys-wave",
@@ -36,19 +42,29 @@
"flat-bees-approve",
"four-brooms-juggle",
"four-meals-fry",
"four-sheep-judge",
"fuzzy-bees-warn",
"fuzzy-jars-admire",
"gentle-dogs-reply",
"good-apes-drum",
"good-insects-wink",
"gorgeous-buses-scream",
"great-months-train",
"green-papayas-do",
"happy-hotels-visit",
"healthy-rice-shout",
"heavy-apes-judge",
"hot-cups-rhyme",
"hot-drinks-approve",
"hungry-baboons-swim",
"late-steaks-give",
"lemon-games-press",
"lemon-seas-push",
"lovely-colts-share",
"lucky-cows-try",
"mean-gorillas-reply",
"modern-cameras-pull",
"modern-ligers-behave",
"moody-bags-walk",
"moody-squids-cheer",
"nervous-beds-travel",
@@ -58,16 +74,21 @@
"nice-starfishes-live",
"nine-birds-confess",
"nine-onions-admire",
"ninety-lies-press",
"ninety-pets-heal",
"olive-bees-buy",
"olive-feet-rhyme",
"olive-sheep-rhyme",
"perfect-eyes-repeat",
"plenty-bottles-swim",
"polite-lizards-love",
"poor-peas-lick",
"poor-penguins-look",
"poor-shrimps-think",
"popular-teachers-pay",
"pretty-games-march",
"purple-singers-greet",
"quick-cycles-confess",
"quiet-feet-travel",
"quiet-pans-hunt",
"quiet-sloths-rule",
@@ -75,13 +96,20 @@
"rich-queens-travel",
"sharp-falcons-begin",
"shy-olives-hang",
"shy-pumpkins-try",
"silent-colts-reply",
"silly-apricots-share",
"six-apricots-kick",
"slimy-needles-taste",
"slow-walls-poke",
"small-socks-confess",
"smooth-planets-admire",
"smooth-stingrays-drum",
"soft-adults-smell",
"sour-lemons-hunt",
"strong-apes-reply",
"stupid-walls-sell",
"sweet-kiwis-cross",
"swift-drinks-dress",
"tall-meals-learn",
"tame-keys-reply",
@@ -92,6 +120,8 @@
"thick-parrots-float",
"thirty-countries-build",
"tidy-clouds-smoke",
"tough-toes-pull",
"twelve-lemons-smile",
"twenty-beans-pump",
"two-carpets-rhyme",
"two-kiwis-help",
@@ -101,6 +131,7 @@
"violet-lions-help",
"weak-suns-shave",
"wicked-ghosts-cough",
"wicked-rings-walk",
"wise-frogs-give"
]
}

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/codemod": patch
---
Import ErrorComponent as DefaultErrorComponent

View File

@@ -0,0 +1,5 @@
---
"blitz": patch
---
fixes blitz not loading custom server

View File

@@ -0,0 +1,6 @@
---
"@blitzjs/next": patch
"@blitzjs/rpc": patch
---
Upgrade react-query to v4

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/next": patch
---
Avoid reassigning queryClient in prefetch methods

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/next": patch
---
Infer result type in the `api` handler and allow customizing it

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/codemod": patch
---
Updates the error messages based on if it's a babel parse error or an unexpected error

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/auth": patch
---
Fix `Page.authenticate` not working for layout components

View File

@@ -0,0 +1,9 @@
---
"@blitzjs/auth": patch
"blitz": patch
---
Fix auth issue where session token and publicData cookie were updated unnecessarily, leading to potential user logout
- Previously, we were updating the session token each time public data changed. This is not needed, and it would cause race condition bugs where a user could be unexpectedly logged out because a request already in flight would not match the new session token.
- Previously, we were updating the publicData cookie even when it hadn't changed. This may reduce unnecessary re-renders on the client.

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/rpc": patch
---
Fix queries/mutations lookup on Windows

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/rpc": patch
---
Remove debug console.log

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/next": patch
---
Fix prefetching multiple queries causes only the last one to be passed to page

View File

@@ -0,0 +1,5 @@
---
"@blitzjs/next": patch
---
Set prefix in moduleNameWrapper's options in Blitz's jest configuration

2
.github/CODEOWNERS vendored
View File

@@ -1,5 +1,5 @@
# https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
* @flybayer @beerose @dillonraphael
* @beerose @dillonraphael
packages/generator/templates**/* @flybayer

2
.npmrc
View File

@@ -6,4 +6,4 @@ public-hoist-pattern[]=*types*
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=@prettier/plugin-*
public-hoist-pattern[]=*prettier-plugin-*
strict-peer-dependencies=false

View File

@@ -1,6 +1,6 @@
# Contributing
[Read the Contributing Guide at Blitzjs.com](https://blitzjs.com/docs/contributing)
[Read the Contributing Guide at Blitzjs.com](https://alpha.blitzjs.com/docs/contributing)
## To run tests

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-381-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-386-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">
@@ -19,25 +19,12 @@
<br>
<h1 align="center">The Fullstack React Framework</h1>
<h5 align="center">"Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails</h3>
<h3 align="center"><a href="https://blitzjs.com/docs/get-started" target="_blank">Read the Documentation</a></h3>
<br>
“Zero-API” data layer **lets you import server code directly into your React components** instead of having to manually add API endpoints and do client-side fetching and caching.
New Blitz apps come with **all the boring stuff already set up for you!** Like ESLint, Prettier, Jest, user sign up, log in, and password reset.
Provides **helpful defaults and conventions** for things like routing, file structure, and authentication while also being extremely flexible.
<h1 align="center">The Missing Fullstack Toolkit for Next.js</h1>
<br>
### Quick Start
You need Node.js 12 or newer
#### Install Blitz
Run `npm install -g blitz` or `yarn global add blitz`
@@ -53,37 +40,8 @@ _You can alternatively use [`npx`](https://www.npmjs.com/package/npx)_
<br><br>
<a aria-label="Bytes Newsletter" href="https://ui.dev/bytes/?r=blitzjs">
<img alt="Bytes Newsletter" src="https://files-8wtskjofb.vercel.app/smarter-16x1.jpg">
</a>
<br><br>
### The Foundational Principles
1. Fullstack & Monolithic
2. API Not Required
3. Convention over Configuration
4. Loose Opinions
5. Easy to Start, Easy to Scale
6. Stability
7. Community over Code
[The Blitz Manifesto](https://blitzjs.com/docs/manifesto) explains these principles in detail.
<br>
### What is Blitz Designed For?
Blitz is designed for tiny to large database-backed applications that have one or more graphical user interfaces.
While we currently only support web, we are pursuing the dream of a single monolithic application that runs on web and mobile with maximum code sharing and minimal boilerplate.
<br>
## Welcome to the Blitz Community 👋
The Blitz community is warm, safe, diverse, inclusive, and fun! LGBTQ+, women, and minorities are especially welcome. Please read our [Code of Conduct](https://blitzjs.com/docs/code-of-conduct).
@@ -379,7 +337,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
</tr>
<tr>
<td align="center"><a href="https://github.com/jschepmans"><img src="https://avatars2.githubusercontent.com/u/5782977?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johan Schepmans</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jschepmans" title="Code">💻</a></td>
<td align="center"><a href="https://twitter.com/dillonraphael"><img src="https://avatars0.githubusercontent.com/u/3496193?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dillon Raphael</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Code">💻</a></td>
<td align="center"><a href="https://twitter.com/dillonraphael"><img src="https://avatars0.githubusercontent.com/u/3496193?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dillon Raphael</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/clgeoio"><img src="https://avatars2.githubusercontent.com/u/37571416?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cody G</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=clgeoio" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=clgeoio" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/madflow"><img src="https://avatars0.githubusercontent.com/u/183248?v=4?s=100" width="100px;" alt=""/><br /><sub><b>madflow</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=madflow" title="Documentation">📖</a></td>
<td align="center"><a href="https://twitter.com/nitaking_"><img src="https://avatars2.githubusercontent.com/u/10850034?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Satoshi Nitawaki</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nitaking" title="Code">💻</a> <a href="#maintenance-nitaking" title="Maintenance">🚧</a> <a href="#question-nitaking" title="Answering Questions">💬</a> <a href="https://github.com/blitz-js/blitz/commits?author=nitaking" title="Documentation">📖</a></td>
@@ -741,6 +699,13 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
<td align="center"><a href="https://github.com/c-ciobanu"><img src="https://avatars.githubusercontent.com/u/33382714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cristi Ciobanu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=c-ciobanu" title="Documentation">📖</a></td>
<td align="center"><a href="https://arpitdalal.dev"><img src="https://avatars.githubusercontent.com/u/61059807?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arpit Dalal</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arpitdalal" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/robertrisch"><img src="https://avatars.githubusercontent.com/u/73828816?v=4?s=100" width="100px;" alt=""/><br /><sub><b>robertrisch</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robertrisch" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/saadaltabari"><img src="https://avatars.githubusercontent.com/u/29986512?v=4?s=100" width="100px;" alt=""/><br /><sub><b>saadaltabari</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=saadaltabari" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=saadaltabari" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/iojcde"><img src="https://avatars.githubusercontent.com/u/31413538?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeeho Ahn</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=iojcde" title="Documentation">📖</a> <a href="#tool-iojcde" title="Tools">🔧</a> <a href="https://github.com/blitz-js/blitz/commits?author=iojcde" title="Code">💻</a></td>
<td align="center"><a href="https://linkedin.com/in/ryanwashburne"><img src="https://avatars.githubusercontent.com/u/12566087?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ryan Washburne</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ryanwashburne" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/sherryxiao1988"><img src="https://avatars.githubusercontent.com/u/1202426?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shundan Xiao</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sherryxiao1988" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/tommywong-dev"><img src="https://avatars.githubusercontent.com/u/79971095?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tommywong-dev</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tommywong-dev" title="Documentation">📖</a></td>
</tr>
</table>

View File

@@ -1,6 +1,7 @@
save-exact=true
legacy-peer-deps=true
public-hoist-pattern[]=@tanstack/react-query
public-hoist-pattern[]=next
public-hoist-pattern[]=secure-password
public-hoist-pattern[]=*jest*

View File

@@ -1,7 +1,11 @@
import React from "react"
import Head from "next/head"
import React, { FC } from "react"
import { BlitzLayout } from "@blitzjs/next"
const Layout: FC<{ title?: string; children?: React.ReactNode }> = ({ title, children }) => {
const Layout: BlitzLayout<{ title?: string; children?: React.ReactNode }> = ({
title,
children,
}) => {
return (
<>
<Head>

View File

@@ -2,7 +2,7 @@
"name": "toolkit-app",
"version": "1.0.1-alpha.16",
"scripts": {
"start:dev": "pnpm run prisma:start && next dev",
"start:dev": "pnpm run prisma:start && blitz dev",
"buildapp": "NODE_ENV=production pnpm blitz codegen && pnpm prisma generate && next build",
"start": "next start",
"lint": "next lint",
@@ -28,8 +28,8 @@
"@blitzjs/next": "workspace:*",
"@blitzjs/rpc": "workspace:*",
"@hookform/resolvers": "2.8.8",
"@prisma/client": "3.9.0",
"blitz": "workspace:2.0.0-alpha.54",
"@prisma/client": "4.0.0",
"blitz": "workspace:2.0.0-alpha.64",
"next": "12.2.0",
"prisma": "4.0.0",
"react": "18.0.0",

8
apps/web/.npmrc Normal file
View File

@@ -0,0 +1,8 @@
save-exact=true
legacy-peer-deps=true
public-hoist-pattern[]=@tanstack/react-query
public-hoist-pattern[]=next
public-hoist-pattern[]=secure-password
public-hoist-pattern[]=*jest*
public-hoist-pattern[]=@testing-library/*

View File

@@ -20,7 +20,7 @@
"@blitzjs/config": "workspace:*",
"@blitzjs/next": "workspace:*",
"@blitzjs/rpc": "workspace:*",
"@prisma/client": "3.9.0",
"@prisma/client": "4.0.0",
"@types/jest": "27.4.1",
"@types/passport-twitter": "1.0.37",
"blitz": "workspace:*",

View File

@@ -16,7 +16,7 @@
"@blitzjs/auth": "workspace:*",
"@blitzjs/config": "workspace:*",
"@blitzjs/next": "workspace:*",
"@prisma/client": "3.9.0",
"@prisma/client": "4.0.0",
"blitz": "workspace:*",
"lowdb": "3.0.0",
"next": "12.2.0",

View File

@@ -16,7 +16,7 @@
"@blitzjs/auth": "workspace:*",
"@blitzjs/next": "workspace:*",
"@blitzjs/rpc": "workspace:*",
"@prisma/client": "3.9.0",
"@prisma/client": "4.0.0",
"blitz": "workspace:*",
"lowdb": "3.0.0",
"next": "12.2.0",

View File

@@ -12,13 +12,13 @@
"@blitzjs/config": "workspace:*",
"@blitzjs/next": "workspace:*",
"@blitzjs/rpc": "workspace:*",
"@prisma/client": "3.9.0",
"@prisma/client": "4.0.0",
"@tanstack/react-query": "4.0.10",
"blitz": "workspace:*",
"next": "12.2.0",
"prisma": "4.0.0",
"react": "18.0.0",
"react-dom": "18.0.0",
"react-query": "3.39.0"
"react-dom": "18.0.0"
},
"devDependencies": {
"@testing-library/react": "13.0.0",

View File

@@ -2,4 +2,4 @@
exports[`useMutation > useMutation calls the resolver with the argument > shouldn't work with query function 1`] = `"\\"useMutation\\" was expected to be called with a mutation but was called with a \\"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\\")"`;
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 \\"@tanstack/react-query\\")."`;

View File

@@ -1,5 +1,5 @@
// Vitest Snapshot v1
exports[`useQuery > a "query" that converts the string parameter to uppercase > shouldn't work with mutation function 1`] = `"Cannot read properties of null (reading 'isReady')"`;
exports[`useQuery > a "query" that converts the string parameter to uppercase > shouldn't work with mutation function 1`] = `"\\"useQuery\\" was expected to be called with a query but was called with a \\"mutation\\""`;
exports[`useQuery > a "query" that converts the string parameter to uppercase > shouldn't work with regular functions 1`] = `"Cannot read properties of null (reading 'isReady')"`;
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 \\"@tanstack/react-query\\")."`;

View File

@@ -1,166 +1,190 @@
import {describe, it, expect, beforeAll, vi} from "vitest"
import {act, screen, waitForElementToBeRemoved, waitFor} from "@testing-library/react"
import {useQuery, useInfiniteQuery} from "@blitzjs/rpc"
import {useQuery, useInfiniteQuery, BlitzRpcPlugin, QueryClientProvider} from "@blitzjs/rpc"
import React from "react"
import delay from "delay"
import {buildMutationRpc, buildQueryRpc, render} from "../../utils/blitz-test-utils"
import {buildMutationRpc, buildQueryRpc, mockRouter, render} from "../../utils/blitz-test-utils"
import {RouterContext} from "next/dist/shared/lib/router-context"
beforeAll(() => {
globalThis.__BLITZ_SESSION_COOKIE_PREFIX = "qm-test-cookie-prefix"
globalThis.IS_REACT_ACT_ENVIRONMENT = true
})
describe("useQuery", () => {
it("Placeholder", async () => {
console.log("placeholder")
const setupHook = (
ID: string,
params: any,
queryFn: (...args: any) => any,
options: Parameters<typeof useQuery>[2] = {} as any,
): [{data?: any; setQueryData?: any}, Function] => {
let res = {}
const qc = BlitzRpcPlugin({})
function TestHarness() {
const [data, {setQueryData}] = useQuery(queryFn, params, {
suspense: true,
...options,
} as any)
Object.assign(res, {data, setQueryData})
return (
<div id={`harness-${ID}`}>
<span>{data ? `Ready${ID}` : "No data"}</span>
<span>{data}</span>
</div>
)
}
const ui = () => (
<React.Suspense fallback="Loading...">
<TestHarness />
</React.Suspense>
)
const {rerender} = render(ui(), {
wrapper: ({children}) => (
<QueryClientProvider client={globalThis.queryClient}>
<RouterContext.Provider value={mockRouter}>{children}</RouterContext.Provider>
</QueryClientProvider>
),
})
return [res, () => rerender(ui())]
}
describe('a "query" that converts the string parameter to uppercase', () => {
const upcase = async (args: string) => {
await delay(500)
return args.toUpperCase()
}
it("should work with Blitz queries", async () => {
const [res] = setupHook("2", "test", buildQueryRpc(upcase))
await waitForElementToBeRemoved(() => screen.getByText("Loading..."))
await act(async () => {
await screen.findByText("Ready2")
expect(res.data).toBe("TEST")
})
})
it("should be able to change the data with setQueryData", async () => {
const [res] = setupHook("3", "fooBar", buildQueryRpc(upcase))
await waitForElementToBeRemoved(() => screen.getByText("Loading..."))
await act(async () => {
await screen.findByText("Ready3")
expect(res.data).toBe("FOOBAR")
res.setQueryData((p: string) => p.substr(3, 3), {refetch: false})
await delay(100)
})
expect(res.data).toBe("BAR")
})
it("shouldn't work with regular functions", () => {
console.error = vi.fn()
expect(() => setupHook("4", "test", upcase)).toThrowErrorMatchingSnapshot()
})
it("shouldn't work with mutation function", () => {
console.error = vi.fn()
expect(() => setupHook("5", "test", buildMutationRpc(upcase))).toThrowErrorMatchingSnapshot()
})
it("suspense disabled if enabled is false", async () => {
setupHook("6", "test", buildQueryRpc(upcase), {enabled: false})
await screen.findByText("No data")
})
it("suspense disabled if enabled is undefined", async () => {
setupHook("7", "test", buildQueryRpc(upcase), {enabled: undefined})
await screen.findByText("No data")
})
// it("suspense disabled if enabled is false and suspense set", async () => {
// setupHook("8", "test", buildQueryRpc(upcase), {
// enabled: false,
// suspense: true,
// })
// await screen.findByText("No data")
// })
it("works with options other than enabled & suspense without type error", () => {
const Demo = () => {
useQuery(buildQueryRpc(upcase), undefined, {refetchInterval: 10000})
return <div></div>
}
const ui = () => <Demo />
const {rerender} = render(ui(), {
wrapper: ({children}) => (
<QueryClientProvider client={globalThis.queryClient}>
<RouterContext.Provider value={mockRouter}>{children}</RouterContext.Provider>
</QueryClientProvider>
),
})
})
})
})
// beforeAll(() => {
// globalThis.__BLITZ_SESSION_COOKIE_PREFIX = "qm-test-cookie-prefix"
// globalThis.IS_REACT_ACT_ENVIRONMENT = true
// })
// describe("useQuery", () => {
// const setupHook = (
// params: any,
// queryFn: (...args: any) => any,
// options: Parameters<typeof useQuery>[2] = {} as any,
// ): [{data?: any; setQueryData?: any}, Function] => {
// let res = {}
// function TestHarness() {
// const [data, {setQueryData}] = useQuery(queryFn, params, {
// suspense: true,
// ...options,
// } as any)
// Object.assign(res, {data, setQueryData})
// return (
// <div id="harness">
// <span>{data ? "Ready" : "No data"}</span>
// <span>{data}</span>
// </div>
// )
// }
describe("useInfiniteQuery", () => {
const setupHook = (
ID: string,
params: (arg?: any) => any,
queryFn: (...args: any) => any,
): [{data?: any; setQueryData?: any}, Function] => {
let res = {}
const qc = BlitzRpcPlugin({})
// const ui = () => (
// <React.Suspense fallback="Loading...">
// <TestHarness />
// </React.Suspense>
// )
function TestHarness() {
// TODO - fix typing
//@ts-ignore
const [groupedData] = useInfiniteQuery(queryFn, params, {
suspense: true,
getNextPageParam: () => {},
})
Object.assign(res, {groupedData})
return (
<div id="harness">
<span>{groupedData ? `Ready${ID}` : "No data"}</span>
<div>
{groupedData.map((data: any, i) => (
<div key={i}>{data}</div>
))}
</div>
</div>
)
}
// const {rerender} = render(ui())
// return [res, () => rerender(ui())]
// }
const ui = () => (
<React.Suspense fallback={`Loading${ID}...`}>
<TestHarness />
</React.Suspense>
)
// describe('a "query" that converts the string parameter to uppercase', () => {
// const upcase = async (args: string) => {
// await delay(1000)
// return args.toUpperCase()
// }
// it("should work with Blitz queries", async () => {
// const [res] = setupHook("test", buildQueryRpc(upcase))
// await waitForElementToBeRemoved(() => screen.getByText("Loading..."))
// await act(async () => {
// await screen.findByText("Ready")
// expect(res.data).toBe("TEST")
// })
// })
const {rerender} = render(ui(), {
wrapper: ({children}) => (
<QueryClientProvider client={globalThis.queryClient}>
<RouterContext.Provider value={mockRouter}>{children}</RouterContext.Provider>
</QueryClientProvider>
),
})
return [res, () => rerender(ui())]
}
// it("should be able to change the data with setQueryData", async () => {
// const [res] = setupHook("test", buildQueryRpc(upcase))
// await waitForElementToBeRemoved(() => screen.getByText("Loading..."))
// await act(async () => {
// await screen.findByText("Ready")
// expect(res.data).toBe("TEST")
// res.setQueryData((p: string) => p.substr(1, 2), {refetch: false})
// await waitFor(() => screen.getByText("ES"))
// })
// })
// it("shouldn't work with regular functions", () => {
// console.error = vi.fn()
// expect(() => setupHook("test", upcase)).toThrowErrorMatchingSnapshot()
// })
// it("shouldn't work with mutation function", () => {
// console.error = vi.fn()
// expect(() => setupHook("test", buildMutationRpc(upcase))).toThrowErrorMatchingSnapshot()
// })
// it("suspense disabled if enabled is false", async () => {
// setupHook("test", buildQueryRpc(upcase), {enabled: false})
// await screen.findByText("No data")
// })
// it("suspense disabled if enabled is undefined", async () => {
// setupHook("test", buildQueryRpc(upcase), {enabled: undefined})
// await screen.findByText("No data")
// })
// it("suspense disabled if enabled is false and suspense set", async () => {
// setupHook("test", buildQueryRpc(upcase), {
// enabled: false,
// suspense: true,
// })
// await screen.findByText("No data")
// })
// })
// // it("works with options other than enabled & suspense without type error", () => {
// // const queryFn = ((() => true) as unknown) as () => Promise<boolean>
// // useQuery(queryFn, undefined, {refetchInterval: 10000})
// // })
// })
// describe("useInfiniteQuery", () => {
// const setupHook = (
// params: (arg?: any) => any,
// queryFn: (...args: any) => any,
// ): [{data?: any; setQueryData?: any}, Function] => {
// let res = {}
// function TestHarness() {
// // TODO - fix typing
// //@ts-ignore
// const [groupedData] = useInfiniteQuery(queryFn, params, {
// suspense: true,
// getNextPageParam: () => {},
// })
// Object.assign(res, {groupedData})
// return (
// <div id="harness">
// <span>{groupedData ? "Ready" : "No data"}</span>
// <div>
// {groupedData.map((data: any, i) => (
// <div key={i}>{data}</div>
// ))}
// </div>
// </div>
// )
// }
// const ui = () => (
// <React.Suspense fallback="Loading...">
// <TestHarness />
// </React.Suspense>
// )
// const {rerender} = render(ui())
// return [res, () => rerender(ui())]
// }
// const getItems = ({id}: {id: number}) => {
// if (id === 1) {
// return "item1"
// } else if (id === 2) {
// return "item2"
// } else {
// throw new Error("No item for this id")
// }
// }
// it("should work", async () => {
// setupHook(() => ({id: 1}), buildQueryRpc(getItems))
// await waitForElementToBeRemoved(() => screen.getByText("Loading..."))
// await act(async () => {
// await screen.findByText("item1")
// })
// setupHook(() => ({id: 2}), buildQueryRpc(getItems))
// await act(async () => {
// await screen.findByText("item2")
// })
// })
// })
const getItems = ({id}: {id: number}) => {
if (id === 1) {
return "item1"
} else if (id === 2) {
return "item2"
} else {
throw new Error("No item for this id")
}
}
it("should show loading", async () => {
setupHook("1", () => ({id: 1}), buildQueryRpc(getItems))
await waitForElementToBeRemoved(() => screen.getByText("Loading1..."))
await act(async () => {
await screen.findByText("item1")
})
})
})

View File

@@ -19,7 +19,7 @@
"@blitzjs/auth": "workspace:*",
"@blitzjs/next": "workspace:*",
"@blitzjs/rpc": "workspace:*",
"@prisma/client": "3.9.0",
"@prisma/client": "4.0.0",
"blitz": "workspace:*",
"lowdb": "3.0.0",
"next": "12.2.0",

View File

@@ -1,11 +1,12 @@
import {render as defaultRender} from "@testing-library/react"
import {NextRouter} from "next/router"
import {vi} from "vitest"
import {QueryClient, QueryClientProvider} from "react-query"
import React from "react"
import {BlitzRpcPlugin} from "@blitzjs/rpc"
import {vi} from "vitest"
import {QueryClient} from "@tanstack/react-query"
import {BlitzRpcPlugin, QueryClientProvider} from "@blitzjs/rpc"
import {NextRouter} from "next/router"
import {RouterContext} from "next/dist/shared/lib/router-context"
import {render as defaultRender} from "@testing-library/react"
const mockRouter: NextRouter = {
export const mockRouter: NextRouter = {
basePath: "",
pathname: "/",
route: "/",
@@ -56,8 +57,6 @@ const BlitzProvider = ({
return children
}
export const RouterContext = React.createContext(null as any)
RouterContext.displayName = "RouterContext"
const compose =
(...rest) =>
(x: React.ComponentType<any>) =>

View File

@@ -1,34 +1,24 @@
interface ChainMethods {
elementByCss: (selector: string) => Chain<Element>
elementById: () => Chain<Element>
getValue: () => Chain<any>
text: () => Chain<string>
type: () => Chain<any>
moveTo: () => Chain<any>
getComputedCss: () => Chain<any>
getAttribute: () => Chain<any>
hasElementByCssSelector: () => Chain<any>
click: () => Chain<any>
elementsByCss: () => Chain<Element[]>
waitForElementByCss: (arg: string) => Chain<any>
eval: (evalStr: string) => Chain<any>
log: () => Chain<any>
url: () => Chain<any>
back: () => Chain<any>
forward: () => Chain<any>
refresh: () => Chain<any>
setDimensions: (opts: {height: number; width: number}) => Chain<any>
close: () => Chain<any>
quit: () => Chain<any>
}
interface Chain<T> extends Promise<T & ChainMethods>, ChainMethods {}
type Browser = {__brand: "Browser"}
export default function (
appPort: number,
path: string,
waitHydration?: boolean,
allowHydrationRetry?: boolean,
): Promise<Chain<Browser>>
import {BrowserInterface} from "./browsers/base"
export declare const USE_SELENIUM: boolean
/**
*
* @param appPortOrUrl can either be the port or the full URL
* @param url the path/query to append when using appPort
* @param options.waitHydration whether to wait for react hydration to finish
* @param options.retryWaitHydration allow retrying hydration wait if reload occurs
* @param options.disableCache disable cache for page load
* @param options.beforePageLoad the callback receiving page instance before loading page
* @returns thenable browser instance
*/
export default function webdriver(
appPortOrUrl: string | number,
url: string,
options?: {
waitHydration?: boolean
retryWaitHydration?: boolean
disableCache?: boolean
beforePageLoad?: (page: any) => void
locale?: string
},
): Promise<BrowserInterface>
//# sourceMappingURL=next-webdriver.d.ts.map

View File

@@ -5,6 +5,7 @@
"devDependencies": {
"@blitzjs/config": "workspace: *",
"@blitzjs/rpc": "workspace: *",
"@tanstack/react-query": "4.0.10",
"@testing-library/react": "13.0.0",
"@types/express": "4.17.13",
"@types/fs-extra": "9.0.13",
@@ -23,7 +24,6 @@
"playwright-chromium": "1.14.1",
"react": "18.0.0",
"react-dom": "18.0.0",
"react-query": "3.39.0",
"resolve-cwd": "3.0.0",
"resolve-from": "5.0.0",
"rimraf": "3.0.2",

View File

@@ -38,5 +38,10 @@
"wait-on": "6.0.1"
},
"npmClient": "pnpm",
"packageManager": "pnpm@7.4.0-1"
"packageManager": "pnpm@7.4.0-1",
"manypkg": {
"ignoredRules": [
"EXTERNAL_MISMATCH"
]
}
}

View File

@@ -1,5 +1,92 @@
# @blitzjs/auth
## 2.0.0-alpha.64
### Patch Changes
- Updated dependencies [54db8a46]
- Updated dependencies [62bf12b5]
- blitz@2.0.0-alpha.64
## 2.0.0-alpha.63
### Patch Changes
- blitz@2.0.0-alpha.63
## 2.0.0-alpha.62
### Patch Changes
- Updated dependencies [365e6709]
- blitz@2.0.0-alpha.62
## 2.0.0-alpha.61
### Patch Changes
- Updated dependencies [240f378b]
- blitz@2.0.0-alpha.61
## 2.0.0-alpha.60
### Patch Changes
- Updated dependencies [1d863f35]
- blitz@2.0.0-alpha.60
## 2.0.0-alpha.59
### Patch Changes
- blitz@2.0.0-alpha.59
## 2.0.0-alpha.58
### Patch Changes
- 83b35590: Truncate errors from `api/auth/<strategy>/callback` request to 100 characters before passing them to the `?authError=` query parameter
- Updated dependencies [83b35590]
- blitz@2.0.0-alpha.58
## 2.0.0-alpha.57
### Patch Changes
- Updated dependencies [3511d5b6]
- blitz@2.0.0-alpha.57
## 2.0.0-alpha.56
### Patch Changes
- 3f20a474: Update `deleteSession` return type — allow undefined values
- abe2afcc: Fix a long-standing issue with occasional blitz auth flakiness
This bug would sometimes cause users to be logged out or to experience an CSRFTokenMismatchError. This bug, when encountered, usually by lots of setPublicData or session.create calls, would not set the cookie headers correctly resulting in cookies being set to a previous state or in a possibly undefined state.
There are no security concerns as far as I can tell.
- 8bcb471a: Fix auth issue where session token and publicData cookie were updated unnecessarily, leading to potential user logout
- Previously, we were updating the session token each time public data changed. This is not needed, and it would cause race condition bugs where a user could be unexpectedly logged out because a request already in flight would not match the new session token.
- Previously, we were updating the publicData cookie even when it hadn't changed. This may reduce unnecessary re-renders on the client.
- Updated dependencies [abb1ad5d]
- Updated dependencies [abe2afcc]
- Updated dependencies [0ac6e171]
- Updated dependencies [8bcb471a]
- blitz@2.0.0-alpha.56
## 2.0.0-alpha.55
### Patch Changes
- 1c809094: Fix `Page.authenticate` not working for layout components
- Updated dependencies [8f166a5d]
- Updated dependencies [54a66a95]
- blitz@2.0.0-alpha.55
## 2.0.0-alpha.54
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/auth",
"version": "2.0.0-alpha.54",
"version": "2.0.0-alpha.64",
"scripts": {
"build": "unbuild",
"predev": "wait-on -d 250 ../blitz/dist/index-server.d.ts",
@@ -26,7 +26,7 @@
"@types/secure-password": "3.1.1",
"b64-lite": "1.4.0",
"bad-behavior": "1.0.1",
"blitz": "2.0.0-alpha.54",
"blitz": "2.0.0-alpha.64",
"cookie": "0.4.1",
"cookie-session": "2.0.0",
"debug": "4.3.3",
@@ -39,7 +39,7 @@
"url": "0.11.0"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-alpha.54",
"@blitzjs/config": "workspace:2.0.0-alpha.64",
"@testing-library/react": "13.0.0",
"@testing-library/react-hooks": "7.0.2",
"@types/cookie": "0.4.1",
@@ -50,7 +50,7 @@
"react": "18.0.0",
"react-dom": "18.0.0",
"typescript": "^4.5.3",
"unbuild": "0.6.9",
"unbuild": "0.7.6",
"watch": "1.0.2"
},
"publishConfig": {

View File

@@ -216,8 +216,8 @@ export function getAuthValues<TProps = any>(
) {
if (!Page) return {}
let authenticate = "authenticate" in Page && Page.authenticate
let redirectAuthenticatedTo = "redirectAuthenticatedTo" in Page && Page.redirectAuthenticatedTo
let authenticate = (Page as BlitzPage)?.authenticate
let redirectAuthenticatedTo = (Page as BlitzPage)?.redirectAuthenticatedTo
if (authenticate === undefined && redirectAuthenticatedTo === undefined) {
const layout = "getLayout" in Page && Page.getLayout?.(<Page {...props} />)

View File

@@ -105,7 +105,6 @@ export function AuthServerPlugin(options: AuthPluginOptions): BlitzServerPlugin<
IncomingMessage,
ServerResponse & {blitzCtx: Ctx}
> = async (req, res, next) => {
console.log("Starting sessionMiddleware...")
if (!res.blitzCtx?.session) {
await getSession(req, res)
}

View File

@@ -0,0 +1,41 @@
import {expect, describe, it} from "vitest"
import {setCookie} from "./auth-sessions"
import cookie from "cookie"
import {ServerResponse} from "http"
describe("blitz-auth", () => {
describe("setCookie", () => {
it("works with empty start", async () => {
const res = new ServerResponse({} as any)
setCookie(res, cookie.serialize("A", "a-value", {}))
expect(res.getHeader("Set-Cookie")).toBe("A=a-value")
})
it("works with string start", async () => {
const res = new ServerResponse({} as any)
res.setHeader("Set-Cookie", cookie.serialize("A", "a-value", {}))
setCookie(res, cookie.serialize("B", "b-value", {}))
expect(res.getHeader("Set-Cookie")).toEqual(["A=a-value", "B=b-value"])
})
it("works with array start for new name", async () => {
const res = new ServerResponse({} as any)
res.setHeader("Set-Cookie", [
cookie.serialize("A", "a-value", {}),
cookie.serialize("B", "b-value", {}),
])
setCookie(res, cookie.serialize("C", "c-value", {}))
expect(res.getHeader("Set-Cookie")).toEqual(["A=a-value", "B=b-value", "C=c-value"])
})
it("works with array start for existing name", async () => {
const res = new ServerResponse({} as any)
res.setHeader("Set-Cookie", [
cookie.serialize("A", "a-value", {}),
cookie.serialize("B", "b-value", {}),
])
setCookie(res, cookie.serialize("A", "new-a-value", {}))
expect(res.getHeader("Set-Cookie")).toEqual(["A=new-a-value", "B=b-value"])
})
})
})

View File

@@ -385,7 +385,7 @@ const parseAnonymousSessionToken = (token: string) => {
}
}
const setCookie = (res: ServerResponse, cookieStr: string) => {
export const setCookie = (res: ServerResponse, cookieStr: string) => {
const getCookieName = (c: string) => c.split("=", 2)[0]
const appendCookie = () => append(res, "Set-Cookie", cookieStr)
@@ -407,7 +407,7 @@ const setCookie = (res: ServerResponse, cookieStr: string) => {
for (let i = 0; i < cookiesHeader.length; i++) {
if (cookieName === getCookieName(cookiesHeader[i] || "")) {
cookiesHeader[i] = cookieStr
res.setHeader("Set-Cookie", cookieStr)
res.setHeader("Set-Cookie", cookiesHeader)
return
}
}
@@ -801,30 +801,16 @@ async function refreshSession(
const expiresAt = addYears(new Date(), 30)
setAnonymousSessionCookie(req, res, anonymousSessionToken, expiresAt)
setPublicDataCookie(req, res, publicDataToken, expiresAt)
setCSRFCookie(req, res, sessionKernel.antiCSRFToken, expiresAt)
} else if (global.sessionConfig.method === "essential" && "sessionToken" in sessionKernel) {
const expiresAt = addMinutes(new Date(), global.sessionConfig.sessionExpiryMinutes as number)
const publicDataToken = createPublicDataToken(sessionKernel.publicData)
let sessionToken: string
// Only generate new session token if public data actually changed
// Otherwise if new session token is generated just for refresh, then
// we have race condition bugs
if (publicDataChanged) {
sessionToken = createSessionToken(sessionKernel.handle, sessionKernel.publicData)
} else {
sessionToken = sessionKernel.sessionToken
}
setSessionCookie(req, res, sessionToken, expiresAt)
setPublicDataCookie(req, res, publicDataToken, expiresAt)
setCSRFCookie(req, res, sessionKernel.antiCSRFToken, expiresAt)
debug("Updating session in db with", {expiresAt})
if (publicDataChanged) {
debug("Public data has changed")
const publicDataToken = createPublicDataToken(sessionKernel.publicData)
setPublicDataCookie(req, res, publicDataToken, expiresAt)
await global.sessionConfig.updateSession(sessionKernel.handle, {
expiresAt,
hashedSessionToken: hash256(sessionToken),
publicData: JSON.stringify(sessionKernel.publicData),
})
} else {

View File

@@ -11,6 +11,7 @@ import {
RequestMiddleware,
MiddlewareResponse,
secureProxyMiddleware,
truncateString,
} from "blitz"
import {IncomingMessage, ServerResponse} from "http"
import {PublicData, SessionContext} from "../shared"
@@ -161,7 +162,10 @@ export function passportAuth(config: BlitzPassportConfig): ApiHandler {
"/"
if (error) {
redirectUrl += "?authError=" + encodeURIComponent(error.toString())
console.error(`Login via ${strategyName} was unsuccessful.`)
console.error(error)
redirectUrl +=
"?authError=" + encodeURIComponent(truncateString(error.toString(), 100))
res.setHeader("Location", redirectUrl)
res.statusCode = 302
res.end()

View File

@@ -47,7 +47,7 @@ export interface SessionConfigMethods {
handle: string,
session: Partial<SessionModel>,
) => Promise<SessionModel | undefined>
deleteSession: (handle: string) => Promise<SessionModel>
deleteSession: (handle: string) => Promise<SessionModel | undefined>
}
export interface SessionConfig extends SessionConfigMethods {

View File

@@ -1,5 +1,77 @@
# @blitzjs/next
## 2.0.0-alpha.64
### Patch Changes
- @blitzjs/rpc@2.0.0-alpha.64
## 2.0.0-alpha.63
### Patch Changes
- f52ca398: Upgrade react-query to v4
- Updated dependencies [f52ca398]
- @blitzjs/rpc@2.0.0-alpha.63
## 2.0.0-alpha.62
### Patch Changes
- 31d7a6f4: Set prefix in moduleNameWrapper's options in Blitz's jest configuration
- @blitzjs/rpc@2.0.0-alpha.62
## 2.0.0-alpha.61
### Patch Changes
- @blitzjs/rpc@2.0.0-alpha.61
## 2.0.0-alpha.60
### Patch Changes
- @blitzjs/rpc@2.0.0-alpha.60
## 2.0.0-alpha.59
### Patch Changes
- 3b213a35: Export router-context from browser entrypoint
- Updated dependencies [3b213a35]
- @blitzjs/rpc@2.0.0-alpha.59
## 2.0.0-alpha.58
### Patch Changes
- 6ab9db78: Infer result type in the `api` handler and allow customizing it
- Updated dependencies [c721c104]
- @blitzjs/rpc@2.0.0-alpha.58
## 2.0.0-alpha.57
### Patch Changes
- 0f18c68d: Avoid reassigning queryClient in prefetch methods
- Updated dependencies [716e188d]
- @blitzjs/rpc@2.0.0-alpha.57
## 2.0.0-alpha.56
### Patch Changes
- d9fc5d8e: Allow prefetching multiple queries in gSSP and gSP
- @blitzjs/rpc@2.0.0-alpha.56
## 2.0.0-alpha.55
### Patch Changes
- 8d9ea00e: Fix prefetching multiple queries causes only the last one to be passed to page
- Updated dependencies [df7cee84]
- @blitzjs/rpc@2.0.0-alpha.55
## 2.0.0-alpha.54
### Patch Changes

View File

@@ -21,6 +21,7 @@ function createJestConfigForNext(options) {
// This ensures any path aliases in tsconfig also work in jest
...pathsToModuleNameMapper(
(tsConfig && tsConfig.compilerOptions && tsConfig.compilerOptions.paths) || {},
{prefix: "<rootDir>/"},
),
"\\.(jpg|jpeg|png|gif|webp|ico)$": path.resolve(__dirname, "./jest-preset/image-mock.js"),
},

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/next",
"version": "2.0.0-alpha.54",
"version": "2.0.0-alpha.64",
"scripts": {
"build": "unbuild",
"dev": "pnpm predev && pnpm watch unbuild src --wait=0.2",
@@ -24,16 +24,16 @@
"eslint.js"
],
"dependencies": {
"@blitzjs/rpc": "2.0.0-alpha.54",
"@blitzjs/rpc": "2.0.0-alpha.64",
"@tanstack/react-query": "4.0.10",
"@types/hoist-non-react-statics": "3.3.1",
"debug": "4.3.3",
"fs-extra": "10.0.1",
"hoist-non-react-statics": "3.3.2",
"react-query": "3.39.0",
"superjson": "1.8.0"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-alpha.54",
"@blitzjs/config": "workspace:2.0.0-alpha.64",
"@testing-library/dom": "8.13.0",
"@testing-library/jest-dom": "5.16.3",
"@testing-library/react": "13.0.0",
@@ -43,7 +43,7 @@
"@types/react": "18.0.1",
"@types/react-dom": "17.0.14",
"@types/testing-library__react-hooks": "4.0.0",
"blitz": "2.0.0-alpha.54",
"blitz": "2.0.0-alpha.64",
"cross-spawn": "7.0.3",
"find-up": "4.1.0",
"next": "12.2.0",
@@ -52,7 +52,7 @@
"resolve-from": "5.0.0",
"ts-jest": "27.1.4",
"typescript": "^4.5.3",
"unbuild": "0.6.9",
"unbuild": "0.7.6",
"watch": "1.0.2"
},
"publishConfig": {

View File

@@ -1,4 +1,4 @@
import {QueryClient} from "react-query"
import {QueryClient} from "@tanstack/react-query"
declare global {
var queryClient: QueryClient

View File

@@ -6,9 +6,8 @@ import type {
Simplify,
} from "blitz"
import Head from "next/head"
import React from "react"
import {QueryClient, QueryClientProvider} from "react-query"
import {Hydrate, HydrateOptions} from "react-query/hydration"
import React, {ReactNode} from "react"
import {QueryClient, QueryClientProvider, Hydrate, HydrateOptions} from "@tanstack/react-query"
import {withSuperJSONPage} from "./superjson"
import {Ctx} from "blitz"
import {UrlObject} from "url"
@@ -19,6 +18,7 @@ import {RouterContext} from "./router-context"
export * from "./error-boundary"
export * from "./error-component"
export * from "./use-params"
export * from "./router-context"
export {Routes} from ".blitz"
const compose =
@@ -80,7 +80,7 @@ export type BlitzPage<P = {}> = React.ComponentType<P> & {
suppressFirstRenderFlicker?: boolean
redirectAuthenticatedTo?: RedirectAuthenticatedTo | RedirectAuthenticatedToFn
}
export type BlitzLayout<P = {}> = React.ComponentType<P> & {
export type BlitzLayout<P = {}> = React.ComponentType<P & {children: ReactNode}> & {
authenticate?: boolean | {redirectTo?: string | RouteUrlObject}
redirectAuthenticatedTo?: RedirectAuthenticatedTo | RedirectAuthenticatedToFn
}

View File

@@ -25,7 +25,7 @@ import {
InstallWebpackConfigOptions,
ResolverPathOptions,
} from "@blitzjs/rpc"
import {DefaultOptions, QueryClient} from "react-query"
import {DefaultOptions, QueryClient} from "@tanstack/react-query"
import {IncomingMessage, ServerResponse} from "http"
import {withSuperJsonProps} from "./superjson"
import {ParsedUrlQuery} from "querystring"
@@ -40,10 +40,10 @@ export interface BlitzNextApiResponse
extends MiddlewareResponse,
Omit<NextApiResponse, keyof MiddlewareResponse> {}
export type NextApiHandler = (
export type NextApiHandler<TResult> = (
req: NextApiRequest,
res: BlitzNextApiResponse,
) => void | Promise<void>
) => TResult | void | Promise<TResult | void>
type SetupBlitzOptions = {
plugins: BlitzServerPlugin<RequestMiddleware, Ctx>[]
@@ -74,11 +74,32 @@ export type BlitzGSPHandler<
GetStaticProps<TProps, Query, PD>
>
export type BlitzAPIHandler = (
req: Parameters<NextApiHandler>[0],
res: Parameters<NextApiHandler>[1],
export type BlitzAPIHandler<TResult> = (
req: NextApiRequest,
res: BlitzNextApiResponse,
ctx: Ctx,
) => ReturnType<NextApiHandler>
) => TResult | void | Promise<TResult | void>
const prefetchQueryFactory = (
ctx: BlitzCtx,
): {
getClient: () => QueryClient | null
prefetchQuery: AddParameters<PrefetchQueryFn, [boolean?]>
} => {
let queryClient: null | QueryClient = null
return {
getClient: () => queryClient,
prefetchQuery: async (fn, input, defaultOptions = {}, infinite = false) => {
if (!queryClient) {
queryClient = new QueryClient({defaultOptions})
}
const queryKey = infinite ? getInfiniteQueryKey(fn, input) : getQueryKey(fn, input)
await queryClient.prefetchQuery(queryKey, () => fn(input, ctx))
},
}
}
export const setupBlitzServer = ({plugins, onError}: SetupBlitzOptions) => {
const middlewares = plugins.flatMap((p) => p.requestMiddlewares)
@@ -94,26 +115,15 @@ export const setupBlitzServer = ({plugins, onError}: SetupBlitzOptions) => {
(y, f) => (f ? f(y) : y),
(res as MiddlewareResponse).blitzCtx,
)
let queryClient: null | QueryClient = null
const prefetchQuery: AddParameters<PrefetchQueryFn, [boolean?]> = async (
fn,
input,
defaultOptions = {},
infinite = false,
) => {
queryClient = new QueryClient({defaultOptions})
const queryKey = infinite ? getInfiniteQueryKey(fn, input) : getQueryKey(fn, input)
await queryClient.prefetchQuery(queryKey, () => fn(input, ctx))
}
const {getClient, prefetchQuery} = prefetchQueryFactory(ctx)
ctx.prefetchQuery = prefetchQuery
ctx.prefetchInfiniteQuery = (...args) => prefetchQuery(...args, true)
try {
const result = await handler({req, res, ctx, ...rest})
return withSuperJsonProps(withDehydratedState(result, queryClient))
return withSuperJsonProps(withDehydratedState(result, getClient()))
} catch (err: any) {
onError?.(err)
throw err
@@ -126,26 +136,14 @@ export const setupBlitzServer = ({plugins, onError}: SetupBlitzOptions) => {
): GetStaticProps<TProps, Query, PD> =>
async (context) => {
const ctx = contextMiddleware.reduceRight((y, f) => (f ? f(y) : y), {} as Ctx)
let queryClient: null | QueryClient = null
const prefetchQuery: AddParameters<PrefetchQueryFn, [boolean?]> = async (
fn,
input,
defaultOptions = {},
infinite = false,
) => {
queryClient = new QueryClient({defaultOptions})
const queryKey = infinite ? getInfiniteQueryKey(fn, input) : getQueryKey(fn, input)
await queryClient.prefetchQuery(queryKey, () => fn(input, ctx))
}
const {getClient, prefetchQuery} = prefetchQueryFactory(ctx)
ctx.prefetchQuery = prefetchQuery
ctx.prefetchInfiniteQuery = (...args) => prefetchQuery(...args, true)
try {
const result = await handler({...context, ctx: ctx})
return withSuperJsonProps(withDehydratedState(result, queryClient))
return withSuperJsonProps(withDehydratedState(result, getClient()))
} catch (err: any) {
onError?.(err)
throw err
@@ -153,7 +151,9 @@ export const setupBlitzServer = ({plugins, onError}: SetupBlitzOptions) => {
}
const api =
(handler: BlitzAPIHandler): NextApiHandler =>
<TResult = Promise<void> | void>(
handler: BlitzAPIHandler<TResult>,
): NextApiHandler<TResult | void> =>
async (req, res) => {
try {
await handleRequestWithMiddleware(req, res, middlewares)

View File

@@ -1,5 +1,95 @@
# @blitzjs/rpc
## 2.0.0-alpha.64
### Patch Changes
- Updated dependencies [54db8a46]
- Updated dependencies [62bf12b5]
- blitz@2.0.0-alpha.64
- @blitzjs/auth@2.0.0-alpha.64
## 2.0.0-alpha.63
### Patch Changes
- f52ca398: Upgrade react-query to v4
- @blitzjs/auth@2.0.0-alpha.63
- blitz@2.0.0-alpha.63
## 2.0.0-alpha.62
### Patch Changes
- Updated dependencies [365e6709]
- blitz@2.0.0-alpha.62
- @blitzjs/auth@2.0.0-alpha.62
## 2.0.0-alpha.61
### Patch Changes
- Updated dependencies [240f378b]
- blitz@2.0.0-alpha.61
- @blitzjs/auth@2.0.0-alpha.61
## 2.0.0-alpha.60
### Patch Changes
- Updated dependencies [1d863f35]
- blitz@2.0.0-alpha.60
- @blitzjs/auth@2.0.0-alpha.60
## 2.0.0-alpha.59
### Patch Changes
- 3b213a35: Remove debug console.log
- @blitzjs/auth@2.0.0-alpha.59
- blitz@2.0.0-alpha.59
## 2.0.0-alpha.58
### Patch Changes
- c721c104: Pass `signal` from useQuery to Blitz internal rpc client to be able to cancel queries on unmount
- Updated dependencies [83b35590]
- blitz@2.0.0-alpha.58
- @blitzjs/auth@2.0.0-alpha.58
## 2.0.0-alpha.57
### Patch Changes
- 716e188d: Fix queries/mutations lookup on Windows
- Updated dependencies [3511d5b6]
- blitz@2.0.0-alpha.57
- @blitzjs/auth@2.0.0-alpha.57
## 2.0.0-alpha.56
### Patch Changes
- Updated dependencies [3f20a474]
- Updated dependencies [abb1ad5d]
- Updated dependencies [abe2afcc]
- Updated dependencies [0ac6e171]
- Updated dependencies [8bcb471a]
- @blitzjs/auth@2.0.0-alpha.56
- blitz@2.0.0-alpha.56
## 2.0.0-alpha.55
### Patch Changes
- df7cee84: Fix pipe resolver return type
- Updated dependencies [8f166a5d]
- Updated dependencies [54a66a95]
- Updated dependencies [1c809094]
- blitz@2.0.0-alpha.55
- @blitzjs/auth@2.0.0-alpha.55
## 2.0.0-alpha.54
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/rpc",
"version": "2.0.0-alpha.54",
"version": "2.0.0-alpha.64",
"scripts": {
"build": "unbuild",
"predev": "wait-on -d 250 ../blitz/dist/index-server.d.ts && wait-on -d 250 ../blitz-auth/dist/index-browser.d.ts",
@@ -20,30 +20,30 @@
"dist/**"
],
"dependencies": {
"@blitzjs/auth": "2.0.0-alpha.54",
"@blitzjs/auth": "2.0.0-alpha.64",
"@tanstack/react-query": "4.0.10",
"b64-lite": "1.4.0",
"bad-behavior": "1.0.1",
"chalk": "^4.1.0",
"debug": "4.3.3",
"react-query": "3.39.0",
"superjson": "1.8.0",
"zod": "3.17.3"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-alpha.54",
"@blitzjs/config": "workspace:2.0.0-alpha.64",
"@types/debug": "4.1.7",
"@types/react": "18.0.1",
"@types/react-dom": "17.0.14",
"blitz": "2.0.0-alpha.54",
"blitz": "2.0.0-alpha.64",
"next": "12.2.0",
"react": "18.0.0",
"react-dom": "18.0.0",
"typescript": "^4.5.3",
"unbuild": "0.6.9",
"unbuild": "0.7.6",
"watch": "1.0.2"
},
"peerDependencies": {
"blitz": "2.0.0-alpha.54",
"blitz": "2.0.0-alpha.64",
"next": ">=12.2.0"
},
"publishConfig": {

View File

@@ -8,7 +8,11 @@ export {
setQueryData,
getQueryClient,
} from "./react-query-utils"
export {useQueryErrorResetBoundary, QueryClient} from "react-query"
export {dehydrate} from "react-query/hydration"
export {
useQueryErrorResetBoundary,
QueryClientProvider,
QueryClient,
dehydrate,
} from "@tanstack/react-query"
export {invoke} from "./invoke"
export {invokeWithCtx} from "./invokeWithCtx"

View File

@@ -1,4 +1,4 @@
import {QueryClient, QueryKey} from "react-query"
import {QueryClient} from "@tanstack/react-query"
import {serialize} from "superjson"
import {isClient, isServer, AsyncFunc} from "blitz"
import {ResolverType, RpcClient} from "./rpc"
@@ -94,7 +94,7 @@ export const validateQueryFn = <TInput, TResult>(
) => {
if (isClient && !isRpcClient(queryFn) && isNotInUserTestEnvironment()) {
throw new Error(
`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")`,
`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 "@tanstack/react-query").`,
)
}
}
@@ -169,14 +169,7 @@ export function invalidateQuery<TInput, TResult, T extends AsyncFunc>(
}
const fullQueryKey = getQueryKey(resolver, params)
let queryKey: QueryKey
if (params) {
queryKey = fullQueryKey
} else {
// Params not provided, only use first query key item (url)
queryKey = fullQueryKey[0]
}
return getQueryClient().invalidateQueries(queryKey)
return getQueryClient().invalidateQueries(fullQueryKey)
}
export function setQueryData<TInput, TResult, T extends AsyncFunc>(

View File

@@ -9,7 +9,7 @@ import {
useMutation as useReactQueryMutation,
UseMutationOptions,
UseMutationResult,
} from "react-query"
} from "@tanstack/react-query"
import {useSession} from "@blitzjs/auth"
import {isServer, FirstParam, PromiseReturnType, AsyncFunc} from "blitz"
import {
@@ -85,14 +85,14 @@ export function useQuery<
const {data, ...queryRest} = useReactQuery({
queryKey: routerIsReady ? queryKey : ["_routerNotReady_"],
queryFn: routerIsReady
? () => enhancedResolverRpcClient(params, {fromQueryHook: true})
? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal)
: (emptyQueryFn as any),
...options,
enabled,
})
if (
queryRest.isIdle &&
queryRest.fetchStatus === "idle" &&
isServer &&
suspenseEnabled !== false &&
!data &&
@@ -170,7 +170,7 @@ export function usePaginatedQuery<
const {data, ...queryRest} = useReactQuery({
queryKey: routerIsReady ? queryKey : ["_routerNotReady_"],
queryFn: routerIsReady
? () => enhancedResolverRpcClient(params, {fromQueryHook: true})
? ({signal}) => enhancedResolverRpcClient(params, {fromQueryHook: true}, signal)
: (emptyQueryFn as any),
...options,
keepPreviousData: true,
@@ -178,7 +178,7 @@ export function usePaginatedQuery<
})
if (
queryRest.isIdle &&
queryRest.fetchStatus === "idle" &&
isServer &&
suspenseEnabled !== false &&
!data &&
@@ -267,17 +267,15 @@ export function useInfiniteQuery<
// Without this cache for usePaginatedQuery and this will conflict and break.
queryKey: routerIsReady ? queryKey : ["_routerNotReady_"],
queryFn: routerIsReady
? ({pageParam}) =>
enhancedResolverRpcClient(getQueryParams(pageParam), {
fromQueryHook: true,
})
? ({pageParam, signal}) =>
enhancedResolverRpcClient(getQueryParams(pageParam), {fromQueryHook: true}, signal)
: (emptyQueryFn as any),
...options,
enabled,
})
if (
queryRest.isIdle &&
queryRest.fetchStatus === "idle" &&
isServer &&
suspenseEnabled !== false &&
!data &&

View File

@@ -39,7 +39,7 @@ export interface EnhancedRpc {
}
export interface RpcClientBase<Input = unknown, Result = unknown> {
(params: Input, opts?: RpcOptions): Promise<Result>
(params: Input, opts?: RpcOptions, signal?: AbortSignal): Promise<Result>
}
export interface RpcClient<Input = unknown, Result = unknown>
@@ -57,7 +57,7 @@ export function __internal_buildRpcClient({
}: BuildRpcClientParams): RpcClient {
const fullRoutePath = normalizeApiRoute("/api/rpc" + routePath)
const httpClient: RpcClientBase = async (params, opts = {}) => {
const httpClient: RpcClientBase = async (params, opts = {}, signal = undefined) => {
const debug = (await import("debug")).default("blitz:rpc")
if (!opts.fromQueryHook && !opts.fromInvoke) {
console.warn(
@@ -93,9 +93,6 @@ export function __internal_buildRpcClient({
serialized = serialize(params)
}
// Create a new AbortController instance for this request
const controller = new AbortController()
const promise = window
.fetch(fullRoutePath, {
method: "POST",
@@ -108,7 +105,7 @@ export function __internal_buildRpcClient({
params: serialized.meta,
},
}),
signal: controller.signal,
signal,
})
.then(async (response) => {
debug("Received request for", routePath)

View File

@@ -1,4 +1,4 @@
import {QueryClient} from "react-query"
import {QueryClient} from "@tanstack/react-query"
declare global {
var queryClient: QueryClient

View File

@@ -1,6 +1,6 @@
import "./global"
import {createClientPlugin} from "blitz"
import {DefaultOptions, QueryClient} from "react-query"
import {DefaultOptions, QueryClient} from "@tanstack/react-query"
export * from "./data-client/index"
@@ -21,7 +21,7 @@ export const BlitzRpcPlugin = createClientPlugin<BlitzRpcOptions, {queryClient:
...reactQueryOptions,
queries: {
...(typeof window === "undefined" && {cacheTime: 0}),
retry: (failureCount, error: any) => {
retry: (failureCount: number, error: any) => {
if (process.env.NODE_ENV !== "production") return false
// Retry (max. 3 times) only if network error detected

View File

@@ -80,7 +80,7 @@ export function installWebpackConfig({
webpackRuleOptions,
}: InstallWebpackConfigOptions) {
webpackConfig.module.rules.push({
test: /\/\[\[\.\.\.blitz]]\.[jt]s$/,
test: /[\\/]\[\[\.\.\.blitz]]\.[jt]sx?$/,
use: [
{
loader: loaderServer,
@@ -146,10 +146,10 @@ export function rpcHandler(config: RpcConfig) {
"It seems your Blitz RPC endpoint file is not named [[...blitz]].(jt)s. Please ensure it is",
)
const relativeRoutePath = req.query.blitz.join("/")
const relativeRoutePath = (req.query.blitz as string[])?.join("/")
const routePath = "/" + relativeRoutePath
const loadableResolver = resolverMap[routePath]
const loadableResolver = resolverMap?.[routePath]
if (!loadableResolver) {
throw new Error("No resolver for path: " + routePath)
}

View File

@@ -1,4 +1,4 @@
import {dirname, join, posix} from "path"
import {dirname, join, posix, relative} from "path"
import {promises} from "fs"
import {
assertPosixPath,
@@ -37,6 +37,10 @@ export async function loader(this: Loader, input: string): Promise<string> {
module.exports = loader
function slash(str: string) {
return str.replace(/\\/g, "/")
}
export async function transformBlitzRpcServer(
src: string,
id: string,
@@ -54,7 +58,7 @@ export async function transformBlitzRpcServer(
code += "\n\n"
for (let resolverFilePath of resolvers) {
const relativeResolverPath = posix.relative(dirname(id), join(root, resolverFilePath))
const relativeResolverPath = slash(relative(dirname(id), join(root, resolverFilePath)))
const routePath = convertPageFilePathToRoutePath(resolverFilePath, options?.resolverPath)
code += `__internal_addBlitzRpcResolver('${routePath}', () => import('${relativeResolverPath}'));`
code += "\n"

View File

@@ -54,7 +54,7 @@ function pipe<A, B, C, D, E, F, G, CA = Ctx, CB = CA, CC = CB, CD = CC, CE = CD,
de: PipeFn<D, E, CD, CE>,
ef: PipeFn<E, F, CE, CF>,
fg: PipeFn<F, G, CF, CG>,
): (input: A, ctx: CA) => EnsurePromise<CG>
): (input: A, ctx: CA) => EnsurePromise<G>
function pipe<
A,
B,

View File

@@ -1,5 +1,91 @@
# blitz
## 2.0.0-alpha.64
### Patch Changes
- 54db8a46: Add missing value to "skip" option when choosing a package manager during new app scaffolding
- 62bf12b5: Fix blitz codegen to work with monorepos
- @blitzjs/generator@2.0.0-alpha.64
## 2.0.0-alpha.63
### Patch Changes
- @blitzjs/generator@2.0.0-alpha.63
## 2.0.0-alpha.62
### Patch Changes
- 365e6709: Fixes the db seed command so that the database can disconnect after running the seed file.
- @blitzjs/generator@2.0.0-alpha.62
## 2.0.0-alpha.61
### Patch Changes
- 240f378b: Passes the correct arguments (without flags) to any bin command ran with the blitz cli
- @blitzjs/generator@2.0.0-alpha.61
## 2.0.0-alpha.60
### Patch Changes
- 1d863f35: Fix APP_ENV not being set before loading env config
- @blitzjs/generator@2.0.0-alpha.60
## 2.0.0-alpha.59
### Patch Changes
- @blitzjs/generator@2.0.0-alpha.59
## 2.0.0-alpha.58
### Minor Changes
- 83b35590: Truncate errors from `api/auth/<strategy>/callback` request to 100 characters before passing them to the `?authError=` query parameter
### Patch Changes
- Updated dependencies [e339e2fd]
- @blitzjs/generator@2.0.0-alpha.58
## 2.0.0-alpha.57
### Patch Changes
- 3511d5b6: Temporarily skip version check
- @blitzjs/generator@2.0.0-alpha.57
## 2.0.0-alpha.56
### Patch Changes
- abb1ad5d: Improve codemod utilities
- abe2afcc: Fix a long-standing issue with occasional blitz auth flakiness
This bug would sometimes cause users to be logged out or to experience an CSRFTokenMismatchError. This bug, when encountered, usually by lots of setPublicData or session.create calls, would not set the cookie headers correctly resulting in cookies being set to a previous state or in a possibly undefined state.
There are no security concerns as far as I can tell.
- 0ac6e171: fixes blitz not loading custom server
- 8bcb471a: Fix auth issue where session token and publicData cookie were updated unnecessarily, leading to potential user logout
- Previously, we were updating the session token each time public data changed. This is not needed, and it would cause race condition bugs where a user could be unexpectedly logged out because a request already in flight would not match the new session token.
- Previously, we were updating the publicData cookie even when it hadn't changed. This may reduce unnecessary re-renders on the client.
- @blitzjs/generator@2.0.0-alpha.56
## 2.0.0-alpha.55
### Patch Changes
- 8f166a5d: Check for new versions when running CLI
- 54a66a95: Show all blitz packages when running `blitz version` command
- Updated dependencies [ab4d9de7]
- @blitzjs/generator@2.0.0-alpha.55
## 2.0.0-alpha.54
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "blitz",
"version": "2.0.0-alpha.54",
"version": "2.0.0-alpha.64",
"scripts": {
"build": "unbuild",
"dev": "watch unbuild src --wait=0.2",
@@ -23,8 +23,9 @@
"blitz": "bin/blitz"
},
"dependencies": {
"@blitzjs/generator": "2.0.0-alpha.54",
"@blitzjs/generator": "2.0.0-alpha.64",
"arg": "5.0.1",
"boxen": "7.0.0",
"chalk": "^4.1.0",
"console-table-printer": "2.10.0",
"cross-spawn": "7.0.3",
@@ -37,6 +38,7 @@
"find-up": "4.1.0",
"fs-extra": "10.0.1",
"hasbin": "1.2.3",
"node-fetch": "3.2.3",
"npm-which": "3.0.1",
"ora": "5.3.0",
"os-name": "5.0.1",
@@ -52,7 +54,7 @@
"watchpack": "2.1.1"
},
"devDependencies": {
"@blitzjs/config": "workspace:2.0.0-alpha.54",
"@blitzjs/config": "workspace:2.0.0-alpha.64",
"@types/cookie": "0.4.1",
"@types/cross-spawn": "6.0.2",
"@types/debug": "4.1.7",
@@ -69,11 +71,10 @@
"@types/test-listen": "1.1.0",
"@types/watchpack": "1.1.1",
"express": "4.17.3",
"node-fetch": "3.2.3",
"react": "18.0.0",
"test-listen": "1.1.0",
"typescript": "^4.5.3",
"unbuild": "0.6.9",
"unbuild": "0.7.6",
"watch": "1.0.2",
"zod": "3.17.3"
},

View File

@@ -51,7 +51,7 @@ const runSeed = async (seedBasePath: string) => {
throw err
}
const db = require(dbPath)
const db = require(dbPath).default
await db.$disconnect()
console.log("Done Seeding")
}

View File

@@ -7,6 +7,7 @@ import {CliCommand} from "../index"
import arg from "arg"
import {AppGenerator, AppGeneratorOptions, getLatestVersion} from "@blitzjs/generator"
import {runPrisma} from "../../prisma-utils"
import {checkLatestVersion} from "../utils/check-latest-version"
const forms = {
"react-final-form": "React Final Form" as const,
@@ -198,7 +199,7 @@ const determinePkgManagerToInstallDeps = async () => {
{title: "npm", value: "npm"},
{title: "yarn", value: "yarn", disabled: !IS_YARN_INSTALLED},
{title: "pnpm", value: "pnpm", disabled: !IS_PNPM_INSTALLED},
{title: "skip"},
{title: "skip", value: "skip"},
],
})
@@ -218,9 +219,9 @@ const determinePkgManagerToInstallDeps = async () => {
}
const newApp: CliCommand = async (argv) => {
const shouldUpgrade = !args["--skip-upgrade"]
const shouldUpgrade = false // !args["--skip-upgrade"]
if (shouldUpgrade) {
//TODO: Handle checking for updates
await checkLatestVersion()
}
await determineProjectName()

View File

@@ -1,12 +1,12 @@
import {NON_STANDARD_NODE_ENV} from "./utils/constants"
import arg from "arg"
import {loadEnvConfig} from "../env-utils"
import {getCommandBin} from "./utils/config"
import spawn from "cross-spawn"
import {readdirSync} from "fs-extra"
import resolveFrom from "resolve-from"
import pkgDir from "pkg-dir"
import {join} from "path"
import {loadEnvConfig} from "../env-utils"
import {NON_STANDARD_NODE_ENV} from "./utils/constants"
import {getCommandBin} from "./utils/config"
import {readVersions} from "./utils/read-versions"
import {getPkgManager} from "./utils/helpers"
const commonArgs = {
// Flags
@@ -57,15 +57,13 @@ if (aliases[args._[0] as Alias]) {
const forwardedArgs = blitzCommand ? args._.slice(1) : args._
const globalBlitzPath = resolveFrom(__dirname, "blitz")
const localBlitzPath = resolveFrom.silent(process.cwd(), "blitz")
async function runCommandFromBin() {
if (!args._[0]) {
console.log("No command specified")
process.exit(1)
}
let commandBin: string | null = null
try {
commandBin = await getCommandBin(args._[0])
} catch (e: any) {
@@ -76,25 +74,24 @@ async function runCommandFromBin() {
process.exit(1)
}
const result = spawn.sync(commandBin, process.argv.slice(3), {stdio: "inherit"})
const result = spawn.sync(commandBin, args._.slice(1), {stdio: "inherit"})
process.exit(result.status || 0)
}
async function printEnvInfo() {
const osName = await import("os-name")
const envinfo = await import("envinfo")
const pkgManager = readdirSync(process.cwd()).includes("pnpm-lock.yaml")
? "pnpm"
: readdirSync(process.cwd()).includes("yarn-lock.yaml")
? "yarn"
: "npm"
const pkgManager = getPkgManager()
const env = await envinfo.default.run(
{
System: ["OS", "CPU", "Memory", "Shell"],
Binaries: ["Node", "Yarn", "npm", "pnpm"],
npmPackages: [
"blitz",
"@blitzjs/rpc",
"@blitzjs/auth",
"@blitzjs/next",
"typescript",
"react",
"react-dom",
@@ -106,18 +103,13 @@ async function printEnvInfo() {
{showNotFound: true},
)
const globalBlitzPkgJsonPath = pkgDir.sync(globalBlitzPath)
const localBlitzPkgJsonPath = pkgDir.sync(localBlitzPath)
if (globalBlitzPkgJsonPath && globalBlitzPkgJsonPath !== localBlitzPkgJsonPath) {
// This branch won't run if user does `npx blitz` or `yarn blitz`
const globalVersion = require(join(globalBlitzPkgJsonPath, "package.json")).version
const {globalVersion, localVersions} = readVersions()
if (globalVersion) {
console.log(`Blitz version: ${globalVersion} (global)`)
}
if (localBlitzPkgJsonPath) {
const localVersion = require(join(localBlitzPkgJsonPath, "package.json")).version
console.log(`Blitz version: ${localVersion} (local)`)
if (localVersions.blitz) {
console.log(`Blitz version: ${localVersions.blitz} (local)`)
}
console.log(
@@ -129,6 +121,9 @@ async function printEnvInfo() {
}
async function main() {
if (args["--env"]) {
process.env.APP_ENV = args["--env"]
}
loadEnvConfig(process.cwd(), undefined, {error: console.error, info: console.info})
// Version is inlined into the file using taskr build pipeline
@@ -136,10 +131,6 @@ async function main() {
await printEnvInfo()
}
if (args["--env"]) {
process.env.APP_ENV = args["--env"]
}
if (args["--help"]) {
forwardedArgs.push("--help")
}

View File

@@ -0,0 +1,183 @@
import findUp from "find-up"
import resolveFrom from "resolve-from"
import {join, dirname} from "path"
import fs from "fs"
import {readVersions, resolveVersionType} from "./read-versions"
import {getPkgManager} from "./helpers"
import superjson from "superjson"
import {isInternalBlitzMonorepoDevelopment} from "./helpers"
const returnNpmEndpoint = (packageName: string) => {
return `https://registry.npmjs.org/-/package/${packageName}/dist-tags`
}
function getUpdateString(packageName: string, tag: string, isGlobal?: boolean) {
const pkgManager = getPkgManager()
switch (pkgManager) {
case "npm":
return `npm install${isGlobal ? " -g" : ""} ${packageName}@${tag}`
case "yarn":
return `yarn${isGlobal ? " global" : ""} add ${packageName}@${tag}`
case "pnpm":
return `pnpm install${isGlobal ? " -g" : ""} ${packageName}@${tag}`
}
}
async function findNodeModulesRoot(src: string) {
const blitzPkgLocation = dirname(
(await findUp("package.json", {
cwd: resolveFrom(src, "blitz"),
})) ?? "",
)
if (!blitzPkgLocation) {
throw new Error("Internal Blitz Error: unable to find 'blitz' package location")
}
return blitzPkgLocation.includes(".pnpm")
? join(blitzPkgLocation, "../../../../")
: join(blitzPkgLocation, "../")
}
export async function checkLatestVersion() {
if (!isInternalBlitzMonorepoDevelopment) {
const fetch = await import("node-fetch")
const boxen = await import("boxen")
const versions = readVersions()
const nodeModulesRoot = await findNodeModulesRoot(process.cwd())
const dotBlitzCacheExists = fs.existsSync(
join(nodeModulesRoot, ".blitz", "checkUpdateCache.json"),
)
let dotBlitzCache
let shouldRun = true
if (dotBlitzCacheExists) {
dotBlitzCache = fs.readFileSync(join(nodeModulesRoot, ".blitz", "checkUpdateCache.json"))
const now = new Date()
const msBetweenTimes = Math.abs(
superjson.parse<{lastUpdated: Date}>(dotBlitzCache.toString()).lastUpdated.getTime() -
now.getTime(),
)
const hoursBetweenTimes = msBetweenTimes / (60 * 60 * 1000)
shouldRun = hoursBetweenTimes > 24
}
if (shouldRun) {
let errors: {message: string; instructions: string}[] = []
try {
const blitzResponse = await fetch.default(returnNpmEndpoint("blitz"))
const remoteBlitzVersions = (await blitzResponse.json()) as Record<string, string>
const blitzNextResponse = await fetch.default(returnNpmEndpoint("@blitzjs/next"))
const remoteBlitzNextVersions = (await blitzNextResponse.json()) as Record<string, string>
const blitzAuthResponse = await fetch.default(returnNpmEndpoint("@blitzjs/auth"))
const remoteBlitzAuthVersions = (await blitzAuthResponse.json()) as Record<string, string>
const blitzRpcResponse = await fetch.default(returnNpmEndpoint("@blitzjs/rpc"))
const remoteBlitzRpcVersions = (await blitzRpcResponse.json()) as Record<string, string>
for (const version of Object.entries(versions)) {
if (version[0] === "globalVersion") {
const versionType = resolveVersionType(version[1] as string)
if (remoteBlitzVersions.hasOwnProperty("beta") && versionType !== "beta") {
errors.push({
message: `blitz(global) (current) ${version[1]} -> (latest) ${remoteBlitzVersions["beta"]}`,
instructions: `${getUpdateString("blitz", "beta", true)}`,
})
} else if (remoteBlitzVersions[versionType] !== version[1]) {
errors.push({
message: `blitz(global) (current) ${version[1]} -> (latest) ${remoteBlitzVersions[versionType]}`,
instructions: `${getUpdateString("blitz", versionType, true)}`,
})
}
} else if (version[0] === "localVersions") {
for (const localVersion of Object.entries(version[1])) {
const versionType = resolveVersionType(localVersion[1] as string)
switch (localVersion[0]) {
case "blitz":
if (remoteBlitzVersions.hasOwnProperty("beta") && versionType !== "beta") {
errors.push({
message: `blitz (current) ${localVersion[1]} -> (latest) ${remoteBlitzVersions["beta"]}`,
instructions: `${getUpdateString("blitz", "beta", false)}`,
})
} else if (remoteBlitzVersions[versionType] !== localVersion[1]) {
errors.push({
message: `blitz (current) ${localVersion[1]} -> (latest) ${remoteBlitzVersions[versionType]}`,
instructions: `${getUpdateString("blitz", versionType, false)}`,
})
}
break
case "blitzAuth":
if (remoteBlitzAuthVersions.hasOwnProperty("beta") && versionType !== "beta") {
errors.push({
message: `@blitzjs/auth (current) ${localVersion[1]} -> (latest) ${remoteBlitzAuthVersions["beta"]}`,
instructions: `${getUpdateString("@blitzjs/auth", "beta", false)}`,
})
} else if (remoteBlitzAuthVersions[versionType] !== localVersion[1]) {
errors.push({
message: `@blitzjs/auth (current) ${localVersion[1]} -> (latest) ${remoteBlitzAuthVersions[versionType]}`,
instructions: `${getUpdateString("@blitzjs/auth", versionType, false)}`,
})
}
break
case "blitzNext":
if (remoteBlitzNextVersions.hasOwnProperty("beta") && versionType !== "beta") {
errors.push({
message: `@blitzjs/next (current) ${localVersion[1]} -> (latest) ${remoteBlitzNextVersions["beta"]}`,
instructions: `${getUpdateString("@blitzjs/next", "beta", false)}`,
})
} else if (remoteBlitzNextVersions[versionType] !== localVersion[1]) {
errors.push({
message: `@blitzjs/next (current) ${localVersion[1]} -> (latest) ${remoteBlitzNextVersions[versionType]}`,
instructions: `${getUpdateString("@blitzjs/next", versionType, false)}`,
})
}
break
case "blitzRpc":
if (remoteBlitzRpcVersions.hasOwnProperty("beta") && versionType !== "beta") {
errors.push({
message: `@blitzjs/rpc (current) ${localVersion[1]} -> (latest) ${remoteBlitzRpcVersions["beta"]}`,
instructions: `${getUpdateString("@blitzjs/rpc", "beta", false)}`,
})
} else if (remoteBlitzRpcVersions[versionType] !== localVersion[1]) {
errors.push({
message: `@blitzjs/rpc (current) ${localVersion[1]} -> (latest) ${remoteBlitzRpcVersions[versionType]}`,
instructions: `${getUpdateString("@blitzjs/rpc", versionType, false)}`,
})
}
break
}
}
}
}
console.log(
boxen.default(
`You are running outdated blitz packages\n\n ${errors
.map((e) => e.message)
.join("\n")} \n\n Run the following to update:\n ${errors
.map((e) => e.instructions)
.join("\n")}`,
{padding: 1},
),
)
const dotBlitz = join(nodeModulesRoot, ".blitz")
fs.writeFileSync(
join(dotBlitz, "checkUpdateCache.json"),
superjson.stringify({lastUpdated: new Date()}),
)
} catch (err) {
if (err instanceof fetch.FetchError) {
// TODO: Check if network error and throw otherwise
// pass fetch error
} else {
console.log(err)
}
}
}
}
}

View File

@@ -0,0 +1,14 @@
import {readdirSync, existsSync} from "fs-extra"
import {join} from "path"
export function getPkgManager() {
return readdirSync(process.cwd()).includes("pnpm-lock.yaml")
? "pnpm"
: readdirSync(process.cwd()).includes("yarn-lock.yaml")
? "yarn"
: "npm"
}
export const isInternalBlitzMonorepoDevelopment =
existsSync(join(process.cwd(), "..", "..", "packages", "blitz", "dist", "chunks")) &&
existsSync(join(process.cwd(), "..", "..", "packages", "blitz-next", "dist", "chunks"))

View File

@@ -7,6 +7,7 @@ import {
startCustomServer,
buildCustomServer,
} from "./next-utils"
import {checkLatestVersion} from "./check-latest-version"
import {readBlitzConfig} from "../../server-utils"
export async function build(config: ServerConfig) {
@@ -18,7 +19,7 @@ export async function build(config: ServerConfig) {
export async function dev(config: ServerConfig) {
const {rootFolder, nextBin} = await normalize({...config, env: "dev"})
// void checkLatestVersion()
if (customServerExists()) {
console.log("Using your custom server")

View File

@@ -10,7 +10,7 @@ import type {ServerConfig} from "./config"
const debug = require("debug")("blitz:utils")
export function getProjectRootSync() {
return path.dirname(process.cwd())
return process.cwd()
}
export function getCustomServerPath() {

View File

@@ -0,0 +1,79 @@
import {join} from "path"
import pkgDir from "pkg-dir"
import resolveFrom from "resolve-from"
const globalBlitzPath = resolveFrom(__dirname, "blitz")
const localBlitzPath = resolveFrom.silent(process.cwd(), "blitz")
const localBlitzAuthPath = resolveFrom.silent(process.cwd(), "@blitzjs/auth")
const localBlitzRpcPath = resolveFrom.silent(process.cwd(), "@blitzjs/rpc")
const localBlitzNextPath = resolveFrom.silent(process.cwd(), "@blitzjs/next")
export function readVersions() {
const globalBlitzPkgJsonPath = pkgDir.sync(globalBlitzPath)
const localBlitzPkgJsonPath = pkgDir.sync(localBlitzPath)
const localBlitzAuthPkgJsonPath = pkgDir.sync(localBlitzAuthPath)
const localBlitzNextPkgJsonPath = pkgDir.sync(localBlitzNextPath)
const localBlitzRpcPkgJsonPath = pkgDir.sync(localBlitzRpcPath)
const versions: {
globalVersion?: string
localVersions: {
blitz?: string
blitzAuth?: string
blitzRpc?: string
blitzNext?: string
}
} = {globalVersion: "", localVersions: {}}
// This branch won't run if user does `npx blitz` or `yarn blitz`
if (globalBlitzPkgJsonPath && globalBlitzPkgJsonPath !== localBlitzPkgJsonPath) {
versions.globalVersion = require(join(globalBlitzPkgJsonPath, "package.json")).version
}
if (localBlitzPkgJsonPath) {
versions.localVersions.blitz = require(join(localBlitzPkgJsonPath, "package.json")).version
}
if (localBlitzAuthPkgJsonPath) {
versions.localVersions.blitzAuth = require(join(
localBlitzAuthPkgJsonPath,
"package.json",
)).version
}
if (localBlitzNextPkgJsonPath) {
versions.localVersions.blitzNext = require(join(
localBlitzNextPkgJsonPath,
"package.json",
)).version
}
if (localBlitzRpcPkgJsonPath) {
versions.localVersions.blitzRpc = require(join(
localBlitzRpcPkgJsonPath,
"package.json",
)).version
}
return versions
}
export function resolveVersionType(version: string) {
if (version.includes("alpha")) {
return "alpha" as const
}
if (version.includes("beta")) {
return "beta" as const
}
if (version.includes("danger")) {
return "danger" as const
}
if (version.includes("canary")) {
return "canary" as const
}
return "latest" as const
}

View File

@@ -6,6 +6,7 @@ import {outputFile, readdir} from "fs-extra"
import findUp from "find-up"
import resolveFrom from "resolve-from"
import Watchpack from "watchpack"
import {isInternalBlitzMonorepoDevelopment} from "./helpers"
export const CONFIG_FILE = ".blitz.config.compiled.js"
export const NEXT_CONFIG_FILE = "next.config.js"
export const PHASE_PRODUCTION_SERVER = "phase-production-server"
@@ -152,9 +153,9 @@ const normalizeConfig = (phase: string, config: any) => {
}
const loadConfig = (pagesDir: string) => {
let userConfigModule
try {
const path = join(pagesDir, NEXT_CONFIG_FILE)
// eslint-disable-next-line no-eval -- block webpack from following this module path
userConfigModule = eval("require")(path)
} catch {
@@ -162,6 +163,7 @@ const loadConfig = (pagesDir: string) => {
// In case user does not have custom config
userConfigModule = {}
}
let userConfig = normalizeConfig(
PHASE_PRODUCTION_SERVER,
userConfigModule.default || userConfigModule,
@@ -485,7 +487,6 @@ export function parseDefaultExportName(contents: string): string | null {
export async function generateManifest() {
const config = await loadConfig(process.cwd())
const allRoutes = await collectAllRoutes(process.cwd(), config)
const routes: Record<string, RouteManifestEntry> = {}
for (let {filePath, route, type} of allRoutes) {
@@ -527,10 +528,6 @@ export async function generateManifest() {
})
}
export const isInternalBlitzMonorepoDevelopment = __dirname.match(
/[\\/]packages[\\/]blitz[\\/]dist[\\/]chunks$/,
)
async function findNodeModulesRoot(src: string) {
let root: string
if (isInternalBlitzMonorepoDevelopment) {

View File

@@ -142,3 +142,7 @@ export function prettyMs(ms: number): string {
export function interopDefault(mod: any) {
return mod.default || mod
}
export function truncateString(str: string, maxLength: number): string {
return str.length > maxLength ? str.substring(0, maxLength - 3) + "..." : str
}

View File

@@ -1,5 +1,93 @@
# @blitzjs/codemod
## 2.0.0-alpha.64
### Patch Changes
- Updated dependencies [54db8a46]
- Updated dependencies [62bf12b5]
- blitz@2.0.0-alpha.64
- @blitzjs/generator@2.0.0-alpha.64
## 2.0.0-alpha.63
### Patch Changes
- @blitzjs/generator@2.0.0-alpha.63
- blitz@2.0.0-alpha.63
## 2.0.0-alpha.62
### Patch Changes
- Updated dependencies [365e6709]
- blitz@2.0.0-alpha.62
- @blitzjs/generator@2.0.0-alpha.62
## 2.0.0-alpha.61
### Patch Changes
- Updated dependencies [240f378b]
- blitz@2.0.0-alpha.61
- @blitzjs/generator@2.0.0-alpha.61
## 2.0.0-alpha.60
### Patch Changes
- Updated dependencies [1d863f35]
- blitz@2.0.0-alpha.60
- @blitzjs/generator@2.0.0-alpha.60
## 2.0.0-alpha.59
### Patch Changes
- @blitzjs/generator@2.0.0-alpha.59
- blitz@2.0.0-alpha.59
## 2.0.0-alpha.58
### Patch Changes
- dcdcd040: These are various changes to will make the codemod more dynamic and work with a larger variety of codebases. These fixes are implemented to make the codemod work with flightdeck.
- 7e538ba4: Import ErrorComponent as DefaultErrorComponent
- 8e00605a: Updates the error messages based on if it's a babel parse error or an unexpected error
- Updated dependencies [83b35590]
- Updated dependencies [e339e2fd]
- blitz@2.0.0-alpha.58
- @blitzjs/generator@2.0.0-alpha.58
## 2.0.0-alpha.57
### Patch Changes
- Updated dependencies [3511d5b6]
- blitz@2.0.0-alpha.57
- @blitzjs/generator@2.0.0-alpha.57
## 2.0.0-alpha.56
### Patch Changes
- Updated dependencies [abb1ad5d]
- Updated dependencies [abe2afcc]
- Updated dependencies [0ac6e171]
- Updated dependencies [8bcb471a]
- blitz@2.0.0-alpha.56
- @blitzjs/generator@2.0.0-alpha.56
## 2.0.0-alpha.55
### Patch Changes
- Updated dependencies [8f166a5d]
- Updated dependencies [54a66a95]
- Updated dependencies [ab4d9de7]
- blitz@2.0.0-alpha.55
- @blitzjs/generator@2.0.0-alpha.55
## 2.0.0-alpha.54
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/codemod",
"version": "2.0.0-alpha.54",
"version": "2.0.0-alpha.64",
"scripts": {
"build": "unbuild",
"dev": "watch unbuild src --wait=0.2",
@@ -25,9 +25,9 @@
"@babel/plugin-proposal-class-properties": "7.17.12",
"@babel/plugin-syntax-jsx": "7.17.12",
"@babel/plugin-syntax-typescript": "7.17.12",
"@blitzjs/generator": "2.0.0-alpha.54",
"@blitzjs/generator": "2.0.0-alpha.64",
"arg": "5.0.1",
"blitz": "2.0.0-alpha.54",
"blitz": "2.0.0-alpha.64",
"chalk": "^4.1.0",
"cross-spawn": "7.0.3",
"debug": "4.3.3",
@@ -42,7 +42,7 @@
"@types/jscodeshift": "0.11.2",
"@types/node": "17.0.16",
"ast-types": "0.14.2",
"unbuild": "0.6.9",
"unbuild": "0.7.6",
"watch": "1.0.2"
},
"publishConfig": {

View File

@@ -184,6 +184,10 @@ const upgradeLegacy = async () => {
BlitzLayout: "@blitzjs/next",
}
const renames: Record<string, string> = {
ErrorComponent: "DefaultErrorComponent",
}
getAllFiles(appDir, [], [], [".ts", ".tsx", ".js", ".jsx"]).forEach((filename) => {
const program = getCollectionFromSource(path.resolve(appDir, filename))
const parsedProgram = program.get()
@@ -197,7 +201,13 @@ const upgradeLegacy = async () => {
? specifier.imported.value
: specifier.imported.name
if (importedName in specialImports) {
addNamedImport(program, importedName, specialImports[importedName]!)
addNamedImport(
program,
importedName,
specialImports[importedName]!,
undefined,
renames[importedName],
)
removeImport(program, importedName, "blitz")
}
})
@@ -433,6 +443,7 @@ const upgradeLegacy = async () => {
j.Identifier,
(node) => node.name === "middleware",
)
if (middlewareArray.length) {
const middlewares = middlewareArray
.get()
@@ -451,7 +462,12 @@ const upgradeLegacy = async () => {
let importStatements = []
for (let nodes of blitzConfigProgram.get().value.program.body) {
if (nodes.type === "ImportDeclaration") {
if (nodes.source.value !== "blitz") {
// Find duplicates
const dup = blitzServerProgram.find(
j.ImportDeclaration,
(node) => node.source.value === nodes.source.value,
)
if (nodes.source.value !== "blitz" && !dup.length) {
importStatements.push(nodes)
}
}
@@ -466,11 +482,7 @@ const upgradeLegacy = async () => {
}
}
importStatements.forEach((s) =>
blitzServerProgram
.get()
.value.program.body.unshift(j.variableDeclaration(s.kind, s.declarations)),
)
importStatements.forEach((s) => blitzServerProgram.get().value.program.body.unshift(s))
fs.writeFileSync(
`${appDir}/blitz-server.${isTypescript ? "ts" : "js"}`,
@@ -741,40 +753,50 @@ const upgradeLegacy = async () => {
const parsedProgram = program.get()
const findRouterQueryImport = findImport(program, "next/router")
findRouterQueryImport?.forEach((node) => {
const getNode = node.get()
getNode.value.specifiers.slice().forEach((specifier: any, index: number) => {
const importedName =
specifier.imported.type === "StringLiteral"
? specifier.imported.value
: specifier.imported.name
if (importedName === "useRouterQuery") {
addNamedImport(program, "useRouter", "next/router")
getNode.value.specifiers.splice(index, 1)
// Removed left overs
if (!getNode.value.specifiers?.length) {
const index = parsedProgram.value.program.body.indexOf(getNode.value)
parsedProgram.value.program.body.splice(index, 1)
if (findRouterQueryImport?.length) {
findRouterQueryImport?.forEach((node) => {
const getNode = node.get()
getNode.value.specifiers.slice().forEach((specifier: any, index: number) => {
const importedName = (): string | null => {
if (specifier.imported) {
if (specifier.imported.type === "StringLiteral") {
return specifier.imported.value
} else if (specifier.imported.type === "Identifier") {
return specifier.imported.name
}
}
return null
}
}
if (importedName() && importedName() === "useRouterQuery") {
addNamedImport(program, "useRouter", "next/router")
getNode.value.specifiers.splice(index, 1)
// Removed left overs
if (!getNode.value.specifiers?.length) {
const index = parsedProgram.value.program.body.indexOf(getNode.value)
parsedProgram.value.program.body.splice(index, 1)
}
}
})
})
})
const findCallUseRouterQuery = program.find(
j.CallExpression,
(node) => node.callee.name === "useRouterQuery",
)
findCallUseRouterQuery.forEach((call) => {
const nodePath = call.get()
nodePath.parentPath.value.init = j.expressionStatement(
j.memberExpression(
j.callExpression(j.identifier("useRouter"), []),
j.identifier("query"),
),
const findCallUseRouterQuery = program.find(
j.CallExpression,
(node) => node.callee.name === "useRouterQuery",
)
})
findCallUseRouterQuery.forEach((call) => {
const nodePath = call.get()
nodePath.parentPath.value.init = j.expressionStatement(
j.memberExpression(
j.callExpression(j.identifier("useRouter"), []),
j.identifier("query"),
),
)
})
fs.writeFileSync(filepath, program.toSource())
fs.writeFileSync(filepath, program.toSource())
}
})
getAllFiles(appDir, [], [], [".ts", ".tsx", ".js", ".jsx"]).forEach((file) => {
@@ -786,45 +808,54 @@ const upgradeLegacy = async () => {
j.ImportDeclaration,
(node) => node.source.value === "next/router",
)
findRouterQueryImport.forEach((node) => {
const getNode = node.get()
getNode.value.specifiers.slice().forEach((specifier: any, index: number) => {
const importedName =
specifier.imported.type === "StringLiteral"
? specifier.imported.value
: specifier.imported.name
if (importedName === "useRouterQuery") {
parsedProgram.value.program.body.unshift(
j.importDeclaration(
[j.importSpecifier(j.identifier("useRouter"))],
j.stringLiteral("next/router"),
),
)
getNode.value.specifiers.splice(index, 1)
// Removed left overs
if (!getNode.value.specifiers?.length) {
const index = parsedProgram.value.program.body.indexOf(getNode.value)
parsedProgram.value.program.body.splice(index, 1)
if (findRouterQueryImport?.length) {
findRouterQueryImport.forEach((node) => {
const getNode = node.get()
getNode.value.specifiers.slice().forEach((specifier: any, index: number) => {
const importedName = (): string | null => {
if (specifier.imported) {
if (specifier.imported.type === "StringLiteral") {
return specifier.imported.value
} else if (specifier.imported.type === "Identifier") {
return specifier.imported.name
}
}
return null
}
}
if (importedName() && importedName() === "useRouterQuery") {
parsedProgram.value.program.body.unshift(
j.importDeclaration(
[j.importSpecifier(j.identifier("useRouter"))],
j.stringLiteral("next/router"),
),
)
getNode.value.specifiers.splice(index, 1)
// Removed left overs
if (!getNode.value.specifiers?.length) {
const index = parsedProgram.value.program.body.indexOf(getNode.value)
parsedProgram.value.program.body.splice(index, 1)
}
}
})
})
})
const findCallUseRouterQuery = program.find(
j.CallExpression,
(node) => node.callee.name === "useRouterQuery",
)
findCallUseRouterQuery.forEach((call) => {
const nodePath = call.get()
nodePath.parentPath.value.init = j.expressionStatement(
j.memberExpression(
j.callExpression(j.identifier("useRouter"), []),
j.identifier("query"),
),
const findCallUseRouterQuery = program.find(
j.CallExpression,
(node) => node.callee.name === "useRouterQuery",
)
})
findCallUseRouterQuery.forEach((call) => {
const nodePath = call.get()
nodePath.parentPath.value.init = j.expressionStatement(
j.memberExpression(
j.callExpression(j.identifier("useRouter"), []),
j.identifier("query"),
),
)
})
fs.writeFileSync(filepath, program.toSource())
fs.writeFileSync(filepath, program.toSource())
}
})
},
})
@@ -907,9 +938,11 @@ const upgradeLegacy = async () => {
)
const documentHead = program
.find(j.Identifier, (node) => node.name === "DocumentHead")
.find(j.JSXElement, (node) => node.openingElement.name.name === "DocumentHead")
.get()
documentHead.value.name = "Head"
documentHead.value.openingElement.name.name = "Head"
documentHead.value.closingElement.name.name = "Head"
const blitzScript = program.find(j.Identifier, (node) => node.name === "BlitzScript").get()
blitzScript.value.name = "NextScript"
@@ -959,15 +992,20 @@ const upgradeLegacy = async () => {
const program = getCollectionFromSource(file)
const defaultExportPath = findDefaultExportPath(program)
if (!defaultExportPath) {
return
if (defaultExportPath) {
const {node} = defaultExportPath
if (node.declaration.type === "Identifier") {
node.declaration = j.callExpression(j.identifier("api"), [node.declaration as any])
addNamedImport(program, "api", "app/blitz-server")
} else if (node.declaration.type === "FunctionDeclaration") {
node.declaration = j.template.expression`api(${node.declaration})`
addNamedImport(program, "api", "app/blitz-server")
}
fs.writeFileSync(path.join(path.resolve(file)), program.toSource())
}
const {node} = defaultExportPath
node.declaration = j.callExpression(j.identifier("api"), [node.declaration as any])
addNamedImport(program, "api", "app/blitz-server")
fs.writeFileSync(path.join(path.resolve(file)), program.toSource())
})
}
},
@@ -1118,8 +1156,23 @@ const upgradeLegacy = async () => {
try {
await step.action()
} catch (err) {
const error = err as {code: string} | string
spinner.fail(`${step.name}`)
log.error(err as string)
log.error(error as string)
if (error && typeof error === "object" && error.code === "BABEL_PARSE_ERROR") {
log.error(
log.withBrand(
"Don't panic, go to the file with the error & manually fix it. Then run the codemod again. It will continue where it left off.",
),
)
} else {
log.error(
log.withBrand(
"This is an unexpected error. Please ask for help in the discord #general-help channel. https://discord.blitzjs.com",
),
)
}
failedAt = index + 1
fs.writeJsonSync(".migration.json", {
failedAt,

View File

@@ -168,6 +168,7 @@ export function addNamedImport(
importStatement: string,
importFrom: string,
defaultSpecifier?: boolean,
asImport?: string,
) {
const existingImport = program.find(
j.ImportDeclaration,
@@ -183,7 +184,11 @@ export function addNamedImport(
if (existingSpecifier.length) {
return
}
existingImport.get().value.specifiers.push(j.importSpecifier(j.identifier(importStatement)))
existingImport
.get()
.value.specifiers.push(
j.importSpecifier(j.identifier(importStatement), asImport ? j.identifier(asImport) : null),
)
} else {
program
.get()
@@ -194,7 +199,12 @@ export function addNamedImport(
j.stringLiteral(importFrom),
)
: j.importDeclaration(
[j.importSpecifier(j.identifier(importStatement))],
[
j.importSpecifier(
j.identifier(importStatement),
asImport ? j.identifier(asImport) : null,
),
],
j.stringLiteral(importFrom),
),
)
@@ -224,7 +234,16 @@ export function getAllFiles(
skipDirs?: string[],
allowedExt?: string[],
) {
let currentFiles = fs.readdirSync(dirPath)
let currentFiles: string[] = []
try {
currentFiles = fs.readdirSync(dirPath)
} catch (e: any) {
if (e.code === "ENOENT") {
return []
}
throw e
}
currentFiles.forEach((file) => {
if (fs.statSync(dirPath + "/" + file).isDirectory()) {

View File

@@ -1,5 +1,25 @@
# @blitzjs/config
## 2.0.0-alpha.64
## 2.0.0-alpha.63
## 2.0.0-alpha.62
## 2.0.0-alpha.61
## 2.0.0-alpha.60
## 2.0.0-alpha.59
## 2.0.0-alpha.58
## 2.0.0-alpha.57
## 2.0.0-alpha.56
## 2.0.0-alpha.55
## 2.0.0-alpha.54
## 2.0.0-alpha.53

View File

@@ -1,7 +1,7 @@
{
"name": "@blitzjs/config",
"private": true,
"version": "2.0.0-alpha.54",
"version": "2.0.0-alpha.64",
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "5.9.1",

View File

@@ -1,5 +1,33 @@
# @blitzjs/generator
## 2.0.0-alpha.64
## 2.0.0-alpha.63
## 2.0.0-alpha.62
## 2.0.0-alpha.61
## 2.0.0-alpha.60
## 2.0.0-alpha.59
## 2.0.0-alpha.58
### Patch Changes
- e339e2fd: Add hoist pattern entry for react-query in new app templates
## 2.0.0-alpha.57
## 2.0.0-alpha.56
## 2.0.0-alpha.55
### Patch Changes
- ab4d9de7: Don't try to copy RPC API endpoint in templates that don't have it
## 2.0.0-alpha.54
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@blitzjs/generator",
"version": "2.0.0-alpha.54",
"version": "2.0.0-alpha.64",
"scripts": {
"dev": "watch unbuild src --wait=0.2",
"build": "unbuild && pnpm build:templates",
@@ -45,7 +45,7 @@
"vinyl": "2.2.1"
},
"devDependencies": {
"@blitzjs/config": "2.0.0-alpha.54",
"@blitzjs/config": "2.0.0-alpha.64",
"@juanm04/cpx": "2.0.1",
"@types/babel__core": "7.1.19",
"@types/diff": "5.0.2",

View File

@@ -30,6 +30,7 @@ export interface AppGeneratorOptions extends GeneratorOptions {
form?: "React Final Form" | "React Hook Form" | "Formik"
onPostInstall?: () => Promise<void>
}
type PkgManager = "npm" | "yarn" | "pnpm"
export class AppGenerator extends Generator<AppGeneratorOptions> {
@@ -76,10 +77,14 @@ export class AppGenerator extends Generator<AppGeneratorOptions> {
this.destinationPath(this.options.useTs ? "package.ts.json" : "package.js.json"),
this.destinationPath("package.json"),
)
this.fs.move(
this.destinationPath(`pages/api/rpc/blitzrpcroute.${this.options.useTs ? "ts" : "js"}`),
this.destinationPath(`pages/api/rpc/[[...blitz]].${this.options.useTs ? "ts" : "js"}`),
)
const rpcEndpointPath = `pages/api/rpc/blitzrpcroute.${this.options.useTs ? "ts" : "js"}`
if (this.fs.exists(rpcEndpointPath)) {
this.fs.move(
this.destinationPath(rpcEndpointPath),
this.destinationPath(`pages/api/rpc/[[...blitz]].${this.options.useTs ? "ts" : "js"}`),
)
}
if (!this.options.template.skipForms) {
this.updateForms()
@@ -286,6 +291,7 @@ export class AppGenerator extends Generator<AppGeneratorOptions> {
}
commitSpinner.succeed()
}
private updateForms() {
const pkg = this.fs.readJSON(this.destinationPath("package.json")) as
| Record<string, any>

View File

@@ -1,7 +1,8 @@
import Head from "next/head"
import React, { FC } from "react"
import React, {FC} from "react"
import {BlitzLayout} from "@blitzjs/next"
const Layout: FC<{ title?: string; children?: React.ReactNode }> = ({ title, children }) => {
const Layout: BlitzLayout<{title?: string; children?: React.ReactNode}> = ({title, children}) => {
return (
<>
<Head>

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