@json-schema-tools/dereferencer
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -1,122 +0,12 @@ | ||
import { JSONSchema, JSONSchemaObject } from "@json-schema-tools/meta-schema"; | ||
export interface RefCache { | ||
[k: string]: JSONSchema; | ||
} | ||
/** | ||
* Options that can be passed to the derefencer constructor. | ||
*/ | ||
export interface DereferencerOptions { | ||
/** | ||
* If true, resolved non-local references will also be dereferenced using the same options. | ||
*/ | ||
recursive?: boolean; | ||
} | ||
export declare const defaultDereferencerOptions: DereferencerOptions; | ||
/** | ||
* Error thrown by the constructor when given a ref that isn't a string | ||
* | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { NonStringRefError } from "@json-schema-tools/dereferencer"; | ||
* | ||
* try { const dereffer = new Dereferencer({}); } | ||
* catch(e) { | ||
* if (e instanceof NonStringRefError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
export declare class NonStringRefError extends Error { | ||
constructor(schema: JSONSchema); | ||
} | ||
/** | ||
* Error thrown when the fetched reference is not properly formatted JSON or is encoded | ||
* incorrectly | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { NonJsonRefError } from "@json-schema-tools/dereferencer"; | ||
* const dereffer = new Dereferencer({}); | ||
* try { await dereffer.resolve(); } | ||
* catch(e) { | ||
* if (e instanceof NonJsonRefError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
export declare class NonJsonRefError extends Error { | ||
constructor(schema: JSONSchemaObject, nonJson: string); | ||
} | ||
/** | ||
* Error thrown when a JSON pointer is provided but is not parseable as per the RFC6901 | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { InvalidJsonPointerRefError } from "@json-schema-tools/dereferencer"; | ||
* const dereffer = new Dereferencer({}); | ||
* try { await dereffer.resolve(); } | ||
* catch(e) { | ||
* if (e instanceof InvalidJsonPointerRefError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
export declare class InvalidJsonPointerRefError extends Error { | ||
constructor(schema: JSONSchemaObject); | ||
} | ||
/** | ||
* Error thrown when given an invalid file system path as a reference. | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { InvalidFileSystemPathError } from "@json-schema-tools/dereferencer"; | ||
* const dereffer = new Dereferencer({}); | ||
* try { await dereffer.resolve(); } | ||
* catch(e) { | ||
* if (e instanceof InvalidFileSystemPathError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
export declare class InvalidFileSystemPathError extends Error { | ||
constructor(ref: string); | ||
} | ||
/** | ||
* Error thrown when given an invalid file system path as a reference. | ||
* | ||
*/ | ||
export declare class InvalidRemoteURLError extends Error { | ||
constructor(ref: string); | ||
} | ||
/** | ||
* When instantiated, represents a fully configured dereferencer. When constructed, references are pulled out. | ||
* No references are fetched until .resolve is called. | ||
*/ | ||
export declare class Dereferencer { | ||
private options; | ||
refs: string[]; | ||
private refCache; | ||
private schema; | ||
constructor(schema: JSONSchema, options?: DereferencerOptions); | ||
/** | ||
* Fetches the schemas for all the refs in the configured input schema(s) | ||
* | ||
* @returns a promise that will resolve a fully dereferenced schema, where all the | ||
* promises for each ref has been resolved as well. | ||
* | ||
* | ||
*/ | ||
resolve(): Promise<JSONSchema>; | ||
fetchRef(ref: string): Promise<JSONSchema>; | ||
/** | ||
* First-pass traversal to collect all the refs that we can find. This allows us to | ||
* optimize the async work required as well. | ||
*/ | ||
collectRefs(): string[]; | ||
} | ||
export default Dereferencer; | ||
declare const _default: { | ||
new (schema: import("@json-schema-tools/meta-schema").JSONSchema, options?: import("./dereferencer").DereferencerOptions): { | ||
refs: string[]; | ||
refCache: import("./dereferencer").RefCache; | ||
schema: import("@json-schema-tools/meta-schema").JSONSchema; | ||
options: import("./dereferencer").DereferencerOptions; | ||
resolve(): Promise<import("@json-schema-tools/meta-schema").JSONSchema>; | ||
fetchRef(ref: string): Promise<import("@json-schema-tools/meta-schema").JSONSchema>; | ||
collectRefs(): string[]; | ||
}; | ||
}; | ||
export default _default; |
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = function (d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
@@ -34,38 +21,2 @@ if (k2 === undefined) k2 = k; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -75,339 +26,5 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Dereferencer = exports.InvalidRemoteURLError = exports.InvalidFileSystemPathError = exports.InvalidJsonPointerRefError = exports.NonJsonRefError = exports.NonStringRefError = exports.defaultDereferencerOptions = void 0; | ||
var traverse_1 = __importDefault(require("@json-schema-tools/traverse")); | ||
var dereferencer_1 = __importDefault(require("./dereferencer")); | ||
var isomorphic_fetch_1 = __importDefault(require("isomorphic-fetch")); | ||
var fs = __importStar(require("fs")); | ||
var node_fetch_1 = __importDefault(require("node-fetch")); | ||
var json_pointer_1 = __importDefault(require("@json-schema-spec/json-pointer")); | ||
var path = __importStar(require("path")); | ||
var fileExistsAndReadable = function (f) { | ||
return new Promise(function (resolve) { | ||
return fs.access(f, fs.constants.F_OK | fs.constants.R_OK, function (e) { | ||
if (e) { | ||
return resolve(false); | ||
} | ||
return resolve(true); | ||
}); | ||
}); | ||
}; | ||
var readFile = function (f) { | ||
return new Promise(function (resolve, reject) { | ||
return fs.readFile(f, "utf8", function (err, data) { | ||
if (err) { | ||
return reject(err); | ||
} | ||
return resolve(data); | ||
}); | ||
}); | ||
}; | ||
exports.defaultDereferencerOptions = { | ||
recursive: true, | ||
}; | ||
/** | ||
* Error thrown by the constructor when given a ref that isn't a string | ||
* | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { NonStringRefError } from "@json-schema-tools/dereferencer"; | ||
* | ||
* try { const dereffer = new Dereferencer({}); } | ||
* catch(e) { | ||
* if (e instanceof NonStringRefError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
var NonStringRefError = /** @class */ (function (_super) { | ||
__extends(NonStringRefError, _super); | ||
function NonStringRefError(schema) { | ||
var _this = this; | ||
var schemaString = ""; | ||
try { | ||
schemaString = JSON.stringify(schema); | ||
} | ||
catch (e) { | ||
schemaString = [ | ||
"Keys: " + Object.keys(schema), | ||
"Respective Values: " + Object.values(schema), | ||
].join("\n"); | ||
} | ||
_this = _super.call(this, [ | ||
"NonStringRefError", | ||
"Found an improperly formatted $ref in schema. $ref must be a string", | ||
"schema in question: " + schemaString, | ||
].join("\n")) || this; | ||
return _this; | ||
} | ||
return NonStringRefError; | ||
}(Error)); | ||
exports.NonStringRefError = NonStringRefError; | ||
/** | ||
* Error thrown when the fetched reference is not properly formatted JSON or is encoded | ||
* incorrectly | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { NonJsonRefError } from "@json-schema-tools/dereferencer"; | ||
* const dereffer = new Dereferencer({}); | ||
* try { await dereffer.resolve(); } | ||
* catch(e) { | ||
* if (e instanceof NonJsonRefError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
var NonJsonRefError = /** @class */ (function (_super) { | ||
__extends(NonJsonRefError, _super); | ||
function NonJsonRefError(schema, nonJson) { | ||
return _super.call(this, [ | ||
"NonJsonRefError", | ||
"The resolved value at the reference: " + schema.$ref + " was not JSON.parse 'able", | ||
"The non-json content in question: " + nonJson, | ||
].join("\n")) || this; | ||
} | ||
return NonJsonRefError; | ||
}(Error)); | ||
exports.NonJsonRefError = NonJsonRefError; | ||
/** | ||
* Error thrown when a JSON pointer is provided but is not parseable as per the RFC6901 | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { InvalidJsonPointerRefError } from "@json-schema-tools/dereferencer"; | ||
* const dereffer = new Dereferencer({}); | ||
* try { await dereffer.resolve(); } | ||
* catch(e) { | ||
* if (e instanceof InvalidJsonPointerRefError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
var InvalidJsonPointerRefError = /** @class */ (function (_super) { | ||
__extends(InvalidJsonPointerRefError, _super); | ||
function InvalidJsonPointerRefError(schema) { | ||
return _super.call(this, [ | ||
"InvalidJsonPointerRefError", | ||
"The provided RFC6901 JSON Pointer is invalid: " + schema.$ref, | ||
].join("\n")) || this; | ||
} | ||
return InvalidJsonPointerRefError; | ||
}(Error)); | ||
exports.InvalidJsonPointerRefError = InvalidJsonPointerRefError; | ||
/** | ||
* Error thrown when given an invalid file system path as a reference. | ||
* | ||
* @example | ||
* ```typescript | ||
* | ||
* import Dereferencer, { InvalidFileSystemPathError } from "@json-schema-tools/dereferencer"; | ||
* const dereffer = new Dereferencer({}); | ||
* try { await dereffer.resolve(); } | ||
* catch(e) { | ||
* if (e instanceof InvalidFileSystemPathError) { ... } | ||
* } | ||
* ``` | ||
* | ||
*/ | ||
var InvalidFileSystemPathError = /** @class */ (function (_super) { | ||
__extends(InvalidFileSystemPathError, _super); | ||
function InvalidFileSystemPathError(ref) { | ||
return _super.call(this, [ | ||
"InvalidFileSystemPathError", | ||
"The path was not resolvable: " + ref, | ||
"resolved path: " + path.resolve(process.cwd(), ref), | ||
].join("\n")) || this; | ||
} | ||
return InvalidFileSystemPathError; | ||
}(Error)); | ||
exports.InvalidFileSystemPathError = InvalidFileSystemPathError; | ||
/** | ||
* Error thrown when given an invalid file system path as a reference. | ||
* | ||
*/ | ||
var InvalidRemoteURLError = /** @class */ (function (_super) { | ||
__extends(InvalidRemoteURLError, _super); | ||
function InvalidRemoteURLError(ref) { | ||
return _super.call(this, [ | ||
"InvalidRemoteURLError", | ||
"The url was not resolvable: " + ref, | ||
].join("\n")) || this; | ||
} | ||
return InvalidRemoteURLError; | ||
}(Error)); | ||
exports.InvalidRemoteURLError = InvalidRemoteURLError; | ||
/** | ||
* When instantiated, represents a fully configured dereferencer. When constructed, references are pulled out. | ||
* No references are fetched until .resolve is called. | ||
*/ | ||
var Dereferencer = /** @class */ (function () { | ||
function Dereferencer(schema, options) { | ||
if (options === void 0) { options = exports.defaultDereferencerOptions; } | ||
this.options = options; | ||
this.refCache = {}; | ||
this.schema = schema; // shallow copy breaks recursive | ||
this.refs = this.collectRefs(); | ||
} | ||
/** | ||
* Fetches the schemas for all the refs in the configured input schema(s) | ||
* | ||
* @returns a promise that will resolve a fully dereferenced schema, where all the | ||
* promises for each ref has been resolved as well. | ||
* | ||
* | ||
*/ | ||
Dereferencer.prototype.resolve = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var refMap, proms, _i, _a, ref, fetched, subDereffer, _b, subFetched, _c, _d, _e, _f, recurseResolve; | ||
var _this = this; | ||
return __generator(this, function (_g) { | ||
switch (_g.label) { | ||
case 0: | ||
refMap = {}; | ||
if (this.schema === true || this.schema === false) { | ||
return [2 /*return*/, Promise.resolve(this.schema)]; | ||
} | ||
if (this.refs.length === 0) { | ||
delete this.schema.definitions; | ||
return [2 /*return*/, Promise.resolve(this.schema)]; | ||
} | ||
proms = []; | ||
_i = 0, _a = this.refs; | ||
_g.label = 1; | ||
case 1: | ||
if (!(_i < _a.length)) return [3 /*break*/, 7]; | ||
ref = _a[_i]; | ||
fetched = this.fetchRef(ref); | ||
proms.push(fetched); | ||
if (!(this.options.recursive === true && ref[0] !== "#")) return [3 /*break*/, 4]; | ||
_b = Dereferencer.bind; | ||
return [4 /*yield*/, fetched]; | ||
case 2: | ||
subDereffer = new (_b.apply(Dereferencer, [void 0, _g.sent(), this.options]))(); | ||
subFetched = subDereffer.resolve(); | ||
proms.push(subFetched); | ||
_c = refMap; | ||
_d = ref; | ||
return [4 /*yield*/, subFetched]; | ||
case 3: | ||
_c[_d] = _g.sent(); | ||
return [3 /*break*/, 6]; | ||
case 4: | ||
_e = refMap; | ||
_f = ref; | ||
return [4 /*yield*/, fetched]; | ||
case 5: | ||
_e[_f] = _g.sent(); | ||
_g.label = 6; | ||
case 6: | ||
_i++; | ||
return [3 /*break*/, 1]; | ||
case 7: | ||
if (this.schema.$ref !== undefined) { | ||
this.schema = refMap[this.schema.$ref]; | ||
} | ||
else { | ||
traverse_1.default(this.schema, function (s) { | ||
if (s === true || s === false) { | ||
return s; | ||
} | ||
if (s.$ref !== undefined) { | ||
return refMap[s.$ref]; | ||
} | ||
return s; | ||
}, { mutable: true }); | ||
} | ||
if (this.options.recursive === true) { | ||
this.refs = this.collectRefs(); | ||
recurseResolve = this.resolve(); | ||
proms.push(recurseResolve); | ||
} | ||
return [2 /*return*/, Promise.all(proms).then(function () { return _this.schema; })]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Dereferencer.prototype.fetchRef = function (ref) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var withoutHash, pointer, reffedSchema, fileContents, reffedSchema, rs, _a, _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
if (this.refCache[ref] !== undefined) { | ||
return [2 /*return*/, Promise.resolve(this.refCache[ref])]; | ||
} | ||
if (ref[0] === "#") { | ||
withoutHash = ref.replace("#", ""); | ||
try { | ||
pointer = json_pointer_1.default.parse(withoutHash); | ||
reffedSchema = pointer.eval(this.schema); | ||
this.refCache[ref] = reffedSchema; | ||
return [2 /*return*/, Promise.resolve(reffedSchema)]; | ||
} | ||
catch (e) { | ||
throw new InvalidJsonPointerRefError({ $ref: ref }); | ||
} | ||
} | ||
return [4 /*yield*/, fileExistsAndReadable(ref)]; | ||
case 1: | ||
if (!((_c.sent()) === true)) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, readFile(ref)]; | ||
case 2: | ||
fileContents = _c.sent(); | ||
reffedSchema = void 0; | ||
try { | ||
reffedSchema = JSON.parse(fileContents); | ||
} | ||
catch (e) { | ||
throw new NonJsonRefError({ $ref: ref }, fileContents); | ||
} | ||
this.refCache[ref] = reffedSchema; | ||
return [2 /*return*/, reffedSchema]; | ||
case 3: | ||
if (["$", ".", "/", ".."].indexOf(ref[0]) !== -1) { | ||
throw new InvalidFileSystemPathError(ref); | ||
} | ||
_c.label = 4; | ||
case 4: | ||
try { | ||
rs = node_fetch_1.default(ref).then(function (r) { return r.json(); }); | ||
} | ||
catch (e) { | ||
throw new InvalidRemoteURLError(ref); | ||
} | ||
_a = this.refCache; | ||
_b = ref; | ||
return [4 /*yield*/, rs]; | ||
case 5: | ||
_a[_b] = _c.sent(); | ||
return [2 /*return*/, rs]; | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* First-pass traversal to collect all the refs that we can find. This allows us to | ||
* optimize the async work required as well. | ||
*/ | ||
Dereferencer.prototype.collectRefs = function () { | ||
var refs = []; | ||
traverse_1.default(this.schema, function (s) { | ||
if (s === true || s === false) { | ||
return s; | ||
} | ||
if (s.$ref && refs.indexOf(s.$ref) === -1) { | ||
if (typeof s.$ref !== "string") { | ||
throw new NonStringRefError(s); | ||
} | ||
refs.push(s.$ref); | ||
} | ||
return s; | ||
}); | ||
return refs; | ||
}; | ||
return Dereferencer; | ||
}()); | ||
exports.Dereferencer = Dereferencer; | ||
exports.default = Dereferencer; | ||
exports.default = dereferencer_1.default(isomorphic_fetch_1.default, fs); |
@@ -0,1 +1,8 @@ | ||
# [1.2.0](https://github.com/json-schema-tools/dereferencer/compare/1.1.0...1.2.0) (2020-07-22) | ||
### Features | ||
* isomorphic browser n node support ([0ef22b4](https://github.com/json-schema-tools/dereferencer/commit/0ef22b4687d3059f0cd68b142acff6e24a3f84cd)) | ||
# [1.1.0](https://github.com/json-schema-tools/dereferencer/compare/1.0.15...1.1.0) (2020-07-21) | ||
@@ -2,0 +9,0 @@ |
{ | ||
"name": "@json-schema-tools/dereferencer", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Dereference (aka parse refs) from JSON Schemas", | ||
"main": "build/index.js", | ||
"browser": "build/index-web.js", | ||
"publishConfig": { | ||
@@ -10,5 +11,8 @@ "access": "public" | ||
"scripts": { | ||
"build": "tsc && typedoc --out docs && touch docs/.nojekyll", | ||
"build": "npm run build:code && typedoc --out docs && touch docs/.nojekyll", | ||
"build:code": "tsc", | ||
"lint": "tslint --fix -p .", | ||
"test": "npm run lint && jest --coverage" | ||
"test": "npm run test:unit && npm run test:web", | ||
"test:unit": "npm run lint && jest --coverage", | ||
"test:web": "npm run build:code && webpack && rm -rf dist" | ||
}, | ||
@@ -30,5 +34,5 @@ "author": "BelfordZ<belfordz66@gmail.com>", | ||
"@json-schema-tools/meta-schema": "^1.3.0", | ||
"@types/isomorphic-fetch": "0.0.35", | ||
"@types/jest": "^26.0.3", | ||
"@types/node": "^14.0.14", | ||
"@types/node-fetch": "^2.5.7", | ||
"jest": "^24.8.0", | ||
@@ -38,3 +42,5 @@ "ts-jest": "^24.1.0", | ||
"typedoc": "^0.17.8", | ||
"typescript": "^3.9.6" | ||
"typescript": "^3.9.6", | ||
"webpack": "^4.31.0", | ||
"webpack-cli": "^3.3.2" | ||
}, | ||
@@ -44,4 +50,4 @@ "dependencies": { | ||
"@json-schema-tools/traverse": "^1.4.2", | ||
"node-fetch": "^2.6.0" | ||
"isomorphic-fetch": "^2.2.1" | ||
} | ||
} |
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
Network access
Supply chain riskThis module accesses the network.
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
45987
10
591
11
2
+ Addedisomorphic-fetch@^2.2.1
+ Addedencoding@0.1.13(transitive)
+ Addediconv-lite@0.6.3(transitive)
+ Addedis-stream@1.1.0(transitive)
+ Addedisomorphic-fetch@2.2.1(transitive)
+ Addednode-fetch@1.7.3(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedwhatwg-fetch@3.6.20(transitive)
- Removednode-fetch@^2.6.0
- Removednode-fetch@2.7.0(transitive)
- Removedtr46@0.0.3(transitive)
- Removedwebidl-conversions@3.0.1(transitive)
- Removedwhatwg-url@5.0.0(transitive)