From e91457f3620ed648edb673fe6a9c607985bbba1b Mon Sep 17 00:00:00 2001 From: shaheerkhan00 Date: Fri, 23 Jan 2026 00:24:37 -0500 Subject: [PATCH] resolve TypeError in drawTable when handling null values --- lib/parser.ts | 28 ++++++++++++++++++++-------- repro_bug_sk.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 repro_bug_sk.js diff --git a/lib/parser.ts b/lib/parser.ts index e9e94f3..ddfd784 100644 --- a/lib/parser.ts +++ b/lib/parser.ts @@ -41,7 +41,7 @@ export const parse = (data: Record): void => { } else { drawJSON(data[key]); } - } else if (typeof data[key] === "object") { + } else if (typeof data[key] === "object" && data[key] !== null) { if (data[key]?.constructor?.name === "BigNumber") { console.log(`${chalk.yellow.bold(key)} : ${data[key]}`); } else { @@ -55,23 +55,35 @@ export const parse = (data: Record): void => { }; export const drawTable = (data: Array>): void => { - if (data.length == 0) { + // 1. Enhanced Guard: Check for empty data or if the first element is null + if (!data || data.length === 0 || data[0] === null) { console.log("[]"); return; } - // Create an object with all the keys in it - const obj = data.reduce((res, item) => ({ ...res, ...item }), {}); + // 2. Safely create an object with all keys. + // Added a check (item || {}) to ensure spread doesn't fail if an array element is null. + const obj = data.reduce((res, item) => ({ ...res, ...(item || {}) }), {}); + // Get those keys as an array const keys = Object.keys(obj); - // Create an object with all keys set to the default value '' + + // 3. Early exit if no keys are found (prevents crash on Object.keys(data[0])) + if (keys.length === 0) { + console.log("-"); + return; + } + + // Create an object with all keys set to the default value '-' const def = keys.reduce((result: Record, key) => { result[key] = "-"; return result; }, {}); - // Use object destructuring to replace all default values with the ones we have - data = data.map((item) => ({ ...def, ...item })); + // Replace default values with actual values, ensuring 'item' is an object + data = data.map((item) => ({ ...def, ...(item || {}) })); + + // This is now safe because we checked data[0] and keys.length above const columns = Object.keys(data[0]); const table = new Table({ @@ -98,7 +110,7 @@ export const drawTable = (data: Array>): void => { data.forEach((row) => { const rowValues: any[] = []; for (const key in row) { - if (row[key] === null) { + if (row[key] === null || row[key] === undefined) { rowValues.push("-"); } else if (Array.isArray(row[key])) { rowValues.push(JSON.stringify(row[key])); diff --git a/repro_bug_sk.js b/repro_bug_sk.js new file mode 100644 index 0000000..2a11fa6 --- /dev/null +++ b/repro_bug_sk.js @@ -0,0 +1,32 @@ +// repro_bug.js + +import { drawTable } from './lib/parser.ts'; // Change .js to .ts + + +console.log("--- Test 1: Simulating Database Trigger with Null values ---"); +const mockExecutionData = [ + { + $id: "65ae12345", + status: "completed", + duration: 0.123, + scheduledAt: null, // This is the value that triggers the crash + trigger: "database" + } +]; + +try { + // Before your fix, this line would throw: + // TypeError: Cannot convert undefined or null to object + drawTable(mockExecutionData); + console.log("\nāœ… Test 1 Passed: Table rendered successfully despite null values."); +} catch (error) { + console.error("\nTest 1 Failed:", error.message); +} + +console.log("\n--- Test 2: Simulating Empty Object array ---"); +try { + drawTable([null]); + console.log("āœ… Test 2 Passed: Handled [null] array gracefully."); +} catch (error) { + console.error(" Test 2 Failed:", error.message); +} \ No newline at end of file