@nejs/basic-extensions 2.20.0 → 2.21.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/bin/repl.basics.js +36 -6
- package/bin/repl.signature.js +63 -0
- package/dist/@nejs/basic-extensions.bundle.2.21.0.js +25 -0
- package/dist/@nejs/basic-extensions.bundle.2.21.0.js.map +7 -0
- package/dist/cjs/classes/descriptor.d.ts +1 -1
- package/dist/cjs/classes/enum.d.ts +37 -19
- package/dist/cjs/classes/enum.js +181 -56
- package/dist/cjs/classes/enum.js.map +1 -1
- package/dist/cjs/classes/iterable.d.ts +3 -3
- package/dist/cjs/classes/param.parser.d.ts +1 -7
- package/dist/cjs/classes/pluggable.proxy.d.ts +2 -1
- package/dist/cjs/classes/property.d.ts +2 -9
- package/dist/cjs/classes/refset.d.ts +2 -2
- package/dist/cjs/classes/symkeys.d.ts +1 -1
- package/dist/cjs/global.this.js +17 -7
- package/dist/cjs/global.this.js.map +1 -1
- package/dist/cjs/index.d.ts +8 -5
- package/dist/cjs/index.js +13 -8
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/string.extensions.js +38 -0
- package/dist/cjs/string.extensions.js.map +1 -1
- package/dist/cjs/utils/copy.object.d.ts +2 -2
- package/dist/cjs/utils/descriptor.utils.d.ts +152 -0
- package/dist/cjs/utils/descriptor.utils.js +228 -9
- package/dist/cjs/utils/descriptor.utils.js.map +1 -1
- package/dist/cjs/utils/index.d.ts +15 -0
- package/dist/cjs/utils/index.js +9 -0
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/stdout.d.ts +742 -0
- package/dist/cjs/utils/stdout.js +1042 -0
- package/dist/cjs/utils/stdout.js.map +1 -0
- package/dist/mjs/classes/descriptor.d.ts +1 -1
- package/dist/mjs/classes/enum.d.ts +37 -19
- package/dist/mjs/classes/enum.js +181 -57
- package/dist/mjs/classes/enum.js.map +1 -1
- package/dist/mjs/classes/iterable.d.ts +3 -3
- package/dist/mjs/classes/param.parser.d.ts +1 -7
- package/dist/mjs/classes/pluggable.proxy.d.ts +2 -1
- package/dist/mjs/classes/property.d.ts +2 -9
- package/dist/mjs/classes/refset.d.ts +2 -2
- package/dist/mjs/classes/symkeys.d.ts +1 -1
- package/dist/mjs/index.d.ts +8 -5
- package/dist/mjs/index.js +13 -8
- package/dist/mjs/index.js.map +1 -1
- package/dist/mjs/string.extensions.js +38 -0
- package/dist/mjs/string.extensions.js.map +1 -1
- package/dist/mjs/utils/copy.object.d.ts +2 -2
- package/dist/mjs/utils/descriptor.utils.d.ts +152 -0
- package/dist/mjs/utils/descriptor.utils.js +222 -9
- package/dist/mjs/utils/descriptor.utils.js.map +1 -1
- package/dist/mjs/utils/index.d.ts +15 -0
- package/dist/mjs/utils/index.js +10 -1
- package/dist/mjs/utils/index.js.map +1 -1
- package/dist/mjs/utils/stdout.d.ts +742 -0
- package/dist/mjs/utils/stdout.js +1037 -0
- package/dist/mjs/utils/stdout.js.map +1 -0
- package/package.json +6 -20
- package/repl.bootstrap.js +24 -16
- package/repl.history +30 -30
- package/src/classes/enum.js +249 -109
- package/src/index.js +22 -8
- package/src/string.extensions.js +41 -0
- package/src/utils/descriptor.utils.js +277 -9
- package/src/utils/index.js +20 -0
- package/src/utils/stdout.js +1151 -0
- package/tests/utils/descriptor.utils.test.js +130 -0
- package/dist/@nejs/basic-extensions.bundle.2.20.0.js +0 -19
- package/dist/@nejs/basic-extensions.bundle.2.20.0.js.map +0 -7
package/src/classes/enum.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Extension } from '@nejs/extension'
|
|
2
|
-
import { accessor, as, data, isDescriptor } from '../utils/index.js'
|
|
2
|
+
import { accessor, as, data, isDescriptor, redescribe } from '../utils/index.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Creates an enumeration object with specified values and properties.
|
|
@@ -12,54 +12,32 @@ import { accessor, as, data, isDescriptor } from '../utils/index.js'
|
|
|
12
12
|
* @returns {Object} The constructed enumeration object.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
|
-
* const colors = Enum('Colors', ['red', 'green', 'blue'])
|
|
16
|
-
* console.log(colors.red) // EnumValue object for 'red'
|
|
17
|
-
*
|
|
18
|
-
* @description
|
|
19
|
-
* The `Enum` function constructs an enumeration object with a given name,
|
|
20
|
-
* values, and optional properties. It supports primitive types, arrays,
|
|
21
|
-
* and objects as values. The function uses a combination of `Object.create`
|
|
22
|
-
* and `Proxy` to define and manage the properties of the enumeration.
|
|
23
|
-
*
|
|
24
|
-
* The enumeration object includes:
|
|
25
|
-
* - A `toString` method that returns the enumeration name.
|
|
26
|
-
* - A `Symbol.toStringTag` for identifying the object as an 'Enum'.
|
|
27
|
-
* - A `Symbol.for('Enum.name')` for storing the enumeration name.
|
|
28
|
-
*
|
|
29
|
-
* For array values, it creates a maker function that returns an
|
|
30
|
-
* `EnumValue` object with properties like `real`, `value`, `type`,
|
|
31
|
-
* `name`, and `compare`.
|
|
32
|
-
*/
|
|
15
|
+
* const colors = Enum('Colors', ['red', 'green', 'blue'])
|
|
16
|
+
* console.log(colors.red) // EnumValue object for 'red'
|
|
17
|
+
*
|
|
18
|
+
* @description
|
|
19
|
+
* The `Enum` function constructs an enumeration object with a given name,
|
|
20
|
+
* values, and optional properties. It supports primitive types, arrays,
|
|
21
|
+
* and objects as values. The function uses a combination of `Object.create`
|
|
22
|
+
* and `Proxy` to define and manage the properties of the enumeration.
|
|
23
|
+
*
|
|
24
|
+
* The enumeration object includes:
|
|
25
|
+
* - A `toString` method that returns the enumeration name.
|
|
26
|
+
* - A `Symbol.toStringTag` for identifying the object as an 'Enum'.
|
|
27
|
+
* - A `Symbol.for('Enum.name')` for storing the enumeration name.
|
|
28
|
+
*
|
|
29
|
+
* For array values, it creates a maker function that returns an
|
|
30
|
+
* `EnumValue` object with properties like `real`, `value`, `type`,
|
|
31
|
+
* `name`, and `compare`.
|
|
32
|
+
*/
|
|
33
33
|
export function Enum(name, values, properties) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
let valueText = valueKeys
|
|
42
|
-
.map(key => `\x1b[1;2m${key}\x1b[22m`)
|
|
43
|
-
.join(', ')
|
|
44
|
-
|
|
45
|
-
if (valueText.length)
|
|
46
|
-
valueText = ` { ${valueText} }`
|
|
47
|
-
|
|
48
|
-
return `\x1b[1menum \x1b[22m${name}${valueText}`
|
|
49
|
-
}, false, true, false
|
|
50
|
-
),
|
|
51
|
-
toString: data(function() {
|
|
52
|
-
return `Enum(${name})`
|
|
53
|
-
}, false, true, false)
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
if (!Array.isArray(values)) {
|
|
57
|
-
values = [values]
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const asString = o => as.string(o, { description: true, stringTag: true })
|
|
61
|
-
|
|
62
|
-
/**
|
|
34
|
+
const enumeration = makeBaseEnum(name)
|
|
35
|
+
|
|
36
|
+
if (!Array.isArray(values)) {
|
|
37
|
+
values = [values]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
63
41
|
* A new base `EnumValue` type object. It contains enough custom symbols and
|
|
64
42
|
* identifiers to allow things like a `compare(to)` function to also work on
|
|
65
43
|
* each of the elements. Thing of this as the shared base functionality for
|
|
@@ -71,25 +49,25 @@ export function Enum(name, values, properties) {
|
|
|
71
49
|
* custom {@link Symbol} keys. The `node.js` custom inspect symbol is also
|
|
72
50
|
* defined for better REPL representation.
|
|
73
51
|
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
52
|
+
const makeEnumValue = (property, enumValue) => ({
|
|
53
|
+
toString: data(() => enumValue, false, true, false),
|
|
54
|
+
|
|
55
|
+
[Symbol.for('Enum.name')]: data(name, false, true, false),
|
|
56
|
+
[Symbol.for('Enum.is')]: data(true, false, false, false),
|
|
57
|
+
[Symbol.for('nodejs.util.inspect.custom')]: data(
|
|
58
|
+
function(depth, options, inspect) {
|
|
59
|
+
const _options = { ...(options || {}), colors: true }
|
|
60
|
+
const _skip = this.value === Symbol.for('Enum.NonAssociatedValue')
|
|
61
|
+
const _value = _skip
|
|
62
|
+
? ''
|
|
63
|
+
: ` { value: ${inspect(this.value, _options) } }`;
|
|
64
|
+
|
|
65
|
+
return `${property}${_value}`
|
|
66
|
+
},
|
|
67
|
+
false, true, false
|
|
68
|
+
),
|
|
69
|
+
[Symbol.toStringTag]: accessor('EnumValue', false, true, false),
|
|
70
|
+
[Symbol.for('compare')]: data(
|
|
93
71
|
function compareValue(to) {
|
|
94
72
|
const toObj = (to && typeof to === 'object') ? to : { real: to }
|
|
95
73
|
const kName = Symbol.for('Enum.name')
|
|
@@ -110,8 +88,8 @@ export function Enum(name, values, properties) {
|
|
|
110
88
|
lName === rName && lType === rType &&
|
|
111
89
|
lReal === rReal && lValue === rValue
|
|
112
90
|
)
|
|
113
|
-
|
|
114
|
-
|
|
91
|
+
}, false, true, false),
|
|
92
|
+
[Symbol.toPrimitive]: data(
|
|
115
93
|
function EnumValueToPrimitive(hint) {
|
|
116
94
|
const original = this.real
|
|
117
95
|
const type = typeof original
|
|
@@ -140,9 +118,9 @@ export function Enum(name, values, properties) {
|
|
|
140
118
|
}
|
|
141
119
|
},
|
|
142
120
|
false, true, false),
|
|
143
|
-
|
|
121
|
+
})
|
|
144
122
|
|
|
145
|
-
|
|
123
|
+
/**
|
|
146
124
|
* Given a value, determine how to represent it as both a key and a response
|
|
147
125
|
* or underlying original value. The method for this is dependent on the type
|
|
148
126
|
* of the value itself.
|
|
@@ -151,7 +129,7 @@ export function Enum(name, values, properties) {
|
|
|
151
129
|
* @returns {[string, any]} an array where the first value is the transformed
|
|
152
130
|
* value as a key and the second element is the originally supplied value.
|
|
153
131
|
*/
|
|
154
|
-
|
|
132
|
+
const fromPrimitive = (value) => {
|
|
155
133
|
let valueType = typeof value
|
|
156
134
|
|
|
157
135
|
switch (valueType) {
|
|
@@ -173,17 +151,17 @@ export function Enum(name, values, properties) {
|
|
|
173
151
|
return [str, str]
|
|
174
152
|
}
|
|
175
153
|
}
|
|
176
|
-
|
|
154
|
+
}
|
|
177
155
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
156
|
+
// Determine the keys that the final proxy should be aware of when computing
|
|
157
|
+
// the enumeration value itself.
|
|
158
|
+
const kValueProps = ['real', 'value', 'type', 'name', 'compare', 'isEnum']
|
|
159
|
+
const kCustomPropKeys = []
|
|
182
160
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
161
|
+
// Capture and calculate any custom properties defined for each element
|
|
162
|
+
// of the enumeration. Each custom property is appended to `kCustomPropKeys`
|
|
163
|
+
const props = {}
|
|
164
|
+
if (properties) {
|
|
187
165
|
if (Array.isArray(properties)) {
|
|
188
166
|
const entries = properties.filter(e => Array.isArray(e) && e.length === 2)
|
|
189
167
|
|
|
@@ -234,14 +212,13 @@ export function Enum(name, values, properties) {
|
|
|
234
212
|
props[property] = value
|
|
235
213
|
}
|
|
236
214
|
}
|
|
237
|
-
|
|
215
|
+
}
|
|
238
216
|
|
|
239
|
-
|
|
217
|
+
for (const value of values) {
|
|
240
218
|
const valueType = Array.isArray(value) ? 'array' : typeof value
|
|
241
219
|
|
|
242
220
|
let property = undefined
|
|
243
221
|
let response = undefined
|
|
244
|
-
let makeNew = undefined
|
|
245
222
|
let wasArray = false
|
|
246
223
|
let elements = value
|
|
247
224
|
|
|
@@ -258,31 +235,31 @@ export function Enum(name, values, properties) {
|
|
|
258
235
|
|
|
259
236
|
const maker = {
|
|
260
237
|
[property](initialValue) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
238
|
+
const storage = new Map()
|
|
239
|
+
const key = property
|
|
240
|
+
const realValue = accessor(response, false, { storage, key })
|
|
241
|
+
|
|
242
|
+
let _opts, associatedValue;
|
|
243
|
+
|
|
244
|
+
if (wasArray) {
|
|
245
|
+
_opts = { storage, key: key + '.associated' }
|
|
246
|
+
associatedValue = elements.length === 1
|
|
247
|
+
? accessor(initialValue, true, _opts)
|
|
248
|
+
: accessor(elements?.[1], elements?.[2], _opts);
|
|
249
|
+
}
|
|
250
|
+
else
|
|
274
251
|
associatedValue = accessor(
|
|
275
252
|
Symbol.for('Enum.NonAssociatedValue'),
|
|
276
253
|
false, false, false)
|
|
277
254
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
255
|
+
const _prop = Object(asString(response))
|
|
256
|
+
const valueProps = [...kValueProps, ...kCustomPropKeys]
|
|
257
|
+
const enumResponse = Object.create(_prop, {
|
|
281
258
|
...makeEnumValue(property, response),
|
|
282
259
|
...props,
|
|
283
|
-
|
|
260
|
+
})
|
|
284
261
|
|
|
285
|
-
|
|
262
|
+
const proxy = new Proxy(_prop, {
|
|
286
263
|
get(target, _property, receiver) {
|
|
287
264
|
if (_property === 'real')
|
|
288
265
|
return realValue.get()
|
|
@@ -317,12 +294,12 @@ export function Enum(name, values, properties) {
|
|
|
317
294
|
|
|
318
295
|
return false
|
|
319
296
|
}
|
|
320
|
-
|
|
297
|
+
})
|
|
321
298
|
|
|
322
|
-
|
|
323
|
-
|
|
299
|
+
Object.setPrototypeOf(proxy, Object.getPrototypeOf(_prop))
|
|
300
|
+
Object.setPrototypeOf(enumResponse, proxy)
|
|
324
301
|
|
|
325
|
-
|
|
302
|
+
return enumResponse
|
|
326
303
|
}
|
|
327
304
|
}
|
|
328
305
|
|
|
@@ -336,9 +313,172 @@ export function Enum(name, values, properties) {
|
|
|
336
313
|
}
|
|
337
314
|
|
|
338
315
|
Object.defineProperty(enumeration, property, data(dataValue, baseProps))
|
|
339
|
-
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return enumeration
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export const EnumExtension = new Extension(Enum)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Converts a given value to a string representation with additional
|
|
327
|
+
* options for description and string tag.
|
|
328
|
+
*
|
|
329
|
+
* @param {any} value - The value to be converted to a string. This can
|
|
330
|
+
* be of any type, including objects, arrays, numbers, etc.
|
|
331
|
+
* @returns {string} A string representation of the input value, enhanced
|
|
332
|
+
* with a description and string tag if applicable.
|
|
333
|
+
*
|
|
334
|
+
* @example
|
|
335
|
+
* // Convert a number to a string with additional options
|
|
336
|
+
* const result = asString(123)
|
|
337
|
+
* console.log(result) // Outputs: "123" with description and string tag
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* // Convert an object to a string with additional options
|
|
341
|
+
* const obj = { key: 'value' }
|
|
342
|
+
* const result = asString(obj)
|
|
343
|
+
* console.log(result) // Outputs: "[object Object]" with description and
|
|
344
|
+
* // string tag
|
|
345
|
+
*/
|
|
346
|
+
function asString(value) {
|
|
347
|
+
return as.string(value, { description: true, stringTag: true })
|
|
348
|
+
}
|
|
340
349
|
|
|
341
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Creates a base enumeration object with predefined properties and
|
|
352
|
+
* symbols. This function is used to initialize an enumeration with
|
|
353
|
+
* specific characteristics, such as a name and various symbolic
|
|
354
|
+
* properties that enhance its functionality and identification.
|
|
355
|
+
*
|
|
356
|
+
* @param {string} name - The name of the enumeration. This name is
|
|
357
|
+
* used to identify the enumeration and is stored as a symbol on
|
|
358
|
+
* the object.
|
|
359
|
+
* @returns {Object} A new enumeration object with specific properties
|
|
360
|
+
* and symbols set for enhanced functionality and identification.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* // Create a base enum with the name 'Color'
|
|
364
|
+
* const colorEnum = makeBaseEnum('Color')
|
|
365
|
+
* console.log(colorEnum[Symbol.for('Enum.name')]) // Outputs: 'Color'
|
|
366
|
+
*/
|
|
367
|
+
export function makeBaseEnum(name) {
|
|
368
|
+
return Object.create({}, {
|
|
369
|
+
/**
|
|
370
|
+
* Defines the `toStringTag` symbol on each enumeration to allow for
|
|
371
|
+
* type identification and to be consistent in naming conventions.
|
|
372
|
+
*
|
|
373
|
+
* @type {string}
|
|
374
|
+
*/
|
|
375
|
+
[Symbol.toStringTag]: accessor('Enum', false, true, false),
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* In addition to the `toStringTag` symbol which defines this enumeration
|
|
379
|
+
* as an Enum type, the name of the enum is also codified in as a symbol
|
|
380
|
+
* on the object. It can be found using `Symbol.for('Enum.name')`.
|
|
381
|
+
*
|
|
382
|
+
* @type {string|symbol|number}
|
|
383
|
+
*/
|
|
384
|
+
[Symbol.for('Enum.name')]: accessor(name, false, true, false),
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Knowing which keys of the enum are part of the keys themselves is also
|
|
388
|
+
* crucial for enumerations. These can always be found on each Enum type
|
|
389
|
+
* as `Symbol.for('Enum.valueKeys')` as an array, but can also be found
|
|
390
|
+
* as the `.keys` property if there is no enum value of that name.
|
|
391
|
+
*/
|
|
392
|
+
[Symbol.for('Enum.valueKeys')]: data([], false, true, false),
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* For users of the node.js REPL, this symbol represents enum types in a
|
|
396
|
+
* more readily readable format. See the docs for node's `util.inspect()`
|
|
397
|
+
* function for more details.
|
|
398
|
+
*
|
|
399
|
+
* @type {(number, object, Function) => string}
|
|
400
|
+
*/
|
|
401
|
+
[Symbol.for('nodejs.util.inspect.custom')]: data(
|
|
402
|
+
function(depth, options, inspect) {
|
|
403
|
+
const valueKeys = this[Symbol.for('Enum.valueKeys')] ?? []
|
|
404
|
+
let valueText = valueKeys
|
|
405
|
+
.map(key => `\x1b[1;2m${key}\x1b[22m`)
|
|
406
|
+
.join(', ')
|
|
407
|
+
|
|
408
|
+
if (valueText.length)
|
|
409
|
+
valueText = ` { ${valueText} }`
|
|
410
|
+
|
|
411
|
+
return `\x1b[1menum \x1b[22m${name}${valueText}`
|
|
412
|
+
}, false, true, false
|
|
413
|
+
),
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* This function checks the supplied `possibleEnumValue` to see if it
|
|
417
|
+
* is an enum value type from this enum.
|
|
418
|
+
*
|
|
419
|
+
* @param {any} possibleEnumValue the value to evaluate
|
|
420
|
+
* @returns {boolean} returns `true` if the value is an enum value type
|
|
421
|
+
* from this `Enum`, irrespective of any associated value. Returns `false`
|
|
422
|
+
* otherwise.
|
|
423
|
+
*/
|
|
424
|
+
isValueOf: data(function isValueOf(possibleEnumValue) {
|
|
425
|
+
if (!possibleEnumValue || typeof possibleEnumValue !== 'object')
|
|
426
|
+
return false
|
|
427
|
+
|
|
428
|
+
const enumValueType = possibleEnumValue?.type
|
|
429
|
+
const enumValueName = possibleEnumValue?.name
|
|
430
|
+
|
|
431
|
+
const thisEnumName = this[Symbol.for('Enum.name')]
|
|
432
|
+
const thisEnumKeys = this[Symbol.for('Enum.valueKeys')]
|
|
433
|
+
|
|
434
|
+
return (
|
|
435
|
+
enumValueType === thisEnumName &&
|
|
436
|
+
thisEnumKeys.includes(enumValueName)
|
|
437
|
+
)
|
|
438
|
+
}, false, true, false),
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* A simple overload of the `toString()` method to represent the enum
|
|
442
|
+
* more identifiably when called. The result will be the word enum with
|
|
443
|
+
* the name of the enum in parenthesis. So a Gender enum might be seen
|
|
444
|
+
* as `Enum(Gender)` as a result to calling this function.
|
|
445
|
+
*
|
|
446
|
+
* @returns {string} a {@link String} representation of this object.
|
|
447
|
+
*/
|
|
448
|
+
toString: data(function toString() {
|
|
449
|
+
return `Enum(${name})`
|
|
450
|
+
}, false, true, false)
|
|
451
|
+
})
|
|
452
|
+
|
|
453
|
+
const applySyntacticSugar = () => {
|
|
454
|
+
createSymlinks(Symbol.for('Enum.valueKeys'), 'keys')
|
|
455
|
+
createSymlinks(Symbol.for('Enum.name'), 'name')
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
return [base, applySyntacticSugar]
|
|
342
459
|
}
|
|
343
460
|
|
|
344
|
-
|
|
461
|
+
/**
|
|
462
|
+
* Creates a symlink for a property from an existing key to a new key on
|
|
463
|
+
* the specified object. This function checks if the new key already
|
|
464
|
+
* exists on the object and, if not, it creates a new property with the
|
|
465
|
+
* same descriptor as the old key.
|
|
466
|
+
*
|
|
467
|
+
* Since this method creates the new link through the use of property
|
|
468
|
+
* descriptors, computed getters and setters also are mapped properly.
|
|
469
|
+
*
|
|
470
|
+
* @param {Object} on - The target object on which the symlink is to be
|
|
471
|
+
* created.
|
|
472
|
+
* @param {string|symbol} oldKey - The existing key whose property
|
|
473
|
+
* descriptor will be used for the new key.
|
|
474
|
+
* @param {string|symbol} newKey - The new key under which the property
|
|
475
|
+
* will be accessible.
|
|
476
|
+
*
|
|
477
|
+
* @example
|
|
478
|
+
* const obj = { a: 1 }
|
|
479
|
+
* createSymlink(obj, 'a', 'b')
|
|
480
|
+
* console.log(obj.b) // Outputs: 1
|
|
481
|
+
*/
|
|
482
|
+
function createSymlinks(on, oldKey, ...newKeys) {
|
|
483
|
+
redescribe(on, oldKey, {}, { alsoAs: newKeys })
|
|
484
|
+
}
|
package/src/index.js
CHANGED
|
@@ -29,6 +29,15 @@ import { RefSetExtensions } from './classes/refset.js'
|
|
|
29
29
|
import { SymkeysExtension } from './classes/symkeys.js'
|
|
30
30
|
import { TypeExtensions } from './classes/type.js'
|
|
31
31
|
|
|
32
|
+
export * from './utils/stdout.js'
|
|
33
|
+
import {
|
|
34
|
+
StringConsole,
|
|
35
|
+
StdoutGlobalPatches,
|
|
36
|
+
StringConsoleExtension,
|
|
37
|
+
|
|
38
|
+
captureStdout,
|
|
39
|
+
} from './utils/stdout.js'
|
|
40
|
+
|
|
32
41
|
export * from './utils/copy.object.js'
|
|
33
42
|
export * from './utils/toolkit.js'
|
|
34
43
|
export * from './utils/descriptor.utils.js'
|
|
@@ -68,6 +77,9 @@ const InstancePatches = [
|
|
|
68
77
|
const Patches = new Map([
|
|
69
78
|
...StaticPatches,
|
|
70
79
|
...InstancePatches,
|
|
80
|
+
|
|
81
|
+
[globalThis, GlobalFunctionsAndProps, 'globalThis'], // Missing .name property
|
|
82
|
+
[globalThis, StdoutGlobalPatches, 'globalThis'], // Missing .name property
|
|
71
83
|
])
|
|
72
84
|
|
|
73
85
|
const Extensions = {
|
|
@@ -85,6 +97,7 @@ const Extensions = {
|
|
|
85
97
|
[PropertyExtensions.key]: PropertyExtensions,
|
|
86
98
|
[RefMapExtensions.key]: RefMapExtensions,
|
|
87
99
|
[RefSetExtensions.key]: RefSetExtensions,
|
|
100
|
+
[StringConsoleExtension.key]: StringConsoleExtension,
|
|
88
101
|
[SymkeysExtension.key]: SymkeysExtension,
|
|
89
102
|
[TypeExtensions.key]: TypeExtensions,
|
|
90
103
|
}
|
|
@@ -121,7 +134,6 @@ Object.assign(Controls, {
|
|
|
121
134
|
|
|
122
135
|
enableExtensions() {
|
|
123
136
|
Object.values(Extensions).forEach((extension) => { extension.apply() })
|
|
124
|
-
GlobalFunctionsAndProps.apply()
|
|
125
137
|
},
|
|
126
138
|
|
|
127
139
|
disableAll() {
|
|
@@ -147,7 +159,6 @@ Object.assign(Controls, {
|
|
|
147
159
|
|
|
148
160
|
disableExtensions() {
|
|
149
161
|
Object.values(Extensions).forEach((extension) => { extension.revert() })
|
|
150
|
-
GlobalFunctionsAndProps.revert()
|
|
151
162
|
},
|
|
152
163
|
})
|
|
153
164
|
|
|
@@ -193,7 +204,9 @@ export const all = (() => {
|
|
|
193
204
|
.reduce(entriesReducer, dest.classes)
|
|
194
205
|
)
|
|
195
206
|
|
|
196
|
-
|
|
207
|
+
const globals = [...GlobalFunctionsAndProps].concat([...StdoutGlobalPatches])
|
|
208
|
+
|
|
209
|
+
for (const [key, entry] of globals) {
|
|
197
210
|
const descriptor = new Descriptor(entry.descriptor, entry.owner)
|
|
198
211
|
Object.defineProperty(dest.global, key, descriptor.toObject(true))
|
|
199
212
|
}
|
|
@@ -203,15 +216,16 @@ export const all = (() => {
|
|
|
203
216
|
|
|
204
217
|
const results = {
|
|
205
218
|
...Controls,
|
|
219
|
+
all,
|
|
220
|
+
Controls,
|
|
206
221
|
Extensions,
|
|
207
|
-
|
|
222
|
+
extensions: Extensions,
|
|
208
223
|
GlobalFunctionsAndProps,
|
|
209
|
-
StaticPatches,
|
|
210
224
|
InstancePatches,
|
|
211
|
-
|
|
212
|
-
extensions: Extensions,
|
|
225
|
+
Patches,
|
|
213
226
|
patches: Patches,
|
|
214
|
-
|
|
227
|
+
StaticPatches,
|
|
228
|
+
StdoutGlobalPatches,
|
|
215
229
|
}
|
|
216
230
|
|
|
217
231
|
export default results
|
package/src/string.extensions.js
CHANGED
|
@@ -723,6 +723,47 @@ export const StringPrototypeExtensions = new Patch(String.prototype, {
|
|
|
723
723
|
};
|
|
724
724
|
}
|
|
725
725
|
},
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Prints the string representation of the current object using a specified
|
|
729
|
+
* function and context.
|
|
730
|
+
*
|
|
731
|
+
* This method converts the current object to a string and then prints it
|
|
732
|
+
* using the provided function. By default, it uses `console.log` to print
|
|
733
|
+
* to the console. The function is called with a specified `thisArg` to
|
|
734
|
+
* set the context in which the function is executed.
|
|
735
|
+
*
|
|
736
|
+
* @param {Function} [fn=console.log] - The function used to print the
|
|
737
|
+
* string. Defaults to `console.log`.
|
|
738
|
+
* @param {Object} [thisArg=console] - The value of `this` provided for
|
|
739
|
+
* the call to `fn`. Defaults to the global `console` object.
|
|
740
|
+
*
|
|
741
|
+
* @returns {string} The string representation of the current object.
|
|
742
|
+
*
|
|
743
|
+
* @example
|
|
744
|
+
* // assuming extensions are applied
|
|
745
|
+
* const str = 'Hello, World!'
|
|
746
|
+
* str.print() // Logs: 'Hello, World!' to the console
|
|
747
|
+
*
|
|
748
|
+
* @example
|
|
749
|
+
* // assuming extensions are applied
|
|
750
|
+
* const str = 'Hello, World!'
|
|
751
|
+
* const customLogger = {
|
|
752
|
+
* time: new Date(),
|
|
753
|
+
* log: (msg) => {
|
|
754
|
+
* console.info('[%s]: %s', this.time..toLocaleDateString(), msg)
|
|
755
|
+
* }
|
|
756
|
+
* }
|
|
757
|
+
* str.print(customLogger.log, customLogger)
|
|
758
|
+
* // prints "[10/16/2024] Hello, World!"
|
|
759
|
+
*/
|
|
760
|
+
print(fn = console.log, thisArg = console) {
|
|
761
|
+
const string = this.toString()
|
|
762
|
+
|
|
763
|
+
fn.call(thisArg, string)
|
|
764
|
+
|
|
765
|
+
return string
|
|
766
|
+
},
|
|
726
767
|
},
|
|
727
768
|
})
|
|
728
769
|
|