Skip to content

Commit 6fe2dbf

Browse files
paccloudclaude
andauthored
fix: tech debt cleanup + security audit (#17)
* refactor: delete dead fish data files and orphaned data copies Remove 6 unused files (~2,500 lines). Only fish_data_v3.js is imported anywhere in the codebase — v1, v2, corrupted backup, root data/ copies, and issue list.md were all dead weight. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: sync yield auto-scaling between Express and Vercel backends The Vercel API auto-scaled decimal yields < 1 to percentages (0.42 → 42) but the Express server did not. Same Excel upload now produces consistent yield values regardless of which backend processes it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: return 201 status for resource creation in Express server POST /api/register, /api/save-calc, and /api/user-data now return 201 to match the Vercel API endpoints and HTTP conventions for resource creation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: standardize CSV export date format between backends Express server used toLocaleDateString() (date only) while Vercel API used toLocaleString() (date + time). Standardized on toLocaleString(). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: wire data validation script and update gitignore Add npm run validate-data script for fish_data_v3 QA checks. Add favicon-preview.html to gitignore (dev artifact). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: security audit — replace xlsx with exceljs, upgrade vulnerable deps - Replace xlsx (unmaintained, CVEs) with exceljs for Excel/CSV parsing in both server/server.js and api/upload-data.js - Upgrade sqlite3 5.x → 6.x (fixes tar/node-gyp/cacache chain) - Upgrade bcrypt 5.x → 6.x (fixes @mapbox/node-pre-gyp/tar chain) - Upgrade multer 2.0 → 2.1 - Drop .xls support (only .xlsx and .csv) - Run npm audit fix across all three package roots Remaining unfixable: elliptic via @stackframe/react (no upstream fix, removed in Cloudflare migration), serialize-javascript via workbox-build (no upstream fix yet for @rollup/plugin-terser). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2f07a08 commit 6fe2dbf

15 files changed

Lines changed: 4998 additions & 6654 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,6 @@ worktrees/
4747
# Design and datasets
4848
Design Inspiration Ideas/
4949
datasets/
50+
51+
# Dev artifacts
52+
favicon-preview.html

api/upload-data.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import formidable from 'formidable';
2-
import * as xlsx from 'xlsx';
2+
import ExcelJS from 'exceljs';
33
import { promises as fs } from 'fs';
44
import { query } from './_lib/db.js';
55
import { requireAuth } from './_lib/auth.js';
@@ -43,10 +43,30 @@ async function handler(req, res) {
4343
const buffer = await fs.readFile(file.filepath);
4444

4545
// Parse Excel/CSV file
46-
const workbook = xlsx.read(buffer, { type: 'buffer' });
47-
const sheetName = workbook.SheetNames[0];
48-
const sheet = workbook.Sheets[sheetName];
49-
const data = xlsx.utils.sheet_to_json(sheet);
46+
const workbook = new ExcelJS.Workbook();
47+
const ext = (file.originalFilename || '').split('.').pop()?.toLowerCase();
48+
if (ext === 'csv') {
49+
await workbook.csv.read(new (await import('stream')).Readable({
50+
read() { this.push(buffer); this.push(null); }
51+
}));
52+
} else {
53+
await workbook.xlsx.load(buffer);
54+
}
55+
const worksheet = workbook.worksheets[0];
56+
if (!worksheet) throw new Error('No worksheet found');
57+
const headers = [];
58+
worksheet.getRow(1).eachCell((cell, colNumber) => {
59+
headers[colNumber] = cell.value != null ? String(cell.value) : `Column${colNumber}`;
60+
});
61+
const data = [];
62+
worksheet.eachRow((row, rowNumber) => {
63+
if (rowNumber === 1) return;
64+
const obj = {};
65+
row.eachCell((cell, colNumber) => {
66+
if (headers[colNumber]) obj[headers[colNumber]] = cell.value;
67+
});
68+
if (Object.keys(obj).length > 0) data.push(obj);
69+
});
5070

5171
let count = 0;
5272

app/package-lock.json

Lines changed: 3221 additions & 2771 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"build": "vite build",
99
"lint": "eslint .",
1010
"preview": "vite preview",
11-
"test": "vitest run"
11+
"test": "vitest run",
12+
"validate-data": "node src/data/validate_fish_data.js"
1213
},
1314
"dependencies": {
1415
"@stackframe/react": "^2.7.1",

0 commit comments

Comments
 (0)