@nejs/basic-extensions 1.4.1 → 1.5.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.
Files changed (47) hide show
  1. package/dist/@nejs/basic-extensions.bundle.1.4.1.js +2 -0
  2. package/dist/@nejs/basic-extensions.bundle.1.4.1.js.map +7 -0
  3. package/dist/cjs/asyncIterable.d.ts +3 -0
  4. package/dist/cjs/asyncIterable.js +203 -0
  5. package/dist/cjs/descriptor.d.ts +1 -1
  6. package/dist/cjs/descriptor.js +16 -3
  7. package/dist/cjs/globals.js +55 -67
  8. package/dist/cjs/index.d.ts +9 -2
  9. package/dist/cjs/index.js +27 -10
  10. package/dist/cjs/iterable.d.ts +3 -0
  11. package/dist/cjs/iterable.js +199 -0
  12. package/dist/cjs/objectextensions.js +9 -0
  13. package/dist/cjs/refset.d.ts +2 -0
  14. package/dist/cjs/refset.js +374 -0
  15. package/dist/cjs/symbolextensions.js +43 -0
  16. package/dist/cjs/weakrefextensions.d.ts +2 -0
  17. package/dist/cjs/weakrefextensions.js +18 -0
  18. package/dist/mjs/asyncIterable.d.ts +3 -0
  19. package/dist/mjs/asyncIterable.js +188 -0
  20. package/dist/mjs/descriptor.d.ts +1 -1
  21. package/dist/mjs/descriptor.js +14 -1
  22. package/dist/mjs/globals.js +55 -67
  23. package/dist/mjs/index.d.ts +9 -2
  24. package/dist/mjs/index.js +20 -10
  25. package/dist/mjs/iterable.d.ts +3 -0
  26. package/dist/mjs/iterable.js +184 -0
  27. package/dist/mjs/objectextensions.js +9 -0
  28. package/dist/mjs/refset.d.ts +2 -0
  29. package/dist/mjs/refset.js +352 -0
  30. package/dist/mjs/symbolextensions.js +43 -0
  31. package/dist/mjs/weakrefextensions.d.ts +2 -0
  32. package/dist/mjs/weakrefextensions.js +15 -0
  33. package/package.json +2 -2
  34. package/src/asyncIterable.js +208 -0
  35. package/src/descriptor.js +16 -1
  36. package/src/globals.js +58 -78
  37. package/src/index.js +35 -10
  38. package/src/iterable.js +203 -0
  39. package/src/objectextensions.js +12 -0
  40. package/src/refset.js +414 -0
  41. package/src/symbolextensions.js +46 -0
  42. package/src/weakrefextensions.js +18 -0
  43. package/tests/asyncIterable.test.js +44 -0
  44. package/tests/iterable.test.js +45 -0
  45. package/tests/refset.test.js +58 -0
  46. package/dist/@nejs/basic-extensions.bundle.1.4.0.js +0 -2
  47. package/dist/@nejs/basic-extensions.bundle.1.4.0.js.map +0 -7
package/src/globals.js CHANGED
@@ -5,51 +5,22 @@ const { isClass, isFunction } = FunctionExtensions.patchEntries.isClass.computed
5
5
  const CustomInspect = Symbol.for('nodejs.util.inspect.custom')
6
6
 
7
7
  export const GlobalFunctionsAndProps = new Patch(globalThis, {
8
- asBigIntObject(
9
- bigIntPrimitive
10
- ) {
11
- const base = { configurable: true, enumerable: false }
12
- const object = { value: bigIntPrimitive }
13
-
14
- Object.defineProperties(object, {
15
- // @ts-ignore
16
- [Symbol.toPrimitive]: { value: function() { return bigIntPrimitive }, ...base },
17
- [Symbol.toStringTag]: { value: BigInt.name, ...base },
18
- [Symbol.species]: { get() { return BigInt }, ...base },
19
- [CustomInspect]: { ...base, value(depth, opts, inspect) {
20
- return inspect(this[Symbol.toPrimitive](), { ...opts, depth })
21
- }}
22
- })
23
-
24
- Object.setPrototypeOf(object, BigInt.prototype)
25
-
26
- Reflect.ownKeys(BigInt.prototype).forEach(key => {
27
- if (typeof object[key] !== 'function') {
28
- return
29
- }
30
-
31
- object[key] = (function (...args) {
32
- return BigInt.prototype[key].apply(this, args)
33
- }).bind(object.value)
34
- })
35
-
36
- return object
37
- },
38
-
39
8
  /**
40
- * Transforms an object to mimic a specified prototype, altering its type conversion
41
- * and inspection behaviors. This function is especially useful for creating objects
42
- * that need to behave like different primitive types under various operations.
9
+ * Transforms an object to mimic a specified prototype, altering its type
10
+ * conversion and inspection behaviors. This function is especially useful
11
+ * for creating objects that need to behave like different primitive types
12
+ * under various operations.
43
13
  *
44
14
  * @param {Object} object - The object to be transformed.
45
- * @param {Function|Object} [prototype=String.prototype] - The prototype or class to
46
- * emulate. If a function is provided, its prototype is used. Defaults to
47
- * String.prototype.
48
- * @param {Function} [toPrimitive=(hint, val) => String(val)] - A function defining how
49
- * the object should be converted to a primitive value. It receives a type hint
50
- * ('number', 'string', or 'default') and the object, returning the primitive value.
51
- * @returns {Object|null} The transformed object, or null if neither a class nor a
52
- * prototype could be derived from the provided prototype parameter.
15
+ * @param {Function|Object} [prototype=String.prototype] - The prototype or
16
+ * class to emulate. If a function is provided, its prototype is used.
17
+ * Defaults to String.prototype.
18
+ * @param {Function} [toPrimitive=(hint, val) => String(val)] - A function
19
+ * defining how the object should be converted to a primitive value. It
20
+ * receives a type hint ('number', 'string', or 'default') and the object,
21
+ * returning the primitive value.
22
+ * @returns {Object|null} The transformed object, or null if neither a class
23
+ * nor a prototype could be derived from the provided prototype parameter.
53
24
  */
54
25
  maskAs(object, classPrototype, options) {
55
26
  const {
@@ -67,9 +38,12 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
67
38
 
68
39
  Object.setPrototypeOf(object, proto)
69
40
  Object.defineProperties(object, {
70
- valueOf: { value() { return String(toPrimitive('default', object)) }, ...base },
41
+ valueOf: {
42
+ value() { return String(toPrimitive('default', object)) }, ...base },
71
43
 
72
- [Symbol.toPrimitive]: { value(hint) { return toPrimitive(hint, object) }, ...base },
44
+ [Symbol.toPrimitive]: {
45
+ value(hint) { return toPrimitive(hint, object) }, ...base
46
+ },
73
47
  [Symbol.toStringTag]: { value: klass.name, ...base },
74
48
  [Symbol.species]: { get() { return klass }, ...base },
75
49
  [CustomInspect]: { ...base, value(depth, opts, inspect) {
@@ -81,18 +55,19 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
81
55
  },
82
56
 
83
57
  /**
84
- * Masks an object as a string-like object by setting its prototype to String and
85
- * defining how it converts to primitive types. This is particularly useful when an
86
- * object needs to behave like a string in certain contexts, such as type coercion or
87
- * logging.
58
+ * Masks an object as a string-like object by setting its prototype to
59
+ * String and defining how it converts to primitive types. This is
60
+ * particularly useful when an object needs to behave like a string in
61
+ * certain contexts, such as type coercion or logging.
88
62
  *
89
63
  * @param {Object} object - The object to be masked as a string.
90
- * @param {string} [stringKey='value'] - The object property key used for the string
91
- * representation. Defaults to 'value'.
92
- * @param {Function} [toPrimitive] - Optional custom function for primitive conversion.
93
- * If omitted, a default function handling various conversion hints is used.
94
- * @returns {Object|null} The string-masked object, or null if the object doesn't have
95
- * the specified stringKey property.
64
+ * @param {string} [stringKey='value'] - The object property key used for
65
+ * the string representation. Defaults to 'value'.
66
+ * @param {Function} [toPrimitive] - Optional custom function for primitive
67
+ * conversion. If omitted, a default function handling various conversion
68
+ * hints is used.
69
+ * @returns {Object|null} The string-masked object, or null if the object
70
+ * doesn't have the specified stringKey property.
96
71
  */
97
72
  maskAsString(
98
73
  object,
@@ -107,17 +82,17 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
107
82
  },
108
83
 
109
84
  /**
110
- * Masks an object as a number-like object. This allows the object to behave like a
111
- * number in operations like arithmetic and type coercion. It sets the prototype to
112
- * Number and defines custom conversion behavior.
85
+ * Masks an object as a number-like object. This allows the object to
86
+ * behave like a number in operations like arithmetic and type coercion.
87
+ * It sets the prototype to Number and defines custom conversion behavior.
113
88
  *
114
- * @param {Object} object - The object to be masked as a number representation.
115
- * Defaults to 'value'.
89
+ * @param {Object} object - The object to be masked as a number
90
+ * representation. Defaults to 'value'.
116
91
  * @param {Function} [toPrimitive] - Optional custom function for primitive
117
- * conversion. If not provided, a default function handling different conversion
118
- * hints is used.
119
- * @returns {Object|null} The number-masked object, or null if the object doesn't
120
- * have the specified numberKey property.
92
+ * conversion. If not provided, a default function handling different
93
+ * conversion hints is used.
94
+ * @returns {Object|null} The number-masked object, or null if the object
95
+ * doesn't have the specified numberKey property.
121
96
  */
122
97
  maskAsNumber(
123
98
  object,
@@ -135,8 +110,8 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
135
110
  * Generates options for generic masking of an object, providing defaults for
136
111
  * prototype and toPrimitive function if not specified.
137
112
  *
138
- * @param {Object} options - The options object including prototype, targetKey,
139
- * and toPrimitive function.
113
+ * @param {Object} options - The options object including prototype,
114
+ * targetKey, and toPrimitive function.
140
115
  * @returns {Object} The options object with defaults applied as necessary.
141
116
  */
142
117
  GenericMask({ prototype, targetKey = 'value', toPrimitive }) {
@@ -145,14 +120,18 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
145
120
  if (!isFunction(toPrimitive)) {
146
121
  options.toPrimitive = (hint, object) => {
147
122
  let property = object[targetKey];
148
- let isNum = (typeof property === 'number' && Number.isFinite(property)) ||
149
- (typeof property === 'string' &&
150
- !isNaN(parseFloat(property)) && isFinite(property)
151
- );
123
+ let isNum = (
124
+ (typeof property === 'number' && Number.isFinite(property)) ||
125
+ (typeof property === 'string' &&
126
+ !isNaN(parseFloat(property)) && isFinite(property)
127
+ )
128
+ );
152
129
 
153
130
  switch (hint) {
154
- case 'string': return isNum ? String(property) : (property ?? String(object));
155
- case 'number': return isNum ? Number(property) : NaN;
131
+ case 'string':
132
+ return isNum ? String(property) : (property ?? String(object));
133
+ case 'number':
134
+ return isNum ? Number(property) : NaN;
156
135
  case 'default':
157
136
  default:
158
137
  return isNum ? Number(property) : property;
@@ -164,10 +143,11 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
164
143
  },
165
144
 
166
145
  /**
167
- * Generates options for string masking of an object, providing a default toPrimitive
168
- * function if not specified.
146
+ * Generates options for string masking of an object, providing a default
147
+ * toPrimitive function if not specified.
169
148
  *
170
- * @param {string} targetKey - The object property key for string representation.
149
+ * @param {string} targetKey - The object property key for string
150
+ * representation.
171
151
  * @param {Function} toPrimitive - Custom function for primitive conversion.
172
152
  * @returns {Object} Options for string masking.
173
153
  */
@@ -189,10 +169,11 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
189
169
  },
190
170
 
191
171
  /**
192
- * Generates options for number masking of an object, providing a default toPrimitive
193
- * function if not specified.
172
+ * Generates options for number masking of an object, providing a default
173
+ * toPrimitive function if not specified.
194
174
  *
195
- * @param {string} targetKey - The object property key for number representation.
175
+ * @param {string} targetKey - The object property key for number
176
+ * representation.
196
177
  * @param {Function} toPrimitive - Custom function for primitive conversion.
197
178
  * @returns {Object} Options for number masking.
198
179
  */
@@ -212,5 +193,4 @@ export const GlobalFunctionsAndProps = new Patch(globalThis, {
212
193
 
213
194
  return options
214
195
  },
215
-
216
196
  })
package/src/index.js CHANGED
@@ -4,8 +4,19 @@ import { ReflectExtensions } from './reflectextensions.js'
4
4
  import { StringExtensions } from './stringextensions.js'
5
5
  import { SymbolExtensions } from './symbolextensions.js'
6
6
  import { ArrayPrototypeExtensions } from './arrayextensions.js'
7
- import { DescriptorExtension } from './descriptor.js'
7
+ import { DescriptorExtensions } from './descriptor.js'
8
8
  import { GlobalFunctionsAndProps } from './globals.js'
9
+ import { RefSetExtensions } from './refset.js'
10
+
11
+ import {
12
+ AsyncIteratorExtensions,
13
+ AsyncIterableExtensions
14
+ } from './asyncIterable.js'
15
+
16
+ import {
17
+ IteratorExtensions,
18
+ IterableExtensions
19
+ } from './iterable.js'
9
20
 
10
21
  import { Patch } from '@nejs/extension'
11
22
 
@@ -21,7 +32,12 @@ const Owners = [
21
32
 
22
33
  const NetNew = [
23
34
  GlobalFunctionsAndProps,
24
- DescriptorExtension,
35
+ DescriptorExtensions,
36
+ AsyncIterableExtensions,
37
+ AsyncIteratorExtensions,
38
+ IterableExtensions,
39
+ IteratorExtensions,
40
+ RefSetExtensions,
25
41
  ]
26
42
 
27
43
  export function enableAll(owners) {
@@ -35,9 +51,11 @@ export function enableAll(owners) {
35
51
  Patch.enableFor(owner)
36
52
  })
37
53
 
38
- NetNew.forEach(extension => {
39
- extension.apply()
40
- })
54
+ enableNetNew()
55
+ }
56
+
57
+ export function enableNetNew() {
58
+ NetNew.forEach(extension => { extension.apply() })
41
59
  }
42
60
 
43
61
  export function disableAll(owners) {
@@ -51,9 +69,11 @@ export function disableAll(owners) {
51
69
  Patch.disableFor(owner)
52
70
  })
53
71
 
54
- NetNew.forEach(extension => {
55
- extension.revert()
56
- })
72
+ disableNetNew()
73
+ }
74
+
75
+ export function disableNetNew() {
76
+ NetNew.forEach(extension => { extension.revert() })
57
77
  }
58
78
 
59
79
  export const all = (() => {
@@ -66,7 +86,7 @@ export const all = (() => {
66
86
  ArrayPrototypeExtensions,
67
87
 
68
88
  GlobalFunctionsAndProps,
69
- DescriptorExtension,
89
+ DescriptorExtensions,
70
90
  ]
71
91
 
72
92
  const dest = extensions.reduce((accumulator, extension) => {
@@ -91,5 +111,10 @@ export {
91
111
  ArrayPrototypeExtensions,
92
112
 
93
113
  GlobalFunctionsAndProps,
94
- DescriptorExtension,
114
+ DescriptorExtensions,
115
+ AsyncIterableExtensions,
116
+ AsyncIteratorExtensions,
117
+ IterableExtensions,
118
+ IteratorExtensions,
119
+ RefSetExtensions,
95
120
  }
@@ -0,0 +1,203 @@
1
+ import { Extension } from '@nejs/extension'
2
+
3
+ /**
4
+ * The Iterable class is designed to provide a convenient way to create synchronous
5
+ * iterable objects. It can be initialized with either an array or individual elements.
6
+ * This class implements the iterable protocol, allowing instances to be used with
7
+ * `for...of` loops and other standard JavaScript iteration mechanisms.
8
+ */
9
+ class Iterable {
10
+ /**
11
+ * Private field to store the elements of the iterable.
12
+ * @private
13
+ */
14
+ #elements = [];
15
+
16
+ /**
17
+ * Constructs an instance of Iterable. It can be initialized with either an
18
+ * iterable object (such as an array, Set, Map, string, or any object
19
+ * implementing the iterable protocol) or individual elements. If the first
20
+ * argument is an iterable, the class instance is initialized with the
21
+ * elements from the iterable, followed by any additional arguments. If the
22
+ * first argument is not an iterable, all arguments are treated as individual
23
+ * elements.
24
+ *
25
+ * @param {Iterable|*} elementsOrFirstElement - An iterable object or the
26
+ * first element.
27
+ * @param {...*} moreElements - Additional elements if the first argument is
28
+ * not an iterable.
29
+ */
30
+ constructor(elementsOrFirstElement, ...moreElements) {
31
+ if (
32
+ elementsOrFirstElement != null &&
33
+ typeof elementsOrFirstElement[Symbol.iterator] === 'function'
34
+ ) {
35
+ this.#elements = [...elementsOrFirstElement, ...moreElements];
36
+ } else {
37
+ this.#elements = [elementsOrFirstElement, ...moreElements];
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Implements the iterable protocol. When an instance of Iterable is used
43
+ * in a `for...of` loop or spread syntax, this generator function is invoked
44
+ * to yield the elements one by one in a synchronous manner.
45
+ *
46
+ * @returns {Generator} A generator that yields each element of the iterable.
47
+ */
48
+ *[Symbol.iterator]() {
49
+ for (const element of this.#elements) {
50
+ yield element;
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Provides access to the elements as a standard array. Useful for scenarios
56
+ * where array methods and behaviors are needed.
57
+ *
58
+ * @returns {Array} An array containing all the elements of the iterable.
59
+ */
60
+ get asArray() {
61
+ return this.#elements;
62
+ }
63
+
64
+ /**
65
+ * Ensures that the constructor of this object instance's name
66
+ * is returned if the string tag for this instance is queried
67
+ *
68
+ * @returns {string} the name of the class
69
+ */
70
+ get [Symbol.toStringTag]() {
71
+ return this.constructor.name
72
+ }
73
+
74
+ /**
75
+ * Being able to create a compliant `Iterator` around any type of iterable
76
+ * object. This can be wrapped around any type of object that has a
77
+ * `[Symbol.iterator]` property assigned to a generator function.
78
+ */
79
+ static Iterator = class Iterator {
80
+ /**
81
+ * Creates a new `Iterator` object instance.
82
+ *
83
+ * @param {object} iterable any object that has a `[Symbol.iterator]`
84
+ * property assigned to a generator function.
85
+ */
86
+ constructor(iterable) {
87
+ if (!iterable || !Reflect.has(iterable, Symbol.iterator)) {
88
+ throw new TypeError(
89
+ 'Value used to instantiate Iterator is not iterable'
90
+ );
91
+ }
92
+
93
+ this.#iterable = iterable;
94
+ this.#iterator = iterable[Symbol.iterator]();
95
+ }
96
+
97
+ /**
98
+ * Returns a new `Array` derived from the iterable this object
99
+ * wraps.
100
+ *
101
+ * @returns {array} a new `Array` generated from the wrapped
102
+ * iterable. The method is generated from `Array.from()`
103
+ */
104
+ get asArray() {
105
+ return Array.from(this.#iterable)
106
+ }
107
+
108
+ /**
109
+ * Returns the actual iterable object passed to the constructor that
110
+ * created this instance.
111
+ *
112
+ * @returns {object} the object containing the `[Symbol.iterator]`
113
+ */
114
+ get iterable() {
115
+ return this.#iterable
116
+ }
117
+
118
+ /**
119
+ * The function retrieves the next value in the iterator. If the
120
+ * the iterator has run its course, `reset()` can be invoked to
121
+ * reset the pointer to the beginning of the iteration.
122
+ *
123
+ * @returns {any} the next value
124
+ */
125
+ next() {
126
+ const result = this.#iterator.next();
127
+ if (result.done) {
128
+ return { value: undefined, done: true };
129
+ } else {
130
+ return { value: result.value, done: false };
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Resets the iterator to the beginning allowing it to be
136
+ * iterated over again.
137
+ */
138
+ reset() {
139
+ this.#iterator = this.#iterable[Symbol.iterator]();
140
+ }
141
+
142
+ /**
143
+ * The existence of this symbol on the object instances, indicates that
144
+ * it can be used in `for(.. of ..)` loops and its values can be
145
+ * extracted from calls to `Array.from()`
146
+ *
147
+ * @returns {Iterator} this is returned since this object is already
148
+ * conforming to the expected JavaScript Iterator interface
149
+ */
150
+ [Symbol.iterator]() {
151
+ return this;
152
+ }
153
+
154
+ /**
155
+ * Ensures that the constructor of this object instance's name
156
+ * is returned if the string tag for this instance is queried
157
+ *
158
+ * @returns {string} the name of the class
159
+ */
160
+ get [Symbol.toStringTag]() {
161
+ return this.constructor.name
162
+ }
163
+
164
+ /**
165
+ * The object from which its iterator functionality is derived.
166
+ *
167
+ * @type {object}
168
+ * @private
169
+ */
170
+ #iterable = null;
171
+
172
+ /**
173
+ * The results of a call to the iterable's `[Symbol.iterator]`
174
+ * generator function.
175
+ *
176
+ * @type {object}
177
+ * @private
178
+ */
179
+ #iterator = null;
180
+ }
181
+
182
+ /**
183
+ * Checks if a given value is an iterable. This method determines if the
184
+ * provided value has a `Symbol.iterator` property that is a generator
185
+ * function. It's a precise way to identify if the value conforms to the
186
+ * iterable protocol using a generator function.
187
+ *
188
+ * Note: This method specifically checks for generator functions. Some
189
+ * iterables might use regular functions that return an iterator, which
190
+ * this method won't identify.
191
+ *
192
+ * @param {*} value - The value to be checked for iterability.
193
+ * @returns {boolean} - Returns true if the value is an iterable implemented
194
+ * using a generator function, false otherwise.
195
+ */
196
+ static isIterable(value) {
197
+ const type = Object.prototype.toString.call(value?.[Symbol.iterator]);
198
+ return type === '[object GeneratorFunction]';
199
+ }
200
+ }
201
+
202
+ export const IterableExtensions = new Extension(Iterable)
203
+ export const IteratorExtensions = new Extension(Iterable.Iterator)
@@ -9,6 +9,10 @@ import { Patch } from '@nejs/extension';
9
9
  * utility functions.
10
10
  */
11
11
  export const ObjectExtensions = new Patch(Object, {
12
+ hasStringTag(value) {
13
+ return Object.isObject(value) && Reflect.has(value, Symbol.toStringTag)
14
+ },
15
+
12
16
  /**
13
17
  * Retrieves the string tag of an object. The string tag is a representation of
14
18
  * the object's type, as defined by its `Object.prototype.toString` method. This
@@ -19,6 +23,14 @@ export const ObjectExtensions = new Patch(Object, {
19
23
  * @returns {string} - The string tag of the object, indicating its type.
20
24
  */
21
25
  getStringTag(value) {
26
+ if (Object.hasStringTag(value)) {
27
+ return value[Symbol.toStringTag]
28
+ }
29
+
30
+ if (value && (typeof value === 'function')) {
31
+ return value.name
32
+ }
33
+
22
34
  return /\s(.+)]/.exec(Object.prototype.toString.call(value))[1];
23
35
  },
24
36