Skip to content

Commit

Permalink
Migrate to prisma and fastify
Browse files Browse the repository at this point in the history
  • Loading branch information
typeofweb committed Jun 13, 2022
1 parent 1305f5b commit 66debae
Show file tree
Hide file tree
Showing 22 changed files with 5,018 additions and 34 deletions.
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# These are supported funding model platforms

github: [typeofweb]
patreon: # Replace with a single Patreon username
open_collective: typeofweb
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env
.env.local
.env.development.local
.env.test.local
Expand Down
22 changes: 22 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"search.exclude": {
"**/node_modules": true,
".next": true
},
"typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"workbench.colorCustomizations": {
"titleBar.activeBackground": "#673ab7",
"titleBar.inactiveBackground": "#401886",
"titleBar.activeForeground": "#ffffff",
"titleBar.inactiveForeground": "#ffffff"
},
"typescript.preferences.importModuleSpecifierEnding": "js",
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
}
}
3 changes: 3 additions & 0 deletions apps/api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
# Keep environment variables out of version control
.env
11 changes: 11 additions & 0 deletions apps/api/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: '3'

services:
devfaq_db:
image: postgres:11-alpine
ports:
- '5432:5432'
environment:
POSTGRES_USER: 'postgres'
POSTGRES_DB: 'database_development'
POSTGRES_PASSWORD: 'api2022'
11 changes: 11 additions & 0 deletions apps/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { fastify } from './server.js';

const start = async () => {
try {
await fastify.listen({ port: 3001, host: '127.0.0.1' });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}
};
start();
20 changes: 20 additions & 0 deletions apps/api/modules/db/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PrismaClient } from '@prisma/client';
import type { FastifyPluginAsync } from 'fastify';
import FP from 'fastify-plugin';

declare module 'fastify' {
interface FastifyInstance {
db: PrismaClient;
}
}

const db: FastifyPluginAsync = async (fastify, options) => {
const prisma = new PrismaClient();

fastify.addHook('onClose', () => prisma.$disconnect());
fastify.decorate('db', prisma);
};

const dbPlugin = FP(db);

export default dbPlugin;
75 changes: 75 additions & 0 deletions apps/api/modules/questions/questions.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
import { FastifyPluginAsync } from 'fastify';
import { getQuestionsSchema } from './questions.schemas.js';

// method: 'GET',
// path: '/questions',

// method: 'POST',
// path: '/questions',

// method: 'PATCH',
// path: '/questions/{id}',

// method: 'GET',
// path: '/questions/{id}',

// method: 'DELETE',
// path: '/questions/{id}',

const questionsPlugin: FastifyPluginAsync = async (fastify) => {
fastify.withTypeProvider<TypeBoxTypeProvider>().route({
url: '/questions',
method: 'GET',
schema: getQuestionsSchema,
async handler(request, reply) {
// const currentUser = getCurrentUser(request);

const { category, level, status, limit, offset, order, orderBy } = request.query;

const where = {
...(category && { categoryId: category }),
...(level && { levelId: { in: level } }),
// ...(status && isAdmin(request) ? { _statusId: status } : { _statusId: 'accepted' }),
...{ statusId: 'accepted' },
};

// @todo also get votes
const [total, questions] = await Promise.all([
fastify.db.question.count({
where,
}),
fastify.db.question.findMany({
where,
take: limit,
skip: offset,
...(order &&
orderBy && {
orderBy: {
[order]: orderBy,
},
}),
}),
]);

const data = questions.map((q) => {
return {
id: q.id,
question: q.question,
_categoryId: q.categoryId,
_levelId: q.levelId,
_statusId: q.statusId,
acceptedAt: q.acceptedAt?.toISOString(),
votesCount: 0,
currentUserVotedOn: false,
// votesCount: q.votesCount,
// currentUserVotedOn: q.didUserVoteOn,
};
});

return { data, meta: { total } };
},
});
};

export default questionsPlugin;
44 changes: 44 additions & 0 deletions apps/api/modules/questions/questions.schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Type, Static } from '@sinclair/typebox';

const getQuestionsQuerySchema = Type.Object({
category: Type.Optional(Type.String()),
status: Type.Optional(Type.String()),
level: Type.Optional(Type.Array(Type.String(), { minItems: 1 })),
limit: Type.Optional(Type.Integer()),
offset: Type.Optional(Type.Integer()),
orderBy: Type.Optional(
Type.Union([Type.Literal('acceptedAt'), Type.Literal('level'), Type.Literal('votesCount')])
),
order: Type.Optional(Type.Union([Type.Literal('asc'), Type.Literal('desc')])),
});
export type GetQuestionsOrderBy = Static<typeof getQuestionsQuerySchema>['orderBy'];
export type GetQuestionsOrder = Static<typeof getQuestionsQuerySchema>['order'];

const questionShape = {
id: Type.Integer(),
question: Type.String(),
_categoryId: Type.String(),
_levelId: Type.String(),
_statusId: Type.String(),
acceptedAt: Type.Optional(Type.String({ format: 'date-time' })),
} as const;

const questionResponseSchema = Type.Object({
...questionShape,
votesCount: Type.Integer(),
currentUserVotedOn: Type.Boolean(),
});

const getQuestionsResponseSchema = Type.Object({
data: Type.Array(questionResponseSchema),
meta: Type.Object({
total: Type.Integer(),
}),
});

export const getQuestionsSchema = {
querystring: getQuestionsQuerySchema,
response: {
200: getQuestionsResponseSchema,
},
} as const;
11 changes: 11 additions & 0 deletions apps/api/nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"restartable": "rs",
"ignore": [
".git",
"node_modules/**/node_modules"
],
"execMap": {
"ts": "node --loader ts-node/esm"
},
"ext": "ts,js,json"
}
Loading

0 comments on commit 66debae

Please sign in to comment.