aveazul 1.0.2 → 2.0.0
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/README.md +1 -1
- package/cjs-entry.cjs +7 -0
- package/dist/any.d.ts +2 -0
- package/dist/any.js +45 -0
- package/dist/aveazul.d.ts +344 -0
- package/dist/aveazul.js +610 -0
- package/dist/disposer.d.ts +9 -0
- package/dist/disposer.js +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +7 -0
- package/dist/not-implemented.d.ts +4 -0
- package/dist/not-implemented.js +101 -0
- package/dist/operational-error.d.ts +20 -0
- package/dist/operational-error.js +36 -0
- package/dist/promisify-all.d.ts +10 -0
- package/dist/promisify-all.js +69 -0
- package/dist/promisify.d.ts +11 -0
- package/dist/promisify.js +59 -0
- package/dist/using.d.ts +12 -0
- package/dist/using.js +124 -0
- package/dist/util.d.ts +29 -0
- package/dist/util.js +173 -0
- package/package.json +36 -22
- package/lib/any.js +0 -55
- package/lib/aveazul.js +0 -645
- package/lib/disposer.js +0 -14
- package/lib/not-implemented.js +0 -110
- package/lib/operational-error.js +0 -46
- package/lib/promisify-all.js +0 -93
- package/lib/promisify.js +0 -70
- package/lib/using.js +0 -142
- package/lib/util.js +0 -199
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
function createNotImplemented(name) {
|
|
2
|
+
return function () {
|
|
3
|
+
const msg = name + " Not implemented in aveazul";
|
|
4
|
+
console.error(msg);
|
|
5
|
+
throw new Error(msg);
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export function createInstanceNotImplemented(AveAzul) {
|
|
9
|
+
const methods = [
|
|
10
|
+
"then",
|
|
11
|
+
"spread",
|
|
12
|
+
"catch",
|
|
13
|
+
"finally",
|
|
14
|
+
"bind",
|
|
15
|
+
"isFulfilled",
|
|
16
|
+
"isRejected",
|
|
17
|
+
"isPending",
|
|
18
|
+
"isCancelled",
|
|
19
|
+
"value",
|
|
20
|
+
"reason",
|
|
21
|
+
"all",
|
|
22
|
+
"props",
|
|
23
|
+
"any",
|
|
24
|
+
"some",
|
|
25
|
+
"map",
|
|
26
|
+
"reduce",
|
|
27
|
+
"filter",
|
|
28
|
+
"each",
|
|
29
|
+
"mapSeries",
|
|
30
|
+
"disposer",
|
|
31
|
+
"asCallback",
|
|
32
|
+
"delay",
|
|
33
|
+
"timeout",
|
|
34
|
+
"cancel",
|
|
35
|
+
"tap",
|
|
36
|
+
"tapCatch",
|
|
37
|
+
"call",
|
|
38
|
+
"get",
|
|
39
|
+
"return",
|
|
40
|
+
"throw",
|
|
41
|
+
"catchReturn",
|
|
42
|
+
"catchThrow",
|
|
43
|
+
"reflect",
|
|
44
|
+
"suppressUnhandledRejections",
|
|
45
|
+
"done",
|
|
46
|
+
];
|
|
47
|
+
const proto = AveAzul.prototype;
|
|
48
|
+
const ret = [];
|
|
49
|
+
for (const method of methods) {
|
|
50
|
+
if (!proto[method]) {
|
|
51
|
+
ret.push(method);
|
|
52
|
+
proto[method] = createNotImplemented("instance " + method);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return ret;
|
|
56
|
+
}
|
|
57
|
+
export function createStaticNotImplemented(AveAzul) {
|
|
58
|
+
const methods = [
|
|
59
|
+
"join",
|
|
60
|
+
"try",
|
|
61
|
+
"method",
|
|
62
|
+
"resolve",
|
|
63
|
+
"reject",
|
|
64
|
+
"props",
|
|
65
|
+
"any",
|
|
66
|
+
"some",
|
|
67
|
+
"map",
|
|
68
|
+
"reduce",
|
|
69
|
+
"filter",
|
|
70
|
+
"each",
|
|
71
|
+
"mapSeries",
|
|
72
|
+
"race",
|
|
73
|
+
"using",
|
|
74
|
+
"promisify",
|
|
75
|
+
"promisifyAll",
|
|
76
|
+
"fromCallback",
|
|
77
|
+
"delay",
|
|
78
|
+
"coroutine",
|
|
79
|
+
"coroutine.addYieldHandler",
|
|
80
|
+
"getNewLibraryCopy",
|
|
81
|
+
"noConflict",
|
|
82
|
+
"setScheduler",
|
|
83
|
+
];
|
|
84
|
+
const ret = [];
|
|
85
|
+
const aveazul = AveAzul;
|
|
86
|
+
for (const method of methods) {
|
|
87
|
+
if (!aveazul[method]) {
|
|
88
|
+
ret.push(method);
|
|
89
|
+
aveazul[method] = createNotImplemented("static " + method);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return ret;
|
|
93
|
+
}
|
|
94
|
+
export function setupNotImplemented(AveAzul) {
|
|
95
|
+
const instanceMethods = createInstanceNotImplemented(AveAzul);
|
|
96
|
+
const staticMethods = createStaticNotImplemented(AveAzul);
|
|
97
|
+
AveAzul.__notImplementedInstance =
|
|
98
|
+
instanceMethods;
|
|
99
|
+
AveAzul.__notImplementedStatic =
|
|
100
|
+
staticMethods;
|
|
101
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OperationalError class for representing errors that are expected during normal operation
|
|
3
|
+
* Similar to Bluebird's OperationalError
|
|
4
|
+
*/
|
|
5
|
+
export declare class OperationalError extends Error {
|
|
6
|
+
isOperational: boolean;
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Check if an error is an operational error
|
|
11
|
+
* @param error - Error to check
|
|
12
|
+
* @returns True if the error is operational
|
|
13
|
+
*/
|
|
14
|
+
export declare function isOperationalError(error: unknown): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Check if an error is a programmer error (unexpected, likely a bug)
|
|
17
|
+
* @param error - Error to check
|
|
18
|
+
* @returns True if the error is a programmer error
|
|
19
|
+
*/
|
|
20
|
+
export declare function isProgrammerError(error: unknown): boolean;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OperationalError class for representing errors that are expected during normal operation
|
|
3
|
+
* Similar to Bluebird's OperationalError
|
|
4
|
+
*/
|
|
5
|
+
export class OperationalError extends Error {
|
|
6
|
+
constructor(message) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "OperationalError";
|
|
9
|
+
this.isOperational = true;
|
|
10
|
+
// Capture stack trace
|
|
11
|
+
if (Error.captureStackTrace) {
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Check if an error is an operational error
|
|
18
|
+
* @param error - Error to check
|
|
19
|
+
* @returns True if the error is operational
|
|
20
|
+
*/
|
|
21
|
+
export function isOperationalError(error) {
|
|
22
|
+
if (!error || typeof error !== "object")
|
|
23
|
+
return false;
|
|
24
|
+
return (error instanceof OperationalError ||
|
|
25
|
+
error.isOperational === true);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if an error is a programmer error (unexpected, likely a bug)
|
|
29
|
+
* @param error - Error to check
|
|
30
|
+
* @returns True if the error is a programmer error
|
|
31
|
+
*/
|
|
32
|
+
export function isProgrammerError(error) {
|
|
33
|
+
if (!error || typeof error !== "object")
|
|
34
|
+
return false;
|
|
35
|
+
return !isOperationalError(error);
|
|
36
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PromisifyOptions } from "./promisify.js";
|
|
2
|
+
type FilterFunction = (name: string, value: unknown, target: object, passesDefaultFilter?: boolean) => boolean;
|
|
3
|
+
type PromisifierFunction = (fn: (...args: any[]) => void, defaultPromisifier: (fn: (...args: any[]) => void, dp: any, options: PromisifyAllOptions) => (...args: any[]) => Promise<unknown>, options: PromisifyAllOptions) => (...args: any[]) => Promise<unknown>;
|
|
4
|
+
export interface PromisifyAllOptions extends PromisifyOptions {
|
|
5
|
+
suffix?: string;
|
|
6
|
+
filter?: FilterFunction;
|
|
7
|
+
promisifier?: PromisifierFunction;
|
|
8
|
+
}
|
|
9
|
+
export declare function promisifyAll<T extends object>(target: T, _options?: PromisifyAllOptions): T;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { promisify } from "./promisify.js";
|
|
2
|
+
import { isIdentifier, isClass, isPromisified, getObjectDataKeys } from "./util.js";
|
|
3
|
+
const defaultSuffix = "Async";
|
|
4
|
+
const defaultFilter = function (name) {
|
|
5
|
+
return (isIdentifier(name) &&
|
|
6
|
+
name.charAt(0) !== "_" &&
|
|
7
|
+
name !== "constructor" &&
|
|
8
|
+
!name.endsWith("Sync"));
|
|
9
|
+
};
|
|
10
|
+
const defaultPromisifier = (fn, _defaultPromisifier, options) => {
|
|
11
|
+
return promisify(fn, {
|
|
12
|
+
...options,
|
|
13
|
+
copyProps: false,
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
function promisifyAll2(obj, options) {
|
|
17
|
+
const allKeys = getObjectDataKeys(obj);
|
|
18
|
+
for (const key of allKeys) {
|
|
19
|
+
const value = obj[key];
|
|
20
|
+
const promisifiedKey = key + options.suffix;
|
|
21
|
+
const passesDefaultFilter = options.filter === defaultFilter ? true : defaultFilter(key, value, obj);
|
|
22
|
+
if (typeof value !== "function" ||
|
|
23
|
+
isPromisified(value) ||
|
|
24
|
+
obj[promisifiedKey] ||
|
|
25
|
+
!options.filter(key, value, obj, passesDefaultFilter)) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (key.endsWith(options.suffix)) {
|
|
29
|
+
throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a See http://goo.gl/MqrFmX\u000a".replace("%s", options.suffix));
|
|
30
|
+
}
|
|
31
|
+
obj[promisifiedKey] = options.promisifier(value, defaultPromisifier, {
|
|
32
|
+
// context: obj, // promisified function should get the binded object using this
|
|
33
|
+
copyProps: false,
|
|
34
|
+
...options,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function promisifyAll(target, _options) {
|
|
39
|
+
if (typeof target !== "function" && typeof target !== "object") {
|
|
40
|
+
throw new TypeError("the target of promisifyAll must be an object or a function");
|
|
41
|
+
}
|
|
42
|
+
const options = {
|
|
43
|
+
suffix: defaultSuffix,
|
|
44
|
+
filter: defaultFilter,
|
|
45
|
+
promisifier: defaultPromisifier,
|
|
46
|
+
Promise: globalThis.Promise,
|
|
47
|
+
multiArgs: false,
|
|
48
|
+
copyProps: true,
|
|
49
|
+
context: undefined,
|
|
50
|
+
..._options,
|
|
51
|
+
};
|
|
52
|
+
const suffix = options.suffix;
|
|
53
|
+
if (!isIdentifier(suffix)) {
|
|
54
|
+
throw new RangeError("suffix must be a valid identifier\u000a\u000a See http://goo.gl/MqrFmX\u000a");
|
|
55
|
+
}
|
|
56
|
+
const allKeys = getObjectDataKeys(target);
|
|
57
|
+
for (const key of allKeys) {
|
|
58
|
+
const value = target[key];
|
|
59
|
+
if (value &&
|
|
60
|
+
key !== "constructor" &&
|
|
61
|
+
!key.startsWith("_") &&
|
|
62
|
+
isClass(value)) {
|
|
63
|
+
promisifyAll2(value.prototype, options);
|
|
64
|
+
promisifyAll2(value, options);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
promisifyAll2(target, options);
|
|
68
|
+
return target;
|
|
69
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PromisifyOptions {
|
|
2
|
+
Promise?: PromiseConstructor;
|
|
3
|
+
multiArgs?: boolean;
|
|
4
|
+
copyProps?: boolean;
|
|
5
|
+
suffix?: string;
|
|
6
|
+
context?: unknown;
|
|
7
|
+
}
|
|
8
|
+
type NodeStyleFunction = (...args: unknown[]) => void;
|
|
9
|
+
type PromisifiedFunction<T> = (...args: unknown[]) => Promise<T>;
|
|
10
|
+
export declare function promisify<T = unknown>(fn: NodeStyleFunction, _options?: PromisifyOptions): PromisifiedFunction<T>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { copyOwnProperties, isPromisified } from "./util.js";
|
|
2
|
+
export function promisify(fn, _options) {
|
|
3
|
+
if (typeof fn !== "function") {
|
|
4
|
+
throw new TypeError("expecting a function but got " + {}.toString.call(fn));
|
|
5
|
+
}
|
|
6
|
+
if (isPromisified(fn)) {
|
|
7
|
+
return fn;
|
|
8
|
+
}
|
|
9
|
+
const options = {
|
|
10
|
+
Promise: globalThis.Promise,
|
|
11
|
+
multiArgs: false,
|
|
12
|
+
copyProps: true,
|
|
13
|
+
suffix: "",
|
|
14
|
+
context: undefined,
|
|
15
|
+
..._options,
|
|
16
|
+
};
|
|
17
|
+
const PromiseCtor = options.Promise;
|
|
18
|
+
const multiArgs = !!options.multiArgs;
|
|
19
|
+
const promisifiedFn = function (...args) {
|
|
20
|
+
return new PromiseCtor((resolve, reject) => {
|
|
21
|
+
// add a callback to the end of the arguments to transfer the result to the promise
|
|
22
|
+
args.push(((err, ...values) => {
|
|
23
|
+
if (err) {
|
|
24
|
+
return reject(err);
|
|
25
|
+
}
|
|
26
|
+
if (multiArgs) {
|
|
27
|
+
resolve(values);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
resolve(values[0]);
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
// call the original function with the updated args
|
|
34
|
+
fn.call(options.context || this, ...args);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
if (options.copyProps) {
|
|
38
|
+
copyOwnProperties(fn, promisifiedFn);
|
|
39
|
+
}
|
|
40
|
+
Object.defineProperty(promisifiedFn, "__isPromisified__", {
|
|
41
|
+
value: true,
|
|
42
|
+
writable: false,
|
|
43
|
+
enumerable: false,
|
|
44
|
+
configurable: true,
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(promisifiedFn, "length", {
|
|
47
|
+
value: fn.length,
|
|
48
|
+
writable: false,
|
|
49
|
+
enumerable: false,
|
|
50
|
+
configurable: false,
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(promisifiedFn, "name", {
|
|
53
|
+
value: fn.name + options.suffix,
|
|
54
|
+
writable: false,
|
|
55
|
+
enumerable: false,
|
|
56
|
+
configurable: false,
|
|
57
|
+
});
|
|
58
|
+
return promisifiedFn;
|
|
59
|
+
}
|
package/dist/using.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AveAzulClass } from "./aveazul.js";
|
|
2
|
+
/**
|
|
3
|
+
* The using function is a utility function that allows you to acquire resources,
|
|
4
|
+
* process them, and then dispose of them in an error-safe manner.
|
|
5
|
+
*
|
|
6
|
+
* @param resources - An array of resources to acquire.
|
|
7
|
+
* @param handler - A function that will be called with the acquired resources.
|
|
8
|
+
* @param PromiseCtor - The Promise implementation to use. AveAzul or Bluebird.
|
|
9
|
+
* @param asArray - Whether to return the result as an array.
|
|
10
|
+
* @returns A promise that resolves to the result of the handler function.
|
|
11
|
+
*/
|
|
12
|
+
export declare function using<R>(resources: any[], handler: (...args: any[]) => R, PromiseCtor: AveAzulClass, asArray: boolean): any;
|
package/dist/using.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Disposer } from "./disposer.js";
|
|
2
|
+
import { isPromise } from "./util.js";
|
|
3
|
+
import { AggregateError } from "@jchip/error";
|
|
4
|
+
const SYM_FN_DISPOSE = Symbol("fnDispose");
|
|
5
|
+
/**
|
|
6
|
+
* The using function is a utility function that allows you to acquire resources,
|
|
7
|
+
* process them, and then dispose of them in an error-safe manner.
|
|
8
|
+
*
|
|
9
|
+
* @param resources - An array of resources to acquire.
|
|
10
|
+
* @param handler - A function that will be called with the acquired resources.
|
|
11
|
+
* @param PromiseCtor - The Promise implementation to use. AveAzul or Bluebird.
|
|
12
|
+
* @param asArray - Whether to return the result as an array.
|
|
13
|
+
* @returns A promise that resolves to the result of the handler function.
|
|
14
|
+
*/
|
|
15
|
+
export function using(resources, handler, PromiseCtor, asArray) {
|
|
16
|
+
if (typeof handler !== "function") {
|
|
17
|
+
throw new TypeError("handler must be a function");
|
|
18
|
+
}
|
|
19
|
+
// resources is guaranateed to be an array of disposer, promise like, or any value
|
|
20
|
+
// first process all resources by mapping the resources array:
|
|
21
|
+
// 1. if it's a disposer, get its promise and resolve its value
|
|
22
|
+
// 2. if it's a promise like, get its value
|
|
23
|
+
// 3. otherwise, return the value
|
|
24
|
+
// Expect Promise to be AveAzul or Bluebird that has map method
|
|
25
|
+
const acquisitionErrors = [];
|
|
26
|
+
// Helper function to process a disposer
|
|
27
|
+
const processDisposer = async (resource, disposer) => {
|
|
28
|
+
try {
|
|
29
|
+
const res = await disposer._promise;
|
|
30
|
+
resource._result = res;
|
|
31
|
+
resource[SYM_FN_DISPOSE] = disposer._data;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
acquisitionErrors.push(error);
|
|
35
|
+
resource._error = error;
|
|
36
|
+
}
|
|
37
|
+
return resource;
|
|
38
|
+
};
|
|
39
|
+
// Helper to check if something is a disposer
|
|
40
|
+
const isDisposer = (obj) => obj != null &&
|
|
41
|
+
(obj instanceof Disposer ||
|
|
42
|
+
(obj._promise !== undefined &&
|
|
43
|
+
typeof obj._data === "function"));
|
|
44
|
+
const acquireResources = () => {
|
|
45
|
+
const promiseRes = resources.map((resource) => {
|
|
46
|
+
// if it's a promise-like, wait for its resolved value
|
|
47
|
+
if (isPromise(resource)) {
|
|
48
|
+
return { ___promise: resource };
|
|
49
|
+
}
|
|
50
|
+
return resource;
|
|
51
|
+
});
|
|
52
|
+
return PromiseCtor.map(promiseRes, async (resource) => {
|
|
53
|
+
// If it's directly a disposer
|
|
54
|
+
if (isDisposer(resource)) {
|
|
55
|
+
return processDisposer({}, resource);
|
|
56
|
+
}
|
|
57
|
+
// if it's a promise like, wait for its resolved value
|
|
58
|
+
if (resource && resource.___promise) {
|
|
59
|
+
try {
|
|
60
|
+
const res = await resource.___promise;
|
|
61
|
+
// Check if the resolved value is a disposer
|
|
62
|
+
if (isDisposer(res)) {
|
|
63
|
+
return processDisposer(resource, res);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
resource._result = res;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
acquisitionErrors.push(error);
|
|
71
|
+
resource._error = error;
|
|
72
|
+
}
|
|
73
|
+
return resource;
|
|
74
|
+
}
|
|
75
|
+
return { _result: resource };
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
const disposeResources = (processedResources) => {
|
|
79
|
+
const errors = [];
|
|
80
|
+
return (PromiseCtor.each(processedResources, async (resource) => {
|
|
81
|
+
// dispose all resources that were acquired without errors
|
|
82
|
+
if (resource && resource[SYM_FN_DISPOSE]) {
|
|
83
|
+
try {
|
|
84
|
+
await resource[SYM_FN_DISPOSE](resource._result);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
errors.push(error);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
})).finally(() => {
|
|
91
|
+
if (errors.length > 0) {
|
|
92
|
+
PromiseCtor.___throwUncaughtError(new AggregateError(errors, "cleanup resources failed"));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
return acquireResources().then((processedResources) => {
|
|
97
|
+
if (acquisitionErrors.length > 0) {
|
|
98
|
+
return disposeResources(processedResources).tap(() => {
|
|
99
|
+
throw acquisitionErrors[0];
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
// now collect all the results into an array
|
|
103
|
+
const results = [];
|
|
104
|
+
for (const resource of processedResources) {
|
|
105
|
+
results.push(resource._result);
|
|
106
|
+
}
|
|
107
|
+
let handlerPromise;
|
|
108
|
+
try {
|
|
109
|
+
// now call the handler with the results
|
|
110
|
+
handlerPromise = PromiseCtor.resolve(asArray ? handler(results) : handler(...results));
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
// catch sync error from handler
|
|
114
|
+
handlerPromise = PromiseCtor.reject(error);
|
|
115
|
+
}
|
|
116
|
+
return handlerPromise
|
|
117
|
+
.tap(() => {
|
|
118
|
+
return disposeResources(processedResources);
|
|
119
|
+
})
|
|
120
|
+
.tapCatch(() => {
|
|
121
|
+
return disposeResources(processedResources);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export declare function isClass(fn: unknown): fn is Function;
|
|
2
|
+
export declare function isIdentifier(str: string): boolean;
|
|
3
|
+
export declare function copyOwnProperties(source: object, target: object, filter?: (key: string) => boolean): void;
|
|
4
|
+
/**
|
|
5
|
+
* Copied from bluebird/js/release/util.js
|
|
6
|
+
*/
|
|
7
|
+
export declare function isPromisified(fn: unknown): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Determines if an object is a Promise instance
|
|
10
|
+
* @param obj - The object to check
|
|
11
|
+
* @returns True if the object is a Promise instance, false otherwise
|
|
12
|
+
*/
|
|
13
|
+
export declare function isPromise(obj: unknown): obj is Promise<unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* Gets all property keys from an object and its prototype chain, excluding standard
|
|
16
|
+
* prototypes like Object.prototype, Array.prototype, and Function.prototype
|
|
17
|
+
*
|
|
18
|
+
* @param obj - The target object to get keys from
|
|
19
|
+
* @param excludedProtos - An array of prototype objects to exclude keys from
|
|
20
|
+
* @returns Array of property keys
|
|
21
|
+
*/
|
|
22
|
+
export declare function getObjectDataKeys(obj: object | null, excludedProtos?: object[]): string[];
|
|
23
|
+
/**
|
|
24
|
+
* Triggers an uncaught exception in a safe way by scheduling it on the next event loop tick
|
|
25
|
+
* This is used for fatal errors that should crash the process
|
|
26
|
+
* @param error - The error to throw
|
|
27
|
+
*/
|
|
28
|
+
export declare function triggerUncaughtException(error: unknown): void;
|
|
29
|
+
export declare function toArray<T>(args: Iterable<T> | ArrayLike<T>): T[];
|
package/dist/util.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines if a function is a class (either ES6 class or ES5 constructor function)
|
|
3
|
+
* This function performs several checks to identify different class patterns:
|
|
4
|
+
* 1. ES6 classes with the 'class' keyword
|
|
5
|
+
* 2. Constructor functions (ES5 classes) with prototype methods
|
|
6
|
+
*
|
|
7
|
+
* @param fn - The value to check
|
|
8
|
+
* @returns True if the function is a class, false otherwise
|
|
9
|
+
*/
|
|
10
|
+
const thisAssignmentPattern = /this\s*\.\s*\S+\s*=/;
|
|
11
|
+
export function isClass(fn) {
|
|
12
|
+
try {
|
|
13
|
+
if (typeof fn === "function") {
|
|
14
|
+
const keys = Object.getOwnPropertyNames(fn.prototype);
|
|
15
|
+
const hasMethods = keys.length > 1;
|
|
16
|
+
const hasMethodsOtherThanConstructor = keys.length > 0 && !(keys.length === 1 && keys[0] === "constructor");
|
|
17
|
+
const hasThisAssignmentAndStaticMethods = thisAssignmentPattern.test(fn + "") &&
|
|
18
|
+
Object.getOwnPropertyNames(fn).length > 0;
|
|
19
|
+
if (hasMethods ||
|
|
20
|
+
hasMethodsOtherThanConstructor ||
|
|
21
|
+
hasThisAssignmentAndStaticMethods) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
catch (_a) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const rident = /^[a-z$_][a-z$_0-9]*$/i;
|
|
32
|
+
export function isIdentifier(str) {
|
|
33
|
+
return rident.test(str);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Prop filtering code copied from bluebird/js/release
|
|
37
|
+
*/
|
|
38
|
+
const noCopyProps = [
|
|
39
|
+
"arity",
|
|
40
|
+
"length",
|
|
41
|
+
"name",
|
|
42
|
+
"arguments",
|
|
43
|
+
"caller",
|
|
44
|
+
"callee",
|
|
45
|
+
"prototype",
|
|
46
|
+
"__isPromisified__",
|
|
47
|
+
];
|
|
48
|
+
const noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$");
|
|
49
|
+
function propsFilter(key) {
|
|
50
|
+
return !noCopyPropsPattern.test(key);
|
|
51
|
+
}
|
|
52
|
+
export function copyOwnProperties(source, target, filter = propsFilter) {
|
|
53
|
+
const names = Object.getOwnPropertyNames(source);
|
|
54
|
+
for (const name of names) {
|
|
55
|
+
if (filter(name)) {
|
|
56
|
+
Object.defineProperty(target, name, Object.getOwnPropertyDescriptor(source, name));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Copied from bluebird/js/release/util.js
|
|
62
|
+
*/
|
|
63
|
+
export function isPromisified(fn) {
|
|
64
|
+
try {
|
|
65
|
+
return fn.__isPromisified__ === true;
|
|
66
|
+
}
|
|
67
|
+
catch (_a) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Determines if an object is a Promise instance
|
|
73
|
+
* @param obj - The object to check
|
|
74
|
+
* @returns True if the object is a Promise instance, false otherwise
|
|
75
|
+
*/
|
|
76
|
+
export function isPromise(obj) {
|
|
77
|
+
return (obj instanceof Promise ||
|
|
78
|
+
(obj != null &&
|
|
79
|
+
typeof obj === "object" &&
|
|
80
|
+
typeof obj.then === "function" &&
|
|
81
|
+
typeof obj.catch === "function"));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Gets all property keys from an object and its prototype chain, excluding standard
|
|
85
|
+
* prototypes like Object.prototype, Array.prototype, and Function.prototype
|
|
86
|
+
*
|
|
87
|
+
* @param obj - The target object to get keys from
|
|
88
|
+
* @param excludedProtos - An array of prototype objects to exclude keys from
|
|
89
|
+
* @returns Array of property keys
|
|
90
|
+
*/
|
|
91
|
+
export function getObjectDataKeys(obj, excludedProtos = []) {
|
|
92
|
+
const excludedPrototypes = [
|
|
93
|
+
Array.prototype,
|
|
94
|
+
Object.prototype,
|
|
95
|
+
Function.prototype,
|
|
96
|
+
...excludedProtos,
|
|
97
|
+
];
|
|
98
|
+
const isExcludedProto = function (val) {
|
|
99
|
+
for (const protoVal of excludedPrototypes) {
|
|
100
|
+
if (protoVal === val) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return false;
|
|
105
|
+
};
|
|
106
|
+
const ret = [];
|
|
107
|
+
const visitedKeys = Object.create(null);
|
|
108
|
+
/* copied from bluebird/js/release/util.js and modified */
|
|
109
|
+
while (obj && !isExcludedProto(obj)) {
|
|
110
|
+
let keys;
|
|
111
|
+
try {
|
|
112
|
+
keys = Object.getOwnPropertyNames(obj);
|
|
113
|
+
}
|
|
114
|
+
catch (_a) {
|
|
115
|
+
/* istanbul ignore next */
|
|
116
|
+
return ret;
|
|
117
|
+
}
|
|
118
|
+
for (const key of keys) {
|
|
119
|
+
/* istanbul ignore if */
|
|
120
|
+
if (visitedKeys[key]) {
|
|
121
|
+
/* istanbul ignore next */
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
visitedKeys[key] = true;
|
|
125
|
+
const desc = Object.getOwnPropertyDescriptor(obj, key);
|
|
126
|
+
/**
|
|
127
|
+
* When desc.get && desc.set are falsy, it means the property is a data
|
|
128
|
+
* property that holds an actual value, rather than being computed dynamically
|
|
129
|
+
* through getter/setter functions.
|
|
130
|
+
*/
|
|
131
|
+
/* istanbul ignore next */
|
|
132
|
+
if (desc && !desc.get && !desc.set) {
|
|
133
|
+
ret.push(key);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
obj = Object.getPrototypeOf(obj);
|
|
137
|
+
}
|
|
138
|
+
return ret;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Triggers an uncaught exception in a safe way by scheduling it on the next event loop tick
|
|
142
|
+
* This is used for fatal errors that should crash the process
|
|
143
|
+
* @param error - The error to throw
|
|
144
|
+
*/
|
|
145
|
+
export function triggerUncaughtException(error) {
|
|
146
|
+
let err;
|
|
147
|
+
if (!(error instanceof Error)) {
|
|
148
|
+
err = new Error(String(error));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
err = error;
|
|
152
|
+
}
|
|
153
|
+
// Use setTimeout with 0ms delay to throw on the next event loop tick
|
|
154
|
+
// This ensures the current execution context completes first
|
|
155
|
+
setTimeout(() => {
|
|
156
|
+
throw err;
|
|
157
|
+
}, 0);
|
|
158
|
+
}
|
|
159
|
+
export function toArray(args) {
|
|
160
|
+
if (!Array.isArray(args)) {
|
|
161
|
+
// Check if args is iterable
|
|
162
|
+
if (args != null &&
|
|
163
|
+
typeof args[Symbol.iterator] === "function") {
|
|
164
|
+
// Convert iterable to array, must do this to get the length, in order
|
|
165
|
+
// to detect if too many errors occurred and completion is impossible.
|
|
166
|
+
args = Array.from(args);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
throw new TypeError("expecting an array or an iterable object but got " + args);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return args;
|
|
173
|
+
}
|