Show how to setup AuthContext in the docs + expose Clerk types
JUNIORCO opened this issue · 9 comments
// index.ts
import { clerkPlugin } from "elysia-clerk";
import someRoute from "./some.route";
const app = new Elysia()
.group("/private", (app) => app.use(clerkPlugin()).use(someRoute))
.listen(3000);
// some.route.ts
const someRoute = new Elysia()
.get(
"/",
// ❌ TypeScript complains here that auth and clerk don't exist
async ({ auth, clerk }) => {
...
}
);
export default someRoute;
It's known the above doesn't work, so I propose adding this code snippet to the docs:
// authContext.ts
import {
SignedInAuthObject,
SignedOutAuthObject,
} from "@clerk/backend/dist/tokens/authObjects";
import type { ClerkClient } from "elysia-clerk";
const authContext = new Elysia().resolve({ as: "scoped" }, (ctx) => {
const ctxWithAuth = ctx as unknown as {
auth: SignedInAuthObject | SignedOutAuthObject | null;
clerk: ClerkClient;
};
if (ctxWithAuth.auth === undefined) {
throw new Error("Missing auth context");
}
return { auth: ctxWithAuth.auth, clerk: ctxWithAuth.clerk };
});
export default authContext;
Which you can then use like
// some.route.ts
import authContext from "./authContext";
const someRoute = new Elysia()
.use(authContext)
.get(
"/",
// ✅ This is typed now!
async ({ auth, clerk }) => {
...
}
);
export default someRoute;
Also I'm getting the SignedInAuthObject
and SignedOutAuthObject
types from @clerk/backend/dist/tokens/authObjects
, which ideally I can get from elysia-clerk
. Any way to export those types from the lib?
Thoughts?
It's known the above doesn't work
Known issue in Elysia if I'm correct?
Also I'm getting the SignedInAuthObject and SignedOutAuthObject types from @clerk/backend/dist/tokens/authObjects, which ideally I can get from elysia-clerk. Any way to export those types from the lib?
You can import AuthObject
instead!
import { AuthObject } from 'elysia-clerk'
Nice, this works
import Elysia from "elysia";
import type { AuthObject, ClerkClient } from "elysia-clerk";
type SignedInAuthObject = Extract<AuthObject, { userId: string }>;
const authContext = new Elysia().resolve({ as: "scoped" }, (ctx) => {
const ctxWithAuth = ctx as unknown as {
auth: AuthObject | null;
clerk: ClerkClient;
};
if (!ctxWithAuth.auth?.userId) {
return ctx.error(401, "Unauthorizedd");
}
return {
auth: ctxWithAuth.auth as SignedInAuthObject,
clerk: ctxWithAuth.clerk,
};
});
export default authContext;
SignedInAuthObject
isn't exported so I had to extract it.
And yeah it's a problem with Elysia but it'd still be helpful if you just had that code snippet in the docs :) would've saved me a lot of time reading old Discord discussions
And yeah it's a problem with Elysia but it'd still be helpful if you just had that code snippet in the docs :) would've saved me a lot of time reading old Discord discussions
Thanks for confirming, yeah I'll check what I can do about that! Appreciate you coming here
Not sure if you've seen this one, but there's a InferContext
type helper from Elysia you can use:
import { Elysia, type InferContext } from 'elysia'
const app = new Elysia()
.group('/private', (app) => app.use(clerkPlugin()).use(someRoute))
.listen(3000);
export type AppContext = InferContext<typeof app>
import type { AppContext } from '../'
const someRoute = new Elysia()
.get(
'/',
async ({ auth, clerk }: AppContext) => {
...
}
);
export default someRoute
Doesn't work for me :/
// index.ts
export const app = new Elysia()
.group("/public", (app) =>
app.use(healthRoute).group("/webhooks", (app) => app.use(clerkRoute)).use(stripeRoute),
)
.group("", (app) => app.use(clerkPlugin()).use(someRoute))
.listen(config.PORT);
// appContext.ts
import { InferContext } from "elysia";
import { app } from ".";
export type AppContext = InferContext<typeof app>;
// someRoute.ts
import type { AppContext } from "./appContext";
const someRoute = new Elysia()
.get(
"/",
async ({ query }: AppContext) => {
...
},
);
export default someRoute;
I get '{ query }' is referenced directly or indirectly in its own type annotation.
Has anyone found a simpler way to achieve the above? Unfortunately using InferContext
doesn't work for me either.
Has anyone found a simpler way to achieve the above? Unfortunately using
InferContext
doesn't work for me either.
Nope, elysia limitation. Sorry
cool stuff @andrewchester1 !