@nejs/basic-extensions 2.9.0 → 2.11.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/dist/@nejs/basic-extensions.bundle.2.11.0.js +19 -0
- package/dist/@nejs/basic-extensions.bundle.2.11.0.js.map +7 -0
- package/dist/cjs/array.extensions.js +174 -0
- package/dist/cjs/array.extensions.js.map +1 -1
- package/dist/cjs/big.int.extension.js +1 -0
- package/dist/cjs/big.int.extension.js.map +1 -1
- package/dist/cjs/classes/descriptor.d.ts +67 -155
- package/dist/cjs/classes/descriptor.js +185 -278
- package/dist/cjs/classes/descriptor.js.map +1 -1
- package/dist/cjs/classes/index.d.ts +1 -0
- package/dist/cjs/classes/index.js +3 -0
- package/dist/cjs/classes/index.js.map +1 -1
- package/dist/cjs/classes/iterable.d.ts +44 -0
- package/dist/cjs/classes/iterable.js +64 -0
- package/dist/cjs/classes/iterable.js.map +1 -1
- package/dist/cjs/classes/param.parser.d.ts +10 -10
- package/dist/cjs/classes/property.d.ts +86 -0
- package/dist/cjs/classes/property.js +284 -0
- package/dist/cjs/classes/property.js.map +1 -0
- package/dist/cjs/classes/symkeys.d.ts +68 -11
- package/dist/cjs/classes/symkeys.js +103 -17
- package/dist/cjs/classes/symkeys.js.map +1 -1
- package/dist/cjs/classes/type.d.ts +4 -4
- package/dist/cjs/function.extensions.js +1 -0
- package/dist/cjs/function.extensions.js.map +1 -1
- package/dist/cjs/global.this.js +29 -0
- package/dist/cjs/global.this.js.map +1 -1
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +19 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/json.extensions.js +19 -18
- package/dist/cjs/json.extensions.js.map +1 -1
- package/dist/cjs/map.extensions.js +1 -0
- package/dist/cjs/map.extensions.js.map +1 -1
- package/dist/cjs/number.extension.js +1 -0
- package/dist/cjs/number.extension.js.map +1 -1
- package/dist/cjs/object.extensions.d.ts +0 -29
- package/dist/cjs/object.extensions.js +218 -255
- package/dist/cjs/object.extensions.js.map +1 -1
- package/dist/cjs/set.extensions.js +1 -0
- package/dist/cjs/set.extensions.js.map +1 -1
- package/dist/cjs/string.extensions.js +474 -469
- package/dist/cjs/string.extensions.js.map +1 -1
- package/dist/cjs/symbol.extensions.js +387 -32
- package/dist/cjs/symbol.extensions.js.map +1 -1
- package/dist/cjs/utils/copy.object.d.ts +408 -0
- package/dist/cjs/utils/copy.object.js +720 -0
- package/dist/cjs/utils/copy.object.js.map +1 -0
- package/dist/cjs/utils/descriptor.utils.d.ts +146 -0
- package/dist/cjs/utils/descriptor.utils.js +614 -0
- package/dist/cjs/utils/descriptor.utils.js.map +1 -0
- package/dist/cjs/utils/index.d.ts +60 -0
- package/dist/cjs/utils/index.js +52 -0
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/toolkit.d.ts +1898 -0
- package/dist/cjs/utils/toolkit.js +1378 -0
- package/dist/cjs/utils/toolkit.js.map +1 -0
- package/dist/mjs/array.extensions.js +174 -0
- package/dist/mjs/array.extensions.js.map +1 -1
- package/dist/mjs/big.int.extension.js +1 -0
- package/dist/mjs/big.int.extension.js.map +1 -1
- package/dist/mjs/classes/descriptor.d.ts +67 -155
- package/dist/mjs/classes/descriptor.js +185 -278
- package/dist/mjs/classes/descriptor.js.map +1 -1
- package/dist/mjs/classes/index.d.ts +1 -0
- package/dist/mjs/classes/index.js +3 -0
- package/dist/mjs/classes/index.js.map +1 -1
- package/dist/mjs/classes/iterable.d.ts +44 -0
- package/dist/mjs/classes/iterable.js +64 -0
- package/dist/mjs/classes/iterable.js.map +1 -1
- package/dist/mjs/classes/param.parser.d.ts +10 -10
- package/dist/mjs/classes/property.d.ts +86 -0
- package/dist/mjs/classes/property.js +280 -0
- package/dist/mjs/classes/property.js.map +1 -0
- package/dist/mjs/classes/symkeys.d.ts +68 -11
- package/dist/mjs/classes/symkeys.js +103 -17
- package/dist/mjs/classes/symkeys.js.map +1 -1
- package/dist/mjs/classes/type.d.ts +4 -4
- package/dist/mjs/function.extensions.js +1 -0
- package/dist/mjs/function.extensions.js.map +1 -1
- package/dist/mjs/global.this.js +6 -0
- package/dist/mjs/global.this.js.map +1 -1
- package/dist/mjs/index.d.ts +3 -0
- package/dist/mjs/index.js +5 -0
- package/dist/mjs/index.js.map +1 -1
- package/dist/mjs/json.extensions.js +19 -18
- package/dist/mjs/json.extensions.js.map +1 -1
- package/dist/mjs/map.extensions.js +1 -0
- package/dist/mjs/map.extensions.js.map +1 -1
- package/dist/mjs/number.extension.js +1 -0
- package/dist/mjs/number.extension.js.map +1 -1
- package/dist/mjs/object.extensions.d.ts +0 -29
- package/dist/mjs/object.extensions.js +215 -251
- package/dist/mjs/object.extensions.js.map +1 -1
- package/dist/mjs/set.extensions.js +1 -0
- package/dist/mjs/set.extensions.js.map +1 -1
- package/dist/mjs/string.extensions.js +474 -469
- package/dist/mjs/string.extensions.js.map +1 -1
- package/dist/mjs/symbol.extensions.js +387 -32
- package/dist/mjs/symbol.extensions.js.map +1 -1
- package/dist/mjs/utils/copy.object.d.ts +408 -0
- package/dist/mjs/utils/copy.object.js +702 -0
- package/dist/mjs/utils/copy.object.js.map +1 -0
- package/dist/mjs/utils/descriptor.utils.d.ts +146 -0
- package/dist/mjs/utils/descriptor.utils.js +606 -0
- package/dist/mjs/utils/descriptor.utils.js.map +1 -0
- package/dist/mjs/utils/index.d.ts +60 -0
- package/dist/mjs/utils/index.js +36 -0
- package/dist/mjs/utils/index.js.map +1 -0
- package/dist/mjs/utils/toolkit.d.ts +1898 -0
- package/dist/mjs/utils/toolkit.js +1373 -0
- package/dist/mjs/utils/toolkit.js.map +1 -0
- package/package.json +29 -37
- package/repl.bootstrap.js +12 -1
- package/src/array.extensions.js +191 -1
- package/src/big.int.extension.js +3 -1
- package/src/classes/descriptor.js +206 -305
- package/src/classes/index.js +4 -0
- package/src/classes/iterable.js +74 -0
- package/src/classes/property.js +333 -0
- package/src/classes/symkeys.js +120 -19
- package/src/function.extensions.js +2 -0
- package/src/global.this.js +8 -0
- package/src/index.js +6 -0
- package/src/json.extensions.js +18 -19
- package/src/map.extensions.js +3 -1
- package/src/number.extension.js +3 -1
- package/src/object.extensions.js +240 -277
- package/src/set.extensions.js +3 -1
- package/src/string.extensions.js +512 -506
- package/src/symbol.extensions.js +413 -30
- package/src/utils/copy.object.js +780 -0
- package/src/utils/descriptor.utils.js +707 -0
- package/src/utils/index.js +74 -0
- package/src/utils/toolkit.js +1473 -0
- package/tests/arrayextensions.test.js +2 -0
- package/tests/index.test.js +1 -0
- package/tests/newClasses/asyncIterable.test.js +2 -0
- package/tests/newClasses/deferred.test.js +5 -3
- package/tests/newClasses/descriptor.test.js +6 -8
- package/tests/newClasses/iterable.test.js +2 -0
- package/tests/newClasses/refmap.test.js +2 -1
- package/tests/newClasses/refset.test.js +2 -0
- package/tests/objectextensions.test.js +2 -0
- package/tests/setextensions.test.js +2 -0
- package/tests/stringextensions.test.js +1 -0
- package/tests/utils/toolkit.test.js +223 -0
- package/tsconfig.base.json +1 -1
- package/vitest.config.js +7 -0
- package/dist/@nejs/basic-extensions.bundle.2.8.0.js +0 -19
- package/dist/@nejs/basic-extensions.bundle.2.8.0.js.map +0 -7
- package/docs/assets/anchor.js +0 -350
- package/docs/assets/bass-addons.css +0 -12
- package/docs/assets/bass.css +0 -544
- package/docs/assets/fonts/EOT/SourceCodePro-Bold.eot +0 -0
- package/docs/assets/fonts/EOT/SourceCodePro-Regular.eot +0 -0
- package/docs/assets/fonts/LICENSE.txt +0 -93
- package/docs/assets/fonts/OTF/SourceCodePro-Bold.otf +0 -0
- package/docs/assets/fonts/OTF/SourceCodePro-Regular.otf +0 -0
- package/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf +0 -0
- package/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf +0 -0
- package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff +0 -0
- package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff +0 -0
- package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff +0 -0
- package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff +0 -0
- package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 +0 -0
- package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 +0 -0
- package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 +0 -0
- package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 +0 -0
- package/docs/assets/fonts/source-code-pro.css +0 -23
- package/docs/assets/github.css +0 -123
- package/docs/assets/site.js +0 -168
- package/docs/assets/split.css +0 -15
- package/docs/assets/split.js +0 -782
- package/docs/assets/style.css +0 -147
- package/docs/index.html +0 -35485
package/src/classes/index.js
CHANGED
|
@@ -21,6 +21,9 @@ export * from './param.parser.js'
|
|
|
21
21
|
import { PluggableProxy, ProxyHandler } from './pluggable.proxy.js'
|
|
22
22
|
export * from './pluggable.proxy.js'
|
|
23
23
|
|
|
24
|
+
import { Property, PropertyExtensions } from './property.js'
|
|
25
|
+
export * from './property.js'
|
|
26
|
+
|
|
24
27
|
import { RefMap } from './refmap.js'
|
|
25
28
|
export * from './refmap.js'
|
|
26
29
|
|
|
@@ -44,6 +47,7 @@ export const NewClassesExtension = new Patch(globalThis, {
|
|
|
44
47
|
ParamParser,
|
|
45
48
|
PluggableProxy,
|
|
46
49
|
ProxyHandler,
|
|
50
|
+
Property,
|
|
47
51
|
RefMap,
|
|
48
52
|
RefSet,
|
|
49
53
|
Symkeys,
|
package/src/classes/iterable.js
CHANGED
|
@@ -215,6 +215,80 @@ export class Iterator {
|
|
|
215
215
|
* @private
|
|
216
216
|
*/
|
|
217
217
|
#iterator = null;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Creates an Iterator for the keys of the given object.
|
|
221
|
+
*
|
|
222
|
+
* @note alternatives to keyFetcher might be `Reflect.ownKeys` or even
|
|
223
|
+
* `Object.keys`. Each type of fetcher has their own requirements but
|
|
224
|
+
* any function that takes an object and returns keys will suffice.
|
|
225
|
+
*
|
|
226
|
+
* @param {Object} object - The object whose keys will be iterated.
|
|
227
|
+
* @param {Function} [mapEach] - Optional function to map each key.
|
|
228
|
+
* @param {Function} [keyFetcher=Object.getOwnPropertyNames] - Function to
|
|
229
|
+
* fetch keys from the object. Defaults to Object.getOwnPropertyNames.
|
|
230
|
+
* @returns {Iterator} An Iterator instance containing the object's keys.
|
|
231
|
+
*/
|
|
232
|
+
static keys(object, mapEach, keyFetcher) {
|
|
233
|
+
keyFetcher ??= Object.getOwnPropertyNames;
|
|
234
|
+
|
|
235
|
+
const keys = keyFetcher(object);
|
|
236
|
+
return new Iterator(keys, mapEach);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Creates an Iterator for the entries of the given object.
|
|
241
|
+
*
|
|
242
|
+
* @note alternatives to keyFetcher might be `Reflect.ownKeys` or even
|
|
243
|
+
* `Object.keys`. Each type of fetcher has their own requirements but
|
|
244
|
+
* any function that takes an object and returns keys will suffice.
|
|
245
|
+
*
|
|
246
|
+
* @param {Object} object - The object whose entries will be iterated.
|
|
247
|
+
* @param {Function} [mapEach] - Optional function to map each entry.
|
|
248
|
+
* @param {Function} [keyFetcher=Object.getOwnPropertyNames] - Function to
|
|
249
|
+
* fetch keys from the object. Defaults to Object.getOwnPropertyNames.
|
|
250
|
+
* @returns {Iterator} An Iterator instance containing the object's entries.
|
|
251
|
+
*/
|
|
252
|
+
static entries(object, mapEach, keyFetcher) {
|
|
253
|
+
keyFetcher ??= Object.getOwnPropertyNames;
|
|
254
|
+
|
|
255
|
+
const keys = keyFetcher(object);
|
|
256
|
+
const entries = [];
|
|
257
|
+
|
|
258
|
+
for (const key of keys) {
|
|
259
|
+
entries.push([key, object[key]]);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return new Iterator(entries, mapEach)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Creates an Iterator for the property descriptors of the given object.
|
|
267
|
+
*
|
|
268
|
+
* @note alternatives to keyFetcher might be `Reflect.ownKeys` or even
|
|
269
|
+
* `Object.keys`. Each type of fetcher has their own requirements but
|
|
270
|
+
* any function that takes an object and returns keys will suffice.
|
|
271
|
+
*
|
|
272
|
+
* @param {Object} object - The object whose descriptors will be iterated.
|
|
273
|
+
* @param {Function} [mapEach] - Optional function to map each descriptor
|
|
274
|
+
* entry.
|
|
275
|
+
* @param {Function} [keyFetcher=Object.getOwnPropertyNames] - Function to
|
|
276
|
+
* fetch keys from the object. Defaults to Object.getOwnPropertyNames.
|
|
277
|
+
* @returns {Iterator} An Iterator instance containing entries of [key,
|
|
278
|
+
* descriptor] pairs.
|
|
279
|
+
*/
|
|
280
|
+
static descriptors(object, mapEach, keyFetcher) {
|
|
281
|
+
keyFetcher ??= Object.getOwnPropertyNames;
|
|
282
|
+
|
|
283
|
+
const keys = keyFetcher(object);
|
|
284
|
+
const entries = [];
|
|
285
|
+
|
|
286
|
+
for (const key of keys) {
|
|
287
|
+
entries.push([key, Object.getOwnPropertyDescriptor(object, key)])
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return new Iterator(entries, mapEach);
|
|
291
|
+
}
|
|
218
292
|
}
|
|
219
293
|
|
|
220
294
|
export const IterableExtensions = new Extension(Iterable)
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { Extension } from '@nejs/extension'
|
|
2
|
+
|
|
3
|
+
export class Property {
|
|
4
|
+
constructor(key, descriptor) {
|
|
5
|
+
if (key.startsWith(':')) key = Symbol.for(key.slice(1))
|
|
6
|
+
if (typeof key !== 'string' && typeof key !== 'symbol') {
|
|
7
|
+
throw new TypeError('Key or symbol or :symbol must be supplied!');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
this.key = key;
|
|
11
|
+
|
|
12
|
+
if (!Property.is.descriptor(descriptor)) {
|
|
13
|
+
this.descriptor = {
|
|
14
|
+
value: descriptor,
|
|
15
|
+
writable: true,
|
|
16
|
+
configurable: true,
|
|
17
|
+
enumerable: true,
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.descriptor = descriptor;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
apply(toObject, asKey) {
|
|
26
|
+
if (!toObject || !['object','function'].some(k => k == typeof toObject))
|
|
27
|
+
return;
|
|
28
|
+
|
|
29
|
+
return Object.defineProperty(toObject, asKey ?? this.key, this.descriptor)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
get descriptor() {
|
|
33
|
+
const baseline = { configurable: true, enumerable: false };
|
|
34
|
+
const result = {
|
|
35
|
+
enumerable: this.meta.enumerable,
|
|
36
|
+
configurable: this.meta.configurable,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
if (this.is.accessor) {
|
|
40
|
+
result.get = this.meta.accessor.get;
|
|
41
|
+
result.set = this.meta.accessor.set;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
result.value = this.meta.data.value;
|
|
45
|
+
result.writable = this.meta.data.writable;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return Object.defineProperties(result, {
|
|
49
|
+
make: {
|
|
50
|
+
...baseline,
|
|
51
|
+
get() {
|
|
52
|
+
const self = this;
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
get enumerable() {self.enumerable = true; return self},
|
|
56
|
+
get hidden() {self.enumerable = false; return self},
|
|
57
|
+
|
|
58
|
+
get writable() {self.writable = true; return self},
|
|
59
|
+
get readonly() {self.writable = false; return self},
|
|
60
|
+
|
|
61
|
+
get configurable() {self.configurable = true; return self},
|
|
62
|
+
get immutable() {self.configurable = false; return self},
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
is: {
|
|
68
|
+
...baseline,
|
|
69
|
+
get() {
|
|
70
|
+
const self = this;
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
get accessor() {return self.is.accssor},
|
|
74
|
+
get data() {return self.is.data}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
set descriptor(descriptor) {
|
|
82
|
+
const { is } = this.constructor;
|
|
83
|
+
|
|
84
|
+
if (!is.descriptor(descriptor))
|
|
85
|
+
return;
|
|
86
|
+
|
|
87
|
+
this.meta.configurable = descriptor.configurable ?? true
|
|
88
|
+
this.meta.enumerable = descriptor.enumerable ?? true
|
|
89
|
+
|
|
90
|
+
if (Reflect.has(descriptor, 'get') || Reflect.has(descriptor, 'set')) {
|
|
91
|
+
const { get, set } = descriptor;
|
|
92
|
+
|
|
93
|
+
if (get !== undefined) this.meta.accessor.get = get;
|
|
94
|
+
if (set !== undefined) this.meta.accessor.set = set;
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const { value, writable } = descriptor;
|
|
98
|
+
|
|
99
|
+
this.meta.data.value = value;
|
|
100
|
+
this.meta.data.writable = writable ?? true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get is() {
|
|
105
|
+
const self = this;
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
get accessor() {
|
|
109
|
+
return !!(
|
|
110
|
+
self.meta.accessor.get ||
|
|
111
|
+
self.meta.accessor.set
|
|
112
|
+
);
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
get data() {
|
|
116
|
+
return !!!this.accessor
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
toString(colors = false, {key, descriptor} = {}) {
|
|
122
|
+
const bold = s => colors ? `\x1b[1m${s}\x1b[22m` : s;
|
|
123
|
+
const dim = s => colors ? `\x1b[2m${s}\x1b[22m` : s;
|
|
124
|
+
const red = s => colors ? `\x1b[31m${s}\x1b[39m` : s;
|
|
125
|
+
const green = s => colors ? `\x1b[32m${s}\x1b[39m` : s;
|
|
126
|
+
const blue = s => colors ? `\x1b[34m${s}\x1b[39m` : s;
|
|
127
|
+
|
|
128
|
+
if (!key) ({key} = this);
|
|
129
|
+
if (!descriptor || !Property.is.descriptor(descriptor))
|
|
130
|
+
({descriptor} = this);
|
|
131
|
+
|
|
132
|
+
const buffer = [`${bold(key)} { `]
|
|
133
|
+
const keyPresent = (object) => (key) => Reflect.has(object, key)
|
|
134
|
+
const eqeq = (value, compare = (a,b) => a === b) =>
|
|
135
|
+
(element) => compare(element, value);
|
|
136
|
+
|
|
137
|
+
if (['get', 'set'].some(keyPresent(descriptor))) {
|
|
138
|
+
if (descriptor.get) {
|
|
139
|
+
buffer.push(blue('getter'))
|
|
140
|
+
if (descriptor.set) {
|
|
141
|
+
buffer.push(bold('|'))
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (descriptor.set) {
|
|
146
|
+
buffer.push(blue('setter'))
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
buffer.push(green('value'))
|
|
151
|
+
buffer.push(bold('|'))
|
|
152
|
+
buffer.push(descriptor.writable ? green('writable') : red('readonly'))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
buffer.push(' ')
|
|
156
|
+
buffer.push(descriptor.configurable ? green('mutable') : red('immuatable'))
|
|
157
|
+
|
|
158
|
+
buffer.push(' ')
|
|
159
|
+
buffer.push(descriptor.enumerable ? green('visible') : red('hidden'))
|
|
160
|
+
|
|
161
|
+
buffer.push(' }')
|
|
162
|
+
|
|
163
|
+
return buffer.join('')
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
[Symbol.for('nodejs.util.inspect.custom')](depth, options, inspect) {
|
|
167
|
+
return this.toString(true);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Creates an accessor property with customizable getter and setter functions.
|
|
172
|
+
*
|
|
173
|
+
* This method offers flexible ways to define accessor properties, including
|
|
174
|
+
* support for storage-based getters and setters. It can handle various input
|
|
175
|
+
* formats, making it versatile for different use cases.
|
|
176
|
+
*
|
|
177
|
+
* @param {string} name - The name of the accessor property.
|
|
178
|
+
* @param {Object} accessors - Object containing getter and/or setter functions.
|
|
179
|
+
* @param {Function} [accessors.get] - Getter function for the property.
|
|
180
|
+
* @param {Function} [accessors.set] - Setter function for the property.
|
|
181
|
+
* @param {Object} [accessors.prototype] - Prototype object for getter/setter.
|
|
182
|
+
* @param {Object} [options] - Additional options for the accessor property.
|
|
183
|
+
* @param {boolean} [options.configurable=true] - Whether property is configurable.
|
|
184
|
+
* @param {boolean} [options.enumerable=true] - Whether property is enumerable.
|
|
185
|
+
* @param {Object} [options.storage] - Storage object for getter/setter closures.
|
|
186
|
+
* @returns {Property} A new Property instance representing the accessor.
|
|
187
|
+
* @throws {TypeError} If no name, getter, or setter is provided.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* // Basic usage
|
|
191
|
+
* Property.accessor('color', {
|
|
192
|
+
* get() { return this._color; },
|
|
193
|
+
* set(value) { this._color = value; }
|
|
194
|
+
* });
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* // Using storage
|
|
198
|
+
* Property.accessor('keyword', {
|
|
199
|
+
* get(storage) { return () => storage.keyword; },
|
|
200
|
+
* set(storage) { return (value) => { storage.keyword = value; } }
|
|
201
|
+
* }, { storage: { keyword: 'initial' } });
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* // Using named getter function
|
|
205
|
+
* Property.accessor('color', function get() { return 'red' })
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* // Using prototype
|
|
209
|
+
* const ColorAccessors = {
|
|
210
|
+
* red: { get() { return this._red; } }
|
|
211
|
+
* };
|
|
212
|
+
* Property.accessor('red', ColorAccessors.red);
|
|
213
|
+
*/
|
|
214
|
+
static accessor(
|
|
215
|
+
name,
|
|
216
|
+
{get, set, prototype},
|
|
217
|
+
{configurable, enumerable, storage} = {}
|
|
218
|
+
) {
|
|
219
|
+
if (!get && !set && prototype) {
|
|
220
|
+
const constructor = prototype?.constructor;
|
|
221
|
+
|
|
222
|
+
if (constructor?.name === 'get') {
|
|
223
|
+
get = constructor;
|
|
224
|
+
}
|
|
225
|
+
else if (constructor?.name === 'set') {
|
|
226
|
+
set = constructor
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (get && storage && get.length == 1) {
|
|
231
|
+
get = get(storage);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (set && storage && set.length == 1) {
|
|
235
|
+
set = set(storage);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!name && !get && !set) throw new TypeError('Cannot create accessor');
|
|
239
|
+
|
|
240
|
+
configurable ??= true
|
|
241
|
+
enumerable ??= true
|
|
242
|
+
|
|
243
|
+
return new Property(name, { get, set, configurable, enumerable });
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
static data(name, value, { writable, configurable, enumerable } = {}) {
|
|
247
|
+
if (!name) throw new TypeError('Cannot create data property without name')
|
|
248
|
+
|
|
249
|
+
writable ??= true
|
|
250
|
+
configurable ??= true
|
|
251
|
+
enumerable ??= true
|
|
252
|
+
|
|
253
|
+
return new Property(name, { value, writable, configurable, enumerable })
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
static from(object, name) {
|
|
257
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, name);
|
|
258
|
+
return new Property(name, descriptor);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static get is() {
|
|
262
|
+
return {
|
|
263
|
+
object(value) {
|
|
264
|
+
return value && ['object','function'].some(k => k == typeof value);
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
descriptor(object) {
|
|
268
|
+
if (!Property.is.object(object)) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const present = element => Reflect.has(object, element);
|
|
273
|
+
const props = {
|
|
274
|
+
base: ['configurable', 'enumerable'],
|
|
275
|
+
data: ['writable', 'value'],
|
|
276
|
+
accessor: ['get', 'set'],
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
if (Object.getOwnPropertyNames(object).length > 4)
|
|
280
|
+
return false;
|
|
281
|
+
|
|
282
|
+
if (props.data.some(present) && props.accessor.some(present))
|
|
283
|
+
return false;
|
|
284
|
+
|
|
285
|
+
if (props.base.some(present)) return true;
|
|
286
|
+
if (props.data.some(present)) return true;
|
|
287
|
+
if (props.accessor.some(present)) return true;
|
|
288
|
+
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
static {
|
|
295
|
+
const storage = Object.assign(Object.create(null), {
|
|
296
|
+
key: undefined,
|
|
297
|
+
meta: {
|
|
298
|
+
enumerable: true,
|
|
299
|
+
configurable: true,
|
|
300
|
+
accessor: {
|
|
301
|
+
get: undefined,
|
|
302
|
+
set: undefined
|
|
303
|
+
},
|
|
304
|
+
data: {
|
|
305
|
+
value: undefined,
|
|
306
|
+
writable: true
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
basic_accessor(this.prototype, 'key', storage.key, storage)
|
|
312
|
+
basic_accessor(this.prototype, 'meta', storage.meta, storage);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export const PropertyExtensions = new Extension(Property);
|
|
317
|
+
|
|
318
|
+
function basic_accessor(prototype, key, initialValue, storage = {}) {
|
|
319
|
+
storage[key] = initialValue;
|
|
320
|
+
|
|
321
|
+
Object.defineProperty(prototype, key, {
|
|
322
|
+
get() {
|
|
323
|
+
return storage[key]
|
|
324
|
+
},
|
|
325
|
+
set(value) {
|
|
326
|
+
storage[key] = value
|
|
327
|
+
},
|
|
328
|
+
enumerable: true,
|
|
329
|
+
configurable: true,
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
return Object.getOwnPropertyDescriptor(prototype, key);
|
|
333
|
+
}
|
package/src/classes/symkeys.js
CHANGED
|
@@ -18,35 +18,136 @@ import { Extension } from '@nejs/extension'
|
|
|
18
18
|
*/
|
|
19
19
|
export class Symkeys {
|
|
20
20
|
/**
|
|
21
|
-
* Adds a new
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
21
|
+
* Adds a new symbol to the Symkeys instance with the given name and
|
|
22
|
+
* associated data.
|
|
23
|
+
*
|
|
24
|
+
* This method generates a unique symbol based on the provided name,
|
|
25
|
+
* optional domain, separator, and token. It also allows embedding
|
|
26
|
+
* additional data into the symbol's name.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} named - The base name for the new symbol.
|
|
29
|
+
* @param {Object} options - Additional options for the symbol.
|
|
30
|
+
* @param {*} [options.associate={}] - Data to associate with the symbol.
|
|
31
|
+
* @param {Object} [options.embed] - Optional data to embed in the symbol.
|
|
32
|
+
* @param {string} [options.useDomain] - Optional domain to include in the
|
|
33
|
+
* symbol's name.
|
|
34
|
+
* @param {string} [options.useSeparator] - Optional separator to use in
|
|
35
|
+
* the symbol's name.
|
|
36
|
+
* @param {string} [options.useToken] - Optional token to use for the
|
|
37
|
+
* symbol. If not provided, a random token is generated.
|
|
38
|
+
* @returns {Symbol} The newly created symbol.
|
|
27
39
|
*
|
|
28
40
|
* @example
|
|
29
|
-
* // Add
|
|
30
|
-
* const
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
41
|
+
* // Add a symbol with associated data
|
|
42
|
+
* const mySymbol = symkeys.add('myIdentifier', {
|
|
43
|
+
* associate: { foo: 'bar' },
|
|
44
|
+
* embed: { baz: 'qux' },
|
|
45
|
+
* useDomain: 'exampleDomain',
|
|
46
|
+
* useSeparator: '-',
|
|
47
|
+
* useToken: 'customToken',
|
|
48
|
+
* })
|
|
49
|
+
* console.log(mySymbol)
|
|
50
|
+
* // Symbol(@exampleDomain-myIdentifier {"baz":"qux"} #customToken)
|
|
34
51
|
*/
|
|
35
|
-
add(
|
|
52
|
+
add(
|
|
53
|
+
named,
|
|
54
|
+
{
|
|
55
|
+
associate = {},
|
|
56
|
+
embed = undefined,
|
|
57
|
+
useDomain = undefined,
|
|
58
|
+
useSeparator = undefined,
|
|
59
|
+
useToken = undefined,
|
|
60
|
+
}
|
|
61
|
+
) {
|
|
36
62
|
// Generate a unique token for the symbol
|
|
37
|
-
const token = Symkeys.token
|
|
63
|
+
const token = useToken ?? Symkeys.token
|
|
38
64
|
|
|
39
65
|
// Calculate a name (optionally with domain and separator)
|
|
40
|
-
|
|
66
|
+
let symName = this.calculateName(named, useDomain, useSeparator)
|
|
67
|
+
|
|
68
|
+
if (embed && typeof embed === 'object') {
|
|
69
|
+
try {
|
|
70
|
+
symName += ` ${JSON.stringify(embed)}`
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.warn(`Cannot create JSON from ${embed}; skipping`)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
41
76
|
|
|
42
77
|
// Create a symbol using the provided name and the unique token
|
|
43
|
-
const symbol = Symbol.for(`@${symName} #${token}`)
|
|
78
|
+
const symbol = Symbol.for(`@${symName} #${token}`)
|
|
44
79
|
|
|
45
80
|
// Store the symbol and associated data in the Symkeys's internal map
|
|
46
|
-
this[Symkeys.kDataKey].set(symbol,
|
|
81
|
+
this[Symkeys.kDataKey].set(symbol, associate ?? {})
|
|
47
82
|
|
|
48
83
|
// Return the unique symbol for external use
|
|
49
|
-
return symbol
|
|
84
|
+
return symbol
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates or retrieves a shared symbol key with the given name and
|
|
89
|
+
* optional associated data.
|
|
90
|
+
*
|
|
91
|
+
* This method generates a shared symbol key using the provided name
|
|
92
|
+
* and optional parameters. If the symbol already exists in the
|
|
93
|
+
* Symkeys's internal map, it updates the associated data if provided.
|
|
94
|
+
* Otherwise, it creates a new symbol with the specified parameters.
|
|
95
|
+
*
|
|
96
|
+
* @param {string} named - The name to use for the shared symbol key.
|
|
97
|
+
* @param {Object} options - Optional parameters for the shared symbol key.
|
|
98
|
+
* @param {Object} [options.associate] - Data to associate with the symbol.
|
|
99
|
+
* @param {Object} [options.embed] - Data to embed in the symbol's name.
|
|
100
|
+
* @param {string} [options.useDomain] - Domain to include in the symbol's name.
|
|
101
|
+
* @param {string} [options.useSeparator] - Separator to use in the symbol's name.
|
|
102
|
+
* @returns {Symbol} The shared symbol key.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* // Create or retrieve a shared symbol key with associated data
|
|
106
|
+
* const sharedSymbol = symkeys.sharedKey('mySharedKey', {
|
|
107
|
+
* associate: { foo: 'bar' },
|
|
108
|
+
* embed: { baz: 'qux' },
|
|
109
|
+
* useDomain: 'exampleDomain',
|
|
110
|
+
* useSeparator: '-',
|
|
111
|
+
* })
|
|
112
|
+
* console.log(sharedSymbol)
|
|
113
|
+
* // Symbol(@exampleDomain-mySharedKey {"baz":"qux"} #shared)
|
|
114
|
+
*/
|
|
115
|
+
sharedKey(named, { associate, embed, useDomain, useSeparator }) {
|
|
116
|
+
// Calculate the symbol name with optional domain and separator
|
|
117
|
+
const symName = this.calculateName(named, useDomain, useSeparator)
|
|
118
|
+
|
|
119
|
+
// Initialize JSON string for embedded data
|
|
120
|
+
let json = ''
|
|
121
|
+
if (embed && typeof embed === 'object') {
|
|
122
|
+
try {
|
|
123
|
+
json = ` ${JSON.stringify(embed)}`
|
|
124
|
+
} catch (ignored) {
|
|
125
|
+
// Ignore JSON stringify errors
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Create the shared symbol key
|
|
130
|
+
const symbol = Symbol.for(`@${symName}${json} #shared`)
|
|
131
|
+
|
|
132
|
+
// Check if the symbol already exists in the internal map
|
|
133
|
+
if (this[Symkeys.kDataKey].has(symbol)) {
|
|
134
|
+
// Update associated data if provided and symbol is a Symkey
|
|
135
|
+
if (associate && symbol.isSymkey) {
|
|
136
|
+
symbol.data = associate
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Return the existing symbol
|
|
140
|
+
return symbol
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Add a new symbol with the specified parameters
|
|
144
|
+
return this.add(named, {
|
|
145
|
+
associate: associate ?? {},
|
|
146
|
+
embed,
|
|
147
|
+
useDomain,
|
|
148
|
+
useSeparator,
|
|
149
|
+
useToken: 'shared'
|
|
150
|
+
})
|
|
50
151
|
}
|
|
51
152
|
|
|
52
153
|
/**
|
|
@@ -175,7 +276,7 @@ export class Symkeys {
|
|
|
175
276
|
token(forSymbol) {
|
|
176
277
|
// Use a regular expression to match the token pattern in the symbol
|
|
177
278
|
// description exists on symbol but our JS output target is too old
|
|
178
|
-
return /^.* \#(.*?)$/.exec(forSymbol)
|
|
279
|
+
return /^.* \#(.*?)$/.exec(forSymbol)?.description?.[1];
|
|
179
280
|
}
|
|
180
281
|
|
|
181
282
|
/**
|
|
@@ -386,7 +487,7 @@ export class Symkeys {
|
|
|
386
487
|
return false
|
|
387
488
|
}
|
|
388
489
|
|
|
389
|
-
return !!/^@.*? #\w+$/.exec(value
|
|
490
|
+
return !!/^@.*? #\w+$/.exec(value?.description)
|
|
390
491
|
}
|
|
391
492
|
|
|
392
493
|
/**
|
|
@@ -772,6 +772,8 @@ export const FunctionPrototypeExtensions = new Patch(Function.prototype, {
|
|
|
772
772
|
// Object<->Function<->Global occurs. See original source in global.this.js
|
|
773
773
|
// {@see globalThis.isThenElse}
|
|
774
774
|
function isThenElse(bv, tv, ev) {
|
|
775
|
+
function isFunction(value) { typeof value === 'function' }
|
|
776
|
+
|
|
775
777
|
if (arguments.length > 1) {
|
|
776
778
|
var _then = isFunction(tv) ? tv(bv) : tv; if (arguments.length > 2) {
|
|
777
779
|
var _else = isFunction(ev) ? tv(bv) : ev; return bv ? _then : _else
|
package/src/global.this.js
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { Patch } from '@nejs/extension'
|
|
2
2
|
import { FunctionExtensions } from './function.extensions.js'
|
|
3
|
+
import * as copyObject from './utils/copy.object.js'
|
|
4
|
+
import { as, has, is, si } from './utils/toolkit.js'
|
|
3
5
|
|
|
4
6
|
const { isClass, isFunction } = FunctionExtensions.patches
|
|
5
7
|
const CustomInspect = Symbol.for('nodejs.util.inspect.custom')
|
|
6
8
|
|
|
7
9
|
export const GlobalFunctionsAndProps = new Patch(globalThis, {
|
|
8
10
|
[Patch.kMutablyHidden]: {
|
|
11
|
+
/** copyObject suite exports into global */
|
|
12
|
+
...copyObject,
|
|
13
|
+
|
|
14
|
+
/** Type toolkit exports into global */
|
|
15
|
+
as, has, is, si,
|
|
16
|
+
|
|
9
17
|
/**
|
|
10
18
|
* The `isThenElse` function is a utility function that behaves like a
|
|
11
19
|
* ternary operator. It takes three arguments: `boolValue`, `thenValue`,
|
package/src/index.js
CHANGED
|
@@ -17,6 +17,7 @@ import { DescriptorExtensions, Descriptor } from './classes/descriptor.js'
|
|
|
17
17
|
import { IntrospectorExtensions } from './classes/introspector.js'
|
|
18
18
|
import { IteratorExtensions, IterableExtensions } from './classes/iterable.js'
|
|
19
19
|
import { ParamParserExtensions } from './classes/param.parser.js'
|
|
20
|
+
import { PropertyExtensions } from './classes/property.js'
|
|
20
21
|
import {
|
|
21
22
|
PluggableProxyExtensions,
|
|
22
23
|
ProxyHandlerExtensions,
|
|
@@ -27,6 +28,10 @@ import { RefSetExtensions } from './classes/refset.js'
|
|
|
27
28
|
import { SymkeysExtension } from './classes/symkeys.js'
|
|
28
29
|
import { TypeExtensions } from './classes/type.js'
|
|
29
30
|
|
|
31
|
+
export * from './utils/copy.object.js'
|
|
32
|
+
export * from './utils/toolkit.js'
|
|
33
|
+
export * from './utils/descriptor.utils.js'
|
|
34
|
+
|
|
30
35
|
import {
|
|
31
36
|
AsyncIteratorExtensions,
|
|
32
37
|
AsyncIterableExtensions
|
|
@@ -75,6 +80,7 @@ const Extensions = {
|
|
|
75
80
|
[ParamParserExtensions.key]: ParamParserExtensions,
|
|
76
81
|
[PluggableProxyExtensions.key]: PluggableProxyExtensions,
|
|
77
82
|
[ProxyHandlerExtensions.key]: ProxyHandlerExtensions,
|
|
83
|
+
[PropertyExtensions.key]: PropertyExtensions,
|
|
78
84
|
[RefMapExtensions.key]: RefMapExtensions,
|
|
79
85
|
[RefSetExtensions.key]: RefSetExtensions,
|
|
80
86
|
[SymkeysExtension.key]: SymkeysExtension,
|