diff --git a/.env.example b/.env.example index 57df0d2b..79ebd6ef 100644 --- a/.env.example +++ b/.env.example @@ -4,6 +4,7 @@ SECRET_KEY=change-me # URLs PUBLIC_URL=http://localhost:3000 +PUBLIC_SERVER_URL=http://localhost:3100 # Database POSTGRES_HOST=localhost diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..c19ed6d8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "attach", + "name": "Debug: Server", + "port": 9229, + "restart": true, + "stopOnEntry": false, + "protocol": "inspector" + }, + { + "name": "Debug: Client", + "type": "node-terminal", + "request": "launch", + "command": "pnpm run dev:client", + "console": "integratedTerminal", + "serverReadyAction": { + "pattern": "started server on .+, url: (https?://.+)", + "uriFormat": "%s", + "action": "debugWithChrome" + } + } + ] +} diff --git a/README.md b/README.md index ecb623ec..2e30a09a 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ Reactive Resume would be nothing without the folks who supported me and kept the - DigitalOcean, infrastructure provider - Crowdin, translation management platform - + diff --git a/client/Dockerfile b/client/Dockerfile index 95db39b1..00b1e731 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -36,13 +36,14 @@ RUN apk add --no-cache curl \ COPY --from=builder /app/pnpm-*.yaml ./ COPY --from=builder /app/package.json ./ +COPY --from=builder /app/client/package.json ./client/package.json + +RUN pnpm install -F client --frozen-lockfile --prod + 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 diff --git a/client/components/build/Center/ArtboardController.tsx b/client/components/build/Center/ArtboardController.tsx index 7cd0583d..f16a3b0b 100644 --- a/client/components/build/Center/ArtboardController.tsx +++ b/client/components/build/Center/ArtboardController.tsx @@ -62,7 +62,7 @@ const ArtboardController: React.FC = ({ zoomIn, zoomOut, c const url = await mutateAsync({ username, slug }); - download(url); + download(`/api${url}`); }; return ( diff --git a/client/components/build/RightSidebar/sections/Export.tsx b/client/components/build/RightSidebar/sections/Export.tsx index 9bf8e445..8607475a 100644 --- a/client/components/build/RightSidebar/sections/Export.tsx +++ b/client/components/build/RightSidebar/sections/Export.tsx @@ -47,7 +47,7 @@ const Export = () => { const url = await mutateAsync({ username, slug }); - download(url); + download(`/api${url}`); }; return ( diff --git a/client/pages/[username]/[slug]/index.tsx b/client/pages/[username]/[slug]/index.tsx index 5207e966..9e2e8c7d 100644 --- a/client/pages/[username]/[slug]/index.tsx +++ b/client/pages/[username]/[slug]/index.tsx @@ -90,7 +90,7 @@ const Preview: NextPage = ({ username, slug, resume: initialData }) => { try { const url = await mutateAsync({ username, slug }); - download(url); + download(`/api${url}`); } catch { toast.error('Something went wrong, please try again later.'); } diff --git a/client/pages/index.tsx b/client/pages/index.tsx index 04f3c23f..2edb5d18 100644 --- a/client/pages/index.tsx +++ b/client/pages/index.tsx @@ -162,7 +162,7 @@ const Home: NextPage = () => {
- + Powered By DigitalOcean
diff --git a/client/pages/r/[shortId].tsx b/client/pages/r/[shortId].tsx index de012403..65749f51 100644 --- a/client/pages/r/[shortId].tsx +++ b/client/pages/r/[shortId].tsx @@ -60,7 +60,7 @@ const Preview: NextPage = ({ shortId }) => { try { const url = await mutateAsync({ username: resume.user.username, slug: resume.slug }); - download(url); + download(`/api${url}`); } catch { toast.error('Something went wrong, please try again later.'); } diff --git a/client/services/resume.ts b/client/services/resume.ts index c60274c2..e0387bda 100644 --- a/client/services/resume.ts +++ b/client/services/resume.ts @@ -1,6 +1,6 @@ +import env from '@beam-australia/react-env'; import { Resume } from '@reactive-resume/schema'; -import { AxiosResponse } from 'axios'; -import isEmpty from 'lodash/isEmpty'; +import _axios, { AxiosResponse } from 'axios'; import isBrowser from '@/utils/isBrowser'; @@ -22,9 +22,6 @@ export type FetchResumeByIdentifierParams = { export type FetchResumeByShortIdParams = { shortId: string; - options?: { - secretKey?: string; - }; }; export type RenameResumeParams = { @@ -60,23 +57,26 @@ export type DeleteResumeParams = { export const fetchResumes = () => axios.get('/resume').then((res) => res.data); -export const fetchResumeByShortId = async ({ shortId, options = { secretKey: '' } }: FetchResumeByShortIdParams) => { - const requestOptions = isEmpty(options.secretKey) ? {} : { params: { secretKey: options.secretKey } }; - - return axios.get(`/resume/short/${shortId}`, requestOptions).then((res) => res.data); -}; - export const fetchResumeByIdentifier = async ({ username, slug, options = { secretKey: '' }, }: FetchResumeByIdentifierParams) => { - const prefix = !isBrowser && process.env.NODE_ENV === 'development' ? 'http://localhost:3100' : ''; - const requestOptions = isEmpty(options.secretKey) ? {} : { params: { secretKey: options.secretKey } }; + if (!isBrowser) { + const serverUrl = env('SERVER_URL'); + const secretKey = options.secretKey; - return axios.get(`${prefix}/resume/${username}/${slug}`, requestOptions).then((res) => res.data); + return _axios + .get(`${serverUrl}/resume/${username}/${slug}`, { params: { secretKey } }) + .then((res) => res.data); + } + + return axios.get(`/resume/${username}/${slug}`).then((res) => res.data); }; +export const fetchResumeByShortId = async ({ shortId }: FetchResumeByShortIdParams) => + axios.get(`/resume/short/${shortId}`).then((res) => res.data); + export const createResume = (createResumeParams: CreateResumeParams) => axios.post, CreateResumeParams>('/resume', createResumeParams).then((res) => res.data); diff --git a/docker-compose.yml b/docker-compose.yml index eb98c519..fe6a95a2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -22,6 +22,7 @@ services: container_name: server env_file: .env environment: + - PUBLIC_URL=http://client:3000 - POSTGRES_HOST=postgres ports: - 3100:3100 @@ -38,6 +39,8 @@ services: dockerfile: client/Dockerfile container_name: client env_file: .env + environment: + - PUBLIC_SERVER_URL=http://server:3100 ports: - 3000:3000 depends_on: diff --git a/package.json b/package.json index 905e99aa..0c77384a 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "lint": "eslint --fix --ext .js,.ts,.tsx .", "format": "prettier --write \"./**/*.{js,ts,tsx,json}\"", "dev:schema": "pnpm -F schema dev", - "dev:server": "pnpm -F server start:dev", + "dev:server": "pnpm -F server start:debugc", "dev:client": "pnpm -F client dev", "dev": "env-cmd --silent concurrently --kill-others \"pnpm run dev:*\"", "build:schema": "pnpm -F schema build", diff --git a/server/Dockerfile b/server/Dockerfile index 69b61fe8..4ea509da 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -31,15 +31,18 @@ FROM mcr.microsoft.com/playwright:focal as production WORKDIR /app -RUN curl -f https://get.pnpm.io/v6.16.js | node - add --global pnpm +RUN apt-get update \ + && apt-get install -y 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/server/dist ./server/dist COPY --from=builder /app/server/package.json ./server/package.json RUN pnpm install -F server --frozen-lockfile --prod +COPY --from=builder /app/server/dist ./server/dist + EXPOSE 3100 ENV PORT 3100 diff --git a/server/src/main.ts b/server/src/main.ts index a1366e87..4ee0297b 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -10,6 +10,7 @@ const bootstrap = async () => { const app = await NestFactory.create(AppModule); // Middleware + app.enableCors({ credentials: true }); app.enableShutdownHooks(); app.use(cookieParser()); diff --git a/server/src/printer/printer.service.ts b/server/src/printer/printer.service.ts index ba926dad..392e5ec4 100644 --- a/server/src/printer/printer.service.ts +++ b/server/src/printer/printer.service.ts @@ -7,7 +7,7 @@ import { join } from 'path'; import { PDFDocument } from 'pdf-lib'; import { Browser, chromium } from 'playwright-chromium'; -export const DELETION_TIME = 10 * 1000; // 10 seconds +export const DELETION_TIME = 10 * 1000 * 1000; // 10 seconds @Injectable() export class PrinterService implements OnModuleInit, OnModuleDestroy {