object/asyncObject.ts

import { ReduceObjectCallbackType, EachObjectCallbackType, filterObjectF, eachObjectF, takeObjectF } from "./object";
import { CheckPromiseReturnType,
  CheckObjectType, CheckPromiseObjectType } from "../types";
import { reduceObjectF, mapObjectF } from "./object";
import { ObjectInterface } from "@daybrush/utils";
import { exec } from "../utils";

/**
 * @namespace asyncObject
 */
/**
 * @memberof asyncObject
 * @typedef
 */
export type ReduceAsyncObjectCallbackType<T, U extends ObjectInterface<any>> =
  ReduceObjectCallbackType<T, CheckPromiseObjectType<U>, U>;

/**
 * @memberof asyncObject
 * @typedef
 */
export type EachAsyncObjectCallbackType<T extends ObjectInterface<any>, U> =
  EachObjectCallbackType<CheckPromiseObjectType<T>, U>;

/**
 * @memberof asyncObject
 * @typedef
 */
export type AsyncObjectReturnType<T extends ObjectInterface<any>, U> =
  CheckPromiseReturnType<CheckObjectType<T>, U>;

export function syncObject<T extends ObjectInterface<any>>(obj: T):
AsyncObjectReturnType<T, ObjectInterface<CheckPromiseObjectType<T>>>;
/**
 * @memberof asyncObject
 * @example
// {a: 1, b: 2, c: 3 , d: 4}
const obj1: ObjectInterface<number> = syncObject({
    a: 1,
    b: 2,
    c: 3,
    d: 4,
});
// Promise => {a: 1, b: 2, c: 3 , d: 4}
const obj2: Promise<ObjectInterface<number>> = syncObject({
    a: 1,
    b: Promise.resolve(2),
    c: 3,
    d: 4,
});
 */
export function syncObject<T extends ObjectInterface<any>>(obj: T) {
  return takeObjectF(Infinity, obj);
}

/**
 * @memberof asyncObject
 */
export function reduceAsyncObjectF<T, U extends ObjectInterface<any>>(
  callbackFn: ReduceAsyncObjectCallbackType<T, U>,
  initial: T,
  iterator: U,
): AsyncObjectReturnType<U, T>;
/**
 * @memberof asyncObject
 */
export function reduceAsyncObjectF<T, U extends ObjectInterface<any>>(
  callbackFn: ReduceAsyncObjectCallbackType<T, U>,
  initial: T,
  obj: U): T | Promise<T> {
  return exec(obj2 => reduceObjectF(callbackFn, initial, obj2), syncObject(obj));
}

export function eachAsyncObjectF<T extends ObjectInterface<any>, U>(
  callbackFn: EachAsyncObjectCallbackType<T, void>, obj: T):
  AsyncObjectReturnType<T, ObjectInterface<CheckPromiseObjectType<T>>>;
/**
 * @memberof asyncObject
 */
export function eachAsyncObjectF<T extends ObjectInterface<any>>(
  callbackFn: EachAsyncObjectCallbackType<T, void>, obj: T) {
  return exec(obj2 => eachObjectF(callbackFn, obj2), syncObject(obj));
}

export function mapAsyncObjectF<T extends ObjectInterface<any>, U>(
  callbackFn: EachAsyncObjectCallbackType<T, U>, obj: T):
  AsyncObjectReturnType<T, U[]>;
/**
 * @memberof asyncObject
 */
export function mapAsyncObjectF<T extends ObjectInterface<any>, U>(
  callbackFn: EachAsyncObjectCallbackType<T, U>, obj: T) {
  return exec(obj2 => mapObjectF(callbackFn, obj2), syncObject(obj));
}

export function filterAsyncObjectF<T extends ObjectInterface<any>>(
  callbackFn: EachAsyncObjectCallbackType<T, boolean>, obj: T):
  AsyncObjectReturnType<T, ObjectInterface<CheckPromiseObjectType<T>>>;
/**
 * @memberof asyncObject
 */
export function filterAsyncObjectF<T extends ObjectInterface<any>>(
  callbackFn: EachAsyncObjectCallbackType<T, boolean>, obj: T) {
  return exec(obj2 => filterObjectF(callbackFn, obj2), syncObject(obj));
}