mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-10 04:22:27 +10:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e87930c758 | |||
| 815a693e58 | |||
| 8287fcae96 | |||
| cd7fe6c404 | |||
| d47d5dd819 | |||
| 1919d79e43 | |||
| ab08cd9e34 | |||
| 2522bdd0a2 | |||
| f9b6aefffe | |||
| 2ba6658a0b | |||
| dbc46f27a3 | |||
| f21e1caed1 | |||
| 4ffe2a6330 | |||
| 1bc0438872 | |||
| 57fb9fdaea | |||
| 58ce641f18 | |||
| 5f4e7802e4 | |||
| 42d3109ae1 | |||
| f7ca7b97fa | |||
| f5d8a54134 | |||
| eaec14dc62 | |||
| c93b3264cd | |||
| bf41aa9c6c | |||
| 8af6bfd5ae | |||
| ab08c10874 | |||
| 9af9a0284e |
13
.env.example
13
.env.example
@ -1,12 +1,3 @@
|
||||
# Turbo Cache (Optional)
|
||||
TURBO_TEAM=
|
||||
TURBO_TOKEN=
|
||||
|
||||
# Sentry Error Logging (Optional)
|
||||
SENTRY_AUTH_TOKEN=
|
||||
SERVER_SENTRY_DSN=
|
||||
PUBLIC_CLIENT_SENTRY_DSN=
|
||||
|
||||
# Server + Client
|
||||
TZ=UTC
|
||||
PUBLIC_URL=http://localhost:3000
|
||||
@ -20,7 +11,7 @@ POSTGRES_PASSWORD=postgres
|
||||
|
||||
# Server
|
||||
SECRET_KEY=
|
||||
POSTGRES_HOST=postgres
|
||||
POSTGRES_HOST=localhost
|
||||
POSTGRES_PORT=5432
|
||||
POSTGRES_SSL_CERT=
|
||||
JWT_SECRET=
|
||||
@ -41,5 +32,5 @@ STORAGE_ACCESS_KEY=
|
||||
STORAGE_SECRET_KEY=
|
||||
PDF_DELETION_TIME=345600000
|
||||
|
||||
# Flags (Client)
|
||||
# Client
|
||||
PUBLIC_FLAG_DISABLE_SIGNUPS=false
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
// TypeScript ESLint
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off"
|
||||
|
||||
19
.github/workflows/docker-build-push.yml
vendored
19
.github/workflows/docker-build-push.yml
vendored
@ -10,11 +10,6 @@ jobs:
|
||||
name: Build and Push Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
image: [client, server]
|
||||
@ -56,22 +51,8 @@ jobs:
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
file: ${{ matrix.image }}/Dockerfile
|
||||
build-args: |
|
||||
TURBO_TEAM=${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TOKEN=${{ secrets.TURBO_TOKEN }}
|
||||
SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
tags: |
|
||||
amruthpillai/reactive-resume:${{ matrix.image }}-latest
|
||||
amruthpillai/reactive-resume:${{ matrix.image }}-${{ steps.version.outputs.current-version }}
|
||||
ghcr.io/amruthpillai/reactive-resume:${{ matrix.image }}-latest
|
||||
ghcr.io/amruthpillai/reactive-resume:${{ matrix.image }}-${{ steps.version.outputs.current-version }}
|
||||
|
||||
- name: Create Sentry Release
|
||||
uses: getsentry/action-release@v1.2.1
|
||||
env:
|
||||
SENTRY_ORG: reactive-resume
|
||||
SENTRY_PROJECT: ${{ matrix.image }}
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||
with:
|
||||
environment: production
|
||||
version: ${{ steps.version.outputs.current-version }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
# Environment Variables
|
||||
.env
|
||||
.env.*
|
||||
!.env.gitpod
|
||||
!.env.example
|
||||
|
||||
# Project Dependencies
|
||||
|
||||
41
.gitpod.yml
Normal file
41
.gitpod.yml
Normal file
@ -0,0 +1,41 @@
|
||||
tasks:
|
||||
- name: Run PostgreSQL Database
|
||||
command: docker run --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres -d postgres
|
||||
|
||||
- name: Install Project Dependencies
|
||||
command: |
|
||||
pnpm install
|
||||
pnpm dlx playwright install --with-deps chromium
|
||||
gp sync-done deps
|
||||
|
||||
- name: Generate Environment Variables
|
||||
init: gp sync-await deps
|
||||
command: |
|
||||
if [ -f .env ]; then
|
||||
echo "Found .env in workspace, skipping generation"
|
||||
else
|
||||
pnpm generate-env
|
||||
fi
|
||||
gp sync-done env
|
||||
|
||||
- name: Build and Run Project
|
||||
init: gp sync-await env
|
||||
command: |
|
||||
pnpm build
|
||||
pnpm start
|
||||
|
||||
ports:
|
||||
# PostgreSQL
|
||||
- port: 5432
|
||||
onOpen: ignore
|
||||
visibility: private
|
||||
|
||||
# Client
|
||||
- port: 3100
|
||||
onOpen: ignore
|
||||
visibility: public
|
||||
|
||||
# Client
|
||||
- port: 3000
|
||||
onOpen: open-browser
|
||||
visibility: public
|
||||
@ -18,7 +18,7 @@ You have complete control over what goes into your resume, how it looks, what co
|
||||
## Table of Contents
|
||||
|
||||
- [Reactive Resume](#reactive-resume)
|
||||
- [Go to App Docs](https://docs.rxresu.me)
|
||||
- [Go to App | Docs](#go-to-app--docs)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Features](#features)
|
||||
- [Languages](#languages)
|
||||
@ -104,6 +104,10 @@ The docs include an extensive [Tutorial](https://docs.rxresu.me/tutorial) sectio
|
||||
|
||||
## Build from Source
|
||||
|
||||
[](https://gitpod.io/#https://github.com/AmruthPillai/Reactive-Resume)
|
||||
|
||||
Initially building the image and project on Gitpod will take at least ~10 minutes, so please be patient on first launch.
|
||||
|
||||
For extensive information on how to build the app on your local machine, head over to the docs [Source Code](https://docs.rxresu.me/source-code) section.
|
||||
|
||||
## Contributing
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '7.1.2' apply false
|
||||
id 'com.android.library' version '7.1.2' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.21' apply false
|
||||
id 'org.jetbrains.kotlin.android' version '1.7.22' apply false
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
|
||||
3
client/.gitignore
vendored
3
client/.gitignore
vendored
@ -40,6 +40,3 @@ __ENV.js
|
||||
|
||||
# next-sitemap
|
||||
sitemap*.xml
|
||||
|
||||
# sentry
|
||||
.sentryclirc
|
||||
@ -21,14 +21,6 @@ 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
|
||||
|
||||
ARG TURBO_TEAM
|
||||
ARG TURBO_TOKEN
|
||||
ARG SENTRY_AUTH_TOKEN
|
||||
|
||||
ENV TURBO_TEAM $TURBO_TEAM
|
||||
ENV TURBO_TOKEN $TURBO_TOKEN
|
||||
ENV SENTRY_AUTH_TOKEN $SENTRY_AUTH_TOKEN
|
||||
|
||||
RUN pnpm run build --filter client
|
||||
|
||||
FROM base as production
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
const { version } = require('../package.json');
|
||||
const { i18n } = require('./next-i18next.config');
|
||||
const { withSentryConfig } = require('@sentry/nextjs');
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
@ -16,11 +15,6 @@ const nextConfig = {
|
||||
domains: ['cdn.rxresu.me', 'www.gravatar.com'],
|
||||
},
|
||||
|
||||
sentry: {
|
||||
hideSourceMaps: true,
|
||||
widenClientFileUpload: true,
|
||||
},
|
||||
|
||||
// Hack to make Tailwind darkMode 'class' strategy with CSS Modules
|
||||
// Ref: https://github.com/tailwindlabs/tailwindcss/issues/3258#issuecomment-968368156
|
||||
webpack: (config) => {
|
||||
@ -53,11 +47,4 @@ const nextConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
/** @type {import('@sentry/nextjs').SentryWebpackPluginOptions} */
|
||||
const sentryConfig = {
|
||||
silent: true,
|
||||
project: 'client',
|
||||
dryRun: process.env.NODE_ENV !== 'production',
|
||||
};
|
||||
|
||||
module.exports = withSentryConfig(nextConfig, sentryConfig);
|
||||
module.exports = nextConfig;
|
||||
|
||||
@ -13,44 +13,43 @@
|
||||
"@emotion/css": "^11.10.5",
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
"@hello-pangea/dnd": "^16.0.1",
|
||||
"@hello-pangea/dnd": "^16.2.0",
|
||||
"@hookform/resolvers": "2.9.10",
|
||||
"@monaco-editor/react": "^4.4.6",
|
||||
"@mui/icons-material": "^5.10.15",
|
||||
"@mui/lab": "^5.0.0-alpha.109",
|
||||
"@mui/material": "^5.10.15",
|
||||
"@mui/system": "^5.10.15",
|
||||
"@mui/x-date-pickers": "5.0.8",
|
||||
"@next/env": "^13.0.5",
|
||||
"@react-oauth/google": "^0.5.0",
|
||||
"@reduxjs/toolkit": "^1.9.0",
|
||||
"@sentry/nextjs": "^7.21.1",
|
||||
"axios": "^1.2.0",
|
||||
"@mui/icons-material": "^5.11.0",
|
||||
"@mui/lab": "^5.0.0-alpha.112",
|
||||
"@mui/material": "^5.11.0",
|
||||
"@mui/system": "^5.11.0",
|
||||
"@mui/x-date-pickers": "5.0.11",
|
||||
"@next/env": "^13.0.7",
|
||||
"@react-oauth/google": "^0.5.1",
|
||||
"@reduxjs/toolkit": "^1.9.1",
|
||||
"axios": "^1.2.1",
|
||||
"clsx": "^1.2.1",
|
||||
"dayjs": "^1.11.6",
|
||||
"dayjs": "^1.11.7",
|
||||
"downloadjs": "^1.4.7",
|
||||
"joi": "^17.7.0",
|
||||
"lodash": "^4.17.21",
|
||||
"md5-hex": "^4.0.0",
|
||||
"monaco-editor": "^0.34.1",
|
||||
"nanoid": "^3.3.4",
|
||||
"next": "13.0.5",
|
||||
"next-i18next": "^13.0.0",
|
||||
"next": "13.0.7",
|
||||
"next-i18next": "^13.0.2",
|
||||
"react": "^18.2.0",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dnd": "16.0.1",
|
||||
"react-dnd-html5-backend": "16.0.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.39.5",
|
||||
"react-hook-form": "^7.40.0",
|
||||
"react-hot-toast": "2.4.0",
|
||||
"react-icons": "^4.6.0",
|
||||
"react-markdown": "^8.0.3",
|
||||
"react-icons": "^4.7.1",
|
||||
"react-markdown": "^8.0.4",
|
||||
"react-query": "^3.39.2",
|
||||
"react-redux": "^8.0.5",
|
||||
"react-zoom-pan-pinch": "^2.1.3",
|
||||
"redux": "^4.2.0",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.2.1",
|
||||
"redux-saga": "^1.2.2",
|
||||
"redux-undo": "^1.0.1",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"sharp": "^0.31.2",
|
||||
@ -58,27 +57,27 @@
|
||||
"webfontloader": "^1.6.28"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.2",
|
||||
"@babel/core": "^7.20.5",
|
||||
"@reactive-resume/schema": "workspace:*",
|
||||
"@tailwindcss/typography": "^0.5.8",
|
||||
"@types/downloadjs": "^1.4.3",
|
||||
"@types/lodash": "^4.14.190",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/react": "^18.0.25",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/node": "^18.11.15",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.9",
|
||||
"@types/react-redux": "^7.1.24",
|
||||
"@types/tailwindcss": "^3.0.11",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@types/webfontloader": "^1.6.35",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"csstype": "^3.1.1",
|
||||
"eslint-config-next": "^13.0.5",
|
||||
"eslint-plugin-tailwindcss": "^3.7.0",
|
||||
"eslint-config-next": "^13.0.7",
|
||||
"eslint-plugin-tailwindcss": "^3.7.1",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"next-sitemap": "^3.1.32",
|
||||
"postcss": "^8.4.19",
|
||||
"sass": "^1.56.1",
|
||||
"next-sitemap": "^3.1.42",
|
||||
"postcss": "^8.4.20",
|
||||
"sass": "^1.56.2",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"typescript": "^4.9.3"
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
import type { NextPage } from 'next';
|
||||
import type { ErrorProps } from 'next/error';
|
||||
import NextErrorComponent from 'next/error';
|
||||
|
||||
const CustomErrorComponent: NextPage<ErrorProps> = (props) => <NextErrorComponent statusCode={props.statusCode} />;
|
||||
|
||||
CustomErrorComponent.getInitialProps = async (contextData) => {
|
||||
await Sentry.captureUnderscoreErrorException(contextData);
|
||||
|
||||
return NextErrorComponent.getInitialProps(contextData);
|
||||
};
|
||||
|
||||
export default CustomErrorComponent;
|
||||
@ -1,15 +0,0 @@
|
||||
import env from '@beam-australia/react-env';
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
import packageJSON from '../package.json';
|
||||
|
||||
const SENTRY_DSN = env('CLIENT_SENTRY_DSN');
|
||||
|
||||
if (SENTRY_DSN) {
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN,
|
||||
tracesSampleRate: 1.0,
|
||||
release: packageJSON.version,
|
||||
enabled: process.env.NODE_ENV === 'production',
|
||||
});
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
defaults.url=https://sentry.io/
|
||||
defaults.org=reactive-resume
|
||||
defaults.project=client
|
||||
@ -1,15 +0,0 @@
|
||||
import env from '@beam-australia/react-env';
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
|
||||
import packageJSON from '../package.json';
|
||||
|
||||
const SENTRY_DSN = env('CLIENT_SENTRY_DSN');
|
||||
|
||||
if (SENTRY_DSN) {
|
||||
Sentry.init({
|
||||
dsn: SENTRY_DSN,
|
||||
tracesSampleRate: 1.0,
|
||||
release: packageJSON.version,
|
||||
enabled: process.env.NODE_ENV === 'production',
|
||||
});
|
||||
}
|
||||
@ -2,16 +2,14 @@ import DateWrapper from './DateWrapper';
|
||||
import FontWrapper from './FontWrapper';
|
||||
import ThemeWrapper from './ThemeWrapper';
|
||||
|
||||
const WrapperRegistry: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
|
||||
return (
|
||||
<ThemeWrapper>
|
||||
<FontWrapper>
|
||||
<DateWrapper>
|
||||
<>{children}</>
|
||||
</DateWrapper>
|
||||
</FontWrapper>
|
||||
</ThemeWrapper>
|
||||
);
|
||||
};
|
||||
const WrapperRegistry: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => (
|
||||
<ThemeWrapper>
|
||||
<FontWrapper>
|
||||
<DateWrapper>
|
||||
<>{children}</>
|
||||
</DateWrapper>
|
||||
</FontWrapper>
|
||||
</ThemeWrapper>
|
||||
);
|
||||
|
||||
export default WrapperRegistry;
|
||||
|
||||
22
package.json
22
package.json
@ -1,13 +1,14 @@
|
||||
{
|
||||
"name": "reactive-resume",
|
||||
"version": "3.6.15",
|
||||
"version": "3.6.16",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "env-cmd --silent cross-var cross-env VERSION=$npm_package_version turbo run dev",
|
||||
"lint": "turbo run lint",
|
||||
"build": "env-cmd --silent cross-var cross-env VERSION=$npm_package_version turbo run build",
|
||||
"start": "env-cmd --silent cross-var cross-env VERSION=$npm_package_version turbo run start",
|
||||
"format": "prettier --write ."
|
||||
"generate-env": "ts-node ./scripts/generate-env.ts",
|
||||
"format": "prettier --write .",
|
||||
"lint": "turbo run lint"
|
||||
},
|
||||
"workspaces": [
|
||||
"schema",
|
||||
@ -18,16 +19,19 @@
|
||||
"cross-env": "^7.0.3",
|
||||
"cross-var": "^1.1.0",
|
||||
"env-cmd": "^10.1.0",
|
||||
"turbo": "^1.6.3"
|
||||
"turbo": "^1.6.3",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^5.44.0",
|
||||
"@typescript-eslint/parser": "^5.44.0",
|
||||
"eslint": "^8.28.0",
|
||||
"@types/node": "^18.11.15",
|
||||
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
||||
"@typescript-eslint/parser": "^5.46.1",
|
||||
"eslint": "^8.29.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||
"prettier": "^2.8.0",
|
||||
"typescript": "^4.9.3"
|
||||
"prettier": "^2.8.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "^4.9.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "17.0.2",
|
||||
|
||||
2276
pnpm-lock.yaml
generated
2276
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@
|
||||
"build": "tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.28.0",
|
||||
"typescript": "^4.9.3"
|
||||
"eslint": "^8.29.0",
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
|
||||
66
scripts/generate-env.ts
Normal file
66
scripts/generate-env.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { randomBytes } from 'crypto';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
const envMap = {
|
||||
TZ: 'UTC',
|
||||
PUBLIC_URL: '',
|
||||
PUBLIC_SERVER_URL: '',
|
||||
PUBLIC_GOOGLE_CLIENT_ID: '',
|
||||
POSTGRES_DB: 'postgres',
|
||||
POSTGRES_USER: 'postgres',
|
||||
POSTGRES_PASSWORD: 'postgres',
|
||||
SECRET_KEY: '',
|
||||
POSTGRES_HOST: 'localhost',
|
||||
POSTGRES_PORT: '5432',
|
||||
POSTGRES_SSL_CERT: '',
|
||||
JWT_SECRET: '',
|
||||
JWT_EXPIRY_TIME: '604800',
|
||||
GOOGLE_CLIENT_SECRET: '',
|
||||
GOOGLE_API_KEY: '',
|
||||
MAIL_FROM_NAME: '',
|
||||
MAIL_FROM_EMAIL: '',
|
||||
MAIL_HOST: '',
|
||||
MAIL_PORT: '',
|
||||
MAIL_USERNAME: '',
|
||||
MAIL_PASSWORD: '',
|
||||
STORAGE_BUCKET: '',
|
||||
STORAGE_REGION: '',
|
||||
STORAGE_ENDPOINT: '',
|
||||
STORAGE_URL_PREFIX: '',
|
||||
STORAGE_ACCESS_KEY: '',
|
||||
STORAGE_SECRET_KEY: '',
|
||||
PDF_DELETION_TIME: '345600000',
|
||||
PUBLIC_FLAG_DISABLE_SIGNUPS: 'false',
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
// URLs
|
||||
// If running in a Gitpod environment, auto generated the URLs
|
||||
if (process.env.GITPOD_WORKSPACE_URL) {
|
||||
const baseUrl = new URL(process.env.GITPOD_WORKSPACE_URL!).host;
|
||||
|
||||
envMap['PUBLIC_SERVER_URL'] = `https://3100-${baseUrl}`;
|
||||
envMap['PUBLIC_URL'] = `https://3000-${baseUrl}`;
|
||||
}
|
||||
// Otherwise, fallback to localhost
|
||||
else {
|
||||
envMap['PUBLIC_SERVER_URL'] = 'https://localhost:3100';
|
||||
envMap['PUBLIC_URL'] = 'https://localhost:3000';
|
||||
}
|
||||
|
||||
// Secret Key
|
||||
envMap['SECRET_KEY'] = randomBytes(20).toString('hex');
|
||||
envMap['JWT_SECRET'] = randomBytes(40).toString('hex');
|
||||
|
||||
const envFile = Object.entries(envMap)
|
||||
.reduce((acc, [key, value]) => {
|
||||
acc.push(`${key}=${value}`);
|
||||
|
||||
return acc;
|
||||
}, [] as string[])
|
||||
.join('\n');
|
||||
|
||||
await fs.writeFile('.env', envFile);
|
||||
};
|
||||
|
||||
main();
|
||||
@ -21,17 +21,9 @@ 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
|
||||
|
||||
ARG TURBO_TEAM
|
||||
ARG TURBO_TOKEN
|
||||
ARG SENTRY_AUTH_TOKEN
|
||||
|
||||
ENV TURBO_TEAM $TURBO_TEAM
|
||||
ENV TURBO_TOKEN $TURBO_TOKEN
|
||||
ENV SENTRY_AUTH_TOKEN $SENTRY_AUTH_TOKEN
|
||||
|
||||
RUN pnpm run build --filter server
|
||||
|
||||
FROM mcr.microsoft.com/playwright:v1.28.0-focal as production
|
||||
FROM mcr.microsoft.com/playwright:v1.28.1-focal as production
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
@ -8,29 +8,27 @@
|
||||
"start": "node dist/main"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.216.0",
|
||||
"@aws-sdk/client-s3": "^3.231.0",
|
||||
"@nestjs/axios": "^1.0.0",
|
||||
"@nestjs/common": "^9.2.0",
|
||||
"@nestjs/common": "^9.2.1",
|
||||
"@nestjs/config": "^2.2.0",
|
||||
"@nestjs/core": "^9.2.0",
|
||||
"@nestjs/core": "^9.2.1",
|
||||
"@nestjs/jwt": "^9.0.0",
|
||||
"@nestjs/mapped-types": "^1.2.0",
|
||||
"@nestjs/passport": "^9.0.0",
|
||||
"@nestjs/platform-express": "^9.2.0",
|
||||
"@nestjs/platform-express": "^9.2.1",
|
||||
"@nestjs/schedule": "^2.1.0",
|
||||
"@nestjs/serve-static": "^3.0.0",
|
||||
"@nestjs/terminus": "^9.1.3",
|
||||
"@nestjs/terminus": "^9.1.4",
|
||||
"@nestjs/typeorm": "^9.0.1",
|
||||
"@sentry/node": "^7.21.1",
|
||||
"@sentry/tracing": "^7.21.1",
|
||||
"@types/passport": "^1.0.11",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"cache-manager": "^5.1.3",
|
||||
"cache-manager": "^5.1.4",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.13.2",
|
||||
"class-validator": "^0.13.0",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"csvtojson": "^2.0.10",
|
||||
"dayjs": "^1.11.6",
|
||||
"dayjs": "^1.11.7",
|
||||
"google-auth-library": "^8.7.0",
|
||||
"joi": "^17.7.0",
|
||||
"lodash": "^4.17.21",
|
||||
@ -46,8 +44,8 @@
|
||||
"playwright-chromium": "^1.28.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
"rxjs": "^7.5.7",
|
||||
"typeorm": "0.3.10",
|
||||
"rxjs": "^7.8.0",
|
||||
"typeorm": "0.3.11",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -56,19 +54,19 @@
|
||||
"@reactive-resume/schema": "workspace:*",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/lodash": "^4.14.190",
|
||||
"@types/express": "^4.17.15",
|
||||
"@types/lodash": "^4.14.191",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/node": "^18.11.15",
|
||||
"@types/nodemailer": "^6.4.6",
|
||||
"@types/passport-jwt": "^3.0.7",
|
||||
"@types/passport-jwt": "^3.0.8",
|
||||
"@types/passport-local": "^1.0.34",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier": "^2.8.1",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ts-loader": "^9.4.1",
|
||||
"ts-loader": "^9.4.2",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.1.0",
|
||||
"typescript": "^4.9.3",
|
||||
"tsconfig-paths": "^4.1.1",
|
||||
"typescript": "^4.9.4",
|
||||
"webpack": "^5.75.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
defaults.url=https://sentry.io/
|
||||
defaults.org=reactive-resume
|
||||
defaults.project=server
|
||||
@ -11,7 +11,6 @@ import { HttpExceptionFilter } from './filters/http-exception.filter';
|
||||
import { FontsModule } from './fonts/fonts.module';
|
||||
import { HealthModule } from './health/health.module';
|
||||
import { IntegrationsModule } from './integrations/integrations.module';
|
||||
import { SentryInterceptor } from './interceptors/sentry.interceptor';
|
||||
import { MailModule } from './mail/mail.module';
|
||||
import { PrinterModule } from './printer/printer.module';
|
||||
import { ResumeModule } from './resume/resume.module';
|
||||
@ -41,10 +40,6 @@ import { UsersModule } from './users/users.module';
|
||||
provide: APP_INTERCEPTOR,
|
||||
useClass: ClassSerializerInterceptor,
|
||||
},
|
||||
{
|
||||
provide: APP_INTERCEPTOR,
|
||||
useClass: SentryInterceptor,
|
||||
},
|
||||
{
|
||||
provide: APP_FILTER,
|
||||
useClass: HttpExceptionFilter,
|
||||
|
||||
@ -7,7 +7,6 @@ import authConfig from './auth.config';
|
||||
import cacheConfig from './cache.config';
|
||||
import databaseConfig from './database.config';
|
||||
import googleConfig from './google.config';
|
||||
import loggingConfig from './logging.config';
|
||||
import mailConfig from './mail.config';
|
||||
import storageConfig from './storage.config';
|
||||
|
||||
@ -60,24 +59,12 @@ const validationSchema = Joi.object({
|
||||
PDF_DELETION_TIME: Joi.number()
|
||||
.default(4 * 24 * 60 * 60 * 1000) // 4 days
|
||||
.allow(''),
|
||||
|
||||
// Logging
|
||||
SERVER_SENTRY_DSN: Joi.string().allow(''),
|
||||
});
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
NestConfigModule.forRoot({
|
||||
load: [
|
||||
appConfig,
|
||||
authConfig,
|
||||
cacheConfig,
|
||||
databaseConfig,
|
||||
googleConfig,
|
||||
loggingConfig,
|
||||
mailConfig,
|
||||
storageConfig,
|
||||
],
|
||||
load: [appConfig, authConfig, cacheConfig, databaseConfig, googleConfig, mailConfig, storageConfig],
|
||||
validationSchema: validationSchema,
|
||||
}),
|
||||
],
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
import { registerAs } from '@nestjs/config';
|
||||
|
||||
export default registerAs('logging', () => ({
|
||||
sentryDSN: process.env.SERVER_SENTRY_DSN,
|
||||
}));
|
||||
@ -1,15 +0,0 @@
|
||||
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import { Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class SentryInterceptor implements NestInterceptor {
|
||||
intercept(_context: ExecutionContext, next: CallHandler): Observable<any> {
|
||||
return next.handle().pipe(
|
||||
tap(null, (exception) => {
|
||||
Sentry.captureException(exception);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,7 @@
|
||||
import '@sentry/tracing';
|
||||
|
||||
import { Logger, ValidationPipe } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { NestExpressApplication } from '@nestjs/platform-express';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import cookieParser from 'cookie-parser';
|
||||
|
||||
import { AppModule } from './app.module';
|
||||
@ -13,27 +10,16 @@ const bootstrap = async () => {
|
||||
const app = await NestFactory.create<NestExpressApplication>(AppModule);
|
||||
const configService = app.get(ConfigService);
|
||||
|
||||
const appUrl = configService.get<string>('app.url');
|
||||
|
||||
// Middleware
|
||||
app.enableCors({ credentials: true });
|
||||
app.enableCors({ origin: [appUrl], credentials: true });
|
||||
app.enableShutdownHooks();
|
||||
app.use(cookieParser());
|
||||
|
||||
// Pipes
|
||||
app.useGlobalPipes(new ValidationPipe({ transform: true }));
|
||||
|
||||
// Sentry Error Logging
|
||||
const sentryDSN = configService.get<string>('logging.sentryDSN');
|
||||
const version = configService.get<string>('app.version');
|
||||
|
||||
if (sentryDSN) {
|
||||
Sentry.init({
|
||||
dsn: sentryDSN,
|
||||
release: version,
|
||||
tracesSampleRate: 1.0,
|
||||
enabled: process.env.NODE_ENV === 'production',
|
||||
});
|
||||
}
|
||||
|
||||
// Server Port
|
||||
const port = configService.get<number>('app.port');
|
||||
await app.listen(port);
|
||||
|
||||
@ -58,6 +58,7 @@ export class PrinterService implements OnModuleInit, OnModuleDestroy {
|
||||
|
||||
await page.goto(`${url}/${username}/${slug}/printer?secretKey=${secretKey}`);
|
||||
await page.waitForSelector('html.wf-active');
|
||||
await page.waitForLoadState("networkidle")
|
||||
|
||||
const pageFormat: PageConfig['format'] = await page.$$eval(
|
||||
'[data-page]',
|
||||
|
||||
16
turbo.json
16
turbo.json
@ -1,19 +1,13 @@
|
||||
{
|
||||
"$schema": "https://turborepo.org/schema.json",
|
||||
"globalDependencies": [".env"],
|
||||
"pipeline": {
|
||||
"dev": {
|
||||
"cache": false
|
||||
},
|
||||
"lint": {
|
||||
"cache": false
|
||||
},
|
||||
"start": {
|
||||
"cache": false
|
||||
},
|
||||
"dev": {},
|
||||
"lint": {},
|
||||
"start": {},
|
||||
"build": {
|
||||
"outputs": ["dist/**", ".next/**"],
|
||||
"dependsOn": ["^build"]
|
||||
}
|
||||
},
|
||||
"globalDependencies": [".env"]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user