@hyperjump/browser
Advanced tools
Comparing version 0.19.0 to 1.0.0
@@ -1,9 +0,35 @@ | ||
const Hyperjump = require("./core"); | ||
const JRef = require("./json-reference/core"); | ||
const Json = require("./json/core"); | ||
import { addMediaTypePlugin } from "./media-types/media-types.js"; | ||
import { jrefMediaTypePlugin } from "./media-types/jref-media-type-plugin.js"; | ||
import { addUriSchemePlugin } from "./uri-schemes/uri-schemes.js"; | ||
import { httpSchemePlugin } from "./uri-schemes/http-scheme-plugin.js"; | ||
import { fileSchemePlugin } from "./uri-schemes/file-scheme-plugin.js"; | ||
Hyperjump.addContentType("application/reference+json", JRef); | ||
Hyperjump.addContentType("application/json", Json); | ||
addMediaTypePlugin("application/reference+json", jrefMediaTypePlugin); | ||
module.exports = Hyperjump; | ||
addUriSchemePlugin("http", httpSchemePlugin); | ||
addUriSchemePlugin("https", httpSchemePlugin); | ||
addUriSchemePlugin("file", fileSchemePlugin); | ||
export { | ||
get, | ||
value, | ||
step, | ||
iter, | ||
keys, | ||
values, | ||
entries, | ||
RetrievalError | ||
} from "./browser/browser.js"; | ||
export { | ||
addMediaTypePlugin, | ||
removeMediaTypePlugin, | ||
setMediaTypeQuality | ||
} from "./media-types/media-types.js"; | ||
export { | ||
addUriSchemePlugin, | ||
removeUriSchemePlugin, | ||
retrieve | ||
} from "./uri-schemes/uri-schemes.js"; |
{ | ||
"name": "@hyperjump/browser", | ||
"version": "0.19.0", | ||
"description": "A generic hypermedia client", | ||
"main": "lib/index.js", | ||
"version": "1.0.0", | ||
"description": "Browse JSON-compatible data with hypermedia references", | ||
"type": "module", | ||
"main": "./lib/index.js", | ||
"exports": { | ||
".": "./lib/index.js", | ||
"./jref": "./lib/jref/index.js" | ||
}, | ||
"browser": { | ||
"./lib/fetch.js": "./lib/fetch.browser.js" | ||
"./lib/index.js": "./lib/index.browser.js", | ||
"./lib/browser/context-uri.js": "./lib/browser/context-uri.browser.js" | ||
}, | ||
"scripts": { | ||
"clean": "xargs -a .gitignore rm -rf", | ||
"lint": "eslint .", | ||
"test": "mocha 'lib/**/*.spec.js'" | ||
"lint": "eslint lib", | ||
"test": "mocha 'lib/**/*.spec.ts'" | ||
}, | ||
"repository": "github:jdesrosiers/hyperjump-browser", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/hyperjump-io/browser.git" | ||
}, | ||
"keywords": [ | ||
"Hyperjump", | ||
"JSON Reference", | ||
"JRef", | ||
"hypermedia", | ||
"generic client" | ||
"json", | ||
"reference", | ||
"jref", | ||
"hypermedia" | ||
], | ||
"author": "Jason Desrosiers <jdesrosi@gmail.com>", | ||
"license": "MIT", | ||
"funding": { | ||
"type": "github", | ||
"url": "https://github.com/sponsors/jdesrosiers" | ||
}, | ||
"devDependencies": { | ||
"chai": "^4.2.0", | ||
"eslint": "^4.19.1", | ||
"eslint-import-resolver-node": "^0.3.2", | ||
"eslint-plugin-import": "^2.18.0", | ||
"mocha": "^5.2.0", | ||
"nock": "^9.6.1", | ||
"rollup": "^1.17.0", | ||
"rollup-plugin-commonjs": "^10.0.1", | ||
"rollup-plugin-node-resolve": "^5.2.0", | ||
"rollup-plugin-terser": "^5.1.1" | ||
"@types/chai": "*", | ||
"@types/mocha": "*", | ||
"@typescript-eslint/eslint-plugin": "*", | ||
"@typescript-eslint/parser": "*", | ||
"chai": "*", | ||
"eslint": "*", | ||
"eslint-import-resolver-node": "*", | ||
"eslint-import-resolver-typescript": "*", | ||
"eslint-plugin-import": "*", | ||
"mocha": "*", | ||
"ts-node": "*", | ||
"typescript": "*", | ||
"yaml": "*" | ||
}, | ||
"engines": { | ||
"node": ">=18.0.0" | ||
}, | ||
"dependencies": { | ||
"@hyperjump/json-pointer": "^0.3.1", | ||
"content-type": "^1.0.4", | ||
"just-curry-it": "^3.1.0", | ||
"make-fetch-happen": "^4.0.2", | ||
"url-resolve-browser": "^1.1.0" | ||
"@hyperjump/json-pointer": "^1.0.1", | ||
"@hyperjump/uri": "^1.2.0", | ||
"content-type": "^1.0.5", | ||
"just-curry-it": "^5.3.0", | ||
"undici": "^5.23.0" | ||
} | ||
} |
284
README.md
@@ -1,153 +0,233 @@ | ||
# Hyperjump Browser | ||
# Hyperjump - Browser | ||
The Hyperjump browser is an experimental generic hypermedia client. It aims to | ||
provide a uniform interface for working with hypermedia enabled media types. | ||
When you use a web browser, you don't interact with HTML, you interact with the | ||
UI that the HTML represents. The Hyperjump browser aims to do the same except | ||
with data. It abstracts away the hypermedia so you can work data as if it's just | ||
plain JSON data without having to leave the browser. | ||
The Hyperjump Browser is a generic client for traversing JSON Reference ([JRef]) | ||
and other [JRef]-compatible media types in a way that abstracts the references | ||
without loosing information. | ||
The Hyperjump browser allows you to plug in support for different media types, | ||
but it comes with support for and was initially designed for [JSON Reference][jref] | ||
(JRef). The Hyperjump browser also has support for JSON, but you won't get | ||
support for the interesting things the browser supports. | ||
## Install | ||
## Installation | ||
This module is designed for node.js (ES Modules, TypeScript) and browsers. It | ||
should work in Bun and Deno as well, but the test runner doesn't work in these | ||
environments, so this module may be less stable in those environments. | ||
### Node.js | ||
```bash | ||
npm install @hyperjump/browser --save | ||
npm install @hyperjump/browser | ||
``` | ||
## Contributing | ||
### Browser | ||
### Tests | ||
When in a browser context, this library is designed to use the browser's `fetch` | ||
implementation instead of a node.js fetch clone. The Webpack bundler does this | ||
properly without any extra configuration, but if you are using the Rollup | ||
bundler you will need to include the `browser: true` option in your Rollup | ||
configuration. | ||
Run the tests | ||
```bash | ||
npm test | ||
```javascript | ||
plugins: [ | ||
resolve({ | ||
browser: true | ||
}) | ||
] | ||
``` | ||
Run the tests with a continuous test runner | ||
## JRef Browser | ||
```bash | ||
npm test -- --watch | ||
This example uses the API at | ||
[https://swapi.hyperjump.io](https://explore.hyperjump.io#https://swapi.hyperjump.io/api/films/1). | ||
It's a variation of the [Star Wars API (SWAPI)](https://swapi.dev) implemented | ||
using the [JRef] media type. | ||
```javascript | ||
import { get, step, value, iter } from "@hyperjump/browser"; | ||
const aNewHope = await get("https://swapi.hyperjump.io/api/films/1"); | ||
const characters = await get("#/characters", aNewHope); // Or | ||
const characters = await step("characters", aNewHope); | ||
for await (const character of iter(characters)) { | ||
const name = await step("name", character); | ||
value(name); // => Luke Skywalker, etc. | ||
} | ||
``` | ||
## Bundlers | ||
You can also work with files on the file system. When working with files, media | ||
types are determined by file extensions. The [JRef] media type uses the `.jref` | ||
extension. | ||
When using with the [Rollup][rollup] bundler, you will need to include the | ||
`browser: true` config option. | ||
```javascript | ||
import { get, value } from "@hyperjump/browser"; | ||
const lukeSkywalker = await get("./api/people/1.jref"); // Paths resolve relative to the current working directory | ||
const name = await step("name", lukeSkywalker); | ||
value(name); // => Luke Skywalker | ||
``` | ||
plugins: [ | ||
resolve({ | ||
browser: true | ||
}), | ||
commonjs() | ||
] | ||
``` | ||
## Usage | ||
### API | ||
The following is short demo. See the [API](#api) section below to see all of the | ||
things you can do. | ||
* get(uri: string, document?: Document): Promise\<Document> | ||
This example uses the API at https://swapi.hyperjump.io. It's a variation of the | ||
[Star Wars API (SWAPI)](https://www.swapi.co) implemented using the [JRef][jref] | ||
media type. | ||
Retrieve a document located at the given URI. Support for [JRef] is built | ||
in. See the [Media Types](#media-type) section for information on how | ||
to support other media types. Support for `http(s):` and `file:` URI schemes | ||
are built in. See the [Uri Schemes](#uri-schemes) section for information on | ||
how to support other URI schemes. | ||
* value(document: Document) => Json | ||
[Hyperjump Pact][pact] is used to apply standard higher-order functions that | ||
work with promises. | ||
Get the JSON compatible value the document represents. Any references will | ||
have been followed so you'll never receive a `Reference` type. | ||
* step(key: string | number, document: Document) => Promise\<Document> | ||
```javascript | ||
const Hyperjump = require("@hyperjump/browser"); | ||
const Pact = require("@hyperjump/pact"); | ||
Move the document cursor by the given "key" value. This is analogous to | ||
indexing into an object or array (`foo[key]`). This function supports | ||
curried application. | ||
* **Schema.iter**: (document: Document) => AsyncGenerator\<Document> | ||
Iterate over the items in the array that the Document represents. | ||
* **Schema.entries**: (document: Document) => AsyncGenerator\<[string, Document]> | ||
const characterHomeworlds = Pact.map(async (character) => { | ||
const name = await character.name; | ||
const homeworld = await character.homeworld.name; | ||
Similar to `Object.entries`, but yields Documents for values. | ||
* **Schema.values**: (document: Document) => AsyncGenerator\<Document> | ||
return `${name} is from ${homeworld}`; | ||
}); | ||
Similar to `Object.values`, but yields Documents for values. | ||
* **Schema.keys**: (document: Document) => Generator\<string> | ||
const ladies = Pact.pipeline([ | ||
Pact.filter(async (character) => (await character.gender) === "female"), | ||
Pact.map((character) => character.name) | ||
]); | ||
Similar to `Object.keys`. | ||
const mass = Pact.reduce(async (acc, character) => { | ||
return acc + (parseInt(await character.mass, 10) || 0); | ||
}, 0); | ||
## Media Types | ||
(async function () { | ||
const film = Hyperjump.fetch("https://swapi.hyperjump.io/api/films/1"); | ||
Support for the [JRef] media type is included by default, but you can add | ||
support for any media type you like as long as it can be represented in a | ||
[JRef]-compatible way. | ||
await film.title; // --> A New Hope | ||
await characterHomeworlds(film.characters); // --> [ 'Luke Skywalker is from Tatooine', | ||
// --> 'C-3PO is from Tatooine', | ||
// --> 'R2-D2 is from Naboo', | ||
// --> ... ] | ||
await ladies(film.characters); // --> [ 'Leia Organa', 'Beru Whitesun lars' ] | ||
await mass(film.characters); // --> 1290 | ||
}()); | ||
```javascript | ||
import { addMediaTypePlugin, removeMediaTypePlugin, setMediaTypeQuality } from "@hyperjump/browser"; | ||
import YAML from "yaml"; | ||
// Add support for YAML version of JRef (YRef) | ||
addMediaTypePlugin("application/reference+yaml", { | ||
parse: async (response) => { | ||
return { | ||
documentValue: YAML.parse(await response.text(), (key, value) => { | ||
return value !== null && typeof value.$href === "string" | ||
? new Reference(value.$href) | ||
: value; | ||
}); | ||
}; | ||
} | ||
}); | ||
// Prefer "YRef" over JRef by reducing the quality for JRef. | ||
setMediaTypeQuality("application/reference+json", 0.9); | ||
// Only support YRef by removing JRef support. | ||
removeMediaTypePlugin("application/reference+json"); | ||
``` | ||
Except for all the promises, this looks exactly like it might if you were | ||
working with a normal in-memory data structure. | ||
### API | ||
## API | ||
* addMediaTypePlugin(contentType: string, plugin: MediaTypePlugin): void | ||
### nil | ||
`Document` | ||
Add support for additional media types. | ||
The nil document. This is like the blank page you see when you first open your | ||
browser. | ||
* type MediaTypePlugin | ||
* parse: (content: string) => Document | ||
* [quality](https://developer.mozilla.org/en-US/docs/Glossary/Quality_values): | ||
number (defaults to `1`) | ||
* removeMediaTypePlugin(contentType: string): void | ||
### get | ||
`(Url, Document|Promise<Document>, Options?) => Promise<Document>` | ||
Removed support or a media type. | ||
* setMediaTypeQuality(contentType: string, quality: number): void; | ||
Retrieve a document with respect to a context document. Options can be passed to | ||
set custom headers. If the value of the document is a link, it will be followed. | ||
Set the | ||
[quality](https://developer.mozilla.org/en-US/docs/Glossary/Quality_values) | ||
that will be used in the | ||
[Accept](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept) | ||
header of requests to indicate to servers what media types are preferred | ||
over others. | ||
### fetch | ||
`(Url, Options?) => Hyperjump` | ||
## URI Schemes | ||
Retrieve a document. Options can be passed to set custom headers. If the value | ||
of the document is a link, it will be followed. | ||
By default, `http(s):` and `file:` URIs are supported. You can add support for | ||
additional URI schemes using plugins. | ||
### value | ||
`(Document|any) => any` | ||
```javascript | ||
import { addUriSchemePlugin, removeUriSchemePlugin, retrieve } from "@hyperjump/browser"; | ||
The value of a document. | ||
// Add support for the `urn:` scheme | ||
addUriSchemePlugin("urn", { | ||
parse: (urn, document) => { | ||
let { nid, nss, query, fragment } = parseUrn(urn); | ||
nid = nid.toLowerCase(); | ||
### source | ||
`(Document) => string` | ||
if (!mappings[nid]?.[nss]) { | ||
throw Error(`Not Found -- ${urn}`); | ||
} | ||
The raw source of a document. | ||
let uri = mappings[nid][nss]; | ||
uri += query ? "?" + query : ""; | ||
uri += fragment ? "#" + fragment : ""; | ||
### step | ||
`(string, Document|Promise<Document>, Options) => Promise<Document|any>` | ||
return retrieve(uri, document); | ||
} | ||
}); | ||
Step into a document using the key given. | ||
// Only support `urn:` by removing default plugins | ||
removeUriSchemePlugin("http"); | ||
removeUriSchemePlugin("https"); | ||
removeUriSchemePlugin("file"); | ||
``` | ||
### construct | ||
`(Url, Headers, string) => Document` | ||
### API | ||
* addUriSchemePlugin(scheme: string, plugin: UriSchemePlugin): void | ||
Construct a document given a URL, headers, and body. For internal use. | ||
Add support for additional URI schemes. | ||
### extend | ||
`(Document, Object) => Document` | ||
* type UriSchemePlugin | ||
* retrieve: (uri: string, document: Document) => Promise\<{ response: Response, fragment: string }> | ||
* removeUriSchemePlugin(scheme: string): void | ||
Modify or add fields to a document. For internal use. | ||
Remove support for a URI scheme. | ||
* retrieve(uri: string, document: Document) => Promise\<{ response: Response, fragment: string }> | ||
### addContentType | ||
`(string, ContentTypeHandler) => void` | ||
This is used internally, but you may need it if mapping names to locators | ||
such as in the example above. | ||
Add support for a new content type. The `ContentTypeHandler` is an object with | ||
three functions: `get`, `value`, and `step`. | ||
## JRef | ||
[jref]: https://github.com/jdesrosiers/hyperjump-browser/blob/master/json-reference/README.md | ||
[pact]: https://github.com/jdesrosiers/hyperjump-pact | ||
[rollup]: https://rollupjs.org | ||
Parse and stringify [JRef] values using the same API as the `JSON` built-in | ||
functions including reviver and replacer functions. | ||
```javascript | ||
import { parse, stringify, Reference } from "@hyperjump/browser/jref"; | ||
const blogPostJref = `{ | ||
"title": "Working with JRef", | ||
"author": { "$href": "/author/jdesrosiers" }, | ||
"content": "lorem ipsum dolor sit amet", | ||
}`; | ||
const blogPost = parse(blogPostJref); | ||
blogPost.author instanceof Reference; // => true | ||
blogPost.author.href; // => "/author/jdesrosiers" | ||
stringify(blogPost, null, " ") === blogPostJref // => true | ||
``` | ||
## Contributing | ||
### Tests | ||
Run the tests | ||
```bash | ||
npm test | ||
``` | ||
Run the tests with a continuous test runner | ||
```bash | ||
npm test -- --watch | ||
``` | ||
[JRef]: https://github.com/hyperjump-io/browser/blob/main/lib/jref/SPECIFICATION.md |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
22275
16
341
1
234
0
2
Yes
13
+ Added@hyperjump/uri@^1.2.0
+ Addedundici@^5.23.0
+ Added@fastify/busboy@2.1.1(transitive)
+ Added@hyperjump/json-pointer@1.1.0(transitive)
+ Added@hyperjump/uri@1.2.2(transitive)
+ Addedjust-curry-it@5.3.0(transitive)
+ Addedundici@5.28.4(transitive)
- Removedmake-fetch-happen@^4.0.2
- Removedurl-resolve-browser@^1.1.0
- Removed@hyperjump/json-pointer@0.3.1(transitive)
- Removedagent-base@4.2.14.3.0(transitive)
- Removedagentkeepalive@3.5.3(transitive)
- Removedaproba@1.2.0(transitive)
- Removedbalanced-match@1.0.2(transitive)
- Removedbluebird@3.7.2(transitive)
- Removedbrace-expansion@1.1.11(transitive)
- Removedbuffer-from@1.1.2(transitive)
- Removedcacache@11.3.3(transitive)
- Removedchownr@1.1.4(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removedconcat-stream@1.6.2(transitive)
- Removedcopy-concurrently@1.0.5(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removedcyclist@1.0.2(transitive)
- Removeddebug@3.1.0(transitive)
- Removedduplexify@3.7.1(transitive)
- Removedencoding@0.1.13(transitive)
- Removedend-of-stream@1.4.4(transitive)
- Removederr-code@1.1.2(transitive)
- Removedes6-promise@4.2.8(transitive)
- Removedes6-promisify@5.0.0(transitive)
- Removedfiggy-pudding@3.5.2(transitive)
- Removedflush-write-stream@1.1.1(transitive)
- Removedfrom2@2.3.0(transitive)
- Removedfs-write-stream-atomic@1.0.10(transitive)
- Removedfs.realpath@1.0.0(transitive)
- Removedglob@7.2.3(transitive)
- Removedgraceful-fs@4.2.11(transitive)
- Removedhttp-cache-semantics@3.8.1(transitive)
- Removedhttp-proxy-agent@2.1.0(transitive)
- Removedhttps-proxy-agent@2.2.4(transitive)
- Removedhumanize-ms@1.2.1(transitive)
- Removediconv-lite@0.6.3(transitive)
- Removediferr@0.1.5(transitive)
- Removedimurmurhash@0.1.4(transitive)
- Removedinflight@1.0.6(transitive)
- Removedinherits@2.0.4(transitive)
- Removedip@1.1.5(transitive)
- Removedisarray@1.0.0(transitive)
- Removedjson-parse-better-errors@1.0.2(transitive)
- Removedjust-curry-it@3.2.1(transitive)
- Removedlru-cache@5.1.1(transitive)
- Removedmake-fetch-happen@4.0.2(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedminimist@1.2.8(transitive)
- Removedmississippi@3.0.0(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedmove-concurrently@1.0.1(transitive)
- Removedms@2.0.0(transitive)
- Removednode-fetch-npm@2.0.4(transitive)
- Removedonce@1.4.0(transitive)
- Removedparallel-transform@1.2.0(transitive)
- Removedpath-is-absolute@1.0.1(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedpromise-inflight@1.0.1(transitive)
- Removedpromise-retry@1.1.1(transitive)
- Removedpump@2.0.13.0.2(transitive)
- Removedpumpify@1.5.1(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedretry@0.10.1(transitive)
- Removedrimraf@2.7.1(transitive)
- Removedrun-queue@1.0.3(transitive)
- Removedsafe-buffer@5.1.25.2.1(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsmart-buffer@4.2.0(transitive)
- Removedsocks@2.3.3(transitive)
- Removedsocks-proxy-agent@4.0.2(transitive)
- Removedssri@6.0.2(transitive)
- Removedstream-each@1.2.3(transitive)
- Removedstream-shift@1.0.3(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedthrough2@2.0.5(transitive)
- Removedtypedarray@0.0.6(transitive)
- Removedunique-filename@1.1.1(transitive)
- Removedunique-slug@2.0.2(transitive)
- Removedurl-resolve-browser@1.2.0(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedwrappy@1.0.2(transitive)
- Removedxtend@4.0.2(transitive)
- Removedy18n@4.0.3(transitive)
- Removedyallist@3.1.1(transitive)
Updatedcontent-type@^1.0.5
Updatedjust-curry-it@^5.3.0