diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d882773 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.git +.github +.env +coverage +dist +node_modules +npm-debug.log* +pnpm-debug.log* diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml new file mode 100644 index 0000000..05f92c3 --- /dev/null +++ b/.github/workflows/trivy.yaml @@ -0,0 +1,44 @@ +name: Trivy Scanner + +on: + push: + branches: + - main + - master + - dev + - develop + pull_request: + workflow_dispatch: + +permissions: + actions: read + contents: read + security-events: write + +jobs: + trivy-scan: + name: Trivy SAST and SCA + runs-on: ubuntu-24.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Run Trivy scanner in repo mode + uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 + with: + version: "v0.73.0" + scan-type: "fs" + scan-ref: "." + ignore-unfixed: true + format: "sarif" + output: "trivy-results.sarif" + severity: "CRITICAL,HIGH,MEDIUM,UNKNOWN" + limit-severities-for-sarif: true + scanners: vuln,secret,misconfig,license + github-pat: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Trivy scan results to GitHub Security tab + if: always() + uses: github/codeql-action/upload-sarif@v4 + with: + sarif_file: "trivy-results.sarif" diff --git a/.nvmrc b/.nvmrc index d5b283a..0a2925f 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.13.1 +26.5.1 diff --git a/Dockerfile b/Dockerfile index ad98a7b..743e47b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,23 @@ +ARG NODE_VERSION=26.5.1 +ARG PNPM_VERSION=10.33.2 + # ---- Base Stage ---- -FROM node:22-alpine AS base +FROM node:${NODE_VERSION}-alpine AS base +ARG PNPM_VERSION WORKDIR /usr/src/app # ---- Dependencies Stage ---- FROM base AS deps -RUN npm install -g pnpm@10.33.2 -COPY package.json pnpm-lock.yaml ./ +RUN npm install -g pnpm@${PNPM_VERSION} +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ RUN pnpm install --frozen-lockfile COPY prisma ./prisma RUN DATABASE_URL="postgresql://user:pass@localhost:5432/db?schema=public" pnpm prisma generate # ---- Build Stage ---- FROM base AS build -RUN npm install -g pnpm@10.33.2 +ARG PNPM_VERSION +RUN npm install -g pnpm@${PNPM_VERSION} COPY --from=deps /usr/src/app/node_modules ./node_modules COPY . . RUN pnpm build @@ -22,10 +27,20 @@ FROM deps AS prod-deps RUN pnpm prune --prod # ---- Production Stage ---- -FROM base AS production -ENV NODE_ENV=production -COPY --from=build /usr/src/app/dist ./dist -COPY --from=prod-deps /usr/src/app/node_modules ./node_modules +FROM alpine:3.24 AS production +ARG NODE_VERSION +RUN apk upgrade --no-cache \ + && apk add --no-cache nodejs-current=${NODE_VERSION}-r0 \ + && addgroup -g 10001 app \ + && adduser -D -u 10001 -G app -h /home/app app + +ENV NODE_ENV=production \ + HOME=/home/app +WORKDIR /usr/src/app +COPY --from=build --chown=10001:10001 /usr/src/app/dist ./dist +COPY --from=prod-deps --chown=10001:10001 /usr/src/app/node_modules ./node_modules + +USER app EXPOSE 3000 diff --git a/README.md b/README.md index 567605b..1e30f1b 100644 --- a/README.md +++ b/README.md @@ -106,4 +106,12 @@ Optional: ## Local Development -Run `nvm use`, install dependencies with `pnpm install`, generate Prisma with `pnpm prisma generate`, and start the service with `pnpm start:dev`. +Node.js 26.5.1 and pnpm 10.33.2 are the supported local toolchain. Run +`nvm use`, install dependencies with `pnpm install`, generate Prisma with +`pnpm prisma generate`, and start the service with `pnpm start:dev`. + +## Container Runtime + +The production image uses Alpine 3.24's patched Node.js 26.5.1 package and runs +as the unprivileged `app` user (UID 10001). Build-only package managers and +development dependencies are excluded from the final image. diff --git a/package.json b/package.json index ba63ab8..338ffc6 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand" }, "dependencies": { - "@nestjs/cli": "^11.0.12", "@nestjs/common": "^11.1.9", "@nestjs/config": "^4.0.2", "@nestjs/core": "^11.1.9", @@ -37,6 +36,7 @@ "devDependencies": { "@eslint/eslintrc": "^3.2.0", "@eslint/js": "^9.18.0", + "@nestjs/cli": "^11.0.12", "@nestjs/schematics": "^11.0.9", "@nestjs/testing": "^11.1.9", "@types/jest": "^29.5.8", @@ -54,16 +54,5 @@ "ts-node": "^10.9.2", "typescript": "^5.4.2", "typescript-eslint": "^8.38.0" - }, - "pnpm": { - "onlyBuiltDependencies": [ - "@prisma/client", - "@prisma/engines", - "prisma" - ], - "ignoredBuiltDependencies": [ - "@scarf/scarf", - "dtrace-provider" - ] } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e7bf97..4853048 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,13 +4,21 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + axios: 1.18.1 + brace-expansion@^1.0.0: 1.1.18 + brace-expansion@^2.0.0: 2.1.4 + brace-expansion@>=3: 5.0.9 + deepmerge-ts: 8.0.0 + fast-uri@^3.0.0: 3.1.5 + js-yaml@^3: 3.15.1 + js-yaml@^4: 4.3.1 + multer: 2.2.0 + importers: .: dependencies: - '@nestjs/cli': - specifier: ^11.0.12 - version: 11.0.23(@types/node@20.19.43)(prettier@3.8.5) '@nestjs/common': specifier: ^11.1.9 version: 11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.1.14)(rxjs@7.8.2) @@ -54,6 +62,9 @@ importers: '@eslint/js': specifier: ^9.18.0 version: 9.39.4 + '@nestjs/cli': + specifier: ^11.0.12 + version: 11.0.23(@types/node@20.19.43)(prettier@3.8.5) '@nestjs/schematics': specifier: ^11.0.9 version: 11.1.0(chokidar@4.0.3)(prettier@3.8.5)(typescript@5.9.3) @@ -1086,6 +1097,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -1171,8 +1186,8 @@ packages: asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - axios@0.30.3: - resolution: {integrity: sha512-5/tmEb6TmE/ax3mdXBc/Mi6YdPGxQsv+0p5YlciXWt3PHIn0VamqCXhRMtScnwY3lbgSXLneOuXAKUhgmSRpwg==} + axios@1.18.1: + resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} @@ -1225,15 +1240,15 @@ packages: resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} engines: {node: '>=18'} - brace-expansion@1.1.15: - resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} + brace-expansion@1.1.18: + resolution: {integrity: sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==} - brace-expansion@2.1.1: - resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + brace-expansion@2.1.4: + resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==} - brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} - engines: {node: 18 || 20 || >=22} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} @@ -1480,8 +1495,8 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - deepmerge-ts@7.1.5: - resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==} + deepmerge-ts@8.0.0: + resolution: {integrity: sha512-ICNjaP0ML+eSdEpJYQC46XiAn/UjAdwbEl0dE8p85ZTeNDinN4Kd4+9jS4OSAuH7st6eC7rQhsqTF5zIDaUm2g==} engines: {node: '>=16.0.0'} deepmerge@4.3.1: @@ -1738,8 +1753,8 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@3.1.2: - resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + fast-uri@3.1.5: + resolution: {integrity: sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==} fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -1934,6 +1949,10 @@ packages: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -2193,16 +2212,12 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@3.15.0: - resolution: {integrity: sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==} + js-yaml@3.15.1: + resolution: {integrity: sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==} hasBin: true - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} - hasBin: true - - js-yaml@4.3.0: - resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} + js-yaml@4.3.1: + resolution: {integrity: sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==} hasBin: true jsesc@3.1.0: @@ -2439,8 +2454,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - multer@2.1.1: - resolution: {integrity: sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==} + multer@2.2.0: + resolution: {integrity: sha512-6rdyFg2kLrMh9Jee7/BMPuV9lEAd7lLW2YUpF9/YxR7njyoUwwQ0ZPh3TaIY50Sw6vlyD2HW3wGOkTS4P79xrQ==} engines: {node: '>= 10.16.0'} mute-stream@2.0.0: @@ -2656,8 +2671,9 @@ packages: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} @@ -3534,7 +3550,7 @@ snapshots: globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.3.0 + js-yaml: 4.3.1 minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -3710,7 +3726,7 @@ snapshots: camelcase: 5.3.1 find-up: 4.1.0 get-package-type: 0.1.0 - js-yaml: 3.15.0 + js-yaml: 3.15.1 resolve-from: 5.0.0 '@istanbuljs/schema@0.1.6': {} @@ -3996,7 +4012,7 @@ snapshots: '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.27)(reflect-metadata@0.1.14)(rxjs@7.8.2) cors: 2.8.6 express: 5.2.1 - multer: 2.1.1 + multer: 2.2.0 path-to-regexp: 8.4.2 tslib: 2.8.1 transitivePeerDependencies: @@ -4021,7 +4037,7 @@ snapshots: '@nestjs/common': 11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.1.14)(rxjs@7.8.2) '@nestjs/core': 11.1.27(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.1.14)(rxjs@7.8.2))(@nestjs/platform-express@11.1.27)(reflect-metadata@0.1.14)(rxjs@7.8.2) '@nestjs/mapped-types': 2.1.1(@nestjs/common@11.1.27(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.1.14)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.1.14) - js-yaml: 4.1.1 + js-yaml: 4.3.1 lodash: 4.18.1 path-to-regexp: 8.4.2 reflect-metadata: 0.1.14 @@ -4060,7 +4076,7 @@ snapshots: '@prisma/config@6.19.3': dependencies: c12: 3.1.0 - deepmerge-ts: 7.1.5 + deepmerge-ts: 8.0.0 effect: 3.21.0 empathic: 2.0.0 transitivePeerDependencies: @@ -4501,6 +4517,12 @@ snapshots: acorn@8.17.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + ajv-formats@2.1.1(ajv@8.20.0): optionalDependencies: ajv: 8.20.0 @@ -4528,14 +4550,14 @@ snapshots: ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.2 + fast-uri: 3.1.5 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.2 + fast-uri: 3.1.5 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 @@ -4576,13 +4598,15 @@ snapshots: asynckit@0.4.0: {} - axios@0.30.3: + axios@1.18.1: dependencies: follow-redirects: 1.16.0 form-data: 4.0.6 - proxy-from-env: 1.1.0 + https-proxy-agent: 5.0.1 + proxy-from-env: 2.1.0 transitivePeerDependencies: - debug + - supports-color babel-jest@29.7.0(@babel/core@7.29.7): dependencies: @@ -4671,16 +4695,16 @@ snapshots: transitivePeerDependencies: - supports-color - brace-expansion@1.1.15: + brace-expansion@1.1.18: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.1.1: + brace-expansion@2.1.4: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.6: + brace-expansion@5.0.9: dependencies: balanced-match: 4.0.4 @@ -4874,7 +4898,7 @@ snapshots: cosmiconfig@8.3.6(typescript@5.9.3): dependencies: import-fresh: 3.3.1 - js-yaml: 4.3.0 + js-yaml: 4.3.1 parse-json: 5.2.0 path-type: 4.0.0 optionalDependencies: @@ -4911,7 +4935,7 @@ snapshots: deep-is@0.1.4: {} - deepmerge-ts@7.1.5: {} + deepmerge-ts@8.0.0: {} deepmerge@4.3.1: {} @@ -5187,7 +5211,7 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@3.1.2: {} + fast-uri@3.1.5: {} fastq@1.20.1: dependencies: @@ -5411,6 +5435,13 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} iconv-lite@0.7.2: @@ -5836,16 +5867,12 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@3.15.0: + js-yaml@3.15.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 - - js-yaml@4.3.0: + js-yaml@4.3.1: dependencies: argparse: 2.0.1 @@ -6033,15 +6060,15 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.6 + brace-expansion: 5.0.9 minimatch@3.1.5: dependencies: - brace-expansion: 1.1.15 + brace-expansion: 1.1.18 minimatch@9.0.9: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 2.1.4 minimist@1.2.8: {} @@ -6057,7 +6084,7 @@ snapshots: ms@2.1.3: {} - multer@2.1.1: + multer@2.2.0: dependencies: append-field: 1.0.0 busboy: 1.6.0 @@ -6255,7 +6282,7 @@ snapshots: forwarded: 0.2.0 ipaddr.js: 1.9.1 - proxy-from-env@1.1.0: {} + proxy-from-env@2.1.0: {} punycode@2.3.1: {} @@ -6534,7 +6561,7 @@ snapshots: tc-core-library-js@https://codeload.github.com/topcoder-platform/tc-core-library-js/tar.gz/323567bc50e433ae488b656f9f94e821ebaf3062: dependencies: - axios: 0.30.3 + axios: 1.18.1 bunyan: 1.8.15 jsonwebtoken: 9.0.3 jwks-rsa: 3.2.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..c23daa8 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,22 @@ +packages: + - . + +overrides: + axios: 1.18.1 + 'brace-expansion@^1.0.0': 1.1.18 + 'brace-expansion@^2.0.0': 2.1.4 + 'brace-expansion@>=3': 5.0.9 + deepmerge-ts: 8.0.0 + 'fast-uri@^3.0.0': 3.1.5 + 'js-yaml@^3': 3.15.1 + 'js-yaml@^4': 4.3.1 + multer: 2.2.0 + +onlyBuiltDependencies: + - '@prisma/client' + - '@prisma/engines' + - prisma + +ignoredBuiltDependencies: + - '@scarf/scarf' + - dtrace-provider diff --git a/src/contracts/contracts.service.ts b/src/contracts/contracts.service.ts index ddee2e2..f628bc4 100644 --- a/src/contracts/contracts.service.ts +++ b/src/contracts/contracts.service.ts @@ -178,7 +178,7 @@ export class ContractsService { * * @returns Number of active contracts whose end date has not passed. */ - async countActive(): Promise { + countActive(): Promise { return this.db.contract.count({ where: { status: ContractStatus.active, diff --git a/src/renewals/renewals.service.ts b/src/renewals/renewals.service.ts index 9f8688a..90d60bd 100644 --- a/src/renewals/renewals.service.ts +++ b/src/renewals/renewals.service.ts @@ -244,7 +244,7 @@ export class RenewalsService { * * @returns Number of renewals that have not reached PO release. */ - async countActive(): Promise { + countActive(): Promise { return this.db.renewal.count({ where: { stage: { not: TERMINAL_RENEWAL_STAGE }, diff --git a/src/vendors/vendors.service.ts b/src/vendors/vendors.service.ts index b0f19a6..7e10e1d 100644 --- a/src/vendors/vendors.service.ts +++ b/src/vendors/vendors.service.ts @@ -127,7 +127,7 @@ export class VendorsService { * * @returns Total number of vendors. */ - async count(): Promise { + count(): Promise { return this.db.vendor.count(); }