Skip to content

Commit

Permalink
Add prisma and a fake new user route
Browse files Browse the repository at this point in the history
  • Loading branch information
d1str0 committed Nov 27, 2024
1 parent 19b72f0 commit 1ba51d3
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 14 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/jest-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ jobs:
run:
working-directory: ./api

services:
postgres:
image: postgres:14
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: testing
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v3
Expand All @@ -28,5 +43,15 @@ jobs:
- name: Install dependencies
run: npm install

- name: Generate Prisma Client
run: npx prisma generate

- name: Run Prisma Migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/testing?schema=public'

- name: Run Jest tests
run: npm test
env:
DATABASE_URL: 'postgresql://postgres:postgres@localhost:5432/testing?schema=public'
17 changes: 17 additions & 0 deletions api/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"license": "ISC",
"dependencies": {
"@aws-sdk/client-ec2": "^3.699.0",
"@faker-js/faker": "^9.2.0",
"@fastify/autoload": "^6.0.0",
"@fastify/sensible": "^6.0.0",
"@prisma/client": "^5.22.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
Warnings:
- Added the required column `password` to the `User` table without a default value. This is not possible if the table is not empty.
- Made the column `name` on table `User` required. This step will fail if there are existing NULL values in that column.
*/
-- AlterTable
ALTER TABLE "User" ADD COLUMN "password" TEXT NOT NULL,
ALTER COLUMN "name" SET NOT NULL;
7 changes: 4 additions & 3 deletions api/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ datasource db {
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
id Int @id @default(autoincrement())
email String @unique
name String
password String
}
2 changes: 2 additions & 0 deletions api/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ module.exports.options = options;

// Start the Fastify server
const start = async () => {
// Set logger options based on environment
const envToLogger: EnvToLogger = {
development: {
transport: {
Expand All @@ -51,6 +52,7 @@ const start = async () => {
};
const fastify = require('fastify')({
logger: envToLogger[process.env.NODE_ENV || 'development'],
ignoreTrailingSlash: true, // Ignore trailing slashes at the end of URLs
});

try {
Expand Down
25 changes: 25 additions & 0 deletions api/src/handlers/user.handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FastifyReply, FastifyRequest } from 'fastify';
import { getAllUserNames } from '../services/user.service';
import { createUser } from '../services/user.service';

export async function getUsersHandler(
request: FastifyRequest,
reply: FastifyReply,
) {
try {
reply.send(await getAllUserNames());
} catch (error) {
reply.status(500).send({ error: 'An error occurred' });
}
}
export async function createUserHandler(
request: FastifyRequest,
reply: FastifyReply,
) {
try {
const user = await createUser();
reply.status(201).send(user);
} catch (error) {
reply.status(500).send({ error: 'An error occurred' });
}
}
13 changes: 13 additions & 0 deletions api/src/lib/prisma.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { PrismaClient } from '@prisma/client';

// Prevent multiple instances in development due to hot reloading
declare global {
var prisma: PrismaClient | undefined;
}

// Create singleton instance
export const prisma = global.prisma || new PrismaClient();

if (process.env.NODE_ENV !== 'production') {
global.prisma = prisma;
}
15 changes: 15 additions & 0 deletions api/src/routes/user.route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { FastifyInstance } from 'fastify';
import { createUserHandler, getUsersHandler } from '../handlers/user.handler';

export default async function userRoutes(fastify: FastifyInstance) {
fastify.route({
method: 'GET',
url: '/user',
handler: getUsersHandler,
});
fastify.route({
method: 'POST',
url: '/user',
handler: createUserHandler,
});
}
21 changes: 21 additions & 0 deletions api/src/services/user.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { prisma } from '../lib/prisma';
import { faker } from '@faker-js/faker';

export async function getAllUserNames() {
const users = await prisma.user.findMany({
select: {
name: true,
},
});
return users.map((user) => user.name);
}
export async function createUser() {
const user = await prisma.user.create({
data: {
name: faker.person.fullName(),
email: faker.internet.email(),
password: faker.internet.password(),
},
});
return user;
}
22 changes: 11 additions & 11 deletions api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */

/* Language and Environment */
"target": "ES2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "ES2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
Expand All @@ -25,8 +25,8 @@
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */

/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */
"module": "commonjs" /* Specify what module code is generated. */,
"rootDir": "./src" /* Specify the root folder within your source files. */,
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
Expand All @@ -41,7 +41,7 @@
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
// "noUncheckedSideEffectImports": true, /* Check side effect imports. */
"resolveJsonModule": true, /* Enable importing .json files. */
"resolveJsonModule": true /* Enable importing .json files. */,
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */

Expand All @@ -58,7 +58,7 @@
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist", /* Specify an output folder for all emitted files. */
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
// "removeComments": true, /* Disable emitting comments. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
Expand All @@ -78,12 +78,12 @@
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
// "isolatedDeclarations": true, /* Require sufficient annotation on exports so other tools can trivially generate declaration files. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,

/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
Expand All @@ -93,8 +93,8 @@
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
"noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
"noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
"noUnusedLocals": true /* Enable error reporting when local variables aren't read. */,
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
Expand All @@ -106,7 +106,7 @@

/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
Expand Down

0 comments on commit 1ba51d3

Please sign in to comment.