Files
linsa-linsa-io/web/lib/providers/jazz-provider.tsx
Aslam H 9ced59b4f3 wip
2024-09-03 20:58:40 +07:00

108 lines
2.9 KiB
TypeScript

"use client"
import { createJazzReactApp } from "jazz-react"
import { LaAccount } from "@/lib/schema"
import { useClerk } from "@clerk/nextjs"
import { createContext, useMemo, useState } from "react"
import { AuthMethodCtx } from "jazz-react"
import { BrowserClerkAuth as X, JazzClerkAuth as Z } from "jazz-react-auth-clerk"
const Jazz = createJazzReactApp({
AccountSchema: LaAccount
})
export const { useAccount, useCoState, useAcceptInvite } = Jazz
export function JazzProvider({ children }: { children: React.ReactNode }) {
return <Jazz.Provider peer="wss://mesh.jazz.tools/?key=example@gmail.com">{children}</Jazz.Provider>
}
export const JazzClerkAuthCtx = createContext<{
errors: string[]
}>({
errors: []
})
export function JazzClerkAuth({ children }: { children: React.ReactNode }) {
const clerk = useClerk()
const [errors, setErrors] = useState<string[]>([])
const authMethod = useMemo(() => {
return new BrowserClerkAuth(
{
onError: error => {
void clerk.signOut()
setErrors(errors => [...errors, error.toString()])
}
},
clerk
)
}, [clerk])
return (
<JazzClerkAuthCtx.Provider value={{ errors }}>
<AuthMethodCtx.Provider value={authMethod}>{children}</AuthMethodCtx.Provider>
</JazzClerkAuthCtx.Provider>
)
}
import { Account, AuthMethod, AuthResult, ID } from "jazz-tools"
import type { LoadedClerk } from "@clerk/types"
import { AgentSecret } from "cojson"
export class BrowserClerkAuth implements AuthMethod {
constructor(
public driver: BrowserClerkAuth.Driver,
private readonly clerkClient: LoadedClerk
) {}
async start(): Promise<AuthResult> {
if (this.clerkClient.user) {
const storedCredentials = this.clerkClient.user.unsafeMetadata
if (storedCredentials.jazzAccountID) {
if (!storedCredentials.jazzAccountSecret) {
throw new Error("No secret for existing user")
}
return {
type: "existing",
credentials: {
accountID: storedCredentials.jazzAccountID as ID<Account>,
secret: storedCredentials.jazzAccountSecret as AgentSecret
},
onSuccess: () => {},
onError: (error: string | Error) => {
this.driver.onError(error)
}
}
} else {
return {
type: "new",
creationProps: {
name: this.clerkClient.user.fullName || this.clerkClient.user.username || this.clerkClient.user.id
},
saveCredentials: async (credentials: { accountID: ID<Account>; secret: AgentSecret }) => {
await this.clerkClient.user?.update({
unsafeMetadata: {
jazzAccountID: credentials.accountID,
jazzAccountSecret: credentials.secret
}
})
},
onSuccess: () => {},
onError: (error: string | Error) => {
this.driver.onError(error)
}
}
}
} else {
throw new Error("Not signed in")
}
}
}
export namespace BrowserClerkAuth {
export interface Driver {
onError: (error: string | Error) => void
}
}