hyperzone
hyperzone12mo ago

using zCustomMutation with convex-ents

How can I create a zMutation I can use from a mutation with a customCtx? I'm using this from the saas-starter:
export const mutation = customMutation(
baseMutation,
customCtx(async (baseCtx) => {
return await mutationCtx(baseCtx);
})
);

async function mutationCtx(baseCtx: BaseMutationCtx) {
const ctx = {
...baseCtx,
db: undefined,
table: entsTableFactory(baseCtx, entDefinitions),
};
const identity = await ctx.auth.getUserIdentity();
const viewer =
identity === null
? null
: await ctx.table("users").get("clerkUserId", identity.subject);
// .get("tokenIdentifier", identity.tokenIdentifier);
const viewerX = () => {
if (viewer === null) {
throw new Error("Expected authenticated viewer");
}
return viewer;
};
return { ...ctx, viewer, viewerX };
}
export const mutation = customMutation(
baseMutation,
customCtx(async (baseCtx) => {
return await mutationCtx(baseCtx);
})
);

async function mutationCtx(baseCtx: BaseMutationCtx) {
const ctx = {
...baseCtx,
db: undefined,
table: entsTableFactory(baseCtx, entDefinitions),
};
const identity = await ctx.auth.getUserIdentity();
const viewer =
identity === null
? null
: await ctx.table("users").get("clerkUserId", identity.subject);
// .get("tokenIdentifier", identity.tokenIdentifier);
const viewerX = () => {
if (viewer === null) {
throw new Error("Expected authenticated viewer");
}
return viewer;
};
return { ...ctx, viewer, viewerX };
}
I don't know if it's correct but I'm trying to export this:
export const zMutation = zCustomMutation(mutation, NoOp);
export const zMutation = zCustomMutation(mutation, NoOp);
but I'm getting a gigantic TS error and I'm pretty sure it's because it expects the db property on the context
5 Replies
hyperzone
hyperzoneOP12mo ago
If I try to go with this:
export const zMutation = zCustomMutation(
baseMutation,
customCtx(async (baseCtx) => {
return await mutationCtx(baseCtx);
})
);
export const zMutation = zCustomMutation(
baseMutation,
customCtx(async (baseCtx) => {
return await mutationCtx(baseCtx);
})
);
wherever I try to use zMutation the context is of type 'never'
ian
ian12mo ago
Chatted offline - the issue was likely around having z.record as the validator. z.record is not supported. v.record is not officially supported. The suggested approach is something like recordToListOfObjects something like Object.entries(myRecord).map(([key, valu]) => { key, value }) and on the other end like Object.fromEntries(listOfObjects.map(({key, value}) => [key, value]))
hyperzone
hyperzoneOP12mo ago
Thanks Ian 👍 Besides changing the mutation argument to:
name: v.array(
v.object({
key: v.string(),
value: v.string(),
})
),
name: v.array(
v.object({
key: v.string(),
value: v.string(),
})
),
will I also have to change my schema from
name: v.object({})
name: v.object({})
to an array of objects? Is it possible to have the name be an object I can push anything to? since records are not supported I guess having name be name: v.any() ?
ian
ian12mo ago
You can make one validator object and share it:
const stringWithTranslations = v.array(
v.object({
key: v.string(),
value: v.string(),
})
);
const stringWithTranslations = v.array(
v.object({
key: v.string(),
value: v.string(),
})
);
And use it both in arguments and in the table def:
items: defineTable({
name: stringWithTranslations,
price: v.number(),
});

...

args: { name: stringWithTranslations }
items: defineTable({
name: stringWithTranslations,
price: v.number(),
});

...

args: { name: stringWithTranslations }
Make sense @hyperzone ? You can also use v.any() and cast, but the type hints are nice Aside: the zCustomMutation shouldn't be returning never when using a z.record. It'll fail at runtime but the types right now don't help you catch unsupported zod validators. Michal is looking into why Ents and zCustomMutation don't play well together.
hyperzone
hyperzoneOP12mo ago
Yes it makes sense thank you!

Did you find this page helpful?