8000 updated · wpcodevo/trpc-react-node-mongodb@d2e528b · GitHub
[go: up one dir, main page]

Skip to content

Commit d2e528b

Browse files
committed
updated
1 parent 5702c56 commit d2e528b

File tree

6 files changed

+292
-13
lines changed

6 files changed

+292
-13
lines changed

packages/server/src/app.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ import { getMeHandler } from './controllers/user.controller';
1717
import { deserializeUser } from './middleware/deserializeUser';
1818
import connectDB from './utils/connectDB';
1919
import customConfig from './config/default';
20+
import {
21+
createPostSchema,
22+
filterQuery,
23+
params,
24+
updatePostSchema,
25+
} from './schema/post.schema';
26+
import {
27+
createPostHandler,
28+
deletePostHandler,
29+
getPostHandler,
30+
getPostsHandler,
31+
updatePostHandler,
32+
} from './controllers/post.controller';
2033

2134
dotenv.config({ path: path.join(__dirname, './.env') });
2235

@@ -59,14 +72,38 @@ const userRouter = createRouter()
5972
resolve: ({ ctx }) => getMeHandler({ ctx }),
6073
});
6174

75+
const postRouter = createRouter()
76+
.mutation('create', {
77+
input: createPostSchema,
78+
resolve: ({ input, ctx }) => createPostHandler({ input, ctx }),
79+
})
80+
.mutation('update', {
81+
input: updatePostSchema,
82+
resolve: ({ input }) =>
83+
updatePostHandler({ paramsInput: input.params, input: input.body }),
84+
})
85+
.mutation('delete', {
86+
input: params,
87+
resolve: ({ input }) => deletePostHandler({ paramsInput: input }),
88+
})
89+
.query('getPost', {
90+
input: params,
91+
resolve: ({ input }) => getPostHandler({ paramsInput: input }),
92+
})
93+
.query('getPosts', {
94+
input: filterQuery,
95+
resolve: ({ input }) => getPostsHandler({ filterQuery: input }),
96+
});
97+
6298
const appRouter = createRouter()
6399
.query('hello', {
64100
resolve() {
65101
return { name: 'Hello World' };
66102
},
67103
})
68104
.merge('auth.', authRouter)
69-
.merge('users.', userRouter);
105+
.merge('users.', userRouter)
106+
.merge('posts.', postRouter);
70107

71108
export type AppRouter = typeof appRouter;
72109

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import { TRPCError } from '@trpc/server';
2+
import { Context } from '../app';
3+
import postModel from '../models/post.model';
4+
import {
5+
CreatePostInput,
6+
FilterQueryInput,
7+
ParamsInput,
8+
UpdatePostInput,
9+
} from '../schema/post.schema';
10+
import {
11+
createPost,
12+
deletePost,
13+
getPost,
14+
updatePost,
15+
} from '../services/post.service';
16+
import { findUserById } from '../services/user.service';
17+
18+
export const createPostHandler = async ({
19+
input,
20+
ctx,
21+
}: {
22+
input: CreatePostInput;
23+
ctx: Context;
24+
}) => {
25+
try {
26+
const userId = ctx.user!.id;
27+
const user = await findUserById(userId);
28+
29+
const post = await createPost({
30+
title: input.title,
31+
content: input.content,
32+
image: input.image,
33+
user: user._id,
34+
});
35+
36+
return {
37+
status: 'success',
38+
data: {
39+
post,
40+
},
41+
};
42+
} catch (err: any) {
43+
if (err.code === '11000') {
44+
throw new TRPCError({
45+
code: 'CONFLICT',
46+
message: 'Post with that title already exists',
47+
});
48+
}
49+
throw err;
50+
}
51+
};
52+
53+
export const getPostHandler = async ({
54+
paramsInput,
55+
}: {
56+
paramsInput: ParamsInput;
57+
}) => {
58+
try {
59+
const post = await getPost({ _id: paramsInput.postId }, { lean: true });
60+
61+
if (!post) {
62+
throw new TRPCError({
63+
code: 'NOT_FOUND',
64+
message: 'Post with that ID not found',
65+
});
66+
}
67+
68+
return {
69+
status: 'success',
70+
data: {
71+
post,
72+
},
73+
};
74+
} catch (err: any) {
75+
throw err;
76+
}
77+
};
78+
79+
export const getPostsHandler = async ({
80+
filterQuery,
81+
}: {
82+
filterQuery: FilterQueryInput;
83+
}) => {
84+
try {
85+
const limit = filterQuery.limit || 10;
86+
const page = filterQuery.page || 1;
87+
const skip = (page - 1) * limit;
88+
const posts = await postModel.find().skip(skip).limit(limit);
89+
90+
return {
91+
status: 'success',
92+
results: posts.length,
93+
data: {
94+
posts,
95+
},
96+
};
97+
} catch (err: any) {
98+
throw new TRPCError({
99+
code: 'INTERNAL_SERVER_ERROR',
100+
message: err.message,
101+
});
102+
}
103+
};
104+
105+
export const updatePostHandler = async ({
106+
paramsInput,
107+
input,
108+
}: {
109+
paramsInput: ParamsInput;
110+
input: UpdatePostInput;
111+
}) => {
112+
try {
113+
const post = await updatePost({ _id: paramsInput.postId }, input, {
114+
lean: true,
115+
});
116+
117+
if (!post) {
118+
throw new TRPCError({
119+
code: 'NOT_FOUND',
120+
message: 'Post with that ID not found',
121+
});
122+
}
123+
124+
return {
125+
status: 'success',
126+
data: {
127+
post,
128+
},
129+
};
130+
} catch (err: any) {
131+
throw err;
132+
}
133+
};
134+
135+
export const deletePostHandler = async ({
136+
paramsInput,
137+
}: {
138+
paramsInput: ParamsInput;
139+
}) => {
140+
try {
141+
const post = await deletePost({ _id: paramsInput.postId }, { lean: true });
142+
143+
if (!post) {
144+
throw new TRPCError({
145+
code: 'NOT_FOUND',
146+
message: 'Post with that ID not found',
147+
});
148+
}
149+
150+
return {
151+
status: 'success',
152+
data: null,
153+
};
154+
} catch (err: any) {
155+
throw err;
156+
}
157+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import {
2+
getModelForClass,
3+
modelOptions,
4+
prop,
5+
Ref,
6+
} from '@typegoose/typegoose';
7+
import { User } from './user.model';
8+
9+
@modelOptions({
10+
schemaOptions: {
11+
// Add createdAt and updatedAt fields
12+
timestamps: true,
13+
},
14+
})
15+
16+
// Export the Post class to be used as TypeScript type
17+
export class Post {
18+
@prop({ unique: true, required: true })
19+
title: string;
20+
21+
@prop({ required: true })
22+
content: string;
23+
24+
@prop({ default: 'default-post.png' })
25+
image: string;
26+
27+
@prop({ ref: () => User })
28+
user: Ref<User>;
29+
}
30+
31+
// Create the post model from the Post class
32+
const postModel = getModelForClass<typeof Post>(Post);
33+
export default postModel;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { number, object, string, TypeOf } from 'zod';
2+
3+
export const createPostSchema = object({
4+
title: string({
5+
required_error: 'Title is required',
6+
}),
7+
content: string({
8+
required_error: 'Content is required',
9+
}),
10+
image: string({
11+
required_error: 'Image is required',
12+
}),
13+
});
14+
15+
export const params = object({
16+
postId: string(),
17+
});
18+
19+
export const updatePostSchema = object({
20+
params,
21+
body: object({
22+
title: string(),
23+
content: string(),
24+
image: string(),
25+
}).partial(),
26+
});
27+
28+
export const filterQuery = object({
29+
limit: number().default(1),
30+
page: number().default(10),
31+
});
32+
33+
export type CreatePostInput = TypeOf<typeof createPostSchema>;
34+
export type ParamsInput = TypeOf<typeof params>;
35+
export type UpdatePostInput = TypeOf<typeof updatePostSchema>['body'];
36+
export type FilterQueryInput = TypeOf<typeof filterQuery>;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { FilterQuery, QueryOptions, UpdateQuery } from 'mongoose';
2+
import postModel, { Post } from '../models/post.model';
3+
4+
export const createPost = async (input: Partial<Post>) => {
5+
return postModel.create(input);
6+
};
7+
8+
export const getPost = async (
9+
query: FilterQuery<Post>,
10+
options?: QueryOptions
11+
) => {
12+
return postModel.findOne(query, {}, options);
13+
};
14+
15+
export const updatePost = async (
16+
query: FilterQuery<Post>,
17+
update: UpdateQuery<Post>,
18+
options: QueryOptions
19+
) => {
20+
return postModel.findOneAndUpdate(query, update, options);
21+
};
22+
23+
export const deletePost = async (
24+
query: FilterQuery<Post>,
25+
options: QueryOptions
26+
) => {
27+
return postModel.findOneAndDelete(query, options);
28+
};

packages/server/src/utils/appError.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)
0