Skip to content

Commit 78b00f7

Browse files
authored
Generate types from JSDoc comments with TypeScript compiler. (#415)
* Generate types from JSDoc comments with TypeScript compiler. * minor edit * - Use import('child_process').ForkOptions and import('worker_threads').WorkerOptions - Remove the WorkerOptions definition, which is already defined by default. * Change to private * Fix types * Add tests for type generation. * Edit a test * Tweak the way of exporting Promise to make the generated types compatible with @types/workerpool. * minor edit
1 parent 5fd5a92 commit 78b00f7

15 files changed

+313
-74
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/types
2+
13
# Logs
24
logs
35
*.log

package-lock.json

+31-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+8-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
],
1919
"main": "src/index.js",
2020
"browser": "dist/workerpool.js",
21+
"types": "types/index.d.ts",
2122
"files": [
2223
"dist",
2324
"src",
@@ -26,14 +27,17 @@
2627
"README.md"
2728
],
2829
"scripts": {
29-
"build": "rollup -c rollup.config.mjs",
30+
"build": "rollup -c rollup.config.mjs && npm run build:types",
31+
"build:types": "tsc -p .",
3032
"watch": "rollup -c rollup.config.mjs -w",
31-
"test": "npm run build && mocha test",
33+
"test": "npm run build && mocha test && npm run test:types",
34+
"test:types": "tsc -p test/types",
3235
"test:debug": "npm run build && mocha debug test",
3336
"coverage": "npm run build && c8 mocha && c8 report --reporter=html && echo Coverage report is available at ./coverage/index.html",
3437
"prepublishOnly": "npm run test"
3538
},
3639
"devDependencies": {
40+
"@types/node": "20.10.4",
3741
"@babel/core": "7.23.5",
3842
"@babel/preset-env": "7.23.5",
3943
"@rollup/plugin-babel": "6.0.4",
@@ -46,6 +50,7 @@
4650
"fs-extra": "11.2.0",
4751
"find-process": "1.4.7",
4852
"mocha": "10.2.0",
49-
"rollup": "4.6.1"
53+
"rollup": "4.6.1",
54+
"typescript": "5.3.3"
5055
}
5156
}

src/Pool.js

+35-15
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,62 @@
1-
var Promise = require('./Promise');
1+
var {Promise} = require('./Promise');
22
var WorkerHandler = require('./WorkerHandler');
33
var environment = require('./environment');
44
var DebugPortAllocator = require('./debug-port-allocator');
55
var DEBUG_PORT_ALLOCATOR = new DebugPortAllocator();
66
/**
7-
* A pool to manage workers
7+
* A pool to manage workers, which can be created using the function workerpool.pool.
8+
*
89
* @param {String} [script] Optional worker script
9-
* @param {WorkerPoolOptions} [options] See docs
10+
* @param {import('./types.js').WorkerPoolOptions} [options] See docs
1011
* @constructor
1112
*/
1213
function Pool(script, options) {
1314
if (typeof script === 'string') {
15+
/** @readonly */
1416
this.script = script || null;
1517
}
1618
else {
1719
this.script = null;
1820
options = script;
1921
}
2022

23+
/** @private */
2124
this.workers = []; // queue with all workers
25+
/** @private */
2226
this.tasks = []; // queue with tasks awaiting execution
2327

2428
options = options || {};
2529

30+
/** @readonly */
2631
this.forkArgs = Object.freeze(options.forkArgs || []);
32+
/** @readonly */
2733
this.forkOpts = Object.freeze(options.forkOpts || {});
34+
/** @readonly */
2835
this.workerOpts = Object.freeze(options.workerOpts || {});
36+
/** @readonly */
2937
this.workerThreadOpts = Object.freeze(options.workerThreadOpts || {})
38+
/** @private */
3039
this.debugPortStart = (options.debugPortStart || 43210);
40+
/** @readonly @deprecated */
3141
this.nodeWorker = options.nodeWorker;
42+
/** @readonly
43+
* @type {'auto' | 'web' | 'process' | 'thread'}
44+
*/
3245
this.workerType = options.workerType || options.nodeWorker || 'auto'
46+
/** @readonly */
3347
this.maxQueueSize = options.maxQueueSize || Infinity;
48+
/** @readonly */
3449
this.workerTerminateTimeout = options.workerTerminateTimeout || 1000;
3550

51+
/** @readonly */
3652
this.onCreateWorker = options.onCreateWorker || (() => null);
53+
/** @readonly */
3754
this.onTerminateWorker = options.onTerminateWorker || (() => null);
3855

3956
// configuration
4057
if (options && 'maxWorkers' in options) {
4158
validateMaxWorkers(options.maxWorkers);
59+
/** @readonly */
4260
this.maxWorkers = options.maxWorkers;
4361
}
4462
else {
@@ -47,6 +65,7 @@ function Pool(script, options) {
4765

4866
if (options && 'minWorkers' in options) {
4967
if(options.minWorkers === 'max') {
68+
/** @readonly */
5069
this.minWorkers = this.maxWorkers;
5170
} else {
5271
validateMinWorkers(options.minWorkers);
@@ -56,6 +75,7 @@ function Pool(script, options) {
5675
this._ensureMinWorkers();
5776
}
5877

78+
/** @private */
5979
this._boundNext = this._next.bind(this);
6080

6181

@@ -86,16 +106,16 @@ function Pool(script, options) {
86106
* .catch(function(error) {
87107
* console.log(error);
88108
* });
89-
*
90-
* @param {String | Function} method Function name or function.
109+
* @template { (...args: any[]) => any } T
110+
* @param {String | T} method Function name or function.
91111
* If `method` is a string, the corresponding
92112
* method on the worker will be executed
93113
* If `method` is a Function, the function
94114
* will be stringified and executed via the
95115
* workers built-in function `run(fn, args)`.
96-
* @param {Array} [params] Function arguments applied when calling the function
97-
* @param {ExecOptions} [options] Options object
98-
* @return {Promise.<*, Error>} result
116+
* @param {Parameters<T> | null} [params] Function arguments applied when calling the function
117+
* @param {import('./types.js').ExecOptions} [options] Options
118+
* @return {Promise<ReturnType<T>>}
99119
*/
100120
Pool.prototype.exec = function (method, params, options) {
101121
// validate type of arguments
@@ -152,9 +172,9 @@ Pool.prototype.exec = function (method, params, options) {
152172

153173
/**
154174
* Create a proxy for current worker. Returns an object containing all
155-
* methods available on the worker. The methods always return a promise.
156-
*
157-
* @return {Promise.<Object, Error>} proxy
175+
* methods available on the worker. All methods return promises resolving the methods result.
176+
* @template { { [k: string]: (...args: any[]) => any } } T
177+
* @return {Promise<import('./types.js').Proxy<T>, Error>} Returns a promise which resolves with a proxy object
158178
*/
159179
Pool.prototype.proxy = function () {
160180
if (arguments.length > 0) {
@@ -194,7 +214,7 @@ Pool.prototype.map = function (array, callback) {
194214
/**
195215
* Grab the first task from the queue, find a free worker, and assign the
196216
* worker to the task.
197-
* @protected
217+
* @private
198218
*/
199219
Pool.prototype._next = function () {
200220
if (this.tasks.length > 0) {
@@ -268,7 +288,7 @@ Pool.prototype._getWorker = function() {
268288
* pool size is met.
269289
* @param {WorkerHandler} worker
270290
* @return {Promise<WorkerHandler>}
271-
* @protected
291+
* @private
272292
*/
273293
Pool.prototype._removeWorker = function(worker) {
274294
var me = this;
@@ -299,7 +319,7 @@ Pool.prototype._removeWorker = function(worker) {
299319
/**
300320
* Remove a worker from the pool list.
301321
* @param {WorkerHandler} worker
302-
* @protected
322+
* @private
303323
*/
304324
Pool.prototype._removeWorkerFromList = function(worker) {
305325
// remove from the list with workers
@@ -374,7 +394,7 @@ Pool.prototype.stats = function () {
374394

375395
/**
376396
* Ensures that a minimum of minWorkers is up and running
377-
* @protected
397+
* @private
378398
*/
379399
Pool.prototype._ensureMinWorkers = function() {
380400
if (this.minWorkers) {

src/Promise.js

+26-12
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
* Promise
55
*
66
* Inspired by https://gist.github.com/RubaXa/8501359 from RubaXa <[email protected]>
7-
*
7+
* @template T
8+
* @template [E=Error]
89
* @param {Function} handler Called as handler(resolve: Function, reject: Function)
910
* @param {Promise} [parent] Parent promise for propagation of cancel and timeout
1011
*/
@@ -23,8 +24,17 @@ function Promise(handler, parent) {
2324
var _onFail = [];
2425

2526
// status
27+
/**
28+
* @readonly
29+
*/
2630
this.resolved = false;
31+
/**
32+
* @readonly
33+
*/
2734
this.rejected = false;
35+
/**
36+
* @readonly
37+
*/
2838
this.pending = true;
2939

3040
/**
@@ -41,9 +51,11 @@ function Promise(handler, parent) {
4151

4252
/**
4353
* Add an onSuccess callback and optionally an onFail callback to the Promise
44-
* @param {Function} onSuccess
45-
* @param {Function} [onFail]
46-
* @returns {Promise} promise
54+
* @template TT
55+
* @template [TE=never]
56+
* @param {(r: T) => TT} onSuccess
57+
* @param {(r: E) => TE} [onFail]
58+
* @returns {Promise<TT | TE, any>} promise
4759
*/
4860
this.then = function (onSuccess, onFail) {
4961
return new Promise(function (resolve, reject) {
@@ -104,7 +116,7 @@ function Promise(handler, parent) {
104116

105117
/**
106118
* Cancel te promise. This will reject the promise with a CancellationError
107-
* @returns {Promise} self
119+
* @returns {this} self
108120
*/
109121
this.cancel = function () {
110122
if (parent) {
@@ -122,7 +134,7 @@ function Promise(handler, parent) {
122134
* the time, the promise will be cancelled and a TimeoutError is thrown.
123135
* If the promise is resolved in time, the timeout is removed.
124136
* @param {number} delay Delay in milliseconds
125-
* @returns {Promise} self
137+
* @returns {this} self
126138
*/
127139
this.timeout = function (delay) {
128140
if (parent) {
@@ -177,8 +189,9 @@ function _then(callback, resolve, reject) {
177189

178190
/**
179191
* Add an onFail callback to the Promise
180-
* @param {Function} onFail
181-
* @returns {Promise} promise
192+
* @template TT
193+
* @param {(error: E) => TT} onFail
194+
* @returns {Promise<T | TT>} promise
182195
*/
183196
Promise.prototype['catch'] = function (onFail) {
184197
return this.then(null, onFail);
@@ -189,8 +202,9 @@ Promise.prototype['catch'] = function (onFail) {
189202

190203
/**
191204
* Execute given callback when the promise either resolves or rejects.
192-
* @param {Function} fn
193-
* @returns {Promise} promise
205+
* @template TT
206+
* @param {() => Promise<TT>} fn
207+
* @returns {Promise<TT>} promise
194208
*/
195209
Promise.prototype.always = function (fn) {
196210
return this.then(fn, fn);
@@ -200,7 +214,7 @@ Promise.prototype.always = function (fn) {
200214
* Create a promise which resolves when all provided promises are resolved,
201215
* and fails when any of the promises resolves.
202216
* @param {Promise[]} promises
203-
* @returns {Promise} promise
217+
* @returns {Promise<any[], any>} promise
204218
*/
205219
Promise.all = function (promises){
206220
return new Promise(function (resolve, reject) {
@@ -276,4 +290,4 @@ TimeoutError.prototype.name = 'TimeoutError';
276290
Promise.TimeoutError = TimeoutError;
277291

278292

279-
module.exports = Promise;
293+
exports.Promise = Promise;

src/WorkerHandler.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
var Promise = require('./Promise');
3+
var {Promise} = require('./Promise');
44
var environment = require('./environment');
55
const {validateOptions, forkOptsNames, workerThreadOptsNames, workerOptsNames} = require("./validateOptions");
66

@@ -206,7 +206,7 @@ function objectToError (obj) {
206206
* on node.js or a WebWorker in a browser environment.
207207
* @param {String} [script] If no script is provided, a default worker with a
208208
* function run will be created.
209-
* @param {WorkerPoolOptions} _options See docs
209+
* @param {import('./types.js').WorkerPoolOptions} [_options] See docs
210210
* @constructor
211211
*/
212212
function WorkerHandler(script, _options) {
@@ -328,7 +328,7 @@ WorkerHandler.prototype.methods = function () {
328328
* @param {String} method
329329
* @param {Array} [params]
330330
* @param {{resolve: Function, reject: Function}} [resolver]
331-
* @param {ExecOptions} [options]
331+
* @param {import('./types.js').ExecOptions} [options]
332332
* @return {Promise.<*, Error>} result
333333
*/
334334
WorkerHandler.prototype.exec = function(method, params, resolver, options) {

0 commit comments

Comments
 (0)