+29
-18
@@ -5,3 +5,4 @@ 'use strict' | ||
| const { ALIASES } = require('pear-aliases') | ||
| const { encode, decode } = require('hypercore-id-encoding') | ||
| const hypercoreid = require('hypercore-id-encoding') | ||
| const { encode } = hypercoreid | ||
| const FILE = 'file:' | ||
@@ -11,5 +12,14 @@ const PEAR = 'pear:' | ||
| function decode (v, info = {}) { | ||
| try { | ||
| return hypercoreid.decode(v) | ||
| } catch (err) { | ||
| if (typeof v === 'string') throw ERR_INVALID_LINK('alias not found: "' + v + '"', { ...info, err }) | ||
| throw err | ||
| } | ||
| } | ||
| class PearLink { | ||
| normalize (link) { | ||
| // if link has url format, separator is always '/' even in Windows | ||
| // if link has link format, separator is always '/' even in Windows | ||
| if (link.startsWith(FILE + DOUB)) return link.endsWith('/') ? link.slice(0, -1) : link | ||
@@ -28,9 +38,9 @@ else return link.endsWith(path.sep) ? link.slice(0, -1) : link | ||
| throw ERR_INVALID_LINK('Unsupported protocol') | ||
| throw ERR_INVALID_LINK('Unsupported protocol', { protocol, pathname, search, hash, drive }) | ||
| } | ||
| parse (url) { | ||
| if (!url) throw ERR_INVALID_LINK('No link specified') | ||
| const isPath = url.startsWith(PEAR + DOUB) === false && url.startsWith(FILE + DOUB) === false | ||
| const isRelativePath = isPath && url[0] !== '/' && url[1] !== ':' | ||
| parse (link) { | ||
| if (!link) throw ERR_INVALID_LINK('No link specified', { link }) | ||
| const isPath = link.startsWith(PEAR + DOUB) === false && link.startsWith(FILE + DOUB) === false | ||
| const isRelativePath = isPath && link[0] !== '/' && link[1] !== ':' | ||
| const keys = Object.fromEntries(Object.entries(ALIASES).map(([k, v]) => [encode(v), k])) | ||
@@ -43,8 +53,9 @@ const { | ||
| hash | ||
| } = isRelativePath ? new URL(url, FILE + DOUB + path.resolve('.') + '/') : new URL(isPath ? FILE + DOUB + url : url) | ||
| } = isRelativePath ? new URL(link, FILE + DOUB + path.resolve('.') + '/') : new URL(isPath ? FILE + DOUB + link : link) | ||
| const info = { link, protocol, hostname, pathname, search, hash } | ||
| if (protocol === FILE) { | ||
| // file:///some/path/to/a/file.js | ||
| const startsWithRoot = hostname === '' | ||
| if (!pathname) throw ERR_INVALID_LINK('Path is missing') | ||
| if (!startsWithRoot) throw ERR_INVALID_LINK('Path needs to start from the root, "/"') | ||
| if (!pathname) throw ERR_INVALID_LINK('Path is missing', info) | ||
| if (!startsWithRoot) throw ERR_INVALID_LINK('Path needs to start from the root, "/"', info) | ||
| return { | ||
@@ -68,3 +79,3 @@ protocol, | ||
| if (parts === 1) { // pear://keyOrAlias[/some/path] | ||
| const key = ALIASES[hostname] || decode(hostname) | ||
| const key = ALIASES[hostname] || decode(hostname, info) | ||
| const origin = keys[encode(key)] ? `${protocol}//${keys[encode(key)]}` : `${protocol}//${hostname}` | ||
@@ -89,11 +100,11 @@ const alias = ALIASES[hostname] ? hostname : null | ||
| if (parts === 2) { // pear://fork.length[/some/path] | ||
| throw ERR_INVALID_LINK('Incorrect hostname') | ||
| throw ERR_INVALID_LINK('Incorrect hostname', info) | ||
| } | ||
| const alias = ALIASES[keyOrAlias] ? keyOrAlias : null | ||
| const key = ALIASES[keyOrAlias] || decode(keyOrAlias) | ||
| const key = ALIASES[keyOrAlias] || decode(keyOrAlias, info) | ||
| const origin = keys[encode(key)] ? `${protocol}//${keys[encode(key)]}` : `${protocol}//${keyOrAlias}` | ||
| if (parts === 3) { // pear://fork.length.keyOrAlias[/some/path] | ||
| if (!Number.isInteger(+fork) || !Number.isInteger(+length)) throw ERR_INVALID_LINK('Incorrect hostname') | ||
| if (!Number.isInteger(+fork) || !Number.isInteger(+length)) throw ERR_INVALID_LINK('Incorrect hostname', info) | ||
| return { | ||
@@ -116,3 +127,3 @@ protocol, | ||
| if (parts === 4) { // pear://fork.length.keyOrAlias.dhash[/some/path] | ||
| if (!Number.isInteger(+fork) || !Number.isInteger(+length)) throw ERR_INVALID_LINK('Incorrect hostname') | ||
| if (!Number.isInteger(+fork) || !Number.isInteger(+length)) throw ERR_INVALID_LINK('Incorrect hostname', info) | ||
@@ -129,3 +140,3 @@ return { | ||
| fork: Number(fork), | ||
| hash: decode(apphash), | ||
| hash: hypercoreid.decode(apphash), | ||
| alias | ||
@@ -136,6 +147,6 @@ } | ||
| throw ERR_INVALID_LINK('Incorrect hostname') | ||
| throw ERR_INVALID_LINK('Incorrect hostname', info) | ||
| } | ||
| throw ERR_INVALID_LINK('Protocol is not supported') | ||
| throw ERR_INVALID_LINK('Protocol is not supported', info) | ||
| } | ||
@@ -142,0 +153,0 @@ } |
+3
-2
| { | ||
| "name": "pear-link", | ||
| "version": "4.0.0", | ||
| "version": "4.1.0", | ||
| "description": "Parse Pear Links", | ||
@@ -39,4 +39,5 @@ "main": "index.js", | ||
| "brittle": "^3.4.1", | ||
| "standard": "^17.1.0" | ||
| "standard": "^17.1.0", | ||
| "url-file-url": "^1.0.5" | ||
| } | ||
| } |
19199
2.52%131
8.26%4
33.33%