diff --git a/package-lock.json b/package-lock.json index 1ad80c8..4ef3329 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@super-protocol/ctl", - "version": "0.12.1", + "version": "0.12.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@super-protocol/ctl", - "version": "0.12.1", + "version": "0.12.3", "license": "MIT", "dependencies": { "@amplitude/node": "^1.10.2", @@ -14,7 +14,7 @@ "@super-protocol/distributed-secrets": "1.1.7", "@super-protocol/dto-js": "1.2.10", "@super-protocol/sdk-js": "3.13.3", - "@super-protocol/sp-files-addon": "^0.11.0", + "@super-protocol/sp-files-addon": "^0.12.1", "@types/tar-stream": "^3.1.3", "axios": "1.6.2", "bip39": "^3.1.0", @@ -5961,23 +5961,23 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/@super-protocol/sp-files-addon": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon/-/sp-files-addon-0.11.0.tgz", - "integrity": "sha512-PChd0xl4CQalR4yrN9CGCNUPw+Z+EyO5Zb/gWq0ooqVcIMAkg38qzYM9zqsxYHHDVylRrAh8+H/0h8ETnvY0Xg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon/-/sp-files-addon-0.12.1.tgz", + "integrity": "sha512-PU658uW91cHTT0xvIw+MEH+t1TJHs0suvt8812X5BLTBmFbeWpgyYtK0nAOBh961iMqVpMT1GUX14n5cmbkG8w==", "license": "MIT", "engines": { "node": ">= 16" }, "optionalDependencies": { - "@super-protocol/sp-files-addon-darwin-arm64": "0.11.0", - "@super-protocol/sp-files-addon-darwin-x64": "0.11.0", - "@super-protocol/sp-files-addon-linux-x64-gnu": "0.11.0" + "@super-protocol/sp-files-addon-darwin-arm64": "0.12.1", + "@super-protocol/sp-files-addon-darwin-x64": "0.12.1", + "@super-protocol/sp-files-addon-linux-x64-gnu": "0.12.1" } }, "node_modules/@super-protocol/sp-files-addon-darwin-arm64": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-arm64/-/sp-files-addon-darwin-arm64-0.11.0.tgz", - "integrity": "sha512-0Sg17HWOV8+jNB3MAEKcd5GUsRjZ96KMYztIrSO1s2gAZMRhN4pZfiWWQzWq4TVQohKiPAu5RIhI2/yQOiC8Zg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-arm64/-/sp-files-addon-darwin-arm64-0.12.1.tgz", + "integrity": "sha512-EZ6ORcF/ByCOpq70IhllPCkmGW6y5x07Nh9tHlksM+qpR9KdBnxuJqunHT7CsaUhcfaI4RTQlcpkYMTWz2oN0w==", "cpu": [ "arm64" ], @@ -5991,9 +5991,9 @@ } }, "node_modules/@super-protocol/sp-files-addon-darwin-x64": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-x64/-/sp-files-addon-darwin-x64-0.11.0.tgz", - "integrity": "sha512-3KbmldXeiQ+LgrbLvDspRMm0/CrIXuzVVEuHPu28JyCK6GLHoseqIElMinXVyhF4b/mNpVDUJLH5/KRfIG7plQ==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-darwin-x64/-/sp-files-addon-darwin-x64-0.12.1.tgz", + "integrity": "sha512-ctxMMIG82KQeuFbzFuVjHN6yQHd4GNe8C8w6PLNG4lNb4jYPsjLEwPCreogB5iBMfhieAwHiudCBg3k/D9fp/g==", "cpu": [ "x64" ], @@ -6007,9 +6007,9 @@ } }, "node_modules/@super-protocol/sp-files-addon-linux-x64-gnu": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-linux-x64-gnu/-/sp-files-addon-linux-x64-gnu-0.11.0.tgz", - "integrity": "sha512-JeyV3oDK34fmVBPXYtkUaDve0R6xF5yRwR/Ro4TdtBswuS4CYjG2xZ8SYvmWuFwrdJ0OvaHr+ZvFHPa0JTbQvg==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/@super-protocol/sp-files-addon-linux-x64-gnu/-/sp-files-addon-linux-x64-gnu-0.12.1.tgz", + "integrity": "sha512-Nn0jsrw6GbOKgLb53BCR9tNNJt2GeMpIfhc46uIzn7xYSi6OsfZre7KBNx5k+ImVNXG9H8HUmHV18KhaJb17xA==", "cpu": [ "x64" ], diff --git a/package.json b/package.json index 4fb7411..e719a19 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@super-protocol/ctl", - "version": "0.12.1", + "version": "0.12.3", "description": "A tool for publishing values in a secure and reliable way.", "main": "./build/index.js", "type": "commonjs", @@ -37,7 +37,7 @@ "@super-protocol/distributed-secrets": "1.1.7", "@super-protocol/dto-js": "1.2.10", "@super-protocol/sdk-js": "3.13.3", - "@super-protocol/sp-files-addon": "^0.11.0", + "@super-protocol/sp-files-addon": "^0.12.1", "@types/tar-stream": "^3.1.3", "axios": "1.6.2", "bip39": "^3.1.0", diff --git a/src/commands/filesCalculateHash.ts b/src/commands/filesCalculateHash.ts new file mode 100644 index 0000000..81a1b5d --- /dev/null +++ b/src/commands/filesCalculateHash.ts @@ -0,0 +1,58 @@ +import path from 'path'; +import { calculateResourceHash } from '@super-protocol/sp-files-addon'; +import { cryptoUtils } from '@super-protocol/sdk-js'; +import { promises as fs } from 'fs'; +import Printer from '../printer'; + +export interface FilesCalculateHashParams { + localPath: string; +} + +export default async (params: FilesCalculateHashParams): Promise => { + const inputPath = typeof params.localPath === 'string' ? params.localPath.trim() : ''; + if (!inputPath) { + Printer.print('Filename should be defined'); + return; + } + + const localPath = path.resolve(inputPath); + + try { + const stat = await fs.stat(localPath); + if (stat.isDirectory()) { + const files = await fs.readdir(localPath); + + Printer.print(`Found folder "${localPath}" with ${files.length} top-level entries`); + } else if (stat.isFile()) { + Printer.print(`Found file "${localPath}"`); + } else { + Printer.print(`Found path "${localPath}" (not a regular file or directory)`); + } + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') { + Printer.error(`\nFile or folder is missing on path ${localPath}`); + return; + } + + throw error; + } + + try { + const objectName = path.basename(localPath); + Printer.print('Calculating hash...'); + + const objectHash = await calculateResourceHash(localPath); + const rootHash = await cryptoUtils.getDirHashFileContents({ [objectName]: objectHash }); + + const raw = rootHash.hash ?? ''; + const colonIndex = raw.indexOf(':'); + + const hash = { + algo: colonIndex > 0 ? raw.slice(0, colonIndex).toLowerCase() : '', + hash: colonIndex > 0 ? raw.slice(colonIndex + 1) : raw, + }; + Printer.print(JSON.stringify(hash, null, 2)); + } catch (error) { + throw new Error(`Failed to calculate hash: ${(error as Error).message}`); + } +}; diff --git a/src/index.ts b/src/index.ts index 66ee561..339f49d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,6 +13,7 @@ import addonDownload from './commands/filesDownload.addon'; import upload from './commands/filesUpload'; import addonUpload, { FilesUploadParams } from './commands/filesUpload.addon'; import filesDelete from './commands/filesDelete'; +import filesCalculateHash from './commands/filesCalculateHash'; import addonFilesDelete from './commands/filesDelete.addon'; import providersList from './commands/providersList'; import providersGet from './commands/providersGet'; @@ -1594,6 +1595,14 @@ async function main(): Promise { } }); + filesCommand + .command('calculate-hash') + .description('Calculate the hash of a file or all files in a folder') + .argument('localPath', 'Path to the file or folder') + .action(async (localPath: string) => { + await filesCalculateHash({ localPath }); + }); + solutionsCommand .command('generate-key') .description('Generate a solution signing key')