Compare commits
42 Commits
@blitzjs/a
...
@blitzjs/c
| 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 |
@@ -4065,6 +4065,75 @@
|
||||
"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
|
||||
|
||||
17
.github/workflows/pr-release.yml
vendored
17
.github/workflows/pr-release.yml
vendored
@@ -22,16 +22,19 @@ 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@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref }}
|
||||
repository: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
ref: ${{ steps.pr_info.outputs.head_sha }}
|
||||
|
||||
- name: Setup PNPM
|
||||
uses: pnpm/action-setup@646cdf48217256a3d0b80361c5a50727664284f2
|
||||
|
||||
14
README.md
14
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-428-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>
|
||||
@@ -754,6 +757,15 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
</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,105 @@
|
||||
# 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-blitz-auth",
|
||||
"version": "0.1.11",
|
||||
"version": "0.1.20",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"blitz:dev": "next dev",
|
||||
@@ -12,28 +12,28 @@
|
||||
"schema": "prisma/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.0.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@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.10",
|
||||
"blitz": "2.2.3",
|
||||
"flatted": "3.2.7",
|
||||
"next": "canary",
|
||||
"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.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@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.10",
|
||||
"next": "canary",
|
||||
"@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.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@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.10",
|
||||
"next": "canary",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"next": "15.0.1",
|
||||
"next-auth": "4.24.7",
|
||||
"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/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.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@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.10",
|
||||
"blitz": "2.2.3",
|
||||
"jest": "29.3.0",
|
||||
"jest-environment-jsdom": "29.3.0",
|
||||
"next": "canary",
|
||||
"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.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@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.10",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"delay": "5.0.0",
|
||||
"next": "canary",
|
||||
"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",
|
||||
|
||||
@@ -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.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.10",
|
||||
"@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": "canary",
|
||||
"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.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.10",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "canary",
|
||||
"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.10",
|
||||
"@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.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"blitz": "2.0.10",
|
||||
"next": "canary",
|
||||
"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,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.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.10",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "canary",
|
||||
"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")
|
||||
|
||||
@@ -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.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.10",
|
||||
"@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": "canary",
|
||||
"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.10",
|
||||
"@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.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@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.10",
|
||||
"next": "canary",
|
||||
"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.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.10",
|
||||
"@blitzjs/next": "2.2.3",
|
||||
"@blitzjs/rpc": "2.2.3",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.3",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "canary",
|
||||
"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.10",
|
||||
"@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.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"blitz": "2.0.10",
|
||||
"next": "canary",
|
||||
"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.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"blitz": "2.0.10",
|
||||
"next": "canary",
|
||||
"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.10",
|
||||
"@blitzjs/next": "2.0.10",
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@prisma/client": "4.6.1",
|
||||
"blitz": "2.0.10",
|
||||
"@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": "canary",
|
||||
"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.10",
|
||||
"@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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "workspace:2.0.10",
|
||||
"@blitzjs/next": "workspace:2.0.10",
|
||||
"@blitzjs/rpc": "workspace:2.0.10",
|
||||
"@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",
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
"husky": "8.0.2",
|
||||
"jsdom": "^19.0.0",
|
||||
"lint-staged": "13.0.3",
|
||||
"next": "canary",
|
||||
"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",
|
||||
@@ -50,7 +50,10 @@
|
||||
"next-auth@4.24.7": "patches/next-auth@4.24.7.patch"
|
||||
},
|
||||
"overrides": {
|
||||
"@types/mime": "3.0.4"
|
||||
"@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,115 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/auth",
|
||||
"version": "2.0.10",
|
||||
"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.10",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"next-auth": "*",
|
||||
"secure-password": "4.0.0"
|
||||
@@ -67,19 +67,18 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@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.10",
|
||||
"next": "canary",
|
||||
"@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": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"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")
|
||||
|
||||
@@ -260,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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -130,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)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {fromBase64, toBase64} from "b64-lite"
|
||||
import cookie, {parse} from "cookie"
|
||||
import {IncomingMessage, ServerResponse} from "http"
|
||||
import {sign as jwtSign, verify as jwtVerify} from "jsonwebtoken"
|
||||
import jsonwebtoken from "jsonwebtoken"
|
||||
import {
|
||||
assert,
|
||||
isPast,
|
||||
@@ -13,9 +12,9 @@ import {
|
||||
AuthorizationError,
|
||||
CSRFTokenMismatchError,
|
||||
log,
|
||||
AuthenticatedCtx,
|
||||
baseLogger,
|
||||
chalk,
|
||||
AuthenticatedCtx,
|
||||
} from "blitz"
|
||||
import {
|
||||
EmptyPublicData,
|
||||
@@ -39,12 +38,69 @@ import {
|
||||
AuthenticatedSessionContext,
|
||||
} from "../shared"
|
||||
import {generateToken, hash256} from "./auth-utils"
|
||||
import {Socket} from "net"
|
||||
import {UrlObject} from "url"
|
||||
import {formatWithValidation} from "../shared/url-utils"
|
||||
|
||||
export function isLocalhost(req: IncomingMessage): boolean {
|
||||
let {host} = req.headers
|
||||
import type {UrlObject} from "url"
|
||||
import type {IncomingMessage, ServerResponse} from "http"
|
||||
|
||||
function splitCookiesString(cookiesString: string) {
|
||||
if (!cookiesString) return []
|
||||
let cookiesStrings = []
|
||||
let pos = 0
|
||||
let start
|
||||
let ch
|
||||
let lastComma
|
||||
let nextStart
|
||||
let cookiesSeparatorFound
|
||||
function skipWhitespace() {
|
||||
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
|
||||
pos += 1
|
||||
}
|
||||
return pos < cookiesString.length
|
||||
}
|
||||
function notSpecialChar() {
|
||||
ch = cookiesString.charAt(pos)
|
||||
return ch !== "=" && ch !== ";" && ch !== ","
|
||||
}
|
||||
while (pos < cookiesString.length) {
|
||||
start = pos
|
||||
cookiesSeparatorFound = false
|
||||
while (skipWhitespace()) {
|
||||
ch = cookiesString.charAt(pos)
|
||||
if (ch === ",") {
|
||||
lastComma = pos
|
||||
pos += 1
|
||||
skipWhitespace()
|
||||
nextStart = pos
|
||||
while (pos < cookiesString.length && notSpecialChar()) {
|
||||
pos += 1
|
||||
}
|
||||
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
|
||||
cookiesSeparatorFound = true
|
||||
pos = nextStart
|
||||
cookiesStrings.push(cookiesString.substring(start, lastComma))
|
||||
start = pos
|
||||
} else {
|
||||
pos = lastComma + 1
|
||||
}
|
||||
} else {
|
||||
pos += 1
|
||||
}
|
||||
}
|
||||
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
|
||||
cookiesStrings.push(cookiesString.substring(start, cookiesString.length))
|
||||
}
|
||||
}
|
||||
return cookiesStrings
|
||||
}
|
||||
|
||||
export function isLocalhost(req: IncomingMessage | Request): boolean {
|
||||
let host: string | undefined
|
||||
if (req instanceof Request) {
|
||||
host = req.headers.get("host") || ""
|
||||
} else {
|
||||
host = req.headers.host || ""
|
||||
}
|
||||
let localhost = false
|
||||
if (host) {
|
||||
host = host.split(":")[0]
|
||||
@@ -69,7 +125,8 @@ export function getCookieParser(headers: {[key: string]: undefined | string | st
|
||||
}
|
||||
}
|
||||
|
||||
const debug = require("debug")("blitz:session")
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz:session")
|
||||
|
||||
export interface SimpleRolesIsAuthorized<RoleType = string> {
|
||||
({ctx, args}: {ctx: any; args: [roleOrRoles?: RoleType | RoleType[]]}): boolean
|
||||
@@ -131,14 +188,6 @@ type AuthedSessionKernel = {
|
||||
}
|
||||
type SessionKernel = AnonSessionKernel | AuthedSessionKernel
|
||||
|
||||
function ensureApiRequest(
|
||||
req: IncomingMessage & {[key: string]: any},
|
||||
): asserts req is IncomingMessage & {cookies: {[key: string]: string}} {
|
||||
if (!("cookies" in req)) {
|
||||
// Cookie parser isn't include inside getServerSideProps, so we have to add it
|
||||
req.cookies = getCookieParser(req.headers)()
|
||||
}
|
||||
}
|
||||
function ensureMiddlewareResponse(
|
||||
res: ServerResponse & {[key: string]: any},
|
||||
): asserts res is ServerResponse & {blitzCtx: Ctx} {
|
||||
@@ -147,58 +196,114 @@ function ensureMiddlewareResponse(
|
||||
}
|
||||
}
|
||||
|
||||
function convertRequestToHeader(req: IncomingMessage | Request): Headers {
|
||||
const headersFromRequest = req.headers
|
||||
if (headersFromRequest instanceof Headers) {
|
||||
return headersFromRequest
|
||||
} else {
|
||||
const headers = new Headers()
|
||||
Object.entries(headersFromRequest).forEach(([key, value]) => {
|
||||
if (value) {
|
||||
if (Array.isArray(value)) {
|
||||
headers.append(key, value.join(","))
|
||||
} else {
|
||||
headers.append(key, value)
|
||||
}
|
||||
}
|
||||
})
|
||||
return headers
|
||||
}
|
||||
}
|
||||
|
||||
function getCookiesFromHeader(headers: Headers) {
|
||||
const cookieHeader = headers.get("Cookie")
|
||||
if (cookieHeader) {
|
||||
return cookie.parse(cookieHeader)
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSession(req: Request): Promise<SessionContext>
|
||||
export async function getSession(req: Request, res: never, isRsc: boolean): Promise<SessionContext>
|
||||
export async function getSession(req: IncomingMessage, res: ServerResponse): Promise<SessionContext>
|
||||
export async function getSession(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
appDir = false,
|
||||
isRsc: boolean,
|
||||
): Promise<SessionContext>
|
||||
export async function getSession(
|
||||
req: IncomingMessage | Request,
|
||||
res?: ServerResponse,
|
||||
isRsc?: boolean,
|
||||
): Promise<SessionContext> {
|
||||
ensureApiRequest(req)
|
||||
ensureMiddlewareResponse(res)
|
||||
|
||||
debug("cookiePrefix", globalThis.__BLITZ_SESSION_COOKIE_PREFIX)
|
||||
|
||||
if (res.blitzCtx.session) {
|
||||
debug("Returning existing session")
|
||||
return res.blitzCtx.session
|
||||
const headers = convertRequestToHeader(req)
|
||||
if (res) {
|
||||
ensureMiddlewareResponse(res)
|
||||
debug("cookiePrefix", globalThis.__BLITZ_SESSION_COOKIE_PREFIX)
|
||||
if (res.blitzCtx.session) {
|
||||
debug("Returning existing session")
|
||||
return res.blitzCtx.session
|
||||
}
|
||||
}
|
||||
|
||||
let sessionKernel = await getSessionKernel(req, res)
|
||||
const method = req.method
|
||||
let sessionKernel = await getSessionKernel({headers, method})
|
||||
|
||||
if (sessionKernel) {
|
||||
debug("Got existing session", sessionKernel)
|
||||
}
|
||||
|
||||
if (!sessionKernel) {
|
||||
debug("No session found, creating anonymous session")
|
||||
sessionKernel = await createAnonymousSession(req, res)
|
||||
sessionKernel = await createAnonymousSession({headers})
|
||||
}
|
||||
|
||||
const sessionContext = makeProxyToPublicData(
|
||||
new SessionContextClass(req, res, sessionKernel, appDir),
|
||||
new SessionContextClass(headers, sessionKernel, !!isRsc, res),
|
||||
)
|
||||
debug("New session context")
|
||||
res.blitzCtx.session = sessionContext
|
||||
if (res) {
|
||||
;(res as any).blitzCtx = {
|
||||
session: sessionContext,
|
||||
}
|
||||
sessionContext.setSession(res)
|
||||
}
|
||||
return sessionContext
|
||||
}
|
||||
|
||||
interface RouteUrlObject extends Pick<UrlObject, "pathname" | "query" | "href"> {
|
||||
pathname: string
|
||||
}
|
||||
|
||||
const makeProxyToPublicData = <T extends SessionContextClass>(ctxClass: T): T => {
|
||||
return new Proxy(ctxClass, {
|
||||
get(target, prop, receiver) {
|
||||
if (prop in target || prop === "then") {
|
||||
return Reflect.get(target, prop, receiver)
|
||||
} else {
|
||||
return Reflect.get(target.$publicData, prop, receiver)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export async function getBlitzContext(): Promise<Ctx> {
|
||||
try {
|
||||
const {headers, cookies} = require("next/headers")
|
||||
const req = new IncomingMessage(new Socket()) as IncomingMessage & {
|
||||
cookies: {[key: string]: string}
|
||||
}
|
||||
req.headers = Object.fromEntries(headers())
|
||||
const csrfToken = cookies().get(COOKIE_CSRF_TOKEN())
|
||||
const cookieStore = await cookies()
|
||||
const headersStore = await headers()
|
||||
const reqHeader = Object.fromEntries(headersStore)
|
||||
const csrfToken = cookieStore.get(COOKIE_CSRF_TOKEN())
|
||||
if (csrfToken) {
|
||||
req.headers[HEADER_CSRF] = csrfToken.value
|
||||
reqHeader[HEADER_CSRF] = csrfToken.value
|
||||
}
|
||||
req.cookies = Object.fromEntries(
|
||||
cookies()
|
||||
.getAll()
|
||||
.map((c: {name: string; value: string}) => [c.name, c.value]),
|
||||
const session = await getSession(
|
||||
{
|
||||
headers: new Headers(reqHeader),
|
||||
method: "POST",
|
||||
} as Request,
|
||||
null as never,
|
||||
true,
|
||||
)
|
||||
const res = new ServerResponse(req)
|
||||
const session = await getSession(req, res, true)
|
||||
const ctx: Ctx = {
|
||||
session,
|
||||
}
|
||||
@@ -206,17 +311,13 @@ export async function getBlitzContext(): Promise<Ctx> {
|
||||
} catch (e) {
|
||||
if ((e as NodeJS.ErrnoException).code === "MODULE_NOT_FOUND") {
|
||||
throw new Error(
|
||||
"Usage of `useAuthenticatedBlitzContext` is supported only in next.js 13.0.0 and above. Please upgrade your next.js version.",
|
||||
"Usage of `getBlitzContext` is supported only in next.js 13.0.0 and above. Please upgrade your next.js version.",
|
||||
)
|
||||
}
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
interface RouteUrlObject extends Pick<UrlObject, "pathname" | "query" | "href"> {
|
||||
pathname: string
|
||||
}
|
||||
|
||||
export async function useAuthenticatedBlitzContext({
|
||||
redirectTo,
|
||||
redirectAuthenticatedTo,
|
||||
@@ -291,18 +392,6 @@ export async function useAuthenticatedBlitzContext({
|
||||
}
|
||||
}
|
||||
|
||||
const makeProxyToPublicData = <T extends SessionContextClass>(ctxClass: T): T => {
|
||||
return new Proxy(ctxClass, {
|
||||
get(target, prop, receiver) {
|
||||
if (prop in target || prop === "then") {
|
||||
return Reflect.get(target, prop, receiver)
|
||||
} else {
|
||||
return Reflect.get(target.$publicData, prop, receiver)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const NotSupportedMessage = async (method: string) => {
|
||||
const message = `Method ${method} is not yet supported in React Server Components`
|
||||
const _box = await log.box(message, log.chalk.hex("8a3df0").bold("Blitz Auth"))
|
||||
@@ -310,21 +399,27 @@ const NotSupportedMessage = async (method: string) => {
|
||||
}
|
||||
|
||||
export class SessionContextClass implements SessionContext {
|
||||
private _req: IncomingMessage & {cookies: {[key: string]: string}}
|
||||
private _res: ServerResponse & {blitzCtx: Ctx}
|
||||
private _headers: Headers
|
||||
private _kernel: SessionKernel
|
||||
private _appDir: boolean
|
||||
private _isRsc: boolean
|
||||
private _response?: ServerResponse
|
||||
|
||||
constructor(
|
||||
req: IncomingMessage & {cookies: {[key: string]: string}},
|
||||
res: ServerResponse & {blitzCtx: Ctx},
|
||||
kernel: SessionKernel,
|
||||
appDir: boolean,
|
||||
) {
|
||||
this._req = req
|
||||
this._res = res
|
||||
private static headersToIncludeInResponse = [
|
||||
HEADER_CSRF,
|
||||
HEADER_CSRF_ERROR,
|
||||
HEADER_PUBLIC_DATA_TOKEN,
|
||||
HEADER_SESSION_CREATED,
|
||||
]
|
||||
|
||||
constructor(headers: Headers, kernel: SessionKernel, isRsc: boolean, response?: ServerResponse) {
|
||||
this._headers = headers
|
||||
this._kernel = kernel
|
||||
this._appDir = appDir
|
||||
this._isRsc = isRsc
|
||||
this._response = response
|
||||
}
|
||||
|
||||
$antiCSRFToken() {
|
||||
return this._kernel.antiCSRFToken
|
||||
}
|
||||
|
||||
get $handle() {
|
||||
@@ -352,38 +447,69 @@ export class SessionContextClass implements SessionContext {
|
||||
$isAuthorized(...args: IsAuthorizedArgs) {
|
||||
if (!this.userId) return false
|
||||
|
||||
return global.sessionConfig.isAuthorized({ctx: this._res.blitzCtx, args})
|
||||
return global.sessionConfig.isAuthorized({
|
||||
ctx: {
|
||||
session: this as AuthenticatedSessionContext,
|
||||
},
|
||||
args,
|
||||
})
|
||||
}
|
||||
|
||||
$thisIsAuthorized(...args: IsAuthorizedArgs): this is AuthenticatedSessionContext {
|
||||
return this.$isAuthorized(...args)
|
||||
}
|
||||
|
||||
setSession(response: Response | ServerResponse) {
|
||||
if (this._isRsc) {
|
||||
void NotSupportedMessage("setSession")
|
||||
return
|
||||
}
|
||||
const cookieHeaders = this._headers.get("set-cookie")
|
||||
if (response instanceof Response) {
|
||||
response.headers.append("Set-Cookie", cookieHeaders!)
|
||||
} else {
|
||||
append(response, "Set-Cookie", splitCookiesString(cookieHeaders!))
|
||||
}
|
||||
|
||||
const headers = this._headers.entries()
|
||||
for (const [key, value] of headers) {
|
||||
if (SessionContextClass.headersToIncludeInResponse.includes(key)) {
|
||||
if (response instanceof Response) {
|
||||
response.headers.set(key, value)
|
||||
} else {
|
||||
response.setHeader(key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async $create(publicData: PublicData, privateData?: Record<any, any>) {
|
||||
if (this._appDir) {
|
||||
if (this._isRsc) {
|
||||
void NotSupportedMessage("$create")
|
||||
return
|
||||
}
|
||||
this._kernel = await createNewSession({
|
||||
req: this._req,
|
||||
res: this._res,
|
||||
headers: this._headers,
|
||||
publicData,
|
||||
privateData,
|
||||
jwtPayload: this._kernel.jwtPayload,
|
||||
anonymous: false,
|
||||
})
|
||||
|
||||
if (this._response) this.setSession(this._response)
|
||||
}
|
||||
|
||||
async $revoke() {
|
||||
if (this._appDir) {
|
||||
if (this._isRsc) {
|
||||
void NotSupportedMessage("$revoke")
|
||||
return
|
||||
}
|
||||
this._kernel = await revokeSession(this._req, this._res, this.$handle)
|
||||
this._kernel = await revokeSession(this._headers, this.$handle)
|
||||
if (this._response) this.setSession(this._response)
|
||||
}
|
||||
|
||||
async $revokeAll() {
|
||||
if (this._appDir) {
|
||||
if (this._isRsc) {
|
||||
void NotSupportedMessage("$revokeAll")
|
||||
return
|
||||
}
|
||||
@@ -395,25 +521,28 @@ export class SessionContextClass implements SessionContext {
|
||||
}
|
||||
|
||||
async $setPublicData(data: Record<any, any>) {
|
||||
if (this._appDir) {
|
||||
if (this._isRsc) {
|
||||
void NotSupportedMessage("$setPublicData")
|
||||
return
|
||||
}
|
||||
if (this.userId) {
|
||||
await syncPubicDataFieldsForUserIfNeeded(this.userId, data)
|
||||
}
|
||||
this._kernel.publicData = await setPublicData(this._req, this._res, this._kernel, data)
|
||||
this._kernel.publicData = await setPublicData(this._headers, this._kernel, data)
|
||||
if (this._response) this.setSession(this._response)
|
||||
}
|
||||
|
||||
async $getPrivateData() {
|
||||
return (await getPrivateData(this.$handle)) || {}
|
||||
}
|
||||
$setPrivateData(data: Record<any, any>) {
|
||||
if (this._appDir) {
|
||||
|
||||
async $setPrivateData(data: Record<any, any>) {
|
||||
if (this._isRsc) {
|
||||
void NotSupportedMessage("$setPrivateData")
|
||||
return Promise.resolve()
|
||||
}
|
||||
return setPrivateData(this._kernel, data)
|
||||
await setPrivateData(this._kernel, data)
|
||||
if (this._response) this.setSession(this._response)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +634,7 @@ const JWT_ANONYMOUS_SUBJECT = "anonymous"
|
||||
const JWT_ALGORITHM = "HS256"
|
||||
|
||||
const createAnonymousSessionToken = (payload: AnonymousSessionPayload) => {
|
||||
return jwtSign({[JWT_NAMESPACE]: payload}, getSessionSecretKey() || "", {
|
||||
return jsonwebtoken.sign({[JWT_NAMESPACE]: payload}, getSessionSecretKey() || "", {
|
||||
algorithm: JWT_ALGORITHM,
|
||||
issuer: JWT_ISSUER,
|
||||
audience: JWT_AUDIENCE,
|
||||
@@ -519,7 +648,7 @@ const parseAnonymousSessionToken = (token: string) => {
|
||||
const secret = getSessionSecretKey()
|
||||
|
||||
try {
|
||||
const fullPayload = jwtVerify(token, secret!, {
|
||||
const fullPayload = jsonwebtoken.verify(token, secret!, {
|
||||
algorithms: [JWT_ALGORITHM],
|
||||
issuer: JWT_ISSUER,
|
||||
audience: JWT_AUDIENCE,
|
||||
@@ -536,126 +665,127 @@ const parseAnonymousSessionToken = (token: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const setCookie = (res: ServerResponse, cookieStr: string) => {
|
||||
const getCookieName = (c: string) => c.split("=", 2)[0]
|
||||
const appendCookie = () => append(res, "Set-Cookie", cookieStr)
|
||||
|
||||
const cookiesHeader = res.getHeader("Set-Cookie")
|
||||
const cookieName = getCookieName(cookieStr)
|
||||
|
||||
if (typeof cookiesHeader !== "string" && !Array.isArray(cookiesHeader)) {
|
||||
appendCookie()
|
||||
return
|
||||
const cookieOptions = (headers: Headers, expires: Date, httpOnly: boolean) => {
|
||||
return {
|
||||
path: "/",
|
||||
secure:
|
||||
global.sessionConfig.secureCookies &&
|
||||
!isLocalhost({
|
||||
headers,
|
||||
} as Request),
|
||||
sameSite: global.sessionConfig.sameSite,
|
||||
domain: global.sessionConfig.domain,
|
||||
expires: new Date(expires),
|
||||
httpOnly,
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof cookiesHeader === "string") {
|
||||
if (cookieName === getCookieName(cookiesHeader)) {
|
||||
res.setHeader("Set-Cookie", cookieStr)
|
||||
function replaceOrAppendValueInSetCookieHeader(
|
||||
headers: Headers,
|
||||
cookieName: string,
|
||||
newValue: string,
|
||||
): string {
|
||||
const cookies = headers.get("set-cookie")
|
||||
if (!cookies) return newValue
|
||||
const cookiesAsArray = splitCookiesString(cookies!)
|
||||
for (let i = 0; i < cookiesAsArray.length; i++) {
|
||||
const cookie = cookiesAsArray[i]
|
||||
if (cookie?.startsWith(cookieName)) {
|
||||
cookiesAsArray[i] = newValue
|
||||
return cookiesAsArray.join(", ")
|
||||
} else {
|
||||
appendCookie()
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < cookiesHeader.length; i++) {
|
||||
if (cookieName === getCookieName(cookiesHeader[i] || "")) {
|
||||
cookiesHeader[i] = cookieStr
|
||||
res.setHeader("Set-Cookie", cookiesHeader)
|
||||
return
|
||||
if (i === cookiesAsArray.length - 1) {
|
||||
cookiesAsArray.push(newValue)
|
||||
return cookiesAsArray.join(", ")
|
||||
}
|
||||
}
|
||||
appendCookie()
|
||||
}
|
||||
return cookiesAsArray.filter(Boolean).join(", ")
|
||||
}
|
||||
|
||||
const setHeader = (res: ServerResponse, name: string, value: string) => {
|
||||
res.setHeader(name, value)
|
||||
if ("_blitz" in res) {
|
||||
;(res as any)._blitz[name] = value
|
||||
}
|
||||
}
|
||||
|
||||
const setSessionCookie = (res: ServerResponse, sessionToken: string, expiresAt: Date) => {
|
||||
setCookie(
|
||||
res,
|
||||
cookie.serialize(COOKIE_SESSION_TOKEN(), sessionToken, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: global.sessionConfig.secureCookies,
|
||||
sameSite: global.sessionConfig.sameSite,
|
||||
domain: global.sessionConfig.domain,
|
||||
expires: expiresAt,
|
||||
}),
|
||||
const setSessionCookie = (headers: Headers, sessionToken: string, expiresAt: Date) => {
|
||||
const sessionCookie = cookie.serialize(
|
||||
COOKIE_SESSION_TOKEN(),
|
||||
sessionToken,
|
||||
cookieOptions(headers, expiresAt, true),
|
||||
)
|
||||
}
|
||||
|
||||
const setAnonymousSessionCookie = (res: ServerResponse, token: string, expiresAt: Date) => {
|
||||
setCookie(
|
||||
res,
|
||||
cookie.serialize(COOKIE_ANONYMOUS_SESSION_TOKEN(), token, {
|
||||
path: "/",
|
||||
httpOnly: true,
|
||||
secure: global.sessionConfig.secureCookies,
|
||||
sameSite: global.sessionConfig.sameSite,
|
||||
domain: global.sessionConfig.domain,
|
||||
expires: expiresAt,
|
||||
}),
|
||||
const newCookies = replaceOrAppendValueInSetCookieHeader(
|
||||
headers,
|
||||
COOKIE_SESSION_TOKEN(),
|
||||
sessionCookie,
|
||||
)
|
||||
headers.set("Set-Cookie", newCookies)
|
||||
}
|
||||
|
||||
const setCSRFCookie = (
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
antiCSRFToken: string,
|
||||
expiresAt: Date,
|
||||
) => {
|
||||
const setAnonymousSessionCookie = (headers: Headers, token: string, expiresAt: Date) => {
|
||||
const anonCookie = cookie.serialize(
|
||||
COOKIE_ANONYMOUS_SESSION_TOKEN(),
|
||||
token,
|
||||
cookieOptions(headers, expiresAt, true),
|
||||
)
|
||||
const newCookies = replaceOrAppendValueInSetCookieHeader(
|
||||
headers,
|
||||
COOKIE_ANONYMOUS_SESSION_TOKEN(),
|
||||
anonCookie,
|
||||
)
|
||||
headers.set("Set-Cookie", newCookies)
|
||||
}
|
||||
|
||||
const setCSRFCookie = (headers: Headers, antiCSRFToken: string, expiresAt: Date) => {
|
||||
debug("setCSRFCookie", antiCSRFToken)
|
||||
assert(antiCSRFToken !== undefined, "Internal error: antiCSRFToken is being set to undefined")
|
||||
setCookie(
|
||||
res,
|
||||
cookie.serialize(COOKIE_CSRF_TOKEN(), antiCSRFToken, {
|
||||
path: "/",
|
||||
secure: global.sessionConfig.secureCookies && !isLocalhost(req),
|
||||
sameSite: global.sessionConfig.sameSite,
|
||||
domain: global.sessionConfig.domain,
|
||||
expires: expiresAt,
|
||||
}),
|
||||
const csrfCookie = cookie.serialize(
|
||||
COOKIE_CSRF_TOKEN(),
|
||||
antiCSRFToken,
|
||||
cookieOptions(headers, expiresAt, false),
|
||||
)
|
||||
|
||||
const newCookies = replaceOrAppendValueInSetCookieHeader(headers, COOKIE_CSRF_TOKEN(), csrfCookie)
|
||||
headers.set("Set-Cookie", newCookies)
|
||||
}
|
||||
|
||||
const setPublicDataCookie = (
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
publicDataToken: string,
|
||||
expiresAt: Date,
|
||||
) => {
|
||||
setHeader(res, HEADER_PUBLIC_DATA_TOKEN, "updated")
|
||||
setCookie(
|
||||
res,
|
||||
cookie.serialize(COOKIE_PUBLIC_DATA_TOKEN(), publicDataToken, {
|
||||
path: "/",
|
||||
secure: global.sessionConfig.secureCookies && !isLocalhost(req),
|
||||
sameSite: global.sessionConfig.sameSite,
|
||||
domain: global.sessionConfig.domain,
|
||||
expires: expiresAt,
|
||||
}),
|
||||
const setPublicDataCookie = (headers: Headers, publicDataToken: string, expiresAt: Date) => {
|
||||
headers.set(HEADER_PUBLIC_DATA_TOKEN, "updated")
|
||||
const publicDataCookie = cookie.serialize(
|
||||
COOKIE_PUBLIC_DATA_TOKEN(),
|
||||
publicDataToken,
|
||||
cookieOptions(headers, expiresAt, false),
|
||||
)
|
||||
const newCookies = replaceOrAppendValueInSetCookieHeader(
|
||||
headers,
|
||||
COOKIE_PUBLIC_DATA_TOKEN(),
|
||||
publicDataCookie,
|
||||
)
|
||||
headers.set("Set-Cookie", newCookies)
|
||||
}
|
||||
|
||||
// --------------------------------
|
||||
// Get Session
|
||||
// --------------------------------
|
||||
async function getSessionKernel(
|
||||
req: IncomingMessage & {cookies: {[key: string]: string}},
|
||||
res: ServerResponse,
|
||||
): Promise<SessionKernel | null> {
|
||||
const anonymousSessionToken = req.cookies[COOKIE_ANONYMOUS_SESSION_TOKEN()]
|
||||
const sessionToken = req.cookies[COOKIE_SESSION_TOKEN()] // for essential method
|
||||
const idRefreshToken = req.cookies[COOKIE_REFRESH_TOKEN()] // for advanced method
|
||||
async function getSessionKernel({
|
||||
headers,
|
||||
method,
|
||||
}: {
|
||||
headers: Headers
|
||||
method: string | undefined
|
||||
}): Promise<SessionKernel | null> {
|
||||
const cookies = getCookiesFromHeader(headers)
|
||||
const anonymousSessionToken = cookies[COOKIE_ANONYMOUS_SESSION_TOKEN()]
|
||||
const sessionToken = cookies[COOKIE_SESSION_TOKEN()] // for essential method
|
||||
const idRefreshToken = cookies[COOKIE_REFRESH_TOKEN()] // for advanced method
|
||||
const antiCSRFToken = headers.get(HEADER_CSRF)
|
||||
debug("getSessionKernel", {
|
||||
anonymousSessionToken,
|
||||
sessionToken,
|
||||
idRefreshToken,
|
||||
antiCSRFToken,
|
||||
})
|
||||
|
||||
const enableCsrfProtection =
|
||||
req.method !== "GET" &&
|
||||
req.method !== "OPTIONS" &&
|
||||
req.method !== "HEAD" &&
|
||||
method !== "GET" &&
|
||||
method !== "OPTIONS" &&
|
||||
method !== "HEAD" &&
|
||||
!process.env.DANGEROUSLY_DISABLE_CSRF_PROTECTION
|
||||
const antiCSRFToken = req.headers[HEADER_CSRF] as string | undefined
|
||||
|
||||
if (sessionToken) {
|
||||
debug("[getSessionKernel] Request has sessionToken")
|
||||
@@ -698,7 +828,7 @@ async function getSessionKernel(
|
||||
)
|
||||
}
|
||||
|
||||
setHeader(res, HEADER_CSRF_ERROR, "true")
|
||||
headers.set(HEADER_CSRF_ERROR, "true")
|
||||
throw new CSRFTokenMismatchError()
|
||||
}
|
||||
|
||||
@@ -710,7 +840,7 @@ async function getSessionKernel(
|
||||
* But only renew with non-GET requests because a GET request could be from a
|
||||
* browser level navigation
|
||||
*/
|
||||
if (req.method !== "GET") {
|
||||
if (method !== "GET") {
|
||||
// The publicData in the DB could have been updated since this client last made
|
||||
// a request. If so, then we generate a new access token
|
||||
const hasPublicDataChanged =
|
||||
@@ -733,8 +863,7 @@ async function getSessionKernel(
|
||||
|
||||
if (hasPublicDataChanged || hasQuarterExpiryTimePassed) {
|
||||
await refreshSession(
|
||||
req,
|
||||
res,
|
||||
headers,
|
||||
{
|
||||
handle,
|
||||
publicData: JSON.parse(persistedSession.publicData || ""),
|
||||
@@ -774,7 +903,7 @@ async function getSessionKernel(
|
||||
)
|
||||
}
|
||||
|
||||
setHeader(res, HEADER_CSRF_ERROR, "true")
|
||||
headers.set(HEADER_CSRF_ERROR, "true")
|
||||
throw new CSRFTokenMismatchError()
|
||||
}
|
||||
|
||||
@@ -795,16 +924,14 @@ async function getSessionKernel(
|
||||
// Create Session
|
||||
// --------------------------------
|
||||
interface CreateNewAnonSession {
|
||||
req: IncomingMessage
|
||||
res: ServerResponse
|
||||
headers: Headers
|
||||
publicData: EmptyPublicData
|
||||
privateData?: Record<any, any>
|
||||
anonymous: true
|
||||
jwtPayload?: JwtPayload
|
||||
}
|
||||
interface CreateNewAuthedSession {
|
||||
req: IncomingMessage
|
||||
res: ServerResponse
|
||||
headers: Headers
|
||||
publicData: PublicData
|
||||
privateData?: Record<any, any>
|
||||
anonymous: false
|
||||
@@ -814,7 +941,6 @@ interface CreateNewAuthedSession {
|
||||
async function createNewSession(
|
||||
args: CreateNewAnonSession | CreateNewAuthedSession,
|
||||
): Promise<SessionKernel> {
|
||||
const {req, res} = args
|
||||
assert(args.publicData.userId !== undefined, "You must provide publicData.userId")
|
||||
|
||||
const antiCSRFToken = createAntiCSRFToken()
|
||||
@@ -835,12 +961,12 @@ async function createNewSession(
|
||||
new Date(),
|
||||
global.sessionConfig.anonSessionExpiryMinutes as number,
|
||||
)
|
||||
setAnonymousSessionCookie(res, anonymousSessionToken, expiresAt)
|
||||
setCSRFCookie(req, res, antiCSRFToken, expiresAt)
|
||||
setPublicDataCookie(req, res, publicDataToken, expiresAt)
|
||||
setAnonymousSessionCookie(args.headers, anonymousSessionToken, expiresAt)
|
||||
setCSRFCookie(args.headers, antiCSRFToken, expiresAt)
|
||||
setPublicDataCookie(args.headers, publicDataToken, expiresAt)
|
||||
// Clear the essential session cookie in case it was previously set
|
||||
setSessionCookie(res, "", new Date(0))
|
||||
setHeader(res, HEADER_SESSION_CREATED, "true")
|
||||
setSessionCookie(args.headers, "", new Date(0))
|
||||
args.headers.set(HEADER_SESSION_CREATED, "true")
|
||||
|
||||
return {
|
||||
handle,
|
||||
@@ -891,12 +1017,13 @@ async function createNewSession(
|
||||
privateData: JSON.stringify(newPrivateData),
|
||||
})
|
||||
|
||||
setSessionCookie(res, sessionToken, expiresAt)
|
||||
setCSRFCookie(req, res, antiCSRFToken, expiresAt)
|
||||
setPublicDataCookie(req, res, publicDataToken, expiresAt)
|
||||
setSessionCookie(args.headers, sessionToken, expiresAt)
|
||||
debug("Session created", {handle, publicData: newPublicData, expiresAt})
|
||||
setCSRFCookie(args.headers, antiCSRFToken, expiresAt)
|
||||
setPublicDataCookie(args.headers, publicDataToken, expiresAt)
|
||||
// Clear the anonymous session cookie in case it was previously set
|
||||
setAnonymousSessionCookie(res, "", new Date(0))
|
||||
setHeader(res, HEADER_SESSION_CREATED, "true")
|
||||
setAnonymousSessionCookie(args.headers, "", new Date(0))
|
||||
args.headers.set(HEADER_SESSION_CREATED, "true")
|
||||
|
||||
return {
|
||||
handle,
|
||||
@@ -914,10 +1041,9 @@ async function createNewSession(
|
||||
}
|
||||
}
|
||||
|
||||
async function createAnonymousSession(req: IncomingMessage, res: ServerResponse) {
|
||||
async function createAnonymousSession({headers}: {headers: Headers}) {
|
||||
return await createNewSession({
|
||||
req,
|
||||
res,
|
||||
headers,
|
||||
publicData: {userId: null},
|
||||
anonymous: true,
|
||||
})
|
||||
@@ -928,8 +1054,7 @@ async function createAnonymousSession(req: IncomingMessage, res: ServerResponse)
|
||||
// --------------------------------
|
||||
|
||||
async function refreshSession(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
headers: Headers,
|
||||
sessionKernel: SessionKernel,
|
||||
{publicDataChanged}: {publicDataChanged: boolean},
|
||||
) {
|
||||
@@ -943,8 +1068,8 @@ async function refreshSession(
|
||||
const publicDataToken = createPublicDataToken(sessionKernel.publicData)
|
||||
|
||||
const expiresAt = addYears(new Date(), 30)
|
||||
setAnonymousSessionCookie(res, anonymousSessionToken, expiresAt)
|
||||
setPublicDataCookie(req, res, publicDataToken, expiresAt)
|
||||
setAnonymousSessionCookie(headers, anonymousSessionToken, expiresAt)
|
||||
setPublicDataCookie(headers, publicDataToken, expiresAt)
|
||||
} else if (global.sessionConfig.method === "essential" && "sessionToken" in sessionKernel) {
|
||||
const expiresAt = addMinutes(new Date(), global.sessionConfig.sessionExpiryMinutes as number)
|
||||
|
||||
@@ -952,7 +1077,7 @@ async function refreshSession(
|
||||
if (publicDataChanged) {
|
||||
debug("Public data has changed")
|
||||
const publicDataToken = createPublicDataToken(sessionKernel.publicData)
|
||||
setPublicDataCookie(req, res, publicDataToken, expiresAt)
|
||||
setPublicDataCookie(headers, publicDataToken, expiresAt)
|
||||
await global.sessionConfig.updateSession(sessionKernel.handle, {
|
||||
expiresAt,
|
||||
publicData: JSON.stringify(sessionKernel.publicData),
|
||||
@@ -994,12 +1119,7 @@ async function syncPubicDataFieldsForUserIfNeeded(
|
||||
}
|
||||
}
|
||||
|
||||
async function revokeSession(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
handle: string,
|
||||
anonymous: boolean = false,
|
||||
) {
|
||||
async function revokeSession(headers: Headers, handle: string, anonymous: boolean = false) {
|
||||
debug("Revoking session", handle)
|
||||
if (!anonymous) {
|
||||
try {
|
||||
@@ -1012,7 +1132,9 @@ async function revokeSession(
|
||||
// This fixes race condition where all client side queries get refreshed
|
||||
// in parallel and each creates a new anon session
|
||||
// https://github.com/blitz-js/blitz/issues/2746
|
||||
return createAnonymousSession(req, res)
|
||||
return createAnonymousSession({
|
||||
headers,
|
||||
})
|
||||
}
|
||||
|
||||
async function revokeAllSessionsForUser(userId: PublicData["userId"]) {
|
||||
@@ -1078,8 +1200,7 @@ async function setPrivateData(sessionKernel: SessionKernel, data: Record<any, an
|
||||
}
|
||||
|
||||
async function setPublicData(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
headers: Headers,
|
||||
sessionKernel: SessionKernel,
|
||||
data: Record<any, any>,
|
||||
) {
|
||||
@@ -1091,7 +1212,7 @@ async function setPublicData(
|
||||
...data,
|
||||
} as PublicData
|
||||
|
||||
await refreshSession(req, res, {...sessionKernel, publicData}, {publicDataChanged: true})
|
||||
await refreshSession(headers, {...sessionKernel, publicData}, {publicDataChanged: true})
|
||||
return publicData
|
||||
}
|
||||
|
||||
@@ -1128,12 +1249,31 @@ export async function setPublicDataForUser(userId: PublicData["userId"], data: R
|
||||
* @param {string} field
|
||||
* @param {string| string[]} val
|
||||
*/
|
||||
function append(res: ServerResponse, field: string, val: string | string[]) {
|
||||
export function append(res: ServerResponse, field: string, val: string | string[]) {
|
||||
let prev: string | string[] | undefined = res.getHeader(field) as string | string[] | undefined
|
||||
let value = val
|
||||
|
||||
if (prev !== undefined) {
|
||||
// concat the new and prev vals
|
||||
if (field.toLowerCase() === "set-cookie") {
|
||||
const prevCookies = prev ? (Array.isArray(prev) ? prev : [prev]) : []
|
||||
const newCookies = Array.isArray(val) ? val : [val]
|
||||
|
||||
const allCookies = [...prevCookies, ...newCookies].reduce((acc: string[], cookieHeader) => {
|
||||
return acc.concat(splitCookiesString(cookieHeader))
|
||||
}, [])
|
||||
|
||||
const cookieMap = new Map()
|
||||
allCookies.forEach((cookieStr) => {
|
||||
const firstSemicolon = cookieStr.indexOf(";")
|
||||
const cookieNameValue = firstSemicolon > -1 ? cookieStr.slice(0, firstSemicolon) : cookieStr
|
||||
const parsed = cookie.parse(cookieNameValue)
|
||||
const name = Object.keys(parsed)[0]
|
||||
if (name) {
|
||||
cookieMap.set(name, cookieStr)
|
||||
}
|
||||
})
|
||||
|
||||
value = Array.from(cookieMap.values())
|
||||
} else if (prev !== undefined) {
|
||||
value = Array.isArray(prev)
|
||||
? prev.concat(val)
|
||||
: Array.isArray(val)
|
||||
@@ -1142,7 +1282,6 @@ function append(res: ServerResponse, field: string, val: string | string[]) {
|
||||
}
|
||||
|
||||
value = Array.isArray(value) ? value.map(String) : String(value)
|
||||
|
||||
res.setHeader(field, value)
|
||||
return res
|
||||
}
|
||||
|
||||
@@ -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,123 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/next",
|
||||
"version": "2.0.10",
|
||||
"version": "2.2.3",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,7 +29,7 @@
|
||||
"eslint.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/rpc": "2.0.10",
|
||||
"@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.10",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"react": "*",
|
||||
"tslog": "4.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@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.10",
|
||||
"blitz": "2.2.3",
|
||||
"cross-spawn": "7.0.3",
|
||||
"find-up": "4.1.0",
|
||||
"next": "canary",
|
||||
"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",
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
export {}
|
||||
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
|
||||
|
||||
@@ -243,6 +243,7 @@ export interface BlitzConfig extends NextConfig {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function withBlitz(nextConfig: BlitzConfig = {}): NextConfig {
|
||||
if (
|
||||
process.env.NODE_ENV !== "production" &&
|
||||
|
||||
@@ -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,114 @@
|
||||
# @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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/rpc",
|
||||
"version": "2.0.10",
|
||||
"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.10",
|
||||
"blitz": "2.2.3",
|
||||
"next": "*",
|
||||
"react": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/auth": "2.0.10",
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@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.10",
|
||||
"next": "canary",
|
||||
"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"
|
||||
@@ -172,6 +172,12 @@ export function installTurboConfig() {
|
||||
as: "*.ts",
|
||||
},
|
||||
},
|
||||
"**/*...blitz*/route.{jsx,tsx,js,ts}": {
|
||||
default: {
|
||||
loaders: [{loader: loaderServer, options: {}}],
|
||||
as: "*.ts",
|
||||
},
|
||||
},
|
||||
"**/{queries,mutations}/**": {
|
||||
browser: {
|
||||
loaders: [
|
||||
@@ -215,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,
|
||||
@@ -227,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")
|
||||
@@ -244,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) {
|
||||
@@ -303,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,
|
||||
@@ -322,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,
|
||||
@@ -349,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)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
777
packages/blitz/README.md
Normal file
777
packages/blitz/README.md
Normal file
@@ -0,0 +1,777 @@
|
||||
[](https://blitzjs.com)
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<p align="center">
|
||||
<a aria-label="Join our Discord Community" href="https://discord.blitzjs.com">
|
||||
<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-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">
|
||||
</a>
|
||||
<a aria-label="NPM version" href="https://www.npmjs.com/package/blitz">
|
||||
<img alt="" src="https://img.shields.io/npm/v/blitz.svg?style=for-the-badge&labelColor=000000&color=E65528">
|
||||
</a>
|
||||
</p>
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<br>
|
||||
|
||||
<h1 align="center">The Missing Fullstack Toolkit for Next.js</h1>
|
||||
|
||||
<br>
|
||||
|
||||
### Quick Start
|
||||
|
||||
#### Install Blitz
|
||||
|
||||
Run `npm install -g blitz` or `yarn global add blitz`
|
||||
|
||||
_You can alternatively use [`npx`](https://www.npmjs.com/package/npx)_
|
||||
|
||||
#### Create a New App
|
||||
|
||||
1. `blitz new myAppName`
|
||||
2. `cd myAppName`
|
||||
3. `blitz dev`
|
||||
4. View your brand new app at http://localhost:3000
|
||||
|
||||
<br><br>
|
||||
|
||||
|
||||
|
||||
## Welcome to the Blitz Community 👋
|
||||
|
||||
The Blitz community is warm, safe, diverse, inclusive, and fun! LGBTQ+, women, and minorities are especially welcome. Please read our [Code of Conduct](https://blitzjs.com/docs/code-of-conduct).
|
||||
|
||||
[Join our Discord Community](https://discord.blitzjs.com) where we help each other build Blitz apps. It's also where we collaborate on building Blitz itself.
|
||||
|
||||
For questions and longer form discussions, [post in our forum](https://github.com/blitz-js/blitz/discussions).
|
||||
|
||||
There's still a lot of work to do, so you are especially invited to join us in building Blitz! A good place to start is [The Contributing Guide](https://blitzjs.com/docs/contributing).
|
||||
|
||||
<br>
|
||||
|
||||
## Financial Contributors
|
||||
|
||||
Your financial contributions help ensure Blitz continues to be developed and maintained! We have monthly sponsorship options starting at $5/month.
|
||||
|
||||
👉 View options and contribute at [GitHub Sponsors](https://github.com/sponsors/blitz-js), [PayPal](https://paypal.me/thebayers), or [Open Collective](https://opencollective.com/blitzjs)
|
||||
|
||||
|
||||
### 🌱 Seedling Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><a aria-label="Andreas Asprou" href="https://andreas.fyi">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/andreas.jpg" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="Digas" href="https://digsas.com">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/digsas.svg" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="userTrack" href="https://www.usertrack.net/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/usertrack.png" width="40px"/>
|
||||
</a></td>
|
||||
<td><a aria-label="MeetKai" href="https://meetkai.com/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/meetkai.png" width="40px"/>
|
||||
</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>
|
||||
|
||||
|
||||
### 🥉 Bronze Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><a aria-label="RIT" href="https://rit-inc.co.jp/?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2021">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/rit_logo.png" width="200px">
|
||||
</a></td>
|
||||
<td><a aria-label="Boostry" href="https://boostry.co.jp/?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2021">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/boostry.svg" width="200px">
|
||||
</a></td>
|
||||
<td>
|
||||
<a aria-label="Byteflow" href="https://byteflow.app/?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/byteflow.png" width="70px">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
### 🥈 Silver Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a aria-label="Fauna" href="https://dashboard.fauna.com/accounts/register?utm_source=BlitzJS&utm_medium=sponsorship&utm_campaign=BlitzJS_Sponsorship_2020">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/Fauna_Logo_Blue.png" width="300px">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### 🏆 Gold Sponsors
|
||||
|
||||
<a aria-label="Your Company" href="#">
|
||||
<img alt="" src="https://dummyimage.com/1000x330/efe8ff/000000.png&text=Your+Logo+Here" width="400px">
|
||||
</a>
|
||||
|
||||
### 💎 Diamond Sponsors
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a aria-label="Flightcontrol" href="https://www.flightcontrol.dev?ref=blitzjs">
|
||||
<img alt="" src="https://raw.githubusercontent.com/blitz-js/blitz/main/assets/flightcontrol.png" width="400px">
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
## Core Team ✨
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://twitter.com/flybayer"><img src="https://avatars3.githubusercontent.com/u/8813276?v=4" width="100px;" alt=""/><br /><sub><b>Brandon Bayer</b></sub></a><br />Creator</td>
|
||||
<td align="center"><a href="http://twitter.com/dillonraphael"><img src="https://avatars.githubusercontent.com/u/3496193?v=4" width="100px;" alt=""/><br /><sub><b>Dillon Raphael</b></sub></a><br /></td>
|
||||
<td align="center">
|
||||
<a href="https://siddharthsuresh.vercel.app/">
|
||||
<img src="https://avatars.githubusercontent.com/u/83594610?v=4" width="100px;" alt="Siddharth Suresh avatar" /><br />
|
||||
<sub>
|
||||
<b>Siddharth Suresh</b>
|
||||
</sub>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
## Maintainers (Level 2) ✨
|
||||
|
||||
_Code ownership, pull request approvals and merging, etc_ (see [Maintainers L2](https://blitzjs.com/docs/maintainers#level-2-maintainers))
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="http://simonknott.de"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4" width="100px;" alt=""/><br /><sub><b>Simon Knott</b></sub></a><br />SuperJSON</td>
|
||||
<td align="center"><a href="http://jins.dev"><img src="https://avatars.githubusercontent.com/u/39466936?v=4" width="100px;" alt=""/><br /><sub><b>JH.Lee</b></sub></a><br />SuperJSON</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<br>
|
||||
|
||||
## Maintainers (Level 1) ✨
|
||||
|
||||
_Issue triage, pull request triage, community encouragement and moderation, etc_ (see [Maintainers L1](https://blitzjs.com/docs/maintainers#level-1-maintainers))
|
||||
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="http://jeremyliberman.com/"><img src="https://avatars3.githubusercontent.com/u/2754163?v=4" width="100px;" alt=""/><br /><sub><b>Jeremy Liberman</b></td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## Contributors ✨
|
||||
|
||||
Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="https://twitter.com/flybayer"><img src="https://avatars3.githubusercontent.com/u/8813276?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Brandon Bayer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=flybayer" title="Code">💻</a> <a href="#content-flybayer" title="Content">🖋</a> <a href="#ideas-flybayer" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aflybayer" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=flybayer" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=flybayer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://medium.com/@ryardley"><img src="https://avatars0.githubusercontent.com/u/1256409?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rudi Yardley</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ryardley" title="Code">💻</a> <a href="#ideas-ryardley" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aryardley" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=ryardley" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://merelinguist.me"><img src="https://avatars3.githubusercontent.com/u/24858006?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dylan Brookes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=merelinguist" title="Code">💻</a> <a href="#ideas-merelinguist" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Amerelinguist" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=merelinguist" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=merelinguist" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/aem"><img src="https://avatars0.githubusercontent.com/u/1909883?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adam Markon</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aem" title="Code">💻</a> <a href="#ideas-aem" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aaem" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=aem" title="Tests">⚠️</a> <a href="#maintenance-aem" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://corey-brown.com"><img src="https://avatars1.githubusercontent.com/u/12791148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Corey Brown</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=coreybrown89" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Acoreybrown89" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-coreybrown89" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/LoriKarikari"><img src="https://avatars1.githubusercontent.com/u/7902980?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lori Karikari</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=LoriKarikari" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3ALoriKarikari" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-LoriKarikari" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=LoriKarikari" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/GeggsElias"><img src="https://avatars3.githubusercontent.com/u/22719177?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Elias Johansson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=eliasjohansson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Aeliasjohansson" title="Reviewed Pull Requests">👀</a> <a href="#maintenance-eliasjohansson" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://fabulas.io"><img src="https://avatars1.githubusercontent.com/u/14793389?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Edelman </b></sub></a><br /><a href="#infra-medelman17" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/blitz-js/blitz/commits?author=medelman17" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.geistinteractive.com"><img src="https://avatars2.githubusercontent.com/u/316792?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Todd Geist</b></sub></a><br /><a href="#financial-toddgeist" title="Financial">💵</a> <a href="https://github.com/blitz-js/blitz/commits?author=toddgeist" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://robdrosenberg.com"><img src="https://avatars0.githubusercontent.com/u/20813991?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert Rosenberg</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robdrosenberg" title="Code">💻</a> <a href="#maintenance-robdrosenberg" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=robdrosenberg" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/quirk0o"><img src="https://avatars3.githubusercontent.com/u/5123725?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Beata Obrok</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=quirk0o" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/tsawan"><img src="https://avatars3.githubusercontent.com/u/3263082?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tahir Awan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tsawan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://raluce.com"><img src="https://avatars1.githubusercontent.com/u/2454632?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Camilo Gonzalez</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=camilo86" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://da.nielkempner.com"><img src="https://avatars3.githubusercontent.com/u/2532112?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Kempner</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dkempner" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://gielcobben.com"><img src="https://avatars0.githubusercontent.com/u/2663212?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Giel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gielcobben" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://jeremyliberman.com/"><img src="https://avatars3.githubusercontent.com/u/2754163?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeremy Liberman</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MrLeebo" title="Code">💻</a> <a href="#maintenance-MrLeebo" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=MrLeebo" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=MrLeebo" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://jimthedev.com"><img src="https://avatars0.githubusercontent.com/u/108938?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jim Cummins</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jimthedev" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kristinamatuska.com/"><img src="https://media-exp1.licdn.com/dms/image/C5603AQHVPAjV21gw9g/profile-displayphoto-shrink_200_200/0?e=1591228800&v=beta&t=0MlbmiYhNvGv1xjLD_fOhOFjVDZ7ltNwfGNeJ4DHedQ?s=100" width="100px;" alt=""/><br /><sub><b>Kristina Matuška</b></sub></a><br /><a href="#design" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/jasonblalock"><img src="https://avatars0.githubusercontent.com/u/5899929?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jason Blalock</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jasonblalock" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/aej11a"><img src="https://avatars2.githubusercontent.com/u/10066422?v=4?s=100" width="100px;" alt=""/><br /><sub><b>aej11a</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aej11a" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/marcoseoane"><img src="https://avatars0.githubusercontent.com/u/28088807?v=4?s=100" width="100px;" alt=""/><br /><sub><b>marcoseoane</b></sub></a><br /><a href="#ideas-marcoseoane" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/rishabhpoddar"><img src="https://avatars2.githubusercontent.com/u/2976287?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rishabh Poddar</b></sub></a><br /><a href="#ideas-rishabhpoddar" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/lorenzorapetti"><img src="https://avatars1.githubusercontent.com/u/2632174?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lorenzo Rapetti</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lorenzorapetti" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/wKovacs64"><img src="https://avatars1.githubusercontent.com/u/1288694?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Justin Hall</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=wKovacs64" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=wKovacs64" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/sijad"><img src="https://avatars3.githubusercontent.com/u/7693001?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sajjad Hashemian</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sijad" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ETLopes"><img src="https://avatars3.githubusercontent.com/u/34959471?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eduardo Lopes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ETLopes" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mattleff"><img src="https://avatars0.githubusercontent.com/u/120155?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matthew Leffler</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mattleff" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://hew.tools"><img src="https://avatars0.githubusercontent.com/u/3103241?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hew" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/sonnypgs"><img src="https://avatars3.githubusercontent.com/u/1431300?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sonny</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sonnypgs" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Zeko369"><img src="https://avatars3.githubusercontent.com/u/3064377?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fran Zekan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Zeko369" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Zeko369" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://twitter.com/JanBaykara"><img src="https://avatars2.githubusercontent.com/u/237556?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jan Baykara</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=janbaykara" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://mikeattara.com"><img src="https://avatars1.githubusercontent.com/u/31483629?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike Perry Y Attara</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mikeattara" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://devanthe.dev"><img src="https://avatars0.githubusercontent.com/u/354652?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Devan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=DevanB" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/jclancy93"><img src="https://avatars2.githubusercontent.com/u/7850202?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jack Clancy</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jclancy93" title="Code">💻</a> <a href="#maintenance-jclancy93" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://github.com/ntgussoni"><img src="https://avatars0.githubusercontent.com/u/10161067?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nicolas Torres</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Antgussoni" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=ntgussoni" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://simonknott.de"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Simon Knott</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Tests">⚠️</a> <a href="#maintenance-Skn0tt" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=Skn0tt" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://jagascript.com"><img src="https://avatars0.githubusercontent.com/u/4562878?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jaga Santagostino</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kandros" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=kandros" title="Documentation">📖</a> <a href="#maintenance-kandros" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="http://www.joaoportela.com"><img src="https://avatars0.githubusercontent.com/u/1010018?v=4?s=100" width="100px;" alt=""/><br /><sub><b>João Portela</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jportela" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://dajin.dev"><img src="https://avatars0.githubusercontent.com/u/7122182?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Da-Jin Chu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dajinchu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://shinyaigeek.dev/"><img src="https://avatars1.githubusercontent.com/u/42742053?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shinobu Hayashi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Shinyaigeek" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://karankiri.com"><img src="https://avatars2.githubusercontent.com/u/19989161?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Karan Kiri</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=karankiri" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/fullmetalengineer"><img src="https://avatars2.githubusercontent.com/u/5294903?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alan Long</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fullmetalengineer" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://codingsh.xyz"><img src="https://avatars2.githubusercontent.com/u/57037080?v=4?s=100" width="100px;" alt=""/><br /><sub><b>codingsh</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=developerfred" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://twitter.com/peaonunes"><img src="https://avatars0.githubusercontent.com/u/3356720?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rafael Nunes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3Apeaonunes" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=peaonunes" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://simonpeterdebbarma.com"><img src="https://avatars3.githubusercontent.com/u/31207418?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Simon Debbarma</b></sub></a><br /><a href="#design-0ww" title="Design">🎨</a> <a href="#maintenance-0ww" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=0ww" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/0xflotus"><img src="https://avatars3.githubusercontent.com/u/26602940?v=4?s=100" width="100px;" alt=""/><br /><sub><b>0xflotus</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=0xflotus" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=0xflotus" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://dev.to/tmns"><img src="https://avatars3.githubusercontent.com/u/35785003?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tmns</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tmns" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=tmns" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://jruharris.com"><img src="https://avatars1.githubusercontent.com/u/8636691?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jru Harris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=harris1717" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/ivandevp"><img src="https://avatars3.githubusercontent.com/u/9284690?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ivan Medina</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ivandevp" title="Code">💻</a> <a href="#maintenance-ivandevp" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.dwightwatson.com"><img src="https://avatars3.githubusercontent.com/u/1100408?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dwight Watson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dwightwatson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dwightwatson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://is2ei.com/"><img src="https://avatars3.githubusercontent.com/u/3948353?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Horie Issei</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=is2ei" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/lednhatkhanh"><img src="https://avatars2.githubusercontent.com/u/9303093?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nhat Khanh</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lednhatkhanh" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://builtforfifty.com"><img src="https://avatars1.githubusercontent.com/u/19371989?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Abu Uzayr</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=abuuzayr" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=abuuzayr" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/nabi009"><img src="https://avatars0.githubusercontent.com/u/3170831?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nabiullah elham</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nabi009" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://lachlanjc.com"><img src="https://avatars1.githubusercontent.com/u/5074763?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lachlan Campbell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lachlanjc" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://enzoferey.com"><img src="https://avatars1.githubusercontent.com/u/10673347?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Enzo Ferey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=enzoferey" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/pgrimaud"><img src="https://avatars1.githubusercontent.com/u/1866496?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pierre Grimaud</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pgrimaud" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://pixelmord.github.io"><img src="https://avatars2.githubusercontent.com/u/224168?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andreas Adam</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pixelmord" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://kevo.dev"><img src="https://avatars3.githubusercontent.com/u/15717067?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Tovar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kevotovar" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://anteprimorac.com.hr"><img src="https://avatars0.githubusercontent.com/u/972083?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ante Primorac</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=anteprimorac" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=anteprimorac" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://mykalmachon.dev"><img src="https://avatars1.githubusercontent.com/u/7844994?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mykal Machon</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MykalMachon" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://jamiedavenport.dev"><img src="https://avatars2.githubusercontent.com/u/1329874?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jamie Davenport</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jamiedavenport" title="Code">💻</a> <a href="#maintenance-jamiedavenport" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="https://cloudnweb.dev/"><img src="https://avatars0.githubusercontent.com/u/17050715?v=4?s=100" width="100px;" alt=""/><br /><sub><b>GaneshMani</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ganeshmani" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://ramonmorcillo.com"><img src="https://avatars3.githubusercontent.com/u/31936665?v=4?s=100" width="100px;" alt=""/><br /><sub><b>reymon359</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=reymon359" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/gregory-vasquez-96413b184/"><img src="https://avatars1.githubusercontent.com/u/36422346?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gvasquez11</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gvasquez11" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/josemiguelo"><img src="https://avatars1.githubusercontent.com/u/15330034?v=4?s=100" width="100px;" alt=""/><br /><sub><b> José Miguel Ochoa</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=josemiguelo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/osirvent"><img src="https://avatars2.githubusercontent.com/u/5927133?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Oscar Sirvent</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=osirvent" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=osirvent" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/donni106"><img src="https://avatars0.githubusercontent.com/u/1942953?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Molnar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=donni106" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=donni106" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/exclipy"><img src="https://avatars1.githubusercontent.com/u/508799?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Wu Won</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=exclipy" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/tehnuge"><img src="https://avatars1.githubusercontent.com/u/1928236?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Duong</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tehnuge" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://noahfleischmann.com"><img src="https://avatars0.githubusercontent.com/u/23707137?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Noah Fleischmann</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fnoah" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/toshi1127"><img src="https://avatars3.githubusercontent.com/u/32378535?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matsumoto Toshi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=toshi1127" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=toshi1127" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/simonedelmann"><img src="https://avatars2.githubusercontent.com/u/2821076?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Simon Edelmann</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=simonedelmann" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://shaun.church"><img src="https://avatars3.githubusercontent.com/u/571764?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shaun Church</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=shaunchurch" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=shaunchurch" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://styfle.dev"><img src="https://avatars1.githubusercontent.com/u/229881?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Steven</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=styfle" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/SigurdMW"><img src="https://avatars3.githubusercontent.com/u/6359003?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sigurd Moland Wahl</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=SigurdMW" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://brianandrews.dev/"><img src="https://avatars1.githubusercontent.com/u/6384100?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Brian Andrews</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sbardian" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://garrisonsnelling.com"><img src="https://avatars0.githubusercontent.com/u/5100597?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Garrison Snelling</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=garrisons" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/tylangesmith"><img src="https://avatars1.githubusercontent.com/u/22609577?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ty Lange-Smith</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tylangesmith" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://rubenmoya.dev"><img src="https://avatars3.githubusercontent.com/u/905225?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rubén Moya</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rubenmoya" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=rubenmoya" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/robertgrzonka"><img src="https://avatars0.githubusercontent.com/u/35585466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>robertgrzonka</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robertgrzonka" title="Code">💻</a> <a href="#infra-robertgrzonka" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://github.com/agoxlea"><img src="https://avatars3.githubusercontent.com/u/1240841?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Orr</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=agoxlea" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://christse.io"><img src="https://avatars1.githubusercontent.com/u/250450?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Tse</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chris-tse" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://twitter.com/nettofarah"><img src="https://avatars1.githubusercontent.com/u/270688?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Netto Farah</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nettofarah" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/rohanjulka19"><img src="https://avatars0.githubusercontent.com/u/19673968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rohan Julka</b></sub></a><br /><a href="#infra-rohanjulka19" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
|
||||
<td align="center"><a href="https://www.ivansantos.me"><img src="https://avatars3.githubusercontent.com/u/301291?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ivan Santos</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pragmaticivan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://able.bio"><img src="https://avatars0.githubusercontent.com/u/12991390?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Soumyajit Pathak</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=drenther" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.sebastiankurpiel.com"><img src="https://avatars2.githubusercontent.com/u/16307737?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sebastian Kurpiel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=SebastianKurp" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/scisteffan"><img src="https://avatars2.githubusercontent.com/u/2676185?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Steffan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=scisteffan" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=scisteffan" title="Documentation">📖</a> <a href="#financial-scisteffan" title="Financial">💵</a></td>
|
||||
<td align="center"><a href="https://github.com/kripod"><img src="https://avatars3.githubusercontent.com/u/14854048?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kristóf Poduszló</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kripod" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Weilbyte"><img src="https://avatars1.githubusercontent.com/u/43392677?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Weilbyte</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Weilbyte" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Weilbyte" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://ricardotrejos.tech"><img src="https://avatars1.githubusercontent.com/u/8602086?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ricardo Trejos</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cardotrejos" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=cardotrejos" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://gkaragkiaouris.tech/"><img src="https://avatars0.githubusercontent.com/u/8822835?v=4?s=100" width="100px;" alt=""/><br /><sub><b>George Karagkiaouris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=karaggeorge" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=karaggeorge" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/brady-pascoe-3bba6b13a/"><img src="https://avatars0.githubusercontent.com/u/18705892?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Brady Pascoe</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bpas247" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.yeahcoach.com"><img src="https://avatars1.githubusercontent.com/u/761766?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jirka Svoboda</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=svobik7" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/alan2207"><img src="https://avatars3.githubusercontent.com/u/12713315?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alan Alickovic</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=alan2207" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=alan2207" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://yngve.hoiseth.net"><img src="https://avatars0.githubusercontent.com/u/8469540?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yngve Høiseth</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=yhoiseth" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/bruno_crosier"><img src="https://avatars1.githubusercontent.com/u/18399089?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bruno Crosier</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=brunocrosier" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/jschepmans"><img src="https://avatars2.githubusercontent.com/u/5782977?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johan Schepmans</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jschepmans" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/dillonraphael"><img src="https://avatars0.githubusercontent.com/u/3496193?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dillon Raphael</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=dillonraphael" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/clgeoio"><img src="https://avatars2.githubusercontent.com/u/37571416?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cody G</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=clgeoio" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=clgeoio" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/madflow"><img src="https://avatars0.githubusercontent.com/u/183248?v=4?s=100" width="100px;" alt=""/><br /><sub><b>madflow</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=madflow" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/nitaking_"><img src="https://avatars2.githubusercontent.com/u/10850034?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Satoshi Nitawaki</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nitaking" title="Code">💻</a> <a href="#maintenance-nitaking" title="Maintenance">🚧</a> <a href="#question-nitaking" title="Answering Questions">💬</a> <a href="https://github.com/blitz-js/blitz/commits?author=nitaking" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/sirmyron"><img src="https://avatars2.githubusercontent.com/u/1430136?v=4?s=100" width="100px;" alt=""/><br /><sub><b>sirmyron</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sirmyron" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=sirmyron" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/engelkes-finstreet"><img src="https://avatars1.githubusercontent.com/u/36962022?v=4?s=100" width="100px;" alt=""/><br /><sub><b>engelkes-finstreet</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=engelkes-finstreet" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=engelkes-finstreet" title="Code">💻</a> <a href="#maintenance-engelkes-finstreet" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://twitter.com/pixelscommander"><img src="https://avatars2.githubusercontent.com/u/810671?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Denis Radin</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/pulls?q=is%3Apr+reviewed-by%3APixelsCommander" title="Reviewed Pull Requests">👀</a> <a href="https://github.com/blitz-js/blitz/commits?author=PixelsCommander" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=PixelsCommander" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/xiaoyu-tamu"><img src="https://avatars3.githubusercontent.com/u/33362998?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Li</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=xiaoyu-tamu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/yuta0801"><img src="https://avatars2.githubusercontent.com/u/21266306?v=4?s=100" width="100px;" alt=""/><br /><sub><b>yuta0801</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=yuta0801" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Obii-bit"><img src="https://avatars2.githubusercontent.com/u/67339820?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Obadja Ris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Obii-bit" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://jfelix.info"><img src="https://avatars2.githubusercontent.com/u/21092519?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jose Felix </b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=JoseRFelix" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/johncantrell97"><img src="https://avatars3.githubusercontent.com/u/41305919?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Cantrell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=johncantrell97" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kwuang.me"><img src="https://avatars1.githubusercontent.com/u/10319942?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kwuang Tang</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cktang88" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/johnletey"><img src="https://avatars1.githubusercontent.com/u/62398724?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Letey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=johnletey" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ditorojuan"><img src="https://avatars0.githubusercontent.com/u/22530892?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Juan Di Toro</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ditorojuan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/taylorcjohnson"><img src="https://avatars0.githubusercontent.com/u/10552296?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Taylor Johnson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=taylorcjohnson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=taylorcjohnson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://twitter.com/tsriram"><img src="https://avatars3.githubusercontent.com/u/450559?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sriram Thiagarajan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tsriram" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://sergiodxa.com"><img src="https://avatars2.githubusercontent.com/u/1312018?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sergio Xalambrí</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sergiodxa" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/doeixd"><img src="https://avatars3.githubusercontent.com/u/13461122?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Patrick G</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doeixd" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://avinash.com.np"><img src="https://avatars3.githubusercontent.com/u/513457?v=4?s=100" width="100px;" alt=""/><br /><sub><b>अभिनाश (Avinash)</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hardfire" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://enricoschaaf.com"><img src="https://avatars1.githubusercontent.com/u/54645197?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Enrico Schaaf</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=enricoschaaf" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kitze.io"><img src="https://avatars0.githubusercontent.com/u/1160594?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kitze</b></sub></a><br /><a href="#ideas-kitze" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||
<td align="center"><a href="https://github.com/drmas"><img src="https://avatars3.githubusercontent.com/u/644440?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mohamed Shaban</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=drmas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jorisre"><img src="https://avatars1.githubusercontent.com/u/7545547?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joris</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jorisre" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Kamshak"><img src="https://avatars3.githubusercontent.com/u/337968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Valentin Funk</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Kamshak" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://lukebennett.com"><img src="https://avatars1.githubusercontent.com/u/135390?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Luke Bennett</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lukebennett" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://haseebmajid.dev"><img src="https://avatars0.githubusercontent.com/u/998807?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Haseeb Majid</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hmajid2301" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/phillippschmedt"><img src="https://avatars0.githubusercontent.com/u/16028406?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Phillipp Schmedt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=phillippschmedt" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://haspar.us"><img src="https://avatars0.githubusercontent.com/u/15332326?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piotr Monwid-Olechnowicz</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hasparus" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://mizchi.dev"><img src="https://avatars2.githubusercontent.com/u/73962?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kotaro Chikuba</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mizchi" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=mizchi" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/konradkalemba"><img src="https://avatars0.githubusercontent.com/u/8682104?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Konrad Kalemba</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=konradkalemba" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=konradkalemba" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Alucard17"><img src="https://avatars1.githubusercontent.com/u/26205172?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alucard17</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Alucard17" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Dohxis"><img src="https://avatars2.githubusercontent.com/u/8768909?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Domantas Mauruča</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Dohxis" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=Dohxis" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://sandulat.com/"><img src="https://avatars0.githubusercontent.com/u/7345874?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stratulat Alexandru</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sandulat" title="Code">💻</a> <a href="#maintenance-sandulat" title="Maintenance">🚧</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/aericson"><img src="https://avatars3.githubusercontent.com/u/692542?v=4?s=100" width="100px;" alt=""/><br /><sub><b>André Ericson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aericson" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=aericson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://Cajotafer.com"><img src="https://avatars2.githubusercontent.com/u/41461969?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Carlos Fernández</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cajotafer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://oesterkilde.dk/"><img src="https://avatars1.githubusercontent.com/u/6379824?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Østerkilde</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Kosai106" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Kosai106" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/aaronfulkerson"><img src="https://avatars0.githubusercontent.com/u/31112737?v=4?s=100" width="100px;" alt=""/><br /><sub><b>aaronfulkerson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aaronfulkerson" title="Code">💻</a> <a href="#question-aaronfulkerson" title="Answering Questions">💬</a></td>
|
||||
<td align="center"><a href="https://github.com/alexnaiman"><img src="https://avatars3.githubusercontent.com/u/25799714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alexandru Naiman</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=alexnaiman" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://davidlutta.github.io/portfolio/"><img src="https://avatars2.githubusercontent.com/u/14890315?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Ezekiel Lutta</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davidlutta" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/wanjuntham"><img src="https://avatars1.githubusercontent.com/u/49380551?v=4?s=100" width="100px;" alt=""/><br /><sub><b>wanjuntham</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=wanjuntham" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://www.nahuelchaves.xyz"><img src="https://avatars3.githubusercontent.com/u/96837?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Victor Nahuel Chaves</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nahue" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/peter50216"><img src="https://avatars3.githubusercontent.com/u/891109?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Peter Shih</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=peter50216" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://seweryn.kale.mba"><img src="https://avatars3.githubusercontent.com/u/37031328?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Seweryn Kalemba</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sewerynkalemba" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://nksaraf.github.io"><img src="https://avatars2.githubusercontent.com/u/11255148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nikhil Saraf</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nksaraf" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=nksaraf" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://zane.sh"><img src="https://avatars0.githubusercontent.com/u/16865690?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zane</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=zanedb" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/dulcehc"><img src="https://avatars1.githubusercontent.com/u/19391835?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dulce Hernández</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dulcehc" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://markhaehnel.de"><img src="https://avatars2.githubusercontent.com/u/1516205?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mark Hähnel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=markhaehnel" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://stackoverflow.com/users/872395/nemesv"><img src="https://avatars0.githubusercontent.com/u/251330?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Viktor Nemes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nemesv" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://gabeoleary.com"><img src="https://avatars1.githubusercontent.com/u/16123225?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gabe O'Leary</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=goleary" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/machadolucasvp"><img src="https://avatars0.githubusercontent.com/u/44952113?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lucas Machado</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=machadolucasvp" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/maciekgrzybek"><img src="https://avatars2.githubusercontent.com/u/16546428?v=4?s=100" width="100px;" alt=""/><br /><sub><b>maciek_grzybek</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maciekgrzybek" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mweibel"><img src="https://avatars1.githubusercontent.com/u/307427?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Weibel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mweibel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://isoppp.com"><img src="https://avatars0.githubusercontent.com/u/16318727?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hiroki Isogai</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=isoppp" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/matamatanot"><img src="https://avatars2.githubusercontent.com/u/39780486?v=4?s=100" width="100px;" alt=""/><br /><sub><b>matamatanot</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=matamatanot" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ericsakmar"><img src="https://avatars3.githubusercontent.com/u/5620709?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eric Sakmar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ericsakmar" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/leggsimon"><img src="https://avatars2.githubusercontent.com/u/11544418?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Simon Legg</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=leggsimon" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://robsoriano.com"><img src="https://avatars3.githubusercontent.com/u/13049130?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert Soriano</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=wobsoriano" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/benediktms"><img src="https://avatars2.githubusercontent.com/u/48836135?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benedikt Schnatterbeck</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=benediktms" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://taloranderson.com"><img src="https://avatars2.githubusercontent.com/u/11509865?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Talor Anderson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Talor-A" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Talor-A" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/akirabaruah"><img src="https://avatars2.githubusercontent.com/u/6751517?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Akira Baruah</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=akirabaruah" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://chriswray.dev/"><img src="https://avatars0.githubusercontent.com/u/53663762?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christopher Wray</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cwray-tech" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/piotrski"><img src="https://avatars0.githubusercontent.com/u/244174?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Piotrek Tomczewski</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=piotrski" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=piotrski" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://raph.site"><img src="https://avatars3.githubusercontent.com/u/1575946?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Raphaël Huchet</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=rap2hpoutre" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://kattcorp.com"><img src="https://avatars1.githubusercontent.com/u/459267?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Johansson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=KATT" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://davidmazza.com"><img src="https://avatars0.githubusercontent.com/u/120893?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Mazza</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dmzza" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rayandrews"><img src="https://avatars1.githubusercontent.com/u/4437323?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ray Andrew</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rayandrews" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=rayandrews" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://Dal.Design"><img src="https://avatars3.githubusercontent.com/u/43112535?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Abdullah Mzaien</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Mzaien" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Mzaien" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://kwao.io"><img src="https://avatars2.githubusercontent.com/u/8839514?v=4?s=100" width="100px;" alt=""/><br /><sub><b>William Kwao</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=williamkwao" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/sakulstra"><img src="https://avatars3.githubusercontent.com/u/4396533?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lukas Strassel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sakulstra" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=sakulstra" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://thibpat.com"><img src="https://avatars3.githubusercontent.com/u/494686?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Thibaut Patel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tpatel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://jonstuebe.com"><img src="https://avatars0.githubusercontent.com/u/156722?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jon Stuebe</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jonstuebe" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://ugogo.dev"><img src="https://avatars2.githubusercontent.com/u/5040476?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ugo Onali</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ugogo" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://saintmalik.me"><img src="https://avatars1.githubusercontent.com/u/37118134?v=4?s=100" width="100px;" alt=""/><br /><sub><b>SaintMalik</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=saintmalik" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://khaledgarbaya.net"><img src="https://avatars1.githubusercontent.com/u/1156093?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Khaled Garbaya</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Khaledgarbaya" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://tundera.dev"><img src="https://avatars0.githubusercontent.com/u/61833561?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tundera</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tundera" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=tundera" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=tundera" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/markylaing"><img src="https://avatars2.githubusercontent.com/u/41469221?v=4?s=100" width="100px;" alt=""/><br /><sub><b>markylaing</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=markylaing" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=markylaing" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://akfm.dev/"><img src="https://avatars2.githubusercontent.com/u/25711332?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Akifumi Sato</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=AkifumiSato" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/beeplin"><img src="https://avatars3.githubusercontent.com/u/13058150?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Beep LIN</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=beeplin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://mattwood.tech/"><img src="https://avatars1.githubusercontent.com/u/22530815?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt Wood</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mattfwood" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://joaquin.axai.mx"><img src="https://avatars1.githubusercontent.com/u/15214?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joaquin Bravo Contreras</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jackbravo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/arjundubey-cr"><img src="https://avatars0.githubusercontent.com/u/40758425?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arjun Dubey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arjundubey-cr" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chanand"><img src="https://avatars0.githubusercontent.com/u/1317789?v=4?s=100" width="100px;" alt=""/><br /><sub><b>chanand</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chanand" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/phillipkregg"><img src="https://avatars0.githubusercontent.com/u/1066044?v=4?s=100" width="100px;" alt=""/><br /><sub><b>phillipkregg</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=phillipkregg" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://timothyreynolds.co.uk"><img src="https://avatars1.githubusercontent.com/u/168870?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tim Reynolds</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=timReynolds" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://linbudu.top/"><img src="https://avatars0.githubusercontent.com/u/48507806?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Linbudu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=linbudu599" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.superservice-international.com"><img src="https://avatars0.githubusercontent.com/u/6090492?v=4?s=100" width="100px;" alt=""/><br /><sub><b>C Reimers</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=creimers" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/kyken"><img src="https://avatars2.githubusercontent.com/u/20137120?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tsuyoshi Osawa</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kyken" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://rembrandtreyes.com/"><img src="https://avatars1.githubusercontent.com/u/15057964?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rembrandt Reyes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rembrandtreyes" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=rembrandtreyes" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rembrandtreyes" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://doi-t.net"><img src="https://avatars2.githubusercontent.com/u/5877477?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Toshiya Doi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doi-t" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.koolii.net/"><img src="https://avatars1.githubusercontent.com/u/3866581?v=4?s=100" width="100px;" alt=""/><br /><sub><b>t.kuriyama</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=koolii" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/malkomalko"><img src="https://avatars3.githubusercontent.com/u/763?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert Malko</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=malkomalko" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ranjan-purbey"><img src="https://avatars3.githubusercontent.com/u/6953187?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ranjan Purbey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ranjan-purbey" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/tarunama"><img src="https://avatars3.githubusercontent.com/u/6047881?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tarunama</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tarunama" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.bacongravy.net/"><img src="https://avatars3.githubusercontent.com/u/16848768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Kramer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bacongravy" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://mikeesto.com"><img src="https://avatars1.githubusercontent.com/u/21051488?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Esteban</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mikeesto" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/marina-ki"><img src="https://avatars0.githubusercontent.com/u/54174518?v=4?s=100" width="100px;" alt=""/><br /><sub><b>marina</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=marina-ki" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=marina-ki" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/jonasthiesen"><img src="https://avatars.githubusercontent.com/u/23408018?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonas Thiesen</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jonasthiesen" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://thakkaryash94.github.io/"><img src="https://avatars.githubusercontent.com/u/7349778?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yash Thakkar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=thakkaryash94" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rince"><img src="https://avatars.githubusercontent.com/u/933895?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kazuma Suzuki</b></sub></a><br /><a href="#design-rince" title="Design">🎨</a> <a href="https://github.com/blitz-js/blitz/commits?author=rince" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://queq1890.info"><img src="https://avatars.githubusercontent.com/u/32263803?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yuji Matsumoto</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=queq1890" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/Gim3l"><img src="https://avatars.githubusercontent.com/u/46765702?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gimel Dick</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Gim3l" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/akbo"><img src="https://avatars.githubusercontent.com/u/1926271?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andreas Bollig</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=akbo" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=akbo" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://ajm.codes"><img src="https://avatars.githubusercontent.com/u/66390428?v=4?s=100" width="100px;" alt=""/><br /><sub><b>AJ Markow</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ajmarkow" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=ajmarkow" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://wafuwafu13.hateblo.jp/"><img src="https://avatars.githubusercontent.com/u/50798936?v=4?s=100" width="100px;" alt=""/><br /><sub><b>TagawaHirotaka</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=wafuwafu13" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=wafuwafu13" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/merodiro"><img src="https://avatars.githubusercontent.com/u/17033502?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amr A.Mohammed</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=merodiro" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.lucaswillems.com"><img src="https://avatars.githubusercontent.com/u/5437552?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lucas Willems</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lcswillems" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=lcswillems" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://alistair.cloud"><img src="https://avatars.githubusercontent.com/u/25351731?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alistair Smith</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=alii" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://rodrigoehlers.com"><img src="https://avatars.githubusercontent.com/u/19683042?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rodrigo Ehlers</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rodrigoehlers" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.builtopen.com/"><img src="https://avatars.githubusercontent.com/u/1734057?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Ford</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mtford90" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://brianypliu.com"><img src="https://avatars.githubusercontent.com/u/3888780?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Brian Liu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=LBrian" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://aleksandra.codes"><img src="https://avatars.githubusercontent.com/u/9019397?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksandra Sikora</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=beerose" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://juanm04.com"><img src="https://avatars.githubusercontent.com/u/16712703?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JuanM04</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=JuanM04" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=JuanM04" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=JuanM04" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/arenddeboer"><img src="https://avatars.githubusercontent.com/u/7022204?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arend de Boer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arenddeboer" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/fmilani"><img src="https://avatars.githubusercontent.com/u/1580375?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Felipe Milani</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fmilani" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://nxhx.org"><img src="https://avatars.githubusercontent.com/u/13018?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joe Edelman</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jxe" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/garytube"><img src="https://avatars.githubusercontent.com/u/3823504?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gary</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=garytube" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://oliverloops.com"><img src="https://avatars.githubusercontent.com/u/33361399?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Oliver Lopez </b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=oliverloops" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://decadentIpsum.me"><img src="https://avatars.githubusercontent.com/u/32861532?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andreas Zaralis</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=DecadentIpsum" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/davetorbeck"><img src="https://avatars.githubusercontent.com/u/5829885?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Torbeck</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davetorbeck" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/gusgard"><img src="https://avatars.githubusercontent.com/u/2577356?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gustavo Gard</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gusgard" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://narrationbox.com"><img src="https://avatars.githubusercontent.com/u/7126128?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Immortalin</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Immortalin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://cristianbgp.com"><img src="https://avatars.githubusercontent.com/u/8507974?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cristian Granda</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cristianbgp" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://deniseyu.io"><img src="https://avatars.githubusercontent.com/u/8420094?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Denise Yu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=deniseyu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://dellacorte.me"><img src="https://avatars.githubusercontent.com/u/295683?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrea Della Corte</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=andreadellacorte" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://aditsachde.com"><img src="https://avatars.githubusercontent.com/u/23707194?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Adit Sachde</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=aditsachde" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/hirenchauhan2"><img src="https://avatars.githubusercontent.com/u/8999668?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hiren Chauhan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hirenchauhan2" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://remjx.com/"><img src="https://avatars.githubusercontent.com/u/35121685?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mark Jackson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=remjx" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=remjx" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://lewisb.cloud/"><img src="https://avatars.githubusercontent.com/u/51877955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lewis Blackburn</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lewisblackburn" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/FDiskas"><img src="https://avatars.githubusercontent.com/u/468006?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vytenis</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=FDiskas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://portfolio.matthieupetit.com"><img src="https://avatars.githubusercontent.com/u/12969089?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matthieu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=matthieu994" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=matthieu994" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/mitchazj"><img src="https://avatars.githubusercontent.com/u/15032956?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mitchell Johnson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mitchazj" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://roshan.page/"><img src="https://avatars.githubusercontent.com/u/31125563?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Roshan Manuel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Roesh" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Roesh" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Roesh" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://kevinlangleyjr.com"><img src="https://avatars.githubusercontent.com/u/877634?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Langley Jr.</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kevinlangleyjr" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=kevinlangleyjr" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://projet-test-99df0.firebaseapp.com/"><img src="https://avatars.githubusercontent.com/u/51029779?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gabriel Picard</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=heavygabriel" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://ryanchenkie.com/"><img src="https://avatars.githubusercontent.com/u/1847678?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ryan Chenkie</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chenkie" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/sbappan"><img src="https://avatars.githubusercontent.com/u/12586088?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Santhosh B. Appan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sbappan" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://stackoverflow.com/users/5207233/james-moran"><img src="https://avatars.githubusercontent.com/u/10858584?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Moran</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=james2406" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=james2406" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://fb.me/yz"><img src="https://avatars.githubusercontent.com/u/14841421?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jack Zhao</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bugzpodder" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/the-red"><img src="https://avatars.githubusercontent.com/u/4494300?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hisaki Akaza</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=the-red" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://flavioander.com/"><img src="https://avatars.githubusercontent.com/u/14948074?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Flavio</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Flavyoo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://bhanuteja.dev/"><img src="https://avatars.githubusercontent.com/u/17903466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bhanu Teja Pachipulusu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pbteja1998" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/pavestru"><img src="https://avatars.githubusercontent.com/u/10186479?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pavel Struhar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=pavestru" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://in-thepink.com/"><img src="https://avatars.githubusercontent.com/u/42126368?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Reo Ishiyama</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=reo777" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://macwright.com/"><img src="https://avatars.githubusercontent.com/u/32314?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tom MacWright</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tmcw" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=tmcw" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=tmcw" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://francoisbest.com"><img src="https://avatars.githubusercontent.com/u/1174092?v=4?s=100" width="100px;" alt=""/><br /><sub><b>François Best</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=franky47" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/FarazPatankar"><img src="https://avatars.githubusercontent.com/u/10681116?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Faraz Patankar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=FarazPatankar" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/ericvicenti"><img src="https://avatars.githubusercontent.com/u/1483597?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eric Vicenti</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ericvicenti" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=ericvicenti" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/amdolan"><img src="https://avatars.githubusercontent.com/u/2552275?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alex Dolan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=amdolan" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=amdolan" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=amdolan" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/Maastrich"><img src="https://avatars.githubusercontent.com/u/58431775?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mathis Pinsault</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Maastrich" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/gstranger"><img src="https://avatars.githubusercontent.com/u/36181416?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gstranger</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gstranger" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=gstranger" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://twitter.com/_markeh"><img src="https://avatars.githubusercontent.com/u/1357323?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mark Hughes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=markhughes" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=markhughes" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.andrearizzello.work"><img src="https://avatars.githubusercontent.com/u/10348930?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrea Rizzello</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=andrearizzello" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="jahred.com.au"><img src="https://avatars.githubusercontent.com/u/13903378?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jahred Hope</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jahredhope" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="simonelnahas.github.io/"><img src="https://avatars.githubusercontent.com/u/29279201?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Simon El Nahas</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=simonelnahas" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.usertrack.net"><img src="https://avatars.githubusercontent.com/u/1384885?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Buleandra Cristian</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Cristy94" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Cristy94" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://palauisaac.me/"><img src="https://avatars.githubusercontent.com/u/12257885?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pedro Enrique Palau Isaac</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=peterpalau" title="Code">💻</a></td>
|
||||
<td align="center"><a href="www.seanbrydon.me"><img src="https://avatars.githubusercontent.com/u/55134778?v=4?s=100" width="100px;" alt=""/><br /><sub><b>sean-brydon</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sean-brydon" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="buonerba.dev"><img src="https://avatars.githubusercontent.com/u/28837891?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Alessandro</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Dieman89" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.jyutping.org"><img src="https://avatars.githubusercontent.com/u/11172180?v=4?s=100" width="100px;" alt=""/><br /><sub><b>laubonghaudoi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=laubonghaudoi" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/TommasoBruno99"><img src="https://avatars.githubusercontent.com/u/61512591?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tommaso Bruno</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=TommasoBruno99" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="antonykamp.de"><img src="https://avatars.githubusercontent.com/u/45163503?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Antony</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=antonykamp" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://blog.6nok.org"><img src="https://avatars.githubusercontent.com/u/868283?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fatih Altinok</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=frontsideair" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://mokshitjain.co/"><img src="https://avatars.githubusercontent.com/u/50412128?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mokshit Jain</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Mokshit06" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://mubaidr.github.io"><img src="https://avatars.githubusercontent.com/u/2222702?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Muhammad Ubaid Raza</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mubaidr" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=mubaidr" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/silicontwin"><img src="https://avatars.githubusercontent.com/u/121665?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nick Warren</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=silicontwin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mlabate"><img src="https://avatars.githubusercontent.com/u/17139676?v=4?s=100" width="100px;" alt=""/><br /><sub><b>mlabate</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mlabate" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/lumaxis"><img src="https://avatars.githubusercontent.com/u/406937?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lukas Spieß</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lumaxis" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://dawnofmidnight.vercel.app"><img src="https://avatars.githubusercontent.com/u/78233879?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DawnOfMidnight</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dawnofmidnight" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/kenzairaki/"><img src="https://avatars.githubusercontent.com/u/17203119?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kenza Iraki</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kirakik" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=kirakik" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/agustif"><img src="https://avatars.githubusercontent.com/u/6601142?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Agusti Fernandez</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=agustif" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Anjianto"><img src="https://avatars.githubusercontent.com/u/61521141?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Anjianto</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Anjianto" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://adrienblanc.com"><img src="https://avatars.githubusercontent.com/u/41756894?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Blanc Adrien</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=adblanc" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/meepdeew"><img src="https://avatars.githubusercontent.com/u/43303008?v=4?s=100" width="100px;" alt=""/><br /><sub><b>meepdeew</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=meepdeew" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/Hardik3296"><img src="https://avatars.githubusercontent.com/u/20360325?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hardik Gaur</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Hardik3296" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/acornellier"><img src="https://avatars.githubusercontent.com/u/8725423?v=4?s=100" width="100px;" alt=""/><br /><sub><b>acornellier</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=acornellier" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/craigglennie"><img src="https://avatars.githubusercontent.com/u/149281?v=4?s=100" width="100px;" alt=""/><br /><sub><b>craigglennie</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=craigglennie" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.fernvillasenor.com"><img src="https://avatars.githubusercontent.com/u/5857808?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fernando Villasenor</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fernvilla" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/swiftgaruda"><img src="https://avatars.githubusercontent.com/u/16741392?v=4?s=100" width="100px;" alt=""/><br /><sub><b>swiftgaruda</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=swiftgaruda" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://pplife.home.blog"><img src="https://avatars.githubusercontent.com/u/35653876?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pankaj Patil</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Patil2099" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="minaabadir.ca"><img src="https://avatars.githubusercontent.com/u/3389914?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mina Abadir</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mabadir" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=mabadir" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=mabadir" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/frankiesardo"><img src="https://avatars.githubusercontent.com/u/1476561?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Francesco Sardo</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=frankiesardo" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=frankiesardo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/enemycnt"><img src="https://avatars.githubusercontent.com/u/320313?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nikolay</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=enemycnt" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://dipeshwagle.com"><img src="https://avatars.githubusercontent.com/u/4191022?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dipesh Wagle</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Dipeshwagle" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://codepoet.de"><img src="https://avatars.githubusercontent.com/u/462455?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benjamin Bender</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=benbender" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://nima.sh"><img src="https://avatars.githubusercontent.com/u/3728170?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nima Shoghi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nimashoghi" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chronark"><img src="https://avatars.githubusercontent.com/u/18246773?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andreas Thomas</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chronark" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/guoqqqi"><img src="https://avatars.githubusercontent.com/u/72343596?v=4?s=100" width="100px;" alt=""/><br /><sub><b>guoqqqi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=guoqqqi" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/timbooker"><img src="https://avatars.githubusercontent.com/u/612681?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tim</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=timbooker" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=timbooker" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="http://orlowski.me/"><img src="https://avatars.githubusercontent.com/u/16357457?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Marek Orłowski</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ormarek" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/AntoineGuestin"><img src="https://avatars.githubusercontent.com/u/70888750?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Antoine G</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=AntoineGuestin" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/swinner2"><img src="https://avatars.githubusercontent.com/u/6707308?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sean Winner</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=swinner2" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=swinner2" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=swinner2" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://usman-s.me"><img src="https://avatars.githubusercontent.com/u/51731966?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Max Programming</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=max-programming" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://makemake.sh"><img src="https://avatars.githubusercontent.com/u/353768?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sebastian Hoitz</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sebastianhoitz" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=sebastianhoitz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/garnerp"><img src="https://avatars.githubusercontent.com/u/737307?v=4?s=100" width="100px;" alt=""/><br /><sub><b>garnerp</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=garnerp" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kivi"><img src="https://avatars.githubusercontent.com/u/366163?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kivi</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kivi" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://dangreaves.com"><img src="https://avatars.githubusercontent.com/u/1036142?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dan Greaves</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dangreaves" title="Code">💻</a></td>
|
||||
<td align="center"><a href="lksnmnn.com"><img src="https://avatars.githubusercontent.com/u/4983285?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lukas Neumann</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lksnmnn" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=lksnmnn" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=lksnmnn" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="dbachrach.com"><img src="https://avatars.githubusercontent.com/u/45016?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dustin Bachrach</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dbachrach" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dbachrach" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/ashikka"><img src="https://avatars.githubusercontent.com/u/58368421?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ashikka Gupta</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ashikka" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=ashikka" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/deini"><img src="https://avatars.githubusercontent.com/u/2752665?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Almaguer</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=deini" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.kevinpeters.net/about/"><img src="https://avatars.githubusercontent.com/u/12736734?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Peters</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=igeligel" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="http://anolilab.de"><img src="https://avatars.githubusercontent.com/u/2716058?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Bannert</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=prisis" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=prisis" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://benjakugler96.github.io/"><img src="https://avatars.githubusercontent.com/u/53273645?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Benja Kugler</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=benjakugler96" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://semeniuc.ml/"><img src="https://avatars.githubusercontent.com/u/3838856?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Eric Semeniuc</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=esemeniuc" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=esemeniuc" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ricardo-rp"><img src="https://avatars.githubusercontent.com/u/30808767?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ricardo Romero</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ricardo-rp" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="exocortex.anothernode.com"><img src="https://avatars.githubusercontent.com/u/3286144?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Moritz Reiter</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=anothernode" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://msich.dev"><img src="https://avatars.githubusercontent.com/u/38794918?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt Sichterman</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=msichterman" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/medihack"><img src="https://avatars.githubusercontent.com/u/120626?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kai Schlamp</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=medihack" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=medihack" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://muyiwa.me"><img src="https://avatars.githubusercontent.com/u/6832244?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Muyiwa Olu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=muyiwaolu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://2hr.me/"><img src="https://avatars.githubusercontent.com/u/4346154?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rabbi Hossain</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rabbihossain" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/bravo-kernel"><img src="https://avatars.githubusercontent.com/u/230500?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bravo-kernel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bravo-kernel" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=bravo-kernel" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://samholmes.net"><img src="https://avatars.githubusercontent.com/u/8385528?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sam Holmes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sam3d" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://doncicuto.medium.com"><img src="https://avatars.githubusercontent.com/u/30386061?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Miguel Cabrerizo</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doncicuto" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=doncicuto" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://zackhobson.com/"><img src="https://avatars.githubusercontent.com/u/12092?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zack Hobson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=zenhob" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=zenhob" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://www.mokhtar.dev"><img src="https://avatars.githubusercontent.com/u/13026820?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mokhtar</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=m5r" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/kenkuan"><img src="https://avatars.githubusercontent.com/u/1924968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ken Kuan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kenkuan" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/meehawk"><img src="https://avatars.githubusercontent.com/u/80167324?v=4?s=100" width="100px;" alt=""/><br /><sub><b>meehawk</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=meehawk" title="Code">💻</a></td>
|
||||
<td align="center"><a href="rahulravindran.in"><img src="https://avatars.githubusercontent.com/u/10168946?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rahul Ravindran</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ravindranrahul" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/s-r-x"><img src="https://avatars.githubusercontent.com/u/41614937?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ilya</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=s-r-x" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/hashimwarren"><img src="https://avatars.githubusercontent.com/u/6027587?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hashim Warren</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=hashimwarren" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://damilolarandolph.com"><img src="https://avatars.githubusercontent.com/u/43427949?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Damilola Randolph</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=damilolarandolph" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/mwcampbell"><img src="https://avatars.githubusercontent.com/u/214820?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Matt Campbell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mwcampbell" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/ratson"><img src="https://avatars.githubusercontent.com/u/2682937?v=4?s=100" width="100px;" alt=""/><br /><sub><b>(◕ᴥ◕)</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ratson" title="Code">💻</a></td>
|
||||
<td align="center"><a href="maciejmyslinski.com"><img src="https://avatars.githubusercontent.com/u/11421186?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mat Milbury</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maciejmyslinski" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://andreas.fyi"><img src="https://avatars.githubusercontent.com/u/8077469?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andreas Asprou</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=andreasasprou" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/kotx"><img src="https://avatars.githubusercontent.com/u/33439542?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kot</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kotx" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=kotx" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=kotx" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/isaka1022"><img src="https://avatars.githubusercontent.com/u/28589716?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Amane</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=isaka1022" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="johnleung.com"><img src="https://avatars.githubusercontent.com/u/20699?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Leung</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fuzzthink" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="roettgers.co"><img src="https://avatars.githubusercontent.com/u/29666239?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bruce</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bcye" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/emilygracekz"><img src="https://avatars.githubusercontent.com/u/57361805?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Emily</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=emilygracekz" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/npverni"><img src="https://avatars.githubusercontent.com/u/3537?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nathan Verni</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=npverni" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://davyengone.io"><img src="https://avatars.githubusercontent.com/u/4896002?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Davy Engone</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davyengone" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://fedeorlandau.dev/"><img src="https://avatars.githubusercontent.com/u/10283686?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Federico Joel Orlandau</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Fedeorlandau" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Fedeorlandau" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/johnmurphy01"><img src="https://avatars.githubusercontent.com/u/2939548?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Murphy</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=johnmurphy01" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=johnmurphy01" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/martinsaxa"><img src="https://avatars.githubusercontent.com/u/33789474?v=4?s=100" width="100px;" alt=""/><br /><sub><b>martinsaxa</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=martinsaxa" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/ajwgeek"><img src="https://avatars.githubusercontent.com/u/2135600?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austin Walhof</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ajwgeek" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="g3offrey.dev"><img src="https://avatars.githubusercontent.com/u/11151445?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Geoffrey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=g3offrey" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=g3offrey" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=g3offrey" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/keevan"><img src="https://avatars.githubusercontent.com/u/9924643?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Pham</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=keevan" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/kimngan-bui"><img src="https://avatars.githubusercontent.com/u/20723478?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kimngan-bui</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kimngan-bui" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="world.hey.com/bach"><img src="https://avatars.githubusercontent.com/u/11691670?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bahk Chanhee</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=9j" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.afterecon.com/"><img src="https://avatars.githubusercontent.com/u/5559355?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Vandivier</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Vandivier" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=Vandivier" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=Vandivier" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://namirsab.github.io"><img src="https://avatars.githubusercontent.com/u/6980777?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Namir</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=namirsab" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=namirsab" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=namirsab" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://twitter.com/scttcper"><img src="https://avatars.githubusercontent.com/u/1400464?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Scott Cooper</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=scttcper" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="abduttayyeb.github.io"><img src="https://avatars.githubusercontent.com/u/55306260?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Abduttayyeb M.r</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Abduttayyeb" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/maybebored"><img src="https://avatars.githubusercontent.com/u/20951181?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mayuran</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maybebored" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/MuckHub"><img src="https://avatars.githubusercontent.com/u/54979136?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksei Vesselko</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MuckHub" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://p-siriphanthong.github.io/"><img src="https://avatars.githubusercontent.com/u/29949429?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Punn Siriphanthong</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=p-siriphanthong" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://my-portfolio-292eb.web.app"><img src="https://avatars.githubusercontent.com/u/83679827?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shawn Fetanat</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=shawn-fetanat" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/mochi-sann"><img src="https://avatars.githubusercontent.com/u/44772513?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Moyuru</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=mochi-sann" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=mochi-sann" title="Tests">⚠️</a> <a href="https://github.com/blitz-js/blitz/commits?author=mochi-sann" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/camsloanftc"><img src="https://avatars.githubusercontent.com/u/16295659?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cam Sloan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=camsloanftc" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://macieksitkowski.com"><img src="https://avatars.githubusercontent.com/u/58401630?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maciek Sitkowski</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sitek94" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/vivek7405"><img src="https://avatars.githubusercontent.com/u/24492244?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vivek</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=vivek7405" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=vivek7405" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://cj.io"><img src="https://avatars.githubusercontent.com/u/1819?v=4?s=100" width="100px;" alt=""/><br /><sub><b>CJ Lazell</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="robertbroersma.com"><img src="https://avatars.githubusercontent.com/u/4519828?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=RobertBroersma" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://christianjensen.netlify.com"><img src="https://avatars.githubusercontent.com/u/12374723?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christian Jensen</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cbejensen" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/dvnrsn"><img src="https://avatars.githubusercontent.com/u/9112811?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Devin Rasmussen</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dvnrsn" title="Code">💻</a></td>
|
||||
<td align="center"><a href="www.linkedin.com/in/devtom"><img src="https://avatars.githubusercontent.com/u/23282613?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Thomas Brenneur</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=devtombiz" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=devtombiz" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=devtombiz" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://lucasvazq.github.io/"><img src="https://avatars.githubusercontent.com/u/38964964?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lucas Vazquez</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lucasvazq" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/chrisj-back2work"><img src="https://avatars.githubusercontent.com/u/68551954?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Johnson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chrisj-back2work" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/thisdotrob"><img src="https://avatars.githubusercontent.com/u/12902589?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rob Stevenson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=thisdotrob" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="www.lucas.computer"><img src="https://avatars.githubusercontent.com/u/1363056?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lucas Heymès</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lovethebomb" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=lovethebomb" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/NorfeldtAbtion"><img src="https://avatars.githubusercontent.com/u/53769763?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lasse Norfeldt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=NorfeldtAbtion" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://nyaripeter.hu/"><img src="https://avatars.githubusercontent.com/u/6048614?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Péter Nyári</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=netwarex" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=netwarex" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.holgerfrohloff.de"><img src="https://avatars.githubusercontent.com/u/84148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Holger Frohloff</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=5minpause" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/basilk76"><img src="https://avatars.githubusercontent.com/u/45275512?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Basil Khan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=basilk76" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://danestves.com/"><img src="https://avatars.githubusercontent.com/u/31737273?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Esteves</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=danestves" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="http://www.bitnative.com"><img src="https://avatars.githubusercontent.com/u/1688997?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cory House</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=coryhouse" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://auspham.dev/"><img src="https://avatars.githubusercontent.com/u/16440123?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austin (Thang Pham)</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rockmanvnx6" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://jammeryhq.com"><img src="https://avatars.githubusercontent.com/u/521777?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Marcus Reinhardt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=noxify" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=noxify" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/davidchristie"><img src="https://avatars.githubusercontent.com/u/12044333?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Christie</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=davidchristie" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/ajanth97"><img src="https://avatars.githubusercontent.com/u/50458502?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ajanth</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ajanth97" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/divpreet"><img src="https://avatars.githubusercontent.com/u/2805650?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Div</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=divpreet" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/david-arteaga"><img src="https://avatars.githubusercontent.com/u/7199015?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Arteaga</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=david-arteaga" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/MukulKolpe"><img src="https://avatars.githubusercontent.com/u/78664749?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mukul Kolpe</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=MukulKolpe" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/skotchpine"><img src="https://avatars.githubusercontent.com/u/13043909?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tyler</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=skotchpine" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/SofianeDjellouli"><img src="https://avatars.githubusercontent.com/u/38258952?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sofiane Djellouli</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=SofianeDjellouli" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/kreako"><img src="https://avatars.githubusercontent.com/u/65113001?v=4?s=100" width="100px;" alt=""/><br /><sub><b>kreako</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kreako" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://sarahdayan.dev"><img src="https://avatars.githubusercontent.com/u/5370675?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sarah Dayan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sarahdayan" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/c-ciobanu"><img src="https://avatars.githubusercontent.com/u/33382714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cristi Ciobanu</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=c-ciobanu" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://arpitdalal.dev"><img src="https://avatars.githubusercontent.com/u/61059807?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Arpit Dalal</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=arpitdalal" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/robertrisch"><img src="https://avatars.githubusercontent.com/u/73828816?v=4?s=100" width="100px;" alt=""/><br /><sub><b>robertrisch</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=robertrisch" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/saadaltabari"><img src="https://avatars.githubusercontent.com/u/29986512?v=4?s=100" width="100px;" alt=""/><br /><sub><b>saadaltabari</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=saadaltabari" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=saadaltabari" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/iojcde"><img src="https://avatars.githubusercontent.com/u/31413538?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jeeho Ahn</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=iojcde" title="Documentation">📖</a> <a href="#tool-iojcde" title="Tools">🔧</a> <a href="https://github.com/blitz-js/blitz/commits?author=iojcde" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://linkedin.com/in/ryanwashburne"><img src="https://avatars.githubusercontent.com/u/12566087?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ryan Washburne</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=ryanwashburne" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/sherryxiao1988"><img src="https://avatars.githubusercontent.com/u/1202426?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shundan Xiao</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sherryxiao1988" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/tommywong-dev"><img src="https://avatars.githubusercontent.com/u/79971095?v=4?s=100" width="100px;" alt=""/><br /><sub><b>tommywong-dev</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tommywong-dev" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/datner"><img src="https://avatars.githubusercontent.com/u/22598347?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Datner</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=datner" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=datner" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://chaiwattsw.com/"><img src="https://avatars.githubusercontent.com/u/30198386?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chaiwat Trisuwan</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=chaiwattsw" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=chaiwattsw" title="Code">💻</a></td>
|
||||
<td align="center"><a href="oltdaniel.eu"><img src="https://avatars.githubusercontent.com/u/53529846?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Oltmanns</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=oltdaniel" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=oltdaniel" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/edrickleong"><img src="https://avatars.githubusercontent.com/u/10529706?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Edrick Leong</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=edrickleong" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=edrickleong" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=edrickleong" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/siddhsuresh"><img src="https://avatars.githubusercontent.com/u/83594610?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Siddharth Suresh</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=siddhsuresh" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=siddhsuresh" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=siddhsuresh" title="Tests">⚠️</a> <a href="#maintenance-siddhsuresh" title="Maintenance">🚧</a></td>
|
||||
<td align="center"><a href="http://jins.dev"><img src="https://avatars.githubusercontent.com/u/39466936?v=4?s=100" width="100px;" alt=""/><br /><sub><b>JH.Lee</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=orionmiz" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=orionmiz" title="Tests">⚠️</a> <a href="#maintenance-orionmiz" title="Maintenance">🚧</a> <a href="https://github.com/blitz-js/blitz/commits?author=orionmiz" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/corydeppen"><img src="https://avatars.githubusercontent.com/u/313264?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cory Deppen</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=corydeppen" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/oloost"><img src="https://avatars.githubusercontent.com/u/72395941?v=4?s=100" width="100px;" alt=""/><br /><sub><b>oloost</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=oloost" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/janvennemann"><img src="https://avatars.githubusercontent.com/u/1406024?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jan Vennemann</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=janvennemann" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=janvennemann" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://kevinjones.engineer"><img src="https://avatars.githubusercontent.com/u/20748598?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Jones</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=joneskj55" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/paulm17"><img src="https://avatars.githubusercontent.com/u/387463?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=paulm17" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=paulm17" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=paulm17" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/selcukfatihsevinc"><img src="https://avatars.githubusercontent.com/u/384836?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Selçuk Fatih Sevinç</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=selcukfatihsevinc" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=selcukfatihsevinc" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/usamaster"><img src="https://avatars.githubusercontent.com/u/5255330?v=4?s=100" width="100px;" alt=""/><br /><sub><b>usamaster</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=usamaster" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="a11rew.dev"><img src="https://avatars.githubusercontent.com/u/87580113?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Glago</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=a11rew" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=a11rew" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://tobiasjordans.de"><img src="https://avatars.githubusercontent.com/u/111561?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tobias</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=tordans" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://www.linkedin.com/in/iagor-moraes/"><img src="https://avatars.githubusercontent.com/u/13892132?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Iagor Moraes</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=iagormoraes" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=iagormoraes" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://twitter.com/trensik"><img src="https://avatars.githubusercontent.com/u/18584155?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dawid Urbaniak</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Trancever" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Trancever" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jhonnymichel"><img src="https://avatars.githubusercontent.com/u/7006387?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jhonny Michel</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jhonnymichel" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=jhonnymichel" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=jhonnymichel" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="sweetliquid.me"><img src="https://avatars.githubusercontent.com/u/18693190?v=4?s=100" width="100px;" alt=""/><br /><sub><b>sweetliquid</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=sweetliquid" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/exKAZUu"><img src="https://avatars.githubusercontent.com/u/436237?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sakamoto, Kazunori</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=exKAZUu" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=exKAZUu" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/jeliasson"><img src="https://avatars.githubusercontent.com/u/865493?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johan Eliasson</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jeliasson" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/jafarlihi"><img src="https://avatars.githubusercontent.com/u/43515211?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hikmat Jafarli</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jafarlihi" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=jafarlihi" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://maotoramm.com"><img src="https://avatars.githubusercontent.com/u/5174884?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maotora ᕙ(⇀‸↼‶)ᕗ</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maotora" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=maotora" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/vitaliemiron"><img src="https://avatars.githubusercontent.com/u/45145592?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vitalie</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=vitaliemiron" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=vitaliemiron" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://estevao.org"><img src="https://avatars.githubusercontent.com/u/19409687?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nelson Estevão</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nelsonmestevao" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=nelsonmestevao" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/dbrxnds"><img src="https://avatars.githubusercontent.com/u/32268383?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=dbrxnds" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=dbrxnds" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=dbrxnds" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/gjmoed"><img src="https://avatars.githubusercontent.com/u/4458993?v=4?s=100" width="100px;" alt=""/><br /><sub><b>G.J. Moed</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gjmoed" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=gjmoed" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://ghken.com"><img src="https://avatars.githubusercontent.com/u/5304351?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tetsuya Fukuda</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=GHKEN" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=GHKEN" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nerixim"><img src="https://avatars.githubusercontent.com/u/26106502?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nikita Kamaev</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nerixim" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://webredone.com/"><img src="https://avatars.githubusercontent.com/u/11588823?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nikola Ivanov</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=nikola-wd" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="jayu.dev"><img src="https://avatars.githubusercontent.com/u/11561585?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jakub Mazurek</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=jayu" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=jayu" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/maciej-ka"><img src="https://avatars.githubusercontent.com/u/5403694?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maciej Kasprzyk</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=maciej-ka" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=maciej-ka" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/justinsmid"><img src="https://avatars.githubusercontent.com/u/34271675?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Justin Smid</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=justinsmid" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=justinsmid" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rodobre"><img src="https://avatars.githubusercontent.com/u/52138375?v=4?s=100" width="100px;" alt=""/><br /><sub><b>rodobre</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rodobre" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rodobre" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/Zamfi99"><img src="https://avatars.githubusercontent.com/u/19189337?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zamfira Costin-Andrei</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Zamfi99" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Zamfi99" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/potikhanovsergey"><img src="https://avatars.githubusercontent.com/u/71494201?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Sergey</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=potikhanovsergey" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://github.com/papsavas"><img src="https://avatars.githubusercontent.com/u/50584606?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Savvas Papageorgiadis</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=papsavas" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=papsavas" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://flow-office.eu/"><img src="https://avatars.githubusercontent.com/u/77194479?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Leonidas</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=LeonMueller-OneAndOnly" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=LeonMueller-OneAndOnly" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://hacknex.us"><img src="https://avatars.githubusercontent.com/u/19937034?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Doc0x1</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=Doc0x1" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=Doc0x1" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/lmisea"><img src="https://avatars.githubusercontent.com/u/106825636?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Luis Isea</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=lmisea" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=lmisea" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.gengjiawen.com"><img src="https://avatars.githubusercontent.com/u/3759816?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jiawen Geng</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=gengjiawen" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=gengjiawen" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://timn.tech"><img src="https://avatars.githubusercontent.com/u/6324199?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tim Neutkens</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=timneutkens" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=timneutkens" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=timneutkens" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://redyetidev.github.io"><img src="https://avatars.githubusercontent.com/u/38299977?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aviv Keller</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=RedYetiDev" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/bezalel6"><img src="https://avatars.githubusercontent.com/u/51681171?v=4?s=100" width="100px;" alt=""/><br /><sub><b>bezalel6</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=bezalel6" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=bezalel6" title="Code">💻</a></td>
|
||||
<td align="center"><a href="cherniavskii.com"><img src="https://avatars.githubusercontent.com/u/13808724?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Cherniavskii</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=cherniavskii" title="Documentation">📖</a></td>
|
||||
<td align="center"><a href="https://danielidoko-r3zt.vercel.app/"><img src="https://avatars.githubusercontent.com/u/95912955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Idoko</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Code">💻</a> <a href="https://github.com/blitz-js/blitz/commits?author=doe-base" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://garyfung.medium.com"><img src="https://avatars.githubusercontent.com/u/3803466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gary Fung</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=fungilation" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=fungilation" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/rene-demonsters"><img src="https://avatars.githubusercontent.com/u/20322259?v=4?s=100" width="100px;" alt=""/><br /><sub><b>René Vlugt</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=rene-demonsters" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=rene-demonsters" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.drupal.org/u/kksandr"><img src="https://avatars.githubusercontent.com/u/132560756?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ksandr</b></sub></a><br /><a href="https://github.com/blitz-js/blitz/commits?author=kksandr7" title="Documentation">📖</a> <a href="https://github.com/blitz-js/blitz/commits?author=kksandr7" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-restore -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blitz",
|
||||
"version": "2.0.10",
|
||||
"version": "2.2.3",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -30,8 +30,8 @@
|
||||
"blitz": "bin/blitz"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/generator": "2.0.10",
|
||||
"@mrleebo/prisma-ast": "0.2.6",
|
||||
"@blitzjs/generator": "2.2.3",
|
||||
"@mrleebo/prisma-ast": "0.4.1",
|
||||
"@types/global-agent": "2.1.1",
|
||||
"arg": "5.0.1",
|
||||
"ast-types": "0.14.2",
|
||||
@@ -80,7 +80,7 @@
|
||||
"watchpack": "2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.0.10",
|
||||
"@blitzjs/config": "2.2.3",
|
||||
"@types/cookie": "0.4.1",
|
||||
"@types/cross-spawn": "6.0.2",
|
||||
"@types/debug": "4.1.7",
|
||||
@@ -95,17 +95,17 @@
|
||||
"@types/npm-which": "3.0.1",
|
||||
"@types/progress": "2.0.5",
|
||||
"@types/prompts": "2.0.14",
|
||||
"@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/test-listen": "1.1.0",
|
||||
"@types/watchpack": "1.1.1",
|
||||
"express": "4.17.3",
|
||||
"react": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"test-listen": "1.1.0",
|
||||
"typescript": "^4.8.4",
|
||||
"unbuild": "0.7.6",
|
||||
"watch": "1.0.2",
|
||||
"zod": "3.20.2"
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -3,7 +3,8 @@ import {CliCommand} from "../index"
|
||||
import prompts from "prompts"
|
||||
import {bootstrap} from "global-agent"
|
||||
import {baseLogger, log} from "../../logging"
|
||||
const debug = require("debug")("blitz:cli")
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz:cli")
|
||||
import {join, resolve, dirname} from "path"
|
||||
import {Stream} from "stream"
|
||||
import {promisify} from "util"
|
||||
|
||||
@@ -274,7 +274,7 @@ const newApp: CliCommand = async () => {
|
||||
)
|
||||
}
|
||||
|
||||
postInstallSteps.push(`${projectPkgManger} blitz dev`)
|
||||
postInstallSteps.push(`${projectPkgManger} ${projectPkgManger === "npm" ? "run " : ""}dev`);
|
||||
|
||||
console.log("\n Your new Blitz app is ready! Next steps:")
|
||||
postInstallSteps.forEach((step, index) => {
|
||||
|
||||
@@ -4,7 +4,8 @@ import {readJSON} from "fs-extra"
|
||||
import path from "path"
|
||||
import pkgDir from "pkg-dir"
|
||||
import resolveCwd from "resolve-cwd"
|
||||
const debug = require("debug")("blitz:utils")
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz:utils")
|
||||
|
||||
export async function resolveBinAsync(pkg: string, executable = pkg) {
|
||||
const packageDir = await pkgDir(resolveCwd(pkg))
|
||||
|
||||
@@ -5,7 +5,8 @@ import path from "path"
|
||||
import * as REPL from "repl"
|
||||
import {REPLCommand, REPLServer} from "repl"
|
||||
// eslint-disable-next-line @next/next/no-assign-module-variable
|
||||
const debug = require("debug")("blitz:repl")
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz:repl")
|
||||
import ProgressBar from "progress"
|
||||
import {log} from "../../logging"
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import * as esbuild from "esbuild"
|
||||
import pkgDir from "pkg-dir"
|
||||
import type {ServerConfig} from "./config"
|
||||
|
||||
const debug = require("debug")("blitz:utils")
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz:utils")
|
||||
|
||||
export function getProjectRootSync() {
|
||||
return process.cwd()
|
||||
|
||||
@@ -5,7 +5,8 @@ import {outputFile, readdir, readFile} from "fs-extra"
|
||||
import Watchpack from "watchpack"
|
||||
import {findNodeModulesRoot} from "./find-node-modules"
|
||||
|
||||
const debug = require("debug")("blitz")
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz")
|
||||
export const CONFIG_FILE = ".blitz.config.compiled.js"
|
||||
export const NEXT_CONFIG_FILE = "next.config.js"
|
||||
export const PHASE_PRODUCTION_SERVER = "phase-production-server"
|
||||
@@ -503,12 +504,13 @@ const pascalCase = (value: string): string => {
|
||||
return val.substr(0, 1).toUpperCase() + val.substr(1)
|
||||
}
|
||||
export function parseDefaultExportName(contents: string): string | null {
|
||||
const result = contents.match(/export\s+default(?:\s+(?:const|let|class|var|function))?\s+(\w+)/)
|
||||
const result = contents.match(/export\s+default(?:\s+(const|let|class|var|function))?\s+(\w+)(?:\(([a-zA-Z_$][a-zA-Z0-9_$]*\b).*\))?/)
|
||||
if (!result) {
|
||||
return null
|
||||
}
|
||||
|
||||
return result[1] ?? null
|
||||
const [,declaration,compOrHOCName,comp] = result
|
||||
if(declaration||!comp) return compOrHOCName ?? null;
|
||||
return comp ?? null
|
||||
}
|
||||
export async function generateManifest() {
|
||||
const config = await loadConfig(process.cwd())
|
||||
|
||||
@@ -89,7 +89,10 @@ export class PaginationArgumentError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
if (isNotInUserTestEnvironment() && !globalThis._BLITZ_ERROR_CLASS_REGISTERED) {
|
||||
let _blitzErrorClassRegistered = false
|
||||
|
||||
export function registerBlitzErrorClasses() {
|
||||
if (_blitzErrorClassRegistered || !isNotInUserTestEnvironment()) return
|
||||
SuperJson.registerClass(AuthenticationError, {
|
||||
identifier: "BlitzAuthenticationError",
|
||||
allowProps: errorProps,
|
||||
@@ -125,5 +128,7 @@ if (isNotInUserTestEnvironment() && !globalThis._BLITZ_ERROR_CLASS_REGISTERED) {
|
||||
allowProps: errorProps,
|
||||
})
|
||||
|
||||
globalThis._BLITZ_ERROR_CLASS_REGISTERED = true
|
||||
_blitzErrorClassRegistered = true
|
||||
}
|
||||
|
||||
registerBlitzErrorClasses()
|
||||
|
||||
@@ -8,8 +8,10 @@ import {
|
||||
PaginationArgumentError,
|
||||
RedirectError,
|
||||
OAuthError,
|
||||
registerBlitzErrorClasses,
|
||||
} from "./errors"
|
||||
import type {EventHooks, MiddlewareHooks} from "./types"
|
||||
import React from "react"
|
||||
export {
|
||||
AuthenticationError,
|
||||
AuthorizationError,
|
||||
@@ -18,13 +20,14 @@ export {
|
||||
PaginationArgumentError,
|
||||
RedirectError,
|
||||
OAuthError,
|
||||
registerBlitzErrorClasses,
|
||||
}
|
||||
export * from "./utils/enhance-prisma"
|
||||
|
||||
export type BlitzProviderComponentType = <TProps = any>(
|
||||
component: ComponentType<TProps>,
|
||||
) => {
|
||||
(props: TProps): JSX.Element
|
||||
(props: TProps): React.JSX.Element
|
||||
displayName: string
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export * from "./utils/enhance-prisma"
|
||||
export * from "./middleware"
|
||||
export * from "./paginate"
|
||||
export * from "./logging"
|
||||
export {reduceBlitzServerPlugins} from "./plugin"
|
||||
export {reduceBlitzServerPlugins, merge, pipe} from "./plugin"
|
||||
export {findNodeModulesRoot, findNodeModulesRootSync} from "./cli/utils/find-node-modules"
|
||||
|
||||
export {startWatcher, stopWatcher} from "./cli/utils/routes-manifest"
|
||||
|
||||
@@ -99,8 +99,8 @@ const branded = (msg: string) => {
|
||||
* @param {string} msg
|
||||
*/
|
||||
const clearLine = (msg?: string) => {
|
||||
readline.clearLine(process.stdout, 0)
|
||||
readline.cursorTo(process.stdout, 0)
|
||||
readline.clearLine(process.stdout as any, 0)
|
||||
readline.cursorTo(process.stdout as any, 0)
|
||||
msg && process.stdout.write(msg)
|
||||
}
|
||||
|
||||
@@ -173,7 +173,8 @@ const box = async (mes: string, title: string) => {
|
||||
* If the DEBUG env var is set this will write to the console
|
||||
* @param str msg
|
||||
*/
|
||||
const debug = require("debug")("blitz")
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz")
|
||||
|
||||
export const log = {
|
||||
withBrand,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user