emil
emil2y ago

TypeError: client[procedureType] is not a function

Has anyone encountered this error before? I'm trying to implement an adapter for Auth.js that can communicate with my backend via tRPC proxy client but I keep getting this error for some reason. This is how i call my route:
import { client } from "../data"
export default function StorefrontApiAdapter() {
return {
async createUser(user) {
const result = await client.authorization.createUser.mutate(user)
return { ...user, id: result.id }

},
async getUser(id) {
const user = await client.authorization.getUser.query(id)
return user
},
async getUserByEmail(email) {
const user = await client.authorization.getUserByEmail.query(email)
return user
},
async getUserByAccount({ providerAccountId, provider }) {
const userByAccount = await client.authorization.getUserByAccount.query(providerAccountId)
return userByAccount
},
async linkAccount(account) {
await client.authorization.linkAccount.mutate(account)
return account
},
[...]
}
}
import { client } from "../data"
export default function StorefrontApiAdapter() {
return {
async createUser(user) {
const result = await client.authorization.createUser.mutate(user)
return { ...user, id: result.id }

},
async getUser(id) {
const user = await client.authorization.getUser.query(id)
return user
},
async getUserByEmail(email) {
const user = await client.authorization.getUserByEmail.query(email)
return user
},
async getUserByAccount({ providerAccountId, provider }) {
const userByAccount = await client.authorization.getUserByAccount.query(providerAccountId)
return userByAccount
},
async linkAccount(account) {
await client.authorization.linkAccount.mutate(account)
return account
},
[...]
}
}
And this is my client:
export const client = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: `${PUBLIC_STOREFRONT_API}/trpc`,
}),
],
})
export const client = createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: `${PUBLIC_STOREFRONT_API}/trpc`,
}),
],
})
Solution:
I used sveltekit so the setup was a bit different and backend was just normal medusa.js node application, the methods are just built like this on the client: ```ts function StorefrontApiAdapter(client: AuthClient): Adapter { return { async createUser(user) {...
Jump to solution
10 Replies
BillyBob
BillyBob9mo ago
@emil Did you ever solve this?
emil
emilOP9mo ago
Oh yeah managed in the end!
BillyBob
BillyBob9mo ago
what as the issue ? i am getting the same problem when upgrading next to anything newer than 14.1.0 or do you have a link to your repo?
emil
emilOP9mo ago
The repo is unfortunately private for work, I can check tmrw what the issue was exactly (off the top of my head it was mismatched trpc versions between my front end and backend)
BillyBob
BillyBob9mo ago
Thanks! the versions are tthe same at least in my case. Do you guys have separated BE/server and client ?
emil
emilOP9mo ago
Ooh interesting, yeah they are separate
BillyBob
BillyBob9mo ago
same Are you using NextJS? how did you setup your api/trpc/[trpc] if so because in all the examples they access the appRouter in there, but if they are separated then how can that be done
Solution
emil
emil9mo ago
I used sveltekit so the setup was a bit different and backend was just normal medusa.js node application, the methods are just built like this on the client:
function StorefrontApiAdapter(client: AuthClient): Adapter {
return {
async createUser(user) {
const userSchema = z
.object({
email: z.string(),
emailVerified: z.date().nullable(),
})
.passthrough()

const validatedUser = userSchema.safeParse(user)
if (!validatedUser.success) throw new Error("Not a valid user")

// email magic link does not give a name and image field
const result = await client.authorization.createUser.mutate({
email: validatedUser.data.email,
name: user.name ?? null,
emailVerified: validatedUser.data.emailVerified as string | null, // turns into string on the way to api
image: user.image ?? null,
})
return { ...user, id: result.id }
},

async getUser(id: string): Promise<AdapterUser | null> {
const user = await client.authorization.getUser.query(id)
return transformToAdapterUser(user)
},
//...all the methods used by authjs (did not fit into the msg)
function StorefrontApiAdapter(client: AuthClient): Adapter {
return {
async createUser(user) {
const userSchema = z
.object({
email: z.string(),
emailVerified: z.date().nullable(),
})
.passthrough()

const validatedUser = userSchema.safeParse(user)
if (!validatedUser.success) throw new Error("Not a valid user")

// email magic link does not give a name and image field
const result = await client.authorization.createUser.mutate({
email: validatedUser.data.email,
name: user.name ?? null,
emailVerified: validatedUser.data.emailVerified as string | null, // turns into string on the way to api
image: user.image ?? null,
})
return { ...user, id: result.id }
},

async getUser(id: string): Promise<AdapterUser | null> {
const user = await client.authorization.getUser.query(id)
return transformToAdapterUser(user)
},
//...all the methods used by authjs (did not fit into the msg)
and then that is imported by a the authjs middleware to be used as a custom adapter:
const handleAuth: Handle = SvelteKitAuth(async () => {
return {
secret: config.authSecret,
strategy: "jwt",
trustHost: true,
adapter: StorefrontApiAdapter(config.client),
// ...rest of the object here
const handleAuth: Handle = SvelteKitAuth(async () => {
return {
secret: config.authSecret,
strategy: "jwt",
trustHost: true,
adapter: StorefrontApiAdapter(config.client),
// ...rest of the object here
the config.client is just the tRPC
createTRPCProxyClient
createTRPCProxyClient
BillyBob
BillyBob9mo ago
thanks @emil Here is my current issue: https://discord.com/channels/867764511159091230/1221402424405790780 If you can help in any way its appreciated
emil
emilOP9mo ago
oh nice you solved it as well, very nice!