implement backend skeleton with MongoDB and Claude AI integration
- Add controllers (Auth, Chat, Event) with placeholder implementations - Add services (Auth, Chat, Event) with business logic interfaces - Add repositories with MongoDB/Mongoose models (User, Event, Chat) - Add middleware for JWT authentication - Add Claude AI adapter implementing AIProvider interface - Add utility modules for JWT and password handling - Add shared types and DTOs for User, CalendarEvent, ChatMessage - Configure routes with proper endpoint structure - Update app.ts with dependency injection setup - Add required dependencies: mongoose, bcrypt, jsonwebtoken, @anthropic-ai/sdk
This commit is contained in:
1
apps/server/src/repositories/index.ts
Normal file
1
apps/server/src/repositories/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './mongo';
|
||||
23
apps/server/src/repositories/mongo/MongoChatRepository.ts
Normal file
23
apps/server/src/repositories/mongo/MongoChatRepository.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { ChatMessage, Conversation, CreateMessageDTO, GetMessagesOptions } from '@caldav/shared';
|
||||
import { ChatRepository } from '../../services/interfaces';
|
||||
import { ChatMessageModel, ConversationModel } from './models';
|
||||
|
||||
export class MongoChatRepository implements ChatRepository {
|
||||
// Conversations
|
||||
async getConversationsByUser(userId: string): Promise<Conversation[]> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async createConversation(userId: string): Promise<Conversation> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
// Messages (cursor-based pagination)
|
||||
async getMessages(conversationId: string, options?: GetMessagesOptions): Promise<ChatMessage[]> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async createMessage(conversationId: string, message: CreateMessageDTO): Promise<ChatMessage> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
}
|
||||
29
apps/server/src/repositories/mongo/MongoEventRepository.ts
Normal file
29
apps/server/src/repositories/mongo/MongoEventRepository.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { CalendarEvent, CreateEventDTO, UpdateEventDTO } from '@caldav/shared';
|
||||
import { EventRepository } from '../../services/interfaces';
|
||||
import { EventModel } from './models';
|
||||
|
||||
export class MongoEventRepository implements EventRepository {
|
||||
async findById(id: string): Promise<CalendarEvent | null> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async findByUserId(userId: string): Promise<CalendarEvent[]> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async findByDateRange(userId: string, startDate: Date, endDate: Date): Promise<CalendarEvent[]> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async create(userId: string, data: CreateEventDTO): Promise<CalendarEvent> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async update(id: string, data: UpdateEventDTO): Promise<CalendarEvent | null> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async delete(id: string): Promise<boolean> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
}
|
||||
17
apps/server/src/repositories/mongo/MongoUserRepository.ts
Normal file
17
apps/server/src/repositories/mongo/MongoUserRepository.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { User } from '@caldav/shared';
|
||||
import { UserRepository, CreateUserData } from '../../services/interfaces';
|
||||
import { UserModel } from './models';
|
||||
|
||||
export class MongoUserRepository implements UserRepository {
|
||||
async findById(id: string): Promise<User | null> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async findByEmail(email: string): Promise<User | null> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
async create(data: CreateUserData): Promise<User> {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
}
|
||||
3
apps/server/src/repositories/mongo/index.ts
Normal file
3
apps/server/src/repositories/mongo/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './MongoUserRepository';
|
||||
export * from './MongoEventRepository';
|
||||
export * from './MongoChatRepository';
|
||||
74
apps/server/src/repositories/mongo/models/ChatModel.ts
Normal file
74
apps/server/src/repositories/mongo/models/ChatModel.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import mongoose, { Schema, Document } from 'mongoose';
|
||||
import { ChatMessage, Conversation, CreateEventDTO } from '@caldav/shared';
|
||||
|
||||
export interface ChatMessageDocument extends Omit<ChatMessage, 'id'>, Document {}
|
||||
export interface ConversationDocument extends Omit<Conversation, 'id'>, Document {}
|
||||
|
||||
const ProposedEventSchema = new Schema<CreateEventDTO>(
|
||||
{
|
||||
title: { type: String, required: true },
|
||||
description: { type: String },
|
||||
startTime: { type: Date, required: true },
|
||||
endTime: { type: Date, required: true },
|
||||
note: { type: String },
|
||||
isRecurring: { type: Boolean },
|
||||
recurrenceRule: { type: String },
|
||||
},
|
||||
{ _id: false }
|
||||
);
|
||||
|
||||
const ChatMessageSchema = new Schema<ChatMessageDocument>(
|
||||
{
|
||||
conversationId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
sender: {
|
||||
type: String,
|
||||
enum: ['user', 'assistant'],
|
||||
required: true,
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
proposedEvent: {
|
||||
type: ProposedEventSchema,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
toJSON: {
|
||||
transform: (_, ret: Record<string, unknown>) => {
|
||||
ret.id = String(ret._id);
|
||||
delete ret._id;
|
||||
delete ret.__v;
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const ConversationSchema = new Schema<ConversationDocument>(
|
||||
{
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
toJSON: {
|
||||
transform: (_, ret: Record<string, unknown>) => {
|
||||
ret.id = String(ret._id);
|
||||
delete ret._id;
|
||||
delete ret.__v;
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export const ChatMessageModel = mongoose.model<ChatMessageDocument>('ChatMessage', ChatMessageSchema);
|
||||
export const ConversationModel = mongoose.model<ConversationDocument>('Conversation', ConversationSchema);
|
||||
56
apps/server/src/repositories/mongo/models/EventModel.ts
Normal file
56
apps/server/src/repositories/mongo/models/EventModel.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import mongoose, { Schema, Document } from 'mongoose';
|
||||
import { CalendarEvent } from '@caldav/shared';
|
||||
|
||||
export interface EventDocument extends Omit<CalendarEvent, 'id'>, Document {}
|
||||
|
||||
const EventSchema = new Schema<EventDocument>(
|
||||
{
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
trim: true,
|
||||
},
|
||||
startTime: {
|
||||
type: Date,
|
||||
required: true,
|
||||
},
|
||||
endTime: {
|
||||
type: Date,
|
||||
required: true,
|
||||
},
|
||||
note: {
|
||||
type: String,
|
||||
},
|
||||
isRecurring: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
recurrenceRule: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
toJSON: {
|
||||
transform: (_, ret: Record<string, unknown>) => {
|
||||
ret.id = String(ret._id);
|
||||
delete ret._id;
|
||||
delete ret.__v;
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
EventSchema.index({ userId: 1, startTime: 1, endTime: 1 });
|
||||
|
||||
export const EventModel = mongoose.model<EventDocument>('Event', EventSchema);
|
||||
39
apps/server/src/repositories/mongo/models/UserModel.ts
Normal file
39
apps/server/src/repositories/mongo/models/UserModel.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import mongoose, { Schema, Document } from 'mongoose';
|
||||
import { User } from '@caldav/shared';
|
||||
|
||||
export interface UserDocument extends Omit<User, 'id'>, Document {}
|
||||
|
||||
const UserSchema = new Schema<UserDocument>(
|
||||
{
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
lowercase: true,
|
||||
trim: true,
|
||||
},
|
||||
displayName: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
passwordHash: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
toJSON: {
|
||||
transform: (_, ret: Record<string, unknown>) => {
|
||||
ret.id = String(ret._id);
|
||||
delete ret._id;
|
||||
delete ret.__v;
|
||||
delete ret.passwordHash;
|
||||
return ret;
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export const UserModel = mongoose.model<UserDocument>('User', UserSchema);
|
||||
3
apps/server/src/repositories/mongo/models/index.ts
Normal file
3
apps/server/src/repositories/mongo/models/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from './UserModel';
|
||||
export * from './EventModel';
|
||||
export * from './ChatModel';
|
||||
Reference in New Issue
Block a user