Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions lib/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const parse = (data: Record<string, any>): 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 {
Expand All @@ -55,23 +55,35 @@ export const parse = (data: Record<string, any>): void => {
};

export const drawTable = (data: Array<Record<string, any>>): 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<string, string>, 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({
Expand All @@ -98,7 +110,7 @@ export const drawTable = (data: Array<Record<string, any>>): 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]));
Expand Down
32 changes: 32 additions & 0 deletions repro_bug_sk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// repro_bug.js

import { drawTable } from './lib/parser.ts'; // Change .js to .ts
Comment on lines +1 to +3
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's find and examine the repro_bug_sk.js file
fd -name "repro_bug_sk.js" -type f

Repository: appwrite/sdk-for-cli

Length of output: 294


🏁 Script executed:

# Check repository structure
git ls-files | grep -E "(repro_bug|test|spec)" | head -20

Repository: appwrite/sdk-for-cli

Length of output: 212


🏁 Script executed:

# Check package.json for test configuration
cat package.json 2>/dev/null | head -50

Repository: appwrite/sdk-for-cli

Length of output: 2283


🏁 Script executed:

# Look for test directories
fd -type d -name "__tests__" -o -name "test" -o -name "tests" -o -name "spec"

Repository: appwrite/sdk-for-cli

Length of output: 234


🏁 Script executed:

# Read the actual repro_bug_sk.js file
cat -n repro_bug_sk.js

Repository: appwrite/sdk-for-cli

Length of output: 1220


🏁 Script executed:

# Check if this file is in .gitignore
cat .gitignore 2>/dev/null | grep -i "repro"

Repository: appwrite/sdk-for-cli

Length of output: 46


🏁 Script executed:

# Check if lib/parser.ts exists
fd -name "parser.ts" -type f

Repository: appwrite/sdk-for-cli

Length of output: 294


🏁 Script executed:

# Check project root structure
ls -la | grep -E "^-.*\.(js|ts)$"

Repository: appwrite/sdk-for-cli

Length of output: 306


Remove this reproduction script from the repository.

The filename in line 1's comment (repro_bug.js) doesn't match the actual filename (repro_bug_sk.js). More importantly, this is a manual debug script rather than a proper automated test. Since the project has no test framework configured ("test": "echo \"Error: no test specified\" && exit 1"), either remove this file or move it to local documentation/notes outside the repository.

The direct .ts import also requires tsx or ts-node to execute, which adds unnecessary complexity for what should be manual verification if needed.

🤖 Prompt for AI Agents
In `@repro_bug_sk.js` around lines 1 - 3, The file repro_bug_sk.js is a manual
reproduction script and should be removed from the repository; delete
repro_bug_sk.js (or move it out to local notes/docs) and remove any references
to it, and if you must keep a local copy update its import of './lib/parser.ts'
(referenced via drawTable import) to a runtime-compatible module (e.g.,
'./lib/parser.js') or remove the import entirely so the repo does not require
tsx/ts-node to run; ensure package.json/test remains unchanged if you remove the
script.



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);
}