{"version":3,"file":"throttle.mjs","sources":["../../../src/throttle.ts"],"sourcesContent":["const DEFAULT_MAX = 5;\n\nexport interface Result<T> {\n    lastCompletedIndex: number;\n    amountDone: number;\n    amountStarted: number;\n    amountResolved: number;\n    amountRejected: number;\n    amountNextCheckFalsey: number;\n    rejectedIndexes: number[];\n    resolvedIndexes: number[];\n    nextCheckFalseyIndexes: number[];\n    taskResults: T[];\n}\n\nexport interface Options<T> {\n    maxInProgress?: number;\n    failFast?: boolean;\n    progressCallback?: (result: Result<T>) => void;\n    nextCheck?: nextTaskCheck<T>;\n    ignoreIsFunctionCheck?: boolean;\n}\n\n/**\n * Default checker which validates if a next task should begin.\n * This can be overwritten to write own checks for example checking the amount\n * of used ram and waiting till the ram is low enough for a next task.\n *\n * It should always resolve with a boolean, either `true` to start a next task\n * or `false` to stop executing a new task.\n *\n * If this method rejects, the error will propagate to the caller\n * @param status\n * @param tasks\n * @returns {Promise}\n */\nconst defaultNextTaskCheck: nextTaskCheck<unknown> = <T>(status: Result<T>, tasks: Tasks<T>): Promise<boolean> => {\n    return Promise.resolve(status.amountStarted < tasks.length);\n};\n\nconst DEFAULT_OPTIONS = {\n    maxInProgress: DEFAULT_MAX,\n    failFast: false,\n    nextCheck: defaultNextTaskCheck,\n    ignoreIsFunctionCheck: false,\n};\n\nexport type Task<T> = () => Promise<T>;\nexport type Tasks<T> = Array<Task<T>>;\nexport type nextTaskCheck<T> = (status: Result<T>, tasks: Tasks<T>) => Promise<boolean>;\n\n/**\n * Raw throttle function, which can return extra meta data.\n * @param tasks required array of tasks to be executed\n * @param options Options object\n * @returns {Promise}\n */\nexport function raw<T>(tasks: Tasks<T>, options?: Options<T>): Promise<Result<T>> {\n    return new Promise<Result<T>>((resolve, reject) => {\n        const myOptions = Object.assign({}, DEFAULT_OPTIONS, options);\n        const result: Result<T> = {\n            lastCompletedIndex: -1,\n            amountDone: 0,\n            amountStarted: 0,\n            amountResolved: 0,\n            amountRejected: 0,\n            amountNextCheckFalsey: 0,\n            rejectedIndexes: [],\n            resolvedIndexes: [],\n            nextCheckFalseyIndexes: [],\n            taskResults: [],\n        };\n\n        if (tasks.length === 0) {\n            return resolve(result);\n        }\n\n        let failedFast = false;\n        let currentTaskIndex = 0;\n\n        const handleError = (error: T, index: number) => {\n            result.taskResults[index] = error;\n            result.rejectedIndexes.push(index);\n            result.amountRejected++;\n            if (myOptions.failFast === true) {\n                result.lastCompletedIndex = index;\n                failedFast = true;\n                return reject(result);\n            }\n            taskDone(index);\n        };\n\n        const executeTask = (index: number) => {\n            result.amountStarted++;\n            if (typeof tasks[index] === 'function') {\n                try {\n                    tasks[index]().then(\n                        (taskResult) => {\n                            result.taskResults[index] = taskResult;\n                            result.resolvedIndexes.push(index);\n                            result.amountResolved++;\n                            taskDone(index);\n                        },\n                        (error) => {\n                            handleError(error, index);\n                        },\n                    );\n                } catch (err) {\n                    handleError(err as T, index);\n                }\n            } else if (myOptions.ignoreIsFunctionCheck === true) {\n                result.taskResults[index] = tasks[index] as any as T;\n                result.resolvedIndexes.push(index);\n                result.amountResolved++;\n                taskDone(index);\n            } else {\n                failedFast = true;\n                return reject(\n                    new Error('tasks[' + index + ']: ' + tasks[index] + ', is supposed to be of type function'),\n                );\n            }\n        };\n\n        const taskDone = (index: number) => {\n            //make sure no more tasks are spawned when we failedFast\n            if (failedFast === true) {\n                return;\n            }\n\n            result.amountDone++;\n            result.lastCompletedIndex = index;\n            if (typeof myOptions.progressCallback === 'function') {\n                myOptions.progressCallback(result);\n            }\n            if (result.amountDone === tasks.length) {\n                return resolve(result);\n            }\n            if (currentTaskIndex < tasks.length) {\n                nextTask(currentTaskIndex++);\n            }\n        };\n\n        const nextTask = (index: number) => {\n            //check if we can execute the next task\n            myOptions.nextCheck(result, tasks).then((canExecuteNextTask) => {\n                if (canExecuteNextTask === true) {\n                    //execute it\n                    executeTask(index);\n                } else {\n                    result.amountNextCheckFalsey++;\n                    result.nextCheckFalseyIndexes.push(index);\n                    taskDone(index);\n                }\n            }, reject);\n        };\n\n        //spawn the first X task\n        for (let i = 0; i < Math.min(myOptions.maxInProgress, tasks.length); i++) {\n            nextTask(currentTaskIndex++);\n        }\n    });\n}\n\n/**\n * Executes the raw function, but only return the task array\n * @param tasks\n * @param options\n * @returns {Promise}\n */\nfunction executeRaw<T>(tasks: Tasks<T>, options: Options<T>): Promise<T[]> {\n    return new Promise<T[]>((resolve, reject) => {\n        raw(tasks, options).then(\n            (result: Result<T>) => {\n                resolve(result.taskResults);\n            },\n            (error: Error | Result<T>) => {\n                if (error instanceof Error) {\n                    reject(error);\n                } else {\n                    reject(error.taskResults[error.rejectedIndexes[0]]);\n                }\n            },\n        );\n    });\n}\n\n/**\n * Simply run all the promises after each other, so in synchronous manner\n * @param tasks required array of tasks to be executed\n * @param options Options object\n * @returns {Promise}\n */\nexport function sync<T>(tasks: Tasks<T>, options?: Options<T>): Promise<T[]> {\n    const myOptions = Object.assign({}, {maxInProgress: 1, failFast: true}, options);\n    return executeRaw(tasks, myOptions);\n}\n\n/**\n * Exposes the same behaviour as Promise.All(), but throttled!\n * @param tasks required array of tasks to be executed\n * @param options Options object\n * @returns {Promise}\n */\nexport function all<T>(tasks: Tasks<T>, options?: Options<T>): Promise<T[]> {\n    const myOptions = Object.assign({}, {failFast: true}, options);\n    return executeRaw(tasks, myOptions);\n}\n"],"names":["DEFAULT_OPTIONS","maxInProgress","failFast","nextCheck","status","tasks","Promise","resolve","amountStarted","length","ignoreIsFunctionCheck","raw","options","reject","myOptions","Object","assign","result","lastCompletedIndex","amountDone","amountResolved","amountRejected","amountNextCheckFalsey","rejectedIndexes","resolvedIndexes","nextCheckFalseyIndexes","taskResults","failedFast","currentTaskIndex","handleError","error","index","push","taskDone","progressCallback","nextTask","then","canExecuteNextTask","taskResult","err","Error","executeTask","i","Math","min","executeRaw","sync","all"],"mappings":"AAAA,IAwCMA,EAAkB,CACpBC,cAzCgB,EA0ChBC,UAAU,EACVC,UAPiD,SAAIC,EAAmBC,GACxE,OAAOC,QAAQC,QAAQH,EAAOI,cAAgBH,EAAMI,OACxD,EAMIC,uBAAuB,GAaX,SAAAC,EAAON,EAAiBO,GACpC,OAAO,IAAIN,SAAmB,SAACC,EAASM,GACpC,IAAMC,EAAYC,OAAOC,OAAO,CAAA,EAAIhB,EAAiBY,GAC/CK,EAAoB,CACtBC,oBAAqB,EACrBC,WAAY,EACZX,cAAe,EACfY,eAAgB,EAChBC,eAAgB,EAChBC,sBAAuB,EACvBC,gBAAiB,GACjBC,gBAAiB,GACjBC,uBAAwB,GACxBC,YAAa,IAGjB,GAAqB,IAAjBrB,EAAMI,OACN,OAAOF,EAAQU,GAmFnB,IAhFA,IAAIU,GAAa,EACbC,EAAmB,EAEjBC,EAAc,SAACC,EAAUC,GAI3B,GAHAd,EAAOS,YAAYK,GAASD,EAC5Bb,EAAOM,gBAAgBS,KAAKD,GAC5Bd,EAAOI,kBACoB,IAAvBP,EAAUZ,SAGV,OAFAe,EAAOC,mBAAqBa,EAC5BJ,GAAa,EACNd,EAAOI,GAElBgB,EAASF,EACb,EAiCME,EAAW,SAACF,GAEd,IAAmB,IAAfJ,EAAJ,CASA,GALAV,EAAOE,aACPF,EAAOC,mBAAqBa,EACc,mBAA/BjB,EAAUoB,kBACjBpB,EAAUoB,iBAAiBjB,GAE3BA,EAAOE,aAAed,EAAMI,OAC5B,OAAOF,EAAQU,GAEfW,EAAmBvB,EAAMI,QACzB0B,EAASP,IAXZ,CAaL,EAEMO,EAAW,SAACJ,GAEdjB,EAAUX,UAAUc,EAAQZ,GAAO+B,MAAK,SAACC,IACV,IAAvBA,EArDQ,SAACN,GAEjB,GADAd,EAAOT,gBACqB,mBAAjBH,EAAM0B,GACb,IACI1B,EAAM0B,KAASK,MACX,SAACE,GACGrB,EAAOS,YAAYK,GAASO,EAC5BrB,EAAOO,gBAAgBQ,KAAKD,GAC5Bd,EAAOG,iBACPa,EAASF,EACZ,IACD,SAACD,GACGD,EAAYC,EAAOC,EACvB,GAEP,CAAC,MAAOQ,GACLV,EAAYU,EAAUR,EACzB,KACE,KAAwC,IAApCjB,EAAUJ,sBAOjB,OADAiB,GAAa,EACNd,EACH,IAAI2B,MAAM,SAAWT,EAAQ,MAAQ1B,EAAM0B,GAAS,yCAPxDd,EAAOS,YAAYK,GAAS1B,EAAM0B,GAClCd,EAAOO,gBAAgBQ,KAAKD,GAC5Bd,EAAOG,iBACPa,EAASF,EAMZ,CACL,CA0BYU,CAAYV,IAEZd,EAAOK,wBACPL,EAAOQ,uBAAuBO,KAAKD,GACnCE,EAASF,GAEhB,GAAElB,EACP,EAGS6B,EAAI,EAAGA,EAAIC,KAAKC,IAAI9B,EAAUb,cAAeI,EAAMI,QAASiC,IACjEP,EAASP,IAEjB,GACJ,CAQA,SAASiB,EAAcxC,EAAiBO,GACpC,OAAO,IAAIN,SAAa,SAACC,EAASM,GAC9BF,EAAIN,EAAOO,GAASwB,MAChB,SAACnB,GACGV,EAAQU,EAAOS,YAClB,IACD,SAACI,GACOA,aAAiBU,MACjB3B,EAAOiB,GAEPjB,EAAOiB,EAAMJ,YAAYI,EAAMP,gBAAgB,IAEvD,GAER,GACJ,CAQgB,SAAAuB,EAAQzC,EAAiBO,GAErC,OAAOiC,EAAWxC,EADAU,OAAOC,OAAO,GAAI,CAACf,cAAe,EAAGC,UAAU,GAAOU,GAE5E,CAQgB,SAAAmC,EAAO1C,EAAiBO,GAEpC,OAAOiC,EAAWxC,EADAU,OAAOC,OAAO,CAAA,EAAI,CAACd,UAAU,GAAOU,GAE1D"}