km-traversal
Version:
This utility provides powerful object traversal capabilities with pattern matching and transformation features.
494 lines • 40.8 kB
JavaScript
import { jsonrepair } from '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(jsonrepair(content)) };
}
catch {
throw new Error(`Invalid object condition: ${content}`);
}
}
if (content.startsWith('[')) {
try {
return { type: 'array-cond', conditions: JSON.parse(jsonrepair(content)) };
}
catch {
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 = {
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),
};
},
};
};
export default { traverseIn, adapter, defaultConditions: defaultConditions.conditions };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL29iamVjdC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBbUd4Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBQ0gsU0FBUyxZQUFZLENBQUMsT0FBZSxFQUFFLE9BQXlDO0lBQzlFLE1BQU0sS0FBSyxHQUFrQixFQUFFLENBQUM7SUFDaEMsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO0lBQ2pCLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztJQUNkLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztJQUVyQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUN2QyxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEIsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUFFO1lBQ3hELFFBQVEsR0FBRyxDQUFDLFFBQVEsQ0FBQztTQUN0QjtRQUVELElBQUksQ0FBQyxRQUFRLEVBQUU7WUFDYixJQUFJLElBQUksS0FBSyxHQUFHO2dCQUFFLEtBQUssRUFBRSxDQUFDO1lBQzFCLElBQUksSUFBSSxLQUFLLEdBQUc7Z0JBQUUsS0FBSyxFQUFFLENBQUM7WUFFMUIsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLEtBQUssS0FBSyxDQUFDLEVBQUU7Z0JBQy9CLElBQUksT0FBTztvQkFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDdEQsT0FBTyxHQUFHLEVBQUUsQ0FB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