Skip to content

Commit d06f225

Browse files
committed
feat: nitro api
1 parent a902bd1 commit d06f225

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1203
-8519
lines changed

apps/api/nitro.config.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
//https://nitro.unjs.io/config
22
export default defineNitroConfig({
3-
srcDir: "server"
3+
srcDir: "server",
4+
preset: 'heroku',
5+
routeRules: {
6+
'/api/**': { cors: true, headers: { 'access-control-allow-methods': '*' } },
7+
}
48
});

apps/api/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,23 @@
44
"build": "nitro build",
55
"dev": "nitro dev",
66
"prepare": "nitro prepare",
7-
"preview": "node .output/server/index.mjs"
7+
"preview": "node .output/server/index.mjs",
8+
"start": "node .output/server/index.mjs",
9+
"db:seed": "npx prisma db seed"
10+
},
11+
"prisma": {
12+
"seed": "npx ts-node --transpile-only ./prisma/seed.ts"
813
},
914
"devDependencies": {
15+
"@ngneat/falso": "^5.0.0",
16+
"@types": "link:@types",
17+
"jsonwebtoken": "^9.0.2",
1018
"nitropack": "latest",
1119
"prisma": "^5.18.0"
1220
},
1321
"dependencies": {
1422
"@prisma/client": "^5.18.0",
1523
"bcryptjs": "^2.4.3",
16-
"jsonwebtoken": "^9.0.2"
24+
"slugify": "^1.6.0"
1725
}
1826
}

apps/api/prisma/seed.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ export const generateComment = async (id: number, slug: string) =>
3838
addComment(randParagraph(), slug, id);
3939

4040
export const main = async () => {
41-
const users = await Promise.all(Array.from({ length: 30 }, () => generateUser()));
41+
const users = await Promise.all(Array.from({ length: 3 }, () => generateUser()));
4242
users?.map(user => user);
4343

4444
// eslint-disable-next-line no-restricted-syntax
4545
for await (const user of users) {
46-
const articles = await Promise.all(Array.from({ length: 20 }, () => generateArticle(user.id)));
46+
const articles = await Promise.all(Array.from({ length: 2 }, () => generateArticle(user.id)));
4747

4848
// eslint-disable-next-line no-restricted-syntax
4949
for await (const article of articles) {

apps/api/server/auth-event-handler.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import {default as jwt} from "jsonwebtoken";
2+
3+
export interface PrivateContext {
4+
auth: {
5+
id: number;
6+
}
7+
}
8+
9+
export function definePrivateEventHandler<T>(
10+
handler: (event: H3Event, cxt: PrivateContext) => T,
11+
options: { requireAuth: boolean } = {requireAuth: true}
12+
) {
13+
return defineEventHandler(async (event) => {
14+
// you can check request hmac, user, token, etc..
15+
const header = getHeader(event, 'authorization');
16+
let token;
17+
18+
if (
19+
(header && header.split(' ')[0] === 'Token') ||
20+
(header && header.split(' ')[0] === 'Bearer')
21+
) {
22+
token = header.split(' ')[1];
23+
}
24+
25+
if (options.requireAuth && !token) {
26+
throw createError({
27+
status: 401,
28+
statusMessage: 'Unauthorized',
29+
message: 'Missing authentication token'
30+
});
31+
}
32+
33+
if (token) {
34+
const verified = jwt.verify(token, process.env.JWT_SECRET);
35+
36+
if (!verified) {
37+
throw createError({
38+
status: 403,
39+
statusMessage: 'Unauthorized',
40+
message: 'Invalid authentication token'
41+
});
42+
}
43+
44+
return handler(event, {
45+
auth: {
46+
id: Number(verified.user.id)
47+
},
48+
})
49+
} else {
50+
return handler(event, {
51+
auth: null,
52+
})
53+
}
54+
55+
56+
})
57+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Comment } from './comment.model';
2+
3+
export interface Article {
4+
id: number;
5+
title: string;
6+
slug: string;
7+
description: string;
8+
comments: Comment[];
9+
favorited: boolean;
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Article } from './article.model';
2+
3+
export interface Comment {
4+
id: number;
5+
createdAt: Date;
6+
updatedAt: Date;
7+
body: string;
8+
article?: Article;
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class HttpException extends Error {
2+
errorCode: number;
3+
constructor(
4+
errorCode: number,
5+
public readonly message: string | any,
6+
) {
7+
super(message);
8+
this.errorCode = errorCode;
9+
}
10+
}
11+
12+
export default HttpException;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export interface Profile {
2+
username: string;
3+
bio: string;
4+
image: string;
5+
following: boolean;
6+
}

apps/api/server/models/tag.model.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface Tag {
2+
name: string;
3+
}

apps/api/server/models/user.model.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Article } from './article.model';
2+
import { Comment } from './comment.model';
3+
4+
export interface User {
5+
id: number;
6+
username: string;
7+
email: string;
8+
password: string;
9+
bio: string | null;
10+
image: any | null;
11+
articles: Article[];
12+
favorites: Article[];
13+
followedBy: User[];
14+
following: User[];
15+
comments: Comment[];
16+
demo: boolean;
17+
}

0 commit comments

Comments
 (0)