@nejs/basic-extensions 1.0.0 → 1.1.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/build +0 -3
- package/bin/clean +8 -0
- package/bin/esbuild +91 -0
- package/dist/@nejs/basic-extensions.bundle.1.0.0.js +2 -0
- package/dist/@nejs/basic-extensions.bundle.1.0.0.js.map +7 -0
- package/dist/cjs/arrayextensions.js +32 -1
- package/dist/cjs/descriptor.d.ts +2 -0
- package/dist/cjs/descriptor.js +484 -0
- package/dist/cjs/index.d.ts +3 -1
- package/dist/cjs/index.js +7 -1
- package/dist/cjs/objectextensions.js +37 -1
- package/dist/cjs/reflectextensions.js +20 -0
- package/dist/cjs/stringextensions.d.ts +10 -0
- package/dist/cjs/stringextensions.js +27 -0
- package/dist/cjs/symbolextensions.d.ts +10 -0
- package/dist/cjs/symbolextensions.js +27 -0
- package/dist/mjs/arrayextensions.js +32 -1
- package/dist/mjs/descriptor.d.ts +2 -0
- package/dist/mjs/descriptor.js +458 -0
- package/dist/mjs/index.d.ts +3 -1
- package/dist/mjs/index.js +5 -1
- package/dist/mjs/objectextensions.js +37 -1
- package/dist/mjs/reflectextensions.js +20 -0
- package/dist/mjs/stringextensions.d.ts +10 -0
- package/dist/mjs/stringextensions.js +24 -0
- package/dist/mjs/symbolextensions.d.ts +10 -0
- package/dist/mjs/symbolextensions.js +24 -0
- package/package.json +10 -4
- package/src/arrayextensions.js +37 -1
- package/src/descriptor.js +533 -0
- package/src/index.js +7 -0
- package/src/objectextensions.js +41 -1
- package/src/reflectextensions.js +28 -1
- package/src/stringextensions.js +25 -0
- package/src/symbolextensions.js +25 -0
|
@@ -8,6 +8,37 @@ import { Patch } from '@nejs/extension';
|
|
|
8
8
|
* operations on arrays and makes code more expressive and concise.
|
|
9
9
|
*/
|
|
10
10
|
export const ArrayPrototypeExtensions = new Patch(Array.prototype, {
|
|
11
|
+
/**
|
|
12
|
+
* Sometimes defining even a short function for the invocation of `find`
|
|
13
|
+
* can be troublesome. This helper function performs that job for you. If
|
|
14
|
+
* the specified element is in the array, `true` will be returned.
|
|
15
|
+
*
|
|
16
|
+
* @param {*} value the value to search for. This value must triple equals
|
|
17
|
+
* the array element in order to return true.
|
|
18
|
+
* @returns true if the exact element exists in the array, false otherwise
|
|
19
|
+
*/
|
|
20
|
+
contains(value) {
|
|
21
|
+
return !!this.find(entry => entry === value);
|
|
22
|
+
},
|
|
23
|
+
/**
|
|
24
|
+
* The `findEntry` function searches the entries of the object and returns
|
|
25
|
+
* the `[index, value]` entry array for the first matching value found.
|
|
26
|
+
*
|
|
27
|
+
* @param {function} findFn a function that takes the element to be checked
|
|
28
|
+
* and returns a boolean value
|
|
29
|
+
* @returns if `findFn` returns `true`, an array with two elements, the first
|
|
30
|
+
* being the index, the second being the value, is returned.
|
|
31
|
+
*/
|
|
32
|
+
findEntry(findFn) {
|
|
33
|
+
const entries = this.entries();
|
|
34
|
+
const VALUE = 1;
|
|
35
|
+
for (let entry of entries) {
|
|
36
|
+
if (findFn(entry[VALUE])) {
|
|
37
|
+
return entry;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
},
|
|
11
42
|
/**
|
|
12
43
|
* A getter property that returns the first element of the array. If the
|
|
13
44
|
* array is empty, it returns `undefined`. This property is useful for
|
|
@@ -32,5 +63,5 @@ export const ArrayPrototypeExtensions = new Patch(Array.prototype, {
|
|
|
32
63
|
*/
|
|
33
64
|
get last() {
|
|
34
65
|
return this[this.length - 1];
|
|
35
|
-
}
|
|
66
|
+
},
|
|
36
67
|
});
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
import { Extension } from '@nejs/extension';
|
|
2
|
+
import { ObjectExtensions } from './objectextensions.js';
|
|
3
|
+
import { ReflectExtensions } from './reflectextensions.js';
|
|
4
|
+
const isObject = ObjectExtensions.patchEntries.isObject.computed;
|
|
5
|
+
const isValidKey = ObjectExtensions.patchEntries.isValidKey.computed;
|
|
6
|
+
const isString = ObjectExtensions.patchEntries.isString.computed;
|
|
7
|
+
const hasSome = ReflectExtensions.patchEntries.hasSome.computed;
|
|
8
|
+
class Descriptor {
|
|
9
|
+
#desc = Descriptor.enigmatic;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new instance of Descriptor either from another object or
|
|
12
|
+
* around the supplied object descriptor value.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} object either an object descriptor or the object
|
|
15
|
+
* from which to get the descriptor
|
|
16
|
+
* @param {symbol|string} key a valid key for accessing the descriptor
|
|
17
|
+
* on the aforesupplied object.
|
|
18
|
+
*/
|
|
19
|
+
constructor(object, key) {
|
|
20
|
+
this.#desc = object;
|
|
21
|
+
if (object && key) {
|
|
22
|
+
this.#desc = Object.getOwnPropertyDescriptor(object, key);
|
|
23
|
+
}
|
|
24
|
+
if (!Descriptor.isDescriptor(this.#desc)) {
|
|
25
|
+
throw new Error(`Not a valid descriptor:`, this.#desc);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Getter around the `configurable` object descriptor property of
|
|
30
|
+
* this instance of Descriptor.
|
|
31
|
+
*
|
|
32
|
+
* @returns {boolean} a boolean value or undefined if the internal
|
|
33
|
+
* descriptor store is invalid.
|
|
34
|
+
*/
|
|
35
|
+
get configurable() {
|
|
36
|
+
return !!this.#desc?.configurable ?? undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Sets the `configurable` value of this object. If the internal descriptor
|
|
40
|
+
* store store is invalid, the value is thrown away
|
|
41
|
+
*
|
|
42
|
+
* @param {boolean} value the value to set for the `configurable` descriptor
|
|
43
|
+
* property. If this value is not a `boolean` it will be converted to one
|
|
44
|
+
*/
|
|
45
|
+
set configurable(value) {
|
|
46
|
+
(this.#desc || {}).configurable = !!value;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Getter around the `enumerable` object descriptor property of
|
|
50
|
+
* this instance of Descriptor.
|
|
51
|
+
*
|
|
52
|
+
* @returns {boolean} a boolean value or undefined if the internal
|
|
53
|
+
* descriptor store is invalid.
|
|
54
|
+
*/
|
|
55
|
+
get enumerable() {
|
|
56
|
+
return this.#desc?.enumerable;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Sets the `enumerable` value of this object. If the internal descriptor
|
|
60
|
+
* store is invalid, the value is thrown away
|
|
61
|
+
*
|
|
62
|
+
* @param {boolean} value the value to set for the `enumerable` descriptor
|
|
63
|
+
* property. If this value is not a `boolean` it will be converted to one
|
|
64
|
+
*/
|
|
65
|
+
set enumerable(value) {
|
|
66
|
+
(this.#desc || {}).enumerable = value;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Getter around the `writable` object descriptor property of
|
|
70
|
+
* this instance of Descriptor.
|
|
71
|
+
*
|
|
72
|
+
* @returns {boolean} a boolean value or undefined if the internal
|
|
73
|
+
* descriptor store is invalid.
|
|
74
|
+
*/
|
|
75
|
+
get writable() {
|
|
76
|
+
return this.#desc?.writable;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sets the `writable` value of this object. If the internal descriptor
|
|
80
|
+
* store is invalid, the value is thrown away
|
|
81
|
+
*
|
|
82
|
+
* @param {boolean} value the value to set for the `writable` descriptor
|
|
83
|
+
* property. If this value is not a `boolean` it will be converted to one
|
|
84
|
+
*/
|
|
85
|
+
set writable(value) {
|
|
86
|
+
(this.#desc || {}).writable = value;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Getter around the `value` object descriptor property of
|
|
90
|
+
* this instance of Descriptor.
|
|
91
|
+
*
|
|
92
|
+
* @returns {any} any value stored in this descriptor
|
|
93
|
+
*/
|
|
94
|
+
get value() {
|
|
95
|
+
return this.#desc?.value;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Sets the `value` value of this object. If the internal descriptor
|
|
99
|
+
* store is invalid, the value is thrown away
|
|
100
|
+
*
|
|
101
|
+
* @param {any} value the value to set for the `value` descriptor
|
|
102
|
+
* property.
|
|
103
|
+
*/
|
|
104
|
+
set value(value) {
|
|
105
|
+
(this.#desc || {}).value = value;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Getter around the `get` object descriptor property of
|
|
109
|
+
* this instance of Descriptor.
|
|
110
|
+
*
|
|
111
|
+
* @returns {function} a function if the getter for this descriptor is
|
|
112
|
+
* defined or `undefined` if the internal descriptor object or the getter
|
|
113
|
+
* is undefined.
|
|
114
|
+
*/
|
|
115
|
+
get get() {
|
|
116
|
+
return this.#desc?.get;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Sets the `get` value of this object. If the internal descriptor
|
|
120
|
+
* store is invalid, the value is thrown away
|
|
121
|
+
*
|
|
122
|
+
* @param {function} value the getter function for this descriptor
|
|
123
|
+
*/
|
|
124
|
+
set get(value) {
|
|
125
|
+
(this.#desc || {}).get = value;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Getter around the `set` object descriptor property of
|
|
129
|
+
* this instance of Descriptor.
|
|
130
|
+
*
|
|
131
|
+
* @returns {function} a function if the setter for this descriptor is
|
|
132
|
+
* defined or `undefined` if the internal descriptor object or the setter
|
|
133
|
+
* is undefined.
|
|
134
|
+
*/
|
|
135
|
+
get set() {
|
|
136
|
+
return this.#desc?.writable;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Sets the `set` value of this object. If the internal descriptor
|
|
140
|
+
* store is invalid, the value is thrown away
|
|
141
|
+
*
|
|
142
|
+
* @param {function} value the setter function for this descriptor
|
|
143
|
+
*/
|
|
144
|
+
set set(value) {
|
|
145
|
+
(this.#desc || {}).set = value;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Take the descriptor defined by this objects values and apply them to
|
|
149
|
+
* the specified object using the specified key.
|
|
150
|
+
*
|
|
151
|
+
* @param {object} object the object to apply this descriptor to
|
|
152
|
+
* @param {string|symbol} forKey the string or symbol for which this
|
|
153
|
+
* descriptor will abe applied
|
|
154
|
+
*/
|
|
155
|
+
applyTo(object, forKey) {
|
|
156
|
+
if (!isObject(object) || !isValidKey(forKey)) {
|
|
157
|
+
throw new Error(`Cannot apply descriptor to non-object or invalid key`);
|
|
158
|
+
}
|
|
159
|
+
Object.defineProperty(object, forKey, this.#desc);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Converts this descriptor object into a base representation
|
|
163
|
+
*
|
|
164
|
+
* @param {string} hint one of `string`, `number` or default;
|
|
165
|
+
* @returns if the hint is 'string', then a string identifying the enum
|
|
166
|
+
* and its type is returned. `number` will always be NaN since it is incoret
|
|
167
|
+
*/
|
|
168
|
+
[Symbol.toPrimitive](hint) {
|
|
169
|
+
switch (hint) {
|
|
170
|
+
case 'string':
|
|
171
|
+
if (this.isAccessor) {
|
|
172
|
+
const hasGetter = Reflect.has(this.#desc, 'get') ? `getter` : '';
|
|
173
|
+
const hasSetter = Reflect.has(this.#desc, 'set') ? `setter` : '';
|
|
174
|
+
const separator = hasGetter && hasSetter ? ', ' : '';
|
|
175
|
+
return `Accessor (${hasGetter}${separator}${hasSetter})`;
|
|
176
|
+
}
|
|
177
|
+
else if (this.isData) {
|
|
178
|
+
const hasGetter = Reflect.has(this.#desc, 'value') ? `value` : '';
|
|
179
|
+
const hasSetter = Reflect.has(this.#desc, 'writable') ? `writable` : '';
|
|
180
|
+
const separator = hasGetter && hasSetter ? ', ' : '';
|
|
181
|
+
return `Data (${hasGetter}${separator}${hasSetter})`;
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
case 'number':
|
|
185
|
+
return NaN;
|
|
186
|
+
default:
|
|
187
|
+
return this.#desc;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The function `getData` retrieves the value of a property from an object if it
|
|
192
|
+
* exists and is a data property.
|
|
193
|
+
*
|
|
194
|
+
* @param object - The "object" parameter is the object from which we want to
|
|
195
|
+
* retrieve data.
|
|
196
|
+
* @param property - The `property` parameter is the name of the property that
|
|
197
|
+
* you want to retrieve the data from.
|
|
198
|
+
* @returns either the value of the specified property if it exists and is a data
|
|
199
|
+
* property, or undefined if the property does not exist or is not a data
|
|
200
|
+
* property.
|
|
201
|
+
*/
|
|
202
|
+
static getData(object, property) {
|
|
203
|
+
if (!isObject(object) || !isString(property)) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
const descriptors = Descriptor.all(object);
|
|
207
|
+
if (descriptors.has(property)) {
|
|
208
|
+
const descriptor = descriptors.get(property);
|
|
209
|
+
if (Descriptor.isData(descriptor)) {
|
|
210
|
+
return descriptor.value;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* The function `getAccessor` checks if an object has a getter/setter accessor
|
|
217
|
+
* for a given property and returns the accessor functions if found.
|
|
218
|
+
*
|
|
219
|
+
* @param object - The `object` parameter is the object from which we want to
|
|
220
|
+
* retrieve the accessor for a specific property.
|
|
221
|
+
* @param property - The `property` parameter is the name of the property for
|
|
222
|
+
* which we want to get the accessor.
|
|
223
|
+
* @returns an object that contains the getter and setter functions for the
|
|
224
|
+
* specified property of the given object. If the property is an accessor
|
|
225
|
+
* property (defined with a getter and/or setter), the returned object will also
|
|
226
|
+
* have additional properties such as "accessor" and "descriptor". If the
|
|
227
|
+
* property is not found or is not an accessor property, the function returns
|
|
228
|
+
* undefined.
|
|
229
|
+
*/
|
|
230
|
+
static getAccessor(object, property) {
|
|
231
|
+
if (!isObject(object))
|
|
232
|
+
return null;
|
|
233
|
+
const [GETTER, SETTER, OBJECT] = [0, 1, 2];
|
|
234
|
+
const results = [undefined, undefined, undefined];
|
|
235
|
+
const descriptors = this.all(object);
|
|
236
|
+
const isDescriptor = Descriptor.isDescriptor(object);
|
|
237
|
+
if (descriptors.has(property) || isDescriptor) {
|
|
238
|
+
const descriptor = isDescriptor ? object : descriptors.get(property);
|
|
239
|
+
if (Descriptor.isAccessor(descriptor)) {
|
|
240
|
+
results[OBJECT] = descriptors.object(property);
|
|
241
|
+
results[GETTER] = descriptor?.get;
|
|
242
|
+
results[SETTER] = descriptor?.set;
|
|
243
|
+
Object.assign(results, {
|
|
244
|
+
get() { this[GETTER].bind(this[OBJECT])(); },
|
|
245
|
+
set(value) { this[SETTER].bind(this[OBJECT])(value); },
|
|
246
|
+
get accessor() { return true; },
|
|
247
|
+
get descriptor() { return descriptor; },
|
|
248
|
+
get boundDescriptor() {
|
|
249
|
+
return {
|
|
250
|
+
...descriptor,
|
|
251
|
+
get: descriptor.get?.bind(object),
|
|
252
|
+
set: descriptor.set?.bind(object),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
return results;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* The function returns an object with enumerable and configurable properties
|
|
263
|
+
* based on the input parameters.
|
|
264
|
+
*
|
|
265
|
+
* @param [enumerable=false] - A boolean value indicating whether the property
|
|
266
|
+
* can be enumerated (listed) when iterating over the object's properties.
|
|
267
|
+
* @param [configurable=false] - The `configurable` parameter determines whether
|
|
268
|
+
* the property can be deleted or its attributes can be modified. If
|
|
269
|
+
* `configurable` is set to `true`, the property can be deleted and its
|
|
270
|
+
* attributes can be changed. If `configurable` is set to `false`, the property
|
|
271
|
+
* cannot be deleted and
|
|
272
|
+
* @returns An object with the properties `enumerable` and `configurable` is
|
|
273
|
+
* being returned. The values of these properties are determined by the arguments
|
|
274
|
+
* passed to the `base` function.
|
|
275
|
+
*/
|
|
276
|
+
static base(enumerable = false, configurable = false) {
|
|
277
|
+
return {
|
|
278
|
+
enumerable,
|
|
279
|
+
configurable
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* The function "newAccessor" creates a new property descriptor object with a
|
|
284
|
+
* getter and setter function, along with optional enumerable and configurable
|
|
285
|
+
* flags.
|
|
286
|
+
*
|
|
287
|
+
* @param getter - The getter parameter is a function that will be used as the
|
|
288
|
+
* getter for the property. It will be called when the property is accessed.
|
|
289
|
+
* @param setter - The `setter` parameter is a function that will be used as the
|
|
290
|
+
* setter for the property. It will be called whenever the property is assigned a
|
|
291
|
+
* new value.
|
|
292
|
+
* @param [] - - `getter`: A function that will be used as the getter for the
|
|
293
|
+
* property.
|
|
294
|
+
* @returns an object with properties "get", "set", "enumerable", and
|
|
295
|
+
* "configurable".
|
|
296
|
+
*/
|
|
297
|
+
static accessor(getter, setter, { enumerable, configurable } = Descriptor.base()) {
|
|
298
|
+
return {
|
|
299
|
+
get: getter,
|
|
300
|
+
set: setter,
|
|
301
|
+
enumerable,
|
|
302
|
+
configurable
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* The function "newData" creates a new data object with customizable properties.
|
|
307
|
+
*
|
|
308
|
+
* @param value - The value parameter represents the value that will be assigned
|
|
309
|
+
* to the property.
|
|
310
|
+
* @param [writable=true] - The `writable` parameter determines whether the value
|
|
311
|
+
* of the property can be changed. If `writable` is set to `true`, the value can
|
|
312
|
+
* be changed. If `writable` is set to `false`, the value cannot be changed.
|
|
313
|
+
* @param [] - - `value`: The value to be assigned to the property.
|
|
314
|
+
* @returns an object with properties `value`, `enumerable`, `writable`, and
|
|
315
|
+
* `configurable`.
|
|
316
|
+
*/
|
|
317
|
+
static data(value, writable = true, { enumerable, configurable } = Descriptor.base()) {
|
|
318
|
+
return {
|
|
319
|
+
value,
|
|
320
|
+
enumerable,
|
|
321
|
+
writable,
|
|
322
|
+
configurable
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The function checks if an object is a valid object descriptor in JavaScript.
|
|
327
|
+
*
|
|
328
|
+
* @param object - The `object` parameter is the object that we want to check if
|
|
329
|
+
* it is a descriptor.
|
|
330
|
+
* @returns a boolean value.
|
|
331
|
+
*/
|
|
332
|
+
static isDescriptor(object) {
|
|
333
|
+
const knownKeys = [
|
|
334
|
+
...Descriptor.SHARED_KEYS,
|
|
335
|
+
...Descriptor.ACCESSOR_KEYS,
|
|
336
|
+
...Descriptor.DATA_KEYS,
|
|
337
|
+
];
|
|
338
|
+
let isa = (hasSome(knownKeys) && (Descriptor.isAccessor(object) ||
|
|
339
|
+
Descriptor.isData(object)));
|
|
340
|
+
return isa;
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* The function checks if a given property or descriptor is a data property.
|
|
344
|
+
*
|
|
345
|
+
* @param descriptor_orProp - The `descriptor_orProp` parameter can be either a
|
|
346
|
+
* descriptor or a property name.
|
|
347
|
+
* @param object - The `object` parameter is the object that you want to check
|
|
348
|
+
* for data properties.
|
|
349
|
+
* @returns a boolean value. It returns `true` if the `descriptor` object has any
|
|
350
|
+
* keys that match the `DATA_KEYS` array, otherwise it returns `false`.
|
|
351
|
+
*/
|
|
352
|
+
static isData(object_orProp, property) {
|
|
353
|
+
const needsDescriptor = (((typeof object_orProp === 'object') || object_orProp instanceof Object) &&
|
|
354
|
+
property instanceof String);
|
|
355
|
+
const descriptor = (needsDescriptor
|
|
356
|
+
? Descriptor.for(object_orProp, property)
|
|
357
|
+
: object_orProp);
|
|
358
|
+
const { ACCESSOR_KEYS, DATA_KEYS } = this;
|
|
359
|
+
let validData = false;
|
|
360
|
+
if (hasSome(descriptor, ACCESSOR_KEYS)) {
|
|
361
|
+
validData = false;
|
|
362
|
+
}
|
|
363
|
+
else if (hasSome(descriptor, DATA_KEYS)) {
|
|
364
|
+
validData = true;
|
|
365
|
+
}
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* The function checks if a given property descriptor or property of an object is
|
|
370
|
+
* an accessor.
|
|
371
|
+
*
|
|
372
|
+
* @param object_orProp - The `descriptor_orProp` parameter can be either a
|
|
373
|
+
* descriptor object or a property name.
|
|
374
|
+
* @param property - The `object` parameter is the object that you want to check
|
|
375
|
+
* for accessor properties.
|
|
376
|
+
* @returns a boolean value. It returns true if the descriptor or property passed
|
|
377
|
+
* as an argument is an accessor descriptor, and false otherwise.
|
|
378
|
+
*/
|
|
379
|
+
static isAccessor(object_orProp, property) {
|
|
380
|
+
const needsDescriptor = ((object_orProp && property) &&
|
|
381
|
+
((typeof object_orProp === 'object') || object_orProp instanceof Object) &&
|
|
382
|
+
(property instanceof String || (typeof property === 'symbol')));
|
|
383
|
+
const descriptor = (needsDescriptor
|
|
384
|
+
? Descriptor.for(object_orProp, property)
|
|
385
|
+
: object_orProp);
|
|
386
|
+
const { ACCESSOR_KEYS, DATA_KEYS } = this;
|
|
387
|
+
let validAccessor = false;
|
|
388
|
+
if (hasSome(descriptor, DATA_KEYS)) {
|
|
389
|
+
validAccessor = false;
|
|
390
|
+
}
|
|
391
|
+
else if (hasSome(descriptor, ACCESSOR_KEYS)) {
|
|
392
|
+
validAccessor = true;
|
|
393
|
+
}
|
|
394
|
+
return validAccessor;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* A base descriptor (new for each read) that is both enumerable and configurable
|
|
398
|
+
*
|
|
399
|
+
* @returns The method `flexible` is returning the result of calling the `base`
|
|
400
|
+
* method with the arguments `true` and `true`.
|
|
401
|
+
*/
|
|
402
|
+
static get flexible() {
|
|
403
|
+
return this.base(true, true);
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* A base descriptor (new for each read) that is not enumerable but is configurable
|
|
407
|
+
*
|
|
408
|
+
* @returns The method `enigmatic` is returning the result of calling the `base`
|
|
409
|
+
* method with the arguments `false` and `true`.
|
|
410
|
+
*/
|
|
411
|
+
static get enigmatic() {
|
|
412
|
+
return this.base(false, true);
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* A base descriptor (new for each read) that is neither enumerable nor configurable
|
|
416
|
+
*
|
|
417
|
+
* @returns The code is returning the result of calling the `base` method with
|
|
418
|
+
* the arguments `false` and `false`.
|
|
419
|
+
*/
|
|
420
|
+
static get intrinsic() {
|
|
421
|
+
return this.base(false, false);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* A base descriptor (new for each read) that enumerable but not configurable
|
|
425
|
+
*
|
|
426
|
+
* @returns The method is returning the result of calling the `base` method with
|
|
427
|
+
* the arguments `true` and `false`.
|
|
428
|
+
*/
|
|
429
|
+
static get transparent() {
|
|
430
|
+
return this.base(true, false);
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* The function returns an array of shared descriptor keys.
|
|
434
|
+
*
|
|
435
|
+
* @returns An array containing the strings 'configurable' and 'enumerable'.
|
|
436
|
+
*/
|
|
437
|
+
static get SHARED_KEYS() {
|
|
438
|
+
return ['configurable', 'enumerable'];
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* The function returns an array of accessor descriptor keys.
|
|
442
|
+
*
|
|
443
|
+
* @returns An array containing the strings 'get' and 'set' is being returned.
|
|
444
|
+
*/
|
|
445
|
+
static get ACCESSOR_KEYS() {
|
|
446
|
+
return ['get', 'set'];
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* The function returns an array of data descriptor keys.
|
|
450
|
+
*
|
|
451
|
+
* @returns An array containing the strings 'value' and 'writable' is being
|
|
452
|
+
* returned.
|
|
453
|
+
*/
|
|
454
|
+
static get DATA_KEYS() {
|
|
455
|
+
return ['value', 'writable'];
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
export const DescriptorExtension = new Extension(Descriptor);
|
package/dist/mjs/index.d.ts
CHANGED
|
@@ -3,5 +3,7 @@ export function disableAll(owners: any): void;
|
|
|
3
3
|
import { ObjectExtensions } from './objectextensions.js';
|
|
4
4
|
import { FunctionExtensions } from './functionextensions.js';
|
|
5
5
|
import { ReflectExtensions } from './reflectextensions.js';
|
|
6
|
+
import { StringExtensions } from './stringextensions.js';
|
|
7
|
+
import { SymbolExtensions } from './symbolextensions.js';
|
|
6
8
|
import { ArrayPrototypeExtensions } from './arrayextensions.js';
|
|
7
|
-
export { ObjectExtensions, FunctionExtensions, ReflectExtensions, ArrayPrototypeExtensions };
|
|
9
|
+
export { ObjectExtensions, FunctionExtensions, ReflectExtensions, StringExtensions, SymbolExtensions, ArrayPrototypeExtensions };
|
package/dist/mjs/index.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { FunctionExtensions } from './functionextensions.js';
|
|
2
2
|
import { ObjectExtensions } from './objectextensions.js';
|
|
3
3
|
import { ReflectExtensions } from './reflectextensions.js';
|
|
4
|
+
import { StringExtensions } from './stringextensions.js';
|
|
5
|
+
import { SymbolExtensions } from './symbolextensions.js';
|
|
4
6
|
import { ArrayPrototypeExtensions } from './arrayextensions.js';
|
|
5
7
|
import { Patch } from '@nejs/extension';
|
|
6
8
|
const Owners = [
|
|
7
9
|
Object,
|
|
8
10
|
Function,
|
|
9
11
|
Reflect,
|
|
12
|
+
String,
|
|
13
|
+
Symbol,
|
|
10
14
|
Array.prototype,
|
|
11
15
|
];
|
|
12
16
|
export function enableAll(owners) {
|
|
@@ -19,4 +23,4 @@ export function disableAll(owners) {
|
|
|
19
23
|
Patch.disableFor(owner);
|
|
20
24
|
});
|
|
21
25
|
}
|
|
22
|
-
export { ObjectExtensions, FunctionExtensions, ReflectExtensions, ArrayPrototypeExtensions, };
|
|
26
|
+
export { ObjectExtensions, FunctionExtensions, ReflectExtensions, StringExtensions, SymbolExtensions, ArrayPrototypeExtensions, };
|
|
@@ -42,7 +42,43 @@ export const ObjectExtensions = new Patch(Object, {
|
|
|
42
42
|
* @returns {string} - The string tag of the object, indicating its type.
|
|
43
43
|
*/
|
|
44
44
|
getStringTag(value) {
|
|
45
|
-
return
|
|
45
|
+
return /\s(.+)]/.exec(Object.prototype.toString.call(value))[1];
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* Strips an object down to only the keys specified. Optionally, any
|
|
49
|
+
* accessors can be made to retain their context on the source object.
|
|
50
|
+
*
|
|
51
|
+
* @param {object} object the object to pare down
|
|
52
|
+
* @param {Array<string|symbol>} keys the keys that should appear in the
|
|
53
|
+
* final reduced object
|
|
54
|
+
* @param {boolean} [bindAccessors = true] if this value is true
|
|
55
|
+
* then any accessors from the source object will continue to have their
|
|
56
|
+
* `this` value bound to the source. If the getter or setter on that object
|
|
57
|
+
* is defined using an arrow function, this will not work as intended.
|
|
58
|
+
* @returns {object} an object containing only the keys and symbols specified
|
|
59
|
+
* in the `keys` parameter.
|
|
60
|
+
*/
|
|
61
|
+
stripTo(object, keys, bindAccessors = true) {
|
|
62
|
+
const result = {};
|
|
63
|
+
if (!Array.isArray(keys)) {
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
for (let key of keys) {
|
|
67
|
+
if (Reflect.has(object, key)) {
|
|
68
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
69
|
+
if (Reflect.has(descriptor, 'get') || Reflect.has(descriptor, 'set')) {
|
|
70
|
+
if (bindAccessors) {
|
|
71
|
+
descriptor.get = descriptor?.get?.bind(object);
|
|
72
|
+
descriptor.set = descriptor?.set?.bind(object);
|
|
73
|
+
}
|
|
74
|
+
Object.defineProperty(result, descriptor);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
Object.defineProperty(result, descriptor);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
46
82
|
},
|
|
47
83
|
/**
|
|
48
84
|
* Determines the type of the given value based on its string tag. This method
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Patch } from '@nejs/extension';
|
|
2
|
+
import { ObjectExtensions } from './objectextensions.js';
|
|
2
3
|
/**
|
|
3
4
|
* The `ReflectExtensions` class is a patch applied to the built-in JavaScript
|
|
4
5
|
* `Reflect` object. It extends `Reflect` with additional utility methods that
|
|
@@ -27,6 +28,25 @@ export const ReflectExtensions = new Patch(Reflect, {
|
|
|
27
28
|
.map(key => Reflect.has(object, key))
|
|
28
29
|
.every(has => has));
|
|
29
30
|
},
|
|
31
|
+
ownDescriptors(object) {
|
|
32
|
+
const result = {};
|
|
33
|
+
const revertOnDone = () => revertOnDone.doIt ? ObjectExtensions.revert() : '';
|
|
34
|
+
revertOnDone.doIt = false;
|
|
35
|
+
if (!Object.isObject) {
|
|
36
|
+
revertOnDone.doIt = true;
|
|
37
|
+
ObjectExtensions.apply();
|
|
38
|
+
}
|
|
39
|
+
if (!Object.isObject(object)) {
|
|
40
|
+
revertOnDone();
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
const keys = Reflect.ownKeys(object);
|
|
44
|
+
for (const key of keys) {
|
|
45
|
+
result[key] = Object.getOwnPropertyDescriptor(key);
|
|
46
|
+
}
|
|
47
|
+
revertOnDone();
|
|
48
|
+
return result;
|
|
49
|
+
},
|
|
30
50
|
/**
|
|
31
51
|
* The function checks if an object has at least one of the specified keys.
|
|
32
52
|
*
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `StringExtensions` is a patch for the JavaScript built-in `String` class. It
|
|
3
|
+
* adds utility methods to the `String` class without modifying the global namespace
|
|
4
|
+
* directly. This patch includes methods for key validation, object type checking,
|
|
5
|
+
* and retrieving the string tag of an object. These methods are useful for
|
|
6
|
+
* enhancing the capabilities of the standard `String` class with additional
|
|
7
|
+
* utility functions.
|
|
8
|
+
*/
|
|
9
|
+
export const StringExtensions: Patch;
|
|
10
|
+
import { Patch } from '@nejs/extension';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Patch } from '@nejs/extension';
|
|
2
|
+
/**
|
|
3
|
+
* `StringExtensions` is a patch for the JavaScript built-in `String` class. It
|
|
4
|
+
* adds utility methods to the `String` class without modifying the global namespace
|
|
5
|
+
* directly. This patch includes methods for key validation, object type checking,
|
|
6
|
+
* and retrieving the string tag of an object. These methods are useful for
|
|
7
|
+
* enhancing the capabilities of the standard `String` class with additional
|
|
8
|
+
* utility functions.
|
|
9
|
+
*/
|
|
10
|
+
export const StringExtensions = new Patch(String, {
|
|
11
|
+
/**
|
|
12
|
+
* The `isString` method does exactly what one would it expect. It returns
|
|
13
|
+
* true if the string matches typeof or instanceof as a string.
|
|
14
|
+
*
|
|
15
|
+
* @param {*} value checks to see if the `value` is a string
|
|
16
|
+
* @returns {boolean} `true` if it is a `String`, `false` otherwise
|
|
17
|
+
*/
|
|
18
|
+
isString(value) {
|
|
19
|
+
if (value && (typeof value === 'string' || value instanceof String)) {
|
|
20
|
+
return value.length > 0;
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `SymbolExtensions` is a patch for the JavaScript built-in `Symbol` class. It
|
|
3
|
+
* adds utility methods to the `Symbol` class without modifying the global namespace
|
|
4
|
+
* directly. This patch includes methods for key validation, object type checking,
|
|
5
|
+
* and retrieving the string tag of an object. These methods are useful for
|
|
6
|
+
* enhancing the capabilities of the standard `Symbol` class with additional
|
|
7
|
+
* utility functions.
|
|
8
|
+
*/
|
|
9
|
+
export const SymbolExtensions: Patch;
|
|
10
|
+
import { Patch } from '@nejs/extension';
|