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.
@@ -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
+ }
@@ -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
+ }