8b77656bb7
Bring backend and frontend to the latest stable releases (no pre-releases), including major upgrades that required code migration. Both projects pass typecheck and production builds. Backend - NestJS 10 -> 11 (common/core/platform-express/jwt/passport/bull/cli/ schematics/testing), @nestjs/config 3->4, @nestjs/swagger 7->11, @nestjs/typeorm 10->11 - @kubernetes/client-node 0.21 -> 1.4: migrate ~200+ call sites across 6 services to the v1 single-object argument API, unwrapped responses, err.code, setHeaderOptions for patch content-type, applyToHTTPSOptions. Add regression spec k8s-client-v1-migration.spec.ts. - typeorm 0.3 -> 1.0: relations/select string arrays -> object form - uuid 9->14 (drops @types/uuid), multer 1->2, bcrypt 5->6, helmet 7->8, class-validator 0.14->0.15 - TypeScript 5->6, ESLint 8->9, @typescript-eslint 6->8, jest 29->30, @types/node 20->24; tsconfig: strictPropertyInitialization:false, ignoreDeprecations, rootDir, explicit types[] - @nestjs/config 4: jwt.strategy uses getOrThrow; @types/express kept at 4 (Nest 11 runs Express 4) Frontend - React 18->19, Next 14->16 (async params via official codemod), Tailwind 3->4 (@tailwindcss/postcss, @import + @config, inline custom @apply), framer-motion 11->12, zustand 4->5, three 0.169->0.184, @react-three/* majors - TypeScript 5->6 (tsconfig target es5->ES2017), ESLint 8->9, eslint-config-next 14->16 Infra/docs - Dockerfiles node:20-alpine -> node:24-alpine (require-esm for k8s client) - Add UPGRADE.md / UPGRADE.en.md; refresh README tech-stack versions Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
164 lines
8.1 KiB
Markdown
164 lines
8.1 KiB
Markdown
# Dependency Upgrade — Latest Stable Versions
|
||
|
||
Branch: `chore/upgrade-dependencies-latest` (based on `feat/abrban-landing`)
|
||
🌐 Persian version: [UPGRADE.md](UPGRADE.md)
|
||
|
||
All backend and frontend dependencies were upgraded to their **latest stable** release
|
||
(no pre-releases), including major upgrades that required code migration. Both projects
|
||
pass type-checking and production builds.
|
||
|
||
---
|
||
|
||
## Status
|
||
|
||
| Project | Typecheck | Build | Tests |
|
||
|---|---|---|---|
|
||
| **backend** | ✅ `tsc` clean | ✅ `nest build` | 95/96 pass (1 pre-existing helm failure, unrelated) + 6 new migration tests |
|
||
| **frontend** | ✅ `tsc` clean | ✅ `next build` (42 routes) | — |
|
||
|
||
> **Minimum runtime Node: 20.19** (because `@kubernetes/client-node@1` is ESM). Dockerfiles were bumped to `node:24-alpine` (LTS).
|
||
|
||
---
|
||
|
||
## Backend — `dependencies`
|
||
|
||
| Package | Before | After | Kind |
|
||
|---|---|---|---|
|
||
| `@kubernetes/client-node` | `^0.21.0` | `^1.4.0` | **major** |
|
||
| `@nestjs/bull` | `^10.1.0` | `^11.0.4` | major |
|
||
| `@nestjs/common` | `^10.3.0` | `^11.1.24` | major |
|
||
| `@nestjs/config` | `^3.1.0` | `^4.0.4` | major |
|
||
| `@nestjs/core` | `^10.3.0` | `^11.1.26` | major |
|
||
| `@nestjs/jwt` | `^10.2.0` | `^11.0.2` | major |
|
||
| `@nestjs/passport` | `^10.0.3` | `^11.0.5` | major |
|
||
| `@nestjs/platform-express` | `^10.3.0` | `^11.1.26` | major |
|
||
| `@nestjs/swagger` | `^7.2.0` | `^11.4.4` | major |
|
||
| `@nestjs/typeorm` | `^10.0.1` | `^11.0.1` | major |
|
||
| `bcrypt` | `^5.1.1` | `^6.0.0` | major |
|
||
| `class-validator` | `^0.14.1` | `^0.15.1` | minor (0.x) |
|
||
| `helmet` | `^7.1.0` | `^8.2.0` | major |
|
||
| `js-yaml` | `^4.1.0` | `^4.2.0` | minor |
|
||
| `multer` | `^1.4.5-lts.1` | `^2.1.1` | **major** |
|
||
| `pg` | `^8.11.0` | `^8.21.0` | minor |
|
||
| `rxjs` | `^7.8.1` | `^7.8.2` | patch (8 not yet stable) |
|
||
| `typeorm` | `^0.3.19` | `^1.0.0` | **major** |
|
||
| `uuid` | `^9.0.0` | `^14.0.0` | **major** |
|
||
|
||
Unchanged (already latest stable): `bull`, `class-transformer`, `handlebars`, `passport`, `passport-jwt`, `reflect-metadata`.
|
||
|
||
## Backend — `devDependencies`
|
||
|
||
| Package | Before | After |
|
||
|---|---|---|
|
||
| `@nestjs/cli` | `^10.3.0` | `^11.0.23` |
|
||
| `@nestjs/schematics` | `^10.1.0` | `^11.1.0` |
|
||
| `@nestjs/testing` | `^10.3.0` | `^11.1.26` |
|
||
| `@types/bcrypt` | `^5.0.2` | `^6.0.0` |
|
||
| `@types/jest` | `^29.5.11` | `^30.0.0` |
|
||
| `@types/multer` | `^1.4.11` | `^2.1.0` |
|
||
| `@types/node` | `^20.11.0` | `^24.0.0` |
|
||
| `@typescript-eslint/eslint-plugin` | `^6.19.0` | `^8.61.0` |
|
||
| `@typescript-eslint/parser` | `^6.19.0` | `^8.61.0` |
|
||
| `eslint` | `^8.56.0` | `^9.0.0` |
|
||
| `jest` | `^29.7.0` | `^30.4.2` |
|
||
| `prettier` | `^3.2.0` | `^3.8.4` |
|
||
| `ts-jest` | `^29.1.1` | `^29.4.11` |
|
||
| `typescript` | `^5.3.3` | `^6.0.0` |
|
||
| `@types/uuid` | `^9.0.7` | **removed** (`uuid@14` ships its own types) |
|
||
|
||
> **`@types/express` deliberately kept at `^4.17.21`**: NestJS 11 runs on Express **4** at runtime; `@types/express@5` only matches Express 5.
|
||
|
||
---
|
||
|
||
## Frontend — `dependencies`
|
||
|
||
| Package | Before | After | Kind |
|
||
|---|---|---|---|
|
||
| `react` | `^18.2.0` | `^19.2.7` | **major** |
|
||
| `react-dom` | `^18.2.0` | `^19.2.7` | **major** |
|
||
| `next` | `14.1.0` | `16.2.9` | **major (2 versions)** |
|
||
| `tailwindcss`* | `^3.4.1` | `^4.3.1` | **major** |
|
||
| `framer-motion` | `^11.18.2` | `^12.40.0` | **major** |
|
||
| `zustand` | `^4.5.0` | `^5.0.14` | **major** |
|
||
| `three` | `^0.169.0` | `^0.184.0` | minor (0.x, breaking) |
|
||
| `@react-three/fiber` | `^8.18.0` | `^9.6.1` | **major** |
|
||
| `@react-three/drei` | `^9.122.0` | `^10.7.7` | **major** |
|
||
| `@react-three/postprocessing` | `^2.19.1` | `^3.0.4` | **major** |
|
||
| `@tanstack/react-query` | `^5.17.0` | `^5.101.0` | minor |
|
||
| `axios` | `^1.6.0` | `^1.17.0` | minor |
|
||
| `lucide-react` | `^1.7.0` | `^1.18.0` | minor |
|
||
| `react-hook-form` | `^7.49.0` | `^7.79.0` | minor |
|
||
| `react-toastify` | `^11.0.5` | `^11.1.0` | minor |
|
||
|
||
\* `tailwindcss` lives in devDependencies; listed here for readability.
|
||
|
||
Unchanged: `clsx`, `lenis`.
|
||
|
||
## Frontend — `devDependencies`
|
||
|
||
| Package | Before | After |
|
||
|---|---|---|
|
||
| `@types/react` | `^18.2.0` | `^19.2.17` |
|
||
| `@types/react-dom` | `^18.2.0` | `^19.2.3` |
|
||
| `@types/three` | `^0.169.0` | `^0.184.1` |
|
||
| `@types/node` | `^20.11.0` | `^24.0.0` |
|
||
| `tailwindcss` | `^3.4.1` | `^4.3.1` |
|
||
| `eslint` | `^8.56.0` | `^9.0.0` |
|
||
| `eslint-config-next` | `14.1.0` | `16.2.9` |
|
||
| `postcss` | `^8.4.33` | `^8.5.15` |
|
||
| `typescript` | `^5.3.3` | `^6.0.3` |
|
||
| `@tailwindcss/postcss` | — | **`^4.3.1` (new)** |
|
||
| `autoprefixer` | `^10.4.17` | **removed** (Tailwind 4 handles vendor prefixing) |
|
||
|
||
---
|
||
|
||
## Code migrations required
|
||
|
||
### Backend
|
||
|
||
- **`@kubernetes/client-node` 0.x → 1.x** (the biggest task — ~200+ call sites across 6 files):
|
||
- Every API method moved from positional arguments to a **single options object**:
|
||
`readNamespacedPod(name, ns)` → `readNamespacedPod({ name, namespace })`.
|
||
- Responses are no longer wrapped in `{ body }` — they return **directly**: `res.body.items` → `res.items`.
|
||
- Error shape changed: `err.statusCode` → **`err.code`**.
|
||
- Patch `Content-Type` is set via `k8s.setHeaderOptions(...)` (the method's 2nd argument).
|
||
- `kc.applyToRequest(opts)` → `kc.applyToHTTPSOptions(opts)`.
|
||
- Files: `kubernetes/kubernetes.service.ts`, `build/build.service.ts`, `clusters/clusters.service.ts`,
|
||
`clusters/cluster-tools.service.ts`, `kubernetes/elasticsearch.service.ts`, `kubernetes/registry.service.ts`.
|
||
- **Regression test:** `kubernetes/k8s-client-v1-migration.spec.ts` — asserts the object-argument shape,
|
||
response unwrapping, and 404 detection via `err.code`.
|
||
- **TypeORM 0.3 → 1.0:** string-array `relations`/`select` is no longer accepted; converted to object form
|
||
(`relations: ['user']` → `relations: { user: true }`) across 9 services.
|
||
- **`@nestjs/config` 3 → 4:** `ConfigService.get()` now returns `T | undefined`; `auth/strategies/jwt.strategy.ts`
|
||
uses `getOrThrow<string>('jwt.secret')` (fails fast at boot if the secret is missing).
|
||
- **TypeScript 5 → 6** (in `backend/tsconfig.json`):
|
||
- `strictPropertyInitialization: false` (TS6 enables it alongside `strictNullChecks`; TypeORM entities rely on it being off).
|
||
- `ignoreDeprecations: "6.0"` (for `baseUrl`, removed in TS7 — still needed by `tsconfig-paths`).
|
||
- `rootDir: "./src"` (new TS6 emit requirement).
|
||
- `types: ["node", "jest", "multer"]` (TS6 no longer auto-includes every `@types/*`; these are ambient-augmentation-only packages).
|
||
|
||
### Frontend
|
||
|
||
- **Next 14 → 16:** `params`/`searchParams` are now `Promise`s; applied with the official codemod
|
||
`npx @next/codemod next-async-request-api` (in `app/[lang]/layout.tsx` and where needed).
|
||
- **TypeScript 6:** `target: "es5"` → `"ES2017"` in `frontend/tsconfig.json` (es5 is deprecated in TS6).
|
||
- **Tailwind 3 → 4:**
|
||
- `postcss.config.js`: the `tailwindcss` + `autoprefixer` plugins were replaced by **`@tailwindcss/postcss`**.
|
||
- `src/app/globals.css`: the three `@tailwind ...` directives were replaced with `@import 'tailwindcss';` + `@config '../../tailwind.config.ts';`
|
||
(so the existing JS config — `primary` colors and fonts — is loaded under v4).
|
||
- `@apply`s that composed **custom** classes (`@apply badge ...`, `@apply card ...`) were inlined
|
||
(v4 doesn't support `@apply`-ing custom classes).
|
||
|
||
### Infrastructure
|
||
|
||
- `backend/Dockerfile` and `frontend/Dockerfile`: base bumped from `node:20-alpine` to **`node:24-alpine`** (guarantees `require(esm)` for the k8s client and aligns with `@types/node@24`).
|
||
|
||
---
|
||
|
||
## Notes & follow-ups
|
||
|
||
- **Residual audit advisories:** backend has a few via a transitive chain (`bull` → old `uuid`); frontend has 2 moderate. They can't be fixed without breaking changes and live in indirect deps.
|
||
- **Next 16 warning:** the `middleware` file convention is deprecated in favor of `proxy` (still works). Rename `middleware.ts` → `proxy.ts` in a later pass.
|
||
- **Pre-existing failing test:** `helm.service.spec.ts › chartPath` asserts a property that doesn't exist on the service; it failed before this upgrade too and is unrelated.
|
||
- **Runtime validation:** with no real k8s cluster available, type-level correctness and builds are verified; before production, the k8s control-plane paths should be exercised against a test cluster.
|