Fix StartOS 0.4 TypeScript packaging to match SDK API
This commit is contained in:
+5
@@ -0,0 +1,5 @@
|
||||
export { DeepSet } from './src/set';
|
||||
export { DeepMap } from './src/map';
|
||||
export { BiDirectionalDeepMap } from './src/map.bi-directional';
|
||||
export { Options } from './src/options';
|
||||
export { areEqual } from './src/areEqual';
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.areEqual = exports.BiDirectionalDeepMap = exports.DeepMap = exports.DeepSet = void 0;
|
||||
var set_1 = require("./src/set");
|
||||
Object.defineProperty(exports, "DeepSet", { enumerable: true, get: function () { return set_1.DeepSet; } });
|
||||
var map_1 = require("./src/map");
|
||||
Object.defineProperty(exports, "DeepMap", { enumerable: true, get: function () { return map_1.DeepMap; } });
|
||||
var map_bi_directional_1 = require("./src/map.bi-directional");
|
||||
Object.defineProperty(exports, "BiDirectionalDeepMap", { enumerable: true, get: function () { return map_bi_directional_1.BiDirectionalDeepMap; } });
|
||||
var areEqual_1 = require("./src/areEqual");
|
||||
Object.defineProperty(exports, "areEqual", { enumerable: true, get: function () { return areEqual_1.areEqual; } });
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { Options } from './options';
|
||||
/**
|
||||
* Static utility for doing a one-time equality check across the provided values.
|
||||
* @param values list whose elements will be compared to each other
|
||||
* @param options configuration options
|
||||
* @returns true if every element in `values` is equal to every other element
|
||||
* @throws {Error} if `values` list is empty
|
||||
*/
|
||||
export declare function areEqual<V, TxV = V>(values: V[], options?: Options<V, null, TxV, null>): boolean;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.areEqual = areEqual;
|
||||
const errors_1 = require("./errors");
|
||||
const set_1 = require("./set");
|
||||
/**
|
||||
* Static utility for doing a one-time equality check across the provided values.
|
||||
* @param values list whose elements will be compared to each other
|
||||
* @param options configuration options
|
||||
* @returns true if every element in `values` is equal to every other element
|
||||
* @throws {Error} if `values` list is empty
|
||||
*/
|
||||
function areEqual(values, options) {
|
||||
if (values.length === 0) {
|
||||
throw new errors_1.DeepEqualityDataStructuresError('Empty values list passed to areEqual function');
|
||||
}
|
||||
const set = new set_1.DeepSet(values, options);
|
||||
return set.size === 1;
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Interface for comparable maps/sets
|
||||
*/
|
||||
export interface Comparable<T> {
|
||||
equals(other: T): boolean;
|
||||
contains(other: T): boolean;
|
||||
union(other: T): T;
|
||||
intersection(other: T): T;
|
||||
difference(other: T): T;
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
export declare class DeepEqualityDataStructuresError extends Error {
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DeepEqualityDataStructuresError = void 0;
|
||||
class DeepEqualityDataStructuresError extends Error {
|
||||
}
|
||||
exports.DeepEqualityDataStructuresError = DeepEqualityDataStructuresError;
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { DeepMap } from './map';
|
||||
import { Options } from './options';
|
||||
/**
|
||||
* A DeepMap implementation that supports O(1) lookups by both keys and values
|
||||
* NOTE: All key-value pairs must be 1-to-1
|
||||
*/
|
||||
export declare class BiDirectionalDeepMap<K, V, TxK = K, TxV = V> extends DeepMap<K, V, TxK, TxV> {
|
||||
private readonly valueMap;
|
||||
/**
|
||||
* @param entries optional list of key-value pairs to initialize the map
|
||||
* @param options configuration options
|
||||
*/
|
||||
constructor(entries?: readonly (readonly [K, V])[] | null, options?: Options<K, V, TxK, TxV>);
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
set(key: K, val: V): this;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
delete(key: K): boolean;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
clear(): void;
|
||||
/**
|
||||
* @returns true if the given value is present in the key-value map.
|
||||
*/
|
||||
hasValue(val: V): boolean;
|
||||
/**
|
||||
* @returns the key associated with the specified value
|
||||
*/
|
||||
getKeyByValue(val: V): K | undefined;
|
||||
/**
|
||||
* @returns true if a value in the map existed and has been removed, else false
|
||||
*/
|
||||
deleteByValue(val: V): boolean;
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BiDirectionalDeepMap = void 0;
|
||||
const errors_1 = require("./errors");
|
||||
const map_1 = require("./map");
|
||||
const utils_1 = require("./utils");
|
||||
/**
|
||||
* A DeepMap implementation that supports O(1) lookups by both keys and values
|
||||
* NOTE: All key-value pairs must be 1-to-1
|
||||
*/
|
||||
class BiDirectionalDeepMap extends map_1.DeepMap {
|
||||
/**
|
||||
* @param entries optional list of key-value pairs to initialize the map
|
||||
* @param options configuration options
|
||||
*/
|
||||
constructor(entries, options) {
|
||||
super(entries, options);
|
||||
const valueEntries = entries ? entries.map(([key, val]) => [this.normalizeValue(val), key]) : null;
|
||||
this.valueMap = new Map(valueEntries);
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
set(key, val) {
|
||||
// Enforce 1-to-1: Don't allow writing a value which is already present in the map for a different key
|
||||
const preexistingValueKey = this.getKeyByValue(val);
|
||||
if (preexistingValueKey !== undefined && this.normalizeKey(preexistingValueKey) !== this.normalizeKey(key)) {
|
||||
throw new errors_1.DeepEqualityDataStructuresError(`Could not set key='${(0, utils_1.stringify)(key)}': The value='${(0, utils_1.stringify)(val)}' is already associated with key='${(0, utils_1.stringify)(preexistingValueKey)}'`);
|
||||
}
|
||||
this.valueMap.set(this.normalizeValue(val), key);
|
||||
return super.set(key, val);
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
delete(key) {
|
||||
const val = this.get(key);
|
||||
if (val) {
|
||||
this.valueMap.delete(this.normalizeValue(val));
|
||||
}
|
||||
return super.delete(key);
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
clear() {
|
||||
this.valueMap.clear();
|
||||
super.clear();
|
||||
}
|
||||
// BI-DIRECTIONAL API
|
||||
/**
|
||||
* @returns true if the given value is present in the key-value map.
|
||||
*/
|
||||
hasValue(val) {
|
||||
return this.valueMap.has(this.normalizeValue(val));
|
||||
}
|
||||
/**
|
||||
* @returns the key associated with the specified value
|
||||
*/
|
||||
getKeyByValue(val) {
|
||||
return this.valueMap.get(this.normalizeValue(val));
|
||||
}
|
||||
/**
|
||||
* @returns true if a value in the map existed and has been removed, else false
|
||||
*/
|
||||
deleteByValue(val) {
|
||||
const key = this.getKeyByValue(val);
|
||||
return key ? this.delete(key) : false;
|
||||
}
|
||||
}
|
||||
exports.BiDirectionalDeepMap = BiDirectionalDeepMap;
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
import { Comparable } from './comparable';
|
||||
import { Normalized } from './normalizer';
|
||||
import { Options } from './options';
|
||||
/**
|
||||
* A Map implementation that supports deep equality for object keys.
|
||||
*/
|
||||
export declare class DeepMap<K, V, TxK = K, TxV = V> extends Map<K, V> implements Comparable<DeepMap<K, V, TxK, TxV>> {
|
||||
private options;
|
||||
private readonly normalizer;
|
||||
private readonly map;
|
||||
/**
|
||||
* @param entries optional list of key-value pairs to initialize the map
|
||||
* @param options configuration options
|
||||
*/
|
||||
constructor(entries?: readonly (readonly [K, V])[] | null, options?: Options<K, V, TxK, TxV>);
|
||||
/**
|
||||
* Getter for number of kev-value pairs in the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
get size(): number;
|
||||
/**
|
||||
* Returns true if the given key is present in the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
has(key: K): boolean;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
set(key: K, val: V): this;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get(key: K): V | undefined;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
delete(key: K): boolean;
|
||||
/**
|
||||
* Clear all key-value pairs from the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
clear(): void;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
forEach(callbackfn: (val: V, key: K, map: Map<K, V>) => void): void;
|
||||
/**
|
||||
* @yields the next key-value pair in the map
|
||||
* @inheritdoc
|
||||
*/
|
||||
[Symbol.iterator](): IterableIterator<[K, V]>;
|
||||
/**
|
||||
* @yields the next key-value pair in the map
|
||||
* @inheritdoc
|
||||
*/
|
||||
entries(): IterableIterator<[K, V]>;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
keys(): IterableIterator<K>;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
values(): IterableIterator<V>;
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns true if the entries of `other` are the same as this map
|
||||
*/
|
||||
equals(other: this): boolean;
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns true if the entries of `other` are all contained in this map
|
||||
*/
|
||||
contains(other: this): boolean;
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns a new map whose keys are the union of keys between `this` and `other` maps.
|
||||
*
|
||||
* NOTE: If both maps prescribe the same key, the key-value pair from `this` will be retained.
|
||||
*/
|
||||
union(other: this): DeepMap<K, V, TxK, TxV>;
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns a new map containing all key-value pairs in `this` that are also present in `other`.
|
||||
*/
|
||||
intersection(other: this): DeepMap<K, V, TxK, TxV>;
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns a new map containing all key-value pairs in `this` that are not present in `other`.
|
||||
*/
|
||||
difference(other: this): DeepMap<K, V, TxK, TxV>;
|
||||
protected normalizeKey(input: K): Normalized<TxK>;
|
||||
protected normalizeValue(input: V): Normalized<TxV>;
|
||||
private validateUsingSameOptionsAs;
|
||||
/**
|
||||
* @returns true if the key is present in the provided map w/ the specified value
|
||||
*/
|
||||
private keyValuePairIsPresentIn;
|
||||
}
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DeepMap = void 0;
|
||||
const errors_1 = require("./errors");
|
||||
const normalizer_1 = require("./normalizer");
|
||||
/**
|
||||
* A Map implementation that supports deep equality for object keys.
|
||||
*/
|
||||
class DeepMap extends Map {
|
||||
// NOTE: This is actually a thin wrapper. We're not using super other than to drive the (typed) API contract.
|
||||
/**
|
||||
* @param entries optional list of key-value pairs to initialize the map
|
||||
* @param options configuration options
|
||||
*/
|
||||
constructor(entries, options = {}) {
|
||||
super();
|
||||
this.options = options;
|
||||
this.normalizer = new normalizer_1.Normalizer(options);
|
||||
const transformedEntries = entries
|
||||
? entries.map(([key, val]) => [this.normalizeKey(key), { key, val }])
|
||||
: null;
|
||||
this.map = new Map(transformedEntries);
|
||||
}
|
||||
/**
|
||||
* Getter for number of kev-value pairs in the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
get size() {
|
||||
return this.map.size;
|
||||
}
|
||||
/**
|
||||
* Returns true if the given key is present in the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
has(key) {
|
||||
return this.map.has(this.normalizeKey(key));
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
set(key, val) {
|
||||
this.map.set(this.normalizeKey(key), { key, val });
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
get(key) {
|
||||
var _a;
|
||||
return (_a = this.map.get(this.normalizeKey(key))) === null || _a === void 0 ? void 0 : _a.val;
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
delete(key) {
|
||||
return this.map.delete(this.normalizeKey(key));
|
||||
}
|
||||
/**
|
||||
* Clear all key-value pairs from the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
clear() {
|
||||
this.map.clear();
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
forEach(callbackfn) {
|
||||
this.map.forEach((pair, _key, _internalMap) => {
|
||||
callbackfn(pair.val, pair.key, this);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @yields the next key-value pair in the map
|
||||
* @inheritdoc
|
||||
*/
|
||||
*[Symbol.iterator]() {
|
||||
for (const [_hashStr, pair] of this.map[Symbol.iterator]()) {
|
||||
yield [pair.key, pair.val];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @yields the next key-value pair in the map
|
||||
* @inheritdoc
|
||||
*/
|
||||
*entries() {
|
||||
for (const entry of this[Symbol.iterator]()) {
|
||||
yield entry;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
*keys() {
|
||||
for (const [key, _val] of this[Symbol.iterator]()) {
|
||||
yield key;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
*values() {
|
||||
for (const [_key, val] of this[Symbol.iterator]()) {
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns true if the entries of `other` are the same as this map
|
||||
*/
|
||||
equals(other) {
|
||||
this.validateUsingSameOptionsAs(other);
|
||||
return this.size === other.size && this.contains(other);
|
||||
}
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns true if the entries of `other` are all contained in this map
|
||||
*/
|
||||
contains(other) {
|
||||
this.validateUsingSameOptionsAs(other);
|
||||
return [...other.entries()].every(([key, val]) => this.keyValuePairIsPresentIn(key, val, this));
|
||||
}
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns a new map whose keys are the union of keys between `this` and `other` maps.
|
||||
*
|
||||
* NOTE: If both maps prescribe the same key, the key-value pair from `this` will be retained.
|
||||
*/
|
||||
union(other) {
|
||||
this.validateUsingSameOptionsAs(other);
|
||||
return new DeepMap([...other.entries(), ...this.entries()], this.options);
|
||||
}
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns a new map containing all key-value pairs in `this` that are also present in `other`.
|
||||
*/
|
||||
intersection(other) {
|
||||
this.validateUsingSameOptionsAs(other);
|
||||
const intersectingPairs = [...this.entries()].filter(([key, val]) => this.keyValuePairIsPresentIn(key, val, other));
|
||||
return new DeepMap(intersectingPairs, this.options);
|
||||
}
|
||||
/**
|
||||
* @param other the map to compare against
|
||||
* @returns a new map containing all key-value pairs in `this` that are not present in `other`.
|
||||
*/
|
||||
difference(other) {
|
||||
this.validateUsingSameOptionsAs(other);
|
||||
const differencePairs = [...this.entries()].filter(([key, val]) => !this.keyValuePairIsPresentIn(key, val, other));
|
||||
return new DeepMap(differencePairs, this.options);
|
||||
}
|
||||
// PRIVATE/PROTECTED METHODS FOLLOW...
|
||||
normalizeKey(input) {
|
||||
return this.normalizer.normalizeKey(input);
|
||||
}
|
||||
normalizeValue(input) {
|
||||
return this.normalizer.normalizeValue(input);
|
||||
}
|
||||
validateUsingSameOptionsAs(other) {
|
||||
if (this.normalizer.getOptionsChecksum() !== other['normalizer'].getOptionsChecksum()) {
|
||||
throw new errors_1.DeepEqualityDataStructuresError('Structures must use same options for Comparable interface operations');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @returns true if the key is present in the provided map w/ the specified value
|
||||
*/
|
||||
keyValuePairIsPresentIn(key, val, mapToCheck) {
|
||||
const checkVal = mapToCheck.get(key);
|
||||
return checkVal !== undefined && this.normalizeValue(checkVal) === this.normalizeValue(val);
|
||||
}
|
||||
}
|
||||
exports.DeepMap = DeepMap;
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import { Options } from './options';
|
||||
/**
|
||||
* Result of object-hash hashing function
|
||||
*/
|
||||
type HashedObject = string;
|
||||
/**
|
||||
* Type for normalized input.
|
||||
*/
|
||||
export type Normalized<T> = HashedObject | T;
|
||||
/**
|
||||
* Class that normalizes object types to strings via hashing
|
||||
*/
|
||||
export declare class Normalizer<K, V, TxK, TxV> {
|
||||
private readonly objectHashOptions;
|
||||
private readonly caseInsensitive;
|
||||
private readonly keyTransformer;
|
||||
private readonly valueTransformer;
|
||||
private readonly optionsChecksum;
|
||||
constructor(options?: Options<K, V, TxK, TxV>);
|
||||
/**
|
||||
* @returns the checksum for the options passed to this Normalizer
|
||||
*/
|
||||
getOptionsChecksum(): string;
|
||||
/**
|
||||
* Normalize the input by transforming and then hashing the result (if an object)
|
||||
* @param input the input to normalize
|
||||
* @returns the normalized result
|
||||
*/
|
||||
normalizeKey(input: K): Normalized<TxK>;
|
||||
/**
|
||||
* Normalize the input by transforming and then hashing the result (if an object)
|
||||
* @param input the input to normalize
|
||||
* @returns the normalized result
|
||||
*/
|
||||
normalizeValue(input: V): Normalized<TxV>;
|
||||
private normalizeHelper;
|
||||
/**
|
||||
* Returns true if the input is a javascript object.
|
||||
*/
|
||||
private static isObject;
|
||||
}
|
||||
export {};
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Normalizer = void 0;
|
||||
const object_hash_1 = __importDefault(require("object-hash"));
|
||||
const options_1 = require("./options");
|
||||
const transformers_1 = require("./transformers");
|
||||
const utils_1 = require("./utils");
|
||||
/**
|
||||
* Class that normalizes object types to strings via hashing
|
||||
*/
|
||||
class Normalizer {
|
||||
constructor(options = {}) {
|
||||
this.optionsChecksum = (0, object_hash_1.default)(options);
|
||||
const _a = (0, options_1.getOptionsWithDefaults)(options), { transformer, mapValueTransformer, useToJsonTransform, caseInsensitive } = _a, objectHashOptions = __rest(_a, ["transformer", "mapValueTransformer", "useToJsonTransform", "caseInsensitive"]);
|
||||
this.objectHashOptions = objectHashOptions;
|
||||
this.caseInsensitive = caseInsensitive;
|
||||
this.keyTransformer = useToJsonTransform
|
||||
? (0, utils_1.chain)([transformers_1.Transformers.jsonSerializeDeserialize, transformer])
|
||||
: transformer;
|
||||
this.valueTransformer = useToJsonTransform
|
||||
? (0, utils_1.chain)([transformers_1.Transformers.jsonSerializeDeserialize, mapValueTransformer])
|
||||
: mapValueTransformer;
|
||||
if (caseInsensitive) {
|
||||
// NOTE: This block ensures case-insensitivity inside objects only.
|
||||
// See normalizeHelper() for logic which handles primitive strings
|
||||
const caseInsensitiveReplacer = (val) => typeof val === 'string' ? val.toLowerCase() : val;
|
||||
const { replacer } = this.objectHashOptions;
|
||||
this.objectHashOptions.replacer = replacer
|
||||
? (0, utils_1.chain)([caseInsensitiveReplacer, replacer])
|
||||
: caseInsensitiveReplacer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @returns the checksum for the options passed to this Normalizer
|
||||
*/
|
||||
getOptionsChecksum() {
|
||||
return this.optionsChecksum;
|
||||
}
|
||||
/**
|
||||
* Normalize the input by transforming and then hashing the result (if an object)
|
||||
* @param input the input to normalize
|
||||
* @returns the normalized result
|
||||
*/
|
||||
normalizeKey(input) {
|
||||
return this.normalizeHelper(this.keyTransformer(input));
|
||||
}
|
||||
/**
|
||||
* Normalize the input by transforming and then hashing the result (if an object)
|
||||
* @param input the input to normalize
|
||||
* @returns the normalized result
|
||||
*/
|
||||
normalizeValue(input) {
|
||||
return this.normalizeHelper(this.valueTransformer(input));
|
||||
}
|
||||
normalizeHelper(input) {
|
||||
if (Normalizer.isObject(input)) {
|
||||
return (0, object_hash_1.default)(input, this.objectHashOptions);
|
||||
}
|
||||
else if (this.caseInsensitive && typeof input === 'string') {
|
||||
return input.toLowerCase();
|
||||
}
|
||||
else {
|
||||
// Primitive value, don't hash
|
||||
return input;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns true if the input is a javascript object.
|
||||
*/
|
||||
static isObject(input) {
|
||||
return typeof input === 'object' && input !== null;
|
||||
}
|
||||
}
|
||||
exports.Normalizer = Normalizer;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { NormalOption as ObjectHashOptions } from 'object-hash';
|
||||
import { TransformFunction } from './transformers';
|
||||
import { Require } from './utils';
|
||||
/**
|
||||
* Library options
|
||||
*/
|
||||
interface DeepEqualityDataStructuresOptions<K, V, TxK, TxV> {
|
||||
/**
|
||||
* A function that transforms Map keys or Set values prior to normalization.
|
||||
*
|
||||
* NOTE: The caller is responsible for not mutating object inputs.
|
||||
*/
|
||||
transformer?: TransformFunction<K, TxK>;
|
||||
/**
|
||||
* A function that transforms Map values prior to normalization.
|
||||
*
|
||||
* NOTE: The caller is responsible for not mutating object inputs.
|
||||
*/
|
||||
mapValueTransformer?: TransformFunction<V, TxV>;
|
||||
/**
|
||||
* If true, objects will be JSON-serialized/deserialized into "plain" objects prior to hashing.
|
||||
*/
|
||||
useToJsonTransform?: boolean;
|
||||
/**
|
||||
* If true, all string values (including keys/values within objects and arrays) will use case-insensitive equality comparisons.
|
||||
*/
|
||||
caseInsensitive?: boolean;
|
||||
}
|
||||
export type Options<K, V, TxK, TxV> = ObjectHashOptions & DeepEqualityDataStructuresOptions<K, V, TxK, TxV>;
|
||||
/**
|
||||
* Given the specified options, resolve default values as appropriate.
|
||||
*/
|
||||
export declare function getOptionsWithDefaults<K, V, TxK, TxV>(options: Options<K, V, TxK, TxV>): Require<Options<K, V, TxK, TxV>, keyof DeepEqualityDataStructuresOptions<K, V, TxK, TxV>>;
|
||||
export {};
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getOptionsWithDefaults = getOptionsWithDefaults;
|
||||
const transformers_1 = require("./transformers");
|
||||
/**
|
||||
* Given the specified options, resolve default values as appropriate.
|
||||
*/
|
||||
function getOptionsWithDefaults(options) {
|
||||
return Object.assign({
|
||||
// Default options
|
||||
algorithm: 'md5', transformer: transformers_1.Transformers.identity, mapValueTransformer: transformers_1.Transformers.identity, useToJsonTransform: false, caseInsensitive: false }, options);
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
import { Comparable } from './comparable';
|
||||
import { Options } from './options';
|
||||
/**
|
||||
* A Set implementation that supports deep equality for values.
|
||||
*/
|
||||
export declare class DeepSet<V, TxV = V> extends Set<V> implements Comparable<DeepSet<V, TxV>> {
|
||||
private options?;
|
||||
private readonly map;
|
||||
/**
|
||||
* @param values optional list of values to initialize the set
|
||||
* @param options configuration options
|
||||
*/
|
||||
constructor(values?: readonly V[] | null, options?: Options<V, null, TxV, null> | undefined);
|
||||
/**
|
||||
* Getter for number of elements in the set.
|
||||
* @inheritdoc
|
||||
*/
|
||||
get size(): number;
|
||||
/**
|
||||
* Returns true if the given value is present in the set.
|
||||
* @inheritdoc
|
||||
*/
|
||||
has(val: V): boolean;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
add(val: V): this;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
delete(val: V): boolean;
|
||||
/**
|
||||
* Clear all values from the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
clear(): void;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
forEach(callbackfn: (val: V, val2: V, set: Set<V>) => void): void;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
[Symbol.iterator](): IterableIterator<V>;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
entries(): IterableIterator<[V, V]>;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
keys(): IterableIterator<V>;
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
values(): IterableIterator<V>;
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns true if the values of `other` are the same as this set
|
||||
*/
|
||||
equals(other: this): boolean;
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns true if the values of `other` are all contained in this set
|
||||
*/
|
||||
contains(other: this): boolean;
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns a new set whose values are the union of `this` and `other`.
|
||||
*/
|
||||
union(other: this): DeepSet<V, TxV>;
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns a new set containing all values in `this` that are also in `other`.
|
||||
*/
|
||||
intersection(other: this): DeepSet<V, TxV>;
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns a new set containing all values in `this` that are not also in `other`.
|
||||
*/
|
||||
difference(other: this): DeepSet<V, TxV>;
|
||||
private getSetFromMapKeys;
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.DeepSet = void 0;
|
||||
const map_1 = require("./map");
|
||||
/**
|
||||
* A Set implementation that supports deep equality for values.
|
||||
*/
|
||||
class DeepSet extends Set {
|
||||
// NOTE: This is actually a thin wrapper. We're not using super other than to drive the (typed) API contract.
|
||||
/**
|
||||
* @param values optional list of values to initialize the set
|
||||
* @param options configuration options
|
||||
*/
|
||||
constructor(values, options) {
|
||||
super();
|
||||
this.options = options;
|
||||
const transformedEntries = values ? values.map((el) => [el, null]) : null;
|
||||
this.map = new map_1.DeepMap(transformedEntries, options);
|
||||
}
|
||||
/**
|
||||
* Getter for number of elements in the set.
|
||||
* @inheritdoc
|
||||
*/
|
||||
get size() {
|
||||
return this.map.size;
|
||||
}
|
||||
/**
|
||||
* Returns true if the given value is present in the set.
|
||||
* @inheritdoc
|
||||
*/
|
||||
has(val) {
|
||||
return this.map.has(val);
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
add(val) {
|
||||
this.map.set(val, null);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
delete(val) {
|
||||
return this.map.delete(val);
|
||||
}
|
||||
/**
|
||||
* Clear all values from the map.
|
||||
* @inheritdoc
|
||||
*/
|
||||
clear() {
|
||||
this.map.clear();
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
forEach(callbackfn) {
|
||||
this.map.forEach((_mapVal, mapKey, _map) => {
|
||||
callbackfn(mapKey, mapKey, this);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
*[Symbol.iterator]() {
|
||||
for (const [key, _val] of this.map[Symbol.iterator]()) {
|
||||
yield key;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
*entries() {
|
||||
for (const val of this[Symbol.iterator]()) {
|
||||
yield [val, val];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
*keys() {
|
||||
for (const val of this[Symbol.iterator]()) {
|
||||
yield val;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
*values() {
|
||||
yield* this.keys();
|
||||
}
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns true if the values of `other` are the same as this set
|
||||
*/
|
||||
equals(other) {
|
||||
return this.map.equals(other['map']);
|
||||
}
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns true if the values of `other` are all contained in this set
|
||||
*/
|
||||
contains(other) {
|
||||
return this.map.contains(other['map']);
|
||||
}
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns a new set whose values are the union of `this` and `other`.
|
||||
*/
|
||||
union(other) {
|
||||
return this.getSetFromMapKeys(this.map.union(other['map']));
|
||||
}
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns a new set containing all values in `this` that are also in `other`.
|
||||
*/
|
||||
intersection(other) {
|
||||
return this.getSetFromMapKeys(this.map.intersection(other['map']));
|
||||
}
|
||||
/**
|
||||
* @param other the set to compare against
|
||||
* @returns a new set containing all values in `this` that are not also in `other`.
|
||||
*/
|
||||
difference(other) {
|
||||
return this.getSetFromMapKeys(this.map.difference(other['map']));
|
||||
}
|
||||
getSetFromMapKeys(map) {
|
||||
return new DeepSet([...map.keys()], this.options);
|
||||
}
|
||||
}
|
||||
exports.DeepSet = DeepSet;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
export type TransformFunction<T, R> = (input: T) => R;
|
||||
export declare class Transformers {
|
||||
static identity<T, R = T>(input: T): R;
|
||||
static jsonSerializeDeserialize<T, R = T>(obj: T): R;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Transformers = void 0;
|
||||
class Transformers {
|
||||
static identity(input) {
|
||||
// Just make the types happy :)
|
||||
return input;
|
||||
}
|
||||
static jsonSerializeDeserialize(obj) {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
}
|
||||
exports.Transformers = Transformers;
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Require the keys K from T if optional.
|
||||
*/
|
||||
export type Require<T, K extends keyof T> = T & {
|
||||
[P in K]-?: T[P];
|
||||
};
|
||||
/**
|
||||
* Format an unknown value to a string for display
|
||||
*/
|
||||
export declare function stringify(value: unknown): string;
|
||||
/**
|
||||
* Chain a list of functions
|
||||
* @returns a function that accepts the args of the first function in the functions list. Each subsequent function is invoked with
|
||||
* the return value of the previous function.
|
||||
*/
|
||||
export declare function chain<TArgs extends any[], T1>(functions: [(...args: TArgs) => T1]): (...args: TArgs) => T1;
|
||||
export declare function chain<TArgs extends any[], T1, T2>(functions: [(...args: TArgs) => T1, (arg: T1) => T2]): (...args: TArgs) => T2;
|
||||
export declare function chain<TArgs extends any[], T1, T2, T3>(functions: [(...args: TArgs) => T1, (arg: T1) => T2, (arg: T2) => T3]): (...args: TArgs) => T3;
|
||||
export declare function chain<TArgs extends any[], T1, T2, T3, T4>(functions: [(...args: TArgs) => T1, (arg: T1) => T2, (arg: T2) => T3, (arg: T3) => T4]): (...args: TArgs) => T4;
|
||||
export declare function chain<TArgs extends any[], T1, T2, T3, T4, T5>(functions: [(...args: TArgs) => T1, (arg: T1) => T2, (arg: T2) => T3, (arg: T3) => T4, (arg: T4) => T5]): (...args: TArgs) => T5;
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.stringify = stringify;
|
||||
exports.chain = chain;
|
||||
/**
|
||||
* Format an unknown value to a string for display
|
||||
*/
|
||||
function stringify(value) {
|
||||
if (value !== null && typeof value === 'object') {
|
||||
// For objects, defer an overridden toString, otherwise use JSON.stringify
|
||||
return 'toString' in value && ![Object.prototype.toString, Array.prototype.toString].includes(value.toString)
|
||||
? value.toString()
|
||||
: JSON.stringify(value);
|
||||
}
|
||||
else {
|
||||
return String(value);
|
||||
}
|
||||
}
|
||||
function chain(functions) {
|
||||
const [head, ...tail] = functions;
|
||||
return (...args) => {
|
||||
return tail.reduce((acc, fn) => fn(acc), head(...args));
|
||||
};
|
||||
}
|
||||
/* eslint-enable @typescript-eslint/no-explicit-any */
|
||||
Reference in New Issue
Block a user