Compare commits
75 Commits
@blitzjs/n
...
blitz@2.2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
030c8135b9 | ||
|
|
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 |
@@ -4024,6 +4024,116 @@
|
||||
"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/dull-fireants-retire.md
Normal file
5
.changeset/dull-fireants-retire.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@blitzjs/auth": patch
|
||||
---
|
||||
|
||||
Upgrade cookie-session dependency to v2.1.1
|
||||
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
|
||||
42
.github/workflows/main.yml
vendored
42
.github/workflows/main.yml
vendored
@@ -16,14 +16,14 @@ jobs:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8.6.5
|
||||
version: 8.6.6
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -37,14 +37,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: pnpm/action-setup@v2.2.4
|
||||
- uses: actions/checkout@v5
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8.6.5
|
||||
version: 8.6.6
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- name: Build
|
||||
@@ -65,17 +65,17 @@ jobs:
|
||||
NODE_VERSION: 18
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@v2.2.4
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8.6.5
|
||||
version: 8.6.6
|
||||
|
||||
- name: Setup node@16
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
outputs:
|
||||
folders: ${{ steps.set-matrix.outputs.folders }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v5
|
||||
- id: set-matrix
|
||||
name: "Find all folders"
|
||||
shell: bash
|
||||
@@ -125,19 +125,19 @@ jobs:
|
||||
- run: echo ${{matrix.folder}}
|
||||
- name: Checkout
|
||||
if: matrix.folder != 'next-13-app-dir' || matrix.os != 'windows-latest'
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- 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
|
||||
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
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 18
|
||||
node-version: 20
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
|
||||
26
.github/workflows/pr-release.yml
vendored
26
.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"
|
||||
|
||||
|
||||
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
|
||||
20
README.md
20
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-424-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>
|
||||
@@ -748,6 +751,21 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<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,187 @@
|
||||
# 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
|
||||
|
||||
@@ -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.4",
|
||||
"version": "0.1.20",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"blitz:dev": "next dev",
|
||||
@@ -12,28 +12,28 @@
|
||||
"schema": "prisma/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@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.3",
|
||||
"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.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@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.3",
|
||||
"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.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@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.3",
|
||||
"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.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@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.3",
|
||||
"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.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@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.3",
|
||||
"@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.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.3",
|
||||
"@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.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.3",
|
||||
"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.3",
|
||||
"@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.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"blitz": "2.0.3",
|
||||
"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.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.3",
|
||||
"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.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.3",
|
||||
"@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.3",
|
||||
"@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.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@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.3",
|
||||
"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.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.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.3",
|
||||
"@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.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"blitz": "2.0.3",
|
||||
"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.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"blitz": "2.0.3",
|
||||
"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.3",
|
||||
"@blitzjs/next": "2.0.3",
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.3",
|
||||
"@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.3",
|
||||
"@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.3",
|
||||
"@blitzjs/next": "workspace:2.0.3",
|
||||
"@blitzjs/rpc": "workspace:2.0.3",
|
||||
"@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,173 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/auth",
|
||||
"version": "2.0.3",
|
||||
"version": "2.2.3",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -28,14 +28,14 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/b64-lite": "1.3.0",
|
||||
"@types/cookie-session": "2.0.44",
|
||||
"@types/cookie-session": "2.0.49",
|
||||
"@types/oauth": "0.9.1",
|
||||
"@types/passport": "1.0.7",
|
||||
"@types/secure-password": "3.1.1",
|
||||
"b64-lite": "1.4.0",
|
||||
"bad-behavior": "1.0.1",
|
||||
"cookie": "0.4.1",
|
||||
"cookie-session": "2.0.0",
|
||||
"cookie-session": "2.1.1",
|
||||
"debug": "4.3.3",
|
||||
"find-up": "4.1.0",
|
||||
"http": "0.0.1-security",
|
||||
@@ -50,7 +50,7 @@
|
||||
"url": "0.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.0.3",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"next-auth": "*",
|
||||
"secure-password": "4.0.0"
|
||||
@@ -67,19 +67,18 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@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.3",
|
||||
"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,195 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/next",
|
||||
"version": "2.0.3",
|
||||
"version": "2.2.3",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,7 +29,7 @@
|
||||
"eslint.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/rpc": "2.0.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@types/hoist-non-react-statics": "3.3.1",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"debug": "4.3.3",
|
||||
@@ -39,30 +39,29 @@
|
||||
"supports-color": "8.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.0.3",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"react": "*",
|
||||
"tslog": "4.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@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.3",
|
||||
"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,
|
||||
@@ -241,6 +243,7 @@ export interface BlitzConfig extends NextConfig {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" &&
|
||||
@@ -271,26 +274,30 @@ export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig {
|
||||
},
|
||||
})
|
||||
|
||||
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 (!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)
|
||||
@@ -299,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
|
||||
}
|
||||
@@ -347,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,177 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/rpc",
|
||||
"version": "2.0.3",
|
||||
"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.3",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"react": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/auth": "2.0.3",
|
||||
"@blitzjs/config": "2.0.3",
|
||||
"@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.3",
|
||||
"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"
|
||||
@@ -157,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
|
||||
// ----------
|
||||
@@ -176,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,
|
||||
@@ -188,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")
|
||||
@@ -205,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) {
|
||||
@@ -264,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,
|
||||
@@ -283,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,
|
||||
@@ -310,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,
|
||||
@@ -68,7 +89,9 @@ export async function transformBlitzRpcServer(
|
||||
|
||||
code += `__internal_addBlitzRpcResolver('${routePath}','${slash(
|
||||
resolverFilePath,
|
||||
)}',() => ${importStrategy}('${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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user