diff --git a/package-lock.json b/package-lock.json index 0d6c29f..6825d07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.15.0", "license": "BSD-3-Clause", "dependencies": { - "@ethersphere/bee-js": "^3.3.4", + "@ethersphere/bee-js": "^4.1.1", "@ethersphere/manifest-js": "1.1.0", "@ethersphere/swarm-cid": "^0.1.0", "@material-ui/core": "4.12.3", @@ -2219,10 +2219,11 @@ } }, "node_modules/@ethersphere/bee-js": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-3.3.4.tgz", - "integrity": "sha512-uxH0kR31tE8IKVON7jyQHANZ/5edlU8OUCz/qyRft1YeS+L4HzEHAD3bN58iE842nt6Iz/fekrJ7yk1ONIcDBg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-4.1.1.tgz", + "integrity": "sha512-4hbgi7rHnku+2pv352z7txV6IhP+2iipCKaQS4sOFhjieui44LE0Lox8gy5tud9tY2wRN2wY6LTqvo2EaYrVRQ==", "dependencies": { + "@ethersphere/swarm-cid": "^0.1.0", "@types/readable-stream": "^2.3.13", "bufferutil": "^4.0.6", "elliptic": "^6.5.4", @@ -2235,12 +2236,12 @@ "tar-js": "^0.3.0", "utf-8-validate": "^5.0.9", "web-streams-polyfill": "^4.0.0-beta.1", - "ws": "^8.5.0" + "ws": "^8.6.0" }, "engines": { - "bee": "1.5.1-d0a77598", - "beeApiVersion": "3.0.0", - "beeDebugApiVersion": "2.0.0", + "bee": "1.6.0-6ceadd35", + "beeApiVersion": "3.0.1", + "beeDebugApiVersion": "2.0.1", "node": ">=12.0.0", "npm": ">=6.0.0" } @@ -2254,9 +2255,9 @@ } }, "node_modules/@ethersphere/bee-js/node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", + "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", "engines": { "node": ">=10.0.0" }, @@ -7461,14 +7462,20 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001278", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz", - "integrity": "sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg==", + "version": "1.0.30001344", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz", + "integrity": "sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] }, "node_modules/capture-exit": { "version": "2.0.0", @@ -30872,10 +30879,11 @@ } }, "@ethersphere/bee-js": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-3.3.4.tgz", - "integrity": "sha512-uxH0kR31tE8IKVON7jyQHANZ/5edlU8OUCz/qyRft1YeS+L4HzEHAD3bN58iE842nt6Iz/fekrJ7yk1ONIcDBg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@ethersphere/bee-js/-/bee-js-4.1.1.tgz", + "integrity": "sha512-4hbgi7rHnku+2pv352z7txV6IhP+2iipCKaQS4sOFhjieui44LE0Lox8gy5tud9tY2wRN2wY6LTqvo2EaYrVRQ==", "requires": { + "@ethersphere/swarm-cid": "^0.1.0", "@types/readable-stream": "^2.3.13", "bufferutil": "^4.0.6", "elliptic": "^6.5.4", @@ -30888,7 +30896,7 @@ "tar-js": "^0.3.0", "utf-8-validate": "^5.0.9", "web-streams-polyfill": "^4.0.0-beta.1", - "ws": "^8.5.0" + "ws": "^8.6.0" }, "dependencies": { "web-streams-polyfill": { @@ -30897,9 +30905,9 @@ "integrity": "sha512-3ux37gEX670UUphBF9AMCq8XM6iQ8Ac6A+DSRRjDoRBm1ufCkaCDdNVbaqq60PsEkdNlLKrGtv/YBP4EJXqNtQ==" }, "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", + "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", "requires": {} } } @@ -34893,9 +34901,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001278", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz", - "integrity": "sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg==", + "version": "1.0.30001344", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz", + "integrity": "sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==", "dev": true }, "capture-exit": { diff --git a/package.json b/package.json index 619fda4..615f58b 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "url": "https://github.com/ethersphere/bee-dashboard.git" }, "dependencies": { - "@ethersphere/bee-js": "^3.3.4", + "@ethersphere/bee-js": "^4.1.1", "@ethersphere/manifest-js": "1.1.0", "@ethersphere/swarm-cid": "^0.1.0", "@material-ui/core": "4.12.3", diff --git a/src/pages/files/AssetSummary.tsx b/src/pages/files/AssetSummary.tsx index c7affd3..943bd56 100644 --- a/src/pages/files/AssetSummary.tsx +++ b/src/pages/files/AssetSummary.tsx @@ -1,25 +1,32 @@ import * as swarmCid from '@ethersphere/swarm-cid' import { Box } from '@material-ui/core' import { ReactElement } from 'react' +import { Utils } from '@ethersphere/bee-js' import { DocumentationText } from '../../components/DocumentationText' import ExpandableListItemKey from '../../components/ExpandableListItemKey' import ExpandableListItemLink from '../../components/ExpandableListItemLink' interface Props { isWebsite?: boolean - hash: string + reference: string } -export function AssetSummary({ isWebsite, hash }: Props): ReactElement { +export function AssetSummary({ isWebsite, reference }: Props): ReactElement { + const isHash = Utils.isHexString(reference) && reference.length === 64 + return ( <> - - - {isWebsite && ( + {isHash && } + {!isHash && } + + {isWebsite && isHash && ( )} diff --git a/src/pages/files/Download.tsx b/src/pages/files/Download.tsx index 71718bd..73f3b84 100644 --- a/src/pages/files/Download.tsx +++ b/src/pages/files/Download.tsx @@ -8,7 +8,7 @@ import { History } from '../../components/History' import { Context, defaultUploadOrigin } from '../../providers/File' import { Context as SettingsContext } from '../../providers/Settings' import { ROUTES } from '../../routes' -import { recognizeSwarmHash } from '../../utils' +import { recognizeEnsOrSwarmHash, regexpEns } from '../../utils' import { determineHistoryName, HISTORY_KEYS, putHistory } from '../../utils/local-storage' import { FileNavigation } from './FileNavigation' @@ -23,10 +23,17 @@ export function Download(): ReactElement { const navigate = useNavigate() const validateChange = (value: string) => { - if (Utils.isHexString(value, 64) || Utils.isHexString(value, 128) || !value.trim().length) { + if ( + Utils.isHexString(value, 64) || + Utils.isHexString(value, 128) || + !value.trim().length || + regexpEns.test(value) + ) { setReferenceError(undefined) } else { - setReferenceError('Incorrect format of swarm hash. Expected 64 or 128 hexstring characters.') + setReferenceError( + 'Incorrect format of swarm hash. Expected 64 or 128 hexstring characters, bzz.link url or ENS domain.', + ) } } @@ -83,7 +90,7 @@ export function Download(): ReactElement { confirmLabelDisabled={Boolean(referenceError) || loading} placeholder="e.g. 31fb0362b1a42536134c86bc58b97ac0244e5c6630beec3e27c2d1cecb38c605" expandedOnly - mapperFn={value => recognizeSwarmHash(value)} + mapperFn={value => recognizeEnsOrSwarmHash(value)} loading={loading} /> diff --git a/src/pages/files/Share.tsx b/src/pages/files/Share.tsx index ba2cfda..81bb571 100644 --- a/src/pages/files/Share.tsx +++ b/src/pages/files/Share.tsx @@ -151,7 +151,7 @@ export function Share(): ReactElement { - + { }) }) -describe('recognizeSwarmHash', () => { - test('should correctly extract hash', () => { - ;[...correctHashes, ...correctCids].forEach(({ input, expectedOutput }) => { - const hash = recognizeSwarmHash(input) +const correctEns: TestObject[] = [ + { + input: 'test.eth', + expectedOutput: 'test.eth', + }, + { + input: 't-est.eth', + expectedOutput: 't-est.eth', + }, + { + input: 'http://test.eth/whatever', + expectedOutput: 'test.eth', + }, + { + input: 'https://alice.test.eth?whatever', + expectedOutput: 'alice.test.eth', + }, + { + input: 'swarm.example.eth/?id=1&page=2', + expectedOutput: 'swarm.example.eth', + }, + { + input: 'http://swarm.example.eth#up', + expectedOutput: 'swarm.example.eth', + }, + { + input: 'http://site.eth:8008', + expectedOutput: 'site.eth', + }, +] + +const wrongEns: string[] = ['http://test.ethereum/whatever'] + +describe('extractEns', () => { + test('should correctly extract ens domain', () => { + correctEns.forEach(({ input, expectedOutput }) => { + const hash = extractEns(input) expect(hash).toBe(expectedOutput) }) }) - test('should not extract hash from incorrect inputs but instead return them', () => { - ;[...wrongHashes, ...wrongCids].forEach(url => { - const hash = recognizeSwarmHash(url) + test('should not extract ens from incorrect inputs', () => { + wrongEns.forEach(url => { + const hash = extractEns(url) + expect(hash).toBe(undefined) + }) + }) +}) + +describe('recognizeEnsOrSwarmHash', () => { + test('should correctly extract hash or ens', () => { + ;[...correctHashes, ...correctCids, ...correctEns].forEach(({ input, expectedOutput }) => { + const hash = recognizeEnsOrSwarmHash(input) + expect(hash).toBe(expectedOutput) + }) + }) + test('should not extract hash or ens from incorrect inputs but instead return them', () => { + ;[...wrongHashes, ...wrongCids, ...wrongEns].forEach(url => { + const hash = recognizeEnsOrSwarmHash(url) expect(hash).toBe(url) }) }) diff --git a/src/utils/index.ts b/src/utils/index.ts index 33e17c1..5a5364c 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -144,8 +144,18 @@ export function extractSwarmCid(s: string): string | undefined { } } -export function recognizeSwarmHash(value: string): string { - return extractSwarmHash(value) || extractSwarmCid(value) || value +// Matches any number of subdomain with .eth +// e.g. this.is.just-a-test.eth +export const regexpEns = /((?:(?:[^-./?:\s][^./?:\s]{0,61}[^-./?:\s]|[^-./?:\s]{1,2})\.)+eth)(?:$|[/?:#].*)/i + +export function extractEns(value: string): string | undefined { + const matches = value.match(regexpEns) + + return (matches && matches[1]) || undefined +} + +export function recognizeEnsOrSwarmHash(value: string): string { + return extractEns(value) || extractSwarmHash(value) || extractSwarmCid(value) || value } export function uuidV4(): string {