@j-o-r/sh 1.1.8 → 1.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/SH.js +5 -22
- package/lib/Test.js +22 -5
- package/package.json +2 -1
- package/types/SH.d.ts +5 -7
package/lib/SH.js
CHANGED
|
@@ -31,7 +31,7 @@ import SHDispatch from './SHDispatch.js';
|
|
|
31
31
|
import Test from './Test.js'
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* @typedef {Object.<string, string
|
|
34
|
+
* @typedef {Object.<string, string>} ArgsObject
|
|
35
35
|
* @property {string} [key: string] - Any string key maps to a string value
|
|
36
36
|
* @property {string[]} _ - Array of strings, unnamed parameters
|
|
37
37
|
* @description Parsed parameters result.
|
|
@@ -111,8 +111,6 @@ const SH = new Proxy(function(pieces, ...args) {
|
|
|
111
111
|
/**
|
|
112
112
|
* Create a async/sync context in new execution callstack
|
|
113
113
|
* @param {function} callback - async/sync function
|
|
114
|
-
* @param {ResolveCallback} [resolve] - optional resolve/result callback
|
|
115
|
-
* @param {RejectCallback} [reject] - optional reject/error callback
|
|
116
114
|
* @example
|
|
117
115
|
* const p = within(async () => {
|
|
118
116
|
* const res = await Promise.all([
|
|
@@ -124,24 +122,8 @@ const SH = new Proxy(function(pieces, ...args) {
|
|
|
124
122
|
* return 'res';
|
|
125
123
|
* });
|
|
126
124
|
*/
|
|
127
|
-
const within = (callback
|
|
128
|
-
|
|
129
|
-
const RCB = jsType(resolve) === 'Function';
|
|
130
|
-
const ECB = jsType(reject) === 'Function';
|
|
131
|
-
(async () => {
|
|
132
|
-
try {
|
|
133
|
-
const res = await Promise.resolve(callback());
|
|
134
|
-
if (RCB) {
|
|
135
|
-
resolve(res);
|
|
136
|
-
}
|
|
137
|
-
} catch (e) {
|
|
138
|
-
if (ECB) {
|
|
139
|
-
reject(e)
|
|
140
|
-
} else {
|
|
141
|
-
throw (e);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
})()
|
|
125
|
+
const within = async (callback) => {
|
|
126
|
+
return await callback();
|
|
145
127
|
}
|
|
146
128
|
|
|
147
129
|
/**
|
|
@@ -162,7 +144,7 @@ const readIn = async () => {
|
|
|
162
144
|
* Retries a given asynchronous function a specified number of times with optional delays between attempts.
|
|
163
145
|
*
|
|
164
146
|
* @param {number} count - The number of retry attempts.
|
|
165
|
-
* @param {string|expBackoff|Function} a - Either a delay duration as a string, a delay generator object, or the callback function.
|
|
147
|
+
* @param {string|number|expBackoff|Function} a - Either a delay duration as a string, a delay generator object, or the callback function.
|
|
166
148
|
* @param {Function} [b] - The callback function to retry, required if `a` is not a function.
|
|
167
149
|
* @returns {Promise<*>} - The result of the callback function if it succeeds within the retry attempts.
|
|
168
150
|
* @throws {Error} - The last error encountered if all retry attempts fail.
|
|
@@ -297,6 +279,7 @@ const parseArgs = (args) => {
|
|
|
297
279
|
result._.push(args[i]);
|
|
298
280
|
}
|
|
299
281
|
}
|
|
282
|
+
// @ts-ignore
|
|
300
283
|
return result;
|
|
301
284
|
};
|
|
302
285
|
|
package/lib/Test.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { nextTick } from 'process';
|
|
1
2
|
import { jsType } from './SH.js'
|
|
3
|
+
import AsyncTracker from '@j-o-r/asynctracker';
|
|
2
4
|
/**
|
|
3
5
|
* Valid jsTypes for test methods
|
|
4
6
|
*/
|
|
@@ -49,6 +51,8 @@ function getDuration(start) {
|
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
class Test {
|
|
54
|
+
/** @type {AsyncTracker} */
|
|
55
|
+
#promiseTracker;
|
|
52
56
|
#catchErrors = false;
|
|
53
57
|
#currentTest = -1;
|
|
54
58
|
/** @type {testDefinition[]} */
|
|
@@ -70,6 +74,9 @@ class Test {
|
|
|
70
74
|
if (quiet) {
|
|
71
75
|
this.#quite = true;
|
|
72
76
|
}
|
|
77
|
+
// Track for unresolved promises
|
|
78
|
+
this.#promiseTracker = new AsyncTracker();
|
|
79
|
+
this.#promiseTracker.enable('PROMISE');
|
|
73
80
|
}
|
|
74
81
|
/**
|
|
75
82
|
* Set the timeout when a synced function is called.
|
|
@@ -111,7 +118,7 @@ class Test {
|
|
|
111
118
|
* @returns {Test}
|
|
112
119
|
*/
|
|
113
120
|
add(description, callback) {
|
|
114
|
-
if (typeof(description) !== 'string') {
|
|
121
|
+
if (typeof (description) !== 'string') {
|
|
115
122
|
throw new Error(`'description' should be a string`)
|
|
116
123
|
}
|
|
117
124
|
if (!FNC.includes(jsType(callback))) {
|
|
@@ -191,12 +198,22 @@ class Test {
|
|
|
191
198
|
|
|
192
199
|
}
|
|
193
200
|
const errors = this.#errors.length;
|
|
194
|
-
if (tests !== executed) {
|
|
195
|
-
if (!this.#quite) console.log('** Not all tests have been executed **');
|
|
196
|
-
}
|
|
197
201
|
if (!this.#quite) {
|
|
198
202
|
console.log('--------------------------------------------------');
|
|
199
203
|
console.log(`Total: ${tests} tests, executed: ${executed} in ${duration} ms - errors: ${errors}`);
|
|
204
|
+
if (tests !== executed) {
|
|
205
|
+
if (!this.#quite) console.log('** Not all tests have been executed **');
|
|
206
|
+
return { tests, executed, duration, errors };
|
|
207
|
+
}
|
|
208
|
+
// Report on unresolved promises when NOT quite
|
|
209
|
+
// This must be on a next tick because the current Promise (where this code is in) is not resolved yet
|
|
210
|
+
nextTick(() => {
|
|
211
|
+
const count = this.#promiseTracker.report(true);
|
|
212
|
+
if (count > 0) {
|
|
213
|
+
console.log('--------------------------------------------------');
|
|
214
|
+
console.log(`${count} Unresolved Promises detected.`);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
200
217
|
}
|
|
201
218
|
return { tests, executed, duration, errors };
|
|
202
219
|
}
|
|
@@ -216,7 +233,7 @@ class Test {
|
|
|
216
233
|
*/
|
|
217
234
|
#handleError(err, outside = false) {
|
|
218
235
|
// A global error is an error catched outside the callstack of the test
|
|
219
|
-
const ERR = outside? 'GLOBAL_ERROR' : 'ERROR'
|
|
236
|
+
const ERR = outside ? 'GLOBAL_ERROR' : 'ERROR'
|
|
220
237
|
if (this.#currentTest > -1) {
|
|
221
238
|
if (!this.#quite) process.stdout.write(`\n`);
|
|
222
239
|
// Register this error
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@j-o-r/sh",
|
|
3
3
|
"author": "Jorrit Duin <j-o-r@duin.work>",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.1.
|
|
5
|
+
"version": "1.1.10",
|
|
6
6
|
"description": "Execute shell commands on Linux-based systems from javascript",
|
|
7
7
|
"main": "lib/SH.js",
|
|
8
8
|
"types": "types/SH.d.ts",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"license": "Apache License, Version 2.0",
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@j-o-r/asynctracker": "^0.0.8",
|
|
26
27
|
"@types/node": "^22.10.10"
|
|
27
28
|
},
|
|
28
29
|
"bugs": {
|
package/types/SH.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type ArgsObject = {
|
|
2
|
-
[x: string]: string
|
|
2
|
+
[x: string]: string;
|
|
3
3
|
};
|
|
4
4
|
export type RejectCallback = Function;
|
|
5
5
|
export type ResolveCallback = Function;
|
|
@@ -29,7 +29,7 @@ export function sleep(duration: string | number): Promise<any>;
|
|
|
29
29
|
* Retries a given asynchronous function a specified number of times with optional delays between attempts.
|
|
30
30
|
*
|
|
31
31
|
* @param {number} count - The number of retry attempts.
|
|
32
|
-
* @param {string|expBackoff|Function} a - Either a delay duration as a string, a delay generator object, or the callback function.
|
|
32
|
+
* @param {string|number|expBackoff|Function} a - Either a delay duration as a string, a delay generator object, or the callback function.
|
|
33
33
|
* @param {Function} [b] - The callback function to retry, required if `a` is not a function.
|
|
34
34
|
* @returns {Promise<*>} - The result of the callback function if it succeeds within the retry attempts.
|
|
35
35
|
* @throws {Error} - The last error encountered if all retry attempts fail.
|
|
@@ -44,7 +44,7 @@ export function sleep(duration: string | number): Promise<any>;
|
|
|
44
44
|
* // Retry a command 3 times with irregular intervals using exponential backoff
|
|
45
45
|
* const p = await retry(3, expBackoff(), () => SH`curl -s https://flipwrsi`);
|
|
46
46
|
*/
|
|
47
|
-
export function retry(count: number, a: string | typeof expBackoff | Function, b?: Function): Promise<any>;
|
|
47
|
+
export function retry(count: number, a: string | number | typeof expBackoff | Function, b?: Function): Promise<any>;
|
|
48
48
|
/**
|
|
49
49
|
* This function reads the standard input (stdin) from the current process.
|
|
50
50
|
* @example
|
|
@@ -54,8 +54,6 @@ export function readIn(): Promise<string>;
|
|
|
54
54
|
/**
|
|
55
55
|
* Create a async/sync context in new execution callstack
|
|
56
56
|
* @param {function} callback - async/sync function
|
|
57
|
-
* @param {ResolveCallback} [resolve] - optional resolve/result callback
|
|
58
|
-
* @param {RejectCallback} [reject] - optional reject/error callback
|
|
59
57
|
* @example
|
|
60
58
|
* const p = within(async () => {
|
|
61
59
|
* const res = await Promise.all([
|
|
@@ -67,7 +65,7 @@ export function readIn(): Promise<string>;
|
|
|
67
65
|
* return 'res';
|
|
68
66
|
* });
|
|
69
67
|
*/
|
|
70
|
-
export function within(callback: Function
|
|
68
|
+
export function within(callback: Function): Promise<any>;
|
|
71
69
|
/**
|
|
72
70
|
* Generates an exponential backoff time with a random jitter.
|
|
73
71
|
*
|
|
@@ -94,7 +92,7 @@ export function expBackoff(max?: string, rand?: string): Generator<number, void,
|
|
|
94
92
|
*/
|
|
95
93
|
export function parseArgs(args?: string[]): ArgsObject;
|
|
96
94
|
/**
|
|
97
|
-
* @typedef {Object.<string, string
|
|
95
|
+
* @typedef {Object.<string, string>} ArgsObject
|
|
98
96
|
* @property {string} [key: string] - Any string key maps to a string value
|
|
99
97
|
* @property {string[]} _ - Array of strings, unnamed parameters
|
|
100
98
|
* @description Parsed parameters result.
|