UNPKG

2.64 kBJavaScriptView Raw
1"use strict";
2
3/** @typedef {import("webpack").Compilation["inputFileSystem"] } InputFileSystem */
4
5/** @typedef {import("fs").Stats } Stats */
6
7/**
8 * @param {InputFileSystem} inputFileSystem
9 * @param {string} path
10 * @return {Promise<undefined | Stats>}
11 */
12function stat(inputFileSystem, path) {
13 return new Promise((resolve, reject) => {
14 inputFileSystem.stat(path,
15 /**
16 * @param {null | undefined | NodeJS.ErrnoException} err
17 * @param {undefined | Stats} stats
18 */
19 // @ts-ignore
20 (err, stats) => {
21 if (err) {
22 reject(err);
23 return;
24 }
25
26 resolve(stats);
27 });
28 });
29}
30/**
31 * @param {InputFileSystem} inputFileSystem
32 * @param {string} path
33 * @return {Promise<string | Buffer>}
34 */
35
36
37function readFile(inputFileSystem, path) {
38 return new Promise((resolve, reject) => {
39 inputFileSystem.readFile(path,
40 /**
41 * @param {null | undefined | NodeJS.ErrnoException} err
42 * @param {undefined | string | Buffer} data
43 */
44 (err, data) => {
45 if (err) {
46 reject(err);
47 return;
48 }
49
50 resolve(
51 /** @type {string | Buffer} */
52 data);
53 });
54 });
55}
56
57const notSettled = Symbol(`not-settled`);
58/**
59 * @template T
60 * @typedef {() => Promise<T>} Task
61 */
62
63/**
64 * Run tasks with limited concurency.
65 * @template T
66 * @param {number} limit - Limit of tasks that run at once.
67 * @param {Task<T>[]} tasks - List of tasks to run.
68 * @returns {Promise<T[]>} A promise that fulfills to an array of the results
69 */
70
71function throttleAll(limit, tasks) {
72 if (!Number.isInteger(limit) || limit < 1) {
73 throw new TypeError(`Expected \`limit\` to be a finite number > 0, got \`${limit}\` (${typeof limit})`);
74 }
75
76 if (!Array.isArray(tasks) || !tasks.every(task => typeof task === `function`)) {
77 throw new TypeError(`Expected \`tasks\` to be a list of functions returning a promise`);
78 }
79
80 return new Promise((resolve, reject) => {
81 const result = Array(tasks.length).fill(notSettled);
82 const entries = tasks.entries();
83
84 const next = () => {
85 const {
86 done,
87 value
88 } = entries.next();
89
90 if (done) {
91 const isLast = !result.includes(notSettled);
92
93 if (isLast) {
94 resolve(
95 /** @type{T[]} **/
96 result);
97 }
98
99 return;
100 }
101
102 const [index, task] = value;
103 /**
104 * @param {T} x
105 */
106
107 const onFulfilled = x => {
108 result[index] = x;
109 next();
110 };
111
112 task().then(onFulfilled, reject);
113 };
114
115 Array(limit).fill(0).forEach(next);
116 });
117}
118
119module.exports = {
120 stat,
121 readFile,
122 throttleAll
123};
\No newline at end of file