Skip to content

Commit 69d7a7a

Browse files
typescript stuff fixed.
1 parent dac01ff commit 69d7a7a

File tree

5 files changed

+145
-122
lines changed

5 files changed

+145
-122
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "for-promise",
3-
"version": "2.0.3",
3+
"version": "2.0.4",
44
"description": "Execute all promises inside a \"for\" script.",
55
"scripts": {
66
"test": "npm run test:mjs && npm run test:cjs && npm run test:js",

src/index.mjs

Lines changed: 108 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,50 @@
11
// Libs
22
import { objType, superValidator, validateTotal } from './utils/essentials.mjs';
33

4+
/**
5+
* @typedef {Object} forPromiseIteration
6+
* @property {Record<string, any>|any[]|number} data - The main data source. Can be an array-like object, number (as count), or object for keys.
7+
* @property {string} [type] - Optional type of iteration. Currently supports "while" for while-like looping.
8+
* @property {*} [while] - While validator
9+
* @property {Function} [checker] - Used only with type: "while" to determine loop continuation.
10+
*/
11+
12+
/**
13+
* Extra control object.
14+
*
15+
* @typedef {Object} forPromiseExtra
16+
* @property {boolean} complete - Whether the extra item has completed processing.
17+
* @property {boolean} forceBreak - Whether the extra item has triggered a forced break.
18+
* @property {number} count - Number of processed items.
19+
* @property {number|null} total - Total expected items, or null if not set.
20+
* @property {Array<any>} items - List of items processed.
21+
* @property {string} [type] - Optional type of processing (e.g., 'while').
22+
* @property {boolean} [error] - Is error.
23+
*/
24+
25+
/**
26+
* @typedef {{
27+
* error: boolean;
28+
* forceBreak: boolean;
29+
* type?: string;
30+
* extra?: Array<forPromiseExtra>;
31+
* count: number;
32+
* total: number|null;
33+
* items: Array<any>
34+
* }} ForPromiseStatus
35+
*/
36+
437
/**
538
* Runs an asynchronous iterative operation with advanced control over flow, breaks, and nested (extra) iterations.
639
* The function accepts a data object and a callback, and returns a Promise that resolves with iteration results.
740
*
8-
* @function
9-
* @param {Object} obj - The data object used to control the iteration process. It must follow a specific structure.
10-
* @param {Object|number} obj.data - The main data source. Can be an array-like object, number (as count), or object for keys.
11-
* @param {string} [obj.type] - Optional type of iteration. Currently supports `"while"` for while-like looping.
12-
* @param {Function} [obj.checker] - Used only with `type: "while"` to determine loop continuation.
41+
* @param {forPromiseIteration} obj - The data object used to control the iteration process. It must follow a specific structure.
1342
* @param {Function} callback - A function that will be called on each iteration step.
14-
* The callback receives the following parameters:
15-
*
16-
* @callback callback
17-
* @param {*} currentItem - The current item or index being iterated.
18-
* @param {Function} result - Function to call when iteration step finishes. Accepts an optional forceBreak configuration.
19-
* @param {Function} error - Function to call if an error is encountered.
20-
* @param {Function} extra - Function to call to register additional (nested) iterations.
21-
*
22-
* @returns {Promise<Object>} Resolves with an object containing the result of the iteration process.
23-
*
24-
* The returned object structure is:
25-
* @typedef {Object} IterationResult
26-
* @property {boolean} error - Whether an error occurred.
27-
* @property {boolean} forceBreak - Whether the iteration was forcefully broken.
28-
* @property {number} count - How many steps were executed.
29-
* @property {number} total - Total expected steps.
30-
* @property {Array} items - The collected results from each callback.
31-
* @property {Array} [extra] - If extras were used, contains an array of extra iteration results with the same structure.
32-
*
33-
* The `result()` function (inside the callback) accepts an optional argument:
34-
* @param {boolean|Object} [forceBreak=false] - If true, breaks the iteration early.
35-
* If an object is passed, it can contain:
36-
* @property {boolean} [break=false] - Whether to break the loop.
37-
* @property {boolean} [dontSendResult=false] - Prevents auto-resolve after completion.
38-
* @property {boolean} [forceResult=false] - Forces result resolution regardless of loop status.
3943
*
40-
* The `extra()` function (inside the callback) is used to spawn additional loops within the current loop.
41-
* It must be passed a valid object like the main one, and returns:
42-
* @returns {Object} An object with a `run(callback)` method to run the extra loop.
43-
*
44-
* @throws {Error} Throws if invalid input types are provided or during execution.
45-
*
46-
* @example
47-
* const obj = { data: [1, 2, 3] };
48-
*
49-
* forPromise(obj, (item, result, error, extra) => {
50-
* console.log(item);
51-
* result(); // move to next
52-
* }).then(res => console.log(res));
53-
*
54-
* @example
55-
* const input = {
56-
* data: [1, 2, 3],
57-
* };
58-
*
59-
* forPromise(input, (item, result, error, extraFn) => {
60-
* if (item === 2) return result({ break: true });
61-
* result();
62-
* }).then(console.log).catch(console.error);
44+
* @returns {Promise<ForPromiseStatus>}
6345
*/
64-
export default function forPromise(obj, callback) {
65-
return new Promise(function (resolve, reject) {
46+
export default async function forPromise(obj, callback) {
47+
return new Promise((resolve, reject) => {
6648
try {
6749
if (typeof obj !== 'object' || obj === null) throw new Error('Invalid object provided.');
6850
if (typeof callback !== 'function') throw new Error('Callback must be a function.');
@@ -75,7 +57,7 @@ export default function forPromise(obj, callback) {
7557

7658
// Validator
7759
if (objValidated.confirmed) {
78-
// Prepare Count
60+
/** @type {ForPromiseStatus} */
7961
let items = {
8062
error: false,
8163
forceBreak: false,
@@ -85,13 +67,21 @@ export default function forPromise(obj, callback) {
8567
};
8668

8769
// Error Result
70+
/** @param {Error} err */
8871
const error_result = function (err) {
8972
// Send Error Reject
9073
items.error = true;
9174
reject(err);
9275
};
9376

94-
// Prepare Result
77+
/**
78+
* Prepare Result
79+
*
80+
* @param {boolean} isExtra
81+
* @param {number} extraIndex
82+
* @param {*} item
83+
* @param {boolean|{ break: boolean; dontSendResult: boolean; forceResult: boolean;}} [forceBreak=false]
84+
*/
9585
const result = function (isExtra, extraIndex, item, forceBreak = false) {
9686
// Prepare Edit
9787
let item_to_edit = null;
@@ -103,8 +93,22 @@ export default function forPromise(obj, callback) {
10393
item_to_edit = extra.list[extraIndex];
10494
}
10595

96+
if (typeof item_to_edit.total !== 'number')
97+
return reject(new Error('Invalid "item_to_edit.total" value: null or undefined.'));
98+
10699
// Force Break
107-
const forceBreakResult = { isObject: objType(forceBreak, 'object') };
100+
/**
101+
* @typedef {Object} ForceBreakResult
102+
* @property {boolean} isObject
103+
* @property {boolean} [allowed]
104+
* @property {boolean} [dontSendResult]
105+
* @property {boolean} [forceResult]
106+
*/
107+
108+
/** @type {ForceBreakResult} */
109+
const forceBreakResult = {
110+
isObject: /** @type {boolean} */ (objType(forceBreak, 'object')),
111+
};
108112

109113
// Is Boolean
110114
if (!forceBreakResult.isObject) {
@@ -118,7 +122,7 @@ export default function forPromise(obj, callback) {
118122
}
119123

120124
// Object
121-
else {
125+
else if (typeof forceBreak === 'object') {
122126
if (!item_to_edit.forceBreak)
123127
forceBreakResult.allowed = typeof forceBreak.break === 'boolean' && forceBreak.break;
124128
else forceBreakResult.allowed = false;
@@ -200,23 +204,32 @@ export default function forPromise(obj, callback) {
200204
}
201205
};
202206

203-
// Run For
204-
const runFor = function (callback, isExtra = false, index = null, new_extra = null) {
205-
// Prepare the Item
207+
/**
208+
* @param {Function} callback
209+
* @param {boolean} [isExtra=false]
210+
* @param {number} [index=-1]
211+
* @param {{data: any, type?: string, checker?: Function}|null} [new_extra=null]
212+
* @returns {void}
213+
*/
214+
const runFor = function (callback, isExtra = false, index = -1, new_extra = null) {
206215
let the_item = null;
207216

208217
// Normal
209218
if (!isExtra) the_item = obj;
210-
else the_item = new_extra;
219+
else if (typeof new_extra === 'object') the_item = new_extra;
211220

212-
// Run Script
221+
/**
222+
* @param {number|string|null} [item=null]
223+
* @returns {boolean}
224+
*/
213225
const runFor_script = function (item = null) {
214226
// No Error
215227
if (!items.error && !items.forceBreak) {
216228
// Try
217229
try {
218230
// Result Function
219-
const result_data = (forceBreak) => result(isExtra, index, item, forceBreak);
231+
const result_data = /** @param {boolean} forceBreak */ (forceBreak) =>
232+
result(isExtra, index, item, forceBreak);
220233

221234
// Exist Item
222235
if (item !== null) callback(item, result_data, error_result, extra.extra_function);
@@ -237,6 +250,8 @@ export default function forPromise(obj, callback) {
237250
else return false;
238251
};
239252

253+
if (the_item === null) throw new Error('Invalid "the_item" value: null or undefined.');
254+
240255
// Start the For
241256
if (typeof the_item.data !== 'number') {
242257
// For Object
@@ -258,8 +273,11 @@ export default function forPromise(obj, callback) {
258273
else {
259274
// Start a While
260275
if (the_item.type === 'while') {
261-
// Prepare
276+
/** @returns {object|void} */
262277
const custom_do = function () {
278+
if (typeof the_item.checker !== 'function')
279+
throw new Error('Invalid "checker" function in "the_item".');
280+
263281
// Validate
264282
if (the_item.checker()) {
265283
// Prepare Edit
@@ -268,15 +286,22 @@ export default function forPromise(obj, callback) {
268286
// Not Extra
269287
if (!isExtra) {
270288
item_to_edit = items;
271-
} else {
272-
item_to_edit = extra.list[index];
273-
}
289+
} else item_to_edit = extra.list[index];
290+
291+
if (typeof item_to_edit.total !== 'number')
292+
throw new Error('Invalid "item_to_edit.total" value: null or undefined.');
274293

275294
// Add Total
276295
item_to_edit.total++;
277296

278297
// Callback and Continue
279298
callback(
299+
/**
300+
* Increments the item count and returns the result handler.
301+
*
302+
* @param {boolean} forceBreak - Whether to forcefully break the loop.
303+
* @returns {*} The result of the handler execution.
304+
*/
280305
function (forceBreak) {
281306
item_to_edit.count++;
282307
return result(isExtra, index, null, forceBreak);
@@ -325,15 +350,27 @@ export default function forPromise(obj, callback) {
325350
// Type
326351
if (objValidated.type) items.type = objValidated.type;
327352

328-
// Prepare Extra
353+
/**
354+
* Represents the extra handling structure.
355+
*
356+
* @typedef {Object} Extra
357+
* @property {boolean} enabled - Whether extra processing is enabled.
358+
* @property {Array<forPromiseExtra>} list - List of extra items.
359+
* @property {function(forPromiseIteration): {run: function(Function): void}|null} extra_function - Function to add a new extra item.
360+
*/
361+
362+
/** @type {Extra} */
329363
const extra = {
330364
// Enabled
331365
enabled: false,
332366

333367
// Extra List
334368
list: [],
335369

336-
// Functions
370+
/**
371+
* @param {forPromiseIteration} new_extra
372+
* @returns {{run: function(Function): void}|null}
373+
*/
337374
extra_function: function (new_extra) {
338375
// Validate Obj
339376
const objValidated = superValidator(new_extra);

src/utils/essentials.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function validateTotal(obj) {
3030
* - Confirms validity if `obj.data` is an object, array, or number.
3131
* - Also confirms if `obj.type` is `'while'`, and `obj.while` is defined, and `obj.checker` is a function.
3232
*
33-
* @param {*} obj - The input object to validate.
33+
* @param {import("../index.mjs").forPromiseIteration} obj - The input object to validate.
3434
* @returns {{ confirmed: boolean, type?: string }} - Returns an object with a `confirmed` boolean.
3535
* If a "while" validation is detected, includes `type: 'while'`.
3636
*
@@ -41,6 +41,7 @@ export function validateTotal(obj) {
4141
*/
4242
export function superValidator(obj) {
4343
// Start Module
44+
/** @type {{ confirmed: boolean, type?: string }} */
4445
const result = { confirmed: false };
4546
// Normal
4647
if (

0 commit comments

Comments
 (0)