From e9ec6d5b4d9b7b49c8feece408b900c4750fdd7f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 28 Oct 2026 11:26:32 +1100 Subject: [PATCH] fix(frontend): upgrade zod to 4.6.7 to clear the last npm audit finding (#132) zod below 4.6.6 can exhaust memory while validating oversized constrained collections. zod 4 needs a key schema for z.record, so the table rows schema now passes z.string(). A new contract test covers that schema; it fails if the cell schema is loosened. npm audit: 0 vulnerabilities. vitest 141 passed. tsc 0. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019YPoXzBSj89ZHgw7nfTmbB --- csv-table-hub-main/package-lock.json | 35 +++---------------- csv-table-hub-main/package.json | 2 +- .../src/__tests__/table-rows-contract.test.ts | 27 ++++++++++++++ csv-table-hub-main/src/lib/csv.functions.ts | 2 +- 4 files changed, 33 insertions(+), 33 deletions(-) create mode 100644 csv-table-hub-main/src/__tests__/table-rows-contract.test.ts diff --git a/csv-table-hub-main/package-lock.json b/csv-table-hub-main/package-lock.json index 824bcb0..7a47fbb 100644 --- a/csv-table-hub-main/package-lock.json +++ b/csv-table-hub-main/package-lock.json @@ -57,7 +57,7 @@ "tw-animate-css": "^1.3.4", "vaul": "^1.1.2", "vite-tsconfig-paths": "^6.0.2", - "zod": "^3.24.2" + "zod": "^4.6.7" }, "devDependencies": { "@eslint/js": "^9.32.0", @@ -3987,15 +3987,6 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, - "node_modules/@tanstack/router-generator/node_modules/zod": { - "version": "4.6.7", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", - "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/@tanstack/router-plugin": { "version": "1.168.48", "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.168.48.tgz", @@ -4044,15 +4035,6 @@ } } }, - "node_modules/@tanstack/router-plugin/node_modules/zod": { - "version": "4.6.7", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", - "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/@tanstack/router-utils": { "version": "1.162.4", "resolved": "https://registry.npmjs.org/@tanstack/router-utils/-/router-utils-1.162.4.tgz", @@ -4168,15 +4150,6 @@ "node": ">=20.16.0" } }, - "node_modules/@tanstack/start-plugin-core/node_modules/zod": { - "version": "4.6.7", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", - "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, "node_modules/@tanstack/start-server-core": { "version": "1.169.45", "resolved": "https://registry.npmjs.org/@tanstack/start-server-core/-/start-server-core-1.169.45.tgz", @@ -8924,9 +8897,9 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.7.tgz", + "integrity": "sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/csv-table-hub-main/package.json b/csv-table-hub-main/package.json index cf64506..cfea108 100644 --- a/csv-table-hub-main/package.json +++ b/csv-table-hub-main/package.json @@ -66,7 +66,7 @@ "tw-animate-css": "^1.3.4", "vaul": "^1.1.2", "vite-tsconfig-paths": "^6.0.2", - "zod": "^3.24.2" + "zod": "^4.6.7" }, "devDependencies": { "@eslint/js": "^9.32.0", diff --git a/csv-table-hub-main/src/__tests__/table-rows-contract.test.ts b/csv-table-hub-main/src/__tests__/table-rows-contract.test.ts new file mode 100644 index 0000000..b30614c --- /dev/null +++ b/csv-table-hub-main/src/__tests__/table-rows-contract.test.ts @@ -0,0 +1,27 @@ +// The table rows response is parsed with z.record, whose signature changed in zod 4 (#132). +import { afterEach, expect, it, vi } from "vitest"; +import { previewCsvTable } from "@/lib/csv.functions"; + +function mockFetchJson(payload: unknown) { + vi.stubGlobal( + "fetch", + vi + .fn() + .mockResolvedValue( + new Response(JSON.stringify(payload), { headers: { "content-type": "application/json" } }), + ), + ); +} + +afterEach(() => vi.unstubAllGlobals()); + +it("accepts rows of string, number, boolean and null cells", async () => { + const rows = [{ name: "a", n: 1, ok: true, gone: null }]; + mockFetchJson({ rows }); + await expect(previewCsvTable("t")).resolves.toEqual({ rows }); +}); + +it("rejects a row cell that is not a scalar", async () => { + mockFetchJson({ rows: [{ nested: { x: 1 } }] }); + await expect(previewCsvTable("t")).rejects.toThrow(/Unexpected response shape/); +}); diff --git a/csv-table-hub-main/src/lib/csv.functions.ts b/csv-table-hub-main/src/lib/csv.functions.ts index 8c6d0b2..d073be8 100644 --- a/csv-table-hub-main/src/lib/csv.functions.ts +++ b/csv-table-hub-main/src/lib/csv.functions.ts @@ -98,7 +98,7 @@ const csvFileSummaryListSchema = z.array(csvFileSummarySchema); const previewRowValueSchema = z.union([z.string(), z.number(), z.boolean(), z.null()]); const previewRowsSchema = z.object({ - rows: z.array(z.record(previewRowValueSchema)), + rows: z.array(z.record(z.string(), previewRowValueSchema)), }); async function apiFetch(path: string, schema: z.ZodType, options?: RequestInit): Promise {