Skip to content

Commit

Permalink
feat: Blitz RPC endpoint to the app directory (#4341)
Browse files Browse the repository at this point in the history
* feat: make `rpchandler` work with `Request` and return a `Response`

* rename: rpcRequestHandler

* feat: improvements

* blitz-auth now works

* return headers

* working

* cleanup

* working sveltekit, with regressin of next.js app dir

* cleanup

* pnpm lock fix

* Update packages/blitz-auth/src/server/auth-plugin.ts

* fix build

* more work

* fixes

* fix issues with auth

* maybe required breaking change

* pointless test

* Update packages/blitz-auth/package.json

* fixes

* fix

* get all tests passing

* more fixes

* changeset

* fixes

* fix

* pnpm lock update

* fix

* update pnpm lcok

* revert unnecessary changes

* imporve api naming

* cleanup

* fix

* Update integration-tests/next-13-app-dir/src/blitz-server.ts

* Apply suggestions from code review

* remove unrelated changes

* Update packages/blitz-auth/src/server/auth-sessions.ts

* fix types

* fix overload

* remove dependence on http module

* review changes

* oops

* fix

* fix types

* Revert "fix types"

This reverts commit b06a4fb.

* Revert "fix"

This reverts commit 47d0cdd.

* Revert "oops"

This reverts commit 94cb558.

* Revert "review changes"

This reverts commit 14d8eb2.

* fix the logic

* sort deps

* template fixes

* chore: add changeset

* chore: remove outdated changeset

* fix changeset formatting

* Update .changeset/tidy-gorillas-confess.md

* remove `blitzAuthRpcMiddleware`

* remove uses of any

* fix jsdoc

* no var

* separate the type imports

* fix unsupported method of session in rsc

* fix

* api changes

* Apply suggestions from code review

Co-authored-by: Brandon Bayer <[email protected]>

* Apply suggestions from code review

* Update .changeset/tidy-gorillas-confess.md

* fix

* fic

---------

Co-authored-by: Brandon Bayer <[email protected]>
  • Loading branch information
siddhsuresh and flybayer committed Jul 1, 2024
1 parent 2560175 commit 3b10b13
Show file tree
Hide file tree
Showing 62 changed files with 1,329 additions and 700 deletions.
47 changes: 47 additions & 0 deletions .changeset/tidy-gorillas-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
"blitz": minor
"@blitzjs/auth": minor
"@blitzjs/next": minor
"@blitzjs/rpc": minor
"@blitzjs/generator": minor
---

feat: add blitz auth support for the Web `Request` API standard

Usage using the new `withBlitzAuth` adapter in the App Router:

```ts
import {withBlitzAuth} from "app/blitz-server"

export const {POST} = withBlitzAuth({
POST: async (_request, _params, ctx) => {
const session = ctx.session
await session.$revoke()

return new Response(
JSON.stringify({
userId: session.userId,
}),
{status: 200},
)
},
})
```

feat: New Blitz RPC handler meant to with the next.js app router `route.ts` files

Usage using the new `rpcAppHandler` function

```ts
// app/api/rpc/[[...blitz]]/route.ts
import {rpcAppHandler} from "@blitzjs/rpc"
import {withBlitzAuth} from "app/blitz-server"

// Usage with blitz auth
export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())

// Standalone usage
export const {GET, POST, HEAD} = rpcAppHandler()
```

chore: Update the app directory starter
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: 18
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
Expand All @@ -44,7 +44,7 @@ jobs:
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: 18
node-version: 20
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- name: Build
Expand Down Expand Up @@ -75,7 +75,7 @@ jobs:
- name: Setup node@16
uses: actions/setup-node@v2
with:
node-version: 18
node-version: 20
cache: "pnpm"

- name: Install dependencies
Expand Down Expand Up @@ -137,7 +137,7 @@ jobs:
if: matrix.folder != 'next-13-app-dir' || matrix.os != 'windows-latest'
uses: actions/setup-node@v2
with:
node-version: 18
node-version: 20
cache: "pnpm"

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion apps/next13/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@tanstack/react-query": "4.0.10",
"blitz": "2.0.10",
"flatted": "3.2.7",
"next": "canary",
"next": "14.3.0-canary.28",
"prisma": "^4.5.0",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
Binary file modified apps/next13/prisma/dev.db
Binary file not shown.
4 changes: 4 additions & 0 deletions apps/next13/src/app/api/rpc/[[...blitz]]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {rpcAppHandler} from "@blitzjs/rpc"
import {withBlitzAuth} from "src/blitz-server"

export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())
39 changes: 20 additions & 19 deletions apps/next13/src/blitz-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,27 @@ import {simpleRolesIsAuthorized} from "@blitzjs/auth"
import {BlitzLogger} from "blitz"
import {RpcServerPlugin} from "@blitzjs/rpc"

const {api, getBlitzContext, useAuthenticatedBlitzContext, invoke} = setupBlitzServer({
plugins: [
AuthServerPlugin({
cookiePrefix: "web-cookie-prefix",
storage: PrismaStorage(db),
isAuthorized: simpleRolesIsAuthorized,
}),
RpcServerPlugin({
logging: {
disablelevel: "debug",
},
onInvokeError(error) {
console.log("onInvokeError", error)
},
}),
],
logger: BlitzLogger({}),
})
const {api, getBlitzContext, useAuthenticatedBlitzContext, invoke, withBlitzAuth} =
setupBlitzServer({
plugins: [
AuthServerPlugin({
cookiePrefix: "web-cookie-prefix",
storage: PrismaStorage(db),
isAuthorized: simpleRolesIsAuthorized,
}),
RpcServerPlugin({
logging: {
disablelevel: "debug",
},
onInvokeError(error) {
console.log("onInvokeError", error)
},
}),
],
logger: BlitzLogger({}),
})

export {api, getBlitzContext, useAuthenticatedBlitzContext, invoke}
export {api, getBlitzContext, useAuthenticatedBlitzContext, invoke, withBlitzAuth}

export const cliConfig: BlitzCliConfig = {
customTemplates: "src/templates",
Expand Down
4 changes: 0 additions & 4 deletions apps/next13/src/pages/api/rpc/[[...blitz]].ts

This file was deleted.

2 changes: 1 addition & 1 deletion apps/next13/src/users/queries/getCurrentUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ export default async function getCurrentUser(input: null, ctx: Ctx) {
}

export const config = {
httpMethod: "GET",
httpMethod: "POST",
}
2 changes: 1 addition & 1 deletion apps/toolkit-app-passportjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"@hookform/resolvers": "2.9.10",
"@prisma/client": "4.6.1",
"blitz": "2.0.10",
"next": "canary",
"next": "14.3.0-canary.28",
"openid-client": "5.2.1",
"prisma": "4.6.1",
"react": "18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/toolkit-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@hookform/resolvers": "2.9.10",
"@prisma/client": "4.6.1",
"blitz": "2.0.10",
"next": "canary",
"next": "14.3.0-canary.28",
"next-auth": "4.24.7",
"prisma": "4.6.1",
"react": "18.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,11 @@ const LoginPage: BlitzPage = () => {
<LoginForm
onSuccess={(_user) => {
const next = router.query.next ? decodeURIComponent(router.query.next as string) : "/"
// return router.push(next)
return router.push(next)
}}
/>
</Layout>
)
}

LoginPage.authenticate = {
redirectTo: "/",
}

export default LoginPage
File renamed without changes.
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"blitz": "2.0.10",
"jest": "29.3.0",
"jest-environment-jsdom": "29.3.0",
"next": "canary",
"next": "14.3.0-canary.28",
"passport-mock-strategy": "2.0.0",
"passport-twitter": "1.0.4",
"prisma": "4.6.1",
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/auth-with-rpc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@prisma/client": "4.6.1",
"blitz": "2.0.10",
"delay": "5.0.0",
"next": "canary",
"next": "14.3.0-canary.28",
"prisma": "4.6.1",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@prisma/client": "4.6.1",
"blitz": "2.0.10",
"lowdb": "3.0.0",
"next": "canary",
"next": "14.3.0-canary.28",
"prisma": "4.6.1",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand Down
7 changes: 2 additions & 5 deletions integration-tests/auth/pages/api/signin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,11 @@ export const authenticateUser = async (email: string, password: string) => {
}

export default api(async (req, res, ctx) => {
const blitzContext = ctx

const user = await authenticateUser(req.query.email as string, req.query.password as string)

await blitzContext.session.$create({
await ctx.session.$create({
userId: user.id,
role: user.role as Role,
})

res.status(200).json({email: req.query.email, userId: blitzContext.session.userId})
res.status(200).json({email: req.query.email, userId: ctx.session.userId})
})
2 changes: 1 addition & 1 deletion integration-tests/get-initial-props/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@prisma/client": "4.6.1",
"blitz": "2.0.10",
"lowdb": "3.0.0",
"next": "canary",
"next": "14.3.0-canary.28",
"prisma": "4.6.1",
"react": "18.2.0",
"react-dom": "18.2.0"
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/middleware/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@blitzjs/next": "2.0.10",
"@blitzjs/rpc": "2.0.10",
"blitz": "2.0.10",
"next": "canary",
"next": "14.3.0-canary.28",
"react": "18.2.0",
"react-dom": "18.2.0"
},
Expand Down
15 changes: 15 additions & 0 deletions integration-tests/next-13-app-dir/app/api/logout/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {withBlitzAuth} from "../../../src/blitz-server"

export const {POST} = withBlitzAuth({
POST: async (_request, _params, ctx) => {
const session = ctx.session
await session.$revoke()

return new Response(
JSON.stringify({
userId: session.userId,
}),
{status: 200},
)
},
})
11 changes: 11 additions & 0 deletions integration-tests/next-13-app-dir/app/api/noauth/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {H} from "@blitzjs/auth/dist/index-0ecbee46"
import {withBlitzAuth} from "../../../src/blitz-server"

const emptyResponse = async () => {
return new Response(null, {status: 200})
}

export const {POST, HEAD} = withBlitzAuth({
POST: emptyResponse,
HEAD: emptyResponse,
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {rpcAppHandler} from "@blitzjs/rpc"
import {withBlitzAuth} from "../../../../src/blitz-server"

export const {GET, POST, HEAD} = withBlitzAuth(rpcAppHandler())
38 changes: 38 additions & 0 deletions integration-tests/next-13-app-dir/app/api/signin/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {withBlitzAuth} from "../../../src/blitz-server"
import prisma from "../../../db/index"
import {Role} from "../../../types"

export const authenticateUser = async (email: string, password: string) => {
const user = await prisma.user.findFirst({where: {email}})

if (!user) throw new Error("Authentication Error")
await prisma.user.update({where: {id: user.id}, data: {hashedPassword: password}})

const {hashedPassword, ...rest} = user
return rest
}

export const {POST} = withBlitzAuth({
POST: async (request: Request, context, ctx) => {
const {searchParams} = new URL(request.url)
const user = await authenticateUser(
searchParams.get("email") as string,
searchParams.get("password") as string,
)

await ctx.session.$create({
userId: user.id,
role: user.role as Role,
})

return new Response(
JSON.stringify({email: searchParams.get("email"), userId: ctx.session.userId}),
{
status: 200,
headers: {
"Content-Type": "application/json",
},
},
)
},
})
1 change: 0 additions & 1 deletion integration-tests/next-13-app-dir/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference types="next/navigation-types/compat/navigation" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
4 changes: 2 additions & 2 deletions integration-tests/next-13-app-dir/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"@prisma/client": "4.6.1",
"blitz": "2.0.10",
"lowdb": "3.0.0",
"next": "canary",
"next": "14.3.0-canary.28",
"prisma": "4.6.1",
"react": "18.2.0",
"react-dom": "18.2.0",
Expand All @@ -45,6 +45,6 @@
"node-fetch": "3.2.3",
"playwright": "1.28.0",
"ts-node": "10.9.1",
"typescript": "^4.8.4"
"typescript": "^4.9.5"
}
}
9 changes: 0 additions & 9 deletions integration-tests/next-13-app-dir/pages/api/logout.ts

This file was deleted.

5 changes: 0 additions & 5 deletions integration-tests/next-13-app-dir/pages/api/noauth.ts

This file was deleted.

This file was deleted.

Loading

0 comments on commit 3b10b13

Please sign in to comment.