Coffee11
Coffee11
CCConvex Community
Created by Coffee11 on 6/22/2024 in #support-community
Image compression integration
Has anyone implemented a middleware to optimize images before uploading to Convex, for example, using the TinyPNG API?
11 replies
CCConvex Community
Created by Coffee11 on 6/21/2024 in #support-community
Dynamic query
Is this how we create dynamic query in convex?
let baseQuery = ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))

if (args?.minPrice !== undefined && args.minPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.gte(q.field("price"), Number(args.minPrice))
);
}

if (args?.maxPrice !== undefined && args.maxPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.lte(q.field("price"), Number(args.maxPrice))
);
}

const results = await baseQuery.order("desc").paginate(args.paginationOpts);

const updatedPage = await Promise.all(
results.page.map(async (propertyListing) => ({
...propertyListing,
}))
);
let baseQuery = ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))

if (args?.minPrice !== undefined && args.minPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.gte(q.field("price"), Number(args.minPrice))
);
}

if (args?.maxPrice !== undefined && args.maxPrice >= 0) {
baseQuery = baseQuery.filter((q) =>
q.lte(q.field("price"), Number(args.maxPrice))
);
}

const results = await baseQuery.order("desc").paginate(args.paginationOpts);

const updatedPage = await Promise.all(
results.page.map(async (propertyListing) => ({
...propertyListing,
}))
);
it's working as expected but getting a typescript warning.
const { isLoading, results, loadMore } = usePaginatedQuery(
api.propertyListings.getPropertyListings, // <- on this part
{
listingTypeId: filters.listingTypeId as Id<"listing_types">,
properTypeId: filters.propertyTypeId as Id<"property_types">,
minPrice: filters.minPrice,
maxPrice: filters.maxPrice,
},
{
initialNumItems: 10,
}
);
const { isLoading, results, loadMore } = usePaginatedQuery(
api.propertyListings.getPropertyListings, // <- on this part
{
listingTypeId: filters.listingTypeId as Id<"listing_types">,
properTypeId: filters.propertyTypeId as Id<"property_types">,
minPrice: filters.minPrice,
maxPrice: filters.maxPrice,
},
{
initialNumItems: 10,
}
);
Argument of type 'FunctionReference<"query", "public", { minPrice?: number | undefined; maxPrice?: number | undefined; listingTypeId: Id<"listing_types">; properTypeId: Id<"property_types">; paginationOpts: { ...; }; }, { ...; }>' is not assignable to parameter of type 'PaginatedQueryReference'.
Types of property '_returnType' are incompatible.
Type '{ page: { listingType: string | undefined; propertyType: string | undefined; favorite: boolean; _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; ... 22 more ...; description: string; }[]; ... 10 more ...; [Symbol.asyncIterator](): AsyncIterator<...>; }' is missing the following properties from type 'PaginationResult<any>': isDone, continueCursorts(2345)
Argument of type 'FunctionReference<"query", "public", { minPrice?: number | undefined; maxPrice?: number | undefined; listingTypeId: Id<"listing_types">; properTypeId: Id<"property_types">; paginationOpts: { ...; }; }, { ...; }>' is not assignable to parameter of type 'PaginatedQueryReference'.
Types of property '_returnType' are incompatible.
Type '{ page: { listingType: string | undefined; propertyType: string | undefined; favorite: boolean; _id: Id<"property_listings">; _creationTime: number; pricePerSqm?: number | undefined; ... 22 more ...; description: string; }[]; ... 10 more ...; [Symbol.asyncIterator](): AsyncIterator<...>; }' is missing the following properties from type 'PaginationResult<any>': isDone, continueCursorts(2345)
8 replies
CCConvex Community
Created by Coffee11 on 6/21/2024 in #support-community
Need guidance on return types of query
Hi, I need help understanding why the return type of the given query contains null in the object return of get despite having a null check?
const userFavoriteCollections = await ctx.db
.query("favorite_listings")
.withIndex("by_user_id")
.filter((q) => q.eq(q.field("userId"), user._id))
.collect();

const userFavorites = await Promise.all(
userFavoriteCollections.map(async (userFavorite) => {
const propertyListing = await ctx.db.get(
userFavorite.propertyListingId
);

if (!propertyListing) {
return null;
}

return { ...propertyListing, favorite: true };
})
);

return userFavorites.filter((userFavorite) => userFavorite !== null);
const userFavoriteCollections = await ctx.db
.query("favorite_listings")
.withIndex("by_user_id")
.filter((q) => q.eq(q.field("userId"), user._id))
.collect();

const userFavorites = await Promise.all(
userFavoriteCollections.map(async (userFavorite) => {
const propertyListing = await ctx.db.get(
userFavorite.propertyListingId
);

if (!propertyListing) {
return null;
}

return { ...propertyListing, favorite: true };
})
);

return userFavorites.filter((userFavorite) => userFavorite !== null);
return type
const getFavoritePropertyListings: RegisteredQuery<"public", EmptyObject, Promise<({
favorite: boolean;
_id: Id<"property_listings">;
_creationTime: number;
pricePerSqm?: number | undefined;
buildingName?: string | undefined;
... 23 more ...;
description: string;
} | null)[]>>
const getFavoritePropertyListings: RegisteredQuery<"public", EmptyObject, Promise<({
favorite: boolean;
_id: Id<"property_listings">;
_creationTime: number;
pricePerSqm?: number | undefined;
buildingName?: string | undefined;
... 23 more ...;
description: string;
} | null)[]>>
but putting "!" solves the issue?
const userFavoriteCollections = await ctx.db
.query("favorite_listings")
.withIndex("by_user_id")
.filter((q) => q.eq(q.field("userId"), user._id))
.collect();

const userFavorites = await Promise.all(
userFavoriteCollections.map(async (userFavorite) => {
const propertyListing = await ctx.db.get(
userFavorite.propertyListingId
);

return { **...propertyListing!**, favorite: true };
})
);

return userFavorites.filter((userFavorite) => userFavorite !== null);
const userFavoriteCollections = await ctx.db
.query("favorite_listings")
.withIndex("by_user_id")
.filter((q) => q.eq(q.field("userId"), user._id))
.collect();

const userFavorites = await Promise.all(
userFavoriteCollections.map(async (userFavorite) => {
const propertyListing = await ctx.db.get(
userFavorite.propertyListingId
);

return { **...propertyListing!**, favorite: true };
})
);

return userFavorites.filter((userFavorite) => userFavorite !== null);
return type
const getFavoritePropertyListings: RegisteredQuery<"public", EmptyObject, Promise<{
favorite: boolean;
_id: Id<"property_listings">;
_creationTime: number;
pricePerSqm?: number | undefined;
buildingName?: string | undefined;
... 23 more ...;
description: string;
}[]>>
const getFavoritePropertyListings: RegisteredQuery<"public", EmptyObject, Promise<{
favorite: boolean;
_id: Id<"property_listings">;
_creationTime: number;
pricePerSqm?: number | undefined;
buildingName?: string | undefined;
... 23 more ...;
description: string;
}[]>>
7 replies
CCConvex Community
Created by Coffee11 on 6/20/2024 in #support-community
"in" filter keyword
How to achieve this in convex?
SELECT
employee_id,
first_name,
last_name,
department,
salary,
hire_date
FROM
employees
WHERE
employee_id IN (101, 102, 105);
SELECT
employee_id,
first_name,
last_name,
department,
salary,
hire_date
FROM
employees
WHERE
employee_id IN (101, 102, 105);
10 replies
CCConvex Community
Created by Coffee11 on 6/19/2024 in #support-community
Drop table property with index
Hi how to delete a property that has an index and data? Document with ID "k970fhqa6pzjy3cxx04esrty4s6v7bsf" in table "property_features" does not match the schema: Object contains extra field tag that is not in the validator. Object: {category: "amenities", name: "Big roads", slug: "motor-way", tag: "amenities", tags: ["condominium", "house-and-lot", "warehouse", "land"]} Validator: v.object({category: v.optional(v.string()), name: v.string(), slug: v.string(), tags: v.optional(v.array(v.string()))})
3 replies
CCConvex Community
Created by Coffee11 on 6/12/2024 in #support-community
Production with react-native?
Any tutorial similar to nextjs deployment?
11 replies
CCConvex Community
Created by Coffee11 on 6/11/2024 in #support-community
Query caching in react-native
Can the useQuery be like tanstak/react-query?
2 replies
CCConvex Community
Created by Coffee11 on 6/9/2024 in #support-community
status: Exhausted when using paginated query?
Why?
3 replies
CCConvex Community
Created by Coffee11 on 6/9/2024 in #support-community
Promise {} is not a supported Convex type in paginated query with join
Working
export const getPropertyListings = query({
args: {
listingTypeId: v.id("listing_types"),
properTypeId: v.id("property_types"),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();

if (identity === null) {
throw new Error("Not authenticated");
}

const results = await ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))
.filter((q) => q.eq(q.field("propertyType"), args.properTypeId))
.order("desc")
.paginate(args.paginationOpts);

return {
...results,
page: results.page.map((propertyListing) => ({
...propertyListing,
})),
};
},
});
export const getPropertyListings = query({
args: {
listingTypeId: v.id("listing_types"),
properTypeId: v.id("property_types"),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();

if (identity === null) {
throw new Error("Not authenticated");
}

const results = await ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))
.filter((q) => q.eq(q.field("propertyType"), args.properTypeId))
.order("desc")
.paginate(args.paginationOpts);

return {
...results,
page: results.page.map((propertyListing) => ({
...propertyListing,
})),
};
},
});
Not working
export const getPropertyListings = query({
args: {
listingTypeId: v.id("listing_types"),
properTypeId: v.id("property_types"),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();

if (identity === null) {
throw new Error("Not authenticated");
}

const results = await ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))
.filter((q) => q.eq(q.field("propertyType"), args.properTypeId))
.order("desc")
.paginate(args.paginationOpts);

return {
...results,
page: results.page.map(async (propertyListing) => ({
...propertyListing,
listingType: await ctx.db.get(propertyListing.listingType),
propertyType: await ctx.db.get(propertyListing.propertyType),
})),
};
},
});
export const getPropertyListings = query({
args: {
listingTypeId: v.id("listing_types"),
properTypeId: v.id("property_types"),
paginationOpts: paginationOptsValidator,
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();

if (identity === null) {
throw new Error("Not authenticated");
}

const results = await ctx.db
.query("property_listings")
.filter((q) => q.eq(q.field("listingType"), args.listingTypeId))
.filter((q) => q.eq(q.field("propertyType"), args.properTypeId))
.order("desc")
.paginate(args.paginationOpts);

return {
...results,
page: results.page.map(async (propertyListing) => ({
...propertyListing,
listingType: await ctx.db.get(propertyListing.listingType),
propertyType: await ctx.db.get(propertyListing.propertyType),
})),
};
},
});
4 replies
CCConvex Community
Created by Coffee11 on 6/9/2024 in #support-community
Dynamic filters?
Hi any tips how to make a dynamic query?
3 replies
CCConvex Community
Created by Coffee11 on 6/2/2024 in #support-community
Mobile and web app project
What is the best strategy if I want to use 1 convex project for my react-native and nextjs project?
18 replies
CCConvex Community
Created by Coffee11 on 6/1/2024 in #support-community
Null user in convex function when using fetchQuery
Does ctx.auth only works with client components? I'm using clerkjs Clerkjs middleware
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

const isPublicRoute = createRouteMatcher(['/sign-in(.*)', '/sign-up(.*)']);

export default clerkMiddleware(
(auth, request) => {
if (!isPublicRoute(request)) {
auth().protect();
}
},
{
debug: false,
}
);

export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

const isPublicRoute = createRouteMatcher(['/sign-in(.*)', '/sign-up(.*)']);

export default clerkMiddleware(
(auth, request) => {
if (!isPublicRoute(request)) {
auth().protect();
}
},
{
debug: false,
}
);

export const config = {
matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};
SSR
const convexUser = await fetchQuery(api.users.getUser, {
clerkId: clerkUserId!,
});
const convexUser = await fetchQuery(api.users.getUser, {
clerkId: clerkUserId!,
});
Convex function
export const getUser = query({
args: {
clerkId: v.string(),
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();

// This is null
console.log(identity);

return await ctx.db
.query('users')
.filter((q) => q.eq(q.field('clerkId'), args.clerkId))
.first();
},
});
export const getUser = query({
args: {
clerkId: v.string(),
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();

// This is null
console.log(identity);

return await ctx.db
.query('users')
.filter((q) => q.eq(q.field('clerkId'), args.clerkId))
.first();
},
});
3 replies