From 7dcfef6a933f31992a1d886d28d925c761b0e09b Mon Sep 17 00:00:00 2001 From: Reinis Ivanovs Date: Thu, 26 Dec 2024 21:26:04 +0200 Subject: [PATCH] fix prod builds --- .env.example | 5 +- .gitignore | 1 + apps/api/Dockerfile | 19 -------- apps/api/prisma/schema.prisma | 4 +- apps/api/project.json | 63 ++++++++++++++++++++++++ apps/api/src/assets/.gitkeep | 0 apps/api/src/db/client.ts | 2 +- apps/api/src/main.ts | 4 ++ apps/api/src/trpc/router.ts | 2 +- apps/api/src/trpc/routers/media.ts | 2 +- apps/web/nginx.conf | 8 ++-- compose.yaml | 25 +++++----- eslint.config.js | 7 ++- modes.code-workspace | 9 +--- package.json | 5 +- pnpm-lock.yaml | 77 +++++------------------------- 16 files changed, 112 insertions(+), 121 deletions(-) delete mode 100644 apps/api/Dockerfile delete mode 100644 apps/api/src/assets/.gitkeep diff --git a/.env.example b/.env.example index 9afdaa6..c232703 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,10 @@ +# TODO: remove hardcoded values DOMAIN=http://modes.local -POSTGRES_HOST=localhost +POSTGRES_HOST=db POSTGRES_PORT=5432 POSTGRES_DB=modes POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres DATABASE_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?schema=public" -API_HOST=localhost +API_HOST=api API_PORT=3000 diff --git a/.gitignore b/.gitignore index 3372311..c6fe00d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ dist tmp out-tsc +generated # dependencies node_modules diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile deleted file mode 100644 index 71f8c5d..0000000 --- a/apps/api/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM node:20-alpine - -RUN corepack enable && corepack prepare pnpm@latest --activate - -WORKDIR /app - -COPY package*.json ./ -COPY pnpm-lock.yaml ./ -COPY nx.json ./ -COPY tsconfig*.json ./ -COPY eslint.config.js ./ - -RUN pnpm install --frozen-lockfile - -COPY apps/api ./apps/api - -EXPOSE 80 - -CMD ["pnpm", "nx", "run", "api:serve", "--configuration=production"] diff --git a/apps/api/prisma/schema.prisma b/apps/api/prisma/schema.prisma index 22efa58..8e05b46 100644 --- a/apps/api/prisma/schema.prisma +++ b/apps/api/prisma/schema.prisma @@ -1,5 +1,7 @@ generator client { - provider = "prisma-client-js" + provider = "prisma-client-js" + output = "../src/generated/client" + binaryTargets = ["native", "linux-musl-openssl-3.0.x"] } datasource db { diff --git a/apps/api/project.json b/apps/api/project.json index af91769..05d8d53 100644 --- a/apps/api/project.json +++ b/apps/api/project.json @@ -4,6 +4,57 @@ "sourceRoot": "apps/api/src", "projectType": "application", "targets": { + "build": { + "executor": "nx:run-commands", + "outputs": ["{options.outputPath}"], + "dependsOn": ["build-esbuild"], + "options": { + "commands": [ + "mkdir -p dist/apps/api/src/generated/client", + "cp -r apps/api/src/generated/client/*.node dist/apps/api/src/generated/client" + ], + "parallel": false + } + }, + "build-esbuild": { + "executor": "@nx/esbuild:esbuild", + "outputs": ["{options.outputPath}"], + "dependsOn": ["prisma-generate"], + "options": { + "platform": "node", + "target": "node20", + "outputPath": "dist/apps/api", + "main": "apps/api/src/main.ts", + "tsConfig": "apps/api/tsconfig.json", + "assets": [ + { + "glob": "**/*", + "input": "apps/api/src/assets", + "output": ".", + "ignore": [".gitkeep"] + } + ], + "generatePackageJson": true, + "bundle": true, + "format": ["cjs"], + "esbuildOptions": { + "sourcemap": false, + "outExtension": { + ".js": ".js" + }, + "minify": true + } + }, + "configurations": { + "development": { + "minify": false + }, + "production": { + "minify": true, + "sourcemap": false + } + } + }, "serve": { "executor": "nx:run-commands", "defaultConfiguration": "development", @@ -54,5 +105,17 @@ "cwd": "apps/api" } } + }, + "targetDefaults": { + "api:serve": { + "dependsOn": [ + { + "target": "build", + "projects": "self", + "params": "forward", + "condition": "configuration === 'production'" + } + ] + } } } diff --git a/apps/api/src/assets/.gitkeep b/apps/api/src/assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/apps/api/src/db/client.ts b/apps/api/src/db/client.ts index 9b6c4ce..987deee 100644 --- a/apps/api/src/db/client.ts +++ b/apps/api/src/db/client.ts @@ -1,3 +1,3 @@ -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from '../generated/client'; export const prisma = new PrismaClient(); diff --git a/apps/api/src/main.ts b/apps/api/src/main.ts index 230b5f4..99a4aed 100644 --- a/apps/api/src/main.ts +++ b/apps/api/src/main.ts @@ -1,5 +1,7 @@ import * as trpcExpress from '@trpc/server/adapters/express'; import cors from 'cors'; +import * as dotenv from 'dotenv'; +import { expand } from 'dotenv-expand'; import 'dotenv/config'; import express from 'express'; import { z } from 'zod'; @@ -7,6 +9,8 @@ import { prisma } from './db/client'; import { appRouter } from './trpc/root'; import { createContext } from './trpc/router'; +expand(dotenv.config()); + const envSchema = z.object({ API_HOST: z.string().default('localhost'), API_PORT: z.string().transform((val) => Number(val)), diff --git a/apps/api/src/trpc/router.ts b/apps/api/src/trpc/router.ts index 797177c..5934474 100644 --- a/apps/api/src/trpc/router.ts +++ b/apps/api/src/trpc/router.ts @@ -1,7 +1,7 @@ -import type { PrismaClient } from '@prisma/client'; import { initTRPC } from '@trpc/server'; import type { CreateNextContextOptions } from '@trpc/server/adapters/next'; import { prisma } from '../db/client'; +import type { PrismaClient } from '../generated/client'; type Context = { db: PrismaClient; diff --git a/apps/api/src/trpc/routers/media.ts b/apps/api/src/trpc/routers/media.ts index d127b76..a05fa7f 100644 --- a/apps/api/src/trpc/routers/media.ts +++ b/apps/api/src/trpc/routers/media.ts @@ -1,5 +1,5 @@ -import { Prisma } from '@prisma/client'; import { z } from 'zod'; +import { Prisma } from '../../generated/client'; import { protectedProcedure } from '../middleware/auth'; import { router } from '../router'; diff --git a/apps/web/nginx.conf b/apps/web/nginx.conf index 75057ca..7df1504 100644 --- a/apps/web/nginx.conf +++ b/apps/web/nginx.conf @@ -7,8 +7,8 @@ server { } location /api/ { - proxy_pass http://api:80/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; -} + proxy_pass http://api:3000/api/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } } diff --git a/compose.yaml b/compose.yaml index 89fd531..c9b3622 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,16 +1,14 @@ version: '3.8' +name: modes + services: db: image: postgres:15-alpine restart: always user: postgres - environment: - - POSTGRES_DB=${POSTGRES_DB} - - POSTGRES_USER=${POSTGRES_USER} - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres} - ports: - - '${POSTGRES_PORT}:5432' + env_file: + - .env volumes: - postgres_data:/var/lib/postgresql/data healthcheck: @@ -26,13 +24,12 @@ services: - caddy api: - build: - context: . - dockerfile: apps/api/Dockerfile + image: node:20-alpine restart: always - environment: - - API_PORT=80 - - API_HOST=0.0.0.0 + working_dir: /app + volumes: + - ./dist/apps/api:/app:ro + command: ['node', 'main.js'] env_file: - .env depends_on: @@ -45,8 +42,8 @@ services: image: nginx:alpine restart: always volumes: - - ./dist/apps/web:/usr/share/nginx/html - - ./apps/web/nginx.conf:/etc/nginx/conf.d/default.conf + - ./dist/apps/web:/usr/share/nginx/html:ro + - ./apps/web/nginx.conf:/etc/nginx/conf.d/default.conf:ro networks: - caddy depends_on: diff --git a/eslint.config.js b/eslint.config.js index c480826..ba6f896 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -27,7 +27,6 @@ module.exports = [ ], 'func-style': ['error', 'expression'], 'arrow-body-style': ['error', 'as-needed'], - 'import/no-default-export': 'error', 'prefer-arrow/prefer-arrow-functions': 'warn', '@typescript-eslint/consistent-type-definitions': ['error', 'type'], // 'unused-imports/no-unused-imports': 'error', @@ -38,6 +37,12 @@ module.exports = [ // 'unused-imports': require('eslint-plugin-unused-imports'), }, }, + { + files: ['**/src/*.tsx', '**/src/*.ts'], + rules: { + 'import/no-default-export': 'error', + }, + }, { files: ['**/*.stories.tsx', '**/*.stories.ts'], rules: { diff --git a/modes.code-workspace b/modes.code-workspace index eddb7ba..9d71f40 100644 --- a/modes.code-workspace +++ b/modes.code-workspace @@ -26,17 +26,12 @@ "source.organizeImports": "always" }, "typescript.tsdk": "✨ root/node_modules/typescript/lib", - "files.exclude": { - "**/dist": true, - "**/.nx/cache": true, - "**/node_modules": true, - "**/storybook-static": true - }, "search.exclude": { "**/dist": true, "**/.nx": true, "**/node_modules": true, - "**/storybook-static": true + "**/storybook-static": true, + "**/generated": true }, "[prisma]": { "editor.defaultFormatter": "Prisma.prisma", diff --git a/package.json b/package.json index d2fb9c0..b55c2b6 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,6 @@ "license": "MIT", "private": true, "packageManager": "pnpm@9.15.1", - "scripts": { - "start": "nx run api:prisma-generate && tsx apps/api/src/main.ts" - }, "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", @@ -24,6 +21,7 @@ "bcryptjs": "^2.4.3", "cors": "^2.8.5", "dotenv": "^16.4.7", + "dotenv-expand": "^12.0.1", "express": "~4.18.1", "jsonwebtoken": "^9.0.2", "msw": "^2.7.0", @@ -41,7 +39,6 @@ }, "devDependencies": { "@eslint/js": "^9.8.0", - "@nx-tools/nx-prisma": "^6.4.1", "@nx/devkit": "20.2.2", "@nx/esbuild": "20.2.2", "@nx/eslint": "20.2.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e6377c3..7f50bc3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,6 +56,9 @@ importers: dotenv: specifier: ^16.4.7 version: 16.4.7 + dotenv-expand: + specifier: ^12.0.1 + version: 12.0.1 express: specifier: ~4.18.1 version: 4.18.3 @@ -102,9 +105,6 @@ importers: '@eslint/js': specifier: ^9.8.0 version: 9.17.0 - '@nx-tools/nx-prisma': - specifier: ^6.4.1 - version: 6.4.1(@nx/devkit@20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))))(@swc/helpers@0.5.15)(prisma@6.1.0)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.6.3))(tslib@2.8.1)(tsx@4.19.2) '@nx/devkit': specifier: 20.2.2 version: 20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))) @@ -374,12 +374,6 @@ importers: packages: - '@actions/exec@1.1.1': - resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} - - '@actions/io@1.1.3': - resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} - '@adobe/css-tools@4.3.3': resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} @@ -1997,24 +1991,6 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@nx-tools/core@6.1.1': - resolution: {integrity: sha512-AXMK/Q7klxtsEMMP9r/xeIfblShVytD6oSA2vYeJUS6Q1YaJcnEo0absYON2t1oquVgBButoTdNZKDvG4wCmmg==} - peerDependencies: - '@nx/devkit': ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 - tslib: ^2.5.0 - - '@nx-tools/nx-prisma@6.4.1': - resolution: {integrity: sha512-DFmIXUiQoMxtb8YuTWGcYObqKAzY43EYb03g8G2quCbeQIYVzhxAg2+zspee42eTf3lD+3EIybvSRdF7JYCPhA==} - peerDependencies: - '@nx/devkit': ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 - '@swc/helpers': ~0.5.11 - prisma: ^5.0.0 - ts-node: ^10.0.0 - tsx: ^4.0.0 - peerDependenciesMeta: - tsx: - optional: true - '@nx/cypress@20.2.2': resolution: {integrity: sha512-Y0V5b8N0J0Ofd8JQK21DPE+MB3SwqiarF0fKMB56P7HIuV9RucLqmwqTqnfVOpnFfKrMMs96Qy1vXsaAlHQLgg==} peerDependencies: @@ -3878,10 +3854,6 @@ packages: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} - ci-info@4.1.0: - resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} - engines: {node: '>=8'} - cjs-module-lexer@1.4.1: resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} @@ -4183,9 +4155,6 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - csv-parse@5.6.0: - resolution: {integrity: sha512-l3nz3euub2QMg5ouu5U09Ew9Wf6/wQ8I++ch1loQ0ljmzhmfZYrH9fflS22i/PQEvsPvxCwxgz5q7UB8K1JO4Q==} - cwd@0.10.0: resolution: {integrity: sha512-YGZxdTTL9lmLkCUTpg4j0zQ7IhRB5ZmqNBbGCl3Tg6MP/d5/6sY7L5mmTjzbc6JKgVZYiqTQTNhPFsbXNGlRaA==} engines: {node: '>=0.8'} @@ -4415,6 +4384,10 @@ packages: resolution: {integrity: sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==} engines: {node: '>=12'} + dotenv-expand@12.0.1: + resolution: {integrity: sha512-LaKRbou8gt0RNID/9RoI+J2rvXsBRPMV7p+ElHlPhcSARbCPDYcYG2s1TIzAfWv4YSgyY5taidWzzs31lNV3yQ==} + engines: {node: '>=12'} + dotenv@16.4.7: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} @@ -8174,12 +8147,6 @@ packages: snapshots: - '@actions/exec@1.1.1': - dependencies: - '@actions/io': 1.1.3 - - '@actions/io@1.1.3': {} - '@adobe/css-tools@4.3.3': {} '@adobe/css-tools@4.4.1': {} @@ -9972,28 +9939,6 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@nx-tools/core@6.1.1(@nx/devkit@20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))))(tslib@2.8.1)': - dependencies: - '@actions/exec': 1.1.1 - '@actions/io': 1.1.3 - '@nx/devkit': 20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))) - chalk: 4.1.2 - ci-info: 4.1.0 - csv-parse: 5.6.0 - tslib: 2.8.1 - - '@nx-tools/nx-prisma@6.4.1(@nx/devkit@20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))))(@swc/helpers@0.5.15)(prisma@6.1.0)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.6.3))(tslib@2.8.1)(tsx@4.19.2)': - dependencies: - '@nx-tools/core': 6.1.1(@nx/devkit@20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))))(tslib@2.8.1) - '@nx/devkit': 20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))) - '@swc/helpers': 0.5.15 - prisma: 6.1.0 - ts-node: 10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.15))(@types/node@22.10.2)(typescript@5.6.3) - optionalDependencies: - tsx: 4.19.2 - transitivePeerDependencies: - - tslib - '@nx/cypress@20.2.2(@babel/traverse@7.26.4)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))(@types/node@22.10.2)(@zkochan/js-yaml@0.0.7)(eslint@9.17.0)(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15)))(typescript@5.6.3)': dependencies: '@nx/devkit': 20.2.2(nx@20.2.2(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.15))(@swc/types@0.1.17)(typescript@5.6.3))(@swc/core@1.5.29(@swc/helpers@0.5.15))) @@ -12473,8 +12418,6 @@ snapshots: ci-info@3.9.0: {} - ci-info@4.1.0: {} - cjs-module-lexer@1.4.1: {} clean-stack@2.2.0: {} @@ -12785,8 +12728,6 @@ snapshots: csstype@3.1.3: {} - csv-parse@5.6.0: {} - cwd@0.10.0: dependencies: find-pkg: 0.1.2 @@ -12992,6 +12933,10 @@ snapshots: dependencies: dotenv: 16.4.7 + dotenv-expand@12.0.1: + dependencies: + dotenv: 16.4.7 + dotenv@16.4.7: {} dunder-proto@1.0.1: