From 0e75cbaedde581095212e8420a52b9ff8667919a Mon Sep 17 00:00:00 2001 From: Ion Gireada Date: Fri, 13 Jun 2025 08:34:10 +0300 Subject: [PATCH 1/2] update contract-shield.config.json, contract-shield.json, configUtils.js and transpile.test.js --- contract-shield.config.json | 2 +- contract-shield.json | 2 +- src/utils/configUtils.js | 48 ++++++++++++++++++++----------- src/utils/validateConfigSchema.js | 23 +++++++++++++++ tests/transpile.test.js | 34 +++++++++++----------- 5 files changed, 73 insertions(+), 36 deletions(-) create mode 100644 src/utils/validateConfigSchema.js diff --git a/contract-shield.config.json b/contract-shield.config.json index b9a9aee..a698e6d 100644 --- a/contract-shield.config.json +++ b/contract-shield.config.json @@ -13,5 +13,5 @@ "__tests__/**", "**/*.test.js" ], - "output": "./dist" + "output": "dist" } \ No newline at end of file diff --git a/contract-shield.json b/contract-shield.json index b9a9aee..a698e6d 100644 --- a/contract-shield.json +++ b/contract-shield.json @@ -13,5 +13,5 @@ "__tests__/**", "**/*.test.js" ], - "output": "./dist" + "output": "dist" } \ No newline at end of file diff --git a/src/utils/configUtils.js b/src/utils/configUtils.js index 5e0f414..f77f78c 100644 --- a/src/utils/configUtils.js +++ b/src/utils/configUtils.js @@ -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. @@ -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); - 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 }; \ No newline at end of file diff --git a/src/utils/validateConfigSchema.js b/src/utils/validateConfigSchema.js new file mode 100644 index 0000000..abc2323 --- /dev/null +++ b/src/utils/validateConfigSchema.js @@ -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; + } + } + + if ( + typeof config.output !== "string" + ) { + return false; + } + + return true; + }, +}; \ No newline at end of file diff --git a/tests/transpile.test.js b/tests/transpile.test.js index 2ec04f0..4f91814 100644 --- a/tests/transpile.test.js +++ b/tests/transpile.test.js @@ -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(); @@ -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 { From ac5aa057cee5d1bbb1328dcd4e177507cc017733 Mon Sep 17 00:00:00 2001 From: Ion Gireada Date: Sat, 14 Jun 2025 18:51:52 +0300 Subject: [PATCH 2/2] Add config-dot-get dependency for configuration file handling --- package-lock.json | 42 ++++++++++++++++++++++++++++++++++++++++-- package.json | 1 + 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f236b08..46a2d66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "ansi-colors": "^4.1.3", "commander": "^14.0.0", + "config-dot-get": "^1.0.1", "winston": "^3.17.0" }, "bin": { @@ -1543,6 +1544,16 @@ "dev": true, "license": "MIT" }, + "node_modules/config-dot-get": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/config-dot-get/-/config-dot-get-1.0.1.tgz", + "integrity": "sha512-+sPOwbLa5H1MwRT7VzJzLJ/xPXPI/yNzgqG6xPyPjCsjf/ocR6wnK+ryPQolBbrLZJGdXHgJXbCRTAbyUPz2uQ==", + "license": "MIT", + "dependencies": { + "lockfile": "^1.0.4", + "proper-lockfile": "^4.1.2" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -1944,7 +1955,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/has-flag": { @@ -2887,6 +2897,15 @@ "node": ">=8" } }, + "node_modules/lockfile": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", + "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "license": "ISC", + "dependencies": { + "signal-exit": "^3.0.2" + } + }, "node_modules/logform": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", @@ -3278,6 +3297,17 @@ "node": ">= 6" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/pure-rand": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", @@ -3380,6 +3410,15 @@ "node": ">=10" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3446,7 +3485,6 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, "license": "ISC" }, "node_modules/simple-swizzle": { diff --git a/package.json b/package.json index 46aee00..0dad454 100644 --- a/package.json +++ b/package.json @@ -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": {