2023-09-15 22:16:21 -05:00
|
|
|
import { paginationOptsValidator } from 'convex/server';
|
2023-09-09 22:29:28 -05:00
|
|
|
import { v } from 'convex/values';
|
2023-09-11 13:49:13 -05:00
|
|
|
import { UserDto } from './../src/app/types/index';
|
2023-09-15 23:43:36 -05:00
|
|
|
import { Doc, Id } from './_generated/dataModel';
|
2023-09-11 00:40:14 -05:00
|
|
|
import {
|
|
|
|
|
QueryCtx,
|
|
|
|
|
internalMutation,
|
|
|
|
|
internalQuery,
|
|
|
|
|
query,
|
|
|
|
|
} from './_generated/server';
|
|
|
|
|
|
|
|
|
|
export async function userQuery(ctx: QueryCtx, clerkUserId: string) {
|
|
|
|
|
return await ctx.db
|
|
|
|
|
.query('users')
|
|
|
|
|
.withIndex('by_clerk_id', q => q.eq('clerkUser.id', clerkUserId))
|
|
|
|
|
.unique();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const getUserByClerkId = query({
|
|
|
|
|
args: { clerkUserId: v.string() },
|
2023-09-11 13:49:13 -05:00
|
|
|
async handler(ctx, args): Promise<UserDto | 'USER_NOT_FOUND'> {
|
2023-09-11 13:44:51 -05:00
|
|
|
const user = await userQuery(ctx, args.clerkUserId);
|
2023-09-11 00:40:14 -05:00
|
|
|
|
|
|
|
|
if (user === null) {
|
|
|
|
|
return 'USER_NOT_FOUND';
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-15 23:43:36 -05:00
|
|
|
return createUserDto(user);
|
2023-09-11 00:40:14 -05:00
|
|
|
},
|
|
|
|
|
});
|
2023-09-09 22:29:28 -05:00
|
|
|
|
2023-09-11 22:05:12 -05:00
|
|
|
export const getUserById = query({
|
|
|
|
|
args: { id: v.id('users') },
|
|
|
|
|
async handler(ctx, args): Promise<UserDto | 'USER_NOT_FOUND'> {
|
|
|
|
|
const user = await ctx.db.get(args.id);
|
|
|
|
|
|
|
|
|
|
if (user === null) {
|
|
|
|
|
return 'USER_NOT_FOUND';
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-15 23:43:36 -05:00
|
|
|
return createUserDto(user);
|
2023-09-11 22:05:12 -05:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2023-09-09 22:29:28 -05:00
|
|
|
export const getUser = internalQuery({
|
|
|
|
|
args: { subject: v.string() },
|
|
|
|
|
async handler(ctx, args) {
|
|
|
|
|
return await userQuery(ctx, args.subject);
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const updateOrCreateUser = internalMutation({
|
|
|
|
|
args: { clerkUser: v.any() },
|
2023-09-11 00:40:14 -05:00
|
|
|
async handler(ctx, { clerkUser }) {
|
2023-09-09 22:29:28 -05:00
|
|
|
const userRecord = await userQuery(ctx, clerkUser.id);
|
|
|
|
|
|
|
|
|
|
if (userRecord === null) {
|
|
|
|
|
await ctx.db.insert('users', { clerkUser });
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await ctx.db.patch(userRecord._id, { clerkUser });
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export const deleteUser = internalMutation({
|
|
|
|
|
args: { id: v.string() },
|
|
|
|
|
async handler(ctx, { id }) {
|
|
|
|
|
const userRecord = await userQuery(ctx, id);
|
|
|
|
|
|
|
|
|
|
if (userRecord === null) {
|
|
|
|
|
console.warn("can't delete user, does not exist", id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-10 20:19:31 -05:00
|
|
|
const userPosts = await ctx.db
|
|
|
|
|
.query('posts')
|
|
|
|
|
.withIndex('by_user_id', q => q.eq('userId', userRecord._id))
|
|
|
|
|
.collect();
|
|
|
|
|
|
2023-09-14 23:08:20 -05:00
|
|
|
const userLikes = await ctx.db
|
|
|
|
|
.query('likes')
|
|
|
|
|
.withIndex('by_user_post_id', q => q.eq('userId', userRecord._id))
|
|
|
|
|
.collect();
|
2023-09-10 20:19:31 -05:00
|
|
|
|
2023-09-15 17:58:22 -05:00
|
|
|
const userFollowers = await ctx.db
|
|
|
|
|
.query('follows')
|
|
|
|
|
.withIndex('by_following', q => q.eq('following', userRecord._id))
|
|
|
|
|
.collect();
|
|
|
|
|
const userFollowings = await ctx.db
|
|
|
|
|
.query('follows')
|
|
|
|
|
.withIndex('by_follower', q => q.eq('follower', userRecord._id))
|
|
|
|
|
.collect();
|
|
|
|
|
|
2023-09-14 23:08:20 -05:00
|
|
|
await Promise.all(
|
|
|
|
|
userPosts.map(async post => await ctx.db.delete(post._id))
|
|
|
|
|
);
|
2023-09-10 20:19:31 -05:00
|
|
|
|
2023-09-14 23:08:20 -05:00
|
|
|
await Promise.all(
|
|
|
|
|
userLikes.map(async like => await ctx.db.delete(like._id))
|
|
|
|
|
);
|
2023-09-10 20:19:31 -05:00
|
|
|
|
2023-09-15 17:58:22 -05:00
|
|
|
await Promise.all(
|
|
|
|
|
userFollowers.map(async follower => await ctx.db.delete(follower._id))
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
await Promise.all(
|
|
|
|
|
userFollowings.map(async following => await ctx.db.delete(following._id))
|
|
|
|
|
);
|
|
|
|
|
|
2023-09-09 22:29:28 -05:00
|
|
|
await ctx.db.delete(userRecord._id);
|
|
|
|
|
},
|
|
|
|
|
});
|
2023-09-15 22:16:21 -05:00
|
|
|
|
|
|
|
|
export const getUsersBySearchTerm = query({
|
|
|
|
|
args: { term: v.string(), paginationOpts: paginationOptsValidator },
|
|
|
|
|
handler: async (ctx, args) => {
|
2023-09-15 23:43:36 -05:00
|
|
|
const users = await ctx.db
|
2023-09-15 22:16:21 -05:00
|
|
|
.query('users')
|
|
|
|
|
.withSearchIndex('search_by_username', q =>
|
|
|
|
|
q.search('clerkUser.username', args.term)
|
|
|
|
|
)
|
|
|
|
|
.paginate(args.paginationOpts);
|
2023-09-15 23:43:36 -05:00
|
|
|
|
|
|
|
|
const userDtos = users.page.map(createUserDto);
|
|
|
|
|
|
|
|
|
|
return { ...users, page: userDtos };
|
2023-09-15 22:16:21 -05:00
|
|
|
},
|
|
|
|
|
});
|
2023-09-15 23:43:36 -05:00
|
|
|
|
|
|
|
|
export function createUserDto(user: Doc<'users'> | null) {
|
|
|
|
|
if (user === null) {
|
|
|
|
|
return {
|
|
|
|
|
_id: '' as Id<'users'>,
|
|
|
|
|
_creationTime: 0,
|
|
|
|
|
clerkUsername: null,
|
|
|
|
|
clerkImageUrl: '',
|
|
|
|
|
clerkUserId: '',
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
_id: user._id,
|
|
|
|
|
_creationTime: user._creationTime,
|
|
|
|
|
clerkUsername: user.clerkUser.username,
|
|
|
|
|
clerkImageUrl: user.clerkUser.image_url,
|
|
|
|
|
clerkUserId: user.clerkUser.id,
|
|
|
|
|
};
|
|
|
|
|
}
|