build(v3): use pnpm, docker, docker-compose to orchestrate two services (client, server)
This commit is contained in:
parent
9c1380f401
commit
938e2e8e25
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@1.7.0/schema.json",
|
||||
"changelog": "@changesets/cli/changelog",
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"ignore": [],
|
||||
"baseBranch": "v3",
|
||||
"access": "restricted",
|
||||
"updateInternalDependencies": "patch"
|
||||
}
|
|
@ -1,6 +1,18 @@
|
|||
# Build Artifacts
|
||||
dist
|
||||
.next
|
||||
Dockerfile
|
||||
|
||||
# IDEs
|
||||
.vscode
|
||||
|
||||
# Project Metadata
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
|
||||
# Project Dependencies
|
||||
node_modules
|
||||
|
||||
# Docker
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
docker-compose.yml
|
||||
docker-compose.yml
|
|
@ -1,8 +1,15 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"extends": ["plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"],
|
||||
"plugins": ["@typescript-eslint/eslint-plugin", "simple-import-sort", "unused-imports"],
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"plugins": [
|
||||
"@typescript-eslint/eslint-plugin",
|
||||
"simple-import-sort",
|
||||
"unused-imports"
|
||||
],
|
||||
"rules": {
|
||||
// TypeScript ESLint
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
|
@ -10,11 +17,9 @@
|
|||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
|
||||
// Simple Import Sort
|
||||
"simple-import-sort/imports": "error",
|
||||
"simple-import-sort/exports": "error",
|
||||
|
||||
// Unused Imports
|
||||
"no-unused-vars": "off",
|
||||
"unused-imports/no-unused-imports": "error",
|
||||
|
@ -30,10 +35,12 @@
|
|||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.js"],
|
||||
"files": [
|
||||
"*.js"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,16 +1,7 @@
|
|||
# Package Manager
|
||||
.pnp.*
|
||||
.yarn/*
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
# Project Dependencies
|
||||
node_modules
|
||||
|
||||
# Environment Variables
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
!.env.example
|
||||
|
||||
# Project Dependencies
|
||||
node_modules
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
{
|
||||
"css.validate": false,
|
||||
"scss.validate": false,
|
||||
"editor.codeActionsOnSave": { "source.fixAll.eslint": true },
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.wordWrap": "on",
|
||||
|
@ -10,5 +12,8 @@
|
|||
"i18n-ally.localesPaths": ["client/public/locales"],
|
||||
"i18n-ally.namespace": true,
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
|
||||
"i18n-ally.sortKeys": true
|
||||
"i18n-ally.sortKeys": true,
|
||||
"[jsonc]": {
|
||||
"editor.defaultFormatter": "vscode.json-language-features"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,7 +0,0 @@
|
|||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
|
||||
spec: "@yarnpkg/plugin-workspace-tools"
|
||||
|
||||
yarnPath: .yarn/releases/yarn-3.2.0.cjs
|
10
README.md
10
README.md
|
@ -43,18 +43,16 @@ git clone https://github.com/AmruthPillai/Reactive-Resume.git
|
|||
cd Reactive-Resume
|
||||
```
|
||||
|
||||
2. I prefer to use `npm`, but you can use anything to install dependencies (`pnpm`/`yarn`)
|
||||
2. I prefer to use `pnpm`, but you can use anything to install dependencies (`npm`/`yarn`)
|
||||
|
||||
```
|
||||
npm install
|
||||
pnpm install
|
||||
```
|
||||
|
||||
3. Copy the .env.example files to .env in multiple locations and fill it with values according to your setup
|
||||
3. Copy the `.env.example` file to `.env` in the project root and fill it with values according to your setup. Everything except the mail server settings are required.
|
||||
|
||||
```
|
||||
cp .env.example .env
|
||||
cp apps/client/.env.example apps/client/.env
|
||||
cp apps/server/.env.example apps/server/.env
|
||||
```
|
||||
|
||||
4. Use Docker Compose to create a PostgreSQL instance and a `reactive_resume` database, or feel free to use your own and modify the variables used in `.env`
|
||||
|
@ -66,7 +64,7 @@ docker-compose up -d
|
|||
5. Run the project and start building!
|
||||
|
||||
```
|
||||
npm start
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
# Install dependencies only when needed
|
||||
FROM node:16-alpine AS dependencies
|
||||
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN yarn set version berry
|
||||
RUN yarn plugin import workspace-tools
|
||||
|
||||
COPY package.json .yarnrc.yml yarn.lock ./
|
||||
COPY schema/package.json ./schema/package.json
|
||||
COPY client/package.json ./client/package.json
|
||||
|
||||
RUN yarn install
|
||||
|
||||
FROM node:16-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN yarn set version berry
|
||||
RUN yarn plugin import workspace-tools
|
||||
|
||||
COPY --from=dependencies /app/package.json .
|
||||
COPY --from=dependencies /app/node_modules ./node_modules
|
||||
|
||||
COPY ./schema ./schema
|
||||
COPY ./client ./client
|
||||
|
||||
RUN yarn workspace @reactive-resume/schema run build
|
||||
RUN yarn workspace @reactive-resume/client run build
|
||||
|
||||
FROM node:16-alpine AS production
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV NODE_ENV production
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
|
||||
COPY --from=builder /app/client/next.config.js ./
|
||||
COPY --from=builder /app/client/next-i18next.config.js ./
|
||||
COPY --from=builder /app/client/public ./public
|
||||
COPY --from=builder /app/client/package.json ./package.json
|
||||
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/client/.next/standalone ./
|
||||
COPY --from=builder --chown=nextjs:nodejs /app/client/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV PORT 3000
|
||||
|
||||
CMD ["node", "server.js"]
|
|
@ -0,0 +1,51 @@
|
|||
FROM node:16-alpine as dependencies
|
||||
|
||||
RUN apk add --no-cache curl g++ make python3 \
|
||||
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json pnpm-*.yaml ./
|
||||
COPY ./schema/package.json ./schema/package.json
|
||||
COPY ./client/package.json ./client/package.json
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
FROM node:16-alpine as builder
|
||||
|
||||
RUN apk add --no-cache curl g++ make python3 \
|
||||
&& curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY . .
|
||||
|
||||
COPY --from=dependencies /app/node_modules ./node_modules
|
||||
COPY --from=dependencies /app/schema/node_modules ./schema/node_modules
|
||||
COPY --from=dependencies /app/client/node_modules ./client/node_modules
|
||||
|
||||
RUN cp .env ./client/.env
|
||||
|
||||
RUN pnpm run build:schema
|
||||
RUN pnpm run build:client
|
||||
|
||||
FROM node:16-alpine as production
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache curl \
|
||||
&& 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/client/.next ./client/.next
|
||||
COPY --from=builder /app/client/public ./client/public
|
||||
COPY --from=builder /app/client/next.config.js ./client/next.config.js
|
||||
COPY --from=builder /app/client/next-i18next.config.js ./client/next-i18next.config.js
|
||||
COPY --from=builder /app/client/package.json ./client/package.json
|
||||
|
||||
RUN pnpm install -F client --frozen-lockfile --prod
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD [ "pnpm", "run", "start:client" ]
|
|
@ -1,6 +1,4 @@
|
|||
import { createTheme } from '@mui/material';
|
||||
import { grey } from '@mui/material/colors';
|
||||
import { teal } from 'tailwindcss/colors';
|
||||
|
||||
const theme = createTheme({
|
||||
typography: {
|
||||
|
@ -57,8 +55,8 @@ export const lightTheme = createTheme({
|
|||
...theme,
|
||||
palette: {
|
||||
mode: 'light',
|
||||
primary: { main: grey[800] },
|
||||
secondary: { main: teal[600] },
|
||||
primary: { main: '#404040' }, // neutral[700]
|
||||
secondary: { main: '#0d9488' }, // teal[600]
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -66,7 +64,7 @@ export const darkTheme = createTheme({
|
|||
...theme,
|
||||
palette: {
|
||||
mode: 'dark',
|
||||
primary: { main: grey[100] },
|
||||
secondary: { main: teal[400] },
|
||||
primary: { main: '#f5f5f5' }, // neutral[100]
|
||||
secondary: { main: '#2dd4bf' }, // teal[400]
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
const { version } = require('../package.json');
|
||||
const { i18n } = require('./next-i18next.config');
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
|
@ -6,20 +7,15 @@ const nextConfig = {
|
|||
|
||||
i18n,
|
||||
|
||||
env: {
|
||||
appVersion: '3.0.0',
|
||||
appUrl: process.env.APP_URL,
|
||||
serverUrl: process.env.SERVER_URL,
|
||||
googleClientId: process.env.GOOGLE_CLIENT_ID,
|
||||
},
|
||||
|
||||
images: {
|
||||
domains: ['www.gravatar.com'],
|
||||
},
|
||||
|
||||
experimental: {
|
||||
externalDir: true,
|
||||
outputStandalone: true,
|
||||
env: {
|
||||
appVersion: version,
|
||||
appUrl: process.env.APP_URL,
|
||||
serverUrl: process.env.SERVER_URL,
|
||||
googleClientId: process.env.GOOGLE_CLIENT_ID,
|
||||
},
|
||||
|
||||
// Hack to make Tailwind darkMode 'class' strategy with CSS Modules
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
"react-hotkeys-hook": "^3.4.4",
|
||||
"react-icons": "^4.3.1",
|
||||
"react-markdown": "^8.0.0",
|
||||
"react-query": "^3.34.16",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-zoom-pan-pinch": "^2.1.3",
|
||||
"redux": "^4.1.2",
|
||||
|
@ -51,7 +52,6 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.17.5",
|
||||
"@reactive-resume/schema": "workspace:^",
|
||||
"@types/downloadjs": "^1.4.3",
|
||||
"@types/lodash": "^4.14.179",
|
||||
"@types/node": "17.0.21",
|
||||
|
@ -66,9 +66,9 @@
|
|||
"eslint-config-next": "12.1.0",
|
||||
"postcss": "^8.4.7",
|
||||
"prettier": "^2.5.1",
|
||||
"react-query": "^3.34.16",
|
||||
"sass": "^1.49.9",
|
||||
"tailwindcss": "^3.0.23",
|
||||
"typescript": "<4.6.0"
|
||||
"typescript": "<4.6.0",
|
||||
"@reactive-resume/schema": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,5 +11,29 @@ services:
|
|||
- ./scripts/database/initialize.sql:/docker-entrypoint-initdb.d/initialize.sql
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
||||
server:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: server/Dockerfile
|
||||
container_name: server
|
||||
env_file: .env
|
||||
environment:
|
||||
- POSTGRES_HOST=postgres
|
||||
ports:
|
||||
- 3100:3100
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
client:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: client/Dockerfile
|
||||
container_name: client
|
||||
env_file: .env
|
||||
ports:
|
||||
- 3000:3000
|
||||
depends_on:
|
||||
- server
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
|
|
29
package.json
29
package.json
|
@ -2,29 +2,38 @@
|
|||
"name": "reactive-resume",
|
||||
"version": "3.0.0",
|
||||
"private": true,
|
||||
"packageManager": "yarn@3.2.0",
|
||||
"workspaces": [
|
||||
"schema",
|
||||
"client",
|
||||
"server"
|
||||
],
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"dev:client": "yarn workspace @reactive-resume/client run dev",
|
||||
"dev:server": "yarn workspace @reactive-resume/server run start:dev",
|
||||
"dev": "env-cmd concurrently --kill-others \"yarn:dev:*\"",
|
||||
"build": "yarn workspaces foreach run build",
|
||||
"lint": "yarn workspaces foreach run lint",
|
||||
"start:client": "yarn workspace @reactive-resume/client run start",
|
||||
"start:server": "yarn workspace @reactive-resume/server run start:prod",
|
||||
"start": "concurrently --kill-others \"yarn:start:*\""
|
||||
"dev:schema": "pnpm -F schema dev",
|
||||
"dev:server": "pnpm -F server start:dev",
|
||||
"dev:client": "pnpm -F client dev",
|
||||
"dev": "env-cmd concurrently --kill-others \"pnpm run dev:*\"",
|
||||
"build:schema": "pnpm -F schema build",
|
||||
"build:server": "pnpm -F server build",
|
||||
"build:client": "pnpm -F client build",
|
||||
"build": "env-cmd concurrently \"pnpm run build:*\"",
|
||||
"start:server": "pnpm -F server start:prod",
|
||||
"start:client": "pnpm -F client start",
|
||||
"start": "env-cmd concurrently --kill-others \"pnpm run start:*\""
|
||||
},
|
||||
"dependencies": {
|
||||
"concurrently": "^7.0.0",
|
||||
"env-cmd": "^10.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.21.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.13.0",
|
||||
"@typescript-eslint/parser": "^5.13.0",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"eslint": "^8.10.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
|
@ -32,6 +41,6 @@
|
|||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"prettier": "^2.5.1",
|
||||
"typescript": "<4.6.0"
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
packages:
|
||||
- 'schema'
|
||||
- 'server'
|
||||
- 'client'
|
|
@ -5,6 +5,7 @@
|
|||
"typings": "./dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc -w",
|
||||
"lint": "eslint --fix --ext .ts ./src"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
FROM node:16-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
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json pnpm-*.yaml ./
|
||||
COPY ./schema/package.json ./schema/package.json
|
||||
COPY ./server/package.json ./server/package.json
|
||||
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
FROM node:16-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
|
||||
|
||||
COPY . .
|
||||
|
||||
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 cp .env ./server/.env
|
||||
|
||||
RUN pnpm run build:schema
|
||||
RUN pnpm run build:server
|
||||
|
||||
FROM mcr.microsoft.com/playwright:focal as production
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN 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/server/dist ./server/dist
|
||||
COPY --from=builder /app/server/package.json ./server/package.json
|
||||
|
||||
RUN pnpm install -F server --frozen-lockfile --prod
|
||||
|
||||
EXPOSE 3100
|
||||
|
||||
CMD [ "pnpm", "run", "start:server" ]
|
|
@ -52,7 +52,6 @@
|
|||
"devDependencies": {
|
||||
"@nestjs/cli": "^8.2.2",
|
||||
"@nestjs/schematics": "^8.0.7",
|
||||
"@reactive-resume/schema": "workspace:^",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/node": "^17.0.21",
|
||||
|
@ -63,6 +62,7 @@
|
|||
"ts-node": "^10.7.0",
|
||||
"tsconfig-paths": "^3.13.0",
|
||||
"typescript": "<4.6.0",
|
||||
"webpack": "^5.70.0"
|
||||
"webpack": "^5.70.0",
|
||||
"@reactive-resume/schema": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ConfigService } from '@nestjs/config';
|
|||
import { SchedulerRegistry } from '@nestjs/schedule';
|
||||
import { mkdir, unlink, writeFile } from 'fs/promises';
|
||||
import { nanoid } from 'nanoid';
|
||||
import { join } from 'path';
|
||||
import { join, resolve } from 'path';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
import { Browser, chromium } from 'playwright-chromium';
|
||||
|
||||
|
@ -42,7 +42,7 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
|
|||
});
|
||||
|
||||
const pdf = await PDFDocument.create();
|
||||
const directory = join(__dirname, 'assets', 'resumes');
|
||||
const directory = resolve('dist/assets/resumes');
|
||||
const filename = `RxResume_PDFExport_${nanoid()}.pdf`;
|
||||
const publicUrl = `${serverUrl}/resumes/${filename}`;
|
||||
|
||||
|
|
Loading…
Reference in New Issue