deep-state-observer
Advanced tools
Comparing version 1.0.1 to 1.0.2
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; |
305
index.js
@@ -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; |
46
index.ts
@@ -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 }; |
305
index.umd.js
@@ -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'); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2
11
4695
158690
- Removedwildstring@^1.0.9
- Removedwildstring@1.0.9(transitive)