chore: harden reliability checks #2

Merged
nalalangan merged 67 commits from main-new into main 2026-05-25 14:28:32 -09:00
7 changed files with 539 additions and 2395 deletions
Showing only changes of commit d2fe873956 - Show all commits

62
backend/build.js Normal file
View File

@ -0,0 +1,62 @@
"use strict";
const fs = require("fs");
const path = require("path");
const rootDir = __dirname;
const distDir = path.join(rootDir, "dist");
const directoriesToCopy = [
"config",
"constants",
"controllers",
"db",
"middleware",
"models",
"routes",
"services",
"utils",
"public",
];
const filesToCopy = ["app.js", "server.js", "package.json", "package-lock.json"];
function copyFile(sourcePath, targetPath) {
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
fs.copyFileSync(sourcePath, targetPath);
}
function copyDirectory(sourceDir, targetDir) {
if (!fs.existsSync(sourceDir)) {
return;
}
for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
const sourcePath = path.join(sourceDir, entry.name);
const targetPath = path.join(targetDir, entry.name);
if (entry.isDirectory()) {
copyDirectory(sourcePath, targetPath);
continue;
}
if (entry.isFile()) {
copyFile(sourcePath, targetPath);
}
}
}
fs.mkdirSync(distDir, { recursive: true });
for (const directory of directoriesToCopy) {
copyDirectory(path.join(rootDir, directory), path.join(distDir, directory));
}
for (const file of filesToCopy) {
const sourcePath = path.join(rootDir, file);
if (fs.existsSync(sourcePath)) {
copyFile(sourcePath, path.join(distDir, file));
}
}
console.log(`Backend build copied runtime files to ${path.relative(rootDir, distDir)}`);

2206
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,13 +10,12 @@
"sharp": "^0.34.5"
},
"devDependencies": {
"cpx": "^1.5.0",
"esbuild": "^0.25.5",
"nodemon": "^3.1.11",
"rimraf": "^6.0.1"
},
"scripts": {
"build": "rimraf dist && node build.js && cpx \"public/**/*\" dist/public",
"build": "rimraf dist && node build.js",
"dev": "nodemon server.js"
}
}

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"typecheck": "tsc -b",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview",
@ -19,8 +20,8 @@
"react-router-dom": "^7.9.6"
},
"devDependencies": {
"@playwright/test": "^1.52.0",
"@eslint/js": "^9.39.1",
"@playwright/test": "^1.58.2",
"@types/node": "^24.10.0",
"@types/react": "^19.2.5",
"@types/react-dom": "^19.2.2",

48
package-lock.json generated
View File

@ -1,10 +1,10 @@
{
"name": "Costco-Grocery-List",
"name": "grocery-app",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "Costco-Grocery-List",
"name": "grocery-app",
"devDependencies": {
"cross-env": "^10.1.0",
"jest": "^30.2.0",
@ -1544,9 +1544,9 @@
}
},
"node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
"integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
@ -3130,9 +3130,9 @@
}
},
"node_modules/jest-util/node_modules/picomatch": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
"dev": true,
"engines": {
"node": ">=12"
@ -3421,12 +3421,12 @@
}
},
"node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"version": "9.0.9",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
"brace-expansion": "^2.0.2"
},
"engines": {
"node": ">=16 || 14 >=14.17"
@ -3671,9 +3671,9 @@
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
"dev": true,
"engines": {
"node": ">=8.6"
@ -3746,9 +3746,9 @@
]
},
"node_modules/qs": {
"version": "6.14.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
"version": "6.15.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
"dev": true,
"dependencies": {
"side-channel": "^1.1.0"
@ -4191,9 +4191,9 @@
}
},
"node_modules/test-exclude/node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
@ -4222,9 +4222,9 @@
}
},
"node_modules/test-exclude/node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"

View File

@ -1,5 +1,18 @@
{
"name": "grocery-app",
"private": true,
"scripts": {
"dev:backend": "npm --prefix backend run dev",
"dev:frontend": "npm --prefix frontend run dev",
"build": "npm run build:backend && npm run build:frontend",
"build:backend": "npm --prefix backend run build",
"build:frontend": "npm --prefix frontend run build",
"lint": "npm --prefix frontend run lint",
"typecheck": "npm --prefix frontend run typecheck",
"audit": "npm run audit:root && npm run audit:backend && npm run audit:frontend",
"audit:root": "npm audit",
"audit:backend": "npm --prefix backend audit",
"audit:frontend": "npm --prefix frontend audit",
"db:migrate": "node scripts/db-migrate.js",
"db:migrate:status": "node scripts/db-migrate-status.js",
"db:migrate:verify": "node scripts/db-migrate-verify.js",