Socket
Socket
Sign inDemoInstall

deep-state-observer

Package Overview
Dependencies
Maintainers
1
Versions
225
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

deep-state-observer - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

wildcard-object-scan.ts

305

index.cjs.js

@@ -1250,179 +1250,97 @@ 'use strict';

var wildstring_1 = createCommonjsModule(function (module) {
function wildcardToRegex(wildcard, delimeter = '.') {
return new RegExp('^' +
wildcard
.split('**')
.map((part) => {
return part
.split('*')
.map((smallPart) => smallPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.join(`[^\\${delimeter}]*`);
})
.join(`.*`) +
'$');
}
function match(first, second, delimeter = '.') {
return wildcardToRegex(first, delimeter).test(second);
}
function scanObject(obj, delimeter = '.') {
const api = {
get(wildcard) {
const wildcardSplit = prepareWildcardSplit(wildcard);
if (wildcardSplit.length === 0) {
return obj;
}
return handleObject(wildcardSplit, obj, 0, '');
}
};
function prepareWildcardSplit(wildcardSplit) {
if (typeof wildcardSplit === 'string') {
if (wildcardSplit === '') {
wildcardSplit = [];
}
else {
wildcardSplit = wildcardSplit.split(delimeter);
}
}
return wildcardSplit;
}
function isEnd(wildcardSplit, partIndex) {
return wildcardSplit.length - 1 <= partIndex;
}
function goFurther(wildcardSplit, currentObj, partIndex, currentPath, result) {
if (Array.isArray(currentObj)) {
handleArray(wildcardSplit, currentObj, partIndex, currentPath, result);
}
else if (currentObj.constructor.name === 'Object') {
handleObject(wildcardSplit, currentObj, partIndex, currentPath, result);
}
}
function handleArray(wildcardSplit, currentArr, partIndex, path, result = {}) {
const currentWildcardPath = wildcardSplit.slice(0, partIndex + 1).join(delimeter);
const end = isEnd(wildcardSplit, partIndex);
const fullWildcard = currentWildcardPath.indexOf('**') > -1;
const traverse = !end || fullWildcard;
let index = 0;
for (const item of currentArr) {
const currentPath = path === '' ? path + index : path + delimeter + index;
if (match(currentWildcardPath, currentPath)) {
if (end) {
result[currentPath] = item;
}
if (traverse) {
goFurther(wildcardSplit, item, partIndex + 1, currentPath, result);
}
}
else if (fullWildcard) {
goFurther(wildcardSplit, item, partIndex + 1, currentPath, result);
}
index++;
}
return result;
}
function handleObject(wildcardSplit, currentObj, partIndex, path, result = {}) {
const currentWildcardPath = wildcardSplit.slice(0, partIndex + 1).join(delimeter);
const end = isEnd(wildcardSplit, partIndex);
const fullWildcard = currentWildcardPath.indexOf('**') > -1;
const traverse = !end || fullWildcard;
for (const key in currentObj) {
const currentPath = path === '' ? path + key : path + delimeter + key;
if (match(currentWildcardPath, currentPath)) {
if (end) {
result[currentPath] = currentObj[key];
}
if (traverse) {
goFurther(wildcardSplit, currentObj[key], partIndex + 1, currentPath, result);
}
}
else if (fullWildcard) {
goFurther(wildcardSplit, currentObj[key], partIndex + 1, currentPath, result);
}
}
return result;
}
return api;
}
/**
* @namespace wildstring
* @property {string} wildcard the wildcard to use in your strings, defaults to '*'
* @property {boolean} caseSensitive whether matches should care about case, defaults to true
*/
var wildstring = {
wildcard: '*',
caseSensitive: true,
/**
* When a match doesn't continue to the end of the string, this function rolls back to try again with the rest of the string
* @memberof wildstring
* @access private
* @param {string[]} rollbackStrings The list of substrings that appeared prior to the current match
* @param {string[]} patternSubstrings The matching list of pattens that need to be matched before the current pattern
*/
checkRollbackStrings: function (rollbackStrings, patternSubstrings) {
for (var s = 0; s < rollbackStrings.length; ++s) {
var currentString = rollbackStrings[s].string; // starting with the rolled back string
var patternIndex = rollbackStrings[s].index;
while (patternIndex < patternSubstrings.length) {
if (currentString.indexOf(patternSubstrings[patternIndex]) === -1) {
break;
}
var testString = currentString.substr(1); //remove just one char to retest
rollbackStrings.push({ string: testString, index: patternIndex });
if (testString.indexOf(patternSubstrings[patternIndex]) === -1) {
rollbackStrings.pop();
}
currentString = currentString.substr(
currentString.indexOf(patternSubstrings[patternIndex]) + patternSubstrings[patternIndex].length
);
patternIndex++;
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
}
if (patternIndex >= patternSubstrings.length) {
if (patternSubstrings[patternSubstrings.length - 1] !== '' &&
currentString.length > 0) {
// not ending with a wildcard, we need to backtrack
break;
}
else {
return true;
}
}
}
}
return false;
},
/**
* Check if a string matches a pattern
* @memberof wildstring
* @param {string} pattern The pattern to match using the configured wildcard
* @param {string} string The string to test for a match
*/
match: function (pattern, string) {
// if there are no wildcards, must be exact
if (pattern.indexOf(wildstring.wildcard) === -1) {
return pattern === string;
}
if (!wildstring.caseSensitive) {
pattern = pattern.toLowerCase();
string = string.toLowerCase();
}
var patternSubstrings = pattern.split(wildstring.wildcard);
var patternIndex = 0;
var currentString = string;
// find pattern beginning
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
// if the pattern is just wildcards, it matches
if (patternIndex === pattern.length) {
return true;
}
}
if (patternIndex === 0 && string.indexOf(patternSubstrings[0]) !== 0) {
// not starting with a wildcard
return false;
}
var rollbackStrings = [];
while (patternIndex < patternSubstrings.length) {
if (currentString.indexOf(patternSubstrings[patternIndex]) === -1) {
return wildstring.checkRollbackStrings(rollbackStrings, patternSubstrings);
}
// create a queue of strings to roll back and try again if we fail later
var testString = currentString.substr(1); //remove just one char to retest
rollbackStrings.push({ string: testString, index: patternIndex });
if (testString.indexOf(patternSubstrings[patternIndex]) === -1) {
rollbackStrings.pop();
}
currentString = currentString.substr(
currentString.indexOf(patternSubstrings[patternIndex]) + patternSubstrings[patternIndex].length
);
patternIndex++;
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
}
}
if (patternIndex >= patternSubstrings.length &&
patternSubstrings[patternSubstrings.length - 1] !== '' &&
currentString.length > 0) {
// not ending with a wildcard, we need to backtrack
if (currentString === string) { // this string doesn't even match a little
return false;
}
return wildstring.checkRollbackStrings(rollbackStrings, patternSubstrings);
}
return true;
},
/**
* Replace wildcards in a pattern with strings (string interpolation)
* @memberof wildstring
* @param {string} pattern The start string, using wildcards as placeholders
* @param {string|string[]} strings The string or strings to replace the wildcards in the pattern.
* If you pass a single string, it will replace all the wildcards with the string.
* If you pass an array of strings, they will replace the wildcards in order from left to right.
* @throws The number of items in the strings array (if you pass an array) must match the number of wildcards in the pattern string.
* @throws You need to pass both parameters
* @throws You need to pass the right types
*/
replace: function (pattern, strings) {
if (pattern === undefined || strings === undefined) {
throw new Error('wildstring.replace takes the pattern as one parameter and either a string or an array of strings as the second. You didn\'t pass enough parameters.');
}
if (typeof(strings) === typeof('')) {
return pattern.replace(wildstring.wildcard, strings);
}
if (!Array.isArray(strings) || typeof(pattern) !== typeof('')) {
throw new Error('wildstring.replace takes the pattern as one parameter and either a string or an array of strings as the second. Your parameter types are incorrect.');
}
if (pattern.indexOf(wildstring.wildcard) === -1) {
return pattern; // if there are no wildcards, just return the pattern
}
var patternSubstrings = pattern.split(wildstring.wildcard);
if (patternSubstrings.length - 1 !== strings.length) {
var message = 'There are a different number of wildcards than strings to replace them. You have ' +
wildstring.wildcard +' wildcards in "' + wildstring.wildcard + '" and ' + wildstring.wildcard +
' replacement strings.';
throw new Error(wildstring.replace(message, [ patternSubstrings.length - 1, pattern, strings.length ]));
}
var result = '';
for (var s = 0; s < strings.length; ++s) {
result += patternSubstrings[s] + strings[s];
}
return result;
}
};
{ module.exports = wildstring; }
if (typeof(angular) !== 'undefined') { angular.module('wildstring', []).factory('wildstring', function() { return wildstring; }); }
});
class Store {

@@ -1446,3 +1364,3 @@ constructor(data = {}, options = { delimeter: '.' }) {

if (this.isWildcard(first)) {
return wildstring_1.match(first, second);
return match(first, second, this.options.delimeter);
}

@@ -1475,5 +1393,2 @@ return false;

}
watchAll(userPaths, fn) {
return this.subscribeAll(userPaths, fn);
}
subscribe(userPath, fn, execute = true) {

@@ -1488,10 +1403,14 @@ if (typeof userPath === 'function') {

this.listeners[userPath].push(fn);
if (execute && !this.isWildcard(userPath)) {
const isWildcard = this.isWildcard(userPath);
if (execute && !isWildcard) {
fn(path(this.split(userPath), this.data), userPath);
}
if (isWildcard) {
const paths = scanObject(this.data, this.options.delimeter).get(userPath);
for (const path in paths) {
fn(paths[path], path);
}
}
return this.unsubscribe(fn);
}
watch(userPath, fn) {
return this.subscribe(userPath, fn);
}
unsubscribe(fn) {

@@ -1507,10 +1426,3 @@ return () => {

}
unwatch(fn) {
return this.unsubscribe(fn);
}
update(userPath, fn, filter = (path, key) => true) {
if (typeof userPath === 'function') {
fn = userPath;
userPath = '';
}
update(userPath, fn) {
const lens = lensPath(this.split(userPath));

@@ -1532,5 +1444,4 @@ let oldValue = fastCopy(view(lens, this.data));

if (this.match(currentPath, userPath)) {
let currentPathSplit = this.split(currentPath);
for (const listener of this.listeners[currentPath]) {
listener(path(currentPathSplit, this.data), userPath);
listener(newValue, userPath);
}

@@ -1541,5 +1452,2 @@ }

}
set(userPath, fn) {
return this.update(userPath, fn);
}
get(userPath = undefined) {

@@ -1555,3 +1463,4 @@ if (typeof userPath === 'undefined' || userPath === '') {

}
var index = { scanObject, match, wildcardToRegex, Store };
module.exports = Store;
module.exports = index;

@@ -1248,179 +1248,97 @@ function _isPlaceholder(a) {

var wildstring_1 = createCommonjsModule(function (module) {
function wildcardToRegex(wildcard, delimeter = '.') {
return new RegExp('^' +
wildcard
.split('**')
.map((part) => {
return part
.split('*')
.map((smallPart) => smallPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.join(`[^\\${delimeter}]*`);
})
.join(`.*`) +
'$');
}
function match(first, second, delimeter = '.') {
return wildcardToRegex(first, delimeter).test(second);
}
function scanObject(obj, delimeter = '.') {
const api = {
get(wildcard) {
const wildcardSplit = prepareWildcardSplit(wildcard);
if (wildcardSplit.length === 0) {
return obj;
}
return handleObject(wildcardSplit, obj, 0, '');
}
};
function prepareWildcardSplit(wildcardSplit) {
if (typeof wildcardSplit === 'string') {
if (wildcardSplit === '') {
wildcardSplit = [];
}
else {
wildcardSplit = wildcardSplit.split(delimeter);
}
}
return wildcardSplit;
}
function isEnd(wildcardSplit, partIndex) {
return wildcardSplit.length - 1 <= partIndex;
}
function goFurther(wildcardSplit, currentObj, partIndex, currentPath, result) {
if (Array.isArray(currentObj)) {
handleArray(wildcardSplit, currentObj, partIndex, currentPath, result);
}
else if (currentObj.constructor.name === 'Object') {
handleObject(wildcardSplit, currentObj, partIndex, currentPath, result);
}
}
function handleArray(wildcardSplit, currentArr, partIndex, path, result = {}) {
const currentWildcardPath = wildcardSplit.slice(0, partIndex + 1).join(delimeter);
const end = isEnd(wildcardSplit, partIndex);
const fullWildcard = currentWildcardPath.indexOf('**') > -1;
const traverse = !end || fullWildcard;
let index = 0;
for (const item of currentArr) {
const currentPath = path === '' ? path + index : path + delimeter + index;
if (match(currentWildcardPath, currentPath)) {
if (end) {
result[currentPath] = item;
}
if (traverse) {
goFurther(wildcardSplit, item, partIndex + 1, currentPath, result);
}
}
else if (fullWildcard) {
goFurther(wildcardSplit, item, partIndex + 1, currentPath, result);
}
index++;
}
return result;
}
function handleObject(wildcardSplit, currentObj, partIndex, path, result = {}) {
const currentWildcardPath = wildcardSplit.slice(0, partIndex + 1).join(delimeter);
const end = isEnd(wildcardSplit, partIndex);
const fullWildcard = currentWildcardPath.indexOf('**') > -1;
const traverse = !end || fullWildcard;
for (const key in currentObj) {
const currentPath = path === '' ? path + key : path + delimeter + key;
if (match(currentWildcardPath, currentPath)) {
if (end) {
result[currentPath] = currentObj[key];
}
if (traverse) {
goFurther(wildcardSplit, currentObj[key], partIndex + 1, currentPath, result);
}
}
else if (fullWildcard) {
goFurther(wildcardSplit, currentObj[key], partIndex + 1, currentPath, result);
}
}
return result;
}
return api;
}
/**
* @namespace wildstring
* @property {string} wildcard the wildcard to use in your strings, defaults to '*'
* @property {boolean} caseSensitive whether matches should care about case, defaults to true
*/
var wildstring = {
wildcard: '*',
caseSensitive: true,
/**
* When a match doesn't continue to the end of the string, this function rolls back to try again with the rest of the string
* @memberof wildstring
* @access private
* @param {string[]} rollbackStrings The list of substrings that appeared prior to the current match
* @param {string[]} patternSubstrings The matching list of pattens that need to be matched before the current pattern
*/
checkRollbackStrings: function (rollbackStrings, patternSubstrings) {
for (var s = 0; s < rollbackStrings.length; ++s) {
var currentString = rollbackStrings[s].string; // starting with the rolled back string
var patternIndex = rollbackStrings[s].index;
while (patternIndex < patternSubstrings.length) {
if (currentString.indexOf(patternSubstrings[patternIndex]) === -1) {
break;
}
var testString = currentString.substr(1); //remove just one char to retest
rollbackStrings.push({ string: testString, index: patternIndex });
if (testString.indexOf(patternSubstrings[patternIndex]) === -1) {
rollbackStrings.pop();
}
currentString = currentString.substr(
currentString.indexOf(patternSubstrings[patternIndex]) + patternSubstrings[patternIndex].length
);
patternIndex++;
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
}
if (patternIndex >= patternSubstrings.length) {
if (patternSubstrings[patternSubstrings.length - 1] !== '' &&
currentString.length > 0) {
// not ending with a wildcard, we need to backtrack
break;
}
else {
return true;
}
}
}
}
return false;
},
/**
* Check if a string matches a pattern
* @memberof wildstring
* @param {string} pattern The pattern to match using the configured wildcard
* @param {string} string The string to test for a match
*/
match: function (pattern, string) {
// if there are no wildcards, must be exact
if (pattern.indexOf(wildstring.wildcard) === -1) {
return pattern === string;
}
if (!wildstring.caseSensitive) {
pattern = pattern.toLowerCase();
string = string.toLowerCase();
}
var patternSubstrings = pattern.split(wildstring.wildcard);
var patternIndex = 0;
var currentString = string;
// find pattern beginning
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
// if the pattern is just wildcards, it matches
if (patternIndex === pattern.length) {
return true;
}
}
if (patternIndex === 0 && string.indexOf(patternSubstrings[0]) !== 0) {
// not starting with a wildcard
return false;
}
var rollbackStrings = [];
while (patternIndex < patternSubstrings.length) {
if (currentString.indexOf(patternSubstrings[patternIndex]) === -1) {
return wildstring.checkRollbackStrings(rollbackStrings, patternSubstrings);
}
// create a queue of strings to roll back and try again if we fail later
var testString = currentString.substr(1); //remove just one char to retest
rollbackStrings.push({ string: testString, index: patternIndex });
if (testString.indexOf(patternSubstrings[patternIndex]) === -1) {
rollbackStrings.pop();
}
currentString = currentString.substr(
currentString.indexOf(patternSubstrings[patternIndex]) + patternSubstrings[patternIndex].length
);
patternIndex++;
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
}
}
if (patternIndex >= patternSubstrings.length &&
patternSubstrings[patternSubstrings.length - 1] !== '' &&
currentString.length > 0) {
// not ending with a wildcard, we need to backtrack
if (currentString === string) { // this string doesn't even match a little
return false;
}
return wildstring.checkRollbackStrings(rollbackStrings, patternSubstrings);
}
return true;
},
/**
* Replace wildcards in a pattern with strings (string interpolation)
* @memberof wildstring
* @param {string} pattern The start string, using wildcards as placeholders
* @param {string|string[]} strings The string or strings to replace the wildcards in the pattern.
* If you pass a single string, it will replace all the wildcards with the string.
* If you pass an array of strings, they will replace the wildcards in order from left to right.
* @throws The number of items in the strings array (if you pass an array) must match the number of wildcards in the pattern string.
* @throws You need to pass both parameters
* @throws You need to pass the right types
*/
replace: function (pattern, strings) {
if (pattern === undefined || strings === undefined) {
throw new Error('wildstring.replace takes the pattern as one parameter and either a string or an array of strings as the second. You didn\'t pass enough parameters.');
}
if (typeof(strings) === typeof('')) {
return pattern.replace(wildstring.wildcard, strings);
}
if (!Array.isArray(strings) || typeof(pattern) !== typeof('')) {
throw new Error('wildstring.replace takes the pattern as one parameter and either a string or an array of strings as the second. Your parameter types are incorrect.');
}
if (pattern.indexOf(wildstring.wildcard) === -1) {
return pattern; // if there are no wildcards, just return the pattern
}
var patternSubstrings = pattern.split(wildstring.wildcard);
if (patternSubstrings.length - 1 !== strings.length) {
var message = 'There are a different number of wildcards than strings to replace them. You have ' +
wildstring.wildcard +' wildcards in "' + wildstring.wildcard + '" and ' + wildstring.wildcard +
' replacement strings.';
throw new Error(wildstring.replace(message, [ patternSubstrings.length - 1, pattern, strings.length ]));
}
var result = '';
for (var s = 0; s < strings.length; ++s) {
result += patternSubstrings[s] + strings[s];
}
return result;
}
};
{ module.exports = wildstring; }
if (typeof(angular) !== 'undefined') { angular.module('wildstring', []).factory('wildstring', function() { return wildstring; }); }
});
class Store {

@@ -1444,3 +1362,3 @@ constructor(data = {}, options = { delimeter: '.' }) {

if (this.isWildcard(first)) {
return wildstring_1.match(first, second);
return match(first, second, this.options.delimeter);
}

@@ -1473,5 +1391,2 @@ return false;

}
watchAll(userPaths, fn) {
return this.subscribeAll(userPaths, fn);
}
subscribe(userPath, fn, execute = true) {

@@ -1486,10 +1401,14 @@ if (typeof userPath === 'function') {

this.listeners[userPath].push(fn);
if (execute && !this.isWildcard(userPath)) {
const isWildcard = this.isWildcard(userPath);
if (execute && !isWildcard) {
fn(path(this.split(userPath), this.data), userPath);
}
if (isWildcard) {
const paths = scanObject(this.data, this.options.delimeter).get(userPath);
for (const path in paths) {
fn(paths[path], path);
}
}
return this.unsubscribe(fn);
}
watch(userPath, fn) {
return this.subscribe(userPath, fn);
}
unsubscribe(fn) {

@@ -1505,10 +1424,3 @@ return () => {

}
unwatch(fn) {
return this.unsubscribe(fn);
}
update(userPath, fn, filter = (path, key) => true) {
if (typeof userPath === 'function') {
fn = userPath;
userPath = '';
}
update(userPath, fn) {
const lens = lensPath(this.split(userPath));

@@ -1530,5 +1442,4 @@ let oldValue = fastCopy(view(lens, this.data));

if (this.match(currentPath, userPath)) {
let currentPathSplit = this.split(currentPath);
for (const listener of this.listeners[currentPath]) {
listener(path(currentPathSplit, this.data), userPath);
listener(newValue, userPath);
}

@@ -1539,5 +1450,2 @@ }

}
set(userPath, fn) {
return this.update(userPath, fn);
}
get(userPath = undefined) {

@@ -1553,3 +1461,4 @@ if (typeof userPath === 'undefined' || userPath === '') {

}
var index = { scanObject, match, wildcardToRegex, Store };
export default Store;
export default index;

@@ -1,4 +0,4 @@

import { path, set, view, lensPath, equals } from 'ramda';
import { path, set, view, lensPath } from 'ramda';
import clone from 'fast-copy';
import wildstring from 'wildstring';
import { scanObject, match, wildcardToRegex } from './wildcard-object-scan';

@@ -13,3 +13,3 @@ export type Listener = (value: any, path: string) => {};

export default class Store {
class Store {
listeners: IListeners;

@@ -39,3 +39,3 @@ data: any;

if (this.isWildcard(first)) {
return wildstring.match(first, second);
return match(first, second, this.options.delimeter);
}

@@ -72,7 +72,3 @@ return false;

watchAll(userPaths, fn) {
return this.subscribeAll(userPaths, fn);
}
subscribe(userPath: string | Listener, fn: Listener | undefined, execute = true) {
subscribe(userPath: string, fn: Listener, execute = true) {
if (typeof userPath === 'function') {

@@ -86,12 +82,15 @@ fn = userPath;

this.listeners[userPath].push(fn);
if (execute && !this.isWildcard(userPath)) {
const isWildcard = this.isWildcard(userPath);
if (execute && !isWildcard) {
fn(path(this.split(userPath), this.data), userPath);
}
if (isWildcard) {
const paths = scanObject(this.data, this.options.delimeter).get(userPath);
for (const path in paths) {
fn(paths[path], path);
}
}
return this.unsubscribe(fn);
}
watch(userPath: string | Listener, fn: Listener | undefined) {
return this.subscribe(userPath, fn);
}
unsubscribe(fn: Listener) {

@@ -108,11 +107,3 @@ return () => {

unwatch(fn: Listener) {
return this.unsubscribe(fn);
}
update(userPath: string | Updater, fn: Updater | undefined, filter = (path, key) => true) {
if (typeof userPath === 'function') {
fn = userPath;
userPath = '';
}
update(userPath: string, fn: Updater) {
const lens = lensPath(this.split(userPath));

@@ -135,5 +126,4 @@ let oldValue = clone(view(lens, this.data));

if (this.match(currentPath, userPath)) {
let currentPathSplit = this.split(currentPath);
for (const listener of this.listeners[currentPath]) {
listener(path(currentPathSplit, this.data), userPath);
listener(newValue, userPath);
}

@@ -145,6 +135,2 @@ }

set(userPath: string | Updater, fn: Updater | undefined) {
return this.update(userPath, fn);
}
get(userPath: string | undefined = undefined) {

@@ -161,1 +147,3 @@ if (typeof userPath === 'undefined' || userPath === '') {

}
export default { scanObject, match, wildcardToRegex, Store };

@@ -1254,179 +1254,97 @@ (function (global, factory) {

var wildstring_1 = createCommonjsModule(function (module) {
function wildcardToRegex(wildcard, delimeter = '.') {
return new RegExp('^' +
wildcard
.split('**')
.map((part) => {
return part
.split('*')
.map((smallPart) => smallPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.join(`[^\\${delimeter}]*`);
})
.join(`.*`) +
'$');
}
function match(first, second, delimeter = '.') {
return wildcardToRegex(first, delimeter).test(second);
}
function scanObject(obj, delimeter = '.') {
const api = {
get(wildcard) {
const wildcardSplit = prepareWildcardSplit(wildcard);
if (wildcardSplit.length === 0) {
return obj;
}
return handleObject(wildcardSplit, obj, 0, '');
}
};
function prepareWildcardSplit(wildcardSplit) {
if (typeof wildcardSplit === 'string') {
if (wildcardSplit === '') {
wildcardSplit = [];
}
else {
wildcardSplit = wildcardSplit.split(delimeter);
}
}
return wildcardSplit;
}
function isEnd(wildcardSplit, partIndex) {
return wildcardSplit.length - 1 <= partIndex;
}
function goFurther(wildcardSplit, currentObj, partIndex, currentPath, result) {
if (Array.isArray(currentObj)) {
handleArray(wildcardSplit, currentObj, partIndex, currentPath, result);
}
else if (currentObj.constructor.name === 'Object') {
handleObject(wildcardSplit, currentObj, partIndex, currentPath, result);
}
}
function handleArray(wildcardSplit, currentArr, partIndex, path, result = {}) {
const currentWildcardPath = wildcardSplit.slice(0, partIndex + 1).join(delimeter);
const end = isEnd(wildcardSplit, partIndex);
const fullWildcard = currentWildcardPath.indexOf('**') > -1;
const traverse = !end || fullWildcard;
let index = 0;
for (const item of currentArr) {
const currentPath = path === '' ? path + index : path + delimeter + index;
if (match(currentWildcardPath, currentPath)) {
if (end) {
result[currentPath] = item;
}
if (traverse) {
goFurther(wildcardSplit, item, partIndex + 1, currentPath, result);
}
}
else if (fullWildcard) {
goFurther(wildcardSplit, item, partIndex + 1, currentPath, result);
}
index++;
}
return result;
}
function handleObject(wildcardSplit, currentObj, partIndex, path, result = {}) {
const currentWildcardPath = wildcardSplit.slice(0, partIndex + 1).join(delimeter);
const end = isEnd(wildcardSplit, partIndex);
const fullWildcard = currentWildcardPath.indexOf('**') > -1;
const traverse = !end || fullWildcard;
for (const key in currentObj) {
const currentPath = path === '' ? path + key : path + delimeter + key;
if (match(currentWildcardPath, currentPath)) {
if (end) {
result[currentPath] = currentObj[key];
}
if (traverse) {
goFurther(wildcardSplit, currentObj[key], partIndex + 1, currentPath, result);
}
}
else if (fullWildcard) {
goFurther(wildcardSplit, currentObj[key], partIndex + 1, currentPath, result);
}
}
return result;
}
return api;
}
/**
* @namespace wildstring
* @property {string} wildcard the wildcard to use in your strings, defaults to '*'
* @property {boolean} caseSensitive whether matches should care about case, defaults to true
*/
var wildstring = {
wildcard: '*',
caseSensitive: true,
/**
* When a match doesn't continue to the end of the string, this function rolls back to try again with the rest of the string
* @memberof wildstring
* @access private
* @param {string[]} rollbackStrings The list of substrings that appeared prior to the current match
* @param {string[]} patternSubstrings The matching list of pattens that need to be matched before the current pattern
*/
checkRollbackStrings: function (rollbackStrings, patternSubstrings) {
for (var s = 0; s < rollbackStrings.length; ++s) {
var currentString = rollbackStrings[s].string; // starting with the rolled back string
var patternIndex = rollbackStrings[s].index;
while (patternIndex < patternSubstrings.length) {
if (currentString.indexOf(patternSubstrings[patternIndex]) === -1) {
break;
}
var testString = currentString.substr(1); //remove just one char to retest
rollbackStrings.push({ string: testString, index: patternIndex });
if (testString.indexOf(patternSubstrings[patternIndex]) === -1) {
rollbackStrings.pop();
}
currentString = currentString.substr(
currentString.indexOf(patternSubstrings[patternIndex]) + patternSubstrings[patternIndex].length
);
patternIndex++;
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
}
if (patternIndex >= patternSubstrings.length) {
if (patternSubstrings[patternSubstrings.length - 1] !== '' &&
currentString.length > 0) {
// not ending with a wildcard, we need to backtrack
break;
}
else {
return true;
}
}
}
}
return false;
},
/**
* Check if a string matches a pattern
* @memberof wildstring
* @param {string} pattern The pattern to match using the configured wildcard
* @param {string} string The string to test for a match
*/
match: function (pattern, string) {
// if there are no wildcards, must be exact
if (pattern.indexOf(wildstring.wildcard) === -1) {
return pattern === string;
}
if (!wildstring.caseSensitive) {
pattern = pattern.toLowerCase();
string = string.toLowerCase();
}
var patternSubstrings = pattern.split(wildstring.wildcard);
var patternIndex = 0;
var currentString = string;
// find pattern beginning
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
// if the pattern is just wildcards, it matches
if (patternIndex === pattern.length) {
return true;
}
}
if (patternIndex === 0 && string.indexOf(patternSubstrings[0]) !== 0) {
// not starting with a wildcard
return false;
}
var rollbackStrings = [];
while (patternIndex < patternSubstrings.length) {
if (currentString.indexOf(patternSubstrings[patternIndex]) === -1) {
return wildstring.checkRollbackStrings(rollbackStrings, patternSubstrings);
}
// create a queue of strings to roll back and try again if we fail later
var testString = currentString.substr(1); //remove just one char to retest
rollbackStrings.push({ string: testString, index: patternIndex });
if (testString.indexOf(patternSubstrings[patternIndex]) === -1) {
rollbackStrings.pop();
}
currentString = currentString.substr(
currentString.indexOf(patternSubstrings[patternIndex]) + patternSubstrings[patternIndex].length
);
patternIndex++;
while (patternSubstrings[patternIndex] === '') {
patternIndex++;
}
}
if (patternIndex >= patternSubstrings.length &&
patternSubstrings[patternSubstrings.length - 1] !== '' &&
currentString.length > 0) {
// not ending with a wildcard, we need to backtrack
if (currentString === string) { // this string doesn't even match a little
return false;
}
return wildstring.checkRollbackStrings(rollbackStrings, patternSubstrings);
}
return true;
},
/**
* Replace wildcards in a pattern with strings (string interpolation)
* @memberof wildstring
* @param {string} pattern The start string, using wildcards as placeholders
* @param {string|string[]} strings The string or strings to replace the wildcards in the pattern.
* If you pass a single string, it will replace all the wildcards with the string.
* If you pass an array of strings, they will replace the wildcards in order from left to right.
* @throws The number of items in the strings array (if you pass an array) must match the number of wildcards in the pattern string.
* @throws You need to pass both parameters
* @throws You need to pass the right types
*/
replace: function (pattern, strings) {
if (pattern === undefined || strings === undefined) {
throw new Error('wildstring.replace takes the pattern as one parameter and either a string or an array of strings as the second. You didn\'t pass enough parameters.');
}
if (typeof(strings) === typeof('')) {
return pattern.replace(wildstring.wildcard, strings);
}
if (!Array.isArray(strings) || typeof(pattern) !== typeof('')) {
throw new Error('wildstring.replace takes the pattern as one parameter and either a string or an array of strings as the second. Your parameter types are incorrect.');
}
if (pattern.indexOf(wildstring.wildcard) === -1) {
return pattern; // if there are no wildcards, just return the pattern
}
var patternSubstrings = pattern.split(wildstring.wildcard);
if (patternSubstrings.length - 1 !== strings.length) {
var message = 'There are a different number of wildcards than strings to replace them. You have ' +
wildstring.wildcard +' wildcards in "' + wildstring.wildcard + '" and ' + wildstring.wildcard +
' replacement strings.';
throw new Error(wildstring.replace(message, [ patternSubstrings.length - 1, pattern, strings.length ]));
}
var result = '';
for (var s = 0; s < strings.length; ++s) {
result += patternSubstrings[s] + strings[s];
}
return result;
}
};
{ module.exports = wildstring; }
if (typeof(angular) !== 'undefined') { angular.module('wildstring', []).factory('wildstring', function() { return wildstring; }); }
});
class Store {

@@ -1450,3 +1368,3 @@ constructor(data = {}, options = { delimeter: '.' }) {

if (this.isWildcard(first)) {
return wildstring_1.match(first, second);
return match(first, second, this.options.delimeter);
}

@@ -1479,5 +1397,2 @@ return false;

}
watchAll(userPaths, fn) {
return this.subscribeAll(userPaths, fn);
}
subscribe(userPath, fn, execute = true) {

@@ -1492,10 +1407,14 @@ if (typeof userPath === 'function') {

this.listeners[userPath].push(fn);
if (execute && !this.isWildcard(userPath)) {
const isWildcard = this.isWildcard(userPath);
if (execute && !isWildcard) {
fn(path(this.split(userPath), this.data), userPath);
}
if (isWildcard) {
const paths = scanObject(this.data, this.options.delimeter).get(userPath);
for (const path in paths) {
fn(paths[path], path);
}
}
return this.unsubscribe(fn);
}
watch(userPath, fn) {
return this.subscribe(userPath, fn);
}
unsubscribe(fn) {

@@ -1511,10 +1430,3 @@ return () => {

}
unwatch(fn) {
return this.unsubscribe(fn);
}
update(userPath, fn, filter = (path, key) => true) {
if (typeof userPath === 'function') {
fn = userPath;
userPath = '';
}
update(userPath, fn) {
const lens = lensPath(this.split(userPath));

@@ -1536,5 +1448,4 @@ let oldValue = fastCopy(view(lens, this.data));

if (this.match(currentPath, userPath)) {
let currentPathSplit = this.split(currentPath);
for (const listener of this.listeners[currentPath]) {
listener(path(currentPathSplit, this.data), userPath);
listener(newValue, userPath);
}

@@ -1545,5 +1456,2 @@ }

}
set(userPath, fn) {
return this.update(userPath, fn);
}
get(userPath = undefined) {

@@ -1559,5 +1467,6 @@ if (typeof userPath === 'undefined' || userPath === '') {

}
var index = { scanObject, match, wildcardToRegex, Store };
return Store;
return index;
}));
{
"name": "deep-state-observer",
"version": "1.0.1",
"version": "1.0.2",
"description": "Deep state observer is an state management library that will fire listeners only when specified object node (which also can be a wildcard) was changed.",

@@ -46,4 +46,3 @@ "main": "index.cjs.js",

"fast-copy": "^2.0.3",
"ramda": "^0.26.1",
"wildstring": "^1.0.9"
"ramda": "^0.26.1"
},

@@ -50,0 +49,0 @@ "devDependencies": {

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

const Store = require('../index.cjs.js');
const { Store, wildcardToRegex } = require('../index.cjs.js');
const R = require('ramda');

@@ -73,19 +73,167 @@

it('should match wildcards', () => {
const state = new Store({ one: { two: { three: { four: { five: 5 } } } } });
it('should match simple wildcards (object)', () => {
const state = new Store({
one: {
two: { three: { four: { five: 5 } } },
'2': { three: { four: { five: 5, six: 6 } } }
}
});
const paths = [];
const values = [];
state.subscribe('one.*.three', (value, path) => {
paths.push(path);
paths.push(path); // 2
values.push(value);
});
state.subscribe('one.**', (value, path) => {
paths.push(path);
});
state.subscribe('one.*.*.four.*', (value, path) => {
paths.push(path);
paths.push(path); // 3
values.push(value);
});
expect(paths.length).toEqual(0);
expect(paths.length).toEqual(5);
expect(values.length).toEqual(5);
expect(values[0]).toEqual({ four: { five: 5, six: 6 } });
expect(values[1]).toEqual({ four: { five: 5 } });
expect(values[2]).toEqual(5);
expect(values[3]).toEqual(6);
expect(values[4]).toEqual(5);
const fullPath = 'one.two.three.four.five';
state.update(fullPath, 'mod');
expect(paths).toEqual([fullPath, fullPath]);
expect(paths.length).toEqual(6);
expect(values.length).toEqual(6);
expect(values[5]).toEqual('mod');
});
it('should match advanced wildcards (object)', () => {
const state = new Store({
one: {
two: { three: { four: { five: 5 } } },
'2': { three: { four: { five: 5, six: 6 } } }
}
});
const paths = [];
const values = [];
state.subscribe('one.two.three.**', (value, path) => {
paths.push(path); // 2
values.push(value);
});
expect(paths.length).toEqual(2);
expect(values.length).toEqual(2);
expect(paths[0]).toEqual('one.two.three.four');
expect(paths[1]).toEqual('one.two.three.four.five');
expect(values[0]).toEqual({ five: 5 });
expect(values[1]).toEqual(5);
const fullPath = 'one.two.three.four.five';
state.update(fullPath, 'mod');
expect(paths.length).toEqual(3);
expect(values.length).toEqual(3);
expect(paths[2]).toEqual('one.two.three.four.five');
expect(values[2]).toEqual('mod');
});
it('should match simple wildcards (array)', () => {
const state = new Store({
one: [{ two: 2 }, { two: 22 }, { two: 222 }, { three: 3 }, [{ test: 'x' }]]
});
const paths = [];
const values = [];
state.subscribe('one.*.two', (value, path) => {
paths.push(path); // 3
values.push(value);
});
state.subscribe('one.*.*.test', (value, path) => {
paths.push(path); // 1
values.push(value);
});
state.subscribe('one.*.three', (value, path) => {
paths.push(path); // 1
values.push(value);
});
expect(paths.length).toEqual(5);
expect(values.length).toEqual(5);
expect(values[0]).toEqual(2);
expect(values[1]).toEqual(22);
expect(values[2]).toEqual(222);
expect(values[3]).toEqual('x');
expect(values[4]).toEqual(3);
const fullPath = 'one.0.two';
state.update(fullPath, 'mod');
expect(paths.length).toEqual(6);
expect(values.length).toEqual(6);
expect(values[5]).toEqual('mod');
});
it('should match advanced wildcards (array)', () => {
const state = new Store({
one: [{ two: 2 }, { two: 22 }, { two: 222 }, { three: 3 }, [{ test: 'x' }]]
});
const paths = [];
const values = [];
state.subscribe('one.**.two', (value, path) => {
paths.push(path); // 3
values.push(value);
});
state.subscribe('one.**.test', (value, path) => {
paths.push(path); // 1
values.push(value);
});
state.subscribe('**.three', (value, path) => {
paths.push(path); // 1
values.push(value);
});
expect(paths.length).toEqual(5);
expect(values.length).toEqual(5);
expect(values[0]).toEqual(2);
expect(values[1]).toEqual(22);
expect(values[2]).toEqual(222);
expect(values[3]).toEqual('x');
expect(values[4]).toEqual(3);
const fullPath = 'one.0.two';
state.update(fullPath, 'mod');
expect(paths.length).toEqual(6);
expect(values.length).toEqual(6);
expect(values[5]).toEqual('mod');
});
it('should match advanced wildcards mixed (array)', () => {
const state = new Store({
one: [{ two: 2 }, { two: 22 }, { two: 222 }, { three: { four: 4 } }, [{ test: 'x' }]]
});
const paths = [];
const values = [];
state.subscribe('one.**.tw*', (value, path) => {
paths.push(path); // 3
values.push(value);
});
state.subscribe('one.**.t*st', (value, path) => {
paths.push(path); // 1
values.push(value);
});
state.subscribe('**.three.*', (value, path) => {
paths.push(path); // 1
values.push(value);
});
expect(paths.length).toEqual(5);
expect(values.length).toEqual(5);
expect(values[0]).toEqual(2);
expect(values[1]).toEqual(22);
expect(values[2]).toEqual(222);
expect(values[3]).toEqual('x');
expect(values[4]).toEqual(4);
const fullPath = 'one.0.two';
state.update(fullPath, 'mod');
expect(paths.length).toEqual(6);
expect(values.length).toEqual(6);
expect(values[5]).toEqual('mod');
});
});
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