mono/packages/kbot/dist-in/async-iterator.js
2025-04-07 16:12:51 +02:00

184 lines
17 KiB
JavaScript

import { JSONPath } from 'jsonpath-plus';
import pThrottle from 'p-throttle';
import pMap from 'p-map';
import { deepClone } from "@polymech/core/objects";
export const DEFAULT_NETWORK_OPTIONS = {
throttleDelay: 1000,
concurrentTasks: 1,
maxRetries: 3,
retryDelay: 2000
};
// Sleep utility for retry mechanism
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
export const isNumber = async (input) => (/^-?\d+(\.\d+)?$/.test(input));
export const isBoolean = async (input) => /^(true|false)$/i.test(input);
export const isValidString = async (input) => input.trim() !== '';
export const testFilters = (filters) => {
return async (input, path) => {
for (const filter of filters) {
if (await filter(input)) {
return false;
}
}
return true;
};
};
export const defaultFilters = (filters = []) => [
isNumber, isBoolean, isValidString, ...filters
];
export async function transformObject(obj, transform, path, networkOptions, errorCallback, testCallback, onTransform, // Pass callbacks down
onTransformed, // Pass callbacks down
options // Pass options context if available
) {
const paths = JSONPath({ path, json: obj, resultType: 'pointer' });
await pMap(paths, async (jsonPointer) => {
const keys = jsonPointer.slice(1).split('/');
await transformPath(obj, keys, transform, networkOptions, jsonPointer, errorCallback, testCallback, onTransform, // Pass callbacks down
onTransformed, // Pass callbacks down
options // Pass options context if available
);
}, { concurrency: networkOptions.concurrentTasks });
}
export async function transformPath(obj, keys, transform, networkOptions, currentPath, // Changed from jsonPointer to represent the logical path
errorCallback, testCallback, onTransform, // Receive callbacks
onTransformed, // Receive callbacks
options // Pass options context if available
) {
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
if (current[keys[i]] === undefined || current[keys[i]] === null) {
return;
}
current = current[keys[i]];
}
const lastKey = keys[keys.length - 1];
const throttle = pThrottle({
limit: 1,
interval: networkOptions.throttleDelay,
});
if (typeof lastKey === 'string' && lastKey !== '') {
// Get the value pointed to by the keys
const value = current[lastKey];
// Check if the value exists before proceeding
if (value !== undefined && value !== null) {
const fullJsonPath = `${currentPath}/${lastKey}`; // Construct full path
// Check if the filter callback allows transformation
// Note: The default filter blocks numbers/booleans. Arrays/Objects depend on the filter implementation.
// The example uses `async () => true`, so arrays should pass.
if (await testCallback(value, fullJsonPath)) {
// Add retry mechanism with exponential backoff
let attempts = 0;
let success = false;
let lastError;
let valueToTransform = value;
// Call onTransform before transformation
try {
valueToTransform = await onTransform(fullJsonPath, valueToTransform, options);
}
catch (error) {
console.error(`Error in onTransform callback for path ${fullJsonPath}:`, error);
// Decide if you want to proceed with the original value or stop
}
while (attempts < networkOptions.maxRetries && !success) {
try {
let transformedValue = await throttle(transform)(valueToTransform, fullJsonPath);
// Call onTransformed after successful transformation
try {
transformedValue = await onTransformed(fullJsonPath, transformedValue, options);
}
catch (error) {
console.error(`Error in onTransformed callback for path ${fullJsonPath}:`, error);
// Decide if you want to proceed with the transformed value or stop/modify
}
current[lastKey] = transformedValue; // Assign potentially modified transformed value
success = true;
}
catch (error) {
lastError = error;
attempts++;
if (attempts < networkOptions.maxRetries) {
// Exponential backoff: retry delay increases with each attempt
const backoffDelay = networkOptions.retryDelay * Math.pow(2, attempts - 1);
await sleep(backoffDelay);
}
}
}
if (!success) {
errorCallback(currentPath, lastKey, lastError); // Use currentPath (logical path)
}
}
}
}
}
export const defaultError = (path, value, error) => {
console.error(`Error at path: ${path}, value: ${value}, error: ${error}`);
};
// Default no-op implementations for the new callbacks
const defaultOnTransform = async (_, value) => value;
const defaultOnTransformed = async (_, transformedValue) => transformedValue;
export async function transformObjectWithOptions(obj, transform, options) {
const { jsonPath, targetPath = null, network = {}, errorCallback = defaultError, filterCallback = testFilters(defaultFilters()), onTransform = defaultOnTransform, // Use default if not provided
onTransformed = defaultOnTransformed, // Use default if not provided
kbotOptions // Destructure kbot options
} = options;
const networkOptions = {
...DEFAULT_NETWORK_OPTIONS,
...network
};
// If targetPath is null, directly transform the object at jsonPath
if (!targetPath) {
return transformObject(obj, transform, jsonPath, networkOptions, errorCallback, filterCallback, onTransform, // Pass down
onTransformed, // Pass down
kbotOptions // Pass down kbot options
);
}
// For targetPath case, create a deep clone and transform it
const dataCopy = deepClone(obj);
// Transform the copy
await transformObject(dataCopy, transform, jsonPath, networkOptions, errorCallback, filterCallback, onTransform, // Pass down
onTransformed, // Pass down
kbotOptions // Pass down kbot options
);
// Get paths from original object
const paths = JSONPath({ path: jsonPath, json: obj, resultType: 'pointer' });
// Apply transformed values to original object with targetPath
for (const p of paths) {
const keys = p.slice(1).split('/');
// Get source path for transformation
const sourceKeys = p.slice(1).split('/');
// Get source value from matching path in processed data
let sourceValue = dataCopy;
for (const key of sourceKeys) {
if (key === '')
continue;
if (sourceValue === undefined || sourceValue === null)
break;
sourceValue = sourceValue[key];
}
// Set value to target path in original object
const parentKeys = keys.slice(0, -1);
let target = obj;
for (const key of parentKeys) {
if (key === '')
continue;
if (target === undefined || target === null)
break;
target = target[key];
}
if (target && sourceValue !== undefined) {
target[targetPath] = sourceValue;
}
}
}
export const defaultOptions = (options = {}) => {
const network = { ...DEFAULT_NETWORK_OPTIONS, ...options.network };
return {
transform: options.transform,
path: options.path || '$[*][0,1,2]',
network,
errorCallback: options.errorCallback || defaultError,
filterCallback: options.filterCallback || testFilters(defaultFilters()),
targetPath: options.targetPath
};
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXN5bmMtaXRlcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvYXN5bmMtaXRlcmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQTtBQUN4QyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUE7QUFDbEMsT0FBTyxJQUFJLE1BQU0sT0FBTyxDQUFBO0FBQ3hCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQTtBQWlCbEQsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQThCO0lBQzlELGFBQWEsRUFBRSxJQUFJO0lBQ25CLGVBQWUsRUFBRSxDQUFDO0lBQ2xCLFVBQVUsRUFBRSxDQUFDO0lBQ2IsVUFBVSxFQUFFLElBQUk7Q0FDbkIsQ0FBQztBQW1CRixvQ0FBb0M7QUFDcEMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxFQUFVLEVBQUUsRUFBRSxDQUFDLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBRTlFLE1BQU0sQ0FBQyxNQUFNLFFBQVEsR0FBVyxLQUFLLEVBQUUsS0FBYSxFQUFFLEVBQUUsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO0FBQ3hGLE1BQU0sQ0FBQyxNQUFNLFNBQVMsR0FBVyxLQUFLLEVBQUUsS0FBYSxFQUFFLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7QUFDdkYsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFXLEtBQUssRUFBRSxLQUFhLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUE7QUFFakYsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLENBQUMsT0FBaUIsRUFBa0IsRUFBRTtJQUM3RCxPQUFPLEtBQUssRUFB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