Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

superjson

Package Overview
Dependencies
Maintainers
4
Versions
52
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

superjson - npm Package Compare versions

Comparing version 1.6.2 to 1.7.1

dist/walker.d.ts

1

dist/accessDeep.d.ts

@@ -1,3 +0,2 @@

export declare const getNthKey: (value: Map<any, any> | Set<any>, n: number) => any;
export declare const getDeep: (object: object, path: (string | number)[]) => object;
export declare const setDeep: (object: any, path: (string | number)[], mapper: (v: any) => any) => any;
"use strict";
exports.__esModule = true;
exports.setDeep = exports.getDeep = exports.getNthKey = void 0;
exports.setDeep = exports.getDeep = void 0;
var is_1 = require("./is");

@@ -13,3 +13,2 @@ var getNthKey = function (value, n) {

};
exports.getNthKey = getNthKey;
var getDeep = function (object, path) {

@@ -38,3 +37,3 @@ path.forEach(function (key) {

var row = +key;
parent = exports.getNthKey(parent, row);
parent = getNthKey(parent, row);
}

@@ -47,4 +46,4 @@ else if (is_1.isMap(parent)) {

var row = +key;
var type = +path[i + 1] === 0 ? 'key' : 'value';
var keyOfRow = exports.getNthKey(parent, row);
var type = +path[++i] === 0 ? 'key' : 'value';
var keyOfRow = getNthKey(parent, row);
switch (type) {

@@ -58,3 +57,2 @@ case 'key':

}
i++;
}

@@ -67,3 +65,3 @@ }

if (is_1.isSet(parent)) {
var oldValue = exports.getNthKey(parent, +lastKey);
var oldValue = getNthKey(parent, +lastKey);
var newValue = mapper(oldValue);

@@ -77,3 +75,3 @@ if (oldValue !== newValue) {

var row = +path[path.length - 2];
var keyToRow = exports.getNthKey(parent, row);
var keyToRow = getNthKey(parent, row);
var type = +lastKey === 0 ? 'key' : 'value';

@@ -80,0 +78,0 @@ switch (type) {

@@ -1,13 +0,8 @@

import { Walker } from './plainer';
import { TypeAnnotation } from './transformer';
import { PathTree } from './pathtree';
import { MinimisedTree } from './walker';
export interface Annotations {
values?: PathTree.CollapsedRootTree<TypeAnnotation>;
referentialEqualities?: PathTree.CollapsedRootTree<PathTree.CollapsedRootTree<string>>;
values?: MinimisedTree<TypeAnnotation>;
referentialEqualities?: Record<string, string[]> | [string[]] | [string[], Record<string, string[]>];
}
export declare function isAnnotations(object: any): object is Annotations;
export declare const makeAnnotator: () => {
getAnnotations: () => Annotations;
annotator: Walker;
};
export declare function createReferentialEqualityAnnotation(identitites: Map<any, any[][]>): Annotations['referentialEqualities'];
export declare const applyAnnotations: (plain: any, annotations: Annotations) => any;

@@ -19,116 +19,42 @@ "use strict";

exports.__esModule = true;
exports.applyAnnotations = exports.makeAnnotator = exports.isAnnotations = void 0;
exports.applyAnnotations = exports.createReferentialEqualityAnnotation = void 0;
var accessDeep_1 = require("./accessDeep");
var transformer_1 = require("./transformer");
var pathstringifier_1 = require("./pathstringifier");
var lodash_1 = require("lodash");
var is_1 = require("./is");
var transformer_1 = require("./transformer");
var pathtree_1 = require("./pathtree");
function isAnnotations(object) {
try {
if (object.values) {
if (!pathtree_1.PathTree.isMinimizedTree(object.values, transformer_1.isTypeAnnotation)) {
return false;
}
var walker_1 = require("./walker");
function createReferentialEqualityAnnotation(identitites) {
var result = {};
var rootEqualityPaths = undefined;
identitites.forEach(function (paths) {
if (paths.length <= 1) {
return;
}
if (object.referentialEqualities) {
if (!pathtree_1.PathTree.isMinimizedTree(object.referentialEqualities, function (tree) {
return pathtree_1.PathTree.isMinimizedTree(tree, is_1.isString);
})) {
return false;
}
var _a = __read(paths
.map(function (path) { return path.map(String); })
.sort(function (a, b) { return a.length - b.length; })), shortestPath = _a[0], identicalPaths = _a.slice(1);
if (shortestPath.length === 0) {
rootEqualityPaths = identicalPaths.map(pathstringifier_1.stringifyPath);
}
return true;
}
catch (error) {
return false;
}
}
exports.isAnnotations = isAnnotations;
var ValueAnnotationFactory = /** @class */ (function () {
function ValueAnnotationFactory() {
this.tree = pathtree_1.PathTree.create(null);
}
ValueAnnotationFactory.prototype.add = function (path, annotation) {
pathtree_1.PathTree.append(this.tree, path, annotation);
};
ValueAnnotationFactory.prototype.create = function () {
pathtree_1.PathTree.compress(this.tree);
return pathtree_1.PathTree.collapseRoot(this.tree);
};
return ValueAnnotationFactory;
}());
var ReferentialEqualityAnnotationFactory = /** @class */ (function () {
function ReferentialEqualityAnnotationFactory() {
this.objectIdentities = new Map();
}
ReferentialEqualityAnnotationFactory.prototype.register = function (object, path) {
var _a;
var paths = (_a = this.objectIdentities.get(object)) !== null && _a !== void 0 ? _a : [];
paths.push(path);
this.objectIdentities.set(object, paths);
};
ReferentialEqualityAnnotationFactory.prototype.create = function () {
var tree = pathtree_1.PathTree.create(null);
this.objectIdentities.forEach(function (paths) {
if (paths.length <= 1) {
return;
}
var _a = __read(paths
.map(function (path) { return path.map(String); })
.sort(function (a, b) { return a.length - b.length; })), shortestPath = _a[0], identicalPaths = _a.slice(1);
var identities = pathtree_1.PathTree.create(null);
identicalPaths.forEach(function (identicalPath) {
pathtree_1.PathTree.appendPath(identities, identicalPath);
});
var minimizedIdentities = pathtree_1.PathTree.collapseRoot(identities);
if (!minimizedIdentities) {
throw new Error('Illegal State');
}
pathtree_1.PathTree.append(tree, shortestPath, minimizedIdentities);
});
return pathtree_1.PathTree.collapseRoot(tree);
};
return ReferentialEqualityAnnotationFactory;
}());
var AnnotationFactory = /** @class */ (function () {
function AnnotationFactory() {
this.valueAnnotations = new ValueAnnotationFactory();
this.objectIdentities = new ReferentialEqualityAnnotationFactory();
}
AnnotationFactory.prototype.create = function () {
var annotations = {};
var values = this.valueAnnotations.create();
if (values) {
annotations.values = values;
else {
result[pathstringifier_1.stringifyPath(shortestPath)] = identicalPaths.map(pathstringifier_1.stringifyPath);
}
var referentialEqualities = this.objectIdentities.create();
if (referentialEqualities) {
annotations.referentialEqualities = referentialEqualities;
});
if (rootEqualityPaths) {
if (is_1.isEmptyObject(result)) {
return [rootEqualityPaths];
}
return annotations;
};
return AnnotationFactory;
}());
var makeAnnotator = function () {
var annotationFactory = new AnnotationFactory();
var valueAnnotations = annotationFactory.valueAnnotations, objectIdentities = annotationFactory.objectIdentities;
var annotator = function (_a) {
var path = _a.path, node = _a.node;
if (!is_1.isPrimitive(node)) {
objectIdentities.register(node, path);
}
var transformed = transformer_1.transformValue(node);
if (transformed) {
valueAnnotations.add(path, transformed.type);
return transformed.value;
}
else {
return node;
return [rootEqualityPaths, result];
}
};
return { getAnnotations: function () { return annotationFactory.create(); }, annotator: annotator };
};
exports.makeAnnotator = makeAnnotator;
}
else {
return is_1.isEmptyObject(result) ? undefined : result;
}
}
exports.createReferentialEqualityAnnotation = createReferentialEqualityAnnotation;
var applyAnnotations = function (plain, annotations) {
if (annotations.values) {
pathtree_1.PathTree.traverseWhileIgnoringNullRoot(pathtree_1.PathTree.expandRoot(annotations.values), function (type, path) {
walker_1.traverse(annotations.values, function (type, path) {
plain = accessDeep_1.setDeep(plain, path, function (v) { return transformer_1.untransformValue(v, type); });

@@ -138,5 +64,12 @@ });

if (annotations.referentialEqualities) {
pathtree_1.PathTree.traverseWhileIgnoringNullRoot(pathtree_1.PathTree.expandRoot(annotations.referentialEqualities), function (identicalObjects, path) {
var object = accessDeep_1.getDeep(plain, path);
pathtree_1.PathTree.traversePaths(pathtree_1.PathTree.expandRoot(identicalObjects), function (identicalObjectPath) {
if (is_1.isArray(annotations.referentialEqualities)) {
lodash_1.forEach(annotations.referentialEqualities[0], function (identicalPath) {
plain = accessDeep_1.setDeep(plain, pathstringifier_1.parsePath(identicalPath), function () { return plain; });
});
}
lodash_1.forEach(is_1.isArray(annotations.referentialEqualities)
? annotations.referentialEqualities[1]
: annotations.referentialEqualities, function (identicalPaths, path) {
var object = accessDeep_1.getDeep(plain, pathstringifier_1.parsePath(path));
identicalPaths.map(pathstringifier_1.parsePath).forEach(function (identicalObjectPath) {
plain = accessDeep_1.setDeep(plain, identicalObjectPath, function () { return object; });

@@ -143,0 +76,0 @@ });

@@ -15,6 +15,2 @@ "use strict";

exports.parse = exports.deserialize = exports.serialize = void 0;
var annotator_1 = require("./annotator");
var is_1 = require("./is");
var plainer_1 = require("./plainer");
var types_1 = require("./types");
var class_registry_1 = require("./class-registry");

@@ -24,12 +20,16 @@ var symbol_registry_1 = require("./symbol-registry");

var error_props_1 = require("./error-props");
var plainer_1 = require("./plainer");
var serialize = function (object) {
var _a = annotator_1.makeAnnotator(), getAnnotations = _a.getAnnotations, annotator = _a.annotator;
var output = plainer_1.plainer(object, annotator);
var annotations = getAnnotations();
var identities = new Map();
var output = plainer_1.walker(object, identities);
var res = {
json: output
json: output.transformedValue
};
if (!is_1.isEmptyObject(annotations)) {
res.meta = annotations;
if (output.annotations) {
res.meta = __assign(__assign({}, res.meta), { values: output.annotations });
}
var equalityAnnotations = plainer_1.generateReferentialEqualityAnnotations(identities);
if (equalityAnnotations) {
res.meta = __assign(__assign({}, res.meta), { referentialEqualities: equalityAnnotations });
}
return res;

@@ -39,10 +39,10 @@ };

var deserialize = function (payload) {
if (!types_1.isSuperJSONResult(payload)) {
throw new Error('Not a valid SuperJSON payload.');
}
var json = payload.json, meta = payload.meta;
var result = json;
if (!!meta) {
return annotator_1.applyAnnotations(result, meta);
if (meta === null || meta === void 0 ? void 0 : meta.values) {
result = plainer_1.applyValueAnnotations(result, meta.values);
}
if (meta === null || meta === void 0 ? void 0 : meta.referentialEqualities) {
result = plainer_1.applyReferentialEqualityAnnotations(result, meta.referentialEqualities);
}
return result;

@@ -49,0 +49,0 @@ };

@@ -6,3 +6,2 @@ export declare type StringifiedPath = string;

export declare const parsePath: (string: StringifiedPath) => string[];
export declare const isStringifiedPath: (string: string) => string is string;
export {};
"use strict";
exports.__esModule = true;
exports.isStringifiedPath = exports.parsePath = exports.stringifyPath = exports.escapeKey = void 0;
exports.parsePath = exports.stringifyPath = exports.escapeKey = void 0;
var escapeKey = function (key) { return key.replace(/\./g, '\\.'); };

@@ -37,12 +37,2 @@ exports.escapeKey = escapeKey;

exports.parsePath = parsePath;
var isStringifiedPath = function (string) {
try {
exports.parsePath(string);
return true;
}
catch (anyError) {
return false;
}
};
exports.isStringifiedPath = isStringifiedPath;
//# sourceMappingURL=pathstringifier.js.map
export declare type Tree<T> = InnerNode<T> | Leaf<T>;
declare type Leaf<T> = [T];
declare type InnerNode<T> = [T, Record<string, Tree<T>>];
export declare function isTree<T>(v: any, valueChecker: (nodeValue: T) => boolean): v is Tree<T>;
export declare module PathTree {
function create<T>(value: T): Tree<T>;
function get<T>(tree: Tree<T>, path: string[]): [T, true] | [null, false];
/**
* @description Optimised for adding new leaves. Does not support adding inner nodes.
*/
function append<T>(tree: Tree<T>, path: string[], value: T): void;
function appendPath(tree: Tree<string | null>, path: string[]): void;
/**
* Depth-first post-order traversal.
*/
function traverse<T>(tree: Tree<T>, walker: (v: T, path: string[]) => void, origin?: string[]): void;
function traverseWhileIgnoringNullRoot<T>(tree: Tree<T | null>, walker: (v: T, path: string[]) => void): void;
function traversePaths(tree: Tree<string | null>, walker: (path: string[]) => void): void;
type CollapsedRootTree<T> = Tree<T> | Record<string, Tree<T>> | undefined;
function isMinimizedTree<T>(v: any, valueChecker: (v: T) => boolean): v is CollapsedRootTree<T>;
/**
* @description Minimizes trees that start with a `null`-root
*/
function collapseRoot<T>(tree: Tree<T | null>): CollapsedRootTree<T>;
function expandRoot<T>(tree: CollapsedRootTree<T>): Tree<T | null>;
/**
* @description Compress nested trees for smaller output
*/
function compress<T>(tree: Tree<T | null>): void;
}
export declare type CollapsedRootTree<T> = Tree<T> | Record<string, Tree<T>> | undefined;
export declare function traversePathTree<T>(tree: CollapsedRootTree<T>, walker: (v: T, path: string[]) => void, origin?: string[]): void;
export {};

@@ -23,176 +23,30 @@ "use strict";

exports.__esModule = true;
exports.PathTree = exports.isTree = void 0;
exports.traversePathTree = void 0;
var pathstringifier_1 = require("./pathstringifier");
var is_1 = require("./is");
var util_1 = require("./util");
function isTree(v, valueChecker) {
if (!is_1.isArray(v)) {
return false;
function traversePathTree(tree, walker, origin) {
if (origin === void 0) { origin = []; }
if (!tree) {
return;
}
if (v.length === 1) {
return valueChecker(v[0]);
if (!is_1.isArray(tree)) {
util_1.forEach(tree, function (subtree, key) {
return traversePathTree(subtree, walker, __spread(origin, pathstringifier_1.parsePath(key)));
});
return;
}
else if (v.length === 2) {
return valueChecker(v[0]) && util_1.every(v[1], function (v) { return isTree(v, valueChecker); });
if (tree.length === 1) {
var _a = __read(tree, 1), nodeValue = _a[0];
walker(nodeValue, origin);
}
return false;
}
exports.isTree = isTree;
var PathTree;
(function (PathTree) {
function create(value) {
return [value];
}
PathTree.create = create;
function get(tree, path) {
if (path.length === 0) {
return [tree[0], true];
}
if (tree.length === 1) {
return [null, false];
}
else {
var _a = __read(path), head = _a[0], tail = _a.slice(1);
var _b = __read(tree, 2), children = _b[1];
return get(children[head], tail);
}
}
PathTree.get = get;
/**
* @description Optimised for adding new leaves. Does not support adding inner nodes.
*/
function append(tree, path, value) {
var _a;
if (path.length === 0) {
tree[0] = value;
return;
}
if (tree.length === 1) {
tree[1] = (_a = {}, _a[pathstringifier_1.stringifyPath(path)] = [value], _a);
}
else {
tree[1][pathstringifier_1.stringifyPath(path)] = [value];
}
}
PathTree.append = append;
function appendPath(tree, path) {
var front = path.slice(0, path.length - 1);
var last = path[path.length - 1];
append(tree, front, last);
}
PathTree.appendPath = appendPath;
/**
* Depth-first post-order traversal.
*/
function traverse(tree, walker, origin) {
if (origin === void 0) { origin = []; }
if (tree.length === 1) {
var _a = __read(tree, 1), nodeValue = _a[0];
walker(nodeValue, origin);
}
else {
var _b = __read(tree, 2), nodeValue = _b[0], children = _b[1];
util_1.forEach(children, function (child, key) {
traverse(child, walker, __spread(origin, pathstringifier_1.parsePath(key)));
});
walker(nodeValue, origin);
}
}
PathTree.traverse = traverse;
function traverseWhileIgnoringNullRoot(tree, walker) {
traverse(tree, function (v, path) {
if (is_1.isNull(v)) {
if (path.length === 0) {
return;
}
throw new Error('Illegal State');
}
walker(v, path);
else {
var _b = __read(tree, 2), nodeValue = _b[0], children = _b[1];
util_1.forEach(children, function (child, key) {
traversePathTree(child, walker, __spread(origin, pathstringifier_1.parsePath(key)));
});
walker(nodeValue, origin);
}
PathTree.traverseWhileIgnoringNullRoot = traverseWhileIgnoringNullRoot;
function traversePaths(tree, walker) {
traverseWhileIgnoringNullRoot(tree, function (last, front) {
return walker(__spread(front, [last]));
});
}
PathTree.traversePaths = traversePaths;
function isMinimizedTree(v, valueChecker) {
if (is_1.isUndefined(v)) {
return true;
}
if (is_1.isPlainObject(v)) {
return util_1.every(v, function (v) { return isTree(v, valueChecker); });
}
return isTree(v, valueChecker);
}
PathTree.isMinimizedTree = isMinimizedTree;
/**
* @description Minimizes trees that start with a `null`-root
*/
function collapseRoot(tree) {
if (is_1.isNull(tree[0])) {
if (tree.length === 1) {
return undefined;
}
else {
return tree[1];
}
}
return tree;
}
PathTree.collapseRoot = collapseRoot;
function expandRoot(tree) {
if (is_1.isArray(tree)) {
return tree;
}
if (is_1.isUndefined(tree)) {
return [null];
}
return [null, tree];
}
PathTree.expandRoot = expandRoot;
/**
* @description Compress nested trees for smaller output
*/
function compress(tree) {
var _a;
if (tree.length === 1) {
// tree root is Leaf
return;
}
var origin = tree[1];
var keys = Object.keys(origin).sort(function (a, b) { return a.length - b.length; });
var transformed = {};
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var parentKey = undefined;
var splittedKey = key.split('.');
while (splittedKey.length > 0) {
splittedKey.pop();
var possibleParentKey = splittedKey.join('.');
if (transformed.hasOwnProperty(possibleParentKey)) {
parentKey = possibleParentKey;
break;
}
}
if (parentKey && transformed[parentKey]) {
transformed[parentKey][1] = Object.assign(transformed[parentKey][1] || {}, (_a = {},
_a[key.substring(parentKey.length + 1)] = origin[key],
_a));
continue;
}
else {
transformed[key] = origin[key];
}
}
// Recursive optimization
var transformedKeys = Object.keys(transformed);
for (var i = 0; i < transformedKeys.length; i++) {
compress(transformed[transformedKeys[i]]);
}
tree[1] = transformed;
}
PathTree.compress = compress;
})(PathTree = exports.PathTree || (exports.PathTree = {}));
}
exports.traversePathTree = traversePathTree;
//# sourceMappingURL=pathtree.js.map

@@ -1,8 +0,15 @@

interface WalkerValue {
isLeaf: boolean;
path: any[];
node: any;
import { TypeAnnotation } from './transformer';
declare type Tree<T> = InnerNode<T> | Leaf<T>;
declare type Leaf<T> = [T];
declare type InnerNode<T> = [T, Record<string, Tree<T>>];
export declare type MinimisedTree<T> = Tree<T> | Record<string, Tree<T>> | undefined;
export declare function applyValueAnnotations(plain: any, annotations: MinimisedTree<TypeAnnotation>): any;
export declare function applyReferentialEqualityAnnotations(plain: any, annotations: ReferentialEqualityAnnotations): any;
interface Result {
transformedValue: any;
annotations?: MinimisedTree<TypeAnnotation>;
}
export declare type Walker = (v: WalkerValue) => any;
export declare const plainer: (object: any, walker: Walker, path?: any[], alreadySeenObjects?: any[]) => any;
export declare type ReferentialEqualityAnnotations = Record<string, string[]> | [string[]] | [string[], Record<string, string[]>];
export declare function generateReferentialEqualityAnnotations(identitites: Map<any, any[][]>): ReferentialEqualityAnnotations | undefined;
export declare const walker: (object: any, identities: Map<any, any[][]>, path?: any[], objectsInThisPath?: any[]) => Result;
export {};

@@ -23,6 +23,57 @@ "use strict";

exports.__esModule = true;
exports.plainer = void 0;
exports.walker = exports.generateReferentialEqualityAnnotations = exports.applyReferentialEqualityAnnotations = exports.applyValueAnnotations = void 0;
var is_1 = require("./is");
var pathstringifier_1 = require("./pathstringifier");
var transformer_1 = require("./transformer");
var util_1 = require("./util");
var pathstringifier_2 = require("./pathstringifier");
var accessDeep_1 = require("./accessDeep");
function traverse(tree, walker, origin) {
if (origin === void 0) { origin = []; }
if (!tree) {
return;
}
if (!is_1.isArray(tree)) {
util_1.forEach(tree, function (subtree, key) {
return traverse(subtree, walker, __spread(origin, pathstringifier_2.parsePath(key)));
});
return;
}
var _a = __read(tree, 2), nodeValue = _a[0], children = _a[1];
if (children) {
util_1.forEach(children, function (child, key) {
traverse(child, walker, __spread(origin, pathstringifier_2.parsePath(key)));
});
}
walker(nodeValue, origin);
}
function applyValueAnnotations(plain, annotations) {
traverse(annotations, function (type, path) {
plain = accessDeep_1.setDeep(plain, path, function (v) { return transformer_1.untransformValue(v, type); });
});
return plain;
}
exports.applyValueAnnotations = applyValueAnnotations;
function applyReferentialEqualityAnnotations(plain, annotations) {
function apply(identicalPaths, path) {
var object = accessDeep_1.getDeep(plain, pathstringifier_2.parsePath(path));
identicalPaths.map(pathstringifier_2.parsePath).forEach(function (identicalObjectPath) {
plain = accessDeep_1.setDeep(plain, identicalObjectPath, function () { return object; });
});
}
if (is_1.isArray(annotations)) {
var _a = __read(annotations, 2), root = _a[0], other = _a[1];
root.forEach(function (identicalPath) {
plain = accessDeep_1.setDeep(plain, pathstringifier_2.parsePath(identicalPath), function () { return plain; });
});
if (other) {
util_1.forEach(other, apply);
}
}
else {
util_1.forEach(annotations, apply);
}
return plain;
}
exports.applyReferentialEqualityAnnotations = applyReferentialEqualityAnnotations;
var isDeep = function (object) {

@@ -35,27 +86,104 @@ return is_1.isPlainObject(object) ||

};
var plainer = function (object, walker, path, alreadySeenObjects) {
function addIdentity(object, path, identities) {
var existingSet = identities.get(object);
if (existingSet) {
existingSet.push(path);
}
else {
identities.set(object, [path]);
}
}
function generateReferentialEqualityAnnotations(identitites) {
var result = {};
var rootEqualityPaths = undefined;
identitites.forEach(function (paths) {
if (paths.length <= 1) {
return;
}
var _a = __read(paths
.map(function (path) { return path.map(String); })
.sort(function (a, b) { return a.length - b.length; })), shortestPath = _a[0], identicalPaths = _a.slice(1);
if (shortestPath.length === 0) {
rootEqualityPaths = identicalPaths.map(pathstringifier_1.stringifyPath);
}
else {
result[pathstringifier_1.stringifyPath(shortestPath)] = identicalPaths.map(pathstringifier_1.stringifyPath);
}
});
if (rootEqualityPaths) {
if (is_1.isEmptyObject(result)) {
return [rootEqualityPaths];
}
else {
return [rootEqualityPaths, result];
}
}
else {
return is_1.isEmptyObject(result) ? undefined : result;
}
}
exports.generateReferentialEqualityAnnotations = generateReferentialEqualityAnnotations;
var walker = function (object, identities, path, objectsInThisPath) {
var _a;
if (path === void 0) { path = []; }
if (alreadySeenObjects === void 0) { alreadySeenObjects = []; }
if (objectsInThisPath === void 0) { objectsInThisPath = []; }
if (!is_1.isPrimitive(object)) {
addIdentity(object, path, identities);
}
if (!isDeep(object)) {
return walker({ isLeaf: true, node: object, path: path });
var transformed_1 = transformer_1.transformValue(object);
if (transformed_1) {
return {
transformedValue: transformed_1.value,
annotations: [transformed_1.type]
};
}
else {
return {
transformedValue: object
};
}
}
object = walker({ isLeaf: false, path: path, node: object });
if (util_1.includes(alreadySeenObjects, object)) {
return null;
if (util_1.includes(objectsInThisPath, object)) {
return {
transformedValue: null
};
}
var transformationResult = transformer_1.transformValue(object);
var transformed = (_a = transformationResult === null || transformationResult === void 0 ? void 0 : transformationResult.value) !== null && _a !== void 0 ? _a : object;
if (!is_1.isPrimitive(object)) {
alreadySeenObjects = __spread(alreadySeenObjects, [object]);
objectsInThisPath = __spread(objectsInThisPath, [object]);
}
if (is_1.isArray(object)) {
return object.map(function (value, index) {
return exports.plainer(value, walker, __spread(path, [index]), alreadySeenObjects);
});
var transformedValue = is_1.isArray(transformed) ? [] : {};
var innerAnnotations = {};
util_1.forEach(transformed, function (value, index) {
var recursiveResult = exports.walker(value, identities, __spread(path, [index]), objectsInThisPath);
transformedValue[index] = recursiveResult.transformedValue;
if (is_1.isArray(recursiveResult.annotations)) {
innerAnnotations[index] = recursiveResult.annotations;
}
else if (is_1.isPlainObject(recursiveResult.annotations)) {
util_1.forEach(recursiveResult.annotations, function (tree, key) {
innerAnnotations[pathstringifier_1.escapeKey(index) + '.' + key] = tree;
});
}
});
if (is_1.isEmptyObject(innerAnnotations)) {
return {
transformedValue: transformedValue,
annotations: !!transformationResult
? [transformationResult.type]
: undefined
};
}
if (is_1.isPlainObject(object)) {
return util_1.mapValues(object, function (value, key) {
return exports.plainer(value, walker, __spread(path, [key]), alreadySeenObjects);
});
else {
return {
transformedValue: transformedValue,
annotations: !!transformationResult
? [transformationResult.type, innerAnnotations]
: innerAnnotations
};
}
};
exports.plainer = plainer;
exports.walker = walker;
//# sourceMappingURL=plainer.js.map

@@ -9,4 +9,2 @@ export declare type PrimitiveTypeAnnotation = 'number' | 'undefined' | 'bigint';

export declare type TypeAnnotation = SimpleTypeAnnotation | CompositeTypeAnnotation;
export declare const isPrimitiveTypeAnnotation: (value: any) => value is PrimitiveTypeAnnotation;
export declare const isTypeAnnotation: (value: any) => value is TypeAnnotation;
export declare function isInstanceOfRegisteredClass(potentialClass: any): potentialClass is any;

@@ -13,0 +11,0 @@ export declare const transformValue: (value: any) => {

@@ -34,3 +34,3 @@ "use strict";

exports.__esModule = true;
exports.untransformValue = exports.transformValue = exports.isInstanceOfRegisteredClass = exports.isTypeAnnotation = exports.isPrimitiveTypeAnnotation = void 0;
exports.untransformValue = exports.transformValue = exports.isInstanceOfRegisteredClass = void 0;
var is_1 = require("./is");

@@ -42,19 +42,2 @@ var class_registry_1 = require("./class-registry");

var util_1 = require("./util");
var ALL_PRIMITIVE_TYPE_ANNOTATIONS = [
'undefined',
'number',
'bigint',
];
var isPrimitiveTypeAnnotation = function (value) {
return util_1.includes(ALL_PRIMITIVE_TYPE_ANNOTATIONS, value);
};
exports.isPrimitiveTypeAnnotation = isPrimitiveTypeAnnotation;
var ALL_TYPE_ANNOTATIONS = ALL_PRIMITIVE_TYPE_ANNOTATIONS.concat(['map', 'regexp', 'set', 'Date', 'Error']);
var isTypeAnnotation = function (value) {
if (Array.isArray(value)) {
return typeof value[1] === 'string';
}
return util_1.includes(ALL_TYPE_ANNOTATIONS, value);
};
exports.isTypeAnnotation = isTypeAnnotation;
function simpleTransformation(isApplicable, annotation, transform, untransform) {

@@ -61,0 +44,0 @@ return {

@@ -1,2 +0,3 @@

import { Annotations } from './annotator';
import { TypeAnnotation } from './transformer';
import { MinimisedTree, ReferentialEqualityAnnotations } from './plainer';
export declare type Class = {

@@ -22,5 +23,7 @@ new (...args: any[]): any;

json: JSONValue;
meta?: Annotations;
meta?: {
values?: MinimisedTree<TypeAnnotation>;
referentialEqualities?: ReferentialEqualityAnnotations;
};
}
export declare function isSuperJSONResult(object: any): object is SuperJSONResult;
export {};
"use strict";
exports.__esModule = true;
exports.isSuperJSONResult = void 0;
var annotator_1 = require("./annotator");
var is_1 = require("./is");
function isSuperJSONResult(object) {
if (!('json' in object)) {
return false;
}
if (is_1.isUndefined(object.meta)) {
return true;
}
return annotator_1.isAnnotations(object.meta);
}
exports.isSuperJSONResult = isSuperJSONResult;
//# sourceMappingURL=types.js.map
export declare function find<T>(record: Record<string, T>, predicate: (v: T) => boolean): T | undefined;
export declare function forEach<T>(record: Record<string, T>, run: (v: T, key: string) => void): void;
export declare function every<T>(record: Record<string, T>, predicate: (v: T) => boolean): boolean;
export declare function includes<T>(arr: T[], value: T): boolean;
export declare function mapValues<A, B>(record: Record<string, A>, mapper: (v: A, key: string) => B): Record<string, B>;
export declare function findArr<T>(record: T[], predicate: (v: T) => boolean): T | undefined;

@@ -19,3 +19,3 @@ "use strict";

exports.__esModule = true;
exports.findArr = exports.mapValues = exports.includes = exports.every = exports.forEach = exports.find = void 0;
exports.findArr = exports.includes = exports.forEach = exports.find = void 0;
function valuesOfObj(record) {

@@ -58,13 +58,2 @@ if ('values' in Object) {

exports.forEach = forEach;
function every(record, predicate) {
var values = valuesOfObj(record);
for (var i = 0; i < values.length; i++) {
var value = values[i];
if (!predicate(value)) {
return false;
}
}
return true;
}
exports.every = every;
function includes(arr, value) {

@@ -74,10 +63,2 @@ return arr.indexOf(value) !== -1;

exports.includes = includes;
function mapValues(record, mapper) {
var result = {};
forEach(record, function (value, key) {
result[key] = mapper(value, key);
});
return result;
}
exports.mapValues = mapValues;
function findArr(record, predicate) {

@@ -84,0 +65,0 @@ for (var i = 0; i < record.length; i++) {

{
"version": "1.6.2",
"version": "1.7.1",
"license": "MIT",

@@ -61,13 +61,11 @@ "main": "dist/index.js",

"@types/lodash": "^4.14.168",
"@types/mongodb": "^3.6.3",
"@types/mongodb": "^3.6.7",
"benchmark": "^2.1.4",
"eslint-plugin-es5": "^1.5.0",
"husky": "^4.3.8",
"mongodb": "^3.6.3",
"mongodb": "^3.6.4",
"tsdx": "^0.14.1",
"typescript": "^4.1.3"
},
"dependencies": {
"debug": "^4.3.1"
},
"dependencies": {},
"resolutions": {

@@ -74,0 +72,0 @@ "**/@typescript-eslint/eslint-plugin": "^4.11.1",

@@ -6,9 +6,11 @@ import { setDeep } from './accessDeep';

const obj = {
a: new Map([['NaN', 10]]),
a: new Map([[new Set(['NaN']), [[1, 'undefined']]]]),
};
setDeep(obj, ['a', 0, 0], Number);
setDeep(obj, ['a', 0, 0, 0], Number);
setDeep(obj, ['a', 0, 1], entries => new Map(entries));
setDeep(obj, ['a', 0, 1, 0, 1], () => undefined);
expect(obj).toEqual({
a: new Map([[NaN, 10]]),
a: new Map([[new Set([NaN]), new Map([[1, undefined]])]]),
});

@@ -19,11 +21,11 @@ });

const obj = {
a: new Set(['NaN']),
a: new Set([10, new Set(['NaN'])]),
};
setDeep(obj, ['a', 0], Number);
setDeep(obj, ['a', 1, 0], Number);
expect(obj).toEqual({
a: new Set([NaN]),
a: new Set([10, new Set([NaN])]),
});
});
});
import { isMap, isArray, isPlainObject, isSet } from './is';
export const getNthKey = (value: Map<any, any> | Set<any>, n: number): any => {
const getNthKey = (value: Map<any, any> | Set<any>, n: number): any => {
const keys = value.keys();

@@ -50,3 +50,3 @@ while (n > 0) {

const row = +key;
const type = +path[i + 1] === 0 ? 'key' : 'value';
const type = +path[++i] === 0 ? 'key' : 'value';

@@ -62,4 +62,2 @@ const keyOfRow = getNthKey(parent, row);

}
i++;
}

@@ -66,0 +64,0 @@ }

@@ -5,4 +5,3 @@ /* eslint-disable es5/no-for-of */

import SuperJSON from './';
import { JSONValue, SuperJSONValue } from './types';
import { Annotations } from './annotator';
import { JSONValue, SuperJSONResult, SuperJSONValue } from './types';
import { isArray, isMap, isPlainObject, isPrimitive, isSet } from './is';

@@ -20,6 +19,7 @@

output: JSONValue | ((v: JSONValue) => void);
outputAnnotations?: Annotations;
outputAnnotations?: SuperJSONResult['meta'];
customExpectations?: (value: any) => void;
skipOnNode10?: boolean;
dontExpectEquality?: boolean;
only?: boolean;
}

@@ -128,3 +128,3 @@ > = {

referentialEqualities: {
selected: [{ options: ['0'] }],
selected: ['options.0'],
},

@@ -314,3 +314,3 @@ },

outputAnnotations: {
referentialEqualities: [{ 'children.0.parents': ['0'] }],
referentialEqualities: [['children.0.parents.0']],
},

@@ -357,3 +357,3 @@ },

referentialEqualities: {
topScorer: [{ 'highscores.0': ['0'] }] as any,
topScorer: ['highscores.0.0'],
},

@@ -381,3 +381,3 @@ },

referentialEqualities: {
a: [['b']],
a: ['b'],
},

@@ -427,3 +427,3 @@ },

referentialEqualities: {
userOfTheMonth: [{ users: ['0'] }],
userOfTheMonth: ['users.0'],
},

@@ -637,2 +637,3 @@ },

dontExpectEquality,
only,
},

@@ -646,2 +647,6 @@ ] of Object.entries(cases)) {

if (only) {
testFunc = test.only;
}
testFunc(testName, () => {

@@ -745,31 +750,3 @@ const inputValue = typeof input === 'function' ? input() : input;

describe('when given a non-SuperJSON object', () => {
it('throws', () => {
expect(() => {
SuperJSON.parse(
JSON.stringify({
value: {
a: 1,
},
meta: {
root: 'invalid_key',
},
})
);
}).toThrow();
expect(() => {
SuperJSON.parse(
JSON.stringify({
value: {
a: 1,
},
meta: {
values: {
a: 'invalid_key',
},
},
})
);
}).toThrow();
});
it.todo('has undefined behaviour');
});

@@ -776,0 +753,0 @@

@@ -1,11 +0,2 @@

import { applyAnnotations, makeAnnotator } from './annotator';
import { isEmptyObject } from './is';
import { plainer } from './plainer';
import {
SuperJSONResult,
SuperJSONValue,
isSuperJSONResult,
Class,
JSONValue,
} from './types';
import { SuperJSONResult, SuperJSONValue, Class, JSONValue } from './types';
import { ClassRegistry, RegisterOptions } from './class-registry';

@@ -18,14 +9,33 @@ import { SymbolRegistry } from './symbol-registry';

import { allowErrorProps } from './error-props';
import {
walker,
applyReferentialEqualityAnnotations,
applyValueAnnotations,
generateReferentialEqualityAnnotations,
} from './plainer';
export const serialize = (object: SuperJSONValue): SuperJSONResult => {
const { getAnnotations, annotator } = makeAnnotator();
const output = plainer(object, annotator);
const annotations = getAnnotations();
const identities = new Map<any, any[][]>();
const output = walker(object, identities);
const res: SuperJSONResult = {
json: output,
json: output.transformedValue,
};
if (!isEmptyObject(annotations)) {
res.meta = annotations;
if (output.annotations) {
res.meta = {
...res.meta,
values: output.annotations,
};
}
const equalityAnnotations = generateReferentialEqualityAnnotations(
identities
);
if (equalityAnnotations) {
res.meta = {
...res.meta,
referentialEqualities: equalityAnnotations,
};
}
return res;

@@ -35,14 +45,17 @@ };

export const deserialize = <T = unknown>(payload: SuperJSONResult): T => {
if (!isSuperJSONResult(payload)) {
throw new Error('Not a valid SuperJSON payload.');
}
const { json, meta } = payload;
const result: T = json as any;
let result: T = json as any;
if (!!meta) {
return applyAnnotations(result, meta);
if (meta?.values) {
result = applyValueAnnotations(result, meta.values);
}
if (meta?.referentialEqualities) {
result = applyReferentialEqualityAnnotations(
result,
meta.referentialEqualities
);
}
return result;

@@ -49,0 +62,0 @@ };

@@ -41,12 +41,1 @@ export type StringifiedPath = string;

};
export const isStringifiedPath = (
string: string
): string is StringifiedPath => {
try {
parsePath(string);
return true;
} catch (anyError) {
return false;
}
};

@@ -1,13 +0,91 @@

import { isArray, isMap, isPlainObject, isPrimitive, isSet } from './is';
import { isInstanceOfRegisteredClass } from './transformer';
import { includes, mapValues } from './util';
import {
isArray,
isEmptyObject,
isMap,
isPlainObject,
isPrimitive,
isSet,
} from './is';
import { escapeKey, stringifyPath } from './pathstringifier';
import {
isInstanceOfRegisteredClass,
transformValue,
TypeAnnotation,
untransformValue,
} from './transformer';
import { includes, forEach } from './util';
import { parsePath } from './pathstringifier';
import { getDeep, setDeep } from './accessDeep';
interface WalkerValue {
isLeaf: boolean;
path: any[];
node: any;
type Tree<T> = InnerNode<T> | Leaf<T>;
type Leaf<T> = [T];
type InnerNode<T> = [T, Record<string, Tree<T>>];
export type MinimisedTree<T> = Tree<T> | Record<string, Tree<T>> | undefined;
function traverse<T>(
tree: MinimisedTree<T>,
walker: (v: T, path: string[]) => void,
origin: string[] = []
): void {
if (!tree) {
return;
}
if (!isArray(tree)) {
forEach(tree, (subtree, key) =>
traverse(subtree, walker, [...origin, ...parsePath(key)])
);
return;
}
const [nodeValue, children] = tree;
if (children) {
forEach(children, (child, key) => {
traverse(child, walker, [...origin, ...parsePath(key)]);
});
}
walker(nodeValue, origin);
}
export type Walker = (v: WalkerValue) => any;
export function applyValueAnnotations(
plain: any,
annotations: MinimisedTree<TypeAnnotation>
) {
traverse(annotations, (type, path) => {
plain = setDeep(plain, path, v => untransformValue(v, type));
});
return plain;
}
export function applyReferentialEqualityAnnotations(
plain: any,
annotations: ReferentialEqualityAnnotations
) {
function apply(identicalPaths: string[], path: string) {
const object = getDeep(plain, parsePath(path));
identicalPaths.map(parsePath).forEach(identicalObjectPath => {
plain = setDeep(plain, identicalObjectPath, () => object);
});
}
if (isArray(annotations)) {
const [root, other] = annotations;
root.forEach(identicalPath => {
plain = setDeep(plain, parsePath(identicalPath), () => plain);
});
if (other) {
forEach(other, apply);
}
} else {
forEach(annotations, apply);
}
return plain;
}
const isDeep = (object: any): boolean =>

@@ -20,33 +98,129 @@ isPlainObject(object) ||

export const plainer = (
function addIdentity(object: any, path: any[], identities: Map<any, any[][]>) {
const existingSet = identities.get(object);
if (existingSet) {
existingSet.push(path);
} else {
identities.set(object, [path]);
}
}
interface Result {
transformedValue: any;
annotations?: MinimisedTree<TypeAnnotation>;
}
export type ReferentialEqualityAnnotations =
| Record<string, string[]>
| [string[]]
| [string[], Record<string, string[]>];
export function generateReferentialEqualityAnnotations(
identitites: Map<any, any[][]>
): ReferentialEqualityAnnotations | undefined {
const result: Record<string, string[]> = {};
let rootEqualityPaths: string[] | undefined = undefined;
identitites.forEach(paths => {
if (paths.length <= 1) {
return;
}
const [shortestPath, ...identicalPaths] = paths
.map(path => path.map(String))
.sort((a, b) => a.length - b.length);
if (shortestPath.length === 0) {
rootEqualityPaths = identicalPaths.map(stringifyPath);
} else {
result[stringifyPath(shortestPath)] = identicalPaths.map(stringifyPath);
}
});
if (rootEqualityPaths) {
if (isEmptyObject(result)) {
return [rootEqualityPaths];
} else {
return [rootEqualityPaths, result];
}
} else {
return isEmptyObject(result) ? undefined : result;
}
}
export const walker = (
object: any,
walker: Walker,
identities: Map<any, any[][]>,
path: any[] = [],
alreadySeenObjects: any[] = []
): any => {
objectsInThisPath: any[] = []
): Result => {
if (!isPrimitive(object)) {
addIdentity(object, path, identities);
}
if (!isDeep(object)) {
return walker({ isLeaf: true, node: object, path });
const transformed = transformValue(object);
if (transformed) {
return {
transformedValue: transformed.value,
annotations: [transformed.type],
};
} else {
return {
transformedValue: object,
};
}
}
object = walker({ isLeaf: false, path, node: object });
if (includes(alreadySeenObjects, object)) {
return null;
if (includes(objectsInThisPath, object)) {
return {
transformedValue: null,
};
}
const transformationResult = transformValue(object);
const transformed = transformationResult?.value ?? object;
if (!isPrimitive(object)) {
alreadySeenObjects = [...alreadySeenObjects, object];
objectsInThisPath = [...objectsInThisPath, object];
}
if (isArray(object)) {
return object.map((value, index) =>
plainer(value, walker, [...path, index], alreadySeenObjects)
const transformedValue: any = isArray(transformed) ? [] : {};
const innerAnnotations: Record<string, Tree<TypeAnnotation>> = {};
forEach(transformed, (value, index) => {
const recursiveResult = walker(
value,
identities,
[...path, index],
objectsInThisPath
);
}
if (isPlainObject(object)) {
return mapValues(object, (value, key) =>
plainer(value, walker, [...path, key], alreadySeenObjects)
);
transformedValue[index] = recursiveResult.transformedValue;
if (isArray(recursiveResult.annotations)) {
innerAnnotations[index] = recursiveResult.annotations;
} else if (isPlainObject(recursiveResult.annotations)) {
forEach(recursiveResult.annotations, (tree, key) => {
innerAnnotations[escapeKey(index) + '.' + key] = tree;
});
}
});
if (isEmptyObject(innerAnnotations)) {
return {
transformedValue,
annotations: !!transformationResult
? [transformationResult.type]
: undefined,
};
} else {
return {
transformedValue,
annotations: !!transformationResult
? [transformationResult.type, innerAnnotations]
: innerAnnotations,
};
}
};

@@ -18,3 +18,3 @@ import {

import { allowedErrorProps } from './error-props';
import { includes, findArr } from './util';
import { findArr } from './util';

@@ -38,26 +38,2 @@ export type PrimitiveTypeAnnotation = 'number' | 'undefined' | 'bigint';

const ALL_PRIMITIVE_TYPE_ANNOTATIONS: TypeAnnotation[] = [
'undefined',
'number',
'bigint',
];
export const isPrimitiveTypeAnnotation = (
value: any
): value is PrimitiveTypeAnnotation => {
return includes(ALL_PRIMITIVE_TYPE_ANNOTATIONS, value);
};
const ALL_TYPE_ANNOTATIONS: TypeAnnotation[] = ALL_PRIMITIVE_TYPE_ANNOTATIONS.concat(
['map', 'regexp', 'set', 'Date', 'Error']
);
export const isTypeAnnotation = (value: any): value is TypeAnnotation => {
if (Array.isArray(value)) {
return typeof value[1] === 'string';
}
return includes(ALL_TYPE_ANNOTATIONS, value);
};
function simpleTransformation<I, O, A extends SimpleTypeAnnotation>(

@@ -64,0 +40,0 @@ isApplicable: (v: any) => v is I,

@@ -1,3 +0,3 @@

import { Annotations, isAnnotations } from './annotator';
import { isUndefined } from './is';
import { TypeAnnotation } from './transformer';
import { MinimisedTree, ReferentialEqualityAnnotations } from './plainer';

@@ -42,15 +42,6 @@ export type Class = { new (...args: any[]): any };

json: JSONValue;
meta?: Annotations;
meta?: {
values?: MinimisedTree<TypeAnnotation>;
referentialEqualities?: ReferentialEqualityAnnotations;
};
}
export function isSuperJSONResult(object: any): object is SuperJSONResult {
if (!('json' in object)) {
return false;
}
if (isUndefined(object.meta)) {
return true;
}
return isAnnotations(object.meta);
}

@@ -48,18 +48,2 @@ function valuesOfObj<T>(record: Record<string, T>): T[] {

export function every<T>(
record: Record<string, T>,
predicate: (v: T) => boolean
) {
const values = valuesOfObj(record);
for (let i = 0; i < values.length; i++) {
const value = values[i];
if (!predicate(value)) {
return false;
}
}
return true;
}
export function includes<T>(arr: T[], value: T) {

@@ -69,15 +53,2 @@ return arr.indexOf(value) !== -1;

export function mapValues<A, B>(
record: Record<string, A>,
mapper: (v: A, key: string) => B
): Record<string, B> {
const result: Record<string, B> = {};
forEach(record, (value, key) => {
result[key] = mapper(value, key);
});
return result;
}
export function findArr<T>(

@@ -84,0 +55,0 @@ record: T[],

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc