diff --git a/package-lock.json b/package-lock.json index bb901359..6076e255 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "2.8.0", "license": "BSD-3-Clause", "dependencies": { - "@ethersphere/bee-js": "^6.7.3", + "@ethersphere/bee-js": "^6.9.0", "@fairdatasociety/bmt-js": "^2.1.0", "bignumber.js": "^9.1.0", "chalk": "^2.4.2", @@ -1227,14 +1227,14 @@ } }, "node_modules/@ethersphere/bee-js": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.7.3.tgz", - "integrity": "sha512-04AXGXP148DousgjVInyGUlHZnWwTGIgiH5leCACJ6daAUnnJQm7CjQgXIH5y72gGPX1XyzXDlqBlB8zLkihkQ==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.9.0.tgz", + "integrity": "sha512-TW7F8V6/Ha0oW1mh5ChFN0DDJHEHYTewCj/phg+CwjKIxagnrGVs52B2DLJKQLf4RnqNHY1MXSBXqAc5FnMwKQ==", "dependencies": { "@ethersphere/swarm-cid": "^0.1.0", "@types/readable-stream": "^2.3.13", - "axios": "^0.27.2", - "cafe-utility": "^10.8.1", + "axios": "^0.28.0", + "cafe-utility": "^15.0.2", "elliptic": "^6.5.4", "fetch-blob": "2.1.2", "isomorphic-ws": "^4.0.1", @@ -1245,13 +1245,18 @@ "ws": "^8.7.0" }, "engines": { - "bee": "1.13.0-f1067884", + "bee": "1.18.2-759f56f", "beeApiVersion": "4.0.0", "beeDebugApiVersion": "4.0.0", "node": ">=14.0.0", "npm": ">=6.0.0" } }, + "node_modules/@ethersphere/bee-js/node_modules/cafe-utility": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-15.0.2.tgz", + "integrity": "sha512-TNKSfA/q/XRd86NwYtF5QImQB8U5n/hKZuWblYFgYW4aveHcSg2RGOfR3+xquXRXF7BCeNoAXe2/snWFKviPzw==" + }, "node_modules/@ethersphere/bee-js/node_modules/web-streams-polyfill": { "version": "4.0.0-beta.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", @@ -2747,12 +2752,13 @@ } }, "node_modules/axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.0.tgz", + "integrity": "sha512-Tu7NYoGY4Yoc7I+Npf9HhUMtEEpV7ZiLH9yndTCoNhcpBH0kwcvFbzYN9/u5QKI5A6uefjsNNWaz5olJVYS62Q==", "dependencies": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/babel-jest": { @@ -3153,7 +3159,8 @@ "node_modules/cafe-utility": { "version": "10.8.1", "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-10.8.1.tgz", - "integrity": "sha512-Tt7O4MRCJa3Nj7qGZGpy7o7PpbdLiKu1yOwQcXFgopnCmfwsSHHJZcIwkpPBu7tyXAbNjmN2f3+pdwwKYpYZcA==" + "integrity": "sha512-Tt7O4MRCJa3Nj7qGZGpy7o7PpbdLiKu1yOwQcXFgopnCmfwsSHHJZcIwkpPBu7tyXAbNjmN2f3+pdwwKYpYZcA==", + "dev": true }, "node_modules/callsites": { "version": "3.1.0", @@ -4498,9 +4505,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -8314,6 +8321,11 @@ "node": ">= 6" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -10667,14 +10679,14 @@ } }, "@ethersphere/bee-js": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.7.3.tgz", - "integrity": "sha512-04AXGXP148DousgjVInyGUlHZnWwTGIgiH5leCACJ6daAUnnJQm7CjQgXIH5y72gGPX1XyzXDlqBlB8zLkihkQ==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-6.9.0.tgz", + "integrity": "sha512-TW7F8V6/Ha0oW1mh5ChFN0DDJHEHYTewCj/phg+CwjKIxagnrGVs52B2DLJKQLf4RnqNHY1MXSBXqAc5FnMwKQ==", "requires": { "@ethersphere/swarm-cid": "^0.1.0", "@types/readable-stream": "^2.3.13", - "axios": "^0.27.2", - "cafe-utility": "^10.8.1", + "axios": "^0.28.0", + "cafe-utility": "^15.0.2", "elliptic": "^6.5.4", "fetch-blob": "2.1.2", "isomorphic-ws": "^4.0.1", @@ -10685,6 +10697,11 @@ "ws": "^8.7.0" }, "dependencies": { + "cafe-utility": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-15.0.2.tgz", + "integrity": "sha512-TNKSfA/q/XRd86NwYtF5QImQB8U5n/hKZuWblYFgYW4aveHcSg2RGOfR3+xquXRXF7BCeNoAXe2/snWFKviPzw==" + }, "web-streams-polyfill": { "version": "4.0.0-beta.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", @@ -11837,12 +11854,13 @@ "dev": true }, "axios": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", - "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.0.tgz", + "integrity": "sha512-Tu7NYoGY4Yoc7I+Npf9HhUMtEEpV7ZiLH9yndTCoNhcpBH0kwcvFbzYN9/u5QKI5A6uefjsNNWaz5olJVYS62Q==", "requires": { - "follow-redirects": "^1.14.9", - "form-data": "^4.0.0" + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "babel-jest": { @@ -12143,7 +12161,8 @@ "cafe-utility": { "version": "10.8.1", "resolved": "https://registry.npmjs.org/cafe-utility/-/cafe-utility-10.8.1.tgz", - "integrity": "sha512-Tt7O4MRCJa3Nj7qGZGpy7o7PpbdLiKu1yOwQcXFgopnCmfwsSHHJZcIwkpPBu7tyXAbNjmN2f3+pdwwKYpYZcA==" + "integrity": "sha512-Tt7O4MRCJa3Nj7qGZGpy7o7PpbdLiKu1yOwQcXFgopnCmfwsSHHJZcIwkpPBu7tyXAbNjmN2f3+pdwwKYpYZcA==", + "dev": true }, "callsites": { "version": "3.1.0", @@ -13154,9 +13173,9 @@ "dev": true }, "follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "form-data": { "version": "4.0.0", @@ -15919,6 +15938,11 @@ "sisteransi": "^1.0.5" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", diff --git a/package.json b/package.json index a1d9591a..4ad3420f 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "typescript": "^4.8.4" }, "dependencies": { - "@ethersphere/bee-js": "^6.7.3", + "@ethersphere/bee-js": "^6.9.0", "@fairdatasociety/bmt-js": "^2.1.0", "bignumber.js": "^9.1.0", "chalk": "^2.4.2", diff --git a/src/command/upload.ts b/src/command/upload.ts index b106eb66..4805213d 100644 --- a/src/command/upload.ts +++ b/src/command/upload.ts @@ -1,4 +1,4 @@ -import { Tag, Utils } from '@ethersphere/bee-js' +import { RedundancyLevel, Tag, Utils } from '@ethersphere/bee-js' import { Presets, SingleBar } from 'cli-progress' import * as FS from 'fs' import { Argument, LeafCommand, Option } from 'furious-commander' @@ -104,6 +104,12 @@ export class Upload extends RootCommand implements LeafCommand { }) public contentType!: string + @Option({ + key: 'redundancy', + description: 'Redundancy of the upload (MEDIUM, STRONG, INSANE, PARANOID)', + }) + public redundancy!: string + // CLASS FIELDS public hash!: string @@ -140,6 +146,7 @@ export class Upload extends RootCommand implements LeafCommand { } await this.maybeRunSizeChecks() + await this.maybePrintRedundancyStats() const tag = this.sync ? await this.bee.createTag() : undefined @@ -211,6 +218,7 @@ export class Upload extends RootCommand implements LeafCommand { encrypt: this.encrypt, contentType, deferred: this.deferred, + redundancyLevel: this.determineRedundancyLevel(), }) this.hash = reference @@ -219,6 +227,8 @@ export class Upload extends RootCommand implements LeafCommand { const { reference } = await this.bee.uploadData(this.stamp, this.stdinData, { tag: tag?.uid, deferred: this.deferred, + encrypt: this.encrypt, + redundancyLevel: this.determineRedundancyLevel(), }) this.hash = reference @@ -239,6 +249,7 @@ export class Upload extends RootCommand implements LeafCommand { pin: this.pin, encrypt: this.encrypt, deferred: this.deferred, + redundancyLevel: this.determineRedundancyLevel(), }) this.hash = reference @@ -260,6 +271,7 @@ export class Upload extends RootCommand implements LeafCommand { encrypt: this.encrypt, contentType, deferred: this.deferred, + redundancyLevel: this.determineRedundancyLevel(), }) this.hash = reference @@ -340,6 +352,35 @@ export class Upload extends RootCommand implements LeafCommand { } } + private async maybePrintRedundancyStats(): Promise { + if (!this.redundancy || this.quiet) { + return + } + + const currentSetting = Utils.getRedundancyStat(this.redundancy) + const originalSize = await this.getUploadSize() + const originalChunks = Math.ceil(originalSize.getBytes() / 4e3) + const sizeMultiplier = Utils.approximateOverheadForRedundancyLevel( + originalChunks, + currentSetting.value, + this.encrypt, + ) + const newSize = new Storage(originalChunks * 4e3 * (1 + sizeMultiplier)) + const extraSize = new Storage(newSize.getBytes() - originalSize.getBytes()) + + this.console.log(createKeyValue('Redundancy setting', currentSetting.label)) + this.console.log(`This setting will provide ${Math.round(currentSetting.errorTolerance * 100)}% error tolerance.`) + this.console.log(`An additional ${extraSize.toString()} of data will be uploaded approximately.`) + this.console.log(`${originalSize.toString()} → ${newSize.toString()} (+${extraSize.toString()})`) + if (!this.yes && !this.quiet) { + const confirmation = await this.console.confirm('Do you want to proceed?') + + if (!confirmation) { + exit(0) + } + } + } + private async getUploadSize(): Promise { let size = -1 @@ -424,4 +465,22 @@ export class Upload extends RootCommand implements LeafCommand { return defaultName } + + private determineRedundancyLevel(): RedundancyLevel | undefined { + if (!this.redundancy) { + return undefined + } + switch (this.redundancy.toUpperCase()) { + case 'MEDIUM': + return RedundancyLevel.MEDIUM + case 'STRONG': + return RedundancyLevel.STRONG + case 'INSANE': + return RedundancyLevel.INSANE + case 'PARANOID': + return RedundancyLevel.PARANOID + default: + throw new CommandLineError(`Invalid redundancy level: ${this.redundancy}`) + } + } }