deps: bump Tier-A patches + react-day-picker 10 + esbuild 0.28

Successfully bumped:
- bullmq 5.76.6 → 5.76.8
- @tanstack/react-query 5.100.9 → 5.100.10
- @tanstack/react-query-devtools 5.100.9 → 5.100.10
- better-auth 1.6.9 → 1.6.10
- @playwright/test 1.59.1 → 1.60.0
- libphonenumber-js 1.12.43 → 1.13.1
- tailwind-merge 3.5.0 → 3.6.0
- vitest 4.1.5 → 4.1.6
- @vitest/coverage-v8 4.1.5 → 4.1.6
- lint-staged 17.0.3 → 17.0.4
- esbuild 0.27.7 → 0.28.0
- react-grab 0.1.33 → 0.1.34
- react-day-picker 9.14.0 → 10.0.0

react-day-picker 10 verified safe: probed v10 release notes against
src/components/ui/calendar.tsx — we use only v9-canonical APIs that
v10 preserves. Removed the `table` className entry from the wrapper
(v10 dropped it since the renderer is now CSS-grid, not table-based).

Tried + rolled back:
- @hookform/resolvers 3 → 5: stricter input/output inference broke
  every form using <{schema}, any, {schema}> implicit shape. Needs
  per-form refactor; parked.

Verified clean: pnpm audit (prod + dev) = 0 vulnerabilities;
pnpm exec tsc --noEmit clean; vitest 1293/1293 pass.

Remaining outdated (deliberately deferred — see docs/AUDIT-2026-05-12.md §34):
- next/eslint-config-next 15 → 16 (2-4 wk wait)
- zod 3 → 4 (couple with @hookform/resolvers 5; codemod-needed)
- tailwindcss 3 → 4 (focused-afternoon project)
- @types/node ^20.19 stays pinned to match runtime (audit decision)
- archiver 7 stays (no @types/archiver@8 published)
- eslint 9 stays (locked to eslint-config-next 15)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-12 17:33:24 +02:00
parent a7d0dd95e2
commit 82049eea92
5 changed files with 365 additions and 382 deletions

View File

@@ -6529,26 +6529,26 @@ major in?" prioritization.
## At a glance — what's outdated
| Package | Current | Latest | Bump size |
|---|---|---|---|
| `next` | 15.5.18 | 16.2.6 | major |
| `eslint-config-next` | 15.5.18 | 16.2.6 | major (matches next) |
| `zod` | 3.25.76 | 4.4.3 | major |
| `tailwindcss` | 3.4.19 | 4.3.0 | major |
| `@hookform/resolvers` | 3.10.0 | 5.2.2 | TWO majors |
| `archiver` | 7.0.1 | 8.0.0 | major |
| `react-day-picker` | 9.14.0 | 10.0.0 | major |
| `eslint` | 9.39.4 | 10.3.0 | major |
| `esbuild` | 0.27.7 | 0.28.0 | pre-1.0 minor (effectively major) |
| `@playwright/test` | 1.59.1 | 1.60.0 | minor |
| `libphonenumber-js` | 1.12.43 | 1.13.1 | minor |
| `tailwind-merge` | 3.5.0 | 3.6.0 | minor |
| `bullmq` | 5.76.6 | 5.76.8 | patch |
| `@tanstack/react-query` | 5.100.9 | 5.100.10 | patch |
| `better-auth` | 1.6.9 | 1.6.10 | patch |
| `vitest` | 4.1.5 | 4.1.6 | patch |
| `lint-staged` | 17.0.3 | 17.0.4 | patch |
| `@vitest/coverage-v8` | 4.1.5 | 4.1.6 | patch |
| Package | Current | Latest | Bump size |
| ----------------------- | ------- | -------- | --------------------------------- |
| `next` | 15.5.18 | 16.2.6 | major |
| `eslint-config-next` | 15.5.18 | 16.2.6 | major (matches next) |
| `zod` | 3.25.76 | 4.4.3 | major |
| `tailwindcss` | 3.4.19 | 4.3.0 | major |
| `@hookform/resolvers` | 3.10.0 | 5.2.2 | TWO majors |
| `archiver` | 7.0.1 | 8.0.0 | major |
| `react-day-picker` | 9.14.0 | 10.0.0 | major |
| `eslint` | 9.39.4 | 10.3.0 | major |
| `esbuild` | 0.27.7 | 0.28.0 | pre-1.0 minor (effectively major) |
| `@playwright/test` | 1.59.1 | 1.60.0 | minor |
| `libphonenumber-js` | 1.12.43 | 1.13.1 | minor |
| `tailwind-merge` | 3.5.0 | 3.6.0 | minor |
| `bullmq` | 5.76.6 | 5.76.8 | patch |
| `@tanstack/react-query` | 5.100.9 | 5.100.10 | patch |
| `better-auth` | 1.6.9 | 1.6.10 | patch |
| `vitest` | 4.1.5 | 4.1.6 | patch |
| `lint-staged` | 17.0.3 | 17.0.4 | patch |
| `@vitest/coverage-v8` | 4.1.5 | 4.1.6 | patch |
`@types/node` deliberately pinned to ^20.19 to match Node 20 runtime
(audit findings — was previously ^25 against a Node 20 runtime, which
@@ -6571,7 +6571,7 @@ verify and full vitest run.
## Tier B — Per-major analysis
### B-1 — Next.js 15.5 → 16.2 *(touches every API route + middleware)*
### B-1 — Next.js 15.5 → 16.2 _(touches every API route + middleware)_
**Upstream summary (via Context7):**
@@ -6580,6 +6580,7 @@ verify and full vitest run.
- Automated codemod: `npx @next/codemod@canary upgrade latest` handles the rename + most boilerplate.
**Risk for us:**
- `src/middleware.ts` rename is a 30-second edit; no semantic change for us because we don't depend on edge runtime.
- The Documenso webhook + websocket server custom-server path (`src/server.ts`) needs to be retested — Next 16 changed some internals around the custom-server contract.
- `eslint-config-next` must bump in lockstep (already at 15.5.18 → 16.2.6).
@@ -6589,7 +6590,7 @@ verify and full vitest run.
---
### B-2 — Zod 3 → 4 *(touches every validator file)*
### B-2 — Zod 3 → 4 _(touches every validator file)_
**Upstream summary (via Context7):**
@@ -6600,6 +6601,7 @@ verify and full vitest run.
- TypeScript server perf improvement (generic-class-signature simplification).
**Risk for us:**
- We have ~30 validator files using `z.string().email()` / `.uuid()` style and `{ message: '...' }` style throughout. Both still work in 4.x but produce deprecation warnings on every parse — noisy in logs.
- `@hookform/resolvers` v5 supports **both** Zod 3 and Zod 4 natively (auto-detects), so this couples cleanly with B-4 below.
- We don't use `z.function()` anywhere, so the biggest breaking change is a non-issue for us.
@@ -6608,7 +6610,7 @@ verify and full vitest run.
---
### B-3 — Tailwind CSS 3 → 4 *(touches `tailwind.config.ts`, `globals.css`, every dynamic-class site)*
### B-3 — Tailwind CSS 3 → 4 _(touches `tailwind.config.ts`, `globals.css`, every dynamic-class site)_
**Upstream summary (via Context7):**
@@ -6619,6 +6621,7 @@ verify and full vitest run.
- Official automated upgrade tool: `npx @tailwindcss/upgrade` (requires Node 20+, which we already use).
**Risk for us:**
- We have a custom `tailwind.config.ts` with brand tokens, CVA + tailwind-merge + clsx, plus the `tailwindcss-animate` plugin. The upgrade tool migrates most of this automatically; the manual review is the design-token spread across `globals.css`.
- shadcn/ui components (`components/ui/*`) use `cn()` + arbitrary values heavily. Some `[--variable]` syntax has changed in v4.
- `tailwindcss-animate` may not yet support v4 — need to confirm or swap for `tailwindcss-animated` (the v4 successor).
@@ -6627,7 +6630,7 @@ verify and full vitest run.
---
### B-4 — `@hookform/resolvers` 3 → 5 *(touches every form file)*
### B-4 — `@hookform/resolvers` 3 → 5 _(touches every form file)_
**Upstream summary (via Context7):**
@@ -6636,17 +6639,19 @@ verify and full vitest run.
- v4 was a transitional version with the same external API; v5 is the stable cut.
**Risk for us:**
- Coupled with the Zod 4 upgrade — if we stay on Zod 3, v5 still works (the resolver detects Zod-3 schemas via shape probing). Bumping resolvers without bumping Zod is safe.
**Recommended:** **GO IN LOCKSTEP with B-2 (Zod 4).** Effort: 5 min once Zod 4 is in.
---
### B-5 — `archiver` 7 → 8 *(touches GDPR-export bundle + backup-restore)*
### B-5 — `archiver` 7 → 8 _(touches GDPR-export bundle + backup-restore)_
**Upstream summary:** Library "/gajus/archiver" not found in Context7 — fallback to npm changelog. We previously rolled back archiver@8 to archiver@7 (in commit `04a5949` per CLAUDE.md history) because of dropped default-export changes that broke our TS types. v8 stabilised since then.
**Risk for us:**
- Last time we tried this it broke. Read the v8 changelog before retrying.
- Used only for GDPR export + backup-restore — narrow blast radius. A failed upgrade is non-customer-facing.
@@ -6654,20 +6659,22 @@ verify and full vitest run.
---
### B-6 — `react-day-picker` 9 → 10 *(touches every date-picker site)*
### B-6 — `react-day-picker` 9 → 10 _(touches every date-picker site)_
**Upstream summary:** v10 is a recent cut. Without Context7 returning a hit on its changelog, treat as "investigate before pulling".
**Risk for us:**
- Used in ~6 surfaces (reminder form, EOI date fields, expense date, invoice due-date, dashboard date-range picker). A breaking change to the calendar render path would affect every form.
**Recommended:** **DEFER 2-3 weeks** to let bug reports surface. Effort to actually do it: ~1h once the spec is reviewed.
---
### B-7 — `eslint` 9 → 10 + `eslint-config-next` *(touches CI)*
### B-7 — `eslint` 9 → 10 + `eslint-config-next` _(touches CI)_
**Risk for us:**
- ESLint 10 likely drops support for some legacy rule configs.
- `eslint-config-next` should bump in lockstep with `next` (B-1).
@@ -6675,9 +6682,10 @@ verify and full vitest run.
---
### B-8 — `esbuild` 0.27 → 0.28 *(touches build pipeline)*
### B-8 — `esbuild` 0.27 → 0.28 _(touches build pipeline)_
**Risk for us:**
- We use esbuild via `pnpm.overrides` plus directly in `build:server` and `build:worker` scripts.
- Pre-1.0 minors at esbuild are typically very safe (Evan Wallace ships tight changelogs), but they do occasionally drop deprecated flags.

View File

@@ -56,13 +56,13 @@
"@radix-ui/react-tabs": "^1.1.13",
"@radix-ui/react-tooltip": "^1.2.8",
"@socket.io/redis-adapter": "^8.3.0",
"@tanstack/react-query": "^5.100.9",
"@tanstack/react-query-devtools": "^5.100.9",
"@tanstack/react-query": "^5.100.10",
"@tanstack/react-query-devtools": "^5.100.10",
"@tanstack/react-table": "^8.21.3",
"@types/pdfkit": "^0.17.6",
"archiver": "^7.0.1",
"better-auth": "^1.6.9",
"bullmq": "^5.76.6",
"better-auth": "^1.6.10",
"bullmq": "^5.76.8",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
@@ -72,7 +72,7 @@
"ioredis": "^5.10.1",
"iso-3166-2": "^1.0.0",
"jose": "^6.2.3",
"libphonenumber-js": "^1.12.43",
"libphonenumber-js": "^1.13.1",
"lucide-react": "^1.14.0",
"mailparser": "^3.9.8",
"minio": "^8.0.7",
@@ -86,7 +86,7 @@
"pino-pretty": "^13.1.3",
"postgres": "^3.4.9",
"react": "^19.2.6",
"react-day-picker": "^9.14.0",
"react-day-picker": "^10.0.0",
"react-dom": "^19.2.6",
"react-easy-crop": "^5.5.7",
"react-hook-form": "^7.75.0",
@@ -95,7 +95,7 @@
"socket.io": "^4.8.3",
"socket.io-client": "^4.8.3",
"sonner": "^2.0.7",
"tailwind-merge": "^3.5.0",
"tailwind-merge": "^3.6.0",
"tailwindcss-animate": "^1.0.7",
"tesseract.js": "^7.0.0",
"vaul": "^1.1.2",
@@ -104,7 +104,7 @@
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.5",
"@playwright/test": "^1.59.1",
"@playwright/test": "^1.60.0",
"@types/archiver": "^7.0.0",
"@types/iso-3166-2": "^1.0.4",
"@types/mailparser": "^3.4.6",
@@ -112,23 +112,23 @@
"@types/nodemailer": "^8.0.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitest/coverage-v8": "^4.1.5",
"@vitest/coverage-v8": "^4.1.6",
"autoprefixer": "^10.5.0",
"dotenv": "^17.4.2",
"drizzle-kit": "^0.31.10",
"esbuild": "^0.27.7",
"esbuild": "^0.28.0",
"eslint": "^9.39.4",
"eslint-config-next": "15.5.18",
"eslint-config-prettier": "^10.1.8",
"husky": "^9.1.7",
"lint-staged": "^17.0.3",
"lint-staged": "^17.0.4",
"postcss": "^8.5.14",
"prettier": "^3.8.3",
"react-grab": "^0.1.33",
"react-grab": "^0.1.34",
"tailwindcss": "^3.4.19",
"tsx": "^4.21.0",
"typescript": "^6.0.3",
"vitest": "^4.1.5"
"vitest": "^4.1.6"
},
"pnpm": {
"overrides": {

630
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -73,7 +73,6 @@ function Calendar({
: '[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5',
defaultClassNames.caption_label,
),
table: 'w-full border-collapse',
weekdays: cn('flex', defaultClassNames.weekdays),
weekday: cn(
'text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal',
@@ -85,6 +84,10 @@ function Calendar({
'text-muted-foreground select-none text-[0.8rem]',
defaultClassNames.week_number,
),
// NB: the 'table' className was removed in react-day-picker 10 —
// the renderer is now CSS-grid based, so the table-derived class
// doesn't apply. shadcn's older Calendar wrapper had it; we drop
// it on the v10 bump.
day: cn(
'group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md',
defaultClassNames.day,

View File

@@ -1,12 +1,7 @@
import { and, asc, eq } from 'drizzle-orm';
import { db } from '@/lib/db';
import {
documentFolders,
documents,
files,
type DocumentFolder,
} from '@/lib/db/schema/documents';
import { documentFolders, documents, files, type DocumentFolder } from '@/lib/db/schema/documents';
import { clients } from '@/lib/db/schema/clients';
import { companies } from '@/lib/db/schema/companies';
import { yachts } from '@/lib/db/schema/yachts';
@@ -231,10 +226,7 @@ export async function moveFolder(
return await db.transaction(async (tx) => {
if (newParentId !== null) {
const newParent = await tx.query.documentFolders.findFirst({
where: and(
eq(documentFolders.id, newParentId),
eq(documentFolders.portId, portId),
),
where: and(eq(documentFolders.id, newParentId), eq(documentFolders.portId, portId)),
});
if (!newParent) throw new ValidationError('Invalid parent folder');
@@ -245,9 +237,7 @@ export async function moveFolder(
const seen = new Set<string>([newParent.id]);
while (cursor) {
if (cursor === folderId) {
throw new ValidationError(
'Cannot move a folder under one of its descendants (cycle)',
);
throw new ValidationError('Cannot move a folder under one of its descendants (cycle)');
}
if (seen.has(cursor)) break; // defensive — pre-existing cycle, bail
seen.add(cursor);
@@ -628,7 +618,11 @@ export async function syncEntityFolderName(
entityId: folder.id,
oldValue: { name: folder.name },
newValue: { name: candidate },
metadata: { type: 'folder_entity_rename_sync', entity: entityType, sourceEntityId: entityId },
metadata: {
type: 'folder_entity_rename_sync',
entity: entityType,
sourceEntityId: entityId,
},
});
return;
}