From aa1dd59f06232e3d070d2b78355b9d5096fa95d8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:43:17 +0000 Subject: [PATCH 1/3] Initial plan From 282ebef336eecf093310dc5eb0d62cb085b9ae9c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:46:08 +0000 Subject: [PATCH 2/3] Initial plan for code quality review improvements Co-authored-by: Many0nne <97261063+Many0nne@users.noreply.github.com> --- package-lock.json | 93 +---------------------------------------------- 1 file changed, 1 insertion(+), 92 deletions(-) diff --git a/package-lock.json b/package-lock.json index 495354b..c28a1c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,6 @@ "commander": "^12.0.0", "cors": "^2.8.5", "express": "^4.18.2", - "http-proxy-middleware": "^2.0.6", "inquirer": "^8.2.7", "intermock": "^0.2.5", "pluralize": "^8.0.0", @@ -1715,15 +1714,6 @@ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "license": "MIT" }, - "node_modules/@types/http-proxy": { - "version": "1.17.17", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", - "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/inquirer": { "version": "8.2.12", "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.12.tgz", @@ -3051,12 +3041,6 @@ "node": ">= 0.6" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "license": "MIT" - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3257,26 +3241,6 @@ "node": ">=8" } }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/foreground-child": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", @@ -3591,44 +3555,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", - "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", - "license": "MIT", - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3898,18 +3824,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4901,6 +4815,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -5605,12 +5520,6 @@ "node": ">=0.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "license": "MIT" - }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", From 0093d7c82bd3728a6eef9e126e519d3fd303168d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 19:48:53 +0000 Subject: [PATCH 3/3] Code quality review: fix verbose logging, remove dead code, improve type safety, fix security vulnerabilities Co-authored-by: Many0nne <97261063+Many0nne@users.noreply.github.com> --- README.md | 2 +- package-lock.json | 20 +++++++++--------- src/core/router.ts | 22 ++++++++++++++------ src/server.ts | 1 + src/types/config.ts | 1 - src/utils/configPersistence.ts | 37 ++++++++++++++++++---------------- src/utils/logger.ts | 4 ++++ src/utils/typeMapping.ts | 5 ----- 8 files changed, 52 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index a08f1fe..1bb42a9 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ npm run dev npx ts-mock-proxy ``` -Y ou'll be prompted for: +You'll be prompted for: - Types directory location - Server port (default: 8080) - Optional features (hot-reload, caching, latency simulation) diff --git a/package-lock.json b/package-lock.json index c28a1c8..d6e7325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4868,9 +4868,9 @@ } }, "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, "license": "ISC", "dependencies": { @@ -5430,9 +5430,9 @@ "license": "MIT" }, "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.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -5646,13 +5646,13 @@ } }, "node_modules/rimraf/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, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" diff --git a/src/core/router.ts b/src/core/router.ts index d1e16a3..645bad2 100644 --- a/src/core/router.ts +++ b/src/core/router.ts @@ -46,8 +46,18 @@ export function dynamicRouteHandler(config: ServerConfig) { // Check the cache first (only for single objects, not arrays) let mockData: Record | Record[]; - if (config.cache && mapping.filePath && !mapping.isArray) { - const cached = schemaCache.get(mapping.typeName, mapping.filePath); + const { filePath } = mapping; + + if (!filePath) { + res.status(500).json({ + error: 'Mock generation failed', + message: `No file path found for type "${mapping.typeName}"`, + }); + return; + } + + if (config.cache && !mapping.isArray) { + const cached = schemaCache.get(mapping.typeName, filePath); if (cached) { mockData = cached.schema; @@ -59,21 +69,21 @@ export function dynamicRouteHandler(config: ServerConfig) { // Generate the mock data if (mapping.isArray) { mockData = generateMockArray( - mapping.filePath!, + filePath, mapping.typeName ); } else { mockData = generateMockFromInterface( - mapping.filePath!, + filePath, mapping.typeName ); } // Store in cache if enabled - if (config.cache && mapping.filePath && !mapping.isArray) { + if (config.cache && !mapping.isArray) { schemaCache.set( mapping.typeName, - mapping.filePath, + filePath, mockData as Record ); } diff --git a/src/server.ts b/src/server.ts index 61b0671..31ba824 100644 --- a/src/server.ts +++ b/src/server.ts @@ -80,6 +80,7 @@ export function startServer( // Configure the logger in verbose mode if necessary if (config.verbose) { + logger.setVerbose(true); logger.info('Verbose mode enabled'); } diff --git a/src/types/config.ts b/src/types/config.ts index 0ff65a0..fe865cc 100644 --- a/src/types/config.ts +++ b/src/types/config.ts @@ -8,7 +8,6 @@ export interface ServerConfig { /** Server port */ port: number; - /** Simulated latency (min-max in milliseconds) */ latency?: { min: number; diff --git a/src/utils/configPersistence.ts b/src/utils/configPersistence.ts index b8859f6..c1b110a 100644 --- a/src/utils/configPersistence.ts +++ b/src/utils/configPersistence.ts @@ -5,6 +5,26 @@ import { logger } from './logger'; const CONFIG_FILE = path.join(process.cwd(), '.mock-config.json'); +/** + * Validates that a parsed JSON object has the shape of a ServerConfig. + * Used to avoid silent failures when loading a malformed or outdated config file. + */ +function isValidSavedConfig(obj: unknown): obj is ServerConfig { + if (typeof obj !== 'object' || obj === null) return false; + const s = obj as Record; + if (typeof s['typesDir'] !== 'string') return false; + if (typeof s['port'] !== 'number') return false; + if (typeof s['hotReload'] !== 'boolean') return false; + if (typeof s['cache'] !== 'boolean') return false; + if (typeof s['verbose'] !== 'boolean') return false; + if (s['latency'] !== undefined) { + if (typeof s['latency'] !== 'object' || s['latency'] === null) return false; + const latency = s['latency'] as Record; + if (typeof latency['min'] !== 'number' || typeof latency['max'] !== 'number') return false; + } + return true; +} + /** * Save the server configuration to a file for later reuse * @param config The configuration to save @@ -38,23 +58,6 @@ export function loadSavedConfig(): ServerConfig | null { const content = fs.readFileSync(CONFIG_FILE, 'utf-8'); const parsed = JSON.parse(content); - // Minimal runtime validation to avoid silent failures from malformed or - // outdated config files. We check required fields and types. - function isValidSavedConfig(obj: unknown): obj is ServerConfig { - if (typeof obj !== 'object' || obj === null) return false; - const s = obj as any; - if (typeof s.typesDir !== 'string') return false; - if (typeof s.port !== 'number') return false; - if (typeof s.hotReload !== 'boolean') return false; - if (typeof s.cache !== 'boolean') return false; - if (typeof s.verbose !== 'boolean') return false; - if (s.latency !== undefined) { - if (typeof s.latency !== 'object' || s.latency === null) return false; - if (typeof s.latency.min !== 'number' || typeof s.latency.max !== 'number') return false; - } - return true; - } - if (!isValidSavedConfig(parsed)) { logger.warn(`Saved configuration at ${CONFIG_FILE} is malformed or missing required fields — ignoring.`); return null; diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 07145b5..d952396 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -3,6 +3,10 @@ import chalk from 'chalk'; export class Logger { constructor(private verbose: boolean = false) {} + setVerbose(verbose: boolean): void { + this.verbose = verbose; + } + info(message: string, ...args: unknown[]): void { console.log(chalk.blue('ℹ'), message, ...args); } diff --git a/src/utils/typeMapping.ts b/src/utils/typeMapping.ts index ac3d2df..0988acc 100644 --- a/src/utils/typeMapping.ts +++ b/src/utils/typeMapping.ts @@ -122,11 +122,6 @@ export function buildTypeMap(directory: string): Map { } } - if (typeMap.size > 0) { - // Debug: Log discovered endpoints - // console.debug(`[typeMapping] Discovered ${typeMap.size} endpoints:`, Array.from(typeMap.keys())); - } - return typeMap; }