1
import { UserJSON } from '@clerk/backend';
2
import { currentUser } from '@clerk/nextjs/server';
3
import { z } from 'zod';
5
import { enableClerk } from '@/const/auth';
6
import { MessageModel } from '@/database/server/models/message';
7
import { SessionModel } from '@/database/server/models/session';
8
import { UserModel, UserNotFoundError } from '@/database/server/models/user';
9
import { authedProcedure, router } from '@/libs/trpc';
10
import { UserService } from '@/server/services/user';
11
import { UserGuideSchema, UserInitializationState, UserPreference } from '@/types/user';
13
const userProcedure = authedProcedure.use(async (opts) => {
15
ctx: { userModel: new UserModel() },
19
export const userRouter = router({
20
getUserState: userProcedure.query(async ({ ctx }): Promise<UserInitializationState> => {
21
let state: Awaited<ReturnType<UserModel['getUserState']>> | undefined;
23
// get or create first-time user
26
state = await ctx.userModel.getUserState(ctx.userId);
28
if (enableClerk && error instanceof UserNotFoundError) {
29
const user = await currentUser();
31
const userService = new UserService();
33
await userService.createUser(user.id, {
34
created_at: user.createdAt,
35
email_addresses: user.emailAddresses.map((e) => ({
36
email_address: e.emailAddress,
39
first_name: user.firstName,
41
image_url: user.imageUrl,
42
last_name: user.lastName,
43
phone_numbers: user.phoneNumbers.map((e) => ({
45
phone_number: e.phoneNumber,
47
primary_email_address_id: user.primaryEmailAddressId,
48
primary_phone_number_id: user.primaryPhoneNumberId,
49
username: user.username,
59
const messageModel = new MessageModel(ctx.userId);
60
const messageCount = await messageModel.count();
62
const sessionModel = new SessionModel(ctx.userId);
63
const sessionCount = await sessionModel.count();
66
canEnablePWAGuide: messageCount >= 4,
67
canEnableTrace: messageCount >= 4,
68
// 有消息,或者创建过助手,则认为有 conversation
69
hasConversation: messageCount > 0 || sessionCount > 1,
71
// always return true for community version
72
isOnboard: state.isOnboarded || true,
73
preference: state.preference as UserPreference,
74
settings: state.settings,
79
makeUserOnboarded: userProcedure.mutation(async ({ ctx }) => {
80
return ctx.userModel.updateUser(ctx.userId, { isOnboarded: true });
83
resetSettings: userProcedure.mutation(async ({ ctx }) => {
84
return ctx.userModel.deleteSetting(ctx.userId);
87
updateGuide: userProcedure.input(UserGuideSchema).mutation(async ({ ctx, input }) => {
88
return ctx.userModel.updateGuide(ctx.userId, input);
91
updatePreference: userProcedure.input(z.any()).mutation(async ({ ctx, input }) => {
92
return ctx.userModel.updatePreference(ctx.userId, input);
95
updateSettings: userProcedure
96
.input(z.object({}).passthrough())
97
.mutation(async ({ ctx, input }) => {
98
return ctx.userModel.updateSetting(ctx.userId, input);
102
export type UserRouter = typeof userRouter;