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

@prosopo/util

Package Overview
Dependencies
Maintainers
3
Versions
69
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@prosopo/util - npm Package Compare versions

Comparing version 0.2.7 to 0.2.8

88

dist/tests/util.test.js

@@ -14,5 +14,91 @@ // Copyright 2021-2023 Prosopo (UK) Ltd.

// limitations under the License.
import { at, get, permutations, rng, seedLodash } from '../util.js';
import { at, get, merge, permutations, rng, seedLodash } from '../util.js';
import { describe, expect, test } from 'vitest';
describe('util', () => {
describe('merge', () => {
// factors:
// - types
// - primitive
// - array
// - object
// - nesting
// - 0 levels
// - 1 levels
// - 2 levels
// - array strat
// - 'update'
// - 'replace'
// - merge nested els in array
// - true
// - false
// - merge nested fields in obj
// - true
// - false
test('array in array', () => {
expect(merge([
[0, 1, 2],
[3, 4, 5],
], [
[6, 7],
[8, 9],
])).to.deep.equal([
[6, 7, 2],
[8, 9, 5],
]);
});
test('array in array atomic', () => {
expect(merge([
[0, 1, 2],
[3, 4, 5],
], [
[6, 7],
[8, 9],
], { atomicArrays: true })).to.deep.equal([
[6, 7],
[8, 9],
]);
});
test('array in object', () => {
expect(merge({ a: [0, 1, 2] }, { a: [3, 4] })).to.deep.equal({ a: [3, 4, 2] });
});
test('array in object atomic', () => {
expect(merge({ a: [0, 1, 2] }, { a: [3, 4] }, { atomicArrays: true })).to.deep.equal({ a: [3, 4] });
});
test('array in object in array', () => {
expect(merge([{ a: [0, 1, 2] }, { b: [3, 4, 5] }], [{ a: [6, 7] }, { b: [8, 9] }])).to.deep.equal([
{ a: [6, 7, 2] },
{ b: [8, 9, 5] },
]);
});
test('array in object in array atomic', () => {
expect(merge([{ a: [0, 1, 2] }, { b: [3, 4, 5] }], [{ a: [6, 7] }, { b: [8, 9] }], { atomicArrays: true })).to.deep.equal([{ a: [6, 7] }, { b: [8, 9] }]);
});
test('primitive replaces array', () => {
expect(merge({ a: [1] }, { a: 1 })).to.deep.equal({ a: 1 });
});
test('primitive replaces object', () => {
expect(merge({ a: { b: 1 } }, { a: 1 })).to.deep.equal({ a: 1 });
});
test('primitive replaces primitive', () => {
expect(merge({ a: 1 }, { a: 2 })).to.deep.equal({ a: 2 });
});
test('array replaces primitive', () => {
expect(merge({ a: 1 }, { a: [1] })).to.deep.equal({ a: [1] });
});
test('array replaces array', () => {
expect(merge({ a: [1] }, { a: [2] })).to.deep.equal({ a: [2] });
});
test('array replaces object', () => {
expect(merge({ a: { b: 1 } }, { a: [1] })).to.deep.equal({ a: [1] });
});
test('object replaces primitive', () => {
expect(merge({ a: 1 }, { a: { b: 1 } })).to.deep.equal({ a: { b: 1 } });
});
test('object replaces array', () => {
expect(merge({ a: [1] }, { a: { b: 1 } })).to.deep.equal({ a: { b: 1 } });
});
test('object replaces object', () => {
expect(merge({ a: { b: 1 } }, { a: { c: 1 } })).to.deep.equal({ a: { b: 1, c: 1 } });
});
});
describe('at', () => {

@@ -19,0 +105,0 @@ test('types', () => {

import _lodash from 'lodash';
export declare const sleep: (ms: number) => Promise<unknown>;
export declare const setSeedGlobal: (seed: number | string) => void;

@@ -39,2 +40,9 @@ export declare const lodash: () => _lodash.LoDashStatic;

export declare const flattenObj: (obj: object, prefix?: string) => Record<string, unknown>;
export declare const kebabCase: (str: string) => string;
export type MergeOptions = {
atomicArrays?: boolean;
};
export declare function merge<T extends object | A[], U extends object | B[], A, B>(dest: T, src: U, options?: MergeOptions): T & U;
export declare const isArray: (value: unknown) => boolean;
export declare const isObject: (value: unknown) => boolean;
//# sourceMappingURL=util.d.ts.map
import _lodash from 'lodash';
import seedrandom from 'seedrandom';
// sleep for some milliseconds
export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// set the seed for the global rng, i.e. seed `Math.random()`

@@ -148,2 +150,96 @@ export const setSeedGlobal = (seed) => {

};
// https://stackoverflow.com/questions/63116039/camelcase-to-kebab-case
export const kebabCase = (str) => str.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? '-' : '') + $.toLowerCase());
// Merge two objects or arrays together.
// Nesting can be infinitely deep.
// Arrays can be homogeneous or hetrogeneous.
// The destination object/array is mutated directly.
// Arrays can be merged in two ways:
// - update (default): replace elements as required and extend array as required, e.g. [1,2,3] + [4,5] = [4,5,3]
// - replace: treat the array as a primitive value and simply replace as-is, e.g. [1,2,3] + [4,5] = [4,5]
// The 'atomicArrays' option controls whether arrays are treated as primitives or not. E.g. atomicArrays=true is the 'replace' strategy, atomicArrays=false is the 'update' strategy.
// This method treats arrays as an object with numeric keys and merged using the object merge strategy.
export function merge(dest, src, options) {
const atomicArrays = options?.atomicArrays;
// maintain a queue of object sources/destinations to merge
const queue = [
{
src,
dest,
},
];
while (queue.length > 0) {
const task = queue.pop();
if (task === undefined) {
throw new Error('queue is empty');
}
if (isArray(task.dest)) {
// handling arrays
const src = task.src;
const dest = task.dest;
if (atomicArrays) {
// delete any items beyond the length of src
while (dest.length > src.length) {
dest.pop();
}
// treat arrays as primitives / atomic
for (let i = 0; i < src.length; i++) {
dest[i] = src[i];
}
}
else {
// else not treating arrays as primitives / atomic
// so need to merge them
// copy the elements from src into dest
for (let i = 0; i < src.length; i++) {
// if the element is an array or object, then we need to merge it
if ((isArray(dest[i]) && isArray(src[i])) || (isObject(dest[i]) && isObject(src[i]))) {
// need to merge arrays or objects
queue.push({
src: src[i],
dest: dest[i],
});
}
else {
// primitive, so replace
// or src[i] is array but dest[i] is not, so replace
// or src[i] is object but dest[i] is not, so replace
dest[i] = src[i];
}
}
}
}
else if (isObject(task.dest)) {
const src = task.src;
const destAny = task.dest;
// for every entry in src
for (const [key, value] of Object.entries(src)) {
// if the value in src + dest is an array or object, then we need to merge it
if ((isArray(value) && isArray(destAny[key])) || (isObject(value) && isObject(destAny[key]))) {
// need to merge arrays or objects
queue.push({
src: value,
dest: destAny[key],
});
}
else {
// primitive, so replace
// or value is array but dest[key] is not, so replace
// or value is object but dest[key] is not, so replace
destAny[key] = value;
}
}
}
else {
throw new Error(`cannot handle type in queue: ${typeof task.dest}`);
}
}
return dest;
}
export const isArray = (value) => {
return Array.isArray(value);
};
export const isObject = (value) => {
return value instanceof Object && !isArray(value);
};
//# sourceMappingURL=util.js.map

3

package.json
{
"name": "@prosopo/util",
"version": "0.2.7",
"version": "0.2.8",
"author": "PROSOPO LIMITED <info@prosopo.io>",

@@ -36,3 +36,2 @@ "license": "Apache-2.0",

"@types/lodash": "^4.14.198",
"@types/mocha": "^10.0.1",
"@types/seedrandom": "^3.0.5",

@@ -39,0 +38,0 @@ "@vitest/coverage-v8": "^0.34.3",

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