aveazul 1.0.0 → 1.0.2

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 CHANGED
@@ -1,4 +1,4 @@
1
- # AveAzul
1
+ # AveAzul.js
2
2
 
3
3
  AveAzul ("Blue Bird" in Spanish) serves as a near drop-in replacement for Bluebird. It's built on native Promise, by extending it with the familiar utility methods from Bluebird.
4
4
 
@@ -14,6 +14,10 @@ Further, if you like Bluebird's API but want to use native Promises, AveAzul giv
14
14
  - Implements most commonly used Bluebird methods
15
15
  - Comprehensive test suite ensuring compatibility
16
16
 
17
+ ## Requirements
18
+
19
+ - node.js version >= 12
20
+
17
21
  ## Installation
18
22
 
19
23
  ```bash
@@ -143,6 +147,7 @@ Key differences to be aware of:
143
147
  - `all()` - Like Promise.all(), resolves when all promises resolve, rejects if any reject
144
148
  - `call(propertyName, ...args)` - Call a method on the resolved value with the provided arguments
145
149
  - `asCallback(callback, options?)` - Register a Node-style callback that handles the resolution or rejection
150
+ - `error(handler)` - Like catch(), but only catches operational errors, letting programmer errors bubble up
146
151
 
147
152
  ### Static Methods
148
153
 
@@ -164,6 +169,10 @@ Key differences to be aware of:
164
169
  - `using(resources, fn)` - Manage resources with automatic cleanup
165
170
  - `join(...values, handler?)` - Wait for multiple promises and pass their resolved values as separate arguments to the handler function. If no handler is provided, behaves like Promise.all
166
171
 
172
+ ### Error Types
173
+
174
+ - `AveAzul.OperationalError` - Error type for representing expected operational errors (network failures, validation errors, etc.)
175
+
167
176
  ### PromisifyAll Options
168
177
 
169
178
  - `suffix` (default: 'Async') - Suffix to append to promisified method names
package/lib/any.js ADDED
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ const { toArray, isPromise } = require("./util");
4
+ const { AggregateError } = require("@jchip/error");
5
+
6
+ function addStaticAny(AveAzul, force = false) {
7
+ if (force || !AveAzul.any) {
8
+ AveAzul.any = function (args) {
9
+ try {
10
+ args = toArray(args);
11
+ } catch (error) {
12
+ return AveAzul.reject(error);
13
+ }
14
+
15
+ if (args.length === 0) {
16
+ return AveAzul.reject(
17
+ new RangeError(
18
+ "Input array must contain at least 1 items but contains only 0 items"
19
+ )
20
+ );
21
+ }
22
+
23
+ return new AveAzul((resolve, reject) => {
24
+ const len = args.length;
25
+ let settled = false;
26
+ const errors = [];
27
+
28
+ const doFinish = (value) => {
29
+ if (settled) return;
30
+ settled = true;
31
+ resolve(value);
32
+ };
33
+
34
+ const addError = (err) => {
35
+ errors.push(err);
36
+ if (!settled && errors.length >= len) {
37
+ settled = true;
38
+ reject(new AggregateError(errors));
39
+ }
40
+ };
41
+
42
+ for (let i = 0; i < len; i++) {
43
+ const arg = args[i];
44
+ if (isPromise(arg)) {
45
+ arg.then(doFinish, addError);
46
+ } else {
47
+ doFinish(arg);
48
+ }
49
+ }
50
+ });
51
+ };
52
+ }
53
+ }
54
+
55
+ module.exports.addStaticAny = addStaticAny;
package/lib/aveazul.js CHANGED
@@ -5,8 +5,9 @@ const { promisify } = require("./promisify");
5
5
  const { promisifyAll } = require("./promisify-all");
6
6
  const { Disposer } = require("./disposer");
7
7
  const { using } = require("./using");
8
- const { isPromise, triggerUncaughtException } = require("./util");
9
-
8
+ const { isPromise, triggerUncaughtException, toArray } = require("./util");
9
+ const { AggregateError } = require("@jchip/error");
10
+ const { OperationalError, isOperationalError } = require("./operational-error");
10
11
  /**
11
12
  * @fileoverview
12
13
  * AveAzul ("Blue Bird" in Spanish) - Extended Promise class that provides Bluebird like utility methods
@@ -86,20 +87,7 @@ class AveAzul extends Promise {
86
87
  */
87
88
  any() {
88
89
  return this.then((args) => {
89
- if (!Array.isArray(args)) {
90
- // Check if args is iterable
91
- if (args != null && typeof args[Symbol.iterator] === "function") {
92
- // Convert iterable to array, must do this to get the length, in order
93
- // to detect if too many errors occurred and completion is impossible.
94
- args = Array.from(args);
95
- } else {
96
- throw new TypeError(
97
- "expecting an array or an iterable object but got " + args
98
- );
99
- }
100
- }
101
-
102
- return AveAzul.any(args);
90
+ return AveAzul.any(toArray(args));
103
91
  });
104
92
  }
105
93
 
@@ -140,7 +128,12 @@ class AveAzul extends Promise {
140
128
  * @returns {Promise} Promise that rejects if timeout occurs
141
129
  */
142
130
  timeout(ms, message = "operation timed out") {
143
- return AveAzul.resolve(xaa.timeout(ms, message).run(this));
131
+ return xaa
132
+ .timeout(ms, message, {
133
+ Promise: AveAzul,
134
+ TimeoutError: OperationalError,
135
+ })
136
+ .run(this);
144
137
  }
145
138
 
146
139
  /**
@@ -291,18 +284,7 @@ class AveAzul extends Promise {
291
284
 
292
285
  some(count) {
293
286
  return this.then((args) => {
294
- if (!Array.isArray(args)) {
295
- // Check if args is iterable
296
- if (args != null && typeof args[Symbol.iterator] === "function") {
297
- // Convert iterable to array, must do this to get the length, in order
298
- // to detect if too many errors occurred and completion is impossible.
299
- args = Array.from(args);
300
- } else {
301
- throw new TypeError(
302
- "expecting an array or an iterable object but got " + args
303
- );
304
- }
305
- }
287
+ args = toArray(args);
306
288
 
307
289
  return new AveAzul((resolve, reject) => {
308
290
  // If too many promises are rejected so that the promise can never become fulfilled,
@@ -314,17 +296,23 @@ class AveAzul extends Promise {
314
296
  const results = [];
315
297
  const len = args.length;
316
298
 
299
+ let settled = false;
300
+
317
301
  const addDone = (result) => {
302
+ if (settled) return;
318
303
  results.push(result);
319
304
  if (results.length >= count) {
305
+ settled = true;
320
306
  // Resolve with exactly count results to match Bluebird's behavior
321
307
  resolve(results.slice(0, count));
322
308
  }
323
309
  };
324
310
 
325
311
  const addError = (err) => {
312
+ if (settled) return;
326
313
  errors.push(err);
327
314
  if (len - errors.length < count) {
315
+ settled = true;
328
316
  reject(new AggregateError(errors, `aggregate error`));
329
317
  }
330
318
  };
@@ -348,19 +336,7 @@ class AveAzul extends Promise {
348
336
  */
349
337
  all() {
350
338
  return this.then((value) => {
351
- if (!Array.isArray(value)) {
352
- // Check if value is iterable
353
- if (value != null && typeof value[Symbol.iterator] === "function") {
354
- // Convert iterable to array
355
- value = Array.from(value);
356
- } else {
357
- throw new TypeError(
358
- "expecting an array or an iterable object but got " + value
359
- );
360
- }
361
- }
362
-
363
- return AveAzul.all(value);
339
+ return AveAzul.all(toArray(value));
364
340
  });
365
341
  }
366
342
 
@@ -420,6 +396,21 @@ class AveAzul extends Promise {
420
396
  return obj[methodName].call(obj, ...args);
421
397
  });
422
398
  }
399
+
400
+ /**
401
+ * Catches only operational errors and passes them to the handler.
402
+ * Programmer errors (non-operational) are rethrown.
403
+ * @param {Function} handler - Function to handle operational errors
404
+ * @returns {Promise} - Promise with the error handled or rethrown
405
+ */
406
+ error(handler) {
407
+ return this.catch((err) => {
408
+ if (isOperationalError(err)) {
409
+ return handler(err);
410
+ }
411
+ throw err;
412
+ });
413
+ }
423
414
  }
424
415
 
425
416
  /**
@@ -584,7 +575,7 @@ AveAzul.using = (resources, ...args) => {
584
575
  * @returns {Promise} Promise that resolves with the handler's return value
585
576
  */
586
577
  AveAzul.join = function (...args) {
587
- if (args.length > 1 && typeof args.at(-1) === "function") {
578
+ if (args.length > 1 && typeof args[args.length - 1] === "function") {
588
579
  const handler = args.pop();
589
580
  return AveAzul.all(args).then((results) => handler(...results));
590
581
  } else {
@@ -641,8 +632,14 @@ AveAzul.some = function (promises, count) {
641
632
  return AveAzul.resolve(promises).some(count);
642
633
  };
643
634
 
635
+ const { addStaticAny } = require("./any");
636
+ addStaticAny(AveAzul);
637
+
644
638
  // Setup the not implemented methods
645
639
  const { setupNotImplemented } = require("./not-implemented");
646
640
  setupNotImplemented(AveAzul);
647
641
 
642
+ // Add these static properties after the class definition
643
+ AveAzul.OperationalError = OperationalError;
644
+
648
645
  module.exports = AveAzul;
@@ -13,7 +13,6 @@ function createInstanceNotImplemented(AveAzul) {
13
13
  "then",
14
14
  "spread",
15
15
  "catch",
16
- "error",
17
16
  "finally",
18
17
  "bind",
19
18
  "isFulfilled",
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * OperationalError class for representing errors that are expected during normal operation
5
+ * Similar to Bluebird's OperationalError
6
+ */
7
+ class OperationalError extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = "OperationalError";
11
+ this.isOperational = true;
12
+
13
+ // Capture stack trace
14
+ if (Error.captureStackTrace) {
15
+ Error.captureStackTrace(this, this.constructor);
16
+ }
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Check if an error is an operational error
22
+ * @param {*} error - Error to check
23
+ * @returns {boolean} True if the error is operational
24
+ */
25
+ function isOperationalError(error) {
26
+ if (!error || typeof error !== "object") return false;
27
+ return error instanceof OperationalError || error.isOperational === true;
28
+ }
29
+
30
+ /**
31
+ * Check if an error is a programmer error (unexpected, likely a bug)
32
+ * @param {*} error - Error to check
33
+ * @returns {boolean} True if the error is a programmer error
34
+ */
35
+ function isProgrammerError(error) {
36
+ if (!error || typeof error !== "object") return false;
37
+ return !isOperationalError(error);
38
+ }
39
+
40
+ // Only export the OperationalError class
41
+ module.exports = {
42
+ OperationalError,
43
+ // Internal utilities used by AveAzul.prototype.error
44
+ isOperationalError,
45
+ isProgrammerError,
46
+ };
@@ -4,16 +4,14 @@ const { promisify } = require("./promisify");
4
4
  const {
5
5
  isIdentifier,
6
6
  isClass,
7
- isConstructor,
8
7
  isPromisified,
9
- getObjectKeys,
10
- isExcludedPrototype,
8
+ getObjectDataKeys,
11
9
  } = require("./util");
12
10
 
13
11
  const defaultSuffix = "Async";
14
12
 
15
13
  const defaultFilter = function (name) {
16
- return isIdentifier(name) && name.charAt(0) !== "_" && name !== "constructor";
14
+ return isIdentifier(name) && name.charAt(0) !== "_" && name !== "constructor" && !name.endsWith("Sync");
17
15
  };
18
16
 
19
17
  const defaultPromisifier = (fn, _defaultPromisifier, options) => {
@@ -23,33 +21,9 @@ const defaultPromisifier = (fn, _defaultPromisifier, options) => {
23
21
  });
24
22
  };
25
23
 
26
- const excludedClasses = [Array, Object, Function];
27
-
28
- // Helper function to determine if a class extends from any excluded class
29
- function isExcludedClass(obj) {
30
- if (excludedClasses.includes(obj)) {
31
- return true;
32
- }
33
-
34
- // Check if obj extends from any excluded class using instanceof
35
- if (typeof obj === "function" && obj.prototype) {
36
- // Check if prototype is instance of any excluded class
37
- for (const excludedClass of excludedClasses) {
38
- if (obj.prototype instanceof excludedClass) {
39
- return true;
40
- }
41
- }
42
- }
43
-
44
- return false;
45
- }
46
24
 
47
25
  function promisifyAll2(obj, options) {
48
- if (isExcludedClass(obj)) {
49
- return;
50
- }
51
-
52
- const allKeys = getObjectKeys(obj);
26
+ const allKeys = getObjectDataKeys(obj);
53
27
 
54
28
  for (const key of allKeys) {
55
29
  const value = obj[key];
@@ -57,7 +31,6 @@ function promisifyAll2(obj, options) {
57
31
  const passesDefaultFilter =
58
32
  options.filter === defaultFilter ? true : defaultFilter(key, value, obj);
59
33
  if (
60
- isConstructor(value) ||
61
34
  typeof value !== "function" ||
62
35
  isPromisified(value) ||
63
36
  obj[promisifiedKey] ||
@@ -76,19 +49,16 @@ function promisifyAll2(obj, options) {
76
49
  }
77
50
 
78
51
  obj[promisifiedKey] = options.promisifier(value, defaultPromisifier, {
79
- context: obj,
52
+ // context: obj, // promisified function should get the binded object using this
80
53
  copyProps: false,
81
- multiArgs: options.multiArgs,
82
- Promise: options.Promise,
54
+ ...options
83
55
  });
84
56
  }
85
57
  }
86
58
 
87
59
  function promisifyAll(target, _options) {
88
60
  if (typeof target !== "function" && typeof target !== "object") {
89
- throw new TypeError(
90
- "the target of promisifyAll must be an object or a function"
91
- );
61
+ throw new TypeError("the target of promisifyAll must be an object or a function");
92
62
  }
93
63
 
94
64
  const options = {
@@ -107,21 +77,12 @@ function promisifyAll(target, _options) {
107
77
  );
108
78
  }
109
79
 
110
- const allKeys = getObjectKeys(target);
80
+ const allKeys = getObjectDataKeys(target);
111
81
 
112
82
  for (const key of allKeys) {
113
83
  const value = target[key];
114
- if (
115
- value &&
116
- key !== "constructor" &&
117
- !key.startsWith("_") &&
118
- isClass(value)
119
- ) {
120
- const proto = Object.getPrototypeOf(value);
121
- if (!isExcludedPrototype(proto)) {
122
- promisifyAll2(proto, options);
123
- }
124
-
84
+ if (value && key !== "constructor" && !key.startsWith("_") && isClass(value)) {
85
+ promisifyAll2(value.prototype, options);
125
86
  promisifyAll2(value, options);
126
87
  }
127
88
  }
package/lib/promisify.js CHANGED
@@ -22,7 +22,7 @@ module.exports.promisify = function promisify(fn, _options) {
22
22
  const Promise = options.Promise;
23
23
  const multiArgs = !!options.multiArgs;
24
24
 
25
- const promisifiedFn = (...args) => {
25
+ const promisifiedFn = function (...args) {
26
26
  return new Promise((resolve, reject) => {
27
27
  // add a callback to the end of the arguments to transfer the result to the promise
28
28
  args.push((err, ...values) => {
@@ -37,7 +37,7 @@ module.exports.promisify = function promisify(fn, _options) {
37
37
  });
38
38
 
39
39
  // call the original function with the updated args
40
- fn.call(options.context, ...args);
40
+ fn.call(options.context || this, ...args);
41
41
  });
42
42
  };
43
43
 
package/lib/using.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  const { Disposer } = require("./disposer");
4
4
  const { isPromise } = require("./util");
5
+ const { AggregateError } = require("@jchip/error");
5
6
 
6
7
  const SYM_FN_DISPOSE = Symbol("fnDispose");
7
8
  /**
@@ -28,6 +29,25 @@ function using(resources, handler, Promise, asArray) {
28
29
  // Expect Promise to be AveAzul or Bluebird that has map method
29
30
  const acquisitionErrors = [];
30
31
 
32
+ // Helper function to process a disposer
33
+ const processDisposer = async (resource, disposer) => {
34
+ try {
35
+ const res = await disposer._promise;
36
+ resource._result = res;
37
+ resource[SYM_FN_DISPOSE] = disposer._data;
38
+ } catch (error) {
39
+ acquisitionErrors.push(error);
40
+ resource._error = error;
41
+ }
42
+ return resource;
43
+ };
44
+
45
+ // Helper to check if something is a disposer
46
+ const isDisposer = (obj) =>
47
+ obj &&
48
+ (obj instanceof Disposer ||
49
+ (obj._promise && typeof obj._data === "function"));
50
+
31
51
  const acquireResources = () => {
32
52
  const promiseRes = resources.map((resource) => {
33
53
  // if it's a promise-like, wait for its resolved value
@@ -38,27 +58,21 @@ function using(resources, handler, Promise, asArray) {
38
58
  });
39
59
 
40
60
  return Promise.map(promiseRes, async (resource) => {
41
- if (
42
- resource &&
43
- (resource instanceof Disposer ||
44
- (resource._promise && typeof resource._data === "function"))
45
- ) {
46
- try {
47
- const res = await resource._promise;
48
- resource._result = res;
49
- resource[SYM_FN_DISPOSE] = resource._data;
50
- } catch (error) {
51
- acquisitionErrors.push(error);
52
- resource._error = error;
53
- }
54
- return resource;
61
+ // If it's directly a disposer
62
+ if (isDisposer(resource)) {
63
+ return processDisposer(resource, resource);
55
64
  }
56
65
 
57
66
  // if it's a promise like, wait for its resolved value
58
67
  if (resource && resource.___promise) {
59
68
  try {
60
69
  const res = await resource.___promise;
61
- resource._result = res;
70
+ // Check if the resolved value is a disposer
71
+ if (isDisposer(res)) {
72
+ return processDisposer(resource, res);
73
+ } else {
74
+ resource._result = res;
75
+ }
62
76
  } catch (error) {
63
77
  acquisitionErrors.push(error);
64
78
  resource._error = error;
package/lib/util.js CHANGED
@@ -11,32 +11,25 @@
11
11
  */
12
12
  const thisAssignmentPattern = /this\s*\.\s*\S+\s*=/;
13
13
  function isClass(fn) {
14
- try {
15
- if (typeof fn === "function") {
16
- const keys = Object.getOwnPropertyNames(fn.prototype);
17
-
18
- const fnStr = fn.toString();
19
- const es6Class = fnStr.startsWith("class ") || /^class\s+/.test(fnStr);
20
- const hasMethods = keys.length > 1;
21
- const hasMethodsOtherThanConstructor =
22
- keys.length > 0 && !(keys.length === 1 && keys[0] === "constructor");
23
- const hasThisAssignmentAndStaticMethods =
24
- thisAssignmentPattern.test(fnStr) &&
25
- Object.getOwnPropertyNames(fn).length > 0;
26
-
27
- if (
28
- es6Class ||
29
- hasMethods ||
30
- hasMethodsOtherThanConstructor ||
31
- hasThisAssignmentAndStaticMethods
32
- ) {
33
- return true;
34
- }
14
+ try {
15
+ if (typeof fn === "function") {
16
+ const keys = Object.getOwnPropertyNames(fn.prototype);
17
+
18
+ const hasMethods = keys.length > 1;
19
+ const hasMethodsOtherThanConstructor = keys.length > 0 &&
20
+ !(keys.length === 1 && keys[0] === "constructor");
21
+ const hasThisAssignmentAndStaticMethods =
22
+ thisAssignmentPattern.test(fn + "") && Object.getOwnPropertyNames (fn).length > 0;
23
+
24
+ if (hasMethods || hasMethodsOtherThanConstructor ||
25
+ hasThisAssignmentAndStaticMethods) {
26
+ return true;
27
+ }
28
+ }
29
+ return false;
30
+ } catch (e) {
31
+ return false;
35
32
  }
36
- return false;
37
- } catch (e) {
38
- return false;
39
- }
40
33
  }
41
34
 
42
35
  const rident = /^[a-z$_][a-z$_0-9]*$/i;
@@ -44,18 +37,6 @@ function isIdentifier(str) {
44
37
  return rident.test(str);
45
38
  }
46
39
 
47
- function isConstructor(func) {
48
- if (!func) {
49
- return false;
50
- }
51
- const proto = func.prototype;
52
- return (
53
- !!proto &&
54
- !!proto.constructor &&
55
- !!proto.constructor.name &&
56
- proto.constructor.name === func.name
57
- );
58
- }
59
40
 
60
41
  /**
61
42
  * Prop filtering code copied from bluebird/js/release
@@ -81,11 +62,7 @@ function copyOwnProperties(source, target, filter = propsFilter) {
81
62
 
82
63
  for (const name of names) {
83
64
  if (filter(name)) {
84
- Object.defineProperty(
85
- target,
86
- name,
87
- Object.getOwnPropertyDescriptor(source, name)
88
- );
65
+ Object.defineProperty(target, name, Object.getOwnPropertyDescriptor(source, name));
89
66
  }
90
67
  }
91
68
  }
@@ -118,52 +95,66 @@ function isPromise(obj) {
118
95
  );
119
96
  }
120
97
 
121
- // istanbul ignore next
122
- const emptyFatArrow = () => {};
123
- // istanbul ignore next
124
- const emptyFunction = function () {};
125
-
126
- const defaultExcluded = [
127
- Object.getPrototypeOf(Array), // Array.prototype
128
- Object.getPrototypeOf(Object), // Object.prototype
129
- Object.getPrototypeOf(Function), // Function.prototype
130
- Object.getPrototypeOf([]),
131
- Object.getPrototypeOf({}),
132
- Object.getPrototypeOf(emptyFatArrow),
133
- Object.getPrototypeOf(emptyFunction),
134
- ];
135
-
136
- function isExcludedPrototype(proto) {
137
- return defaultExcluded.includes(proto);
138
- }
139
-
140
98
  /**
141
99
  * Gets all property keys from an object and its prototype chain, excluding standard
142
100
  * prototypes like Object.prototype, Array.prototype, and Function.prototype
143
101
  *
144
- * @param {Object} target - The target object to get keys from
102
+ * @param {Object} obj - The target object to get keys from
145
103
  * @param {Array} [excludedPrototypes=[]] - An array of prototype objects to exclude keys from
146
104
  * @returns {Array<string>} - Array of property keys
147
105
  */
148
- function getObjectKeys(target, excludedPrototypes = []) {
149
- const excluded =
150
- excludedPrototypes.length > 0 ? excludedPrototypes : defaultExcluded;
151
-
152
- // Get own properties
153
- const ownKeys = Object.getOwnPropertyNames(target);
154
-
155
- // Get prototype properties, excluding those from excluded prototypes
156
- let protoKeys = [];
157
- let currentProto = Object.getPrototypeOf(target);
106
+ function getObjectDataKeys(obj, excludedProtos = []) {
107
+ const excludedPrototypes = [
108
+ Array.prototype,
109
+ Object.prototype,
110
+ Function.prototype,
111
+ ...excludedProtos,
112
+ ];
113
+
114
+ const isExcludedProto = function (val) {
115
+ for (const protoVal of excludedPrototypes) {
116
+ if (protoVal === val) {
117
+ return true;
118
+ }
119
+ }
120
+ return false;
121
+ };
122
+
123
+ const ret = [];
124
+ const visitedKeys = Object.create(null);
125
+
126
+ /* copied from bluebird/js/release/util.js and modified */
127
+ while (obj && !isExcludedProto(obj)) {
128
+ let keys;
129
+ try {
130
+ keys = Object.getOwnPropertyNames(obj);
131
+ } catch (e) {
132
+ /* istanbul ignore next */
133
+ return ret;
134
+ }
158
135
 
159
- // Walk up the prototype chain until we hit null or an excluded prototype
160
- while (currentProto && !excluded.includes(currentProto)) {
161
- protoKeys = [...protoKeys, ...Object.getOwnPropertyNames(currentProto)];
162
- currentProto = Object.getPrototypeOf(currentProto);
136
+ for (const key of keys) {
137
+ /* istanbul ignore if */
138
+ if (visitedKeys[key]) {
139
+ /* istanbul ignore next */
140
+ continue;
141
+ }
142
+ visitedKeys[key] = true;
143
+ const desc = Object.getOwnPropertyDescriptor(obj, key);
144
+ /**
145
+ * When desc.get && desc.set are falsy, it means the property is a data
146
+ * property that holds an actual value, rather than being computed dynamically
147
+ * through getter/setter functions.
148
+ */
149
+ /* istanbul ignore next */
150
+ if (desc && !desc.get && !desc.set) {
151
+ ret.push(key);
152
+ }
153
+ }
154
+ obj = Object.getPrototypeOf(obj);
163
155
  }
164
156
 
165
- // Combine own properties and prototype properties
166
- return [...protoKeys, ...ownKeys];
157
+ return ret;
167
158
  }
168
159
 
169
160
  /**
@@ -183,12 +174,26 @@ function triggerUncaughtException(error) {
183
174
  }, 0);
184
175
  }
185
176
 
177
+ function toArray(args) {
178
+ if (!Array.isArray(args)) {
179
+ // Check if args is iterable
180
+ if (args != null && typeof args[Symbol.iterator] === "function") {
181
+ // Convert iterable to array, must do this to get the length, in order
182
+ // to detect if too many errors occurred and completion is impossible.
183
+ args = Array.from(args);
184
+ } else {
185
+ throw new TypeError("expecting an array or an iterable object but got " + args);
186
+ }
187
+ }
188
+
189
+ return args;
190
+ }
191
+
186
192
  module.exports.copyOwnProperties = copyOwnProperties;
187
193
  module.exports.isClass = isClass;
188
194
  module.exports.isIdentifier = isIdentifier;
189
- module.exports.isConstructor = isConstructor;
190
195
  module.exports.isPromisified = isPromisified;
191
196
  module.exports.isPromise = isPromise;
192
197
  module.exports.triggerUncaughtException = triggerUncaughtException;
193
- module.exports.getObjectKeys = getObjectKeys;
194
- module.exports.isExcludedPrototype = isExcludedPrototype;
198
+ module.exports.getObjectDataKeys = getObjectDataKeys;
199
+ module.exports.toArray = toArray;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aveazul",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Bluebird drop-in replacement built on native Promise",
5
5
  "main": "lib/aveazul.js",
6
6
  "homepage": "https://github.com/jchip/aveazul",
@@ -53,18 +53,24 @@
53
53
  "any",
54
54
  "props",
55
55
  "filter",
56
- "reduce"
56
+ "reduce",
57
+ "aveazul",
58
+ "aveazul.js"
57
59
  ],
58
60
  "repository": {
59
61
  "type": "git",
60
62
  "url": "git+https://github.com/jchip/aveazul.git"
61
63
  },
62
64
  "dependencies": {
63
- "xaa": "^1.7.3"
65
+ "@jchip/error": "^1.0.3",
66
+ "xaa": "^1.8.0"
64
67
  },
65
68
  "devDependencies": {
66
69
  "bluebird": "^3.7.2",
67
- "jest": "^29.7.0",
70
+ "jest": "^28.0.0",
68
71
  "rimraf": "^3.0.1"
72
+ },
73
+ "engines": {
74
+ "node": ">=12.0.0"
69
75
  }
70
76
  }