@dataql/node
Version:
DataQL core SDK for unified data management with MongoDB and GraphQL - Production Multi-Cloud Ready
218 lines (217 loc) • 6.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginUtilsImpl = void 0;
const uuid_1 = require("uuid");
/**
* Utility functions for DataQL plugins
*
* Provides common helper functions that plugins can use for
* configuration validation, data manipulation, and other tasks.
*/
class PluginUtilsImpl {
/**
* Generate a unique ID
*/
generateId() {
return (0, uuid_1.v4)();
}
/**
* Validate configuration against a schema
*/
validateConfig(config, schema) {
try {
// Simple validation - in a real implementation you might use
// a library like Joi, Yup, or JSON Schema validator
return this.validateObjectAgainstSchema(config, schema);
}
catch (error) {
throw new Error(`Configuration validation failed: ${error.message}`);
}
}
/**
* Merge configurations with deep merge
*/
mergeConfig(base, override) {
return this.deepMerge(base, override);
}
/**
* Deep clone an object
*/
clone(obj) {
if (obj === null || typeof obj !== "object") {
return obj;
}
if (obj instanceof Date) {
return new Date(obj.getTime());
}
if (obj instanceof Array) {
return obj.map((item) => this.clone(item));
}
if (typeof obj === "object") {
const cloned = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
cloned[key] = this.clone(obj[key]);
}
}
return cloned;
}
return obj;
}
/**
* Check if object is empty
*/
isEmpty(obj) {
if (obj == null)
return true;
if (typeof obj === "string" || Array.isArray(obj))
return obj.length === 0;
if (typeof obj === "object")
return Object.keys(obj).length === 0;
return false;
}
/**
* Retry operation with backoff
*/
async retry(fn, options = { attempts: 3, delay: 1000 }) {
const { attempts, delay, backoff = "linear" } = options;
let lastError;
for (let attempt = 1; attempt <= attempts; attempt++) {
try {
return await fn();
}
catch (error) {
lastError = error;
if (attempt === attempts) {
throw error;
}
// Calculate delay based on backoff strategy
let currentDelay = delay;
if (backoff === "exponential") {
currentDelay = delay * Math.pow(2, attempt - 1);
}
await this.sleep(currentDelay);
}
}
throw lastError;
}
/**
* Sleep for specified milliseconds
*/
async sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Debounce a function
*/
debounce(func, wait) {
let timeout;
return (...args) => {
const later = () => {
timeout = undefined;
func(...args);
};
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(later, wait);
};
}
/**
* Throttle a function
*/
throttle(func, wait) {
let lastTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastTime >= wait) {
lastTime = now;
func(...args);
}
};
}
/**
* Get nested property value from object
*/
get(obj, path, defaultValue) {
const keys = path.split(".");
let current = obj;
for (const key of keys) {
if (current == null || typeof current !== "object") {
return defaultValue;
}
current = current[key];
}
return current !== undefined ? current : defaultValue;
}
/**
* Set nested property value in object
*/
set(obj, path, value) {
const keys = path.split(".");
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (!(key in current) || typeof current[key] !== "object") {
current[key] = {};
}
current = current[key];
}
current[keys[keys.length - 1]] = value;
}
/**
* Private: Deep merge two objects
*/
deepMerge(target, source) {
if (source == null || typeof source !== "object") {
return source;
}
if (target == null || typeof target !== "object") {
return source;
}
const result = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === "object" && !Array.isArray(source[key])) {
result[key] = this.deepMerge(result[key], source[key]);
}
else {
result[key] = source[key];
}
}
}
return result;
}
/**
* Private: Simple schema validation
*/
validateObjectAgainstSchema(obj, schema) {
if (schema == null)
return true;
for (const key in schema) {
if (schema.hasOwnProperty(key)) {
const schemaValue = schema[key];
const objValue = obj[key];
// Check required fields
if (schemaValue.required &&
(objValue === undefined || objValue === null)) {
throw new Error(`Required field missing: ${key}`);
}
// Check types
if (objValue !== undefined && schemaValue.type) {
const expectedType = schemaValue.type;
const actualType = typeof objValue;
if (expectedType !== actualType) {
throw new Error(`Type mismatch for field ${key}: expected ${expectedType}, got ${actualType}`);
}
}
// Check nested objects
if (schemaValue.properties && typeof objValue === "object") {
this.validateObjectAgainstSchema(objValue, schemaValue.properties);
}
}
}
return true;
}
}
exports.PluginUtilsImpl = PluginUtilsImpl;