mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-11 20:00:23 +01:00
108 lines
2.9 KiB
TypeScript
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
|
|
}
|
|
}
|