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
2 changes: 1 addition & 1 deletion contract-shield.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"__tests__/**",
"**/*.test.js"
],
"output": "./dist"
"output": "dist"
}
2 changes: 1 addition & 1 deletion contract-shield.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"__tests__/**",
"**/*.test.js"
],
"output": "./dist"
"output": "dist"
}
42 changes: 40 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"dependencies": {
"ansi-colors": "^4.1.3",
"commander": "^14.0.0",
"config-dot-get": "^1.0.1",
"winston": "^3.17.0"
},
"devDependencies": {
Expand Down
48 changes: 31 additions & 17 deletions src/utils/configUtils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const fs = require("fs");
const path = require("path");
const os = require("os");
const { validateConfigSchema } = require("../utils/validateConfigSchema");

/**
* Loads and parses a configuration file from a specified path or default locations.
Expand All @@ -18,23 +19,36 @@ const loadConfig = (configPath) => {
GLOBAL: "contract-shield.json",
};

const defaultProjectConfig = path.resolve(
process.cwd(),
CONFIG_FILES.PROJECT
);

const defaultGlobalConfig = path.resolve(os.homedir(), CONFIG_FILES.GLOBAL);
const finalConfigPath =
configPath ||
(fs.existsSync(defaultProjectConfig)
? defaultProjectConfig
: fs.existsSync(defaultGlobalConfig)
? defaultGlobalConfig
: null);
const defaultProjectConfig = path.resolve(process.cwd(), CONFIG_FILES.PROJECT);
// const defaultGlobalConfig = path.resolve(os.homedir(), CONFIG_FILES.GLOBAL);
const defaultGlobalConfig = path.resolve(__dirname__, CONFIG_FILES.GLOBAL);
Copy link

Choose a reason for hiding this comment

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

Invalid dirname reference category Functionality

Tell me more
What is the issue?

The code uses 'dirname' (with double underscores) which is an undefined variable. The correct Node.js global variable is '__dirname' (single underscore).

Why this matters

This will cause a ReferenceError when trying to access the undefined variable, preventing the global configuration file from being found.

Suggested change ∙ Feature Preview

Replace 'dirname' with '__dirname':

const defaultGlobalConfig = path.resolve(__dirname, CONFIG_FILES.GLOBAL);
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.


return finalConfigPath && fs.existsSync(finalConfigPath)
? JSON.parse(fs.readFileSync(finalConfigPath, "utf-8"))
: {};
const finalConfigPath = configPath ||
[defaultProjectConfig, defaultGlobalConfig].find(fs.existsSync) || null;

if (finalConfigPath) {
try {
const fileContent = fs.readFileSync(finalConfigPath, "utf-8");
try {
const config = JSON.parse(fileContent);

const isValidConfig = validateConfigSchema(config);
if (!isValidConfig) {
console.error("Invalid configuration structure.");
return {};
}

return config;
} catch (parseError) {
console.error("Error parsing JSON:", parseError);
return {};
}
} catch (error) {
console.error(`Error loading configuration from ${finalConfigPath}:`, error);
return {};
}
}
return {};
};

module.exports = { loadConfig };
module.exports = { loadConfig };
23 changes: 23 additions & 0 deletions src/utils/validateConfigSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

module.exports = {
validateConfigSchema: (config) => {
if (typeof config !== "object" || config === null) {
return false;
}

const requiredFields = ["output"];
for (const field of requiredFields) {
if (!Object.prototype.hasOwnProperty.call(config, field)) {
return false;
}
}
Comment on lines +8 to +13
Copy link

Choose a reason for hiding this comment

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

Schema Definition Mixed with Validation Logic category Design

Tell me more
What is the issue?

The validation logic mixes concerns by handling both the required fields list and the validation logic in the same function, making it harder to extend or modify the schema requirements.

Why this matters

Future changes to the configuration schema will require modifying the validation function directly, violating the Open-Closed Principle.

Suggested change ∙ Feature Preview

Separate schema definition from validation logic:

const CONFIG_SCHEMA = {
  required: ['output'],
  types: {
    output: 'string'
  }
};

module.exports = {
  validateConfigSchema: (config) => {
    return validateAgainstSchema(config, CONFIG_SCHEMA);
  }
};
Provide feedback to improve future suggestions

Nice Catch Incorrect Not in Scope Not in coding standard Other

💬 Looking for more details? Reply to this comment to chat with Korbit.


if (
typeof config.output !== "string"
) {
return false;
}

return true;
},
};
34 changes: 17 additions & 17 deletions tests/transpile.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@ describe('Contract Shield CLI - Basic Transpile Tests', () => {
beforeAll(() => cleanupFiles()); // Cleanup before tests
afterAll(() => cleanupFiles()); // Cleanup after tests

// test('CLI runs without errors', () => {
// const output = execSync('node src/cli.js').toString();
// expect(output).toBeDefined();
// });
test('CLI runs without errors', () => {
const output = execSync('node src/cli.js').toString()
expect(output).toBeDefined();
});

// test('Explicit transpile command runs', () => {
// const output = execSync('node src/cli.js transpile').toString();
// expect(output).toBeDefined();
// });
test('Explicit transpile command runs', () => {
const output = execSync('node src/cli.js transpile').toString();
expect(output).toBeDefined();
});

// test('Silent mode suppresses console output', () => {
// const output = execSync('node src/cli.js transpile --silent').toString().trim();
// expect(output).toBe('');
// });
test('Silent mode suppresses console output', () => {
const output = execSync('node src/cli.js transpile --silent').toString().trim();
expect(output).toBe('');
});

test('Loads version from package.json', () => {
const output = execSync('node src/cli.js --version').toString().trim();
Expand All @@ -49,11 +49,11 @@ describe('Contract Shield CLI - Basic Transpile Tests', () => {
}
});

// test('CLI runs with a specified config file', () => {
// fs.writeFileSync('test-config.json', JSON.stringify({ option: true })); // Create config
// const output = execSync('node src/cli.js transpile --config test-config.json').toString();
// expect(output).toBeDefined();
// });
test('CLI runs with a specified config file', () => {
fs.writeFileSync('test-config.json', JSON.stringify({ option: true })); // Create config
const output = execSync('node src/cli.js transpile --config test-config.json').toString();
expect(output).toBeDefined();
});

test('Handles missing transpilation source gracefully', () => {
try {
Expand Down
Loading