besper-frontend-site-dev-0935
Version:
Professional B-esper Frontend Site - Site-wide integration toolkit for full website bot deployment
125 lines (108 loc) • 3.15 kB
text/typescript
// General helper utility functions
export function generateId(prefix: string = 'besper'): string {
return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
}
export function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
export function deepClone<T>(obj: T): T {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj.getTime()) as unknown as T;
if (obj instanceof Array)
return obj.map(item => deepClone(item)) as unknown as T;
if (typeof obj === 'object') {
const clonedObj = {} as T;
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clonedObj[key] = deepClone(obj[key]);
}
}
return clonedObj;
}
return obj;
}
export function mergeDeep<T extends Record<string, any>>(
target: T,
source: Partial<T>
): T {
const result = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key)) {
const sourceValue = source[key];
const targetValue = result[key];
if (isObject(sourceValue) && isObject(targetValue)) {
result[key] = mergeDeep(targetValue, sourceValue);
} else {
result[key] = sourceValue as T[Extract<keyof T, string>];
}
}
}
return result;
}
function isObject(item: any): item is Record<string, any> {
return item && typeof item === 'object' && !Array.isArray(item);
}
export function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
const result = {} as Pick<T, K>;
keys.forEach(key => {
if (key in obj) {
result[key] = obj[key];
}
});
return result;
}
export function omit<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
const result = { ...obj };
keys.forEach(key => {
delete result[key];
});
return result;
}
export function isEmpty(value: any): boolean {
if (value == null) return true;
if (Array.isArray(value) || typeof value === 'string')
return value.length === 0;
if (typeof value === 'object') return Object.keys(value).length === 0;
return false;
}
export function retry<T>(
fn: () => Promise<T>,
maxAttempts: number = 3,
delay: number = 1000
): Promise<T> {
return new Promise((resolve, reject) => {
let attempts = 0;
const attempt = async () => {
try {
const result = await fn();
resolve(result);
} catch (error) {
attempts++;
if (attempts >= maxAttempts) {
reject(error);
} else {
setTimeout(attempt, delay * attempts);
}
}
};
attempt();
});
}
export function createUrlWithParams(
baseUrl: string,
params: Record<string, string | number | boolean>
): string {
const url = new URL(baseUrl);
Object.entries(params).forEach(([key, value]) => {
url.searchParams.set(key, String(value));
});
return url.toString();
}
export function parseQueryString(queryString: string): Record<string, string> {
const params = new URLSearchParams(queryString);
const result: Record<string, string> = {};
params.forEach((value, key) => {
result[key] = value;
});
return result;
}