beerman
beerman
CCConvex Community
Created by beerman on 1/21/2025 in #support-community
Not getting indexRange callback type
Hey all, I'm having an issue with one of my queries where the type of q inside withIndex is not being inferred. Did I miss something?
export const getSpins = query({
args: {
limit: v.optional(v.number()),
before: v.optional(v.number()),
after: v.optional(v.number()),
},
handler: async (ctx, args) => {
// base query using timestamp index
const query = await ctx.db
.query("spins")
.withIndex("by_timestamp", (q) => {
// Build query based on provided arguments
if (args.after && args.before) {
// Range query
q = q.gte("timestamp", args.after).lt("timestamp", args.before);
} else if (args.after) {
q = q.gte("timestamp", args.after);
} else if (args.before) {
q = q.lt("timestamp", args.before);
}
})
.order("desc")
.take(args.limit || 10000);

return query;
},
});
export const getSpins = query({
args: {
limit: v.optional(v.number()),
before: v.optional(v.number()),
after: v.optional(v.number()),
},
handler: async (ctx, args) => {
// base query using timestamp index
const query = await ctx.db
.query("spins")
.withIndex("by_timestamp", (q) => {
// Build query based on provided arguments
if (args.after && args.before) {
// Range query
q = q.gte("timestamp", args.after).lt("timestamp", args.before);
} else if (args.after) {
q = q.gte("timestamp", args.after);
} else if (args.before) {
q = q.lt("timestamp", args.before);
}
})
.order("desc")
.take(args.limit || 10000);

return query;
},
});
6 replies
CCConvex Community
Created by beerman on 1/18/2025 in #support-community
getting type of query
+page.svelte
const accounts = useQuery(api.accounts.list, {});
const accounts = useQuery(api.accounts.list, {});
component
interface Props {
accounts: ;
}
let { accounts }: Props = $props();
interface Props {
accounts: ;
}
let { accounts }: Props = $props();
FunctionReturnType<api.accounts.list> returns the type of the data but doesn't include the query states. And UsePaginatedQueryReturnType<api.accounts.list> creates a type mismatch. What's the correct way to do this?
4 replies
CCConvex Community
Created by beerman on 1/17/2025 in #support-community
Type Mismatch in Update Mutation with Optional Fields
I’m running into a type mismatch issue when updating an account using a mutation. Simplified version of my setup: schema.ts
export const account = v.object({
name: v.string(),
type: accountType,
balance: v.number(),
totalDeposited: v.number(),
totalWithdrawn: v.number(),
profitLoss: v.number(),
commission: v.number(),
notes: v.string(),
isActive: v.boolean()
});
export const account = v.object({
name: v.string(),
type: accountType,
balance: v.number(),
totalDeposited: v.number(),
totalWithdrawn: v.number(),
profitLoss: v.number(),
commission: v.number(),
notes: v.string(),
isActive: v.boolean()
});
accounts.ts
onst { type, ...updates } = account.fields;

export const update = mutation({
args: v.object({
accountId: v.id('accounts'),
...updates
}),
handler: async (ctx, args) => {
const { accountId, ...updates } = args;
await ctx.db.patch(accountId, updates);
}
});
onst { type, ...updates } = account.fields;

export const update = mutation({
args: v.object({
accountId: v.id('accounts'),
...updates
}),
handler: async (ctx, args) => {
const { accountId, ...updates } = args;
await ctx.db.patch(accountId, updates);
}
});
component
async function handleUpdateAccount(
accountId: Id<'accounts'>,
updates: Partial<Omit<WithoutSystemFields<Doc<'accounts'>>, 'type'>>
) {
await client.mutation(api.accounts.update, {
accountId,
...updates
});
}
async function handleUpdateAccount(
accountId: Id<'accounts'>,
updates: Partial<Omit<WithoutSystemFields<Doc<'accounts'>>, 'type'>>
) {
await client.mutation(api.accounts.update, {
accountId,
...updates
});
}
Error
Types of property 'name' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
• In the mutation, I’ve excluded the type field and allowed the remaining fields to be updated. • The handleUpdateAccount function uses Partial so only the fields that need updating are passed. • I suspect the issue is that the mutation expects all fields to be required, but I’m passing optionals. Is there a proper way to define the mutation to accept optional fields without manually marking each field as optional? Should I adjust the schema or is there a better solution to handle partial updates?
3 replies
CCConvex Community
Created by beerman on 10/5/2024 in #support-community
a little confused about getManyVia
Hey all, I have a table features which stores different feature options and joiner table property_features which connects the features to properties and has an additional details field for property specific information per feature. I'm trying to get all the property features (name, as well as the details), so I thought that getManyVia would be the best option to use, but I'm only getting the names but not the details. Have I misunderstood how this works? extract from schema
properties: defineTable({
...
})

features: defineTable({
name: v.string()
})
.index('by_name', ['name']),

property_features: defineTable({
feature_id: v.id('features'),
property_id: v.id('properties'),
details: v.optional(v.string())
})
.index('by_feature_id', ['feature_id'])
.index('by_property_id', ['property_id']),
properties: defineTable({
...
})

features: defineTable({
name: v.string()
})
.index('by_name', ['name']),

property_features: defineTable({
feature_id: v.id('features'),
property_id: v.id('properties'),
details: v.optional(v.string())
})
.index('by_feature_id', ['feature_id'])
.index('by_property_id', ['property_id']),
query
export const get = query({
args: {},
handler: async (ctx) => {
// Fetch all properties
const properties = await ctx.db.query('properties').collect();

// Fetch related data for each property
return await Promise.all(
properties.map(async (property) => {
const propertyFeatures = await getManyVia(
ctx.db,
'property_features',
'feature_id',
'by_property_id',
property._id
);

return {
propertyFeatures
};
})
);
}
});
export const get = query({
args: {},
handler: async (ctx) => {
// Fetch all properties
const properties = await ctx.db.query('properties').collect();

// Fetch related data for each property
return await Promise.all(
properties.map(async (property) => {
const propertyFeatures = await getManyVia(
ctx.db,
'property_features',
'feature_id',
'by_property_id',
property._id
);

return {
propertyFeatures
};
})
);
}
});
2 replies
CCConvex Community
Created by beerman on 10/3/2024 in #support-community
unable to query relation with getOneFrom helper
import { query } from './_generated/server';
import { getOneFrom, getAll, getManyFrom, getManyVia } from 'convex-helpers/server/relationships';

export const get = query({
args: {},
handler: async (ctx) => {
// Fetch all properties
const properties = await ctx.db.query('properties').collect();

// Fetch related data for each property
return await Promise.all(
properties.map(async (property) => {
// Fetch related data here. For example:
const propertyType = await getOneFrom(
ctx.db,
'property_type_options',
'id',
property.property_type_id
);
const propertyLocation = await getOneFrom(
ctx.db,
'property_locations',
'id',
property.property_location_id
);

// Return the property with its related data
return {
...property,
propertyType,
propertyLocation
};
})
);
}
});
import { query } from './_generated/server';
import { getOneFrom, getAll, getManyFrom, getManyVia } from 'convex-helpers/server/relationships';

export const get = query({
args: {},
handler: async (ctx) => {
// Fetch all properties
const properties = await ctx.db.query('properties').collect();

// Fetch related data for each property
return await Promise.all(
properties.map(async (property) => {
// Fetch related data here. For example:
const propertyType = await getOneFrom(
ctx.db,
'property_type_options',
'id',
property.property_type_id
);
const propertyLocation = await getOneFrom(
ctx.db,
'property_locations',
'id',
property.property_location_id
);

// Return the property with its related data
return {
...property,
propertyType,
propertyLocation
};
})
);
}
});
4 replies
CCConvex Community
Created by beerman on 10/1/2024 in #support-community
struggling with mutation
I'm trying to infer a type from my schema in order to type locationData which I will pass to the mutation but I keep getting the following error:
src/convex/addCompleteProperty.ts|7 col 23-62 error| Type 'TableDefinition<VObject<{ district?: string | undefined; city?: string | undefined; area?: string | undefined; postal_code?: string | undefined; nearest_landmark?: string | undefined; latitude?: number | undefined; longitude?: number | undefined; country: string; province: string; address: string; }, { ...; }, "requ...' does not satisfy the constraint 'Validator<any, OptionalProperty, any>'.
import { mutation } from './_generated/server';
import schema from './schema';
import { Infer } from 'convex/values';

type Location = Infer<typeof schema.tables.property_locations>;

export default mutation(
async ({ db }, { propertyData, locationData, features, amenities, views }) => {
// Insert or find the location
const location = await db
.query('property_locations')
.withIndex('by_province', (q) => q.eq('province', locationData.province))
.first();
}))
...
import { mutation } from './_generated/server';
import schema from './schema';
import { Infer } from 'convex/values';

type Location = Infer<typeof schema.tables.property_locations>;

export default mutation(
async ({ db }, { propertyData, locationData, features, amenities, views }) => {
// Insert or find the location
const location = await db
.query('property_locations')
.withIndex('by_province', (q) => q.eq('province', locationData.province))
.first();
}))
...
Here's the relevant section of my schema
export default defineSchema({
property_locations: defineTable({
country: v.string(),
province: v.string(),
district: v.optional(v.string()),
city: v.optional(v.string()),
area: v.optional(v.string()),
postal_code: v.optional(v.string()),
address: v.string(),
nearest_landmark: v.optional(v.string()),
latitude: v.optional(v.number()),
longitude: v.optional(v.number())
})
.index('by_province', ['province'])
.index('by_district', ['district'])
.index('by_city', ['city'])
.index('by_city_area', ['city', 'area'])
.index('by_country', ['country'])
});
export default defineSchema({
property_locations: defineTable({
country: v.string(),
province: v.string(),
district: v.optional(v.string()),
city: v.optional(v.string()),
area: v.optional(v.string()),
postal_code: v.optional(v.string()),
address: v.string(),
nearest_landmark: v.optional(v.string()),
latitude: v.optional(v.number()),
longitude: v.optional(v.number())
})
.index('by_province', ['province'])
.index('by_district', ['district'])
.index('by_city', ['city'])
.index('by_city_area', ['city', 'area'])
.index('by_country', ['country'])
});
Where did I go wrong?
238 replies