Compare commits
83 Commits
@blitzjs/c
...
v2.2.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f5ca746c6 | ||
|
|
aa033af9f1 | ||
|
|
c7bb5864f3 | ||
|
|
d174c014f3 | ||
|
|
ab455acf0b | ||
|
|
bddc1d88f5 | ||
|
|
ce1a603b26 | ||
|
|
125370a1d0 | ||
|
|
39c8c0ab80 | ||
|
|
fbf5e51a78 | ||
|
|
9cda1be11b | ||
|
|
5b20ce6282 | ||
|
|
0fc2d71a18 | ||
|
|
3fa3a4ef30 | ||
|
|
565db3c5a8 | ||
|
|
ae04524b4c | ||
|
|
38d320fd28 | ||
|
|
8723d0053c | ||
|
|
ce23d4ed09 | ||
|
|
b6c9c4ae6d | ||
|
|
0b3286468b | ||
|
|
50f17d21ce | ||
|
|
57add5f1c5 | ||
|
|
3f239e78b6 | ||
|
|
3bf90c167c | ||
|
|
56bd32b553 | ||
|
|
2711291e97 | ||
|
|
ab29c5bf3f | ||
|
|
a096f2cd80 | ||
|
|
ded16b325b | ||
|
|
4494662d6d | ||
|
|
9a0ba87d15 | ||
|
|
c80ce51d36 | ||
|
|
b505933a16 | ||
|
|
d53da39cbf | ||
|
|
e1055f7366 | ||
|
|
3b10b13e6b | ||
|
|
25601754a4 | ||
|
|
e0cfa328ec | ||
|
|
f02469aac8 | ||
|
|
2f3c552ac3 | ||
|
|
721461a7b9 | ||
|
|
3193bdea48 | ||
|
|
318e9740d6 | ||
|
|
0df368308b | ||
|
|
ad94bee56a | ||
|
|
5a14306f7b | ||
|
|
6e8eeb1514 | ||
|
|
5e61a16815 | ||
|
|
77555468f3 | ||
|
|
22e402af01 | ||
|
|
19afc57530 | ||
|
|
b7dab1d800 | ||
|
|
ee7bf87ec0 | ||
|
|
451ead089c | ||
|
|
5d9570f7f4 | ||
|
|
178c152b2c | ||
|
|
bbe1a54d7a | ||
|
|
9b075dbb47 | ||
|
|
60a4d90c86 | ||
|
|
a674897601 | ||
|
|
5a587a6c31 | ||
|
|
744242f25b | ||
|
|
0f5297f1aa | ||
|
|
76a2544f9d | ||
|
|
6f44c2334e | ||
|
|
8a417533f6 | ||
|
|
6f54841b7a | ||
|
|
e8f564ea66 | ||
|
|
71b9950037 | ||
|
|
28a79040e4 | ||
|
|
dd604c7675 | ||
|
|
0a8d4bfdaf | ||
|
|
f25aac08c0 | ||
|
|
a09685a63a | ||
|
|
595f400e9a | ||
|
|
6f333ee643 | ||
|
|
956a739e83 | ||
|
|
47722e0456 | ||
|
|
2f5c8a3a0d | ||
|
|
4ac47ff2a1 | ||
|
|
e8fd12e4f9 | ||
|
|
89d3d0279e |
@@ -4014,6 +4014,126 @@
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "LeonMueller-OneAndOnly",
|
||||
"name": "Leonidas",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/77194479?v=4",
|
||||
"profile": "https://flow-office.eu/",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Doc0x1",
|
||||
"name": "Doc0x1",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/19937034?v=4",
|
||||
"profile": "https://hacknex.us",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lmisea",
|
||||
"name": "Luis Isea",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/106825636?v=4",
|
||||
"profile": "https://github.com/lmisea",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "gengjiawen",
|
||||
"name": "Jiawen Geng",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3759816?v=4",
|
||||
"profile": "https://www.gengjiawen.com",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "timneutkens",
|
||||
"name": "Tim Neutkens",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6324199?v=4",
|
||||
"profile": "https://timn.tech",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "RedYetiDev",
|
||||
"name": "Aviv Keller",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/38299977?v=4",
|
||||
"profile": "https://redyetidev.github.io",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "bezalel6",
|
||||
"name": "bezalel6",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/51681171?v=4",
|
||||
"profile": "https://github.com/bezalel6",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cherniavskii",
|
||||
"name": "Andrew Cherniavskii",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/13808724?v=4",
|
||||
"profile": "cherniavskii.com",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "doe-base",
|
||||
"name": "Daniel Idoko",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/95912955?v=4",
|
||||
"profile": "https://danielidoko-r3zt.vercel.app/",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fungilation",
|
||||
"name": "Gary Fung",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3803466?v=4",
|
||||
"profile": "https://garyfung.medium.com",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rene-demonsters",
|
||||
"name": "René Vlugt",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/20322259?v=4",
|
||||
"profile": "https://github.com/rene-demonsters",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kksandr7",
|
||||
"name": "Ksandr",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/132560756?v=4",
|
||||
"profile": "https://www.drupal.org/u/kksandr",
|
||||
"contributions": [
|
||||
"doc",
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
|
||||
5
.changeset/stale-keys-guess.md
Normal file
5
.changeset/stale-keys-guess.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@blitzjs/auth": patch
|
||||
---
|
||||
|
||||
fix: Overriden custom cookies with pages router
|
||||
24
.github/workflows/main.yml
vendored
24
.github/workflows/main.yml
vendored
@@ -17,13 +17,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
- uses: pnpm/action-setup@v4.0.0
|
||||
with:
|
||||
version: 8.6.5
|
||||
version: 8.6.6
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -38,13 +38,13 @@ jobs:
|
||||
name: Build
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
- uses: pnpm/action-setup@v4.0.0
|
||||
with:
|
||||
version: 8.6.5
|
||||
version: 8.6.6
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- name: Build
|
||||
@@ -68,14 +68,14 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
with:
|
||||
version: 8.6.5
|
||||
version: 8.6.6
|
||||
|
||||
- name: Setup node@16
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -129,15 +129,15 @@ jobs:
|
||||
|
||||
- name: Setup PNPM
|
||||
if: matrix.folder != 'next-13-app-dir' || matrix.os != 'windows-latest'
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
uses: pnpm/action-setup@v4.0.0
|
||||
with:
|
||||
version: 8.6.5
|
||||
version: 8.6.6
|
||||
|
||||
- name: Setup node@18
|
||||
if: matrix.folder != 'next-13-app-dir' || matrix.os != 'windows-latest'
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
|
||||
28
.github/workflows/pr-release.yml
vendored
28
.github/workflows/pr-release.yml
vendored
@@ -22,23 +22,29 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: resolve pr refs
|
||||
id: refs
|
||||
uses: eficode/resolve-pr-refs@main
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Fetch PR information
|
||||
id: pr_info
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
pr="$(gh api repos/${{ github.repository }}/pulls/${{ github.event.issue.number }})"
|
||||
head_sha="$(echo "$pr" | jq -r .head.sha)"
|
||||
|
||||
echo "head_sha=$head_sha" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ steps.refs.outputs.head_ref }}
|
||||
ref: ${{ steps.pr_info.outputs.head_sha }}
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.1
|
||||
uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
|
||||
with:
|
||||
version: 8.9.0
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version: 20
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
cache: "pnpm"
|
||||
|
||||
@@ -96,5 +102,5 @@ jobs:
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: 'Snapshot Release: ' + process.env.MESSAGE
|
||||
body: `Snapshot Release ${{steps.getSnapshotName.outputs.result}}`
|
||||
})
|
||||
|
||||
21
.github/workflows/release.yml
vendored
21
.github/workflows/release.yml
vendored
@@ -19,12 +19,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js 16.x
|
||||
uses: actions/setup-node@v2
|
||||
- name: Setup Node.js 20.x
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 20.x
|
||||
|
||||
- name: Creating .npmrc
|
||||
run: |
|
||||
@@ -37,8 +37,10 @@ jobs:
|
||||
- name: Pre-publish
|
||||
uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
|
||||
with:
|
||||
version: 6.32.6
|
||||
- run: pnpm install --no-frozen-lockfile
|
||||
version: 8.9.0
|
||||
- run: pnpm install
|
||||
env:
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
- run: pnpm build
|
||||
|
||||
- name: Create Release Pull Request
|
||||
@@ -49,10 +51,3 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
# - name: Github Release
|
||||
# uses: release-drafter/release-drafter@v5.19.0
|
||||
# with:
|
||||
# config-name: release-drafter.yml
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
16.13.2
|
||||
21
README.md
21
README.md
@@ -6,7 +6,7 @@
|
||||
<img alt="" src="https://img.shields.io/badge/Join%20our%20community-6700EB.svg?style=for-the-badge&labelColor=000000&logoWidth=20&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQ9SURBVHgB7d3dVdtAEIbhcSpICUoH0IEogQqSVBBSAU4FSSpIOoAORAfQgSghHXzZ1U/YcMD4R9rZmf2ec3y448LyiNf27iLiGIAmPLrweC9Un3DhrzG6EarLNP09nlwJ1SOZ/lQr5N80/S/p2QMVCBf5N17XCfm1Y/rBHqjAG9PPHvBsz+mf9WAP+HLA9M/YA14cOP2payH7jpj+VCtk1wnTP+vj7xCy6cTpn7EHLMLp059iD1iD8eveJbVCNsSLheX1YA/YgOWnf8YeKB3Wmf7Ud6Fy4f/FHmtpxbl3YlC4MJ/Cj0bWdwPnPbARg+L0S54XQHS32WwuxClzd4CM0z9rPfeAuTtA5ulPXYQ7wZ04Y+oOoDD9KZc9YOoOoDj9s4dwFzgXR6w1wIPoOvPWA9buAHEJ173o3gWiy3AnuBUHLEbgmYwvAk1/wuM8vAgexThzbwPDkx7/DHwVXfFOxP2GmsKd4Ab6zPeAyU8CI7AHFmH2BRCBPXAyk18GzUrqAXCTiR4ssyj0VFw/oCU8+e+RZ33AWz6KMaYbIIWxB+JSLs1bsbkeMN0AqakHvoku9oA2sAfqBvbAQdw0QArsgb25aYBUQT3QgT2gB+yBuqGcHij2UCqXDZACe2Anlw2QYg/QAOyBuoE98CL3DZDCuK4/rh/Q7oGL6U+TOvcNkJoijN8X1C48+T+g75eQDrAH/qmqAVJgDwyqaoAUe4AGYA/UDZX3QLUNkEIZPRCd5+6BahsgVUgPROwBTSijB7jpVAvGHriHvmw9wAZ4BpX1ABvgmakHtPcbRuwBTWAPULgAV9D/jKDY9YRvwvgEaurD44uQHvAol7qBW7WKluVtIHiUS7GyvA0s6CiXDnxrpQfsgbqBS7GKk/2jYHCrVlGyfxTMrVo0ALdq1Q3sgSKofh0M9oA61a+D2QM0AHugbmAPqClmSRjK2apVVQ8UsySsoK1aHdgDesCtWnUDeyCrIpeFg1u3sylyWTi3btMA7IG6gT2wuuK3hoE9sKrit4YVslWLPaAN7IG6ocKt2zmY2h4O9sDiTG0PZw/QANy6XTewBxZj9ogYVHy025LMHhEz9cBn0We6B0yfERReBLfhx0/R1YQHPx/QBPbA0VwcEwf2wNFcHBPHHjiem3MC2QPHcXdSaJjA+KfgTPQ8hhfjBzHC40mhlzJ+Xq9lK4a4PCs43AVaGTed5mZq+iOXZwWHi3AnOj2wFWNcnxYe7gTxLtBKHuamP/J+Wnh8a5irB7ZC5Yk9gPX1QuXC+usHWqGyhYvUYR0a7zboUOFCNVhnk0krZAOW7wFOvzXhom2xnEbIHizTA1wEYhWW6YFGyC6c1gOcfg9wfA80Qj7g8B7g9HuCww+haIR8wf49wOn3Cvv9k8tGyC/s7gFOv3fY3QONkH+v9MBWqB7PeqDn9FcIT//kcitUn6kHOu/T/xfWzlQy3dEHhwAAAABJRU5ErkJggg==">
|
||||
</a>
|
||||
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||
<a aria-label="All Contributors" href="#contributors-"><img alt="" src="https://img.shields.io/badge/all_contributors-423-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-435-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/main/LICENSE">
|
||||
<img alt="" src="https://img.shields.io/npm/l/blitz.svg?style=for-the-badge&labelColor=000000&color=blue">
|
||||
@@ -79,6 +79,9 @@ Your financial contributions help ensure Blitz continues to be developed and mai
|
||||
</a></td>
|
||||
<td><a aria-label="Simon Lammes" href="https://github.com/simon-lammes">
|
||||
<img alt="" src="https://avatars.githubusercontent.com/u/46446421?v=4" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="Route Optimizer and Route Planning Software" href="https://route4me.com">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/route4me.png" width="40px"/>
|
||||
</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -747,6 +750,22 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<td align="center"><a href="https://github.com/Zamfi99"><img src="https://avatars.githubusercontent.com/u/19189337?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zamfira Costin-Andrei</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Zamfi99" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Zamfi99" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/potikhanovsergey"><img src="https://avatars.githubusercontent.com/u/71494201?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sergey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=potikhanovsergey" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/papsavas"><img src="https://avatars.githubusercontent.com/u/50584606?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Savvas Papageorgiadis</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=papsavas" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=papsavas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://flow-office.eu/"><img src="https://avatars.githubusercontent.com/u/77194479?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Leonidas</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=LeonMueller-OneAndOnly" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=LeonMueller-OneAndOnly" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://hacknex.us"><img src="https://avatars.githubusercontent.com/u/19937034?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Doc0x1</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Doc0x1" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Doc0x1" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/lmisea"><img src="https://avatars.githubusercontent.com/u/106825636?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Luis Isea</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lmisea" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=lmisea" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.gengjiawen.com"><img src="https://avatars.githubusercontent.com/u/3759816?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jiawen Geng</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gengjiawen" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=gengjiawen" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://timn.tech"><img src="https://avatars.githubusercontent.com/u/6324199?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tim Neutkens</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=timneutkens" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=timneutkens" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=timneutkens" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://redyetidev.github.io"><img src="https://avatars.githubusercontent.com/u/38299977?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aviv Keller</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=RedYetiDev" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/bezalel6"><img src="https://avatars.githubusercontent.com/u/51681171?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bezalel6</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bezalel6" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=bezalel6" title="Code">💻</a></td>
|
||||
<td align="center"><a href="cherniavskii.com"><img src="https://avatars.githubusercontent.com/u/13808724?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Cherniavskii</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cherniavskii" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://danielidoko-r3zt.vercel.app/"><img src="https://avatars.githubusercontent.com/u/95912955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Idoko</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://garyfung.medium.com"><img src="https://avatars.githubusercontent.com/u/3803466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gary Fung</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fungilation" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=fungilation" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rene-demonsters"><img src="https://avatars.githubusercontent.com/u/20322259?v=4?s=100" width="100px;" alt=""/><br /><sub><b>René Vlugt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rene-demonsters" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rene-demonsters" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.drupal.org/u/kksandr"><img src="https://avatars.githubusercontent.com/u/132560756?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ksandr</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kksandr7" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=kksandr7" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -1,5 +1,209 @@
|
||||
# next-blitz-auth
|
||||
|
||||
## 0.1.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [aa033af9f]
|
||||
- @blitzjs/auth@2.2.3
|
||||
- @blitzjs/rpc@2.2.3
|
||||
- @blitzjs/next@2.2.3
|
||||
- @blitzjs/config@2.2.3
|
||||
- blitz@2.2.3
|
||||
|
||||
## 0.1.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ab455acf0]
|
||||
- @blitzjs/auth@2.2.2
|
||||
- @blitzjs/rpc@2.2.2
|
||||
- @blitzjs/next@2.2.2
|
||||
- @blitzjs/config@2.2.2
|
||||
- blitz@2.2.2
|
||||
|
||||
## 0.1.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
- @blitzjs/auth@2.2.1
|
||||
- @blitzjs/next@2.2.1
|
||||
- @blitzjs/rpc@2.2.1
|
||||
- @blitzjs/config@2.2.1
|
||||
|
||||
## 0.1.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
- @blitzjs/auth@2.2.0
|
||||
- @blitzjs/next@2.2.0
|
||||
- @blitzjs/rpc@2.2.0
|
||||
- @blitzjs/config@2.2.0
|
||||
|
||||
## 0.1.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ce23d4ed0]
|
||||
- @blitzjs/next@2.1.4
|
||||
- blitz@2.1.4
|
||||
- @blitzjs/auth@2.1.4
|
||||
- @blitzjs/rpc@2.1.4
|
||||
- @blitzjs/config@2.1.4
|
||||
|
||||
## 0.1.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- @blitzjs/auth@2.1.3
|
||||
- @blitzjs/next@2.1.3
|
||||
- @blitzjs/rpc@2.1.3
|
||||
- blitz@2.1.3
|
||||
- @blitzjs/config@2.1.3
|
||||
|
||||
## 0.1.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.2
|
||||
- @blitzjs/auth@2.1.2
|
||||
- @blitzjs/next@2.1.2
|
||||
- @blitzjs/rpc@2.1.2
|
||||
- @blitzjs/config@2.1.2
|
||||
|
||||
## 0.1.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9a0ba87d1]
|
||||
- @blitzjs/rpc@2.1.1
|
||||
- blitz@2.1.1
|
||||
- @blitzjs/next@2.1.1
|
||||
- @blitzjs/auth@2.1.1
|
||||
- @blitzjs/config@2.1.1
|
||||
|
||||
## 0.1.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [d53da39cb]
|
||||
- Updated dependencies [3b10b13e6]
|
||||
- blitz@2.1.0
|
||||
- @blitzjs/auth@2.1.0
|
||||
- @blitzjs/next@2.1.0
|
||||
- @blitzjs/rpc@2.1.0
|
||||
- @blitzjs/config@2.1.0
|
||||
|
||||
## 0.1.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [318e9740d]
|
||||
- @blitzjs/auth@2.0.10
|
||||
- blitz@2.0.10
|
||||
- @blitzjs/rpc@2.0.10
|
||||
- @blitzjs/next@2.0.10
|
||||
- @blitzjs/config@2.0.10
|
||||
|
||||
## 0.1.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5a14306f7]
|
||||
- @blitzjs/next@2.0.9
|
||||
- @blitzjs/rpc@2.0.9
|
||||
- blitz@2.0.9
|
||||
- @blitzjs/auth@2.0.9
|
||||
- @blitzjs/config@2.0.9
|
||||
|
||||
## 0.1.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e61a1681]
|
||||
- Updated dependencies [77555468f]
|
||||
- @blitzjs/next@2.0.8
|
||||
- blitz@2.0.8
|
||||
- @blitzjs/auth@2.0.8
|
||||
- @blitzjs/rpc@2.0.8
|
||||
- @blitzjs/config@2.0.8
|
||||
|
||||
## 0.1.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ee7bf87ec]
|
||||
- Updated dependencies [178c152b2]
|
||||
- blitz@2.0.7
|
||||
- @blitzjs/next@2.0.7
|
||||
- @blitzjs/rpc@2.0.7
|
||||
- @blitzjs/auth@2.0.7
|
||||
- @blitzjs/config@2.0.7
|
||||
|
||||
## 0.1.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [76a2544f9]
|
||||
- Updated dependencies [5a587a6c3]
|
||||
- blitz@2.0.6
|
||||
- @blitzjs/auth@2.0.6
|
||||
- @blitzjs/next@2.0.6
|
||||
- @blitzjs/rpc@2.0.6
|
||||
- @blitzjs/config@2.0.6
|
||||
|
||||
## 0.1.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [6f54841b7]
|
||||
- Updated dependencies [8a417533f]
|
||||
- @blitzjs/auth@2.0.5
|
||||
- blitz@2.0.5
|
||||
- @blitzjs/rpc@2.0.5
|
||||
- @blitzjs/next@2.0.5
|
||||
- @blitzjs/config@2.0.5
|
||||
|
||||
## 0.1.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [dd604c767]
|
||||
- Updated dependencies [28a79040e]
|
||||
- @blitzjs/auth@2.0.4
|
||||
- blitz@2.0.4
|
||||
- @blitzjs/next@2.0.4
|
||||
- @blitzjs/rpc@2.0.4
|
||||
- @blitzjs/config@2.0.4
|
||||
|
||||
## 0.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [2f5c8a3a0]
|
||||
- @blitzjs/next@2.0.3
|
||||
- @blitzjs/rpc@2.0.3
|
||||
- blitz@2.0.3
|
||||
- @blitzjs/auth@2.0.3
|
||||
- @blitzjs/config@2.0.3
|
||||
|
||||
## 0.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e8fd12e4f]
|
||||
- @blitzjs/rpc@2.0.2
|
||||
- blitz@2.0.2
|
||||
- @blitzjs/next@2.0.2
|
||||
- @blitzjs/auth@2.0.2
|
||||
- @blitzjs/config@2.0.2
|
||||
|
||||
## 0.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
const {withBlitz} = require("@blitzjs/next")
|
||||
|
||||
const loaderClient = require.resolve("@blitzjs/rpc/dist/loader-client.cjs")
|
||||
const loaderServer = require.resolve("@blitzjs/rpc/dist/loader-server.cjs")
|
||||
const loaderServerResolvers = require.resolve("@blitzjs/rpc/dist/loader-server-resolvers.cjs")
|
||||
|
||||
console.log("loaderClient", loaderClient)
|
||||
console.log("loaderServer", loaderServer)
|
||||
console.log("loaderServerResolvers", loaderServerResolvers)
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-blitz-auth",
|
||||
"version": "0.1.2",
|
||||
"version": "0.1.20",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"blitz:dev": "next dev",
|
||||
@@ -12,28 +12,28 @@
|
||||
"schema": "prisma/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "^4.5.0",
|
||||
"@tanstack/react-query": "4.0.10",
|
||||
"blitz": "2.0.1",
|
||||
"blitz": "2.2.3",
|
||||
"flatted": "3.2.7",
|
||||
"next": "14.0.4",
|
||||
"next": "15.0.1",
|
||||
"prisma": "^4.5.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"superjson": "1.11.0",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "18.11.7",
|
||||
"@types/react": "18.0.23",
|
||||
"@types/react-dom": "18.0.7",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"eslint": "8.26.0",
|
||||
"eslint-config-next": "13.0.0",
|
||||
"typescript": "4.8.4"
|
||||
|
||||
Binary file not shown.
4
apps/next13/src/app/api/rpc/[[...blitz]]/route.ts
Normal file
4
apps/next13/src/app/api/rpc/[[...blitz]]/route.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import {rpcAppHandler} from "@blitzjs/rpc"
|
||||
import {withBlitzAuth} from "src/blitz-server"
|
||||
|
||||
export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())
|
||||
@@ -6,26 +6,27 @@ import {simpleRolesIsAuthorized} from "@blitzjs/auth"
|
||||
import {BlitzLogger} from "blitz"
|
||||
import {RpcServerPlugin} from "@blitzjs/rpc"
|
||||
|
||||
const {api, getBlitzContext, useAuthenticatedBlitzContext, invoke} = setupBlitzServer({
|
||||
plugins: [
|
||||
AuthServerPlugin({
|
||||
cookiePrefix: "web-cookie-prefix",
|
||||
storage: PrismaStorage(db),
|
||||
isAuthorized: simpleRolesIsAuthorized,
|
||||
}),
|
||||
RpcServerPlugin({
|
||||
logging: {
|
||||
disablelevel: "debug",
|
||||
},
|
||||
onInvokeError(error) {
|
||||
console.log("onInvokeError", error)
|
||||
},
|
||||
}),
|
||||
],
|
||||
logger: BlitzLogger({}),
|
||||
})
|
||||
const {api, getBlitzContext, useAuthenticatedBlitzContext, invoke, withBlitzAuth} =
|
||||
setupBlitzServer({
|
||||
plugins: [
|
||||
AuthServerPlugin({
|
||||
cookiePrefix: "web-cookie-prefix",
|
||||
storage: PrismaStorage(db),
|
||||
isAuthorized: simpleRolesIsAuthorized,
|
||||
}),
|
||||
RpcServerPlugin({
|
||||
logging: {
|
||||
disablelevel: "debug",
|
||||
},
|
||||
onInvokeError(error) {
|
||||
console.log("onInvokeError", error)
|
||||
},
|
||||
}),
|
||||
],
|
||||
logger: BlitzLogger({}),
|
||||
})
|
||||
|
||||
export {api, getBlitzContext, useAuthenticatedBlitzContext, invoke}
|
||||
export {api, getBlitzContext, useAuthenticatedBlitzContext, invoke, withBlitzAuth}
|
||||
|
||||
export const cliConfig: BlitzCliConfig = {
|
||||
customTemplates: "src/templates",
|
||||
|
||||
@@ -4,7 +4,7 @@ import {zodResolver} from "@hookform/resolvers/zod"
|
||||
import {z} from "zod"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
extends Omit<PropsWithoutRef<React.JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
/** All your form fields */
|
||||
children?: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
|
||||
@@ -2,14 +2,15 @@ import {forwardRef, PropsWithoutRef, ComponentPropsWithoutRef} from "react"
|
||||
import {useFormContext} from "react-hook-form"
|
||||
import {ErrorMessage} from "@hookform/error-message"
|
||||
|
||||
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> {
|
||||
export interface LabeledTextFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["input"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
type?: "text" | "password" | "email" | "number"
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import {rpcHandler} from "@blitzjs/rpc"
|
||||
import {api} from "../../../blitz-server"
|
||||
|
||||
export default api(rpcHandler({onError: (error, ctx) => console.log(error)}))
|
||||
@@ -12,5 +12,5 @@ export default async function getCurrentUser(input: null, ctx: Ctx) {
|
||||
}
|
||||
|
||||
export const config = {
|
||||
httpMethod: "GET",
|
||||
httpMethod: "POST",
|
||||
}
|
||||
|
||||
@@ -23,31 +23,30 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"openid-client": "5.2.1",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"ts-node": "10.9.1",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/jest": "29.2.2",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/preview-email": "2.0.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
"eslint": "8.27.0",
|
||||
"eslint-config-next": "12.3.1",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { z } from "zod"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
extends Omit<PropsWithoutRef<React.JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
/** All your form fields */
|
||||
children?: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
|
||||
@@ -2,14 +2,15 @@ import { forwardRef, PropsWithoutRef, ComponentPropsWithoutRef } from "react"
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { ErrorMessage } from "@hookform/error-message"
|
||||
|
||||
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> {
|
||||
export interface LabeledTextFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["input"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
type?: "text" | "password" | "email" | "number"
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
apps/toolkit-app/next-env.d.ts
vendored
2
apps/toolkit-app/next-env.d.ts
vendored
@@ -2,4 +2,4 @@
|
||||
/// <reference types="next/image-types/global" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -24,31 +24,30 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"next-auth": "4.18.7",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"next-auth": "4.24.7",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"ts-node": "10.9.1",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/preview-email": "2.0.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
"@vitejs/plugin-react": "2.2.0",
|
||||
"eslint": "8.27.0",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { z } from "zod"
|
||||
|
||||
export interface FormProps<S extends z.ZodType<any, any>>
|
||||
extends Omit<PropsWithoutRef<JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
extends Omit<PropsWithoutRef<React.JSX.IntrinsicElements["form"]>, "onSubmit"> {
|
||||
/** All your form fields */
|
||||
children?: ReactNode
|
||||
/** Text to display in the submit button */
|
||||
|
||||
@@ -2,14 +2,15 @@ import { ComponentPropsWithoutRef, forwardRef, PropsWithoutRef } from "react"
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { ErrorMessage } from "@hookform/error-message"
|
||||
|
||||
export interface LabeledSelectFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["select"]> {
|
||||
export interface LabeledSelectFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["select"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
options: any[]
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,15 @@ import { forwardRef, PropsWithoutRef, ComponentPropsWithoutRef } from "react"
|
||||
import { useFormContext } from "react-hook-form"
|
||||
import { ErrorMessage } from "@hookform/error-message"
|
||||
|
||||
export interface LabeledTextFieldProps extends PropsWithoutRef<JSX.IntrinsicElements["input"]> {
|
||||
export interface LabeledTextFieldProps
|
||||
extends PropsWithoutRef<React.JSX.IntrinsicElements["input"]> {
|
||||
/** Field name. */
|
||||
name: string
|
||||
/** Field label. */
|
||||
label: string
|
||||
/** Field type. Doesn't include radio buttons and checkboxes */
|
||||
type?: "text" | "password" | "email" | "number"
|
||||
outerProps?: PropsWithoutRef<JSX.IntrinsicElements["div"]>
|
||||
outerProps?: PropsWithoutRef<React.JSX.IntrinsicElements["div"]>
|
||||
labelProps?: ComponentPropsWithoutRef<"label">
|
||||
}
|
||||
|
||||
|
||||
@@ -11,15 +11,11 @@ const LoginPage: BlitzPage = () => {
|
||||
<LoginForm
|
||||
onSuccess={(_user) => {
|
||||
const next = router.query.next ? decodeURIComponent(router.query.next as string) : "/"
|
||||
// return router.push(next)
|
||||
return router.push(next)
|
||||
}}
|
||||
/>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
LoginPage.authenticate = {
|
||||
redirectTo: "/",
|
||||
}
|
||||
|
||||
export default LoginPage
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,27 +16,27 @@
|
||||
"schema": "./db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"@types/jest": "29.2.2",
|
||||
"@types/passport-twitter": "1.0.37",
|
||||
"blitz": "2.0.1",
|
||||
"blitz": "2.2.3",
|
||||
"jest": "29.3.0",
|
||||
"jest-environment-jsdom": "29.3.0",
|
||||
"next": "14.0.4",
|
||||
"next": "15.0.1",
|
||||
"passport-mock-strategy": "2.0.0",
|
||||
"passport-twitter": "1.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"ts-node": "10.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"eslint": "8.27.0",
|
||||
"typescript": "^4.8.4"
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
assets/route4me.png
Normal file
BIN
assets/route4me.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
@@ -17,31 +17,30 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"delay": "5.0.0",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-hook-form": "7.39.1",
|
||||
"ts-node": "10.9.1",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/preview-email": "2.0.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
"@vitejs/plugin-react": "2.2.0",
|
||||
"eslint": "8.27.0",
|
||||
|
||||
@@ -79,11 +79,13 @@ const runTests = () => {
|
||||
let text = await browser.elementByCss("#content").text()
|
||||
expect(text).toMatch(/logged-out/)
|
||||
await browser.elementByCss("#login").click()
|
||||
await waitFor(200)
|
||||
await waitFor(7500)
|
||||
text = await browser.elementByCss("#content").text()
|
||||
|
||||
expect(text).toMatch(/logged-in/)
|
||||
|
||||
await browser.elementByCss("#logout").click()
|
||||
await waitFor(250)
|
||||
await waitFor(5000)
|
||||
text = await browser.elementByCss("#content").text()
|
||||
expect(text).toMatch(/logged-out/)
|
||||
|
||||
@@ -93,16 +95,16 @@ const runTests = () => {
|
||||
it("should logout without infinite loop #2233", async () => {
|
||||
// Login
|
||||
let browser = await webdriver(appPort, "/login")
|
||||
await waitFor(200)
|
||||
await waitFor(5000)
|
||||
await browser.elementByCss("#login").click()
|
||||
await waitFor(200)
|
||||
await waitFor(5000)
|
||||
|
||||
await browser.eval(`window.location = "/authenticated-query"`)
|
||||
await browser.waitForElementByCss("#content")
|
||||
let text = await browser.elementByCss("#content").text()
|
||||
expect(text).toMatch(/authenticated-basic-result/)
|
||||
await browser.elementByCss("#logout").click()
|
||||
await waitFor(200)
|
||||
await waitFor(5000)
|
||||
await browser.waitForElementByCss("#error")
|
||||
text = await browser.elementByCss("#error").text()
|
||||
if (mode === "server") {
|
||||
@@ -115,9 +117,9 @@ const runTests = () => {
|
||||
|
||||
it("Page.authenticate = {role} should throw authentication error ", async () => {
|
||||
let browser = await webdriver(appPort, "/login")
|
||||
await waitFor(200)
|
||||
await waitFor(5000)
|
||||
await browser.elementByCss("#login").click()
|
||||
await waitFor(200)
|
||||
await waitFor(5000)
|
||||
await browser.eval(`window.location = "/page-dot-authenticate-role"`)
|
||||
await browser.waitForElementByCss("#error")
|
||||
let text = await browser.elementByCss("#error").text()
|
||||
@@ -169,7 +171,7 @@ const runTests = () => {
|
||||
let text = await browser.elementByCss("#content").text()
|
||||
expect(text).toMatch(/authenticated-basic-result/)
|
||||
await browser.elementByCss("#logout").click()
|
||||
await waitFor(500)
|
||||
await waitFor(5000)
|
||||
|
||||
expect(await browser.url()).toMatch(/\/login/)
|
||||
if (browser) await browser.close()
|
||||
@@ -275,7 +277,7 @@ const runTests = () => {
|
||||
}
|
||||
|
||||
describe("Auth Tests", () => {
|
||||
describe("dev mode", () => {
|
||||
describe("dev mode - webpack", () => {
|
||||
beforeAll(async () => {
|
||||
mode = "dev"
|
||||
try {
|
||||
@@ -290,6 +292,21 @@ describe("Auth Tests", () => {
|
||||
runTests()
|
||||
})
|
||||
|
||||
describe("dev mode - turbo", () => {
|
||||
beforeAll(async () => {
|
||||
mode = "dev"
|
||||
try {
|
||||
await runBlitzCommand(["prisma", "migrate", "reset", "--force"])
|
||||
appPort = await findPort()
|
||||
app = await blitzLaunchApp(appPort, {cwd: process.cwd()}, true)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}, 5000 * 60 * 2)
|
||||
afterAll(async () => await killApp(app))
|
||||
runTests()
|
||||
})
|
||||
|
||||
describe("server mode", () => {
|
||||
beforeAll(async () => {
|
||||
mode = "server"
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"secure-password": "4.0.0",
|
||||
"wait-port": "1.0.4"
|
||||
},
|
||||
@@ -36,7 +36,7 @@
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node": "18.7.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -21,14 +21,11 @@ export const authenticateUser = async (email: string, password: string) => {
|
||||
}
|
||||
|
||||
export default api(async (req, res, ctx) => {
|
||||
const blitzContext = ctx
|
||||
|
||||
const user = await authenticateUser(req.query.email as string, req.query.password as string)
|
||||
|
||||
await blitzContext.session.$create({
|
||||
await ctx.session.$create({
|
||||
userId: user.id,
|
||||
role: user.role as Role,
|
||||
})
|
||||
|
||||
res.status(200).json({email: req.query.email, userId: blitzContext.session.userId})
|
||||
res.status(200).json({email: req.query.email, userId: ctx.session.userId})
|
||||
})
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"lowdb": "2.1.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,20 +11,20 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
"get-port": "6.1.2",
|
||||
|
||||
15
integration-tests/next-13-app-dir/app/api/logout/route.ts
Normal file
15
integration-tests/next-13-app-dir/app/api/logout/route.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import {withBlitzAuth} from "../../../src/blitz-server"
|
||||
|
||||
export const {POST} = withBlitzAuth({
|
||||
POST: async (_request, _params, ctx) => {
|
||||
const session = ctx.session
|
||||
await session.$revoke()
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
userId: session.userId,
|
||||
}),
|
||||
{status: 200},
|
||||
)
|
||||
},
|
||||
})
|
||||
11
integration-tests/next-13-app-dir/app/api/noauth/route.ts
Normal file
11
integration-tests/next-13-app-dir/app/api/noauth/route.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import {H} from "@blitzjs/auth/dist/index-0ecbee46"
|
||||
import {withBlitzAuth} from "../../../src/blitz-server"
|
||||
|
||||
const emptyResponse = async () => {
|
||||
return new Response(null, {status: 200})
|
||||
}
|
||||
|
||||
export const {POST, HEAD} = withBlitzAuth({
|
||||
POST: emptyResponse,
|
||||
HEAD: emptyResponse,
|
||||
})
|
||||
@@ -0,0 +1,4 @@
|
||||
import {rpcAppHandler} from "@blitzjs/rpc"
|
||||
import {withBlitzAuth} from "../../../../src/blitz-server"
|
||||
|
||||
export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())
|
||||
38
integration-tests/next-13-app-dir/app/api/signin/route.ts
Normal file
38
integration-tests/next-13-app-dir/app/api/signin/route.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import {withBlitzAuth} from "../../../src/blitz-server"
|
||||
import prisma from "../../../db/index"
|
||||
import {Role} from "../../../types"
|
||||
|
||||
export const authenticateUser = async (email: string, password: string) => {
|
||||
const user = await prisma.user.findFirst({where: {email}})
|
||||
|
||||
if (!user) throw new Error("Authentication Error")
|
||||
await prisma.user.update({where: {id: user.id}, data: {hashedPassword: password}})
|
||||
|
||||
const {hashedPassword, ...rest} = user
|
||||
return rest
|
||||
}
|
||||
|
||||
export const {POST} = withBlitzAuth({
|
||||
POST: async (request: Request, context, ctx) => {
|
||||
const {searchParams} = new URL(request.url)
|
||||
const user = await authenticateUser(
|
||||
searchParams.get("email") as string,
|
||||
searchParams.get("password") as string,
|
||||
)
|
||||
|
||||
await ctx.session.$create({
|
||||
userId: user.id,
|
||||
role: user.role as Role,
|
||||
})
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({email: searchParams.get("email"), userId: ctx.session.userId}),
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
)
|
||||
},
|
||||
})
|
||||
@@ -1,34 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import {useQuery, useMutation} from "@blitzjs/rpc"
|
||||
import logout from "../src/auth/mutations/logout"
|
||||
import getCurrentUser from "../src/users/queries/getCurrentUser"
|
||||
import {useTransition} from "react"
|
||||
import {useRouter} from "next/navigation"
|
||||
|
||||
export default function Test() {
|
||||
const router = useRouter()
|
||||
const [user] = useQuery(getCurrentUser, null)
|
||||
const [isPending, startTransition] = useTransition()
|
||||
const [logoutMutation] = useMutation(logout)
|
||||
console.log(user)
|
||||
return (
|
||||
<div>
|
||||
<h1>Test</h1>
|
||||
<p>{user?.email}</p>
|
||||
<button
|
||||
className="button small"
|
||||
onClick={async () => {
|
||||
await logoutMutation()
|
||||
startTransition(() => {
|
||||
// Refresh the current route and fetch new data from the server without
|
||||
// losing client-side browser or React state.
|
||||
router.refresh()
|
||||
})
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
||||
|
||||
@@ -17,17 +17,17 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"lowdb": "2.1.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"secure-password": "4.0.0",
|
||||
"wait-port": "1.0.4"
|
||||
},
|
||||
@@ -37,7 +37,7 @@
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node": "18.7.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
@@ -45,6 +45,6 @@
|
||||
"node-fetch": "3.2.3",
|
||||
"playwright": "1.28.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "^4.8.4"
|
||||
"typescript": "^4.9.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import {api} from "../../src/blitz-server"
|
||||
|
||||
export default api(async (_req, res, ctx) => {
|
||||
const blitzContext = ctx
|
||||
|
||||
await blitzContext.session.$revoke()
|
||||
|
||||
res.status(200).json({userId: blitzContext.session.userId})
|
||||
})
|
||||
@@ -1,5 +0,0 @@
|
||||
import {api} from "../../src/blitz-server"
|
||||
|
||||
export default api(async (_req, res, ctx) => {
|
||||
res.status(200).end()
|
||||
})
|
||||
@@ -1,4 +0,0 @@
|
||||
import {rpcHandler} from "@blitzjs/rpc"
|
||||
import {api} from "../../../src/blitz-server"
|
||||
|
||||
export default api(rpcHandler({onError: (error, ctx) => console.log(error)}))
|
||||
@@ -1,34 +0,0 @@
|
||||
import {api} from "../../src/blitz-server"
|
||||
import prisma from "../../db/index"
|
||||
import {SecurePassword} from "@blitzjs/auth/secure-password"
|
||||
import {Role} from "../../types"
|
||||
|
||||
export const authenticateUser = async (email: string, password: string) => {
|
||||
const user = await prisma.user.findFirst({where: {email}})
|
||||
|
||||
if (!user) throw new Error("Authentication Error")
|
||||
|
||||
const result = await SecurePassword.verify(user.hashedPassword, password)
|
||||
|
||||
if (result === SecurePassword.VALID_NEEDS_REHASH) {
|
||||
// Upgrade hashed password with a more secure hash
|
||||
const improvedHash = await SecurePassword.hash(password)
|
||||
await prisma.user.update({where: {id: user.id}, data: {hashedPassword: improvedHash}})
|
||||
}
|
||||
|
||||
const {hashedPassword, ...rest} = user
|
||||
return rest
|
||||
}
|
||||
|
||||
export default api(async (req, res, ctx) => {
|
||||
const blitzContext = ctx
|
||||
|
||||
const user = await authenticateUser(req.query.email as string, req.query.password as string)
|
||||
|
||||
await blitzContext.session.$create({
|
||||
userId: user.id,
|
||||
role: user.role as Role,
|
||||
})
|
||||
|
||||
res.status(200).json({email: req.query.email, userId: blitzContext.session.userId})
|
||||
})
|
||||
@@ -3,16 +3,16 @@ import {AuthServerPlugin, PrismaStorage} from "@blitzjs/auth"
|
||||
import db from "../db"
|
||||
import {simpleRolesIsAuthorized} from "@blitzjs/auth"
|
||||
import {BlitzLogger} from "blitz"
|
||||
import {RpcServerPlugin} from "@blitzjs/rpc"
|
||||
|
||||
const {api, getBlitzContext} = setupBlitzServer({
|
||||
export const {api, getBlitzContext, withBlitzAuth} = setupBlitzServer({
|
||||
plugins: [
|
||||
AuthServerPlugin({
|
||||
cookiePrefix: "auth-tests-cookie-prefix",
|
||||
storage: PrismaStorage(db),
|
||||
isAuthorized: simpleRolesIsAuthorized,
|
||||
}),
|
||||
RpcServerPlugin({}),
|
||||
],
|
||||
logger: BlitzLogger({}),
|
||||
})
|
||||
|
||||
export {api, getBlitzContext}
|
||||
|
||||
@@ -57,7 +57,7 @@ const runTests = (mode?: string) => {
|
||||
"should render result for open query",
|
||||
async () => {
|
||||
const res = await fetch(`http://localhost:${appPort}/api/noauth`, {
|
||||
method: "GET",
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json; charset=utf-8"},
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
@@ -67,7 +67,7 @@ const runTests = (mode?: string) => {
|
||||
|
||||
it("sets correct cookie", async () => {
|
||||
const res = await fetch(`http://localhost:${appPort}/api/noauth`, {
|
||||
method: "GET",
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json; charset=utf-8"},
|
||||
})
|
||||
const cookieHeader = res.headers.get("Set-Cookie")
|
||||
@@ -94,6 +94,8 @@ const runTests = (mode?: string) => {
|
||||
async () => {
|
||||
const browser = await webdriver(appPort, "/react-query")
|
||||
|
||||
await browser.refresh()
|
||||
|
||||
browser.waitForElementByCss("#button", 0)
|
||||
await browser.elementByCss("#button").click()
|
||||
|
||||
@@ -133,7 +135,7 @@ const runTests = (mode?: string) => {
|
||||
|
||||
it("does not require CSRF header on HEAD requests", async () => {
|
||||
const res = await fetch(`http://localhost:${appPort}/api/noauth`, {
|
||||
method: "GET",
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json; charset=utf-8"},
|
||||
})
|
||||
const cookieHeader = res.headers.get("Set-Cookie")
|
||||
@@ -153,7 +155,7 @@ const runTests = (mode?: string) => {
|
||||
}
|
||||
|
||||
describe("Auth Tests", () => {
|
||||
describe("dev mode", async () => {
|
||||
describe("dev mode - webpack", async () => {
|
||||
beforeAll(async () => {
|
||||
try {
|
||||
await runBlitzCommand(["prisma", "migrate", "reset", "--force"])
|
||||
@@ -169,19 +171,19 @@ describe("Auth Tests", () => {
|
||||
runTests()
|
||||
})
|
||||
|
||||
// describe("server mode", () => {
|
||||
// beforeAll(async () => {
|
||||
// try {
|
||||
// await runBlitzCommand(["prisma", "generate"])
|
||||
// await runBlitzCommand(["prisma", "migrate", "deploy"])
|
||||
// await blitzBuild()
|
||||
// // appPort = await findPort()
|
||||
// app = await blitzStart(appPort, {cwd: process.cwd()})
|
||||
// } catch (err) {
|
||||
// console.log(err)
|
||||
// }
|
||||
// }, 5000 * 60 * 2)
|
||||
// afterAll(async () => await killApp(app))
|
||||
// runTests()
|
||||
// })
|
||||
describe("dev mode - turbo", async () => {
|
||||
beforeAll(async () => {
|
||||
try {
|
||||
await runBlitzCommand(["prisma", "migrate", "reset", "--force"])
|
||||
appPort = await findPort()
|
||||
app = await blitzLaunchApp(appPort, {cwd: process.cwd()}, true)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}, 5000 * 60 * 2)
|
||||
afterAll(async () => {
|
||||
await killApp(app)
|
||||
})
|
||||
runTests()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,21 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"@tanstack/react-query": "4.0.10",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@types/react": "18.0.25",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@vitejs/plugin-react": "1.3.0",
|
||||
"delay": "5.0.0",
|
||||
"eslint": "8.27.0",
|
||||
|
||||
@@ -16,23 +16,23 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -16,24 +16,24 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/next": "2.0.1",
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "14.0.4",
|
||||
"prisma": "4.6.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"b64-lite": "1.4.0",
|
||||
"eslint": "8.27.0",
|
||||
"fs-extra": "10.0.1",
|
||||
|
||||
@@ -9,7 +9,6 @@ declare module "@blitzjs/auth" {
|
||||
PublicData: {
|
||||
userId: User["id"]
|
||||
role: Role
|
||||
views?: number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,6 +233,7 @@ export function runBlitzCommandDev(argv, stdOut, opts: RunNextCommandDevOptions
|
||||
}
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
console.log(`Running command "blitz ${argv.join(" ")}"`)
|
||||
const instance = spawn("node", [blitzBin, ...argv], {
|
||||
cwd,
|
||||
env,
|
||||
@@ -294,8 +295,8 @@ export function runBlitzCommandDev(argv, stdOut, opts: RunNextCommandDevOptions
|
||||
}
|
||||
|
||||
// Blitz Utils
|
||||
export function blitzLaunchApp(port, opts: RunNextCommandDevOptions) {
|
||||
return runBlitzCommandDev(["dev", "-p", port], undefined, opts)
|
||||
export function blitzLaunchApp(port, opts: RunNextCommandDevOptions, turbo = false) {
|
||||
return runBlitzCommandDev(["dev", "-p", port, turbo ? "--turbo" : ""], undefined, opts)
|
||||
}
|
||||
|
||||
export function blitzBuild(args = [], opts = {}): any {
|
||||
@@ -437,7 +438,7 @@ export function runNextCommandDev(argv, stdOut, opts: RunNextCommandDevOptions =
|
||||
}
|
||||
|
||||
if (opts.stdout !== false) {
|
||||
process.stdout.write(message)
|
||||
process.stdout.write(message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -923,4 +924,5 @@ interface RunNextCommandDevOptions {
|
||||
nodeArgs?: []
|
||||
bootupMarker?: any
|
||||
nextStart?: boolean
|
||||
turbo?: boolean
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "workspace:2.0.1",
|
||||
"@blitzjs/next": "workspace:2.0.1",
|
||||
"@blitzjs/rpc": "workspace:2.0.1",
|
||||
"@blitzjs/config": "workspace:2.2.3",
|
||||
"@blitzjs/next": "workspace:2.2.3",
|
||||
"@blitzjs/rpc": "workspace:2.2.3",
|
||||
"@tanstack/react-query": "4.13.0",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/node-fetch": "2.6.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/rimraf": "3.0.2",
|
||||
"@types/selenium-webdriver": "4.0.18",
|
||||
"chromedriver": "100.0.0",
|
||||
@@ -23,8 +23,8 @@
|
||||
"node-fetch": "3.2.3",
|
||||
"pkg-dir": "5.0.0",
|
||||
"playwright-chromium": "1.28.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"resolve-cwd": "3.0.0",
|
||||
"resolve-from": "5.0.0",
|
||||
"rimraf": "3.0.2",
|
||||
|
||||
12
package.json
12
package.json
@@ -29,9 +29,9 @@
|
||||
"husky": "8.0.2",
|
||||
"jsdom": "^19.0.0",
|
||||
"lint-staged": "13.0.3",
|
||||
"next": "14.0.4",
|
||||
"next": "15.0.1",
|
||||
"only-allow": "1.1.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-prisma": "4.4.0",
|
||||
"pretty-quick": "3.1.3",
|
||||
"turbo": "1.10.9",
|
||||
@@ -47,7 +47,13 @@
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"next-auth@4.18.7": "patches/next-auth@4.18.7.patch"
|
||||
"next-auth@4.24.7": "patches/next-auth@4.24.7.patch"
|
||||
},
|
||||
"overrides": {
|
||||
"@types/mime": "3.0.4",
|
||||
"next": "15.0.1",
|
||||
"@types/react": "npm:types-react@rc",
|
||||
"@types/react-dom": "npm:types-react-dom@rc"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,187 @@
|
||||
# @blitzjs/auth
|
||||
|
||||
## 2.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- aa033af9f: fix: Overriden custom cookies with pages router
|
||||
- blitz@2.2.3
|
||||
|
||||
## 2.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ab455acf0: fix: Overriden custom cookies used inside `withBlitzAuth`
|
||||
- blitz@2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3fa3a4ef3: chore: support next.js 15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.4
|
||||
|
||||
## 2.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0b3286468: chore: bump `next.js` and `zod` versions
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- blitz@2.1.3
|
||||
|
||||
## 2.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.2
|
||||
|
||||
## 2.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9a0ba87d1]
|
||||
- blitz@2.1.1
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3b10b13e6: feat: add blitz auth support for the Web `Request` API standard
|
||||
|
||||
Usage using the new `withBlitzAuth` adapter in the App Router:
|
||||
|
||||
```ts
|
||||
import {withBlitzAuth} from "app/blitz-server"
|
||||
|
||||
export const {POST} = withBlitzAuth({
|
||||
POST: async (_request, _params, ctx) => {
|
||||
const session = ctx.session
|
||||
await session.$revoke()
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
userId: session.userId,
|
||||
}),
|
||||
{status: 200},
|
||||
)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
feat: New Blitz RPC handler meant to with the next.js app router `route.ts` files
|
||||
|
||||
Usage using the new `rpcAppHandler` function
|
||||
|
||||
```ts
|
||||
// app/api/rpc/[[...blitz]]/route.ts
|
||||
import {rpcAppHandler} from "@blitzjs/rpc"
|
||||
import {withBlitzAuth} from "app/blitz-server"
|
||||
|
||||
// Usage with blitz auth
|
||||
export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())
|
||||
|
||||
// Standalone usage
|
||||
export const {GET, POST, HEAD} = rpcAppHandler()
|
||||
```
|
||||
|
||||
chore: Update the app directory starter
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [d53da39cb]
|
||||
- Updated dependencies [3b10b13e6]
|
||||
- blitz@2.1.0
|
||||
|
||||
## 2.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 318e9740d: feat: support next-auth version 4.24.7
|
||||
- Updated dependencies [318e9740d]
|
||||
- blitz@2.0.10
|
||||
|
||||
## 2.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5a14306f7]
|
||||
- blitz@2.0.9
|
||||
|
||||
## 2.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 77555468f: fix: add missing host while initialising the next-auth adapter
|
||||
- Updated dependencies [5e61a1681]
|
||||
- Updated dependencies [77555468f]
|
||||
- blitz@2.0.8
|
||||
|
||||
## 2.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [ee7bf87ec]
|
||||
- Updated dependencies [178c152b2]
|
||||
- blitz@2.0.7
|
||||
|
||||
## 2.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5a587a6c3: Fix bundling issue that occurs in vercel due to the way imports were handled internally
|
||||
- Updated dependencies [76a2544f9]
|
||||
- blitz@2.0.6
|
||||
|
||||
## 2.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 6f54841b7: fix: getBlitzContext() can only be used in React Server Components in Nextjs 13 or higher
|
||||
- 8a417533f: fix: remove restriction to use `secure` cookies in localhost / during development following spec in [developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
|
||||
- Updated dependencies [6f54841b7]
|
||||
- blitz@2.0.5
|
||||
|
||||
## 2.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- dd604c767: perf: add filter to select only non expired sessions
|
||||
- Updated dependencies [dd604c767]
|
||||
- Updated dependencies [28a79040e]
|
||||
- blitz@2.0.4
|
||||
|
||||
## 2.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [2f5c8a3a0]
|
||||
- blitz@2.0.3
|
||||
|
||||
## 2.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e8fd12e4f]
|
||||
- blitz@2.0.2
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/auth",
|
||||
"version": "2.0.1",
|
||||
"version": "2.2.3",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -50,7 +50,7 @@
|
||||
"url": "0.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.0.1",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"next-auth": "*",
|
||||
"secure-password": "4.0.0"
|
||||
@@ -67,19 +67,18 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/cookie": "0.4.1",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/jsonwebtoken": "8.5.8",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"next-auth": "4.18.7",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"next-auth": "4.24.7",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"secure-password": "4.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"unbuild": "0.7.6",
|
||||
|
||||
@@ -7,7 +7,7 @@ import {parsePublicDataToken, getPublicDataStore, useSession} from "./index"
|
||||
import {COOKIE_PUBLIC_DATA_TOKEN} from "../shared"
|
||||
import {toBase64} from "b64-lite"
|
||||
import {act} from "@testing-library/react"
|
||||
import {renderHook} from "@testing-library/react-hooks"
|
||||
import {renderHook} from "@testing-library/react"
|
||||
|
||||
vi.mock("blitz", async () => {
|
||||
const blitz = await vi.importActual("blitz")
|
||||
|
||||
@@ -161,6 +161,8 @@ export const useSession = (options: UseSessionOptions = {}): ClientSession => {
|
||||
if (isServer) {
|
||||
const e = new Error()
|
||||
e.name = "Rendering Suspense fallback..."
|
||||
;(e as any).digest = "DYNAMIC_SERVER_USAGE"
|
||||
e.message = "DYNAMIC_SERVER_USAGE"
|
||||
delete e.stack
|
||||
throw e
|
||||
} else {
|
||||
@@ -258,7 +260,7 @@ export type RedirectAuthenticatedToFn = (
|
||||
) => RedirectAuthenticatedTo
|
||||
|
||||
export type BlitzPage<P = {}> = React.ComponentType<P> & {
|
||||
getLayout?: (component: JSX.Element) => JSX.Element
|
||||
getLayout?: (component: React.JSX.Element) => React.JSX.Element
|
||||
authenticate?: boolean | {redirectTo?: string | RouteUrlObject; role?: string | Array<string>}
|
||||
suppressFirstRenderFlicker?: boolean
|
||||
redirectAuthenticatedTo?: RedirectAuthenticatedTo | RedirectAuthenticatedToFn
|
||||
|
||||
@@ -107,13 +107,8 @@ export function NextAuthAdapter<P extends Provider[]>(
|
||||
providerId = providerId.split("?")[0]
|
||||
}
|
||||
const {options, cookies} = await init({
|
||||
// @ts-ignore
|
||||
url: new URL(
|
||||
// @ts-ignore
|
||||
internalRequest.url!,
|
||||
process.env.APP_ORIGIN || process.env.BLITZ_DEV_SERVER_ORIGIN,
|
||||
),
|
||||
authOptions: config as unknown as AuthOptions,
|
||||
origin: internalRequest.origin,
|
||||
action,
|
||||
providerId,
|
||||
callbackUrl: req.body?.callbackUrl ?? (req.query?.callbackUrl as string),
|
||||
|
||||
@@ -47,7 +47,12 @@ async function readJSONBody(
|
||||
// prettier-ignore
|
||||
const actions = [ "providers", "session", "csrf", "login", "signout", "callback", "verify-request", "error", "_log"]
|
||||
|
||||
export async function toInternalRequest(req: Request): Promise<RequestInternal | Error> {
|
||||
export async function toInternalRequest(req: Request): Promise<
|
||||
| (RequestInternal & {
|
||||
url: URL
|
||||
})
|
||||
| Error
|
||||
> {
|
||||
try {
|
||||
// TODO: url.toString() should not include action and providerId
|
||||
// see init.ts
|
||||
@@ -69,17 +74,28 @@ export async function toInternalRequest(req: Request): Promise<RequestInternal |
|
||||
providerId = providerIdOrAction
|
||||
}
|
||||
|
||||
const headers = Object.fromEntries(req.headers)
|
||||
const detectOrigin = (host?: string, proto?: string) => {
|
||||
if (process.env.VERCEL ?? process.env.FLIGHTCONTROL ?? process.env.AUTH_TRUST_HOST)
|
||||
return `${proto === "http" ? "http" : "https"}://${host}`
|
||||
|
||||
return process.env.NEXTAUTH_URL
|
||||
}
|
||||
|
||||
return {
|
||||
//@ts-ignore
|
||||
url,
|
||||
action,
|
||||
providerId,
|
||||
method: req.method ?? "GET",
|
||||
headers: Object.fromEntries(req.headers),
|
||||
headers,
|
||||
body: req.body ? await readJSONBody(req.body) : undefined,
|
||||
cookies: parseCookie(req.headers.get("cookie") ?? "") ?? {},
|
||||
error: url.searchParams.get("error") ?? undefined,
|
||||
query: Object.fromEntries(url.searchParams),
|
||||
origin: detectOrigin(
|
||||
headers["x-forwarded-host"] ?? headers.host,
|
||||
headers["x-forwarded-proto"],
|
||||
),
|
||||
}
|
||||
} catch (error) {
|
||||
return error as Error
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {RequestMiddleware, Ctx, createServerPlugin} from "blitz"
|
||||
import {assert} from "blitz"
|
||||
import {IncomingMessage, ServerResponse} from "http"
|
||||
import type {IncomingMessage, ServerResponse} from "http"
|
||||
import {PublicData, SessionModel, SessionConfigMethods} from "../shared/types"
|
||||
import {getBlitzContext, getSession, useAuthenticatedBlitzContext} from "./auth-sessions"
|
||||
|
||||
@@ -22,7 +22,9 @@ interface IsAuthorized {
|
||||
interface PrismaClientWithSession {
|
||||
session: {
|
||||
findFirst(args?: {where?: {handle?: SessionModel["handle"]}}): Promise<SessionModel | null>
|
||||
findMany(args?: {where?: {userId?: PublicData["userId"]}}): Promise<SessionModel[]>
|
||||
findMany(args?: {
|
||||
where?: {userId?: PublicData["userId"]; expiresAt?: {gt?: Date}}
|
||||
}): Promise<SessionModel[]>
|
||||
create(args: {
|
||||
data: SessionModel & {
|
||||
userId?: any
|
||||
@@ -42,7 +44,7 @@ export const PrismaStorage = <Client extends PrismaClientWithSession>(
|
||||
): SessionConfigMethods => {
|
||||
return {
|
||||
getSession: (handle) => db.session.findFirst({where: {handle}}),
|
||||
getSessions: (userId) => db.session.findMany({where: {userId}}),
|
||||
getSessions: (userId) => db.session.findMany({where: {userId, expiresAt: {gt: new Date()}}}),
|
||||
createSession: (session) => {
|
||||
let user
|
||||
if (session.userId) {
|
||||
@@ -128,11 +130,28 @@ export const AuthServerPlugin = createServerPlugin((options: AuthPluginOptions)
|
||||
if (!globalThis.__BLITZ_GET_RSC_CONTEXT) {
|
||||
globalThis.__BLITZ_GET_RSC_CONTEXT = getBlitzContext
|
||||
}
|
||||
|
||||
type Handler = (request: Request, context: any, ctx: Ctx) => Promise<Response> | Response
|
||||
function withBlitzAuth<T extends {[method: string]: Handler}>(handlers: T): T {
|
||||
return Object.fromEntries(
|
||||
Object.entries(handlers).map(([method, handler]) => [
|
||||
method,
|
||||
async (request: Request, params: unknown) => {
|
||||
const session = await getSession(request)
|
||||
const response = await handler(request, params, {session})
|
||||
session.setSession(response)
|
||||
return response
|
||||
},
|
||||
]),
|
||||
) as unknown as T
|
||||
}
|
||||
|
||||
return {
|
||||
requestMiddlewares: [authPluginSessionMiddleware()],
|
||||
exports: () => ({
|
||||
getBlitzContext,
|
||||
useAuthenticatedBlitzContext,
|
||||
withBlitzAuth,
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,41 +1,226 @@
|
||||
import {expect, describe, it} from "vitest"
|
||||
import {setCookie} from "./auth-sessions"
|
||||
import cookie from "cookie"
|
||||
import {expect, describe, it, beforeEach} from "vitest"
|
||||
import {ServerResponse} from "http"
|
||||
import {Writable} from "stream"
|
||||
import {append} from "./auth-sessions"
|
||||
|
||||
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")
|
||||
class MockServerResponse extends Writable {
|
||||
private headers: Map<string, string | string[]> = new Map()
|
||||
|
||||
getHeader(name: string) {
|
||||
return this.headers.get(name)
|
||||
}
|
||||
|
||||
setHeader(name: string, value: string | string[]) {
|
||||
this.headers.set(name, value)
|
||||
}
|
||||
|
||||
getHeaders() {
|
||||
return Object.fromEntries(this.headers)
|
||||
}
|
||||
|
||||
_write(_chunk: unknown, _encoding: string, callback: (error?: Error | null) => void): void {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
describe("append", () => {
|
||||
let res: ServerResponse
|
||||
const COOKIE_PREFIX = "auth-tests-cookie-prefix_s"
|
||||
|
||||
beforeEach(() => {
|
||||
res = new MockServerResponse() as unknown as ServerResponse
|
||||
})
|
||||
|
||||
describe("Blitz Auth Flows", () => {
|
||||
const anonymousSessionCookie = `${COOKIE_PREFIX}AnonymousSessionToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJibGl0empzIjp7ImlzQW5vbnltb3VzIjp0cnVlLCJoYW5kbGUiOiJEVjk4OVZadFpra0lpWHFSOFRPX3Fvem44MHBwWFBnaDphand0IiwicHVibGljRGF0YSI6eyJ1c2VySWQiOm51bGx9LCJhbnRpQ1NSRlRva2VuIjoiM25BdDBZWVI0b0xDNnAtTm1fQW1CeFQxRmJmVmpiaXMifSwiaWF0IjoxNzQwODA0NTE4LCJhdWQiOiJibGl0empzIiwiaXNzIjoiYmxpdHpqcyIsInN1YiI6ImFub255bW91cyJ9.ZpMxWh3Yq2Qe4BXzZ61d4V0YGV2luswF7ovE90DxURM; Path=/; Expires=Thu, 28 Feb 2030 04:48:38 GMT; HttpOnly; SameSite=Lax`
|
||||
const antiCsrfCookie = `${COOKIE_PREFIX}AntiCsrfToken=3nAt0YYR4oLC6p-Nm_AmBxT1FbfVjbis; Path=/; Expires=Thu, 28 Feb 2030 04:48:38 GMT; SameSite=Lax`
|
||||
const publicDataCookie = `${COOKIE_PREFIX}PublicDataToken=eyJ1c2VySWQiOm51bGx9; Path=/; Expires=Thu, 28 Feb 2030 04:48:38 GMT; SameSite=Lax`
|
||||
|
||||
const expiredSessionCookie = `${COOKIE_PREFIX}SessionToken=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; SameSite=Lax`
|
||||
const expiredAnonymousCookie = `${COOKIE_PREFIX}AnonymousSessionToken=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; SameSite=Lax`
|
||||
|
||||
// Login cookies
|
||||
const loginAntiCsrfCookie = `${COOKIE_PREFIX}AntiCsrfToken=1s3yaYs0yThO-DwOuiepJLzycvN090tO; Path=/; Expires=Mon, 31 Mar 2025 04:48:38 GMT; SameSite=Lax`
|
||||
const loginPublicDataCookie = `${COOKIE_PREFIX}PublicDataToken=eyJ1c2VySWQiOjEsInJvbGUiOiJ1c2VyIn0%3D; Path=/; Expires=Mon, 31 Mar 2025 04:48:38 GMT; SameSite=Lax`
|
||||
const loginSessionCookie = `${COOKIE_PREFIX}SessionToken=aGNjc0o5anJ5eTF4bDdqRE5VN09LeEx5QUJoR2toUjc6b3RzO1NaWC1la3YydGR4UGNjWVp6QkM0SlBQbUdWWmZEMlpFOzhhYWU1MDI2M2Q0YmUyNDIxZWYwNDBmMmFhZGI2MDk4YTNiNjhjMTAyZjlmNmNjYTQ4NzUzMGZiYjc0ZTdhYmI7djA%3D; Path=/; Expires=Mon, 31 Mar 2025 04:48:38 GMT; HttpOnly; SameSite=Lax`
|
||||
|
||||
it("should handle anonymous session cookies", () => {
|
||||
append(res, "Set-Cookie", [anonymousSessionCookie, antiCsrfCookie, publicDataCookie])
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(cookies).toHaveLength(3)
|
||||
expect(cookies[0]).toBe(anonymousSessionCookie)
|
||||
expect(cookies[1]).toBe(antiCsrfCookie)
|
||||
expect(cookies[2]).toBe(publicDataCookie)
|
||||
})
|
||||
|
||||
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("should deduplicate cookies when the same one is set twice", () => {
|
||||
append(res, "Set-Cookie", anonymousSessionCookie)
|
||||
append(res, "Set-Cookie", anonymousSessionCookie)
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(cookies).toHaveLength(1)
|
||||
expect(cookies[0]).toBe(anonymousSessionCookie)
|
||||
})
|
||||
|
||||
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", {}),
|
||||
it("should replace cookies with same name when values change", () => {
|
||||
append(res, "Set-Cookie", anonymousSessionCookie)
|
||||
|
||||
const updatedAnonymousCookie = `${COOKIE_PREFIX}AnonymousSessionToken=NEW_TOKEN_VALUE; Path=/; SameSite=Lax`
|
||||
append(res, "Set-Cookie", updatedAnonymousCookie)
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(cookies).toHaveLength(1)
|
||||
expect(cookies[0]).toBe(updatedAnonymousCookie)
|
||||
})
|
||||
|
||||
it("should handle session expiration", () => {
|
||||
// First add anonymous session
|
||||
append(res, "Set-Cookie", [anonymousSessionCookie, antiCsrfCookie, publicDataCookie])
|
||||
|
||||
append(res, "Set-Cookie", [expiredSessionCookie, expiredAnonymousCookie])
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(cookies).toHaveLength(4)
|
||||
|
||||
expect(cookies.find((c) => c === expiredSessionCookie)).toBeDefined()
|
||||
expect(cookies.find((c) => c === expiredAnonymousCookie)).toBeDefined()
|
||||
})
|
||||
|
||||
it("should handle login flow cookies", () => {
|
||||
// First anonymous session
|
||||
append(res, "Set-Cookie", [anonymousSessionCookie, antiCsrfCookie, publicDataCookie])
|
||||
|
||||
// Then login, which expires anonymous and sets new session
|
||||
append(res, "Set-Cookie", [
|
||||
expiredAnonymousCookie,
|
||||
loginSessionCookie,
|
||||
loginAntiCsrfCookie,
|
||||
loginPublicDataCookie,
|
||||
])
|
||||
setCookie(res, cookie.serialize("C", "c-value", {}))
|
||||
expect(res.getHeader("Set-Cookie")).toEqual(["A=a-value", "B=b-value", "C=c-value"])
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
|
||||
// Should have 4 cookies:
|
||||
// - Original antiCsrf cookie (should be replaced by login one)
|
||||
// - Expired anonymous cookie
|
||||
// - Login session cookie
|
||||
// - Login publicData cookie
|
||||
expect(cookies).toHaveLength(4)
|
||||
|
||||
// Check proper replacement by extracting cookie names
|
||||
const cookieNames = cookies.map((c) => {
|
||||
const namePart = c.substring(0, c.indexOf("="))
|
||||
return namePart
|
||||
})
|
||||
|
||||
expect(cookieNames.filter((n) => n === `${COOKIE_PREFIX}AntiCsrfToken`)).toHaveLength(1)
|
||||
expect(cookieNames.filter((n) => n === `${COOKIE_PREFIX}PublicDataToken`)).toHaveLength(1)
|
||||
expect(cookieNames.filter((n) => n === `${COOKIE_PREFIX}SessionToken`)).toHaveLength(1)
|
||||
// the expired cookie
|
||||
expect(cookieNames.filter((n) => n === `${COOKIE_PREFIX}AnonymousSessionToken`)).toHaveLength(
|
||||
1,
|
||||
)
|
||||
})
|
||||
|
||||
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", {}),
|
||||
it("should properly combine multiple append calls with different cookie groups", () => {
|
||||
append(res, "Set-Cookie", [anonymousSessionCookie, antiCsrfCookie])
|
||||
|
||||
append(res, "Set-Cookie", [publicDataCookie, loginAntiCsrfCookie])
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
|
||||
expect(cookies).toHaveLength(3)
|
||||
|
||||
const antiCsrfCookies = cookies.filter((c) => c.includes(`${COOKIE_PREFIX}AntiCsrfToken`))
|
||||
expect(antiCsrfCookies).toHaveLength(1)
|
||||
expect(antiCsrfCookies[0]).toBe(loginAntiCsrfCookie)
|
||||
})
|
||||
|
||||
it("should handle the full session flow", () => {
|
||||
append(res, "Set-Cookie", [anonymousSessionCookie, antiCsrfCookie, publicDataCookie])
|
||||
|
||||
const initialCookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(initialCookies).toHaveLength(3)
|
||||
|
||||
append(res, "Set-Cookie", [
|
||||
expiredAnonymousCookie,
|
||||
loginSessionCookie,
|
||||
loginAntiCsrfCookie,
|
||||
loginPublicDataCookie,
|
||||
])
|
||||
setCookie(res, cookie.serialize("A", "new-a-value", {}))
|
||||
expect(res.getHeader("Set-Cookie")).toEqual(["A=new-a-value", "B=b-value"])
|
||||
const loginCookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(loginCookies).toHaveLength(4)
|
||||
|
||||
append(res, "Set-Cookie", [
|
||||
expiredSessionCookie,
|
||||
anonymousSessionCookie,
|
||||
antiCsrfCookie,
|
||||
publicDataCookie,
|
||||
])
|
||||
const logoutCookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(logoutCookies).toHaveLength(4)
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
|
||||
const cookieNames = cookies.map((c) => c.substring(0, c.indexOf("=")))
|
||||
|
||||
const counts = cookieNames.reduce((acc, name) => {
|
||||
acc[name] = (acc[name] || 0) + 1
|
||||
return acc
|
||||
}, {} as Record<string, number>)
|
||||
|
||||
expect(Object.keys(counts).length).toBe(4)
|
||||
|
||||
Object.values(counts).forEach((count) => {
|
||||
expect(count).toBeLessThanOrEqual(3)
|
||||
})
|
||||
})
|
||||
|
||||
it("should handle cookies with quoted values and special characters", () => {
|
||||
const specialCookie = `${COOKIE_PREFIX}PublicDataToken="eyJ1c2VySWQiOjEsIm5hbWUiOiJKb2huIERvZSwgSnIuIn0%3D"; Path=/; SameSite=Lax`
|
||||
append(res, "Set-Cookie", specialCookie)
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
expect(cookies).toHaveLength(1)
|
||||
expect(cookies[0]).toBe(specialCookie)
|
||||
})
|
||||
|
||||
it("should properly merge with existing custom cookies already in the response", () => {
|
||||
const customCookie1 = "custom1=value1; Path=/; HttpOnly"
|
||||
const customCookie2 = "custom2=value2; Path=/; HttpOnly"
|
||||
const existingAuthCookie = `${COOKIE_PREFIX}AntiCsrfToken=old-token; Path=/; SameSite=Lax`
|
||||
|
||||
res.setHeader("Set-Cookie", [customCookie1, customCookie2, existingAuthCookie])
|
||||
|
||||
// login
|
||||
append(res, "Set-Cookie", [anonymousSessionCookie, loginAntiCsrfCookie, publicDataCookie])
|
||||
|
||||
const cookies = res.getHeader("Set-Cookie") as string[]
|
||||
|
||||
expect(cookies).toHaveLength(5)
|
||||
|
||||
// Custom cookies should be preserved
|
||||
expect(cookies).toContain(customCookie1)
|
||||
expect(cookies).toContain(customCookie2)
|
||||
|
||||
// Auth cookies should be correctly applied, with antiCsrf being updated
|
||||
expect(cookies).toContain(anonymousSessionCookie)
|
||||
expect(cookies).toContain(loginAntiCsrfCookie)
|
||||
expect(cookies).toContain(publicDataCookie)
|
||||
|
||||
// The old auth cookie should be replaced
|
||||
expect(cookies).not.toContain(existingAuthCookie)
|
||||
|
||||
// Verify we have the right counts of each cookie type
|
||||
const cookieNames = cookies.map((c) => c.substring(0, c.indexOf("=")))
|
||||
expect(cookieNames.filter((n) => n === "custom1")).toHaveLength(1)
|
||||
expect(cookieNames.filter((n) => n === "custom2")).toHaveLength(1)
|
||||
expect(cookieNames.filter((n) => n === `${COOKIE_PREFIX}AnonymousSessionToken`)).toHaveLength(
|
||||
1,
|
||||
)
|
||||
expect(cookieNames.filter((n) => n === `${COOKIE_PREFIX}AntiCsrfToken`)).toHaveLength(1)
|
||||
expect(cookieNames.filter((n) => n === `${COOKIE_PREFIX}PublicDataToken`)).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,8 +9,6 @@ export {
|
||||
getSession,
|
||||
isLocalhost,
|
||||
setPublicDataForUser,
|
||||
setCookie,
|
||||
simpleRolesIsAuthorized,
|
||||
getBlitzContext,
|
||||
} from "./auth-sessions"
|
||||
export type {AnonymousSessionPayload, SimpleRolesIsAuthorized} from "./auth-sessions"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//@ts-nocheck
|
||||
import {Ctx} from "blitz"
|
||||
import type {Ctx} from "blitz"
|
||||
import type {ServerResponse} from "http"
|
||||
|
||||
export interface Session {
|
||||
// isAuthorize can be injected here
|
||||
@@ -66,6 +67,12 @@ export interface SessionContextBase {
|
||||
$getPrivateData: () => Promise<Record<any, any>>
|
||||
$setPrivateData: (data: Record<any, any>) => Promise<void>
|
||||
$setPublicData: (data: Partial<Omit<PublicData, "userId">>) => Promise<void>
|
||||
/**
|
||||
* This function is only for manual session handling
|
||||
*
|
||||
* Instead use {@link https://blitzjs.com/docs/auth-server#with-blitz-auth-api withBlitzAuth} to handle session creation and update
|
||||
*/
|
||||
setSession: (res: Response | ServerResponse) => void
|
||||
}
|
||||
|
||||
// Could be anonymous
|
||||
|
||||
@@ -1,5 +1,212 @@
|
||||
# @blitzjs/next
|
||||
|
||||
## 2.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @blitzjs/rpc@2.2.3
|
||||
- blitz@2.2.3
|
||||
|
||||
## 2.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @blitzjs/rpc@2.2.2
|
||||
- blitz@2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
- @blitzjs/rpc@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3fa3a4ef3: chore: support next.js 15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
- @blitzjs/rpc@2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ce23d4ed0: fix: Update `turbopack-empty.js` syntax to support latest turbopack and next.js versions
|
||||
- blitz@2.1.4
|
||||
- @blitzjs/rpc@2.1.4
|
||||
|
||||
## 2.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0b3286468: chore: bump `next.js` and `zod` versions
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- @blitzjs/rpc@2.1.3
|
||||
- blitz@2.1.3
|
||||
|
||||
## 2.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.2
|
||||
- @blitzjs/rpc@2.1.2
|
||||
|
||||
## 2.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9a0ba87d1]
|
||||
- @blitzjs/rpc@2.1.1
|
||||
- blitz@2.1.1
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3b10b13e6: feat: add blitz auth support for the Web `Request` API standard
|
||||
|
||||
Usage using the new `withBlitzAuth` adapter in the App Router:
|
||||
|
||||
```ts
|
||||
import {withBlitzAuth} from "app/blitz-server"
|
||||
|
||||
export const {POST} = withBlitzAuth({
|
||||
POST: async (_request, _params, ctx) => {
|
||||
const session = ctx.session
|
||||
await session.$revoke()
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
userId: session.userId,
|
||||
}),
|
||||
{status: 200},
|
||||
)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
feat: New Blitz RPC handler meant to with the next.js app router `route.ts` files
|
||||
|
||||
Usage using the new `rpcAppHandler` function
|
||||
|
||||
```ts
|
||||
// app/api/rpc/[[...blitz]]/route.ts
|
||||
import {rpcAppHandler} from "@blitzjs/rpc"
|
||||
import {withBlitzAuth} from "app/blitz-server"
|
||||
|
||||
// Usage with blitz auth
|
||||
export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())
|
||||
|
||||
// Standalone usage
|
||||
export const {GET, POST, HEAD} = rpcAppHandler()
|
||||
```
|
||||
|
||||
chore: Update the app directory starter
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [d53da39cb]
|
||||
- Updated dependencies [3b10b13e6]
|
||||
- blitz@2.1.0
|
||||
- @blitzjs/rpc@2.1.0
|
||||
|
||||
## 2.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [318e9740d]
|
||||
- blitz@2.0.10
|
||||
- @blitzjs/rpc@2.0.10
|
||||
|
||||
## 2.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5a14306f7: fix export `enhancePrisma` in client
|
||||
- Updated dependencies [5a14306f7]
|
||||
- @blitzjs/rpc@2.0.9
|
||||
- blitz@2.0.9
|
||||
|
||||
## 2.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5e61a1681: bug: merge existing and custom blitz turbo configs
|
||||
- Updated dependencies [5e61a1681]
|
||||
- Updated dependencies [77555468f]
|
||||
- blitz@2.0.8
|
||||
- @blitzjs/rpc@2.0.8
|
||||
|
||||
## 2.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ee7bf87ec: Turbopack support for Blitz
|
||||
|
||||
This PR includes the changes required to make the Blitz loaders work with Turbopack.
|
||||
|
||||
Usage:
|
||||
|
||||
```bash
|
||||
pnpm blitz dev --turbo
|
||||
```
|
||||
|
||||
- Updated dependencies [ee7bf87ec]
|
||||
- Updated dependencies [178c152b2]
|
||||
- blitz@2.0.7
|
||||
- @blitzjs/rpc@2.0.7
|
||||
|
||||
## 2.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [76a2544f9]
|
||||
- blitz@2.0.6
|
||||
- @blitzjs/rpc@2.0.6
|
||||
|
||||
## 2.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [6f54841b7]
|
||||
- blitz@2.0.5
|
||||
- @blitzjs/rpc@2.0.5
|
||||
|
||||
## 2.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 28a79040e: feat: export `BlitzServerMiddleware` from blitz-next with stronger types
|
||||
- Updated dependencies [dd604c767]
|
||||
- Updated dependencies [28a79040e]
|
||||
- blitz@2.0.4
|
||||
- @blitzjs/rpc@2.0.4
|
||||
|
||||
## 2.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2f5c8a3a0: Address missing sodium native prebuilds required to use secure-password during server rendering
|
||||
- Updated dependencies [2f5c8a3a0]
|
||||
- @blitzjs/rpc@2.0.3
|
||||
- blitz@2.0.3
|
||||
|
||||
## 2.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [e8fd12e4f]
|
||||
- @blitzjs/rpc@2.0.2
|
||||
- blitz@2.0.2
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/next",
|
||||
"version": "2.0.1",
|
||||
"version": "2.2.3",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,8 +29,9 @@
|
||||
"eslint.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/rpc": "2.0.1",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@types/hoist-non-react-statics": "3.3.1",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"debug": "4.3.3",
|
||||
"fs-extra": "10.0.1",
|
||||
"hoist-non-react-statics": "3.3.2",
|
||||
@@ -38,30 +39,29 @@
|
||||
"supports-color": "8.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.0.1",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"react": "*",
|
||||
"tslog": "4.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@testing-library/dom": "8.13.0",
|
||||
"@testing-library/jest-dom": "5.16.3",
|
||||
"@testing-library/react": "13.4.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@testing-library/user-event": "13.5.0",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"@types/testing-library__react-hooks": "4.0.0",
|
||||
"blitz": "2.0.1",
|
||||
"blitz": "2.2.3",
|
||||
"cross-spawn": "7.0.3",
|
||||
"find-up": "4.1.0",
|
||||
"next": "14.0.4",
|
||||
"next": "15.0.1",
|
||||
"next-router-mock": "0.9.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"resolve-from": "5.0.0",
|
||||
"ts-jest": "27.1.4",
|
||||
"tslog": "4.9.0",
|
||||
|
||||
@@ -170,6 +170,7 @@ function codegen() {
|
||||
const defaultIndexJsPath = path.join(dotBlitzDir, "index.js")
|
||||
const defaultIndexBrowserJSPath = path.join(dotBlitzDir, "index-browser.js")
|
||||
const defaultIndexDTSPath = path.join(dotBlitzDir, "index.d.ts")
|
||||
const emptyJSPath = path.join(dotBlitzDir, "turbopack-empty.js")
|
||||
|
||||
if (!fs.existsSync(defaultIndexJsPath)) {
|
||||
await copyFile(path.join(__dirname, "default-index.js"), defaultIndexJsPath)
|
||||
@@ -181,6 +182,10 @@ function codegen() {
|
||||
if (!fs.existsSync(defaultIndexDTSPath)) {
|
||||
await copyFile(path.join(__dirname, "default-index.d.ts"), defaultIndexDTSPath)
|
||||
}
|
||||
|
||||
if (!fs.existsSync(emptyJSPath)) {
|
||||
await copyFile(path.join(__dirname, "turbopack-empty.js"), emptyJSPath)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
8
packages/blitz-next/scripts/turbopack-empty.js
Normal file
8
packages/blitz-next/scripts/turbopack-empty.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const exports = {
|
||||
"npm-which": {},
|
||||
"cross-spawn": {},
|
||||
fs: {},
|
||||
child_process: {},
|
||||
}
|
||||
|
||||
module.exports = exports
|
||||
@@ -70,7 +70,7 @@ test("handleError forwards along async errors", async () => {
|
||||
//
|
||||
// React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary."
|
||||
// `)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// can recover
|
||||
@@ -116,7 +116,7 @@ test("can pass an error to useErrorHandler", async () => {
|
||||
//
|
||||
// React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary."
|
||||
// `)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// can recover
|
||||
|
||||
@@ -77,25 +77,10 @@ test("standard use-case", () => {
|
||||
const {unmount} = render(<App />)
|
||||
|
||||
userEvent.type(screen.getByRole("textbox", {name: /username/i}), "fail")
|
||||
|
||||
const [[actualError], [componentStack]] = consoleError.mock.calls
|
||||
expect(firstLine(actualError as string)).toMatchInlineSnapshot(
|
||||
`"Error: Uncaught [Error: 💥 CABOOM 💥]"`,
|
||||
)
|
||||
expect(cleanStack(componentStack)).toMatchInlineSnapshot(`
|
||||
"Error: Uncaught [Error: 💥 CABOOM 💥]
|
||||
at reportException
|
||||
at innerInvokeEventListeners
|
||||
at invokeEventListeners
|
||||
at HTMLUnknownElementImpl._dispatch
|
||||
at HTMLUnknownElementImpl.dispatchEvent
|
||||
at HTMLUnknownElement.dispatchEvent
|
||||
at Object.invokeGuardedCallbackDev
|
||||
at invokeGuardedCallback
|
||||
at beginWork\$1
|
||||
at performUnitOfWork "
|
||||
`)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
const calls = consoleError.mock.calls[0]
|
||||
//@ts-expect-error - it's a mock
|
||||
expect(calls[1]).toMatchInlineSnapshot("[Error: 💥 CABOOM 💥]")
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
expect(screen.getByRole("alert")).toMatchInlineSnapshot(`
|
||||
@@ -149,7 +134,7 @@ test("fallbackRender prop", () => {
|
||||
}
|
||||
|
||||
const {unmount} = render(<App />)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// the render prop API allows a single action to reset the app state
|
||||
@@ -168,7 +153,7 @@ test("simple fallback is supported", () => {
|
||||
<span>child</span>
|
||||
</ErrorBoundary>,
|
||||
)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
expect(screen.getByText(/oh no/i)).to.exist
|
||||
expect(screen.queryByText(/child/i)).to.not.exist
|
||||
@@ -183,27 +168,16 @@ test("withErrorBoundary HOC", () => {
|
||||
() => {
|
||||
throw new Error("💥 CABOOM 💥")
|
||||
},
|
||||
{FallbackComponent: ErrorFallback, onError: onErrorHandler},
|
||||
{
|
||||
FallbackComponent: ErrorFallback,
|
||||
onError: onErrorHandler,
|
||||
},
|
||||
)
|
||||
const {unmount} = render(<Boundary />)
|
||||
|
||||
const [[actualError], [componentStack]] = consoleError.mock.calls
|
||||
const firstLineOfError = firstLine(actualError as string)
|
||||
expect(firstLineOfError).toMatchInlineSnapshot(`"Error: Uncaught [Error: 💥 CABOOM 💥]"`)
|
||||
expect(cleanStack(componentStack)).toMatchInlineSnapshot(`
|
||||
"Error: Uncaught [Error: 💥 CABOOM 💥]
|
||||
at reportException
|
||||
at innerInvokeEventListeners
|
||||
at invokeEventListeners
|
||||
at HTMLUnknownElementImpl._dispatch
|
||||
at HTMLUnknownElementImpl.dispatchEvent
|
||||
at HTMLUnknownElement.dispatchEvent
|
||||
at Object.invokeGuardedCallbackDev
|
||||
at invokeGuardedCallback
|
||||
at beginWork\$1
|
||||
at performUnitOfWork "
|
||||
`)
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
const calls = consoleError.mock.calls[0]
|
||||
//@ts-expect-error - it's a mock
|
||||
expect(calls[1]).toMatchInlineSnapshot("[Error: 💥 CABOOM 💥]")
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
const [error, onErrorComponentStack] = (onErrorHandler.mock.calls as [[Error, string]])[0]
|
||||
@@ -265,7 +239,6 @@ test("requires either a fallback, fallbackRender, or FallbackComponent", () => {
|
||||
let unmount: undefined | (() => void)
|
||||
expect(() => {
|
||||
const result = render(
|
||||
// @ts-expect-error we're testing the runtime check of missing props here
|
||||
<ErrorBoundary>
|
||||
<Bomb />
|
||||
</ErrorBoundary>,
|
||||
@@ -318,7 +291,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
// blow it up
|
||||
userEvent.click(screen.getByText("toggle explode"))
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// recover via try again button
|
||||
@@ -333,7 +306,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
// blow it up again
|
||||
userEvent.click(screen.getByText("toggle explode"))
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// recover via resetKeys change
|
||||
@@ -348,7 +321,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
// blow it up again
|
||||
userEvent.click(screen.getByText("toggle explode"))
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// toggles adding an extra resetKey to the array
|
||||
@@ -358,7 +331,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
expect(handleResetKeysChange).toHaveBeenCalledWith([true], [true, true])
|
||||
handleResetKeysChange.mockClear()
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// toggle explode back to false
|
||||
@@ -369,7 +342,7 @@ test("supports automatic reset of error boundary when resetKeys change", () => {
|
||||
expect(handleResetKeysChange).toHaveBeenCalledWith([true, true], [false, true])
|
||||
expect(screen.getByRole("alert")).to.exist
|
||||
handleResetKeysChange.mockClear()
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// toggle extra resetKey
|
||||
@@ -411,7 +384,7 @@ test("supports reset via resetKeys right after error is triggered on component m
|
||||
|
||||
// it blows up on render
|
||||
expect(screen.queryByRole("alert", {})).to.exist
|
||||
expect(consoleError).toHaveBeenCalledTimes(3)
|
||||
expect(consoleError).toHaveBeenCalledTimes(1)
|
||||
consoleError.mockClear()
|
||||
|
||||
// recover via "toggle explode" button
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {RedirectError} from "blitz"
|
||||
import {useRouter} from "next/compat/router"
|
||||
import type {NextRouter} from "next/router"
|
||||
import * as React from "react"
|
||||
import React from "react"
|
||||
import {RouterContext} from "./router-context"
|
||||
import _debug from "debug"
|
||||
import type {ExcludeRouterProps, WithRouterProps} from "next/dist/client/with-router"
|
||||
@@ -77,7 +77,7 @@ const initialState: ErrorBoundaryState = {error: null}
|
||||
function withRouter<P extends WithRouterProps>(
|
||||
ComposedComponent: React.ComponentType<P>,
|
||||
): React.ComponentType<ExcludeRouterProps<P>> {
|
||||
function WithRouterWrapper(props: any): JSX.Element {
|
||||
function WithRouterWrapper(props: any): React.JSX.Element {
|
||||
return <ComposedComponent router={useRouter()} {...props} />
|
||||
}
|
||||
|
||||
@@ -114,7 +114,13 @@ export const ErrorBoundary = withRouter(
|
||||
await this.props.router.push(error.url)
|
||||
return
|
||||
}
|
||||
this.props.onError?.(error, info)
|
||||
if (this.props.onError) {
|
||||
let componentStack = info.componentStack
|
||||
if (!componentStack) {
|
||||
componentStack = new Error("Stack trace").stack || ""
|
||||
}
|
||||
this.props.onError(error, {componentStack})
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -190,7 +196,7 @@ export const ErrorBoundary = withRouter(
|
||||
},
|
||||
)
|
||||
|
||||
function withErrorBoundary<P extends JSX.IntrinsicAttributes>(
|
||||
function withErrorBoundary<P extends React.JSX.IntrinsicAttributes>(
|
||||
Component: React.ComponentType<P>,
|
||||
errorBoundaryProps: ErrorBoundaryProps,
|
||||
): React.ComponentType<P> {
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import React from "react"
|
||||
import {NextPageContext} from "next"
|
||||
import dynamic from "next/dynamic"
|
||||
const Head = dynamic(() => import("next/head").then((mod) => mod.default), {
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
})
|
||||
const Head = dynamic(
|
||||
() =>
|
||||
import("next/head").then((mod) => ({
|
||||
default: mod.default,
|
||||
})),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
},
|
||||
)
|
||||
|
||||
const statusCodes: {[code: number]: string} = {
|
||||
400: "Bad Request",
|
||||
|
||||
@@ -9,10 +9,16 @@ import type {Router} from "next/router"
|
||||
import {BlitzProvider} from "./provider"
|
||||
import dynamic from "next/dynamic"
|
||||
export {Routes} from ".blitz"
|
||||
const Head = dynamic(() => import("next/head").then((mod) => mod.default), {
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
})
|
||||
const Head = dynamic(
|
||||
() =>
|
||||
import("next/head").then((mod) => ({
|
||||
default: mod.default,
|
||||
})),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => null,
|
||||
},
|
||||
)
|
||||
|
||||
export {BlitzProvider} from "./provider"
|
||||
|
||||
@@ -55,7 +61,7 @@ type RedirectAuthenticatedToFnCtx = {
|
||||
}
|
||||
type RedirectAuthenticatedToFn = (args: RedirectAuthenticatedToFnCtx) => RedirectAuthenticatedTo
|
||||
export type BlitzPage<P = {}> = React.ComponentType<P> & {
|
||||
getLayout?: (component: JSX.Element) => JSX.Element
|
||||
getLayout?: (component: React.JSX.Element) => React.JSX.Element
|
||||
authenticate?: boolean | {redirectTo?: string | RouteUrlObject; role?: string | Array<string>}
|
||||
suppressFirstRenderFlicker?: boolean
|
||||
redirectAuthenticatedTo?: RedirectAuthenticatedTo | RedirectAuthenticatedToFn
|
||||
|
||||
@@ -22,11 +22,13 @@ import {
|
||||
RouteUrlObject,
|
||||
startWatcher,
|
||||
stopWatcher,
|
||||
RequestMiddleware,
|
||||
} from "blitz"
|
||||
import {
|
||||
getInfiniteQueryKey,
|
||||
getQueryKey,
|
||||
installWebpackConfig,
|
||||
installTurboConfig,
|
||||
InstallWebpackConfigOptions,
|
||||
ResolverPathOptions,
|
||||
DefaultOptions,
|
||||
@@ -38,6 +40,9 @@ import {withSuperJsonProps} from "./superjson"
|
||||
import {ParsedUrlQuery} from "querystring"
|
||||
import {PreviewData} from "next/types"
|
||||
import {resolveHref} from "next/dist/client/resolve-href"
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
import CopyPlugin from "copy-webpack-plugin"
|
||||
|
||||
export * from "./index-browser"
|
||||
|
||||
@@ -238,6 +243,7 @@ export interface BlitzConfig extends NextConfig {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" &&
|
||||
@@ -268,6 +274,31 @@ export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig {
|
||||
},
|
||||
})
|
||||
|
||||
if (!process.env.TURBOPACK) {
|
||||
try {
|
||||
const sodiumNativePath = fs.realpathSync(
|
||||
path.join(require.resolve("sodium-native"), ".."),
|
||||
)
|
||||
const dotNextDirectory = `${process.cwd()}/.next`
|
||||
config.plugins.push(
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
//dev
|
||||
from: `${sodiumNativePath}/prebuilds/`,
|
||||
to: `${dotNextDirectory}/server/vendor-chunks/prebuilds/`,
|
||||
},
|
||||
{
|
||||
//prod
|
||||
from: `${sodiumNativePath}/prebuilds/`,
|
||||
to: `${dotNextDirectory}/server/chunks/prebuilds/`,
|
||||
},
|
||||
],
|
||||
}),
|
||||
)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if (typeof nextConfig.webpack === "function") {
|
||||
return nextConfig.webpack(config, options)
|
||||
}
|
||||
@@ -275,6 +306,26 @@ export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig {
|
||||
},
|
||||
})
|
||||
|
||||
if (process.env.TURBOPACK) {
|
||||
const blitzTurboConfig = installTurboConfig()
|
||||
config.experimental = {
|
||||
...config.experimental,
|
||||
turbo: {
|
||||
loaders: {
|
||||
...config.experimental?.turbo?.loaders,
|
||||
},
|
||||
resolveAlias: {
|
||||
...config.experimental?.turbo?.resolveAlias,
|
||||
...blitzTurboConfig.resolveAlias,
|
||||
},
|
||||
rules: {
|
||||
...config.experimental?.turbo?.rules,
|
||||
...blitzTurboConfig.rules,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const {blitz, ...rest} = config
|
||||
return rest
|
||||
}
|
||||
@@ -323,3 +374,15 @@ declare module "blitz" {
|
||||
prefetchInfiniteQuery: PrefetchQueryFn
|
||||
}
|
||||
}
|
||||
|
||||
export const BlitzServerMiddleware = <
|
||||
TMiddleware extends RequestMiddleware<NextApiRequest, BlitzNextApiResponse> = RequestMiddleware<
|
||||
NextApiRequest,
|
||||
BlitzNextApiResponse
|
||||
>,
|
||||
>(
|
||||
middleware: TMiddleware,
|
||||
): BlitzServerPlugin<{}> => ({
|
||||
requestMiddlewares: [middleware],
|
||||
exports: () => ({}),
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@ import type {QueryClient, HydrateOptions} from "@blitzjs/rpc"
|
||||
import React from "react"
|
||||
|
||||
export type BlitzProviderProps = {
|
||||
children: JSX.Element
|
||||
children: React.JSX.Element
|
||||
client?: QueryClient
|
||||
contextSharing?: boolean
|
||||
dehydratedState?: unknown
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import React from "react"
|
||||
import {describe, it, expect, vi, afterEach} from "vitest"
|
||||
import {extractRouterParams, useParam, useParams} from "./use-params"
|
||||
import {renderHook as defaultRenderHook} from "@testing-library/react-hooks"
|
||||
import {renderHook as defaultRenderHook} from "@testing-library/react"
|
||||
import {NextRouter} from "next/router"
|
||||
import {RouterContext} from "./router-context"
|
||||
|
||||
|
||||
@@ -1,5 +1,193 @@
|
||||
# @blitzjs/rpc
|
||||
|
||||
## 2.2.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.3
|
||||
|
||||
## 2.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3fa3a4ef3: chore: support next.js 15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [565db3c5a]
|
||||
- Updated dependencies [3fa3a4ef3]
|
||||
- blitz@2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.4
|
||||
|
||||
## 2.1.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 0b3286468: chore: bump `next.js` and `zod` versions
|
||||
- Updated dependencies [0b3286468]
|
||||
- Updated dependencies [50f17d21c]
|
||||
- blitz@2.1.3
|
||||
|
||||
## 2.1.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.1.2
|
||||
|
||||
## 2.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 9a0ba87d1: fix: make sure blitz superjson custom error registers in rpc handler
|
||||
- Updated dependencies [9a0ba87d1]
|
||||
- blitz@2.1.1
|
||||
|
||||
## 2.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- 3b10b13e6: feat: add blitz auth support for the Web `Request` API standard
|
||||
|
||||
Usage using the new `withBlitzAuth` adapter in the App Router:
|
||||
|
||||
```ts
|
||||
import {withBlitzAuth} from "app/blitz-server"
|
||||
|
||||
export const {POST} = withBlitzAuth({
|
||||
POST: async (_request, _params, ctx) => {
|
||||
const session = ctx.session
|
||||
await session.$revoke()
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
userId: session.userId,
|
||||
}),
|
||||
{status: 200},
|
||||
)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
feat: New Blitz RPC handler meant to with the next.js app router `route.ts` files
|
||||
|
||||
Usage using the new `rpcAppHandler` function
|
||||
|
||||
```ts
|
||||
// app/api/rpc/[[...blitz]]/route.ts
|
||||
import {rpcAppHandler} from "@blitzjs/rpc"
|
||||
import {withBlitzAuth} from "app/blitz-server"
|
||||
|
||||
// Usage with blitz auth
|
||||
export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())
|
||||
|
||||
// Standalone usage
|
||||
export const {GET, POST, HEAD} = rpcAppHandler()
|
||||
```
|
||||
|
||||
chore: Update the app directory starter
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [d53da39cb]
|
||||
- Updated dependencies [3b10b13e6]
|
||||
- blitz@2.1.0
|
||||
|
||||
## 2.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [318e9740d]
|
||||
- blitz@2.0.10
|
||||
|
||||
## 2.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5a14306f7: fix export `enhancePrisma` in client
|
||||
- Updated dependencies [5a14306f7]
|
||||
- blitz@2.0.9
|
||||
|
||||
## 2.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5e61a1681]
|
||||
- Updated dependencies [77555468f]
|
||||
- blitz@2.0.8
|
||||
|
||||
## 2.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ee7bf87ec: Turbopack support for Blitz
|
||||
|
||||
This PR includes the changes required to make the Blitz loaders work with Turbopack.
|
||||
|
||||
Usage:
|
||||
|
||||
```bash
|
||||
pnpm blitz dev --turbo
|
||||
```
|
||||
|
||||
- Updated dependencies [ee7bf87ec]
|
||||
- Updated dependencies [178c152b2]
|
||||
- blitz@2.0.7
|
||||
|
||||
## 2.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [76a2544f9]
|
||||
- blitz@2.0.6
|
||||
|
||||
## 2.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [6f54841b7]
|
||||
- blitz@2.0.5
|
||||
|
||||
## 2.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [dd604c767]
|
||||
- Updated dependencies [28a79040e]
|
||||
- blitz@2.0.4
|
||||
|
||||
## 2.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 2f5c8a3a0: Address missing sodium native prebuilds required to use secure-password during server rendering
|
||||
- Updated dependencies [2f5c8a3a0]
|
||||
- blitz@2.0.3
|
||||
|
||||
## 2.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- e8fd12e4f: Fix: windows slash correction for rpc resolvers
|
||||
- Updated dependencies [e8fd12e4f]
|
||||
- blitz@2.0.2
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/rpc",
|
||||
"version": "2.0.1",
|
||||
"version": "2.2.3",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -37,25 +37,25 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/query-core": "4.24.4",
|
||||
"blitz": "2.0.1",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"react": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/auth": "2.0.1",
|
||||
"@blitzjs/config": "2.0.1",
|
||||
"@blitzjs/auth": "2.2.3",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@tanstack/query-core": "4.24.4",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react-dom": "17.0.14",
|
||||
"blitz": "2.0.1",
|
||||
"next": "14.0.4",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"unbuild": "0.7.6",
|
||||
"watch": "1.0.2",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {assert, Ctx, ResolverConfig} from "blitz"
|
||||
import {assert, Ctx, ResolverConfig, registerBlitzErrorClasses} from "blitz"
|
||||
import {NextApiRequest, NextApiResponse} from "next"
|
||||
import {resolve} from "path"
|
||||
import {deserialize, parse, serialize as superjsonSerialize} from "superjson"
|
||||
@@ -119,6 +119,7 @@ export interface InstallWebpackConfigOptions {
|
||||
[key: string]: boolean | string
|
||||
}
|
||||
}
|
||||
plugins: any[]
|
||||
module: {
|
||||
rules: WebpackRule[]
|
||||
}
|
||||
@@ -156,6 +157,51 @@ export function installWebpackConfig({
|
||||
})
|
||||
}
|
||||
|
||||
export function installTurboConfig() {
|
||||
return {
|
||||
resolveAlias: {
|
||||
"cross-spawn": {browser: ".blitz/turbopack-empty.js"},
|
||||
"npm-which": {browser: ".blitz/turbopack-empty.js"},
|
||||
fs: {browser: ".blitz/turbopack-empty.js"},
|
||||
child_process: {browser: ".blitz/turbopack-empty.js"},
|
||||
},
|
||||
rules: {
|
||||
"**/*...blitz*.{jsx,tsx,js,ts}": {
|
||||
default: {
|
||||
loaders: [{loader: loaderServer, options: {}}],
|
||||
as: "*.ts",
|
||||
},
|
||||
},
|
||||
"**/*...blitz*/route.{jsx,tsx,js,ts}": {
|
||||
default: {
|
||||
loaders: [{loader: loaderServer, options: {}}],
|
||||
as: "*.ts",
|
||||
},
|
||||
},
|
||||
"**/{queries,mutations}/**": {
|
||||
browser: {
|
||||
loaders: [
|
||||
{
|
||||
loader: loaderClient,
|
||||
options: {},
|
||||
},
|
||||
],
|
||||
as: "*.ts",
|
||||
},
|
||||
default: {
|
||||
loaders: [
|
||||
{
|
||||
loader: loaderServerResolvers,
|
||||
options: {},
|
||||
},
|
||||
],
|
||||
as: "*.ts",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
// END LOADER
|
||||
// ----------
|
||||
@@ -175,7 +221,7 @@ async function getResolverMap(): Promise<ResolverFiles | null | undefined> {
|
||||
// Handles:
|
||||
// - Vite
|
||||
// {
|
||||
// const {resolverFilesLoaded, viteProvider} = await loadTelefuncFilesWithVite(runContext)
|
||||
// const {resolverFilesLoaded, viteProvider} = await loadTelefuncFilesWithVite(run
|
||||
// if (resolverFilesLoaded) {
|
||||
// assertUsage(
|
||||
// Object.keys(resolverFilesLoaded).length > 0,
|
||||
@@ -187,12 +233,13 @@ async function getResolverMap(): Promise<ResolverFiles | null | undefined> {
|
||||
}
|
||||
|
||||
interface RpcConfig {
|
||||
onError?: (error: Error, ctx: Ctx) => void
|
||||
formatError?: (error: Error, ctx: Ctx) => Error
|
||||
onError?: (error: Error, ctx?: Ctx) => void
|
||||
formatError?: (error: Error, ctx?: Ctx) => Error
|
||||
logging?: RpcLoggerOptions
|
||||
}
|
||||
|
||||
export function rpcHandler(config: RpcConfig) {
|
||||
export function rpcHandler(config?: RpcConfig) {
|
||||
registerBlitzErrorClasses()
|
||||
return async function handleRpcRequest(req: NextApiRequest, res: NextApiResponse, ctx: Ctx) {
|
||||
const resolverMap = await getResolverMap()
|
||||
assert(resolverMap, "No query or mutation resolvers found")
|
||||
@@ -204,7 +251,7 @@ export function rpcHandler(config: RpcConfig) {
|
||||
const relativeRoutePath = (req.query.blitz as string[])?.join("/")
|
||||
const routePath = "/" + relativeRoutePath
|
||||
const resolverName = routePath.replace(/(\/api\/rpc)?\//, "")
|
||||
const rpcLogger = new RpcLogger(resolverName, config.logging)
|
||||
const rpcLogger = new RpcLogger(resolverName, config?.logging)
|
||||
|
||||
const loadableResolver = resolverMap?.[routePath]?.resolver
|
||||
if (!loadableResolver) {
|
||||
@@ -263,6 +310,7 @@ export function rpcHandler(config: RpcConfig) {
|
||||
|
||||
rpcLogger.timer.initNextJsSerialization()
|
||||
;(res as any).blitzResult = result
|
||||
ctx?.session?.setSession(res)
|
||||
res.json({
|
||||
result: serializedResult.json,
|
||||
error: null,
|
||||
@@ -282,16 +330,18 @@ export function rpcHandler(config: RpcConfig) {
|
||||
error.stack = ""
|
||||
}
|
||||
|
||||
config.onError?.(error, ctx)
|
||||
config?.onError?.(error, ctx)
|
||||
rpcLogger.error(error)
|
||||
|
||||
if (!error.statusCode) {
|
||||
error.statusCode = 500
|
||||
}
|
||||
|
||||
const formattedError = config.formatError?.(error, ctx) ?? error
|
||||
const formattedError = config?.formatError?.(error, ctx) ?? error
|
||||
const serializedError = superjsonSerialize(formattedError)
|
||||
|
||||
ctx?.session?.setSession(res)
|
||||
|
||||
res.json({
|
||||
result: null,
|
||||
error: serializedError.json,
|
||||
@@ -309,3 +359,130 @@ export function rpcHandler(config: RpcConfig) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Params = Record<string, unknown>
|
||||
|
||||
export function rpcAppHandler(config?: RpcConfig) {
|
||||
registerBlitzErrorClasses()
|
||||
async function handleRpcRequest(req: Request, segmentData: {params: Promise<Params>}, ctx?: Ctx) {
|
||||
const params = await segmentData.params
|
||||
const session = ctx?.session
|
||||
const resolverMap = await getResolverMap()
|
||||
assert(resolverMap, "No query or mutation resolvers found")
|
||||
|
||||
assert(
|
||||
Array.isArray(params.blitz),
|
||||
"It seems your Blitz RPC endpoint file is not named [[...blitz]].(jt)s. Please ensure it is",
|
||||
)
|
||||
|
||||
const relativeRoutePath = (params.blitz as string[])?.join("/")
|
||||
const routePath = "/" + relativeRoutePath
|
||||
const resolverName = routePath.replace(/(\/api\/rpc)?\//, "")
|
||||
const rpcLogger = new RpcLogger(resolverName, config?.logging)
|
||||
|
||||
const loadableResolver = resolverMap?.[routePath]?.resolver
|
||||
if (!loadableResolver) {
|
||||
throw new Error("No resolver for path: " + routePath)
|
||||
}
|
||||
|
||||
const {default: resolver, config: resolverConfig} = await loadableResolver()
|
||||
|
||||
if (!resolver) {
|
||||
throw new Error("No default export for resolver path: " + routePath)
|
||||
}
|
||||
|
||||
const resolverConfigWithDefaults = {...defaultConfig, ...resolverConfig}
|
||||
|
||||
if (req.method === "HEAD") {
|
||||
// We used to initiate database connection here
|
||||
return new Response(null, {status: 200})
|
||||
}
|
||||
|
||||
if (
|
||||
req.method === "POST" ||
|
||||
(req.method === "GET" && resolverConfigWithDefaults.httpMethod === "GET")
|
||||
) {
|
||||
const body = await req.json()
|
||||
if (req.method === "POST" && typeof body.params === "undefined") {
|
||||
const error = {message: "Request body is missing the `params` key"}
|
||||
rpcLogger.error(error.message)
|
||||
return new Response(JSON.stringify({result: null, error}), {status: 400})
|
||||
}
|
||||
|
||||
try {
|
||||
const data = deserialize({
|
||||
json:
|
||||
req.method === "POST"
|
||||
? body.params
|
||||
: params.params
|
||||
? parse(`${params.params}`)
|
||||
: undefined,
|
||||
meta:
|
||||
req.method === "POST"
|
||||
? body.meta?.params
|
||||
: params.meta
|
||||
? parse(`${params.meta}`)
|
||||
: undefined,
|
||||
})
|
||||
rpcLogger.timer.initResolver()
|
||||
rpcLogger.preResolver(data)
|
||||
|
||||
const result = await resolver(data, {session})
|
||||
rpcLogger.timer.resolverDuration()
|
||||
rpcLogger.postResolver(result)
|
||||
|
||||
rpcLogger.timer.initSerialization()
|
||||
const serializedResult = superjsonSerialize(result)
|
||||
|
||||
rpcLogger.timer.initNextJsSerialization()
|
||||
const response = new Response(
|
||||
JSON.stringify({
|
||||
result: serializedResult.json,
|
||||
error: null,
|
||||
meta: {
|
||||
result: serializedResult.meta,
|
||||
},
|
||||
}),
|
||||
)
|
||||
session?.setSession(response)
|
||||
return response
|
||||
} catch (error: any) {
|
||||
if (error._clearStack) {
|
||||
error.stack = ""
|
||||
}
|
||||
|
||||
config?.onError?.(error, {session} as Ctx)
|
||||
rpcLogger.error(error)
|
||||
|
||||
if (!error.statusCode) {
|
||||
error.statusCode = 500
|
||||
}
|
||||
|
||||
const formattedError = config?.formatError?.(error, {session} as Ctx) ?? error
|
||||
const serializedError = superjsonSerialize(formattedError)
|
||||
|
||||
const response = new Response(
|
||||
JSON.stringify({
|
||||
result: null,
|
||||
error: serializedError.json,
|
||||
meta: {
|
||||
error: serializedError.meta,
|
||||
},
|
||||
}),
|
||||
)
|
||||
session?.setSession(response)
|
||||
return response
|
||||
}
|
||||
} else {
|
||||
// Everything else is error
|
||||
rpcLogger.warn(`${req.method} method not supported`)
|
||||
return new Response(null, {status: 404})
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
GET: handleRpcRequest,
|
||||
POST: handleRpcRequest,
|
||||
HEAD: handleRpcRequest,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {QueryClientProvider} from "@tanstack/react-query"
|
||||
import React from "react"
|
||||
|
||||
export type BlitzProviderType = ({children}: {children: React.ReactNode}) => JSX.Element
|
||||
export type BlitzProviderType = ({children}: {children: React.ReactNode}) => React.JSX.Element
|
||||
|
||||
const BlitzProvider: BlitzProviderType = ({children}) => {
|
||||
const [queryClient] = React.useState(globalThis.queryClient)
|
||||
|
||||
@@ -14,12 +14,24 @@ import {getResolverConfig} from "../../parsers/parse-rpc-config"
|
||||
// Subset of `import type { LoaderDefinitionFunction } from 'webpack'`
|
||||
|
||||
export async function loader(this: Loader, input: string): Promise<string> {
|
||||
const compiler = this._compiler!
|
||||
const id = this.resource
|
||||
const root = this._compiler!.context
|
||||
const root = this.rootContext
|
||||
|
||||
const isSSR = compiler.name === "server"
|
||||
if (!isSSR) {
|
||||
// Webpack has `_compiler` property. Turbopack does not.
|
||||
const webpackCompilerName = this._compiler?.name
|
||||
if (webpackCompilerName) {
|
||||
const isSSR = webpackCompilerName === "server"
|
||||
if (!isSSR) {
|
||||
return await transformBlitzRpcResolverClient(
|
||||
input,
|
||||
toPosixPath(id),
|
||||
toPosixPath(root),
|
||||
this.query,
|
||||
)
|
||||
}
|
||||
// Handle Turbopack / other bundlers case.
|
||||
// The decision of which environment to run the loader in is decided by the loader configuration instead.
|
||||
} else {
|
||||
return await transformBlitzRpcResolverClient(
|
||||
input,
|
||||
toPosixPath(id),
|
||||
|
||||
@@ -13,12 +13,24 @@ import {posix} from "path"
|
||||
// Subset of `import type { LoaderDefinitionFunction } from 'webpack'`
|
||||
|
||||
export async function loader(this: Loader, input: string): Promise<string> {
|
||||
const compiler = this._compiler!
|
||||
const id = this.resource
|
||||
const root = this._compiler!.context
|
||||
const root = this.rootContext
|
||||
|
||||
const isSSR = compiler.name === "server"
|
||||
if (isSSR) {
|
||||
// Webpack has `_compiler` property. Turbopack does not.
|
||||
const webpackCompilerName = this._compiler?.name
|
||||
if (webpackCompilerName) {
|
||||
const isSSR = webpackCompilerName === "server"
|
||||
if (isSSR) {
|
||||
return await transformBlitzRpcResolverServer(
|
||||
input,
|
||||
toPosixPath(id),
|
||||
toPosixPath(root),
|
||||
this.query,
|
||||
)
|
||||
}
|
||||
// Handle Turbopack / other bundlers case.
|
||||
// The decision of which environment to run the loader in is decided by the loader configuration instead.
|
||||
} else {
|
||||
return await transformBlitzRpcResolverServer(
|
||||
input,
|
||||
toPosixPath(id),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {join} from "path"
|
||||
import {join, relative} from "path"
|
||||
import {promises} from "fs"
|
||||
import {
|
||||
assertPosixPath,
|
||||
@@ -14,17 +14,37 @@ import {
|
||||
// Subset of `import type { LoaderDefinitionFunction } from 'webpack'`
|
||||
|
||||
export async function loader(this: Loader, input: string): Promise<string> {
|
||||
const compiler = this._compiler!
|
||||
const id = this.resource
|
||||
const root = this._compiler!.context
|
||||
const root = this.rootContext
|
||||
const rpcFolders = this.query.includeRPCFolders ? this.query.includeRPCFolders : []
|
||||
|
||||
const isSSR = compiler.name === "server"
|
||||
if (isSSR) {
|
||||
// Webpack has `_compiler` property. Turbopack does not.
|
||||
const webpackCompilerName = this._compiler?.name
|
||||
if (webpackCompilerName) {
|
||||
const isSSR = webpackCompilerName === "server"
|
||||
if (isSSR) {
|
||||
this.cacheable(false)
|
||||
|
||||
const resolvers = await collectResolvers(root, rpcFolders, ["ts", "js", "tsx", "jsx"])
|
||||
|
||||
return await transformBlitzRpcServer(
|
||||
this.context,
|
||||
input,
|
||||
toPosixPath(id),
|
||||
toPosixPath(root),
|
||||
resolvers,
|
||||
this.query,
|
||||
)
|
||||
}
|
||||
// Handle Turbopack / other bundlers case.
|
||||
// The decision of which environment to run the loader in is decided by the loader configuration instead.
|
||||
} else {
|
||||
this.cacheable(false)
|
||||
|
||||
const resolvers = await collectResolvers(root, rpcFolders, ["ts", "js", "tsx", "jsx"])
|
||||
|
||||
return await transformBlitzRpcServer(
|
||||
this.context,
|
||||
input,
|
||||
toPosixPath(id),
|
||||
toPosixPath(root),
|
||||
@@ -43,6 +63,7 @@ function slash(str: string) {
|
||||
}
|
||||
|
||||
export async function transformBlitzRpcServer(
|
||||
context: string,
|
||||
src: string,
|
||||
id: string,
|
||||
root: string,
|
||||
@@ -66,9 +87,11 @@ export async function transformBlitzRpcServer(
|
||||
|
||||
const importStrategy = options?.resolversDynamicImport ? "import" : "require"
|
||||
|
||||
code += `__internal_addBlitzRpcResolver('${routePath}','${resolverFilePath}',() => ${importStrategy}('${slash(
|
||||
code += `__internal_addBlitzRpcResolver('${routePath}','${slash(
|
||||
resolverFilePath,
|
||||
)}'));`
|
||||
)}',() => ${importStrategy}('${slash(
|
||||
relative(context, resolverFilePath).replace(/\\/g, "/"),
|
||||
)}'))`
|
||||
code += "\n"
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,11 @@ export interface LoaderOptions {
|
||||
}
|
||||
|
||||
export interface Loader {
|
||||
_compiler?: {
|
||||
_compiler: {
|
||||
name: string
|
||||
context: string
|
||||
}
|
||||
rootContext: string
|
||||
context: string
|
||||
resource: string
|
||||
cacheable: (enabled: boolean) => void
|
||||
query: LoaderOptions
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user