Implement Turbo Workspaces, among other things

This commit is contained in:
Amruth Pillai
2022-08-21 22:18:12 +02:00
parent 73af4a6859
commit 0630369087
35 changed files with 569 additions and 50703 deletions

View File

@ -1,22 +1,19 @@
FROM node:lts-alpine as dependencies
RUN apk add --no-cache g++ curl make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
FROM node:lts-alpine AS base
WORKDIR /app
COPY package.json pnpm-*.yaml ./
RUN apk add --no-cache g++ git curl make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
FROM base AS dependencies
COPY package.json pnpm-*.yaml turbo.json ./
COPY ./schema/package.json ./schema/package.json
COPY ./server/package.json ./server/package.json
RUN pnpm install --frozen-lockfile
FROM node:lts-alpine as builder
RUN apk add --no-cache g++ curl make python3 \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
WORKDIR /app
FROM base AS builder
COPY . .
@ -24,25 +21,25 @@ COPY --from=dependencies /app/node_modules ./node_modules
COPY --from=dependencies /app/schema/node_modules ./schema/node_modules
COPY --from=dependencies /app/server/node_modules ./server/node_modules
RUN pnpm run build:schema
RUN pnpm run build:server
RUN pnpm run build --filter server
FROM mcr.microsoft.com/playwright:focal as production
FROM mcr.microsoft.com/playwright:next-jammy as production
WORKDIR /app
RUN apt-get update \
&& apt-get install -y curl \
&& apt-get install -y curl build-essential \
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
COPY --from=builder /app/pnpm-*.yaml ./
COPY --from=builder /app/package.json ./
COPY --from=builder /app/package.json /app/pnpm-*.yaml /app/turbo.json ./
COPY --from=builder /app/server/package.json ./server/package.json
RUN pnpm install -F server --frozen-lockfile --prod
RUN npx playwright install --with-deps chromium
RUN pnpm install --filter server --prod --frozen-lockfile --workspace-root
COPY --from=builder /app/server/dist ./server/dist
VOLUME /app/server/dist/assets/exports
VOLUME /app/server/dist/assets/uploads
EXPOSE 3100
@ -52,4 +49,4 @@ ENV PORT 3100
HEALTHCHECK --interval=30s --timeout=20s --retries=3 --start-period=15s \
CMD curl -fSs localhost:3100/health || exit 1
CMD [ "pnpm", "run", "start:server" ]
CMD [ "pnpm", "run", "start", "--filter", "server" ]

View File

@ -1,13 +1,10 @@
{
"name": "@reactive-resume/server",
"scripts": {
"dev": "nest start --watch",
"build": "rimraf dist && nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint --fix --ext .ts ./src"
"debug": "nest start --debug --watch",
"start": "node dist/main"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.154.0",
@ -25,7 +22,7 @@
"@nestjs/typeorm": "^9.0.1",
"@sendgrid/mail": "^7.7.0",
"@types/passport": "^1.0.10",
"bcrypt": "^5.0.1",
"bcryptjs": "^2.4.3",
"cache-manager": "^4.1.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
@ -54,7 +51,7 @@
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.1",
"@reactive-resume/schema": "workspace:*",
"@types/bcrypt": "^5.0.0",
"@types/bcryptjs": "^2.4.2",
"@types/cookie-parser": "^1.4.3",
"@types/express": "^4.17.13",
"@types/lodash": "^4.14.184",
@ -62,7 +59,6 @@
"@types/node": "^18.7.8",
"@types/passport-jwt": "^3.0.6",
"@types/passport-local": "^1.0.34",
"eslint": "^8.22.0",
"prettier": "^2.7.1",
"source-map-support": "^0.5.21",
"ts-loader": "^9.3.1",

View File

@ -2,8 +2,7 @@ import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { SchedulerRegistry } from '@nestjs/schedule';
import bcrypt from 'bcrypt';
import { randomInt } from 'crypto';
import { compareSync, hashSync } from 'bcryptjs';
import { OAuth2Client } from 'google-auth-library';
import { PostgresErrorCode } from '@/database/errorCodes.enum';
@ -24,12 +23,12 @@ export class AuthService {
) {}
async register(registerDto: RegisterDto) {
const hashedPassword = await bcrypt.hash(registerDto.password, randomInt(8, 12));
const password = hashSync(registerDto.password);
try {
const createdUser = await this.usersService.create({
...registerDto,
password: hashedPassword,
password,
provider: 'email',
});
@ -43,6 +42,17 @@ export class AuthService {
}
}
async verifyPassword(password: string, hashedPassword: string) {
const isPasswordMatching = compareSync(password, hashedPassword);
if (!isPasswordMatching) {
throw new HttpException(
'The username/email and password combination provided was incorrect.',
HttpStatus.UNAUTHORIZED
);
}
}
async getUser(identifier: string, password: string) {
try {
const user = await this.usersService.findByIdentifier(identifier);
@ -58,27 +68,17 @@ export class AuthService {
}
}
async verifyPassword(password: string, hashedPassword: string) {
const isPasswordMatching = await bcrypt.compare(password, hashedPassword);
if (!isPasswordMatching) {
throw new HttpException(
'The username/email and password combination provided was incorrect.',
HttpStatus.UNAUTHORIZED
);
}
}
forgotPassword(email: string) {
return this.usersService.generateResetToken(email);
}
async resetPassword(resetPasswordDto: ResetPasswordDto) {
const user = await this.usersService.findByResetToken(resetPasswordDto.resetToken);
const hashedPassword = await bcrypt.hash(resetPasswordDto.password, randomInt(8, 12));
const password = hashSync(resetPasswordDto.password);
await this.usersService.update(user.id, {
password: hashedPassword,
password,
resetToken: null,
});

View File

@ -12,8 +12,6 @@ export class HealthController {
@Get()
@HealthCheck()
check() {
return this.health.check([
() => this.db.pingCheck('database'),
]);
return this.health.check([() => this.db.pingCheck('database')]);
}
}

View File

@ -3,33 +3,33 @@
"exclude": ["dist"],
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "dist",
"baseUrl": ".",
"sourceMap": true,
"declaration": true,
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"removeComments": true,
"strictNullChecks": false,
"resolveJsonModule": true,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noFallthroughCasesInSwitch": false,
"baseUrl": ".",
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": false,
"paths": {
"@/auth/*": ["src/auth/*"],
"@/config/*": ["src/config/*"],
"@/constants/*": ["src/constants/*"],
"@/database/*": ["src/database/*"],
"@/decorators/*": ["src/decorators/*"],
"@/filters/*": ["src/filters/*"],
"@/mail/*": ["src/mail/*"],
"@/users/*": ["src/users/*"],
"@/config/*": ["src/config/*"],
"@/resume/*": ["src/resume/*"],
"@/users/*": ["src/users/*"]
"@/filters/*": ["src/filters/*"],
"@/database/*": ["src/database/*"],
"@/constants/*": ["src/constants/*"],
"@/decorators/*": ["src/decorators/*"]
}
}
}