+19
-21
| 'use strict' | ||
| const path = require('path') | ||
| const { ERR_INVALID_LINK } = require('pear-errors') | ||
| const { ALIASES } = require('pear-aliases') | ||
| const { encode, decode } = require('hypercore-id-encoding') | ||
@@ -8,8 +10,3 @@ const FILE = 'file:' | ||
| module.exports = class PearLink { | ||
| constructor (aliases = {}, E = Error) { | ||
| this.aliases = aliases | ||
| this.Error = E | ||
| } | ||
| class PearLink { | ||
| normalize (link) { | ||
@@ -30,11 +27,10 @@ // if link has url format, separator is always '/' even in Windows | ||
| throw new this.Error('Unsupported protocol') | ||
| throw ERR_INVALID_LINK('Unsupported protocol') | ||
| } | ||
| parse (url) { | ||
| const { aliases, Error } = this | ||
| if (!url) throw new Error('No link specified') | ||
| 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] !== ':' | ||
| const keys = Object.fromEntries(Object.entries(aliases).map(([k, v]) => [encode(v), k])) | ||
| const keys = Object.fromEntries(Object.entries(ALIASES).map(([k, v]) => [encode(v), k])) | ||
| const { | ||
@@ -50,4 +46,4 @@ protocol, | ||
| const startsWithRoot = hostname === '' | ||
| if (!pathname) throw new Error('Path is missing') | ||
| if (!startsWithRoot) throw new Error('Path needs to start from the root, "/"') | ||
| if (!pathname) throw ERR_INVALID_LINK('Path is missing') | ||
| if (!startsWithRoot) throw ERR_INVALID_LINK('Path needs to start from the root, "/"') | ||
| return { | ||
@@ -71,5 +67,5 @@ protocol, | ||
| if (parts === 1) { // pear://keyOrAlias[/some/path] | ||
| const key = aliases[hostname] || decode(hostname) | ||
| const key = ALIASES[hostname] || decode(hostname) | ||
| const origin = keys[encode(key)] ? `${protocol}//${keys[encode(key)]}` : `${protocol}//${hostname}` | ||
| const alias = aliases[hostname] ? hostname : null | ||
| const alias = ALIASES[hostname] ? hostname : null | ||
| return { | ||
@@ -92,11 +88,11 @@ protocol, | ||
| if (parts === 2) { // pear://fork.length[/some/path] | ||
| throw new Error('Incorrect hostname') | ||
| throw ERR_INVALID_LINK('Incorrect hostname') | ||
| } | ||
| const alias = aliases[keyOrAlias] ? keyOrAlias : null | ||
| const key = aliases[keyOrAlias] || decode(keyOrAlias) | ||
| const alias = ALIASES[keyOrAlias] ? keyOrAlias : null | ||
| const key = ALIASES[keyOrAlias] || decode(keyOrAlias) | ||
| 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 new Error('Incorrect hostname') | ||
| if (!Number.isInteger(+fork) || !Number.isInteger(+length)) throw ERR_INVALID_LINK('Incorrect hostname') | ||
| return { | ||
@@ -119,3 +115,3 @@ protocol, | ||
| if (parts === 4) { // pear://fork.length.keyOrAlias.dhash[/some/path] | ||
| if (!Number.isInteger(+fork) || !Number.isInteger(+length)) throw new Error('Incorrect hostname') | ||
| if (!Number.isInteger(+fork) || !Number.isInteger(+length)) throw ERR_INVALID_LINK('Incorrect hostname') | ||
@@ -138,7 +134,9 @@ return { | ||
| throw new Error('Incorrect hostname') | ||
| throw ERR_INVALID_LINK('Incorrect hostname') | ||
| } | ||
| throw new Error('Protocol is not supported') | ||
| throw ERR_INVALID_LINK('Protocol is not supported') | ||
| } | ||
| } | ||
| module.exports = new PearLink() |
+6
-3
| { | ||
| "name": "pear-link", | ||
| "version": "3.1.1", | ||
| "version": "4.0.0", | ||
| "description": "Parse Pear Links", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "test": "brittle test/index.test.js && standard", | ||
| "test:bare": "bare test/index.test.js" | ||
| "test": "brittle-bare test/index.test.js", | ||
| "test:node": "node test/index.test.js", | ||
| "lint": "standard" | ||
| }, | ||
@@ -31,2 +32,4 @@ "repository": { | ||
| "hypercore-id-encoding": "^1.2.0", | ||
| "pear-aliases": "^1.0.0", | ||
| "pear-errors": "^1.0.0", | ||
| "which-runtime": "^1.2.1" | ||
@@ -33,0 +36,0 @@ }, |
+57
-1
| # pear-link | ||
| Parse Pear Links | ||
| Parse Pear Links. This includes URLs with `pear:` & `file:` protocols. | ||
@@ -9,4 +9,60 @@ ``` | ||
| ## Pear Link Format | ||
| The `pear:` protocol supports the following syntax: | ||
| ``` | ||
| pear://[<fork>.][<length>.]<keyOrAlias>[.<dhash>]<path>[?<search>][#<lochash>] | ||
| ``` | ||
| - `fork` is the [fork id](https://github.com/holepunchto/hypercore#corefork) for the underlying hypercore. | ||
| - `length` is the [length](https://github.com/holepunchto/hypercore#corelength) of the underlying hypercore. | ||
| - `keyOrAlias` is the z32 or hex encoded key or an alias for the key. | ||
| - `path` is zero or more path segments separated by a `/`. | ||
| - `search` is a query string of non-hierarchical data proceeded by a question | ||
| mark (`?`). | ||
| - `lochash` is the fragment proceeded by a hash (`#`). | ||
| ## API | ||
| ### `const plink = require('pear-link')` | ||
| Exports a singleton with methods `parse`, `serialize` and `normalize`. | ||
| Supports aliases per [`pear-aliases`](https://github.com/holepunchto/pear-aliases). | ||
| #### `const { protocol, pathname, search, hash, origin, drive } = plink.parse(url)` | ||
| Parses the provided `url` string returning an object describing the URL's | ||
| properties. | ||
| The returned object contains the following: | ||
| ``` | ||
| { | ||
| protocol, // The url's protocol. Supported protocols include `pear:` & `file:` | ||
| pathname, // The `some/path` in `pear://key/some/path`. Same as the standard URL pathname | ||
| search, // The query string in the URL, aka anything after a `?` including the `?` | ||
| hash, // The fragment part of the URL, eg `#fragment` in `pear://key/path#fragment`. Includes the `#`. | ||
| origin: this.normalize(`${protocol}//${hostname}${pathname}`), | ||
| drive: { | ||
| key, // The key for the hyperdrive. Usually the `key` part of a pear link. | ||
| length, // The hyperdrive length defined in the URL. | ||
| fork, // The hyperdrive fork defined in the URL. | ||
| hash, // The dhash in the URL. | ||
| } | ||
| } | ||
| ``` | ||
| #### `const normalizedLink = plink.normalize(link)` | ||
| Normalizes the link by removing trailing path separators (`/`). | ||
| #### `const link = plink.serialize({ protocol, pathname, search, hash, drive })` | ||
| Returns the serialized version of the object describing a URL as a string. | ||
| ## License | ||
| Apache-2.0 |
18727
13.44%68
466.67%4
100%121
-1.63%+ Added
+ Added
+ Added
+ Added