Compare commits
10 Commits
siddharth/
...
@blitzjs/c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7bb5864f3 | ||
|
|
d174c014f3 | ||
|
|
ab455acf0b | ||
|
|
bddc1d88f5 | ||
|
|
ce1a603b26 | ||
|
|
125370a1d0 | ||
|
|
39c8c0ab80 | ||
|
|
fbf5e51a78 | ||
|
|
9cda1be11b | ||
|
|
5b20ce6282 |
@@ -4114,6 +4114,26 @@
|
||||
"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,
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"access": "restricted",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": ["web", "test-*", "toolkit-*", "next13"]
|
||||
"ignore": ["web", "test-*", "toolkit-*", "@blitzjs/recipe-*"]
|
||||
}
|
||||
|
||||
@@ -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-433-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">
|
||||
@@ -762,6 +762,10 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
<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,26 @@
|
||||
# next-blitz-auth
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-blitz-auth",
|
||||
"version": "0.1.17",
|
||||
"version": "0.1.19",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"blitz:dev": "next dev",
|
||||
@@ -12,15 +12,15 @@
|
||||
"schema": "prisma/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "^4.5.0",
|
||||
"@tanstack/react-query": "4.0.10",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"flatted": "3.2.7",
|
||||
"next": "15.0.1",
|
||||
"prisma": "^4.5.0",
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"openid-client": "5.2.1",
|
||||
"prisma": "6.1.0",
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"next-auth": "4.24.7",
|
||||
"prisma": "6.1.0",
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
"schema": "./db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"@types/jest": "29.2.2",
|
||||
"@types/passport-twitter": "1.0.37",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"jest": "29.3.0",
|
||||
"jest-environment-jsdom": "29.3.0",
|
||||
"next": "15.0.1",
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@hookform/error-message": "2.0.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"delay": "5.0.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"lowdb": "2.1.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
@@ -28,7 +28,7 @@
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"blitz": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"lowdb": "2.1.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
"prisma:studio": "prisma studio"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
@@ -28,7 +28,7 @@
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"@tanstack/react-query": "4.0.10",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
"react": "19.0.0",
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
@@ -27,7 +27,7 @@
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"blitz": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"blitz": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0"
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
"schema": "db/schema.prisma"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/next": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/next": "2.2.2",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@prisma/client": "6.1.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"lowdb": "3.0.0",
|
||||
"next": "15.0.1",
|
||||
"prisma": "6.1.0",
|
||||
@@ -28,7 +28,7 @@
|
||||
"react-dom": "19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@next/bundle-analyzer": "12.0.8",
|
||||
"@types/express": "4.17.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "workspace:2.2.0",
|
||||
"@blitzjs/next": "workspace:2.2.0",
|
||||
"@blitzjs/rpc": "workspace:2.2.0",
|
||||
"@blitzjs/config": "workspace:2.2.2",
|
||||
"@blitzjs/next": "workspace:2.2.2",
|
||||
"@blitzjs/rpc": "workspace:2.2.2",
|
||||
"@tanstack/react-query": "4.13.0",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/express": "4.17.13",
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
# @blitzjs/auth
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/auth",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -50,7 +50,7 @@
|
||||
"url": "0.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "*",
|
||||
"next-auth": "*",
|
||||
"secure-password": "4.0.0"
|
||||
@@ -67,14 +67,14 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/cookie": "0.4.1",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/jsonwebtoken": "8.5.8",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"next-auth": "4.24.7",
|
||||
"react": "19.0.0",
|
||||
|
||||
@@ -466,7 +466,7 @@ export class SessionContextClass implements SessionContext {
|
||||
}
|
||||
const cookieHeaders = this._headers.get("set-cookie")
|
||||
if (response instanceof Response) {
|
||||
response.headers.set("Set-Cookie", cookieHeaders!)
|
||||
response.headers.append("Set-Cookie", cookieHeaders!)
|
||||
} else {
|
||||
response.setHeader("Set-Cookie", splitCookiesString(cookieHeaders!))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @blitzjs/next
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/next",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -29,7 +29,7 @@
|
||||
"eslint.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@blitzjs/rpc": "2.2.0",
|
||||
"@blitzjs/rpc": "2.2.2",
|
||||
"@types/hoist-non-react-statics": "3.3.1",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"debug": "4.3.3",
|
||||
@@ -39,13 +39,13 @@
|
||||
"supports-color": "8.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "*",
|
||||
"react": "*",
|
||||
"tslog": "4.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@testing-library/dom": "8.13.0",
|
||||
"@testing-library/jest-dom": "5.16.3",
|
||||
"@testing-library/react": "16.0.1",
|
||||
@@ -55,7 +55,7 @@
|
||||
"@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.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"cross-spawn": "7.0.3",
|
||||
"find-up": "4.1.0",
|
||||
"next": "15.0.1",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @blitzjs/rpc
|
||||
|
||||
## 2.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- blitz@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/rpc",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -37,18 +37,18 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/query-core": "4.24.4",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "*",
|
||||
"react": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/auth": "2.2.0",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/auth": "2.2.2",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@tanstack/query-core": "4.24.4",
|
||||
"@types/debug": "4.1.7",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# blitz
|
||||
|
||||
## 2.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @blitzjs/generator@2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5b20ce628]
|
||||
- Updated dependencies [fbf5e51a7]
|
||||
- @blitzjs/generator@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
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,7 +1,7 @@
|
||||
import {BuildConfig} from "unbuild"
|
||||
|
||||
const config: BuildConfig = {
|
||||
entries: ["./src/index-browser", "./src/index-server", "./src/cli/index"],
|
||||
entries: ["./src/index-browser", "./src/index-server", "./src/cli/index", "./src/installer"],
|
||||
externals: ["index-browser.cjs", "index-browser.mjs", "index.cjs", "zod", "react"],
|
||||
declaration: true,
|
||||
rollup: {
|
||||
|
||||
1
packages/blitz/installer.d.ts
vendored
Normal file
1
packages/blitz/installer.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./dist/installer"
|
||||
1
packages/blitz/installer.js
Normal file
1
packages/blitz/installer.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require("./dist/installer.cjs")
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "blitz",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -22,6 +22,7 @@
|
||||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"installer.*",
|
||||
"dist/**",
|
||||
"bin/**"
|
||||
],
|
||||
@@ -29,7 +30,7 @@
|
||||
"blitz": "bin/blitz"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blitzjs/generator": "2.2.0",
|
||||
"@blitzjs/generator": "2.2.2",
|
||||
"@mrleebo/prisma-ast": "0.4.1",
|
||||
"@types/global-agent": "2.1.1",
|
||||
"arg": "5.0.1",
|
||||
@@ -79,7 +80,7 @@
|
||||
"watchpack": "2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@types/cookie": "0.4.1",
|
||||
"@types/cross-spawn": "6.0.2",
|
||||
"@types/debug": "4.1.7",
|
||||
|
||||
325
packages/blitz/src/cli/commands/install.ts
Normal file
325
packages/blitz/src/cli/commands/install.ts
Normal file
@@ -0,0 +1,325 @@
|
||||
import arg from "arg"
|
||||
import {CliCommand} from "../index"
|
||||
import prompts from "prompts"
|
||||
import {bootstrap} from "global-agent"
|
||||
import {baseLogger, log} from "../../logging"
|
||||
import Debug from "debug"
|
||||
const debug = Debug("blitz:cli")
|
||||
import {join, resolve, dirname} from "path"
|
||||
import {Stream} from "stream"
|
||||
import {promisify} from "util"
|
||||
import {RecipeCLIFlags, RecipeExecutor} from "../../installer"
|
||||
import {setupTsnode} from "../utils/setup-ts-node"
|
||||
import {isInternalBlitzMonorepoDevelopment} from "../utils/helpers"
|
||||
import findUp from "find-up"
|
||||
import resolveFrom from "resolve-from"
|
||||
import {findNodeModulesRoot} from "../utils/find-node-modules"
|
||||
|
||||
interface GlobalAgent {
|
||||
HTTP_PROXY?: string
|
||||
HTTPS_PROXY?: string
|
||||
NO_PROXY?: string
|
||||
}
|
||||
|
||||
declare global {
|
||||
var GLOBAL_AGENT: GlobalAgent
|
||||
}
|
||||
|
||||
const args = arg(
|
||||
{
|
||||
// Types
|
||||
"--help": Boolean,
|
||||
"--env": String,
|
||||
"--yes": Boolean,
|
||||
|
||||
// Aliases
|
||||
"-e": "--env",
|
||||
"-y": "--yes",
|
||||
},
|
||||
{
|
||||
permissive: true,
|
||||
},
|
||||
)
|
||||
|
||||
const pipeline = promisify(Stream.pipeline)
|
||||
|
||||
const got = async (url: string) => {
|
||||
return require("got")(url).catch((e: any) => {
|
||||
if (e.response.statusCode === 403) {
|
||||
baseLogger().error(e.response.body)
|
||||
} else {
|
||||
return e
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const gotJSON = async (url: string) => {
|
||||
debug("[gotJSON] Downloading json from ", url)
|
||||
const res = await got(url)
|
||||
return JSON.parse(res.body)
|
||||
}
|
||||
|
||||
const isUrlValid = async (url: string) => {
|
||||
return (await got(url).catch((e) => e)).statusCode === 200
|
||||
}
|
||||
|
||||
const requireJSON = (file: string) => {
|
||||
return JSON.parse(require("fs-extra").readFileSync(file).toString("utf-8"))
|
||||
}
|
||||
|
||||
const checkLockFileExists = async (filename: string) => {
|
||||
const dotBlitz = join(await findNodeModulesRoot(process.cwd()), ".blitz")
|
||||
return require("fs-extra").existsSync(resolve(join(dotBlitz, "..", "..", filename)))
|
||||
}
|
||||
|
||||
const GH_ROOT = "https://github.com/"
|
||||
const API_ROOT = "https://api.github.com/repos/"
|
||||
const RAW_ROOT = "https://raw.githubusercontent.com/"
|
||||
const CODE_ROOT = "https://codeload.github.com/"
|
||||
|
||||
export enum RecipeLocation {
|
||||
Local,
|
||||
Remote,
|
||||
}
|
||||
|
||||
interface RecipeMeta {
|
||||
path: string
|
||||
subdirectory?: string
|
||||
location: RecipeLocation
|
||||
}
|
||||
|
||||
interface Tree {
|
||||
path: string
|
||||
mode: string
|
||||
type: string
|
||||
sha: string
|
||||
size: number
|
||||
url: string
|
||||
}
|
||||
|
||||
interface GithubRepoAPITrees {
|
||||
sha: string
|
||||
url: string
|
||||
tree: Tree[]
|
||||
truncated: boolean
|
||||
}
|
||||
|
||||
const getOfficialRecipeList = async (): Promise<string[]> => {
|
||||
return await gotJSON(`${API_ROOT}blitz-js/blitz/git/trees/main?recursive=1`).then(
|
||||
(release: GithubRepoAPITrees) =>
|
||||
release.tree.reduce((recipesList: string[], item) => {
|
||||
const filePath = item.path.split("/")
|
||||
const [directory, recipeName] = filePath
|
||||
if (
|
||||
directory === "recipes" &&
|
||||
filePath.length === 2 &&
|
||||
item.type === "tree" &&
|
||||
recipeName
|
||||
) {
|
||||
recipesList.push(recipeName)
|
||||
}
|
||||
return recipesList
|
||||
}, []),
|
||||
)
|
||||
}
|
||||
|
||||
const normalizeRecipePath = (recipeArg: string): RecipeMeta => {
|
||||
const isNativeRecipe = /^([\w\-_]*)$/.test(recipeArg)
|
||||
const isUrlRecipe = recipeArg.startsWith(GH_ROOT)
|
||||
const isGitHubShorthandRecipe = /^([\w-_]*)\/([\w-_]*)$/.test(recipeArg)
|
||||
if (isNativeRecipe || isUrlRecipe || isGitHubShorthandRecipe) {
|
||||
let repoUrl
|
||||
let subdirectory
|
||||
switch (true) {
|
||||
case isUrlRecipe:
|
||||
repoUrl = recipeArg
|
||||
break
|
||||
case isNativeRecipe:
|
||||
repoUrl = `${GH_ROOT}blitz-js/blitz`
|
||||
subdirectory = `recipes/${recipeArg}`
|
||||
break
|
||||
case isGitHubShorthandRecipe:
|
||||
repoUrl = `${GH_ROOT}${recipeArg}`
|
||||
break
|
||||
default:
|
||||
throw new Error(
|
||||
"should be impossible, the 3 cases are the only way to get into this switch",
|
||||
)
|
||||
}
|
||||
return {
|
||||
path: repoUrl,
|
||||
subdirectory,
|
||||
location: RecipeLocation.Remote,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
path: recipeArg,
|
||||
location: RecipeLocation.Local,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const cloneRepo = async (
|
||||
repoFullName: string,
|
||||
defaultBranch: string,
|
||||
subdirectory?: string,
|
||||
): Promise<string> => {
|
||||
debug("[cloneRepo] starting...")
|
||||
const dotBlitz = join(await findNodeModulesRoot(process.cwd()), ".blitz")
|
||||
const recipeDir = join(dotBlitz, "..", "..", "recipe-install")
|
||||
// clean up from previous run in case of error
|
||||
require("rimraf").sync(recipeDir)
|
||||
require("fs-extra").mkdirsSync(recipeDir)
|
||||
process.chdir(recipeDir)
|
||||
debug("Extracting recipe to ", recipeDir)
|
||||
|
||||
const repoName = repoFullName.split("/")[1]
|
||||
// `tar` top-level filter is `${repoName}-${defaultBranch}`, and then we want to get our recipe path
|
||||
// within that folder
|
||||
const extractPath = subdirectory ? [`${repoName}-${defaultBranch}/${subdirectory}`] : undefined
|
||||
const depth = subdirectory ? subdirectory.split("/").length + 1 : 1
|
||||
await pipeline(
|
||||
require("got").stream(`${CODE_ROOT}${repoFullName}/tar.gz/${defaultBranch}`),
|
||||
require("tar").extract({strip: depth}, extractPath),
|
||||
)
|
||||
|
||||
return recipeDir
|
||||
}
|
||||
|
||||
const installRecipeAtPath = async (
|
||||
recipePath: string,
|
||||
...runArgs: Parameters<RecipeExecutor<any>["run"]>
|
||||
) => {
|
||||
const recipe = require(recipePath).default as RecipeExecutor<any>
|
||||
|
||||
await recipe.run(...runArgs)
|
||||
}
|
||||
|
||||
const setupProxySupport = async () => {
|
||||
const httpProxy = process.env.http_proxy || process.env.HTTP_PROXY
|
||||
const httpsProxy = process.env.https_proxy || process.env.HTTPS_PROXY
|
||||
const noProxy = process.env.no_proxy || process.env.NO_PROXY
|
||||
|
||||
if (httpProxy || httpsProxy) {
|
||||
globalThis.GLOBAL_AGENT = {
|
||||
HTTP_PROXY: httpProxy,
|
||||
HTTPS_PROXY: httpsProxy,
|
||||
NO_PROXY: noProxy,
|
||||
}
|
||||
|
||||
bootstrap()
|
||||
}
|
||||
}
|
||||
|
||||
const install: CliCommand = async () => {
|
||||
setupTsnode()
|
||||
let selectedRecipe: string | null = args._[1] ? `${args._[1]}` : null
|
||||
await setupProxySupport()
|
||||
|
||||
if (!selectedRecipe) {
|
||||
const officialRecipeList = await getOfficialRecipeList()
|
||||
const res = await prompts({
|
||||
type: "select",
|
||||
name: "recipeName",
|
||||
message: "Select a recipe to install",
|
||||
choices: officialRecipeList.map((r) => {
|
||||
return {title: r, value: r}
|
||||
}),
|
||||
})
|
||||
selectedRecipe = res.recipeName
|
||||
}
|
||||
|
||||
if (selectedRecipe) {
|
||||
const recipeInfo = normalizeRecipePath(selectedRecipe)
|
||||
// Take all the args after the recipe string
|
||||
//
|
||||
// ['material-ui', '--yes', 'prop=true']
|
||||
// --> ['material-ui', 'prop=true']
|
||||
// --> ['prop=true']
|
||||
// --> { prop: 'true' }
|
||||
const cliArgs = args._.filter((arg) => !arg.startsWith("--"))
|
||||
.slice(2)
|
||||
.reduce(
|
||||
(acc, arg) => ({
|
||||
...acc,
|
||||
[`${arg.split("=")[0]}`]: arg.split("=")[1] ? JSON.parse(`"${arg.split("=")[1]}"`) : true, // if no value is provided, assume it's a boolean flag
|
||||
}),
|
||||
{},
|
||||
)
|
||||
|
||||
const cliFlags: RecipeCLIFlags = {
|
||||
yesToAll: args["--yes"] || false,
|
||||
}
|
||||
|
||||
const chalk = (await import("chalk")).default
|
||||
if (recipeInfo.location === RecipeLocation.Remote) {
|
||||
const apiUrl = recipeInfo.path.replace(GH_ROOT, API_ROOT)
|
||||
const rawUrl = recipeInfo.path.replace(GH_ROOT, RAW_ROOT)
|
||||
const repoInfo = await gotJSON(apiUrl)
|
||||
const packageJsonPath = join(
|
||||
`${rawUrl}`,
|
||||
repoInfo.default_branch,
|
||||
recipeInfo.subdirectory ?? "",
|
||||
"package.json",
|
||||
)
|
||||
|
||||
if (!(await isUrlValid(packageJsonPath))) {
|
||||
debug("Url is invalid for ", packageJsonPath)
|
||||
baseLogger().error(`Could not find recipe "${args._[1]}"\n`)
|
||||
console.log(`${chalk.bold("Please provide one of the following:")}
|
||||
|
||||
1. The name of a recipe to install (e.g. "tailwind")
|
||||
${chalk.dim("- Available recipes listed at https://github.com/blitz-js/blitz/tree/main/recipes")}
|
||||
2. The full name of a GitHub repository (e.g. "blitz-js/example-recipe"),
|
||||
3. A full URL to a Github repository (e.g. "https://github.com/blitz-js/example-recipe"), or
|
||||
4. A file path to a locally-written recipe.\n`)
|
||||
process.exit(1)
|
||||
} else {
|
||||
let spinner = log.spinner(`Cloning GitHub repository for ${selectedRecipe} recipe`).start()
|
||||
const recipeRepoPath = await cloneRepo(
|
||||
repoInfo.full_name,
|
||||
repoInfo.default_branch,
|
||||
recipeInfo.subdirectory,
|
||||
)
|
||||
spinner.stop()
|
||||
spinner = log.spinner("Installing package.json dependencies").start()
|
||||
|
||||
let pkgManager = "npm"
|
||||
let installArgs = ["install", "--legacy-peer-deps", "--ignore-scripts"]
|
||||
|
||||
if (await checkLockFileExists("yarn.lock")) {
|
||||
pkgManager = "yarn"
|
||||
installArgs = ["install", "--ignore-scripts"]
|
||||
} else if (await checkLockFileExists("pnpm-lock.yaml")) {
|
||||
pkgManager = "pnpm"
|
||||
installArgs = ["install", "--ignore-scripts"]
|
||||
}
|
||||
|
||||
await new Promise((resolve) => {
|
||||
const installProcess = require("cross-spawn")(pkgManager, installArgs)
|
||||
installProcess.on("exit", resolve)
|
||||
})
|
||||
spinner.stop()
|
||||
|
||||
const recipePackageMain = requireJSON("./package.json").main
|
||||
const recipeEntry = resolve(recipePackageMain)
|
||||
process.chdir(join(process.cwd(), ".."))
|
||||
|
||||
await installRecipeAtPath(recipeEntry, cliArgs, cliFlags)
|
||||
|
||||
require("rimraf").sync(recipeRepoPath)
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
await installRecipeAtPath(resolve(`${args._[1]}`), cliArgs, cliFlags)
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
throw new Error(err.message)
|
||||
}
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {install}
|
||||
@@ -35,6 +35,7 @@ const commands = {
|
||||
generate: () => import("./commands/generate").then((i) => i.generate),
|
||||
codegen: () => import("./commands/codegen").then((i) => i.codegen),
|
||||
db: () => import("./commands/db").then((i) => i.db),
|
||||
install: () => import("./commands/install").then((i) => i.install),
|
||||
console: () => import("./commands/console").then((i) => i.consoleREPL),
|
||||
routes: () => import("./commands/routes").then((i) => i.routes),
|
||||
}
|
||||
@@ -46,6 +47,7 @@ const aliases: Record<string, keyof typeof commands> = {
|
||||
e: "export",
|
||||
n: "new",
|
||||
g: "generate",
|
||||
i: "install",
|
||||
c: "console",
|
||||
r: "routes",
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import {Text} from "ink"
|
||||
import * as React from "react"
|
||||
import {Newline} from "./newline"
|
||||
|
||||
export const EnterToContinue: React.FC<{message?: string}> = ({
|
||||
message = "Press ENTER to continue",
|
||||
}) => (
|
||||
<>
|
||||
<Newline />
|
||||
<Text bold>{message}</Text>
|
||||
</>
|
||||
)
|
||||
6
packages/blitz/src/installer/components/newline.tsx
Normal file
6
packages/blitz/src/installer/components/newline.tsx
Normal file
@@ -0,0 +1,6 @@
|
||||
import {Box} from "ink"
|
||||
import * as React from "react"
|
||||
|
||||
export const Newline: React.FC<{count?: number}> = ({count = 1}) => {
|
||||
return <Box paddingBottom={count} />
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
import {spawn} from "cross-spawn"
|
||||
import * as fs from "fs-extra"
|
||||
import {Box, Text} from "ink"
|
||||
import Spinner from "ink-spinner"
|
||||
import * as path from "path"
|
||||
import * as React from "react"
|
||||
import {Newline} from "../components/newline"
|
||||
import {RecipeCLIArgs} from "../types"
|
||||
import {useEnterToContinue} from "../utils/use-enter-to-continue"
|
||||
import {useUserInput} from "../utils/use-user-input"
|
||||
import {IExecutor, executorArgument, ExecutorConfig, getExecutorArgument} from "./executor"
|
||||
|
||||
interface NpmPackage {
|
||||
name: string
|
||||
// defaults to latest published
|
||||
version?: string
|
||||
// defaults to false
|
||||
isDevDep?: boolean
|
||||
}
|
||||
|
||||
export interface Config extends ExecutorConfig {
|
||||
packages: executorArgument<NpmPackage[]>
|
||||
}
|
||||
|
||||
export function isAddDependencyExecutor(executor: ExecutorConfig): executor is Config {
|
||||
return (executor as Config).packages !== undefined
|
||||
}
|
||||
|
||||
export const type = "add-dependency"
|
||||
|
||||
function Package({pkg, loading}: {pkg: NpmPackage; loading: boolean}) {
|
||||
return (
|
||||
<Text>
|
||||
{` `}
|
||||
{loading ? <Spinner /> : "📦"}
|
||||
{` ${pkg.name}@${pkg.version}`}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
|
||||
const DependencyList = ({
|
||||
lede = "Hang tight! Installing dependencies...",
|
||||
depsLoading = false,
|
||||
devDepsLoading = false,
|
||||
packages,
|
||||
}: {
|
||||
lede?: string
|
||||
depsLoading?: boolean
|
||||
devDepsLoading?: boolean
|
||||
packages: NpmPackage[]
|
||||
}) => {
|
||||
const prodPackages = packages.filter((p) => !p.isDevDep)
|
||||
const devPackages = packages.filter((p) => p.isDevDep)
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>{lede}</Text>
|
||||
<Newline />
|
||||
{prodPackages.length ? <Text>Dependencies to be installed:</Text> : null}
|
||||
{prodPackages.map((pkg) => (
|
||||
<Package key={pkg.name} pkg={pkg} loading={depsLoading} />
|
||||
))}
|
||||
<Newline />
|
||||
{devPackages.length ? <Text>Dev Dependencies to be installed:</Text> : null}
|
||||
{devPackages.map((pkg) => (
|
||||
<Package key={pkg.name} pkg={pkg} loading={devDepsLoading} />
|
||||
))}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Exported for unit testing purposes
|
||||
*/
|
||||
export function getPackageManager() {
|
||||
if (fs.existsSync(path.resolve("yarn.lock"))) {
|
||||
return "yarn"
|
||||
} else if (fs.existsSync(path.resolve("pnpm-lock.yaml"))) {
|
||||
return "pnpm"
|
||||
} else {
|
||||
return "npm"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exported for unit testing purposes
|
||||
*/
|
||||
export async function installPackages(packages: NpmPackage[], isDev = false) {
|
||||
const packageManager = getPackageManager()
|
||||
const isNPM = packageManager === "npm"
|
||||
const pkgInstallArg = isNPM ? "install" : "add"
|
||||
const args: string[] = [pkgInstallArg]
|
||||
|
||||
if (isDev) {
|
||||
args.push(isNPM ? "--save-dev" : "-D")
|
||||
}
|
||||
packages.forEach((pkg) => {
|
||||
pkg.version ? args.push(`${pkg.name}@${pkg.version}`) : args.push(pkg.name)
|
||||
})
|
||||
await new Promise((resolve) => {
|
||||
const cp = spawn(packageManager, args, {
|
||||
stdio: ["inherit", "pipe", "pipe"],
|
||||
})
|
||||
cp.on("exit", resolve)
|
||||
})
|
||||
}
|
||||
|
||||
export const Commit: IExecutor["Commit"] = ({cliArgs, cliFlags, step, onChangeCommitted}) => {
|
||||
const userInput = useUserInput(cliFlags)
|
||||
const [depsInstalled, setDepsInstalled] = React.useState(false)
|
||||
const [devDepsInstalled, setDevDepsInstalled] = React.useState(false)
|
||||
|
||||
const handleChangeCommitted = React.useCallback(() => {
|
||||
const packages = (step as Config).packages
|
||||
const dependencies = packages.length === 1 ? "dependency" : "dependencies"
|
||||
onChangeCommitted(`Installed ${packages.length} ${dependencies}`)
|
||||
}, [onChangeCommitted, step])
|
||||
|
||||
React.useEffect(() => {
|
||||
async function installDeps() {
|
||||
const packagesToInstall = getExecutorArgument((step as Config).packages, cliArgs).filter(
|
||||
(p) => !p.isDevDep,
|
||||
)
|
||||
await installPackages(packagesToInstall)
|
||||
setDepsInstalled(true)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
installDeps()
|
||||
}, [cliArgs, step])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!depsInstalled) return
|
||||
async function installDevDeps() {
|
||||
const packagesToInstall = getExecutorArgument((step as Config).packages, cliArgs).filter(
|
||||
(p) => p.isDevDep,
|
||||
)
|
||||
await installPackages(packagesToInstall, true)
|
||||
setDevDepsInstalled(true)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
installDevDeps()
|
||||
}, [cliArgs, depsInstalled, step])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (depsInstalled && devDepsInstalled) {
|
||||
handleChangeCommitted()
|
||||
}
|
||||
}, [depsInstalled, devDepsInstalled, handleChangeCommitted])
|
||||
|
||||
if (!isAddDependencyExecutor(step)) {
|
||||
onChangeCommitted()
|
||||
return null
|
||||
}
|
||||
|
||||
const childProps: CommitChildProps = {
|
||||
depsInstalled,
|
||||
devDepsInstalled,
|
||||
handleChangeCommitted,
|
||||
step,
|
||||
cliArgs,
|
||||
}
|
||||
|
||||
if (userInput) return <CommitWithInput {...childProps} />
|
||||
else return <CommitWithoutInput {...childProps} />
|
||||
}
|
||||
|
||||
interface CommitChildProps {
|
||||
depsInstalled: boolean
|
||||
devDepsInstalled: boolean
|
||||
handleChangeCommitted: () => void
|
||||
step: Config
|
||||
cliArgs: RecipeCLIArgs
|
||||
}
|
||||
|
||||
const CommitWithInput = ({
|
||||
depsInstalled,
|
||||
devDepsInstalled,
|
||||
handleChangeCommitted,
|
||||
step,
|
||||
cliArgs,
|
||||
}: CommitChildProps) => {
|
||||
useEnterToContinue(handleChangeCommitted, depsInstalled && devDepsInstalled)
|
||||
|
||||
return (
|
||||
<DependencyList
|
||||
depsLoading={!depsInstalled}
|
||||
devDepsLoading={!devDepsInstalled}
|
||||
packages={getExecutorArgument(step.packages, cliArgs)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const CommitWithoutInput = ({depsInstalled, devDepsInstalled, step, cliArgs}: CommitChildProps) => (
|
||||
<DependencyList
|
||||
depsLoading={!depsInstalled}
|
||||
devDepsLoading={!devDepsInstalled}
|
||||
packages={getExecutorArgument(step.packages, cliArgs)}
|
||||
/>
|
||||
)
|
||||
71
packages/blitz/src/installer/executors/executor.tsx
Normal file
71
packages/blitz/src/installer/executors/executor.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import {Box, Text} from "ink"
|
||||
import * as React from "react"
|
||||
import {Newline} from "../components/newline"
|
||||
import {RecipeCLIArgs, RecipeCLIFlags} from "../types"
|
||||
|
||||
export interface ExecutorConfig {
|
||||
successIcon?: string
|
||||
stepId: string | number
|
||||
stepName: string
|
||||
stepType: string
|
||||
// a bit to display to the user to give context to the change
|
||||
explanation: string
|
||||
}
|
||||
|
||||
export interface IExecutor {
|
||||
type: string
|
||||
Propose?: React.FC<{
|
||||
step: ExecutorConfig
|
||||
onProposalAccepted: (data?: any) => void
|
||||
cliArgs: RecipeCLIArgs
|
||||
cliFlags: RecipeCLIFlags
|
||||
}>
|
||||
Commit: React.FC<{
|
||||
step: ExecutorConfig
|
||||
proposalData?: any
|
||||
onChangeCommitted: (data?: any) => void
|
||||
cliArgs: RecipeCLIArgs
|
||||
cliFlags: RecipeCLIFlags
|
||||
}>
|
||||
}
|
||||
|
||||
type dynamicExecutorArgument<T> = (cliArgs: RecipeCLIArgs) => T
|
||||
|
||||
function isDynamicExecutorArgument<T>(
|
||||
input: executorArgument<T>,
|
||||
): input is dynamicExecutorArgument<T> {
|
||||
return typeof (input as dynamicExecutorArgument<T>) === "function"
|
||||
}
|
||||
|
||||
export type executorArgument<T> = T | dynamicExecutorArgument<T>
|
||||
|
||||
export function Frontmatter({executor}: {executor: ExecutorConfig}) {
|
||||
const lineLength = executor.stepName.length + 6
|
||||
const verticalBorder = `+${new Array(lineLength).fill("–").join("")}+`
|
||||
return (
|
||||
<Box flexDirection="column" paddingBottom={1}>
|
||||
<Newline />
|
||||
<Box flexDirection="column">
|
||||
<Text color="#8a3df0" bold>
|
||||
{verticalBorder}
|
||||
</Text>
|
||||
<Text color="#8a3df0" bold>
|
||||
⎪ {executor.stepName} ⎪
|
||||
</Text>
|
||||
<Text color="#8a3df0" bold>
|
||||
{verticalBorder}
|
||||
</Text>
|
||||
</Box>
|
||||
<Text color="gray" italic>
|
||||
{executor.explanation}
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export function getExecutorArgument<T>(input: executorArgument<T>, cliArgs: RecipeCLIArgs): T {
|
||||
if (isDynamicExecutorArgument(input)) {
|
||||
return input(cliArgs)
|
||||
}
|
||||
return input
|
||||
}
|
||||
41
packages/blitz/src/installer/executors/file-prompt.ts
Normal file
41
packages/blitz/src/installer/executors/file-prompt.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
// import { prompt as enquirer } from 'enquirer'
|
||||
import prompts from "prompts"
|
||||
|
||||
enum SearchType {
|
||||
file,
|
||||
directory,
|
||||
}
|
||||
|
||||
interface FilePromptOptions {
|
||||
globFilter?: string
|
||||
getChoices?(context: any): string[]
|
||||
searchType?: SearchType
|
||||
context: any
|
||||
}
|
||||
|
||||
async function getMatchingFiles(filter: string = ""): Promise<string[]> {
|
||||
let {globby} = await import("globby")
|
||||
return globby(filter, {expandDirectories: true})
|
||||
}
|
||||
|
||||
export async function filePrompt(options: FilePromptOptions): Promise<string> {
|
||||
const choices = options.getChoices
|
||||
? options.getChoices(options.context)
|
||||
: await getMatchingFiles(options.globFilter)
|
||||
|
||||
if (choices.length === 1) {
|
||||
return `${choices[0]}`
|
||||
}
|
||||
|
||||
const results: {file: string} = await prompts({
|
||||
type: "autocomplete",
|
||||
name: "file",
|
||||
message: "Select the target file",
|
||||
// @ts-ignore
|
||||
limit: 10,
|
||||
choices: choices.map((choice) => {
|
||||
return {title: choice, value: choice}
|
||||
}),
|
||||
})
|
||||
return results.file
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import {createPatch} from "diff"
|
||||
import * as fs from "fs-extra"
|
||||
import {Box, Text} from "ink"
|
||||
import Spinner from "ink-spinner"
|
||||
import * as React from "react"
|
||||
import {EnterToContinue} from "../components/enter-to-continue"
|
||||
import {RecipeCLIArgs} from "../types"
|
||||
import {
|
||||
processFile,
|
||||
stringProcessFile,
|
||||
StringTransformer,
|
||||
transform,
|
||||
Transformer,
|
||||
TransformStatus,
|
||||
} from "../utils/transform"
|
||||
import {useEnterToContinue} from "../utils/use-enter-to-continue"
|
||||
import {useUserInput} from "../utils/use-user-input"
|
||||
import {IExecutor, executorArgument, ExecutorConfig, getExecutorArgument} from "./executor"
|
||||
import {filePrompt} from "./file-prompt"
|
||||
|
||||
export interface Config extends ExecutorConfig {
|
||||
selectTargetFiles?(cliArgs: RecipeCLIArgs): any[]
|
||||
singleFileSearch?: executorArgument<string>
|
||||
transform?: Transformer
|
||||
transformPlain?: StringTransformer
|
||||
}
|
||||
|
||||
export function isFileTransformExecutor(executor: ExecutorConfig): executor is Config {
|
||||
return (
|
||||
(executor as Config).transform !== undefined ||
|
||||
(executor as Config).transformPlain !== undefined
|
||||
)
|
||||
}
|
||||
|
||||
export const type = "file-transform"
|
||||
export const Propose: IExecutor["Propose"] = ({cliArgs, cliFlags, onProposalAccepted, step}) => {
|
||||
const userInput = useUserInput(cliFlags)
|
||||
const [diff, setDiff] = React.useState<string | null>(null)
|
||||
const [error, setError] = React.useState<Error | null>(null)
|
||||
const [filePath, setFilePath] = React.useState("")
|
||||
const [proposalAccepted, setProposalAccepted] = React.useState(false)
|
||||
|
||||
const acceptProposal = React.useCallback(() => {
|
||||
setProposalAccepted(true)
|
||||
onProposalAccepted(filePath)
|
||||
}, [onProposalAccepted, filePath])
|
||||
|
||||
React.useEffect(() => {
|
||||
async function generateDiff() {
|
||||
const fileToTransform: string = await filePrompt({
|
||||
context: cliArgs,
|
||||
globFilter: getExecutorArgument((step as Config).singleFileSearch, cliArgs),
|
||||
getChoices: (step as Config).selectTargetFiles,
|
||||
})
|
||||
|
||||
setFilePath(fileToTransform)
|
||||
const originalFile = fs.readFileSync(fileToTransform).toString("utf-8")
|
||||
|
||||
const newFile = await ((step as Config).transformPlain
|
||||
? stringProcessFile(originalFile, (step as Config).transformPlain!)
|
||||
: processFile(originalFile, (step as Config).transform!))
|
||||
|
||||
return createPatch(fileToTransform, originalFile, newFile)
|
||||
}
|
||||
|
||||
generateDiff().then(setDiff, setError)
|
||||
}, [cliArgs, step])
|
||||
|
||||
// Let the renderer deal with errors from file transformers, otherwise the
|
||||
// process would just hang.
|
||||
if (error) throw error
|
||||
|
||||
if (!diff) {
|
||||
return (
|
||||
<Box>
|
||||
<Text>
|
||||
<Spinner />
|
||||
Generating file diff...
|
||||
</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const childProps: ProposeChildProps = {
|
||||
diff,
|
||||
filePath,
|
||||
proposalAccepted,
|
||||
acceptProposal,
|
||||
}
|
||||
|
||||
if (userInput) return <ProposeWithInput {...childProps} />
|
||||
else return <ProposeWithoutInput {...childProps} />
|
||||
}
|
||||
|
||||
interface ProposeChildProps {
|
||||
diff: string
|
||||
filePath: string
|
||||
proposalAccepted: boolean
|
||||
acceptProposal: () => void
|
||||
}
|
||||
|
||||
const Diff = ({diff}: {diff: string}) => (
|
||||
<>
|
||||
{diff
|
||||
.split("\n")
|
||||
.slice(2)
|
||||
.map((line, idx) => {
|
||||
let styleProps: any = {}
|
||||
if (line.startsWith("-") && !line.startsWith("---")) {
|
||||
styleProps.bold = true
|
||||
styleProps.color = "red"
|
||||
} else if (line.startsWith("+") && !line.startsWith("+++")) {
|
||||
styleProps.bold = true
|
||||
styleProps.color = "green"
|
||||
}
|
||||
return (
|
||||
<Text {...styleProps} key={idx}>
|
||||
{line}
|
||||
</Text>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
|
||||
const ProposeWithInput = ({
|
||||
diff,
|
||||
filePath,
|
||||
proposalAccepted,
|
||||
acceptProposal,
|
||||
}: ProposeChildProps) => {
|
||||
useEnterToContinue(acceptProposal, filePath !== "" && !proposalAccepted)
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Diff diff={diff} />
|
||||
<EnterToContinue message="The above changes will be made. Press ENTER to continue" />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const ProposeWithoutInput = ({
|
||||
diff,
|
||||
filePath,
|
||||
proposalAccepted,
|
||||
acceptProposal,
|
||||
}: ProposeChildProps) => {
|
||||
React.useEffect(() => {
|
||||
if (filePath !== "" && !proposalAccepted) {
|
||||
acceptProposal()
|
||||
}
|
||||
}, [acceptProposal, filePath, proposalAccepted])
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Diff diff={diff} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export const Commit: IExecutor["Commit"] = ({onChangeCommitted, proposalData: filePath, step}) => {
|
||||
React.useEffect(() => {
|
||||
void (async function () {
|
||||
const results = await transform(
|
||||
async (original) =>
|
||||
await ((step as Config).transformPlain
|
||||
? stringProcessFile(original, (step as Config).transformPlain!)
|
||||
: processFile(original, (step as Config).transform!)),
|
||||
[filePath],
|
||||
)
|
||||
if (results.some((r) => r.status === TransformStatus.Failure)) {
|
||||
console.error(results)
|
||||
}
|
||||
onChangeCommitted(`Modified file: ${filePath}`)
|
||||
})()
|
||||
}, [filePath, onChangeCommitted, step])
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Spinner />
|
||||
<Text>Applying file changes</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
136
packages/blitz/src/installer/executors/new-file-executor.tsx
Normal file
136
packages/blitz/src/installer/executors/new-file-executor.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import {Generator, GeneratorOptions, SourceRootType} from "@blitzjs/generator"
|
||||
import {Box, Text} from "ink"
|
||||
import {useEffect, useState} from "react"
|
||||
import * as React from "react"
|
||||
import {EnterToContinue} from "../components/enter-to-continue"
|
||||
import {useEnterToContinue} from "../utils/use-enter-to-continue"
|
||||
import {useUserInput} from "../utils/use-user-input"
|
||||
import {IExecutor, executorArgument, ExecutorConfig, getExecutorArgument} from "./executor"
|
||||
|
||||
export interface Config extends ExecutorConfig {
|
||||
targetDirectory?: executorArgument<string>
|
||||
templatePath: executorArgument<string>
|
||||
templateValues: executorArgument<{[key: string]: string}>
|
||||
destinationPathPrompt?: executorArgument<string>
|
||||
}
|
||||
|
||||
export function isNewFileExecutor(executor: ExecutorConfig): executor is Config {
|
||||
return (executor as Config).templatePath !== undefined
|
||||
}
|
||||
|
||||
export const type = "new-file"
|
||||
|
||||
interface TempGeneratorOptions extends GeneratorOptions {
|
||||
targetDirectory?: string
|
||||
templateRoot: string
|
||||
templateValues: any
|
||||
run?: any
|
||||
}
|
||||
|
||||
class TempGenerator extends Generator<TempGeneratorOptions> {
|
||||
sourceRoot: SourceRootType
|
||||
targetDirectory: string
|
||||
templateValues: any
|
||||
returnResults = true
|
||||
|
||||
constructor(options: TempGeneratorOptions) {
|
||||
super(options)
|
||||
this.sourceRoot = {type: "absolute", path: options.templateRoot}
|
||||
this.templateValues = options.templateValues
|
||||
this.targetDirectory = options.targetDirectory || "."
|
||||
}
|
||||
|
||||
getTemplateValues() {
|
||||
return this.templateValues
|
||||
}
|
||||
|
||||
getTargetDirectory() {
|
||||
return this.targetDirectory
|
||||
}
|
||||
}
|
||||
|
||||
export const Commit: IExecutor["Commit"] = ({cliArgs, cliFlags, onChangeCommitted, step}) => {
|
||||
const userInput = useUserInput(cliFlags)
|
||||
const generatorArgs = React.useMemo(
|
||||
() => ({
|
||||
destinationRoot: ".",
|
||||
targetDirectory: getExecutorArgument((step as Config).targetDirectory, cliArgs),
|
||||
templateRoot: getExecutorArgument((step as Config).templatePath, cliArgs),
|
||||
templateValues: getExecutorArgument((step as Config).templateValues, cliArgs),
|
||||
}),
|
||||
[cliArgs, step],
|
||||
)
|
||||
const [fileCreateOutput, setFileCreateOutput] = useState("")
|
||||
const [changeCommited, setChangeCommited] = useState(false)
|
||||
const fileCreateLines = fileCreateOutput.split("\n")
|
||||
const handleChangeCommitted = React.useCallback(() => {
|
||||
setChangeCommited(true)
|
||||
onChangeCommitted(
|
||||
`Successfully created ${fileCreateLines
|
||||
.map((l) => l.split(" ").slice(1).join("").trim())
|
||||
.join(", ")}`,
|
||||
)
|
||||
}, [fileCreateLines, onChangeCommitted])
|
||||
|
||||
useEffect(() => {
|
||||
async function createNewFiles() {
|
||||
if (!fileCreateOutput) {
|
||||
const generator = new TempGenerator(generatorArgs)
|
||||
const results = (await generator.run()) as unknown as string
|
||||
setFileCreateOutput(results)
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
createNewFiles()
|
||||
}, [fileCreateOutput, generatorArgs])
|
||||
|
||||
const childProps: CommitChildProps = {
|
||||
changeCommited,
|
||||
fileCreateOutput,
|
||||
handleChangeCommitted,
|
||||
}
|
||||
|
||||
if (userInput) return <CommitWithInput {...childProps} />
|
||||
else return <CommitWithoutInput {...childProps} />
|
||||
}
|
||||
|
||||
interface CommitChildProps {
|
||||
changeCommited: boolean
|
||||
fileCreateOutput: string
|
||||
handleChangeCommitted: () => void
|
||||
}
|
||||
|
||||
const CommitWithInput = ({
|
||||
changeCommited,
|
||||
fileCreateOutput,
|
||||
handleChangeCommitted,
|
||||
}: CommitChildProps) => {
|
||||
useEnterToContinue(handleChangeCommitted, !changeCommited && fileCreateOutput !== "")
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
{fileCreateOutput !== "" && (
|
||||
<>
|
||||
<Text>{fileCreateOutput}</Text>
|
||||
<EnterToContinue />
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const CommitWithoutInput = ({
|
||||
changeCommited,
|
||||
fileCreateOutput,
|
||||
handleChangeCommitted,
|
||||
}: CommitChildProps) => {
|
||||
React.useEffect(() => {
|
||||
if (!changeCommited && fileCreateOutput !== "") {
|
||||
handleChangeCommitted()
|
||||
}
|
||||
}, [changeCommited, fileCreateOutput, handleChangeCommitted])
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">{fileCreateOutput !== "" && <Text>{fileCreateOutput}</Text>}</Box>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import {Box, Text} from "ink"
|
||||
import * as React from "react"
|
||||
import {EnterToContinue} from "../components/enter-to-continue"
|
||||
import {useEnterToContinue} from "../utils/use-enter-to-continue"
|
||||
import {useUserInput} from "../utils/use-user-input"
|
||||
import {IExecutor, executorArgument, ExecutorConfig, getExecutorArgument} from "./executor"
|
||||
|
||||
export interface Config extends ExecutorConfig {
|
||||
message: executorArgument<string>
|
||||
}
|
||||
|
||||
export const type = "print-message"
|
||||
|
||||
export const Commit: IExecutor["Commit"] = ({cliArgs, cliFlags, onChangeCommitted, step}) => {
|
||||
const userInput = useUserInput(cliFlags)
|
||||
const generatorArgs = React.useMemo(
|
||||
() => ({
|
||||
message: getExecutorArgument((step as Config).message, cliArgs),
|
||||
stepName: getExecutorArgument((step as Config).stepName, cliArgs),
|
||||
}),
|
||||
[cliArgs, step],
|
||||
)
|
||||
const [changeCommited, setChangeCommited] = React.useState(false)
|
||||
|
||||
const handleChangeCommitted = React.useCallback(() => {
|
||||
setChangeCommited(true)
|
||||
onChangeCommitted(generatorArgs.stepName)
|
||||
}, [onChangeCommitted, generatorArgs])
|
||||
|
||||
const childProps: CommitChildProps = {
|
||||
changeCommited,
|
||||
generatorArgs,
|
||||
handleChangeCommitted,
|
||||
}
|
||||
|
||||
if (userInput) return <CommitWithInput {...childProps} />
|
||||
else return <CommitWithoutInput {...childProps} />
|
||||
}
|
||||
|
||||
interface CommitChildProps {
|
||||
changeCommited: boolean
|
||||
generatorArgs: {message: string; stepName: string}
|
||||
handleChangeCommitted: () => void
|
||||
}
|
||||
|
||||
const CommitWithInput = ({
|
||||
changeCommited,
|
||||
generatorArgs,
|
||||
handleChangeCommitted,
|
||||
}: CommitChildProps) => {
|
||||
useEnterToContinue(handleChangeCommitted, !changeCommited)
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>{generatorArgs.message}</Text>
|
||||
<EnterToContinue />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const CommitWithoutInput = ({
|
||||
changeCommited,
|
||||
generatorArgs,
|
||||
handleChangeCommitted,
|
||||
}: CommitChildProps) => {
|
||||
React.useEffect(() => {
|
||||
if (!changeCommited) {
|
||||
handleChangeCommitted()
|
||||
}
|
||||
}, [changeCommited, handleChangeCommitted])
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>{generatorArgs.message}</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
136
packages/blitz/src/installer/executors/run-command-executor.tsx
Normal file
136
packages/blitz/src/installer/executors/run-command-executor.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import {spawn} from "cross-spawn"
|
||||
import {Box, Text} from "ink"
|
||||
import Spinner from "ink-spinner"
|
||||
import * as React from "react"
|
||||
import {Newline} from "../components/newline"
|
||||
import {RecipeCLIArgs} from "../types"
|
||||
import {useEnterToContinue} from "../utils/use-enter-to-continue"
|
||||
import {useUserInput} from "../utils/use-user-input"
|
||||
import {IExecutor, ExecutorConfig, getExecutorArgument} from "./executor"
|
||||
|
||||
export type CliCommand = string | [string, ...string[]]
|
||||
|
||||
export interface Config extends ExecutorConfig {
|
||||
command: CliCommand
|
||||
}
|
||||
export interface CommitChildProps {
|
||||
commandInstalled: boolean
|
||||
handleChangeCommitted: () => void
|
||||
command: CliCommand
|
||||
cliArgs: RecipeCLIArgs
|
||||
step: Config
|
||||
}
|
||||
|
||||
export const type = "run-command"
|
||||
|
||||
function Command({command, loading}: {command: CliCommand; loading: boolean}) {
|
||||
return (
|
||||
<Text>
|
||||
{` `}
|
||||
{loading ? <Spinner /> : "✅"}
|
||||
{` ${typeof command === "string" ? command : command.join(" ")}`}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
|
||||
const CommandList = ({
|
||||
lede = "Hang tight! Running...",
|
||||
commandLoading = false,
|
||||
step,
|
||||
command,
|
||||
}: {
|
||||
lede?: string
|
||||
commandLoading?: boolean
|
||||
step: Config
|
||||
command: CliCommand
|
||||
}) => {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>{lede}</Text>
|
||||
<Newline />
|
||||
<Command key={step.stepId} command={command} loading={commandLoading} />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INFO: Exported for unit testing purposes
|
||||
*
|
||||
* This function calls the defined command with their optional arguments if defined
|
||||
*
|
||||
* @param {CliCommand} input The Command and arguments
|
||||
* @return Promise<void>
|
||||
*
|
||||
* @example await executeCommand("ls")
|
||||
* @example await executeCommand(["ls"])
|
||||
* @example await executeCommand(["ls", ...["-a", "-l"]])
|
||||
*/
|
||||
export async function executeCommand(input: CliCommand): Promise<void> {
|
||||
// from https://stackoverflow.com/a/43766456/9950655
|
||||
const argsRegex =
|
||||
/("[^"\\]*(?:\\[\S\s][^"\\]*)*"|'[^'\\]*(?:\\[\S\s][^'\\]*)*'|\/[^/\\]*(?:\\[\S\s][^/\\]*)*\/[gimy]*(?=\s|$)|(?:\\\s|\S)+)/g
|
||||
const command: string[] = Array.isArray(input) ? input : input.match(argsRegex) || []
|
||||
|
||||
if (command.length === 0) {
|
||||
throw new Error(`The command is too short: \`${JSON.stringify(input)}\``)
|
||||
}
|
||||
|
||||
await new Promise((resolve) => {
|
||||
const cp = spawn(`${command[0]}`, command.slice(1), {
|
||||
stdio: ["inherit", "pipe", "pipe"],
|
||||
})
|
||||
cp.on("exit", resolve)
|
||||
cp.stdout.on("data", () => {})
|
||||
})
|
||||
}
|
||||
|
||||
export const Commit: IExecutor["Commit"] = ({cliArgs, cliFlags, step, onChangeCommitted}) => {
|
||||
const userInput = useUserInput(cliFlags)
|
||||
const [commandInstalled, setCommandInstalled] = React.useState(false)
|
||||
const executorCommand = getExecutorArgument((step as Config).command, cliArgs)
|
||||
|
||||
const handleChangeCommitted = React.useCallback(() => {
|
||||
onChangeCommitted(`Executed command ${executorCommand}`)
|
||||
}, [executorCommand, onChangeCommitted])
|
||||
|
||||
React.useEffect(() => {
|
||||
async function runCommand() {
|
||||
await executeCommand(executorCommand)
|
||||
setCommandInstalled(true)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
runCommand()
|
||||
}, [cliArgs, step, executorCommand])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (commandInstalled) {
|
||||
handleChangeCommitted()
|
||||
}
|
||||
}, [commandInstalled, handleChangeCommitted])
|
||||
|
||||
const childProps: CommitChildProps = {
|
||||
commandInstalled,
|
||||
handleChangeCommitted,
|
||||
command: executorCommand,
|
||||
cliArgs,
|
||||
step: step as Config,
|
||||
}
|
||||
|
||||
if (userInput) return <CommitWithInput {...childProps} />
|
||||
else return <CommitWithoutInput {...childProps} />
|
||||
}
|
||||
|
||||
const CommitWithInput = ({
|
||||
commandInstalled,
|
||||
handleChangeCommitted,
|
||||
command,
|
||||
step,
|
||||
}: CommitChildProps) => {
|
||||
useEnterToContinue(handleChangeCommitted, commandInstalled)
|
||||
|
||||
return <CommandList commandLoading={!commandInstalled} step={step} command={command} />
|
||||
}
|
||||
|
||||
const CommitWithoutInput = ({commandInstalled, command, step}: CommitChildProps) => (
|
||||
<CommandList commandLoading={!commandInstalled} step={step} command={command} />
|
||||
)
|
||||
12
packages/blitz/src/installer/index.ts
Normal file
12
packages/blitz/src/installer/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export * from "./recipe-executor"
|
||||
export * from "./recipe-builder"
|
||||
export * from "./executors/executor"
|
||||
export {type as AddDependencyType} from "./executors/add-dependency-executor"
|
||||
export {type as FileTransformType} from "./executors/file-transform-executor"
|
||||
export {type as NewFileType} from "./executors/new-file-executor"
|
||||
export {type as PrintMessageType} from "./executors/print-message-executor"
|
||||
|
||||
export * from "./utils/paths"
|
||||
export * from "./transforms"
|
||||
export {customTsParser} from "./utils/transform"
|
||||
export type {Program, RecipeCLIArgs, RecipeCLIFlags} from "./types"
|
||||
85
packages/blitz/src/installer/recipe-builder.ts
Normal file
85
packages/blitz/src/installer/recipe-builder.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import * as AddDependencyExecutor from "./executors/add-dependency-executor"
|
||||
import * as TransformFileExecutor from "./executors/file-transform-executor"
|
||||
import * as NewFileExecutor from "./executors/new-file-executor"
|
||||
import * as PrintMessageExecutor from "./executors/print-message-executor"
|
||||
import * as RunCommandExecutor from "./executors/run-command-executor"
|
||||
import {ExecutorConfigUnion, RecipeExecutor} from "./recipe-executor"
|
||||
import {RecipeMeta} from "./types"
|
||||
|
||||
export interface IRecipeBuilder {
|
||||
setName(name: string): IRecipeBuilder
|
||||
setDescription(description: string): IRecipeBuilder
|
||||
printMessage(
|
||||
step: Omit<Omit<PrintMessageExecutor.Config, "stepType">, "explanation">,
|
||||
): IRecipeBuilder
|
||||
setOwner(owner: string): IRecipeBuilder
|
||||
setRepoLink(repoLink: string): IRecipeBuilder
|
||||
addAddDependenciesStep(step: Omit<AddDependencyExecutor.Config, "stepType">): IRecipeBuilder
|
||||
addNewFilesStep(step: Omit<NewFileExecutor.Config, "stepType">): IRecipeBuilder
|
||||
addTransformFilesStep(step: Omit<TransformFileExecutor.Config, "stepType">): IRecipeBuilder
|
||||
addRunCommandStep(step: Omit<RunCommandExecutor.Config, "stepType">): IRecipeBuilder
|
||||
|
||||
build(): RecipeExecutor<any>
|
||||
}
|
||||
|
||||
export function RecipeBuilder(): IRecipeBuilder {
|
||||
const steps: ExecutorConfigUnion[] = []
|
||||
const meta: Partial<RecipeMeta> = {}
|
||||
|
||||
return {
|
||||
setName(name: string) {
|
||||
meta.name = name
|
||||
return this
|
||||
},
|
||||
setDescription(description: string) {
|
||||
meta.description = description
|
||||
return this
|
||||
},
|
||||
printMessage(step: Omit<PrintMessageExecutor.Config, "stepType">) {
|
||||
steps.push({
|
||||
stepType: PrintMessageExecutor.type,
|
||||
...step,
|
||||
})
|
||||
return this
|
||||
},
|
||||
setOwner(owner: string) {
|
||||
meta.owner = owner
|
||||
return this
|
||||
},
|
||||
setRepoLink(repoLink: string) {
|
||||
meta.repoLink = repoLink
|
||||
return this
|
||||
},
|
||||
addAddDependenciesStep(step: Omit<AddDependencyExecutor.Config, "stepType">) {
|
||||
steps.push({
|
||||
stepType: AddDependencyExecutor.type,
|
||||
...step,
|
||||
})
|
||||
return this
|
||||
},
|
||||
addNewFilesStep(step: Omit<NewFileExecutor.Config, "stepType">) {
|
||||
steps.push({
|
||||
stepType: NewFileExecutor.type,
|
||||
...step,
|
||||
})
|
||||
return this
|
||||
},
|
||||
addTransformFilesStep(step: Omit<TransformFileExecutor.Config, "stepType">) {
|
||||
steps.push({
|
||||
stepType: TransformFileExecutor.type,
|
||||
...step,
|
||||
})
|
||||
return this
|
||||
},
|
||||
addRunCommandStep(step: Omit<RunCommandExecutor.Config, "stepType">) {
|
||||
steps.push({
|
||||
stepType: RunCommandExecutor.type,
|
||||
...step,
|
||||
})
|
||||
return this
|
||||
},
|
||||
build() {
|
||||
return new RecipeExecutor(meta as RecipeMeta, steps)
|
||||
},
|
||||
}
|
||||
}
|
||||
50
packages/blitz/src/installer/recipe-executor.tsx
Normal file
50
packages/blitz/src/installer/recipe-executor.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import {render} from "ink"
|
||||
import {baseLogger} from "../logging"
|
||||
import React from "react"
|
||||
import * as AddDependencyExecutor from "./executors/add-dependency-executor"
|
||||
import * as FileTransformExecutor from "./executors/file-transform-executor"
|
||||
import * as NewFileExecutor from "./executors/new-file-executor"
|
||||
import * as PrintMessageExecutor from "./executors/print-message-executor"
|
||||
import {RecipeRenderer} from "./recipe-renderer"
|
||||
import {RecipeCLIArgs, RecipeCLIFlags, RecipeMeta} from "./types"
|
||||
// const debug = require('debug')("blitz:installer")
|
||||
|
||||
type ExecutorConfig =
|
||||
| AddDependencyExecutor.Config
|
||||
| FileTransformExecutor.Config
|
||||
| NewFileExecutor.Config
|
||||
| PrintMessageExecutor.Config
|
||||
|
||||
export type {ExecutorConfig as ExecutorConfigUnion}
|
||||
|
||||
export class RecipeExecutor<Options extends RecipeMeta> {
|
||||
private readonly steps: ExecutorConfig[]
|
||||
private readonly options: Options
|
||||
|
||||
constructor(options: Options, steps: ExecutorConfig[]) {
|
||||
this.options = options
|
||||
this.steps = steps
|
||||
}
|
||||
|
||||
async run(
|
||||
cliArgs: RecipeCLIArgs = {},
|
||||
cliFlags: RecipeCLIFlags = {yesToAll: false},
|
||||
): Promise<void> {
|
||||
try {
|
||||
const {waitUntilExit} = render(
|
||||
<RecipeRenderer
|
||||
cliArgs={cliArgs}
|
||||
cliFlags={cliFlags}
|
||||
steps={this.steps}
|
||||
recipeMeta={this.options}
|
||||
/>,
|
||||
{exitOnCtrlC: false},
|
||||
)
|
||||
await waitUntilExit()
|
||||
baseLogger().info(`\n🎉 The ${this.options.name} recipe has been installed!\n`)
|
||||
} catch (e) {
|
||||
baseLogger().error(e as any)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
310
packages/blitz/src/installer/recipe-renderer.tsx
Normal file
310
packages/blitz/src/installer/recipe-renderer.tsx
Normal file
@@ -0,0 +1,310 @@
|
||||
import {Box, Text, useApp, useInput} from "ink"
|
||||
import React from "react"
|
||||
import {assert} from "../index-server"
|
||||
import {EnterToContinue} from "./components/enter-to-continue"
|
||||
import {Newline} from "./components/newline"
|
||||
import * as AddDependencyExecutor from "./executors/add-dependency-executor"
|
||||
import {ExecutorConfig, Frontmatter, IExecutor} from "./executors/executor"
|
||||
import * as FileTransformExecutor from "./executors/file-transform-executor"
|
||||
import * as NewFileExecutor from "./executors/new-file-executor"
|
||||
import * as PrintMessageExecutor from "./executors/print-message-executor"
|
||||
import * as RunCommandExecutor from "./executors/run-command-executor"
|
||||
import {RecipeCLIArgs, RecipeCLIFlags, RecipeMeta} from "./types"
|
||||
import {useEnterToContinue} from "./utils/use-enter-to-continue"
|
||||
import {useUserInput} from "./utils/use-user-input"
|
||||
|
||||
enum Action {
|
||||
SkipStep,
|
||||
ProposeChange,
|
||||
ApplyChange,
|
||||
CommitApproved,
|
||||
CompleteChange,
|
||||
}
|
||||
|
||||
enum Status {
|
||||
Pending,
|
||||
Proposed,
|
||||
ReadyToCommit,
|
||||
Committing,
|
||||
Committed,
|
||||
}
|
||||
|
||||
const ExecutorMap: {[key: string]: IExecutor} = {
|
||||
[AddDependencyExecutor.type]: AddDependencyExecutor,
|
||||
[NewFileExecutor.type]: NewFileExecutor,
|
||||
[PrintMessageExecutor.type]: PrintMessageExecutor,
|
||||
[FileTransformExecutor.type]: FileTransformExecutor,
|
||||
[RunCommandExecutor.type]: RunCommandExecutor,
|
||||
} as const
|
||||
|
||||
interface State {
|
||||
steps: {
|
||||
executor: ExecutorConfig
|
||||
status: Status
|
||||
proposalData?: any
|
||||
successMsg: string
|
||||
}[]
|
||||
current: number
|
||||
}
|
||||
|
||||
function recipeReducer(state: State, action: {type: Action; data?: any}) {
|
||||
const newState = {...state}
|
||||
const step = newState.steps[newState.current]
|
||||
|
||||
switch (action.type) {
|
||||
case Action.ProposeChange:
|
||||
assert(step, "Step is empty in recipeReducer function")
|
||||
step.status = Status.Proposed
|
||||
break
|
||||
case Action.CommitApproved:
|
||||
assert(step, "Step is empty in recipeReducer function")
|
||||
step.status = Status.ReadyToCommit
|
||||
step.proposalData = action.data
|
||||
break
|
||||
case Action.ApplyChange:
|
||||
assert(step, "Step is empty in recipeReducer function")
|
||||
step.status = Status.Committing
|
||||
break
|
||||
case Action.CompleteChange:
|
||||
assert(step, "Step is empty in recipeReducer function")
|
||||
step.status = Status.Committed
|
||||
step.successMsg = action.data as string
|
||||
newState.current = Math.min(newState.current + 1, newState.steps.length - 1)
|
||||
break
|
||||
case Action.SkipStep:
|
||||
newState.current += 1
|
||||
break
|
||||
}
|
||||
|
||||
return newState
|
||||
}
|
||||
|
||||
interface RecipeProps {
|
||||
cliArgs: RecipeCLIArgs
|
||||
cliFlags: RecipeCLIFlags
|
||||
steps: ExecutorConfig[]
|
||||
recipeMeta: RecipeMeta
|
||||
}
|
||||
|
||||
const DispatchContext = React.createContext<React.Dispatch<{type: Action; data?: any}>>(() => {})
|
||||
|
||||
function WelcomeMessage({
|
||||
recipeMeta,
|
||||
enterToContinue = true,
|
||||
}: {
|
||||
recipeMeta: RecipeMeta
|
||||
enterToContinue?: boolean
|
||||
}) {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text color="#8a3df0" bold>
|
||||
Recipe: {recipeMeta.name}
|
||||
</Text>
|
||||
<Newline />
|
||||
<Text color="gray">
|
||||
<Text italic>{recipeMeta.description}</Text>
|
||||
</Text>
|
||||
<Newline />
|
||||
<Text color="gray">
|
||||
Repo: <Text italic>{recipeMeta.repoLink}</Text>
|
||||
</Text>
|
||||
<Text color="gray">
|
||||
Author: <Text italic>{recipeMeta.owner}</Text>
|
||||
</Text>
|
||||
{enterToContinue && <EnterToContinue />}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function StepMessages({state}: {state: State}) {
|
||||
const messages = state.steps
|
||||
.map((step) => ({
|
||||
msg: step.successMsg,
|
||||
icon: step.executor.successIcon ?? "✅",
|
||||
}))
|
||||
.filter((s) => s.msg)
|
||||
|
||||
return (
|
||||
<>
|
||||
{messages.map(({msg, icon}, index) => (
|
||||
<Text key={msg + index} color="green">
|
||||
{msg === "\n" ? "" : icon} {msg}
|
||||
</Text>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function StepExecutor({
|
||||
cliArgs,
|
||||
cliFlags,
|
||||
proposalData,
|
||||
step,
|
||||
status,
|
||||
}: {
|
||||
step: ExecutorConfig
|
||||
status: Status
|
||||
cliArgs: RecipeCLIArgs
|
||||
cliFlags: RecipeCLIFlags
|
||||
proposalData?: any
|
||||
}) {
|
||||
const executor = ExecutorMap[step.stepType]
|
||||
assert(executor, `Executor not found for ${step.stepType}`)
|
||||
const {Propose, Commit}: IExecutor = executor
|
||||
const dispatch = React.useContext(DispatchContext)
|
||||
|
||||
const handleProposalAccepted = React.useCallback(
|
||||
(msg: any) => {
|
||||
dispatch({type: Action.CommitApproved, data: msg})
|
||||
},
|
||||
[dispatch],
|
||||
)
|
||||
const handleChangeCommitted = React.useCallback(
|
||||
(msg: any) => {
|
||||
dispatch({type: Action.CompleteChange, data: msg})
|
||||
},
|
||||
[dispatch],
|
||||
)
|
||||
|
||||
React.useEffect(() => {
|
||||
if (status === Status.Pending) {
|
||||
dispatch({type: Action.ProposeChange})
|
||||
} else if (status === Status.ReadyToCommit) {
|
||||
dispatch({type: Action.ApplyChange})
|
||||
}
|
||||
if (status === Status.Proposed && !Propose) {
|
||||
dispatch({type: Action.CommitApproved})
|
||||
}
|
||||
}, [dispatch, status, Propose])
|
||||
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
{status !== Status.Committed ? <Frontmatter executor={step} /> : null}
|
||||
{[Status.Proposed].includes(status) && Propose ? (
|
||||
<Propose
|
||||
cliArgs={cliArgs}
|
||||
cliFlags={cliFlags}
|
||||
step={step}
|
||||
onProposalAccepted={handleProposalAccepted}
|
||||
/>
|
||||
) : null}
|
||||
{[Status.Committing].includes(status) ? (
|
||||
<Commit
|
||||
cliArgs={cliArgs}
|
||||
cliFlags={cliFlags}
|
||||
proposalData={proposalData}
|
||||
step={step}
|
||||
onChangeCommitted={handleChangeCommitted}
|
||||
/>
|
||||
) : null}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export function RecipeRenderer({cliArgs, cliFlags, steps, recipeMeta}: RecipeProps) {
|
||||
const userInput = useUserInput(cliFlags)
|
||||
const {exit} = useApp()
|
||||
const mappedSteps = steps.map((e) => ({
|
||||
executor: e,
|
||||
status: Status.Pending,
|
||||
successMsg: "",
|
||||
}))
|
||||
|
||||
if (steps.length === 0) {
|
||||
exit(new Error("This recipe has no steps"))
|
||||
}
|
||||
|
||||
const [state, dispatch] = React.useReducer(recipeReducer, {
|
||||
current: userInput ? -1 : 0,
|
||||
steps: mappedSteps,
|
||||
})
|
||||
|
||||
React.useEffect(() => {
|
||||
if (
|
||||
state.current === state.steps.length - 1 &&
|
||||
state.steps[state.current]?.status === Status.Committed
|
||||
) {
|
||||
exit()
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<DispatchContext.Provider value={dispatch}>
|
||||
{userInput ? (
|
||||
<RecipeRendererWithInput
|
||||
cliArgs={cliArgs}
|
||||
cliFlags={cliFlags}
|
||||
state={state}
|
||||
recipeMeta={recipeMeta}
|
||||
/>
|
||||
) : (
|
||||
<RecipeRendererWithoutInput
|
||||
cliArgs={cliArgs}
|
||||
cliFlags={cliFlags}
|
||||
state={state}
|
||||
recipeMeta={recipeMeta}
|
||||
/>
|
||||
)}
|
||||
</DispatchContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
function RecipeRendererWithInput({
|
||||
cliArgs,
|
||||
cliFlags,
|
||||
recipeMeta,
|
||||
state,
|
||||
}: Omit<RecipeProps, "steps"> & {state: State}) {
|
||||
const {exit} = useApp()
|
||||
const dispatch = React.useContext(DispatchContext)
|
||||
const step = state.steps[state.current]
|
||||
|
||||
useInput((input, key) => {
|
||||
if (input === "c" && key.ctrl) {
|
||||
exit(new Error("You aborted installation"))
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
useEnterToContinue(() => dispatch({type: Action.SkipStep}), state.current === -1)
|
||||
|
||||
return (
|
||||
<>
|
||||
<StepMessages state={state} />
|
||||
{state.current === -1 ? (
|
||||
<WelcomeMessage recipeMeta={recipeMeta} />
|
||||
) : step ? (
|
||||
<StepExecutor
|
||||
cliArgs={cliArgs}
|
||||
cliFlags={cliFlags}
|
||||
proposalData={state.steps[state.current]?.proposalData}
|
||||
step={step.executor}
|
||||
status={step.status}
|
||||
/>
|
||||
) : (
|
||||
new Error("Step not found in RecipeRendererWithInput")
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function RecipeRendererWithoutInput({
|
||||
cliArgs,
|
||||
cliFlags,
|
||||
recipeMeta,
|
||||
state,
|
||||
}: Omit<RecipeProps, "steps"> & {state: State}) {
|
||||
return (
|
||||
<>
|
||||
<WelcomeMessage recipeMeta={recipeMeta} enterToContinue={false} />
|
||||
<StepMessages state={state} />
|
||||
<StepExecutor
|
||||
cliArgs={cliArgs}
|
||||
cliFlags={cliFlags}
|
||||
proposalData={state.steps[state.current]?.proposalData}
|
||||
step={state.steps[state.current]?.executor as ExecutorConfig}
|
||||
status={state.steps[state.current]?.status as Status}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import type {ExpressionKind} from "ast-types/gen/kinds"
|
||||
import j from "jscodeshift"
|
||||
import {Program} from "../types"
|
||||
import {addImport} from "./add-import"
|
||||
|
||||
export const addBlitzMiddleware = (program: Program, middleware: ExpressionKind): Program => {
|
||||
const pluginArray = program.find(j.Identifier, (node) => node.name === "plugins")
|
||||
|
||||
pluginArray.get().parentPath.value.value.elements = [
|
||||
...pluginArray.get().parentPath.value.value.elements,
|
||||
j.template.expression`BlitzServerMiddleware(${middleware})`,
|
||||
]
|
||||
const blitzServerMiddleWare = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("BlitzServerMiddleware"))],
|
||||
j.literal("blitz"),
|
||||
)
|
||||
addImport(program, blitzServerMiddleWare)
|
||||
|
||||
return program
|
||||
}
|
||||
17
packages/blitz/src/installer/transforms/add-import.ts
Normal file
17
packages/blitz/src/installer/transforms/add-import.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import j from "jscodeshift"
|
||||
import {Program} from "../types"
|
||||
|
||||
export function addImport(program: Program, importToAdd: j.ImportDeclaration): Program {
|
||||
const importStatementCount = program.find(j.ImportDeclaration).length
|
||||
if (importStatementCount === 0) {
|
||||
program.find(j.Statement).at(0).insertBefore(importToAdd)
|
||||
return program
|
||||
}
|
||||
program.find<j.ImportDeclaration>(j.ImportDeclaration).forEach((stmt, idx) => {
|
||||
const node = stmt.node
|
||||
if (idx === importStatementCount - 1) {
|
||||
stmt.replace(node, importToAdd)
|
||||
}
|
||||
})
|
||||
return program
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import j from "jscodeshift"
|
||||
import {Program} from "../types"
|
||||
|
||||
export const findModuleExportsExpressions = (program: Program) =>
|
||||
program.find<j.AssignmentExpression>(j.AssignmentExpression).filter((path) => {
|
||||
const {left, right} = path.value
|
||||
|
||||
return (
|
||||
left.type === "MemberExpression" &&
|
||||
left.object.type === "Identifier" &&
|
||||
left.property.type === "Identifier" &&
|
||||
left.property.name === "exports" &&
|
||||
right.type === "ObjectExpression"
|
||||
)
|
||||
})
|
||||
9
packages/blitz/src/installer/transforms/index.ts
Normal file
9
packages/blitz/src/installer/transforms/index.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export * from "./add-import"
|
||||
export * from "./add-blitz-middleware"
|
||||
export * from "./find-module-exports-expressions"
|
||||
export * from "./prisma"
|
||||
export * from "./transform-next-config"
|
||||
export * from "./with-utilities"
|
||||
export * from "./wrap-blitz-config"
|
||||
export * from "./update-babel-config"
|
||||
export * from "./wrap-app-return-statement"
|
||||
@@ -0,0 +1,27 @@
|
||||
import {Enum} from "@mrleebo/prisma-ast"
|
||||
import {produceSchema} from "./produce-schema"
|
||||
|
||||
/**
|
||||
* Adds an enum to your schema.prisma data model.
|
||||
*
|
||||
* @param source - schema.prisma source file contents
|
||||
* @param enumProps - the enum to add
|
||||
* @returns The modified schema.prisma source
|
||||
* @example Usage
|
||||
* ```
|
||||
* addPrismaEnum(source, {
|
||||
type: "enum",
|
||||
name: "Role",
|
||||
enumerators: [
|
||||
{type: "enumerator", name: "USER"},
|
||||
{type: "enumerator", name: "ADMIN"},
|
||||
],
|
||||
})
|
||||
* ```
|
||||
*/
|
||||
export function addPrismaEnum(source: string, enumProps: Enum): Promise<string> {
|
||||
return produceSchema(source, (schema) => {
|
||||
const existing = schema.list.find((x) => x.type === "enum" && x.name === enumProps.name)
|
||||
existing ? Object.assign(existing, enumProps) : schema.list.push(enumProps)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import {Field, Model} from "@mrleebo/prisma-ast"
|
||||
import {produceSchema} from "./produce-schema"
|
||||
|
||||
/**
|
||||
* Adds a field to a model in your schema.prisma data model.
|
||||
*
|
||||
* @param source - schema.prisma source file contents
|
||||
* @param modelName - name of the model to add a field to
|
||||
* @param fieldProps - the field to add
|
||||
* @returns The modified schema.prisma source
|
||||
* @example Usage
|
||||
* ```
|
||||
* addPrismaField(source, "Project", {
|
||||
type: "field",
|
||||
name: "name",
|
||||
fieldType: "String",
|
||||
optional: false,
|
||||
attributes: [{type: "attribute", kind: "field", name: "unique"}],
|
||||
})
|
||||
* ```
|
||||
*/
|
||||
export function addPrismaField(
|
||||
source: string,
|
||||
modelName: string,
|
||||
fieldProps: Field,
|
||||
): Promise<string> {
|
||||
return produceSchema(source, (schema) => {
|
||||
const model = schema.list.find((x) => x.type === "model" && x.name === modelName) as Model
|
||||
if (!model) return
|
||||
|
||||
const existing = model.properties.find((x) => x.type === "field" && x.name === fieldProps.name)
|
||||
existing ? Object.assign(existing, fieldProps) : model.properties.push(fieldProps)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import {Generator} from "@mrleebo/prisma-ast"
|
||||
import {produceSchema} from "./produce-schema"
|
||||
|
||||
/**
|
||||
* Adds a generator to your schema.prisma data model.
|
||||
*
|
||||
* @param source - schema.prisma source file contents
|
||||
* @param generatorProps - the generator to add
|
||||
* @returns The modified schema.prisma source
|
||||
* @example Usage
|
||||
* ```
|
||||
* addPrismaGenerator(source, {
|
||||
type: "generator",
|
||||
name: "nexusPrisma",
|
||||
assignments: [{type: "assignment", key: "provider", value: '"nexus-prisma"'}],
|
||||
})
|
||||
* ```
|
||||
*/
|
||||
export function addPrismaGenerator(source: string, generatorProps: Generator): Promise<string> {
|
||||
return produceSchema(source, (schema) => {
|
||||
const existing = schema.list.find(
|
||||
(x) => x.type === "generator" && x.name === generatorProps.name,
|
||||
) as Generator
|
||||
existing ? Object.assign(existing, generatorProps) : schema.list.push(generatorProps)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import {Model, ModelAttribute} from "@mrleebo/prisma-ast"
|
||||
import {produceSchema} from "./produce-schema"
|
||||
|
||||
/**
|
||||
* Adds a field to a model in your schema.prisma data model.
|
||||
*
|
||||
* @remarks Not ready for actual use
|
||||
* @param source - schema.prisma source file contents
|
||||
* @param modelName - name of the model to add a field to
|
||||
* @param attributeProps - the model attribute (such as an index) to add
|
||||
* @returns The modified schema.prisma source
|
||||
* @example Usage
|
||||
* ```
|
||||
* addPrismaModelAttribute(source, "Project", {
|
||||
* type: "attribute",
|
||||
* kind: "model",
|
||||
* name: "index",
|
||||
* args: [{ type: "attributeArgument", value: { type: "array", args: ["name"] } }]
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function addPrismaModelAttribute(
|
||||
source: string,
|
||||
modelName: string,
|
||||
attributeProps: ModelAttribute,
|
||||
): Promise<string> {
|
||||
return produceSchema(source, (schema) => {
|
||||
const model = schema.list.find((x) => x.type === "model" && x.name === modelName) as Model
|
||||
if (!model) return
|
||||
|
||||
const existing = model.properties.find(
|
||||
(x) => x.type === "attribute" && x.name === attributeProps.name,
|
||||
)
|
||||
|
||||
existing ? Object.assign(existing, attributeProps) : model.properties.push(attributeProps)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import {Model} from "@mrleebo/prisma-ast"
|
||||
import {produceSchema} from "./produce-schema"
|
||||
|
||||
/**
|
||||
* Adds an enum to your schema.prisma data model.
|
||||
*
|
||||
* @param source - schema.prisma source file contents
|
||||
* @param modelProps - the model to add
|
||||
* @returns The modified schema.prisma source
|
||||
* @example Usage
|
||||
* ```
|
||||
* addPrismaModel(source, {
|
||||
type: "model",
|
||||
name: "Project",
|
||||
properties: [{type: "field", name: "id", fieldType: "String"}],
|
||||
})
|
||||
* ```
|
||||
*/
|
||||
export function addPrismaModel(source: string, modelProps: Model): Promise<string> {
|
||||
return produceSchema(source, (schema) => {
|
||||
const existing = schema.list.find((x) => x.type === "model" && x.name === modelProps.name)
|
||||
existing ? Object.assign(existing, modelProps) : schema.list.push(modelProps)
|
||||
})
|
||||
}
|
||||
7
packages/blitz/src/installer/transforms/prisma/index.ts
Normal file
7
packages/blitz/src/installer/transforms/prisma/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export * from "./add-prisma-enum"
|
||||
export * from "./add-prisma-field"
|
||||
export * from "./add-prisma-generator"
|
||||
export * from "./add-prisma-model-attribute"
|
||||
export * from "./add-prisma-model"
|
||||
export * from "./produce-schema"
|
||||
export * from "./set-prisma-data-source"
|
||||
@@ -0,0 +1,14 @@
|
||||
import {printSchema as printer, Schema} from "@mrleebo/prisma-ast"
|
||||
|
||||
/**
|
||||
* Takes the schema.prisma document parsed from @mrleebo/prisma-ast and
|
||||
* serializes it back to a schema.prisma source string. To ensure consistent
|
||||
* formatting and prettify the document, we also execute the
|
||||
* IntrospectionEngine from @prisma/sdk.
|
||||
*
|
||||
* @param schema - the parsed prisma schema
|
||||
* @returns the schema.prisma source string
|
||||
*/
|
||||
export function printSchema(schema: Schema): string {
|
||||
return printer(schema)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import {getSchema, printSchema, Schema} from "@mrleebo/prisma-ast"
|
||||
|
||||
/**
|
||||
* A file transformer that parses a schema.prisma string, offers you a callback
|
||||
* of the parsed document object, then takes your changes to the document and
|
||||
* writes out a new schema.prisma string with the changes applied.
|
||||
*
|
||||
* @param source - schema.prisma source file contents
|
||||
* @param producer - a callback function that can mutate the parsed data model
|
||||
* @returns The modified schema.prisma source
|
||||
*/
|
||||
export async function produceSchema(
|
||||
source: string,
|
||||
producer: (schema: Schema) => void,
|
||||
): Promise<string> {
|
||||
const schema = await getSchema(source)
|
||||
producer(schema)
|
||||
return printSchema(schema)
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import {Datasource} from "@mrleebo/prisma-ast"
|
||||
import {produceSchema} from "./produce-schema"
|
||||
|
||||
/**
|
||||
* Modify the prisma datasource metadata to use the provider and url specified.
|
||||
*
|
||||
* @param source - schema.prisma source file contents
|
||||
* @param datasourceProps - datasource object to assign to the schema
|
||||
* @returns The modified schema.prisma source
|
||||
* @example Usage
|
||||
* ```
|
||||
* setPrismaDataSource(source, {
|
||||
type: "datasource",
|
||||
name: "db",
|
||||
assignments: [
|
||||
{type: "assignment", key: "provider", value: '"postgresql"'},
|
||||
{
|
||||
type: "assignment",
|
||||
key: "url",
|
||||
value: {type: "function", name: "env", params: ['"DATABASE_URL"']},
|
||||
},
|
||||
],
|
||||
})
|
||||
* ```
|
||||
*/
|
||||
export function setPrismaDataSource(source: string, datasourceProps: Datasource): Promise<string> {
|
||||
return produceSchema(source, (schema) => {
|
||||
const existing = schema.list.find((x) => x.type === "datasource")
|
||||
existing ? Object.assign(existing, datasourceProps) : schema.list.push(datasourceProps)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import type {ExpressionKind} from "ast-types/gen/kinds"
|
||||
import j from "jscodeshift"
|
||||
import {Program} from "../types"
|
||||
|
||||
function recursiveConfigSearch(
|
||||
program: Program,
|
||||
obj: ExpressionKind,
|
||||
): j.ObjectExpression | undefined {
|
||||
// Identifier being a variable name
|
||||
if (obj.type === "Identifier") {
|
||||
const {node} = j(obj).get()
|
||||
|
||||
// Get the definition of the variable
|
||||
const identifier: j.ASTPath<j.VariableDeclarator> = program
|
||||
.find(j.VariableDeclarator, {
|
||||
id: {name: node.name},
|
||||
})
|
||||
.get()
|
||||
|
||||
// Return what is after the `=`
|
||||
return identifier.value.init ? recursiveConfigSearch(program, identifier.value.init) : undefined
|
||||
} else if (obj.type === "CallExpression") {
|
||||
// If it's an function call (like `withBundleAnalyzer`), get the first argument
|
||||
if (obj.arguments.length === 0) {
|
||||
// If it has no arguments, create an empty object: `{}`
|
||||
let config = j.objectExpression([])
|
||||
obj.arguments.push(config)
|
||||
return config
|
||||
} else {
|
||||
const arg = obj.arguments[0]
|
||||
if (arg) {
|
||||
if (arg.type === "SpreadElement") return undefined
|
||||
else return recursiveConfigSearch(program, arg)
|
||||
}
|
||||
}
|
||||
} else if (obj.type === "ObjectExpression") {
|
||||
// If it's an object, return it
|
||||
return obj
|
||||
} else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export type TransformBlitzConfigCallback = (config: j.ObjectExpression) => j.ObjectExpression
|
||||
|
||||
export function transformBlitzConfig(
|
||||
program: Program,
|
||||
transform: TransformBlitzConfigCallback,
|
||||
): Program {
|
||||
let moduleExportsExpressions = program.find(j.AssignmentExpression, {
|
||||
operator: "=",
|
||||
left: {object: {name: "module"}, property: {name: "exports"}},
|
||||
right: {},
|
||||
})
|
||||
|
||||
// If there isn't any `module.exports = ...`, create one
|
||||
if (moduleExportsExpressions.length === 0) {
|
||||
let config = j.objectExpression([])
|
||||
|
||||
config = transform(config)
|
||||
|
||||
let moduleExportExpression = j.expressionStatement(
|
||||
j.assignmentExpression(
|
||||
"=",
|
||||
j.memberExpression(j.identifier("module"), j.identifier("exports")),
|
||||
config,
|
||||
),
|
||||
)
|
||||
|
||||
program.get().node.program.body.push(moduleExportExpression)
|
||||
} else if (moduleExportsExpressions.length === 1) {
|
||||
let moduleExportsExpression: j.ASTPath<j.AssignmentExpression> = moduleExportsExpressions.get()
|
||||
|
||||
let config: j.ObjectExpression | undefined = recursiveConfigSearch(
|
||||
program,
|
||||
moduleExportsExpression.value.right,
|
||||
)
|
||||
|
||||
if (config) {
|
||||
config = transform(config)
|
||||
} else {
|
||||
console.warn(
|
||||
"The configuration couldn't be found, but there is a 'module.exports' inside `blitz.config.js`",
|
||||
)
|
||||
}
|
||||
} else {
|
||||
console.warn("There are multiple 'module.exports' inside 'blitz.config.js'")
|
||||
}
|
||||
|
||||
return program
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import j from "jscodeshift"
|
||||
import {assert} from "../../index-server"
|
||||
import {Program} from "../types"
|
||||
|
||||
export function transformNextConfig(program: Program): {
|
||||
program: Program
|
||||
configObj: []
|
||||
pushToConfig: (property: j.ObjectProperty) => void
|
||||
wrapConfig: (func: string | j.CallExpression) => {
|
||||
withBlitz: j.Identifier | j.CallExpression
|
||||
}
|
||||
addRequireStatement: (identifier: string, packageName: string) => void
|
||||
} {
|
||||
const configObj = program
|
||||
.find<j.VariableDeclarator>(j.VariableDeclarator, (filter) => filter.id.name === "config")
|
||||
.get().parentPath.value[0].init.properties
|
||||
|
||||
assert(configObj, "Config object not found")
|
||||
|
||||
const pushToConfig = (property: j.ObjectProperty) => {
|
||||
configObj.push(property)
|
||||
}
|
||||
|
||||
const wrapConfig = (
|
||||
func: string | j.CallExpression,
|
||||
): {
|
||||
withBlitz: j.Identifier | j.CallExpression
|
||||
} => {
|
||||
const withBlitz = program
|
||||
.find(j.CallExpression, (filter) => filter.callee.name === "withBlitz")
|
||||
.get().value.arguments
|
||||
|
||||
assert(withBlitz, "withBlitz wrapper not found")
|
||||
|
||||
if (typeof func === "string") {
|
||||
withBlitz.push(j.template.expression`${func}(${withBlitz})`)
|
||||
withBlitz.splice(0, 1)
|
||||
} else {
|
||||
withBlitz.push(func)
|
||||
withBlitz.splice(0, 1)
|
||||
}
|
||||
|
||||
return {
|
||||
withBlitz,
|
||||
}
|
||||
}
|
||||
|
||||
const addRequireStatement = (identifier: string, packageName: string) => {
|
||||
program
|
||||
.get()
|
||||
.value.program.body.unshift(
|
||||
j.expressionStatement(
|
||||
j.assignmentExpression(
|
||||
"=",
|
||||
j.identifier(identifier),
|
||||
j.callExpression(j.identifier("require"), [j.identifier(`"${packageName}"`)]),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
program,
|
||||
configObj,
|
||||
pushToConfig,
|
||||
wrapConfig,
|
||||
addRequireStatement,
|
||||
}
|
||||
}
|
||||
113
packages/blitz/src/installer/transforms/update-babel-config.ts
Normal file
113
packages/blitz/src/installer/transforms/update-babel-config.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import type {ExpressionKind} from "ast-types/gen/kinds"
|
||||
import {namedTypes} from "ast-types"
|
||||
import j, {ASTPath} from "jscodeshift"
|
||||
import {JsonObject, JsonValue} from "../types"
|
||||
import {Program} from "../types"
|
||||
import {findModuleExportsExpressions} from "./find-module-exports-expressions"
|
||||
|
||||
type AddBabelItemDefinition = string | [name: string, options: JsonObject]
|
||||
|
||||
const jsonValueToExpression = (value: JsonValue): ExpressionKind =>
|
||||
typeof value === "string"
|
||||
? j.stringLiteral(value)
|
||||
: typeof value === "number"
|
||||
? j.numericLiteral(value)
|
||||
: typeof value === "boolean"
|
||||
? j.booleanLiteral(value)
|
||||
: value === null
|
||||
? j.nullLiteral()
|
||||
: Array.isArray(value)
|
||||
? j.arrayExpression(value.map(jsonValueToExpression))
|
||||
: j.objectExpression(
|
||||
Object.entries(value)
|
||||
.filter((entry): entry is [string, JsonValue] => entry[1] !== undefined)
|
||||
.map(([key, value]) =>
|
||||
j.objectProperty(j.stringLiteral(key), jsonValueToExpression(value)),
|
||||
),
|
||||
)
|
||||
|
||||
function updateBabelConfig(program: Program, item: AddBabelItemDefinition, key: string): Program {
|
||||
findModuleExportsExpressions(program).forEach((moduleExportsExpression) => {
|
||||
const foundExpression: Program = j(moduleExportsExpression)
|
||||
foundExpression
|
||||
.find<j.ObjectProperty>(j.ObjectProperty, {key: {name: key}})
|
||||
.forEach((items) => {
|
||||
// Don't add it again if it already exists,
|
||||
// that what this code does. For simplicity,
|
||||
// all the examples will be with key = 'presets'
|
||||
|
||||
const itemName = Array.isArray(item) ? item[0] : item
|
||||
|
||||
if (items.node.value.type === "Literal" || items.node.value.type === "StringLiteral") {
|
||||
// {
|
||||
// presets: "this-preset"
|
||||
// }
|
||||
if (itemName !== items.node.value.value) {
|
||||
items.node.value = j.arrayExpression([items.node.value, jsonValueToExpression(item)])
|
||||
}
|
||||
} else if (items.node.value.type === "ArrayExpression") {
|
||||
// {
|
||||
// presets: ["this-preset", "maybe-another", ...]
|
||||
// }
|
||||
// Here, it will return if it find the preset inside the
|
||||
// array, so the last line doesn't push a duplicated preset
|
||||
for (const [i, element] of items.node.value.elements.entries()) {
|
||||
if (!element) continue
|
||||
|
||||
if (element.type === "Literal" || element.type === "StringLiteral") {
|
||||
// {
|
||||
// presets: [..., "this-preset", ...]
|
||||
// }
|
||||
if (element.value === itemName) return
|
||||
} else if (element.type === "ArrayExpression") {
|
||||
// {
|
||||
// presets: [..., ["this-preset"], ...]
|
||||
// }
|
||||
if (
|
||||
(element.elements[0]?.type === "Literal" ||
|
||||
element.elements[0]?.type === "StringLiteral") &&
|
||||
element.elements[0].value === itemName
|
||||
) {
|
||||
if (
|
||||
element.elements[1]?.type === "ObjectExpression" &&
|
||||
element.elements[1].properties.length > 0
|
||||
) {
|
||||
// The preset has a config.
|
||||
// ["this-preset", {...}]
|
||||
if (Array.isArray(item)) {
|
||||
// If it has an adittional config, add the new keys
|
||||
// (don't matter if they already exists, let the user handle it later by themself)
|
||||
let obj = element.elements[1]
|
||||
|
||||
for (const key in item[1]) {
|
||||
const value = item[1][key]
|
||||
if (value === undefined) continue
|
||||
obj.properties.push(
|
||||
j.objectProperty(j.stringLiteral(key), jsonValueToExpression(value)),
|
||||
)
|
||||
}
|
||||
|
||||
items.node.value.elements[i] = obj
|
||||
}
|
||||
} else {
|
||||
// The preset has no config.
|
||||
// Its ["this-preset"]
|
||||
items.node.value.elements[i] = jsonValueToExpression(item)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
items.node.value.elements.push(jsonValueToExpression(item))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
export const addBabelPreset = (program: Program, preset: AddBabelItemDefinition): Program =>
|
||||
updateBabelConfig(program, preset, "presets")
|
||||
export const addBabelPlugin = (program: Program, plugin: AddBabelItemDefinition): Program =>
|
||||
updateBabelConfig(program, plugin, "plugins")
|
||||
20
packages/blitz/src/installer/transforms/with-utilities.ts
Normal file
20
packages/blitz/src/installer/transforms/with-utilities.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import {CommentKind, TypeAnnotationKind, TSTypeAnnotationKind} from "ast-types/gen/kinds"
|
||||
import j from "jscodeshift"
|
||||
|
||||
export function withComments<
|
||||
Node extends {
|
||||
comments?: CommentKind[] | null
|
||||
},
|
||||
>(node: Node, comments: CommentKind[]): Node {
|
||||
node.comments = comments
|
||||
return node
|
||||
}
|
||||
|
||||
export function withTypeAnnotation<
|
||||
Node extends {
|
||||
typeAnnotation?: TypeAnnotationKind | TSTypeAnnotationKind | null
|
||||
},
|
||||
>(node: Node, type: Parameters<typeof j.tsTypeAnnotation>[0]): Node {
|
||||
node.typeAnnotation = j.tsTypeAnnotation(type)
|
||||
return node
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import {NodePath} from "ast-types/lib/node-path"
|
||||
import j, {JSXAttribute} from "jscodeshift"
|
||||
import {assert} from "../../index-server"
|
||||
import {Program} from "../types"
|
||||
|
||||
export function wrapAppWithProvider(
|
||||
program: Program,
|
||||
element: string,
|
||||
attributes?: string[],
|
||||
): Program {
|
||||
const findMyApp = program.find(j.FunctionDeclaration, (node) => node.id.name === "MyApp")
|
||||
assert(findMyApp.length, "MyApp function not found")
|
||||
|
||||
findMyApp.forEach((path: NodePath) => {
|
||||
const statement = path.value.body.body.filter(
|
||||
(b: j.ReturnStatement) => b.type === "ReturnStatement",
|
||||
)[0]
|
||||
const argument = statement.argument
|
||||
|
||||
let attrs: JSXAttribute[] = []
|
||||
if (attributes) {
|
||||
attrs = attributes.map((i) => j.jsxAttribute(j.jsxIdentifier(i)))
|
||||
}
|
||||
|
||||
statement.argument = j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier(element), attrs),
|
||||
j.jsxClosingElement(j.jsxIdentifier(element)),
|
||||
[j.jsxText("\n"), argument, j.jsxText("\n")],
|
||||
)
|
||||
})
|
||||
|
||||
return program
|
||||
}
|
||||
33
packages/blitz/src/installer/transforms/wrap-blitz-config.ts
Normal file
33
packages/blitz/src/installer/transforms/wrap-blitz-config.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import j from "jscodeshift"
|
||||
import {Program} from "../types"
|
||||
|
||||
export function wrapBlitzConfig(program: Program, functionName: string): Program {
|
||||
let moduleExportsExpressions = program.find(j.AssignmentExpression, {
|
||||
operator: "=",
|
||||
left: {object: {name: "module"}, property: {name: "exports"}},
|
||||
right: {},
|
||||
})
|
||||
|
||||
// If there isn't any `module.exports = ...`, create one
|
||||
if (moduleExportsExpressions.length === 0) {
|
||||
let moduleExportExpression = j.expressionStatement(
|
||||
j.assignmentExpression(
|
||||
"=",
|
||||
j.memberExpression(j.identifier("module"), j.identifier("exports")),
|
||||
j.callExpression(j.identifier(functionName), [j.objectExpression([])]),
|
||||
),
|
||||
)
|
||||
|
||||
program.get().node.program.body.push(moduleExportExpression)
|
||||
} else if (moduleExportsExpressions.length === 1) {
|
||||
let moduleExportsExpression: j.ASTPath<j.AssignmentExpression> = moduleExportsExpressions.get()
|
||||
|
||||
moduleExportsExpression.value.right = j.callExpression(j.identifier(functionName), [
|
||||
moduleExportsExpression.value.right,
|
||||
])
|
||||
} else {
|
||||
console.warn("There are multiple 'module.exports' inside 'blitz.config.js'")
|
||||
}
|
||||
|
||||
return program
|
||||
}
|
||||
41
packages/blitz/src/installer/types.ts
Normal file
41
packages/blitz/src/installer/types.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type * as j from "jscodeshift"
|
||||
|
||||
export interface RecipeMeta {
|
||||
name: string
|
||||
description: string
|
||||
owner: string
|
||||
repoLink: string
|
||||
}
|
||||
|
||||
export type RecipeCLIArgs = {[Key in string]?: string | true}
|
||||
|
||||
export interface RecipeCLIFlags {
|
||||
yesToAll: boolean
|
||||
}
|
||||
|
||||
export type Program = j.Collection<j.Program>
|
||||
|
||||
/**
|
||||
Matches a JSON object.
|
||||
This type can be useful to enforce some input to be JSON-compatible or as a super-type to be extended from. Don't use this as a direct return type as the user would have to double-cast it: `jsonObject as unknown as CustomResponse`. Instead, you could extend your CustomResponse type from it to ensure your type only uses JSON-compatible types: `interface CustomResponse extends JsonObject { … }`.
|
||||
@see https://github.com/sindresorhus/type-fest
|
||||
*/
|
||||
export type JsonObject = {[Key in string]?: JsonValue}
|
||||
|
||||
/**
|
||||
Matches a JSON array.
|
||||
@see https://github.com/sindresorhus/type-fest
|
||||
*/
|
||||
export type JsonArray = JsonValue[]
|
||||
|
||||
/**
|
||||
Matches any valid JSON primitive value.
|
||||
@see https://github.com/sindresorhus/type-fest
|
||||
*/
|
||||
export type JsonPrimitive = string | number | boolean | null
|
||||
|
||||
/**
|
||||
Matches any valid JSON value.
|
||||
@see https://github.com/sindresorhus/type-fest
|
||||
*/
|
||||
export type JsonValue = JsonPrimitive | JsonObject | JsonArray
|
||||
77
packages/blitz/src/installer/utils/paths.ts
Normal file
77
packages/blitz/src/installer/utils/paths.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import * as fs from "fs-extra"
|
||||
import * as path from "path"
|
||||
|
||||
function ext(jsx = false) {
|
||||
return fs.existsSync(path.resolve("tsconfig.json")) ? (jsx ? ".tsx" : ".ts") : ".js"
|
||||
}
|
||||
|
||||
function getBlitzPath(type: string) {
|
||||
const appPath = `app/blitz-${type}${ext(false)}`
|
||||
const srcPath = `src/blitz-${type}${ext(false)}`
|
||||
const appDir = fs.existsSync(path.resolve(appPath))
|
||||
const srcDir = fs.existsSync(path.resolve(srcPath))
|
||||
|
||||
if (appDir) {
|
||||
return appPath
|
||||
} else if (srcDir) {
|
||||
return srcPath
|
||||
}
|
||||
}
|
||||
|
||||
function getAppSourceDir() {
|
||||
const srcPath = "src/pages"
|
||||
const srcDir = fs.existsSync(path.resolve(srcPath))
|
||||
|
||||
if (srcDir) {
|
||||
return "src"
|
||||
} else {
|
||||
return "app"
|
||||
}
|
||||
}
|
||||
|
||||
function findPageDir() {
|
||||
const srcPagePath = `src/pages`
|
||||
const srcPage = getAppSourceDir()
|
||||
|
||||
switch (srcPage) {
|
||||
case "src": {
|
||||
return srcPagePath
|
||||
}
|
||||
default: {
|
||||
return `pages`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const paths = {
|
||||
document() {
|
||||
return `${findPageDir()}/_document${ext(true)}`
|
||||
},
|
||||
app() {
|
||||
return `${findPageDir()}/_app${ext(true)}`
|
||||
},
|
||||
appSrcDirectory() {
|
||||
return getAppSourceDir()
|
||||
},
|
||||
blitzServer() {
|
||||
return getBlitzPath("server")
|
||||
},
|
||||
blitzClient() {
|
||||
return getBlitzPath("client")
|
||||
},
|
||||
entry() {
|
||||
return `${findPageDir()}/index${ext(true)}`
|
||||
},
|
||||
nextConfig() {
|
||||
return `next.config.js`
|
||||
},
|
||||
babelConfig() {
|
||||
return `babel.config.js`
|
||||
},
|
||||
packageJson() {
|
||||
return "package.json"
|
||||
},
|
||||
prismaSchema() {
|
||||
return "db/schema.prisma"
|
||||
},
|
||||
}
|
||||
73
packages/blitz/src/installer/utils/transform.ts
Normal file
73
packages/blitz/src/installer/utils/transform.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import * as fs from "fs-extra"
|
||||
import j from "jscodeshift"
|
||||
import getBabelOptions, {Overrides} from "recast/parsers/_babel_options"
|
||||
import * as babel from "recast/parsers/babel"
|
||||
import {Program} from "../types"
|
||||
|
||||
export const customTsParser: {} = {
|
||||
parse(source: string, options?: Overrides) {
|
||||
const babelOptions = getBabelOptions(options)
|
||||
babelOptions.plugins.push("typescript")
|
||||
babelOptions.plugins.push("jsx")
|
||||
|
||||
return babel.parser.parse(source, babelOptions)
|
||||
},
|
||||
}
|
||||
|
||||
export enum TransformStatus {
|
||||
Success = "success",
|
||||
Failure = "failure",
|
||||
}
|
||||
export interface TransformResult {
|
||||
status: TransformStatus
|
||||
filename: string
|
||||
error?: Error
|
||||
}
|
||||
|
||||
export type StringTransformer = (program: string) => string | Promise<string>
|
||||
export type Transformer = (program: Program) => Program | Promise<Program>
|
||||
|
||||
export function stringProcessFile(
|
||||
original: string,
|
||||
transformerFn: StringTransformer,
|
||||
): string | Promise<string> {
|
||||
return transformerFn(original)
|
||||
}
|
||||
|
||||
export async function processFile(original: string, transformerFn: Transformer): Promise<string> {
|
||||
const program = j(original, {parser: customTsParser})
|
||||
return (await transformerFn(program)).toSource()
|
||||
}
|
||||
|
||||
export async function transform(
|
||||
processFile: (original: string) => Promise<string>,
|
||||
targetFilePaths: string[],
|
||||
): Promise<TransformResult[]> {
|
||||
const results: TransformResult[] = []
|
||||
for (const filePath of targetFilePaths) {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
results.push({
|
||||
status: TransformStatus.Failure,
|
||||
filename: filePath,
|
||||
error: new Error(`Error: ${filePath} not found`),
|
||||
})
|
||||
}
|
||||
try {
|
||||
const fileBuffer = fs.readFileSync(filePath)
|
||||
const fileSource = fileBuffer.toString("utf-8")
|
||||
const transformedCode = await processFile(fileSource)
|
||||
fs.writeFileSync(filePath, transformedCode)
|
||||
results.push({
|
||||
status: TransformStatus.Success,
|
||||
filename: filePath,
|
||||
})
|
||||
} catch (err) {
|
||||
results.push({
|
||||
status: TransformStatus.Failure,
|
||||
filename: filePath,
|
||||
error: err as any,
|
||||
})
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import {useInput} from "ink"
|
||||
|
||||
export function useEnterToContinue(cb: Function, additionalCondition: boolean = true) {
|
||||
useInput((_input, key) => {
|
||||
if (additionalCondition && key.return) {
|
||||
cb()
|
||||
}
|
||||
})
|
||||
}
|
||||
7
packages/blitz/src/installer/utils/use-user-input.ts
Normal file
7
packages/blitz/src/installer/utils/use-user-input.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import {useStdin} from "ink"
|
||||
import {RecipeCLIFlags} from "../types"
|
||||
|
||||
export function useUserInput(cliFlags: RecipeCLIFlags) {
|
||||
const {isRawModeSupported} = useStdin()
|
||||
return isRawModeSupported && !cliFlags.yesToAll
|
||||
}
|
||||
@@ -1,5 +1,21 @@
|
||||
# @blitzjs/codemod
|
||||
|
||||
## 2.2.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- @blitzjs/generator@2.2.2
|
||||
- blitz@2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [5b20ce628]
|
||||
- Updated dependencies [fbf5e51a7]
|
||||
- @blitzjs/generator@2.2.1
|
||||
- blitz@2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/codemod",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"scripts": {
|
||||
"build": "unbuild",
|
||||
"dev": "watch unbuild src --wait=0.2",
|
||||
@@ -25,9 +25,9 @@
|
||||
"@babel/plugin-proposal-class-properties": "7.17.12",
|
||||
"@babel/plugin-syntax-jsx": "7.17.12",
|
||||
"@babel/plugin-syntax-typescript": "7.17.12",
|
||||
"@blitzjs/generator": "2.2.0",
|
||||
"@blitzjs/generator": "2.2.2",
|
||||
"arg": "5.0.1",
|
||||
"blitz": "2.2.0",
|
||||
"blitz": "2.2.2",
|
||||
"chalk": "^4.1.0",
|
||||
"cross-spawn": "7.0.3",
|
||||
"debug": "4.3.3",
|
||||
@@ -38,7 +38,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "7.12.10",
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@types/jscodeshift": "0.11.2",
|
||||
"@types/node": "18.11.9",
|
||||
"ast-types": "0.14.2",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# @blitzjs/config
|
||||
|
||||
## 2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
## 2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@blitzjs/config",
|
||||
"private": true,
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# @blitzjs/generator
|
||||
|
||||
## 2.2.2
|
||||
|
||||
## 2.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 5b20ce628: Fixes Error: Cannot find module when running blitz new and selecting the minimal pages router option
|
||||
- fbf5e51a7: chore: update next and react versions in new template using next.js app directory
|
||||
|
||||
## 2.2.0
|
||||
|
||||
## 2.1.4
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@blitzjs/generator",
|
||||
"version": "2.2.0",
|
||||
"version": "2.2.2",
|
||||
"homepage": "https://blitzjs.com/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -54,7 +54,7 @@
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@juanm04/cpx": "2.0.1",
|
||||
"@types/babel__core": "7.1.19",
|
||||
"@types/diff": "5.0.2",
|
||||
|
||||
@@ -31,10 +31,10 @@
|
||||
"@prisma/client": "5.4.2",
|
||||
"blitz": "latest",
|
||||
"formik": "2.4.5",
|
||||
"next": "14.2.15",
|
||||
"next": "15.0.1",
|
||||
"prisma": "5.4.2",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"secure-password": "4.0.0",
|
||||
"zod": "3.23.8"
|
||||
},
|
||||
@@ -44,7 +44,7 @@
|
||||
"@testing-library/react": "16.0.1",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/preview-email": "2.0.1",
|
||||
"@types/react": "18.0.25",
|
||||
"@types/react": "19.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.42.1",
|
||||
"@vitejs/plugin-react": "2.2.0",
|
||||
"ajv": "^7.0.0",
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"dependencies": {
|
||||
"@blitzjs/next": "latest",
|
||||
"blitz": "latest",
|
||||
"next": "13.4.5",
|
||||
"next": "15.0.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"ts-node": "10.9.1"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"dependencies": {
|
||||
"@blitzjs/next": "latest",
|
||||
"blitz": "latest",
|
||||
"next": "13.4.5",
|
||||
"next": "15.0.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"ts-node": "10.9.1"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"@typescript-eslint/parser": "5.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/config": "2.2.0",
|
||||
"@blitzjs/config": "2.2.2",
|
||||
"@types/react": "npm:types-react@19.0.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0",
|
||||
"react": "19.0.0",
|
||||
|
||||
1824
pnpm-lock.yaml
generated
1824
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
25
recipes/base-web/CHANGELOG.md
Normal file
25
recipes/base-web/CHANGELOG.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# @blitzjs/recipe-base-web
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1476a577]
|
||||
- blitz@2.0.0-beta.11
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9db6c885]
|
||||
- Updated dependencies [d98e4bac]
|
||||
- Updated dependencies [9fe0cc54]
|
||||
- Updated dependencies [af58e2b2]
|
||||
- Updated dependencies [2ade7268]
|
||||
- Updated dependencies [0edeaa37]
|
||||
- Updated dependencies [430f6ec7]
|
||||
- Updated dependencies [15d22af2]
|
||||
- Updated dependencies [aa34661f]
|
||||
- Updated dependencies [8e0c9d76]
|
||||
- Updated dependencies [e2c18895]
|
||||
- blitz@2.0.0-beta.5
|
||||
12
recipes/base-web/README.md
Normal file
12
recipes/base-web/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## base-web
|
||||
|
||||
The Blitz Recipe for installing Base Web
|
||||
|
||||
## more information
|
||||
|
||||
- [Base Web Homepage](https://baseweb.design/)
|
||||
- [Github page](https://github.com/uber/baseweb)
|
||||
|
||||
## contributors
|
||||
|
||||
- Konrad Kalemba <konrad@kale.mba>
|
||||
355
recipes/base-web/index.ts
Normal file
355
recipes/base-web/index.ts
Normal file
@@ -0,0 +1,355 @@
|
||||
import {addImport, paths, RecipeBuilder} from "blitz/installer"
|
||||
import j from "jscodeshift"
|
||||
import {join} from "path"
|
||||
|
||||
export default RecipeBuilder()
|
||||
.setName("Base Web")
|
||||
.setDescription(`This will install all necessary dependencies and configure Base Web for use.`)
|
||||
.setOwner("Konrad Kalemba <konrad@kale.mba>")
|
||||
.setRepoLink("https://github.com/blitz-js/blitz/")
|
||||
.addAddDependenciesStep({
|
||||
stepId: "addDeps",
|
||||
stepName: "Add dependencies",
|
||||
explanation: `Add 'baseui' and Styletron as a dependency too -- it's a toolkit for CSS in JS styling which Base Web relies on.`,
|
||||
packages: [
|
||||
{name: "baseui", version: "^10.5.0"},
|
||||
{name: "styletron-engine-atomic", version: "^1.4.8"},
|
||||
{name: "styletron-react", version: "^6.0.2"},
|
||||
{name: "@types/styletron-engine-atomic", version: "^1.1.1"},
|
||||
{name: "@types/styletron-react", version: "^5.0.3"},
|
||||
],
|
||||
})
|
||||
.addNewFilesStep({
|
||||
stepId: "addStyletronUtil",
|
||||
stepName: "Add Styletron util file",
|
||||
explanation: `Next, we need to add a util file that will help us to make Styletron work both client- and server-side.`,
|
||||
targetDirectory: "./utils",
|
||||
templatePath: join(__dirname, "templates", "utils"),
|
||||
templateValues: {},
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
stepId: "addStyletronAndBaseProvidersToApp",
|
||||
stepName: "Import required providers and wrap the root of the app with them",
|
||||
explanation: `Additionally we supply StyletronProvider with 'value' and 'debug' props. BaseProvider requires a 'theme' prop we set with default Base Web's light theme.`,
|
||||
singleFileSearch: paths.app(),
|
||||
transform(program) {
|
||||
const styletronProviderImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("Provider"), j.identifier("StyletronProvider"))],
|
||||
j.literal("styletron-react"),
|
||||
)
|
||||
|
||||
const styletronAndDebugImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("styletron")), j.importSpecifier(j.identifier("debug"))],
|
||||
j.literal("utils/styletron"),
|
||||
)
|
||||
|
||||
const themeAndBaseProviderImport = j.importDeclaration(
|
||||
[
|
||||
j.importSpecifier(j.identifier("LightTheme")),
|
||||
j.importSpecifier(j.identifier("BaseProvider")),
|
||||
],
|
||||
j.literal("baseui"),
|
||||
)
|
||||
|
||||
addImport(program, styletronProviderImport)
|
||||
addImport(program, styletronAndDebugImport)
|
||||
addImport(program, themeAndBaseProviderImport)
|
||||
|
||||
program
|
||||
.find(j.FunctionDeclaration, (node) => node.id.name === "MyApp")
|
||||
.forEach((path) => {
|
||||
const statement = path.value.body.body.filter(
|
||||
(b) => b.type === "ReturnStatement",
|
||||
)[0] as j.ReturnStatement
|
||||
const argument = statement?.argument as j.JSXElement
|
||||
|
||||
statement.argument = j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier("StyletronProvider"), [
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("value"),
|
||||
j.jsxExpressionContainer(j.identifier("styletron")),
|
||||
),
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("debug"),
|
||||
j.jsxExpressionContainer(j.identifier("debug")),
|
||||
),
|
||||
j.jsxAttribute(j.jsxIdentifier("debugAfterHydration")),
|
||||
]),
|
||||
j.jsxClosingElement(j.jsxIdentifier("StyletronProvider")),
|
||||
[
|
||||
j.literal("\n"),
|
||||
j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier("BaseProvider"), [
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("theme"),
|
||||
j.jsxExpressionContainer(j.identifier("LightTheme")),
|
||||
),
|
||||
]),
|
||||
j.jsxClosingElement(j.jsxIdentifier("BaseProvider")),
|
||||
[j.literal("\n"), argument, j.literal("\n")],
|
||||
),
|
||||
j.literal("\n"),
|
||||
],
|
||||
)
|
||||
})
|
||||
|
||||
return program
|
||||
},
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
stepId: "modifyGetInitialPropsAndAddStylesheetsToDocument",
|
||||
stepName: "Modify getInitialProps method and add stylesheets to Document",
|
||||
explanation: `To make Styletron work server-side we need to modify getInitialProps method of custom Document class. We also have to put Styletron's generated stylesheets in DocumentHead.`,
|
||||
singleFileSearch: paths.document(),
|
||||
transform(program) {
|
||||
const styletronProviderImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("Provider"), j.identifier("StyletronProvider"))],
|
||||
j.literal("styletron-react"),
|
||||
)
|
||||
|
||||
const styletronServerAndSheetImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("Server")), j.importSpecifier(j.identifier("Sheet"))],
|
||||
j.literal("styletron-engine-atomic"),
|
||||
)
|
||||
|
||||
const styletronImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("styletron"))],
|
||||
j.literal("utils/styletron"),
|
||||
)
|
||||
|
||||
addImport(program, styletronProviderImport)
|
||||
addImport(program, styletronServerAndSheetImport)
|
||||
addImport(program, styletronImport)
|
||||
|
||||
program
|
||||
.find(j.ImportDeclaration, {source: {value: "next/document"}})
|
||||
.forEach((nextDocumentImportPath) => {
|
||||
let specifiers = nextDocumentImportPath.value.specifiers || []
|
||||
if (
|
||||
!specifiers
|
||||
.filter((spec) => j.ImportSpecifier.check(spec))
|
||||
.some((node) => (node as j.ImportSpecifier)?.imported?.name === "DocumentContext")
|
||||
) {
|
||||
specifiers.push(j.importSpecifier(j.identifier("DocumentContext")))
|
||||
}
|
||||
})
|
||||
|
||||
program.find(j.ClassDeclaration).forEach((path) => {
|
||||
const props = j.typeAlias(
|
||||
j.identifier("MyDocumentProps"),
|
||||
null,
|
||||
j.objectTypeAnnotation([
|
||||
j.objectTypeProperty(
|
||||
j.identifier("stylesheets"),
|
||||
j.arrayTypeAnnotation(j.genericTypeAnnotation(j.identifier("Sheet"), null)),
|
||||
false,
|
||||
),
|
||||
]),
|
||||
)
|
||||
|
||||
path.insertBefore(props)
|
||||
|
||||
path.value.superTypeParameters = j.typeParameterInstantiation([
|
||||
j.genericTypeAnnotation(j.identifier("MyDocumentProps"), null),
|
||||
])
|
||||
})
|
||||
|
||||
program.find(j.ClassBody).forEach((path) => {
|
||||
const {node} = path
|
||||
|
||||
const ctxParam = j.identifier("ctx")
|
||||
ctxParam.typeAnnotation = j.tsTypeAnnotation(
|
||||
j.tsTypeReference(j.identifier("DocumentContext")),
|
||||
)
|
||||
|
||||
const stylesheetsObjectProperty = j.objectProperty(
|
||||
j.identifier("stylesheets"),
|
||||
j.identifier("stylesheets"),
|
||||
)
|
||||
stylesheetsObjectProperty.shorthand = true
|
||||
|
||||
const getInitialPropsBody = j.blockStatement([
|
||||
j.variableDeclaration("const", [
|
||||
j.variableDeclarator(
|
||||
j.identifier("originalRenderPage"),
|
||||
j.memberExpression(j.identifier("ctx"), j.identifier("renderPage")),
|
||||
),
|
||||
]),
|
||||
j.expressionStatement(
|
||||
j.assignmentExpression(
|
||||
"=",
|
||||
j.memberExpression(j.identifier("ctx"), j.identifier("renderPage")),
|
||||
j.arrowFunctionExpression(
|
||||
[],
|
||||
j.callExpression(j.identifier("originalRenderPage"), [
|
||||
j.objectExpression([
|
||||
j.objectProperty(
|
||||
j.identifier("enhanceApp"),
|
||||
j.arrowFunctionExpression(
|
||||
[j.identifier("App")],
|
||||
j.arrowFunctionExpression(
|
||||
[j.identifier("props")],
|
||||
j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier("StyletronProvider"), [
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("value"),
|
||||
j.jsxExpressionContainer(j.identifier("styletron")),
|
||||
),
|
||||
]),
|
||||
j.jsxClosingElement(j.jsxIdentifier("StyletronProvider")),
|
||||
[
|
||||
j.literal("\n"),
|
||||
j.jsxElement(
|
||||
j.jsxOpeningElement(
|
||||
j.jsxIdentifier("App"),
|
||||
[j.jsxSpreadAttribute(j.identifier("props"))],
|
||||
true,
|
||||
),
|
||||
),
|
||||
j.literal("\n"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
j.variableDeclaration("const", [
|
||||
j.variableDeclarator(
|
||||
j.identifier("initialProps"),
|
||||
j.awaitExpression(
|
||||
j.callExpression(
|
||||
j.memberExpression(j.identifier("Document"), j.identifier("getInitialProps")),
|
||||
[j.identifier("ctx")],
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
j.variableDeclaration("const", [
|
||||
j.variableDeclarator(
|
||||
j.identifier("stylesheets"),
|
||||
j.logicalExpression(
|
||||
"||",
|
||||
j.callExpression(
|
||||
j.memberExpression(
|
||||
j.parenthesizedExpression(
|
||||
j.tsAsExpression(
|
||||
j.identifier("styletron"),
|
||||
j.tsTypeReference(j.identifier("Server")),
|
||||
),
|
||||
),
|
||||
j.identifier("getStylesheets"),
|
||||
),
|
||||
[],
|
||||
),
|
||||
j.arrayExpression([]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
j.returnStatement(
|
||||
j.objectExpression([
|
||||
j.spreadElement(j.identifier("initialProps")),
|
||||
stylesheetsObjectProperty,
|
||||
]),
|
||||
),
|
||||
])
|
||||
|
||||
const getInitialPropsMethod = j.classMethod(
|
||||
"method",
|
||||
j.identifier("getInitialProps"),
|
||||
[ctxParam],
|
||||
getInitialPropsBody,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
getInitialPropsMethod.async = true
|
||||
|
||||
// TODO: better way will be to check if the method already exists and modify it or else add it
|
||||
// currently it gets added assuming it did not exist before
|
||||
node.body.splice(0, 0, getInitialPropsMethod)
|
||||
})
|
||||
|
||||
program.find(j.JSXElement, {openingElement: {name: {name: "Head"}}}).forEach((path) => {
|
||||
const {node} = path
|
||||
path.replace(
|
||||
j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier("Head")),
|
||||
j.jsxClosingElement(j.jsxIdentifier("Head")),
|
||||
[
|
||||
...(node.children || []),
|
||||
j.literal("\n"),
|
||||
j.jsxExpressionContainer(
|
||||
j.callExpression(
|
||||
j.memberExpression(
|
||||
j.memberExpression(
|
||||
j.memberExpression(j.thisExpression(), j.identifier("props")),
|
||||
j.identifier("stylesheets"),
|
||||
),
|
||||
j.identifier("map"),
|
||||
),
|
||||
[
|
||||
j.arrowFunctionExpression(
|
||||
[j.identifier("sheet"), j.identifier("i")],
|
||||
j.jsxElement(
|
||||
j.jsxOpeningElement(
|
||||
j.jsxIdentifier("style"),
|
||||
[
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("className"),
|
||||
j.literal("_styletron_hydrate_"),
|
||||
),
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("dangerouslySetInnerHTML"),
|
||||
j.jsxExpressionContainer(
|
||||
j.objectExpression([
|
||||
j.objectProperty(
|
||||
j.identifier("__html"),
|
||||
j.memberExpression(j.identifier("sheet"), j.identifier("css")),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("media"),
|
||||
j.jsxExpressionContainer(
|
||||
j.memberExpression(
|
||||
j.memberExpression(j.identifier("sheet"), j.identifier("attrs")),
|
||||
j.identifier("media"),
|
||||
),
|
||||
),
|
||||
),
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("data-hydrate"),
|
||||
j.jsxExpressionContainer(
|
||||
j.memberExpression(
|
||||
j.memberExpression(j.identifier("sheet"), j.identifier("attrs")),
|
||||
j.stringLiteral("data-hydrate"),
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
j.jsxAttribute(
|
||||
j.jsxIdentifier("key"),
|
||||
j.jsxExpressionContainer(j.jsxIdentifier("i")),
|
||||
),
|
||||
],
|
||||
true,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
j.literal("\n"),
|
||||
],
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
return program
|
||||
},
|
||||
})
|
||||
.build()
|
||||
32
recipes/base-web/package.json
Normal file
32
recipes/base-web/package.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@blitzjs/recipe-base-web",
|
||||
"private": true,
|
||||
"version": "2.0.0-beta.11",
|
||||
"description": "The Blitz Recipe for installing Base Web",
|
||||
"main": "index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"No tests yet\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/blitz-js/blitz.git"
|
||||
},
|
||||
"keywords": [
|
||||
"blitz",
|
||||
"blitzjs",
|
||||
"base-web"
|
||||
],
|
||||
"author": "Konrad Kalemba <konrad@kale.mba>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/blitz-js/blitz/issues"
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"blitz": "2.2.2",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jscodeshift": "0.11.2"
|
||||
}
|
||||
}
|
||||
14
recipes/base-web/templates/utils/styletron.ts
Normal file
14
recipes/base-web/templates/utils/styletron.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import {Client, Server} from "styletron-engine-atomic"
|
||||
import {DebugEngine} from "styletron-react"
|
||||
|
||||
const getHydrateClass = () =>
|
||||
document.getElementsByClassName("_styletron_hydrate_") as HTMLCollectionOf<HTMLStyleElement>
|
||||
|
||||
export const styletron =
|
||||
typeof window === "undefined"
|
||||
? new Server()
|
||||
: new Client({
|
||||
hydrate: getHydrateClass(),
|
||||
})
|
||||
|
||||
export const debug = process.env.NODE_ENV === "production" ? void 0 : new DebugEngine()
|
||||
25
recipes/bulma/CHANGELOG.md
Normal file
25
recipes/bulma/CHANGELOG.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# @blitzjs/recipe-bulma
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1476a577]
|
||||
- blitz@2.0.0-beta.11
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9db6c885]
|
||||
- Updated dependencies [d98e4bac]
|
||||
- Updated dependencies [9fe0cc54]
|
||||
- Updated dependencies [af58e2b2]
|
||||
- Updated dependencies [2ade7268]
|
||||
- Updated dependencies [0edeaa37]
|
||||
- Updated dependencies [430f6ec7]
|
||||
- Updated dependencies [15d22af2]
|
||||
- Updated dependencies [aa34661f]
|
||||
- Updated dependencies [8e0c9d76]
|
||||
- Updated dependencies [e2c18895]
|
||||
- blitz@2.0.0-beta.5
|
||||
17
recipes/bulma/README.md
Normal file
17
recipes/bulma/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
## bulma
|
||||
|
||||
The Blitz Recipe for installing Bulma CSS
|
||||
|
||||
```
|
||||
blitz install bulma
|
||||
```
|
||||
|
||||
## More information
|
||||
|
||||
- [How to use receipes in Blitz](https://blitzjs.com/docs/using-recipes)
|
||||
- [Learn about Bulma CSS](https://bulma.io/)
|
||||
- [Bulma CSS's Github](https://github.com/jgthms/bulma)
|
||||
|
||||
## Contributors
|
||||
|
||||
- vivek <vivek7405@hey.com>
|
||||
37
recipes/bulma/index.ts
Normal file
37
recipes/bulma/index.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import {addImport, paths, RecipeBuilder} from "blitz/installer"
|
||||
import j from "jscodeshift"
|
||||
import {join} from "path"
|
||||
|
||||
export default RecipeBuilder()
|
||||
.setName("Bulma CSS")
|
||||
.setDescription(`This will install all necessary dependencies and configure Bulma for use.`)
|
||||
.setOwner("vivek7405@hey.com")
|
||||
.setRepoLink("https://github.com/blitz-js/blitz/")
|
||||
.addAddDependenciesStep({
|
||||
stepId: "addDeps",
|
||||
stepName: "npm dependencies",
|
||||
explanation: `Bulma CSS requires a couple of dependencies including sass for converting sass and scss to css`,
|
||||
packages: [
|
||||
{name: "bulma", version: "0.9.x", isDevDep: true},
|
||||
{name: "sass", version: "1.43.x", isDevDep: true},
|
||||
],
|
||||
})
|
||||
.addNewFilesStep({
|
||||
stepId: "addStyles",
|
||||
stepName: "Stylesheet",
|
||||
explanation: `Adds a root CSS stylesheet where Bulma is imported and where you can add global styles`,
|
||||
targetDirectory: "./app/core/styles",
|
||||
templatePath: join(__dirname, "templates", "styles"),
|
||||
templateValues: {},
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
stepId: "importStyles",
|
||||
stepName: "Import stylesheets",
|
||||
explanation: `Imports the stylesheet we just added into your app`,
|
||||
singleFileSearch: paths.app(),
|
||||
transform(program) {
|
||||
const stylesImport = j.importDeclaration([], j.literal("app/core/styles/index.scss"))
|
||||
return addImport(program, stylesImport)
|
||||
},
|
||||
})
|
||||
.build()
|
||||
31
recipes/bulma/package.json
Normal file
31
recipes/bulma/package.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "@blitzjs/recipe-bulma",
|
||||
"private": true,
|
||||
"version": "2.0.0-beta.11",
|
||||
"description": "The Blitz Recipe for installing Bulma CSS",
|
||||
"main": "index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"No tests yet\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/blitz-js/blitz.git"
|
||||
},
|
||||
"keywords": [
|
||||
"blitz",
|
||||
"blitzjs"
|
||||
],
|
||||
"author": "vivek <vivek7405@hey.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/blitz-js/blitz/issues"
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"blitz": "2.2.2",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jscodeshift": "0.11.2"
|
||||
}
|
||||
}
|
||||
29
recipes/bulma/templates/styles/index.scss
Normal file
29
recipes/bulma/templates/styles/index.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
@charset "utf-8";
|
||||
|
||||
// Customization
|
||||
|
||||
// You can easily customize Bulma with your own variables.
|
||||
// Just uncomment the following block to see the result.
|
||||
|
||||
/*
|
||||
1. Import the initial variables
|
||||
@import "node_modules/bulma/sass/utilities/initial-variables";
|
||||
|
||||
2. Set your own initial variables
|
||||
Update the blue shade, used for links
|
||||
$blue: #06bcef;
|
||||
Add pink and its invert
|
||||
$pink: #ff8080;
|
||||
$pink-invert: #fff;
|
||||
Update the sans-serif font family
|
||||
$family-sans-serif: "Helvetica", "Arial", sans-serif;
|
||||
|
||||
3. Set the derived variables
|
||||
Use the new pink as the primary color
|
||||
$primary: $pink;
|
||||
$primary-invert: $pink-invert;
|
||||
|
||||
4. Import the rest of Bulma
|
||||
*/
|
||||
|
||||
@import "node_modules/bulma/bulma.sass";
|
||||
25
recipes/bumbag-ui/CHANGELOG.md
Normal file
25
recipes/bumbag-ui/CHANGELOG.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# @blitzjs/recipe-bumbag-ui
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1476a577]
|
||||
- blitz@2.0.0-beta.11
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9db6c885]
|
||||
- Updated dependencies [d98e4bac]
|
||||
- Updated dependencies [9fe0cc54]
|
||||
- Updated dependencies [af58e2b2]
|
||||
- Updated dependencies [2ade7268]
|
||||
- Updated dependencies [0edeaa37]
|
||||
- Updated dependencies [430f6ec7]
|
||||
- Updated dependencies [15d22af2]
|
||||
- Updated dependencies [aa34661f]
|
||||
- Updated dependencies [8e0c9d76]
|
||||
- Updated dependencies [e2c18895]
|
||||
- blitz@2.0.0-beta.5
|
||||
12
recipes/bumbag-ui/README.md
Normal file
12
recipes/bumbag-ui/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## bumbag-ui
|
||||
|
||||
The Blitz Recipe for installing Bumbag UI
|
||||
|
||||
## more information
|
||||
|
||||
- [Bumbag UI Homepage](https://www.bumbag.style/)
|
||||
- [Github page](https://github.com/jxom/bumbag-ui)
|
||||
|
||||
## contributors
|
||||
|
||||
- Agusti Fernandez Pardo <agusti@cruceritis.com>
|
||||
121
recipes/bumbag-ui/index.ts
Normal file
121
recipes/bumbag-ui/index.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import {addImport, paths, Program, RecipeBuilder} from "blitz/installer"
|
||||
import j from "jscodeshift"
|
||||
|
||||
function wrapComponentWithBumbagProvider(program: Program) {
|
||||
program
|
||||
.find(j.FunctionDeclaration, (node) => node.id.name === "MyApp")
|
||||
.forEach((path) => {
|
||||
const statement = path.value.body.body.filter(
|
||||
(b) => b.type === "ReturnStatement",
|
||||
)[0] as j.ReturnStatement
|
||||
const argument = statement?.argument as j.JSXElement
|
||||
|
||||
try {
|
||||
statement.argument = j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier("BumbagProvider isSSR")),
|
||||
j.jsxClosingElement(j.jsxIdentifier("BumbagProvider")),
|
||||
[j.jsxText("\n"), argument, j.jsxText("\n")],
|
||||
)
|
||||
} catch {
|
||||
console.error("Already installed recipe")
|
||||
}
|
||||
})
|
||||
return program
|
||||
}
|
||||
|
||||
function injectInitializeColorModeAndExtractCritical(program: Program) {
|
||||
// Finds body element and injects InitializeColorMode before it.
|
||||
program.find(j.JSXElement, {openingElement: {name: {name: "body"}}}).forEach((path) => {
|
||||
const {node} = path
|
||||
path.replace(
|
||||
j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier("body")),
|
||||
j.jsxClosingElement(j.jsxIdentifier("body")),
|
||||
[
|
||||
j.literal("\n"),
|
||||
j.jsxElement(j.jsxOpeningElement(j.jsxIdentifier("InitializeColorMode"), [], true)),
|
||||
...(node.children || []),
|
||||
],
|
||||
),
|
||||
)
|
||||
})
|
||||
// Find ClassDeclaration and insert extractCritical on getInitialProps
|
||||
program
|
||||
.find(j.ClassDeclaration)
|
||||
.at(0)
|
||||
.get()
|
||||
.insertAfter(
|
||||
`
|
||||
MyDocument.getInitialProps = async (ctx) => {
|
||||
const initialProps = await Document.getInitialProps(ctx)
|
||||
const styles = extractCritical(initialProps.html)
|
||||
return {
|
||||
...initialProps,
|
||||
styles: (
|
||||
<>
|
||||
{initialProps.styles}
|
||||
<style
|
||||
data-emotion-css={styles.ids.join(' ')}
|
||||
dangerouslySetInnerHTML={{ __html: styles.css }}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
}
|
||||
}
|
||||
`,
|
||||
)
|
||||
return program
|
||||
}
|
||||
|
||||
export default RecipeBuilder()
|
||||
.setName("Bumbag UI")
|
||||
.setDescription(
|
||||
`This will install all necessary dependencies and configure BumbagProvider in your _app and _document`,
|
||||
)
|
||||
.setOwner("me@agusti.me")
|
||||
.setRepoLink("https://github.com/blitz-js/blitz/")
|
||||
.addAddDependenciesStep({
|
||||
stepId: "addDeps",
|
||||
stepName: "npm dependencies",
|
||||
explanation: `Bumbag UI requires both "bumbag" and "bumbag-server" (SSR) npm packages`,
|
||||
packages: [
|
||||
{name: "bumbag", version: "2.x"},
|
||||
{name: "bumbag-server", version: "2.x"},
|
||||
],
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
stepId: "importBmumbagProvider",
|
||||
stepName: "Import BumbagProvider",
|
||||
explanation: `Import bumbag Provider as BumbagProvider into _app`,
|
||||
singleFileSearch: paths.app(),
|
||||
transform(program) {
|
||||
const stylesImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("Provider as BumbagProvider"))],
|
||||
j.literal("bumbag"),
|
||||
)
|
||||
|
||||
addImport(program, stylesImport)
|
||||
return wrapComponentWithBumbagProvider(program)
|
||||
},
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
stepId: "ImportExtractCriticalAndInitializeColorMode",
|
||||
stepName: "ImportExtractCritical & initializeColorMode",
|
||||
explanation: `Import InitializeColorMode from bumbag, and extractCritical into _document`,
|
||||
singleFileSearch: paths.document(),
|
||||
transform(program) {
|
||||
const initializeColorModeImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("InitializeColorMode"))],
|
||||
j.literal("bumbag"),
|
||||
)
|
||||
const exctractCriticalImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("extractCritical"))],
|
||||
j.literal("bumbag-server"),
|
||||
)
|
||||
addImport(program, initializeColorModeImport)
|
||||
addImport(program, exctractCriticalImport)
|
||||
|
||||
return injectInitializeColorModeAndExtractCritical(program)
|
||||
},
|
||||
})
|
||||
.build()
|
||||
34
recipes/bumbag-ui/package.json
Normal file
34
recipes/bumbag-ui/package.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@blitzjs/recipe-bumbag-ui",
|
||||
"private": true,
|
||||
"version": "2.0.0-beta.11",
|
||||
"description": "The Blitz Recipe for installing Bumbag UI",
|
||||
"main": "index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"No tests yet\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/blitz-js/blitz.git"
|
||||
},
|
||||
"keywords": [
|
||||
"blitz",
|
||||
"blitzjs",
|
||||
"chakra",
|
||||
"bumbag-ui"
|
||||
],
|
||||
"author": "Agusti Fernandez Pardo <agusti@cruceritis.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/blitz-js/blitz/issues"
|
||||
},
|
||||
"homepage": "https://github.com/blitz-js/blitz#readme",
|
||||
"dependencies": {
|
||||
"blitz": "2.2.2",
|
||||
"jscodeshift": "0.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jscodeshift": "0.11.2",
|
||||
"ast-types": "0.14.2"
|
||||
}
|
||||
}
|
||||
25
recipes/chakra-ui/CHANGELOG.md
Normal file
25
recipes/chakra-ui/CHANGELOG.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# @blitzjs/recipe-chakra-ui
|
||||
|
||||
## 2.0.0-beta.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1476a577]
|
||||
- blitz@2.0.0-beta.11
|
||||
|
||||
## 2.0.0-beta.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [9db6c885]
|
||||
- Updated dependencies [d98e4bac]
|
||||
- Updated dependencies [9fe0cc54]
|
||||
- Updated dependencies [af58e2b2]
|
||||
- Updated dependencies [2ade7268]
|
||||
- Updated dependencies [0edeaa37]
|
||||
- Updated dependencies [430f6ec7]
|
||||
- Updated dependencies [15d22af2]
|
||||
- Updated dependencies [aa34661f]
|
||||
- Updated dependencies [8e0c9d76]
|
||||
- Updated dependencies [e2c18895]
|
||||
- blitz@2.0.0-beta.5
|
||||
12
recipes/chakra-ui/README.md
Normal file
12
recipes/chakra-ui/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
## chakra-ui
|
||||
|
||||
Easily styling Blitz app using Chakra UI
|
||||
|
||||
## more information
|
||||
|
||||
- [Chakra UI homepage](https://chakra-ui.com)
|
||||
- [Github page](https://github.com/chrisbull/blitz-app-with-chakra-ui-template)
|
||||
|
||||
## contributors
|
||||
|
||||
- zeko369
|
||||
192
recipes/chakra-ui/index.ts
Normal file
192
recipes/chakra-ui/index.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import {addImport, paths, Program, RecipeBuilder, wrapAppWithProvider} from "blitz/installer"
|
||||
import j, {JSXIdentifier} from "jscodeshift"
|
||||
|
||||
function updateLabeledTextFieldWithInputComponent(program: Program) {
|
||||
program
|
||||
.find(j.TSInterfaceDeclaration)
|
||||
.find(j.TSExpressionWithTypeArguments)
|
||||
.forEach((path: j.ASTPath<j.TSExpressionWithTypeArguments>) => {
|
||||
path.replace(
|
||||
j.tsExpressionWithTypeArguments(
|
||||
j.identifier("ComponentPropsWithoutRef"),
|
||||
j.tsTypeParameterInstantiation([j.tsTypeQuery(j.identifier("Input"))]),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
function replaceOuterDivWithFormControl(program: Program) {
|
||||
program
|
||||
.find(j.JSXElement)
|
||||
.filter((path) => {
|
||||
const {node} = path
|
||||
const openingElementNameNode = node?.openingElement?.name as JSXIdentifier
|
||||
|
||||
// This will not include JSX elements within curly braces
|
||||
const countOfChildrenJSXElements =
|
||||
path.node.children?.filter((childNode) => childNode.type === "JSXElement").length || 0
|
||||
|
||||
return (
|
||||
openingElementNameNode?.name === "div" &&
|
||||
node?.openingElement?.selfClosing === false &&
|
||||
countOfChildrenJSXElements === 1
|
||||
)
|
||||
})
|
||||
.forEach((path) => {
|
||||
path.node.openingElement = j.jsxOpeningElement(
|
||||
j.jsxIdentifier("FormControl"),
|
||||
path.node.openingElement.attributes,
|
||||
)
|
||||
path.node.closingElement = j.jsxClosingElement(j.jsxIdentifier("FormControl"))
|
||||
})
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
function replaceInputWithChakraInput(program: Program) {
|
||||
program
|
||||
.find(j.JSXElement)
|
||||
.filter((path) => {
|
||||
const {node} = path
|
||||
const openingElementNameNode = node?.openingElement?.name as JSXIdentifier
|
||||
|
||||
return openingElementNameNode?.name === "input" && node?.openingElement?.selfClosing === true
|
||||
})
|
||||
.forEach((path) => {
|
||||
const {node} = path
|
||||
node.openingElement = j.jsxOpeningElement(
|
||||
j.jsxIdentifier("Input"),
|
||||
node.openingElement.attributes,
|
||||
node?.openingElement?.selfClosing,
|
||||
)
|
||||
})
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
function replaceLabelWithChakraLabel(program: Program) {
|
||||
program
|
||||
.find(j.JSXElement)
|
||||
.filter((path) => {
|
||||
const {node} = path
|
||||
const openingElementNameNode = node?.openingElement?.name as JSXIdentifier
|
||||
|
||||
return openingElementNameNode?.name === "label" && node?.openingElement?.selfClosing === false
|
||||
})
|
||||
.forEach((path) => {
|
||||
path.node.openingElement = j.jsxOpeningElement(
|
||||
j.jsxIdentifier("FormLabel"),
|
||||
path.node.openingElement.attributes,
|
||||
)
|
||||
path.node.closingElement = j.jsxClosingElement(j.jsxIdentifier("FormLabel"))
|
||||
})
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
function removeDefaultStyleElement(program: Program) {
|
||||
program
|
||||
.find(j.JSXElement)
|
||||
.filter((path) => {
|
||||
const {node} = path
|
||||
const openingElementNameNode = node?.openingElement?.name as JSXIdentifier
|
||||
|
||||
// Assumes there's one style element at the point the user runs the recipe.
|
||||
return openingElementNameNode?.name === "style" && node?.openingElement?.selfClosing === false
|
||||
})
|
||||
.forEach((path) => {
|
||||
// Removes the node.
|
||||
path.replace()
|
||||
})
|
||||
|
||||
return program
|
||||
}
|
||||
|
||||
export default RecipeBuilder()
|
||||
.setName("Chakra UI")
|
||||
.setDescription(`This will install all necessary dependencies and configure Chakra UI for use.`)
|
||||
.setOwner("zekan.fran369@gmail.com")
|
||||
.setRepoLink("https://github.com/blitz-js/blitz/")
|
||||
.addAddDependenciesStep({
|
||||
stepId: "addDeps",
|
||||
stepName: "npm dependencies",
|
||||
explanation: `Chakra UI requires some other dependencies like emotion to work`,
|
||||
packages: [
|
||||
{name: "@chakra-ui/react", version: "1.x"},
|
||||
{name: "@emotion/react", version: "11.x"},
|
||||
{name: "@emotion/styled", version: "11.x"},
|
||||
{name: "framer-motion", version: "5.x"},
|
||||
],
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
stepId: "importProviderAndReset",
|
||||
stepName: "Import ChakraProvider component",
|
||||
explanation: `Import the chakra-ui provider into _app, so it is accessible in the whole app`,
|
||||
singleFileSearch: paths.app(),
|
||||
transform(program) {
|
||||
const stylesImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("ChakraProvider"))],
|
||||
j.literal("@chakra-ui/react"),
|
||||
)
|
||||
|
||||
addImport(program, stylesImport)
|
||||
return wrapAppWithProvider(program, "ChakraProvider")
|
||||
},
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
stepId: "updateLabeledTextField",
|
||||
stepName: "Update the `LabeledTextField` with Chakra UI's `Input` component",
|
||||
explanation: `The LabeledTextField component uses Chakra UI's input component`,
|
||||
singleFileSearch: `${paths.appSrcDirectory()}/core/components/LabeledTextField.tsx`,
|
||||
transform(program) {
|
||||
// Add ComponentPropsWithoutRef import
|
||||
program.find(j.ImportDeclaration, {source: {value: "react"}}).forEach((path) => {
|
||||
let specifiers = path.value.specifiers || []
|
||||
if (
|
||||
!specifiers.some(
|
||||
(node) => (node as j.ImportSpecifier)?.imported?.name === "ComponentPropsWithoutRef",
|
||||
)
|
||||
) {
|
||||
specifiers.push(j.importSpecifier(j.identifier("ComponentPropsWithoutRef")))
|
||||
}
|
||||
})
|
||||
|
||||
const chakraInputImport = j.importDeclaration(
|
||||
[j.importSpecifier(j.identifier("Input"))],
|
||||
j.literal("@chakra-ui/input"),
|
||||
)
|
||||
|
||||
const chakraFormControlImport = j.importDeclaration(
|
||||
[
|
||||
j.importSpecifier(j.identifier("FormControl")),
|
||||
j.importSpecifier(j.identifier("FormLabel")),
|
||||
],
|
||||
j.literal("@chakra-ui/form-control"),
|
||||
)
|
||||
|
||||
addImport(program, chakraInputImport)
|
||||
addImport(program, chakraFormControlImport)
|
||||
|
||||
// Imperative steps to describe transformations
|
||||
|
||||
// 1. Update the type of `LabeledTextField`
|
||||
updateLabeledTextFieldWithInputComponent(program)
|
||||
|
||||
// 2. Remove the default <style jsx> styling
|
||||
removeDefaultStyleElement(program)
|
||||
|
||||
// 3. Replace outer div with `FormControl`
|
||||
replaceOuterDivWithFormControl(program)
|
||||
|
||||
// 4. Replace `input` with `ChakraInput`
|
||||
replaceInputWithChakraInput(program)
|
||||
|
||||
// 5. Replace `label` with `ChakraLabel`
|
||||
replaceLabelWithChakraLabel(program)
|
||||
|
||||
return program
|
||||
},
|
||||
})
|
||||
.build()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user