David Alonso
David Alonso
CCConvex Community
Created by David Alonso on 12/15/2024 in #support-community
`too many open files` when running `expo start` in Convex RN template
No description
2 replies
CCConvex Community
Created by David Alonso on 12/14/2024 in #support-community
Connect to multiple projects from the same nextjs app
Is this a matter of having the right imports for types and having multiple convex folders? I’m curious if anyone has tried this. Basically being able to call functions in different projects in different parts of the app. With the firestore sdk for instance you can define as many db objects as you want
33 replies
CCConvex Community
Created by David Alonso on 12/11/2024 in #support-community
Debounce calls to a mutation without doing so for the optimistic update
No description
10 replies
CCConvex Community
Created by David Alonso on 12/10/2024 in #support-community
Full-text search across fields in different tables
I'm wondering what the easiest way is to do this? I assume I can just create a search index on a new table and use triggers to denormalize data, but maybe there's a better way
10 replies
CCConvex Community
Created by David Alonso on 12/8/2024 in #support-community
dbRules functions not being triggered
I have the following:
export const dbRules: Rules<AuthQueryCtx | AuthMutationCtx, DataModel> = {
firestoreEdits: {
insert: async (ctx, edit) => {
const role = await _getExistingRoleFromUserAndOrgWorkspaceIds(ctx, {
userId: ctx.user._id,
workspaceId: ctx.workspace._id,
});
console.log("role", role);

if (role?.role === "admin") {
return true;
}
return false;
},
...
export const dbRules: Rules<AuthQueryCtx | AuthMutationCtx, DataModel> = {
firestoreEdits: {
insert: async (ctx, edit) => {
const role = await _getExistingRoleFromUserAndOrgWorkspaceIds(ctx, {
userId: ctx.user._id,
workspaceId: ctx.workspace._id,
});
console.log("role", role);

if (role?.role === "admin") {
return true;
}
return false;
},
...
And this:
export const zAuthenticatedMutation = zCustomMutation(
mutationWithTriggers, // The base function we're extending
{
args: {
// This type makes sure we can't just forget to pass the clerkOrgId
// clerkOrgId: v.union(v.string(), v.null()),
clerkOrgId: v.string(),
userTokenIdentifier: v.optional(v.string()),
},
input: async (ctx, args) => {
const { user, workspace } = await enhanceClientAuthContext(
ctx,
args.clerkOrgId,
args.userTokenIdentifier
);

// RLS wrapper
const safeDB: DatabaseWriter = wrapDatabaseWriter(
{ user, workspace, ...ctx },
ctx.db,
dbRules
);

return { ctx: { user, workspace }, db: safeDB, args: { ...args } };
},
}
);
export const zAuthenticatedMutation = zCustomMutation(
mutationWithTriggers, // The base function we're extending
{
args: {
// This type makes sure we can't just forget to pass the clerkOrgId
// clerkOrgId: v.union(v.string(), v.null()),
clerkOrgId: v.string(),
userTokenIdentifier: v.optional(v.string()),
},
input: async (ctx, args) => {
const { user, workspace } = await enhanceClientAuthContext(
ctx,
args.clerkOrgId,
args.userTokenIdentifier
);

// RLS wrapper
const safeDB: DatabaseWriter = wrapDatabaseWriter(
{ user, workspace, ...ctx },
ctx.db,
dbRules
);

return { ctx: { user, workspace }, db: safeDB, args: { ...args } };
},
}
);
I have a mutation that adds edits:
export const addEdit = zAuthenticatedMutation({
args: {
edit: zAddEditArgs,
},
handler: async (ctx, args) => {
...
export const addEdit = zAuthenticatedMutation({
args: {
edit: zAddEditArgs,
},
handler: async (ctx, args) => {
...
But when i trigger it and an edit is created I don't see any logs put inside the insert function in the rules, and it doesn't seem to be used.. How is this possible?
5 replies
CCConvex Community
Created by David Alonso on 11/30/2024 in #support-community
Underscores not allowed at start of nested fields
We've run into this issue when storing some data inside v.any() fields. This is a blocker for us cause we have to store changes of our customer's schema in Convex so it would be great to have this limit removed. If I'm missing something please let me know!
6 replies
CCConvex Community
Created by David Alonso on 11/30/2024 in #support-community
Cannot store/validate `undefined` in array?
Just making sure I'm not missing something
13 replies
CCConvex Community
Created by David Alonso on 11/29/2024 in #support-community
Exponential number of indexes required?
No description
46 replies
CCConvex Community
Created by David Alonso on 11/2/2024 in #support-community
Mutation error: `Returned promise will never resolve` caused by triggers
I've never seen this error before, and when i get rid of this trigger in my blocks mutation it goes away... The original mutation contains some promise all statements that insert docs into the blocks table Any ideas?
triggers.register("blocks", async (ctx, change) => {
if (change.operation === "insert") {
const newBlockFid = parseFid(change.newDoc.fid, "blocks");
// Try to fetch block with same fid - which will throw if there's multiple. Note that at the time of running this query the new doc is returned by the query
await _getBlockByFid(ctx, {
blockFid: newBlockFid,
});
} else if (change.operation === "update") {
// Throw an error if the fid is being updated
if (change.oldDoc.fid !== change.newDoc.fid) {
throw new ConvexError("Block FID cannot be updated");
}
}
});
triggers.register("blocks", async (ctx, change) => {
if (change.operation === "insert") {
const newBlockFid = parseFid(change.newDoc.fid, "blocks");
// Try to fetch block with same fid - which will throw if there's multiple. Note that at the time of running this query the new doc is returned by the query
await _getBlockByFid(ctx, {
blockFid: newBlockFid,
});
} else if (change.operation === "update") {
// Throw an error if the fid is being updated
if (change.oldDoc.fid !== change.newDoc.fid) {
throw new ConvexError("Block FID cannot be updated");
}
}
});
54 replies
CCConvex Community
Created by David Alonso on 10/24/2024 in #support-community
Patching convex-helpers package
I'd love to add a new type of Zod Id (similar to Zid but our own custom Fid) to my schema and have it work with zodToConvex. I'm wondering what the easiest approach would be and whether there are any docs on how to add a patch to the helpers package
59 replies
CCConvex Community
Created by David Alonso on 10/17/2024 in #support-community
Unable to push Convex functions `Function execution timed out`
The full error I'm getting is:
Error fetching POST https://sensible-salmon-524.convex.cloud/api/push_config 400 Bad Request: InvalidModules: Hit an error while pushing:
Loading the pushed modules encountered the following
error:
Function execution timed out (maximum duration: 1s)
Error fetching POST https://sensible-salmon-524.convex.cloud/api/push_config 400 Bad Request: InvalidModules: Hit an error while pushing:
Loading the pushed modules encountered the following
error:
Function execution timed out (maximum duration: 1s)
Not really sure where to start looking... Typecheck passes, schema validation passes...
56 replies
CCConvex Community
Created by David Alonso on 10/4/2024 in #support-community
immutable schema field
I guess the only way to do this atm is with a db writer wrapper? Would be a pretty useful helper imo! By marking a field as immutable, once it’s value is set it cannot be changed just to be clear
19 replies
CCConvex Community
Created by David Alonso on 9/23/2024 in #support-community
`default()` on Convex validators
.parse() and .default() are some of my favorite features of Zod validators, and it would be really great to not have to think about doing z.parse() before writing something to Convex and that Convex could automatically apply defaults specified in the schema. Is this on the roadmap?
2 replies
CCConvex Community
Created by David Alonso on 9/22/2024 in #support-community
Setting `_id` when creating documents with optimistic update
We absolutely love optimistic updates and use them heavily on our app. There's however some places where we can't use them because we would require Convex to create a document with an id that we pass it which is equal to the id of the document created optimistically. In our app, when you create a page, a document gets created and we navigate the user to pages/<doc_id> Doing this optimistically would break atm...
8 replies
CCConvex Community
Created by David Alonso on 9/21/2024 in #support-community
Buggy dashboard schema validator
See screenrecording. I briefly remove a field and add it back in but I still see errors
17 replies
CCConvex Community
Created by David Alonso on 9/20/2024 in #support-community
Infinite loading schema on dashboard / unable to push
No description
11 replies
CCConvex Community
Created by David Alonso on 9/20/2024 in #support-community
Migrations `dryRun` on multiple samples
When I run a migration in dry mode it executes on only one single document, which sometimes is skipped because it's not the instance of a document that needs to be migrated, which makes it hard to test the migration. Any suggestions?
6 replies
CCConvex Community
Created by David Alonso on 9/20/2024 in #support-community
prefix validator keys helper 🙏
I'm playing around with this code:
// Helper function to prefix object keys for the Convex validator
function prefixValidatorKeys<T extends Record<string, any>>(obj: T, prefix: z.infer<typeof zBlockType>) {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [`${prefix}_${key}`, value])
);
}

// Create the Geopoint block properties validator
export const vGeopointBlockProperties = v.object({
...vCommonProps.fields,
...prefixValidatorKeys(vGeopointSpecificProps.fields, "geopoint"),
});

// Create a type that includes both common and prefixed specific properties
type PrefixProperties<T, P extends z.infer<typeof zBlockType>> = {
[K in keyof T as `${P}_${string & K}`]: T[K]
};

export type GeopointBlockProperties =
Infer<typeof vCommonProps> &
PrefixProperties<Infer<typeof vGeopointSpecificProps>, 'geopoint'>;

const testGeopointBlock: GeopointBlockProperties = {
gridLayout: { x: 0, y: 0 },
geopoint_mapType: "roadmap",
geopoint_zoom: 10,
};
// Helper function to prefix object keys for the Convex validator
function prefixValidatorKeys<T extends Record<string, any>>(obj: T, prefix: z.infer<typeof zBlockType>) {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [`${prefix}_${key}`, value])
);
}

// Create the Geopoint block properties validator
export const vGeopointBlockProperties = v.object({
...vCommonProps.fields,
...prefixValidatorKeys(vGeopointSpecificProps.fields, "geopoint"),
});

// Create a type that includes both common and prefixed specific properties
type PrefixProperties<T, P extends z.infer<typeof zBlockType>> = {
[K in keyof T as `${P}_${string & K}`]: T[K]
};

export type GeopointBlockProperties =
Infer<typeof vCommonProps> &
PrefixProperties<Infer<typeof vGeopointSpecificProps>, 'geopoint'>;

const testGeopointBlock: GeopointBlockProperties = {
gridLayout: { x: 0, y: 0 },
geopoint_mapType: "roadmap",
geopoint_zoom: 10,
};
The part that uses regular TS types works, but I'm having issues with the validators part, namely prefixValidatorKeys. Any idea of how this could be implemented?
10 replies
CCConvex Community
Created by David Alonso on 9/18/2024 in #support-community
Dashboard - export documents that match query
No description
10 replies
CCConvex Community
Created by David Alonso on 9/1/2024 in #support-community
`withOptimisticUpdate` with custom (auth) mutations
I have the following custom mutation:
export function useAuthMutation<Mutation extends AuthFunction<"mutation">>(
name: Mutation
) {
const organization = useOrganization();
const clerkOrgId = organization?.organization?.id;
const originalMutation = useMutation(name);

return useCallback(
async (
...args: AuthArgsArray<Mutation>
): Promise<FunctionReturnType<Mutation>> => {
const newArgs = {
...(args[0] ?? {}),
clerkOrgId,
} as FunctionArgs<Mutation>;

return originalMutation(...([newArgs] as OptionalRestArgs<Mutation>));
},
[clerkOrgId, originalMutation]
);
}
export function useAuthMutation<Mutation extends AuthFunction<"mutation">>(
name: Mutation
) {
const organization = useOrganization();
const clerkOrgId = organization?.organization?.id;
const originalMutation = useMutation(name);

return useCallback(
async (
...args: AuthArgsArray<Mutation>
): Promise<FunctionReturnType<Mutation>> => {
const newArgs = {
...(args[0] ?? {}),
clerkOrgId,
} as FunctionArgs<Mutation>;

return originalMutation(...([newArgs] as OptionalRestArgs<Mutation>));
},
[clerkOrgId, originalMutation]
);
}
which automatically injects the clerkOrgId into the args. I'm unfortunately not able to do useAuthMutation().withOptimisticUpdate(). Can anyone who has worked on convex-helpers offer suggestions? 🙏
10 replies