km-traversal
Version:
This utility provides powerful object traversal capabilities with pattern matching and transformation features.
491 lines • 40.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const jsonrepair_1 = require("jsonrepair");
/**
* Parses pattern string into executable traversal steps
* @param pattern - Traversal pattern string
* @returns Array of PatternStep objects
*
* Pattern Syntax:
* - Properties: 'user'
* - Single-star: '(*)' , shortcut: '*'
* - Double-star: '(**)' , '(*2*)' , shortcut: '*2*' , '**'
* - Single-key: '("id")' , (id)
* - Multi-key: '("id","name")' , (id,name)
* - Object condition: '({"value.startsWith"."a"})' , '({value.startsWith:"a"})'
* - Array condition: '([{"value.>":5},{"value.<":10}])' , ([{value.>:5},{value.<:10}])
*
* Example: 'users.(*).contacts.(**).email'
* Example: `users.(0,"3",'5').contacts.(**).email`
* Example: 'users.(*).(contacts).(**).email'
* Example: 'users.(*).('contacts',info,"meta").(**).email'
* Example: 'users.(*).("contacts").(**).(email,password,phone)'
* Example: 'users.(*).("contacts").(**).({key.equalWith:'phone',value:startsWith:"+98"})'
* Example: 'users.(*).("contacts").(**).([{key.equalWith:'phone',value:startsWith:"+98"},{key.equalWith:'phone',value:startsWith:"+92"}])'
*/
function parsePattern(pattern, options) {
const steps = [];
let current = '';
let depth = 0;
let inQuotes = false;
for (let i = 0; i < pattern.length; i++) {
const char = pattern[i];
if (char === '"' && (i === 0 || pattern[i - 1] !== '\\')) {
inQuotes = !inQuotes;
}
if (!inQuotes) {
if (char === '(')
depth++;
if (char === ')')
depth--;
if (char === '.' && depth === 0) {
if (current)
steps.push(createStep(current, options));
current = '';
continue;
}
}
current += char;
}
if (current)
steps.push(createStep(current, options));
return steps;
}
const isInStringScope = (value) => {
const isInSingleQute = value.startsWith('"') && value.endsWith('"');
const isInDoubleQute = value.startsWith("'") && value.endsWith("'");
return { isInDoubleQute, isInSingleQute };
};
/**
* Creates a PatternStep from tokenized pattern segment
* @param token - Segment of pattern string
* @returns Parsed PatternStep
*/
function createStep(token, options) {
if (token.startsWith('(') && token.endsWith(')')) {
const content = token.substring(1, token.length - 1).trim();
if (content === '*')
return { type: 'single-star' };
const regxOfNumberBeforeDubble = /^(\d*)\*\*$/;
const regxOfNumberBetweenDubble = /^\*(\d*)\*$/;
const doubleStarMatch = content.match(regxOfNumberBetweenDubble);
if (doubleStarMatch) {
return doubleStarMatch[1]
? { type: 'double-star', depth: parseInt(doubleStarMatch[1]) }
: { type: 'double-star' };
}
if (content.startsWith('{')) {
try {
return { type: 'object-cond', conditions: JSON.parse((0, jsonrepair_1.jsonrepair)(content)) };
}
catch (_a) {
throw new Error(`Invalid object condition: ${content}`);
}
}
if (content.startsWith('[')) {
try {
return { type: 'array-cond', conditions: JSON.parse((0, jsonrepair_1.jsonrepair)(content)) };
}
catch (_b) {
throw new Error(`Invalid array condition: ${content}`);
}
}
if (!content.includes(',') && !content.startsWith('[') && !content.startsWith('{')) {
let stringScope = isInStringScope(content);
let repairedContent = content;
if (stringScope.isInDoubleQute) {
repairedContent = content;
}
else if (stringScope.isInSingleQute) {
repairedContent = content.replace("'", '"');
}
else if (stringScope.isInDoubleQute == false && stringScope.isInSingleQute == false) {
repairedContent = `"${content}"`;
}
else {
repairedContent = content.replace("'", '"');
}
return { type: 'single-key', key: repairedContent.slice(1, -1) };
}
if (content.includes(',') &&
!content.startsWith('[') &&
!content.startsWith('{')
// &&
// content.split(',').every((part) => part.trim().startsWith('"') && part.trim().endsWith('"'))
) {
const repairedContent = content
.split(',')
.map((part) => {
const trimedPart = part.trim();
const stringScope = isInStringScope(trimedPart);
if (stringScope.isInDoubleQute) {
return part;
}
else if (stringScope.isInSingleQute) {
return part.replace("'", '"');
}
else if (stringScope.isInDoubleQute == false && stringScope.isInSingleQute == false) {
return `"${part}"`;
}
else {
return part.replace("'", '"');
}
})
.join(',');
const keys = repairedContent.split(',').map((s) => s.trim().slice(1, -1));
return { type: 'multi-key', keys };
}
throw new Error(`Unrecognized pattern token: ${token}`);
}
if (options.shortcuts.singleStar == true && token.trim() === '*') {
const repairedToken = `(${token})`;
return createStep(repairedToken, options);
}
if (options.shortcuts.doubleStar == true && token.trim() === '**') {
const repairedToken = `(${token})`;
return createStep(repairedToken, options);
}
if (options.shortcuts.braketScope && token.trim().startsWith('[') && token.trim().endsWith(']')) {
const repairedToken = token.trim().replace('[', '(').replace(']', ')');
return createStep(repairedToken, options);
}
return { type: 'property', name: token };
}
/**
* Evaluates a condition using injected condition functions
* @param cond - Condition string (e.g., 'value.startsWith')
* @param condValue - Value to compare against
* @param key - Current key
* @param value - Current value
* @param injectedConditions - Custom condition functions
* @returns Boolean evaluation result
*
* Condition Syntax:
* - 'key.conditionName' - Apply to key (in default 'conditionName' === 'key.conditionName')
* - '!key.conditionName' - Negate condition Apply to key
* - 'value.conditionName' - Apply to value
* - '!value.conditionName' - Negate condition Apply to value
* - '!conditionName' - Negate condition (in default '!conditionName' === '!key.conditionName')
*/
function evaluateCondition(cond, condValue, key, value, injectedConditions = []) {
const [prefix, conditionName] = cond.split('.');
const negate = prefix.startsWith('!');
const cleanConditionName = conditionName == undefined ? prefix : conditionName;
const condition = injectedConditions.find((c) => c.name === cleanConditionName);
if (!condition)
throw new Error(`Condition not found: ${cleanConditionName}`);
const target = prefix.endsWith('value') ? value : key;
const result = condition.action(key, value, target, condValue);
return negate ? !result : result;
}
const makeConditions = (conditions) => {
return {
conditions,
names: conditions.map((i) => {
return i.name;
}),
};
};
const defaultConditions = makeConditions([
// String operations
{
name: 'startsWith',
action: (_, __, target, conditionValue) => typeof target === 'string' && target.startsWith(conditionValue),
},
{
name: 'endsWith',
action: (_, __, target, conditionValue) => typeof target === 'string' && target.endsWith(conditionValue),
},
{
name: 'includes',
action: (_, __, target, conditionValue) => typeof target === 'string' && target.includes(conditionValue),
},
{
name: 'matches',
action: (_, __, target, conditionValue) => typeof target === 'string' && new RegExp(conditionValue).test(target),
},
// Numeric comparisons
{
name: 'greaterThan',
action: (_, __, target, conditionValue) => typeof target === 'number' && target > conditionValue,
},
{
name: '>',
action: (_, __, target, conditionValue) => typeof target === 'number' && target > conditionValue,
},
{
name: 'lessThan',
action: (_, __, target, conditionValue) => typeof target === 'number' && target < conditionValue,
},
{
name: '<',
action: (_, __, target, conditionValue) => typeof target === 'number' && target < conditionValue,
},
{
name: 'between',
action: (_, __, target, conditionValue) => typeof target === 'number' && target >= conditionValue[0] && target <= conditionValue[1],
},
// Equality checks
{
name: 'equalWith',
action: (_, __, target, conditionValue) => target === conditionValue,
},
{
name: 'notEqual',
action: (_, __, target, conditionValue) => target !== conditionValue,
},
// Type checking
{
name: 'isString',
action: (_, __, target) => typeof target === 'string',
},
{
name: 'isNumber',
action: (_, __, target) => typeof target === 'number',
},
{
name: 'isArray',
action: (_, __, target) => Array.isArray(target),
},
{
name: 'isObject',
action: (_, __, target) => typeof target === 'object' && !Array.isArray(target) && target !== null,
},
// Array operations
{
name: 'arrayIncludes',
action: (_, __, target, conditionValue) => Array.isArray(target) && target.includes(conditionValue),
},
{
name: 'length',
action: (_, __, target, conditionValue) => Array.isArray(target) && target.length === conditionValue,
},
]);
/**
* Main traversal function for complex data structures
* @param data - Input data to traverse
* @param options - Configuration options
* @param patterns - Array of pattern strings
* @param callbacks - Corresponding callbacks for each pattern
*
* Features:
* - Multiple pattern/callback support
* - Deep nested traversal
* - In-memory data modification
* - Conditional filtering
*
* Usage:
* customEach(data, options, patterns, callbacks)
*/
const traverseIn = (data, options, patterns, callbacks) => {
const defaultShortcuts = Object.assign({ singleStar: true, doubleStar: true, braketScope: false }, options.shortcuts);
if (patterns.length !== callbacks.length) {
throw new Error('Patterns and callbacks must have the same length');
}
patterns.forEach((_pattern, index) => {
const setCondName = (v) => v;
const pattern = typeof _pattern == 'function'
? _pattern({ setCondName })
: typeof _pattern == 'string'
? _pattern
: _pattern.join('.');
const steps = parsePattern(pattern, { shortcuts: defaultShortcuts });
const callback = callbacks[index];
let currentNodes = [
{
node: data,
parent: null,
key: null,
path: [],
},
];
for (const step of steps) {
const nextNodes = [];
for (const { node, parent, key, path } of currentNodes) {
if (node === null || typeof node !== 'object')
continue;
switch (step.type) {
case 'property':
if (typeof node === 'object' && step.name in node) {
nextNodes.push({
node: node[step.name],
parent: node,
key: step.name,
path: [...path, step.name],
});
}
break;
case 'single-star':
if (Array.isArray(node)) {
node.forEach((item, i) => nextNodes.push({
node: item,
parent: node,
key: i,
path: [...path, i],
}));
}
else if (typeof node === 'object') {
Object.entries(node).forEach(([k, v]) => nextNodes.push({
node: v,
parent: node,
key: k,
path: [...path, k],
}));
}
break;
case 'double-star':
const queue = [{ node, parent, key, path, depth: 0 }];
while (queue.length > 0) {
const { node: curr, parent: p, key: k, path: pth, depth: d } = queue.shift();
nextNodes.push({
node: curr,
parent: p,
key: k,
path: pth,
});
if (step.depth !== undefined && d >= step.depth)
continue;
if (curr && typeof curr === 'object') {
if (Array.isArray(curr)) {
curr.forEach((item, i) => queue.push({
node: item,
parent: curr,
key: i,
path: [...pth, i],
depth: d + 1,
}));
}
else {
Object.entries(curr).forEach(([childKey, childValue]) => queue.push({
node: childValue,
parent: curr,
key: childKey,
path: [...pth, childKey],
depth: d + 1,
}));
}
}
}
break;
case 'single-key':
if (typeof node === 'object' && step.key in node) {
nextNodes.push({
node: node[step.key],
parent: node,
key: step.key,
path: [...path, step.key],
});
}
break;
case 'multi-key':
step.keys.forEach((k) => {
if (typeof node === 'object' && k in node) {
nextNodes.push({
node: node[k],
parent: node,
key: k,
path: [...path, k],
});
}
});
break;
case 'object-cond':
if (typeof node === 'object') {
Object.entries(node).forEach(([childKey, childValue]) => {
const satisfies = Object.entries(step.conditions).every(([cond, condValue]) => evaluateCondition(cond, condValue, childKey, childValue, options.injectedConditions));
if (satisfies) {
nextNodes.push({
node: childValue,
parent: node,
key: childKey,
path: [...path, childKey],
});
}
});
}
break;
case 'array-cond':
if (typeof node === 'object') {
Object.entries(node).forEach(([childKey, childValue]) => {
const satisfies = step.conditions.some((conditionSet) => Object.entries(conditionSet).every(([cond, condValue]) => evaluateCondition(cond, condValue, childKey, childValue, options.injectedConditions)));
if (satisfies) {
nextNodes.push({
node: childValue,
parent: node,
key: childKey,
path: [...path, childKey],
});
}
});
}
break;
}
}
currentNodes = nextNodes;
}
currentNodes.forEach(({ node, parent, key, path }) => {
if (key === null)
return; // Skip root node
callback({
key: key,
value: node,
objectPath: path,
parent,
setKey: (newKey) => {
if (parent && !Array.isArray(parent)) {
parent[newKey] = node;
delete parent[key];
}
else {
throw new Error('Cannot rename array elements or root node');
}
},
remove: () => {
if (parent && !Array.isArray(parent)) {
delete parent[key];
}
else {
throw new Error('Cannot rename array elements or root node');
}
},
removeNears: () => {
if (parent && !Array.isArray(parent)) {
const nears = Object.keys(parent).filter((item) => {
return item !== key;
});
nears.forEach((nearKey) => {
delete parent[nearKey];
});
}
else {
throw new Error('Cannot rename array elements or root node');
}
},
setValue: (newValue) => {
if (parent && key !== null) {
if (Array.isArray(parent)) {
parent[key] = newValue;
}
else {
parent[key] = newValue;
}
}
else {
throw new Error('Cannot set value on root node');
}
},
});
});
});
};
const adapter = () => {
return {
register: (conditions) => {
return {
traverseIn: (data, patterns, callbacks) => traverseIn(data, { injectedConditions: conditions }, patterns, callbacks),
};
},
};
};
exports.default = { traverseIn, adapter, defaultConditions: defaultConditions.conditions };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL29iamVjdC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLDJDQUF3QztBQW1HeEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILFNBQVMsWUFBWSxDQUFDLE9BQWUsRUFBRSxPQUF5QztJQUM5RSxNQUFNLEtBQUssR0FBa0IsRUFBRSxDQUFDO0lBQ2hDLElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQztJQUNqQixJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDZCxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFFckIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDdkMsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXhCLElBQUksSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsRUFBRTtZQUN4RCxRQUFRLEdBQUcsQ0FBQyxRQUFRLENBQUM7U0FDdEI7UUFFRCxJQUFJLENBQUMsUUFBUSxFQUFFO1lBQ2IsSUFBSSxJQUFJLEtBQUssR0FBRztnQkFBRSxLQUFLLEVBQUUsQ0FBQztZQUMxQixJQUFJLElBQUksS0FBSyxHQUFHO2dCQUFFLEtBQUssRUFBRSxDQUFDO1lBRTFCLElBQUksSUFBSSxLQUFLLEdBQUcsSUFBSSxLQUFLLEtBQUssQ0FBQyxFQUFFO2dCQUMvQixJQUFJLE9BQU87b0JBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQ3RELE9BQU8sR0FBRyxFQUFFLENBQUM7Z0JBQ2IsU0FBUzthQUNWO1NBQ0Y7UUFF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