@nejs/basic-extensions 2.8.0 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/README.md +268 -147
  2. package/bin/version +100 -0
  3. package/dist/@nejs/basic-extensions.bundle.2.10.0.js +19 -0
  4. package/dist/@nejs/basic-extensions.bundle.2.10.0.js.map +7 -0
  5. package/dist/cjs/array.extensions.js +174 -0
  6. package/dist/cjs/array.extensions.js.map +1 -1
  7. package/dist/cjs/big.int.extension.js +1 -0
  8. package/dist/cjs/big.int.extension.js.map +1 -1
  9. package/dist/cjs/classes/descriptor.js +1 -1
  10. package/dist/cjs/classes/descriptor.js.map +1 -1
  11. package/dist/cjs/classes/index.d.ts +1 -0
  12. package/dist/cjs/classes/index.js +3 -0
  13. package/dist/cjs/classes/index.js.map +1 -1
  14. package/dist/cjs/classes/iterable.d.ts +44 -0
  15. package/dist/cjs/classes/iterable.js +64 -0
  16. package/dist/cjs/classes/iterable.js.map +1 -1
  17. package/dist/cjs/classes/param.parser.d.ts +10 -10
  18. package/dist/cjs/classes/property.d.ts +86 -0
  19. package/dist/cjs/classes/property.js +284 -0
  20. package/dist/cjs/classes/property.js.map +1 -0
  21. package/dist/cjs/classes/symkeys.d.ts +68 -11
  22. package/dist/cjs/classes/symkeys.js +103 -17
  23. package/dist/cjs/classes/symkeys.js.map +1 -1
  24. package/dist/cjs/classes/type.d.ts +4 -4
  25. package/dist/cjs/function.extensions.js +1 -0
  26. package/dist/cjs/function.extensions.js.map +1 -1
  27. package/dist/cjs/global.this.js +29 -0
  28. package/dist/cjs/global.this.js.map +1 -1
  29. package/dist/cjs/index.d.ts +2 -0
  30. package/dist/cjs/index.js +18 -0
  31. package/dist/cjs/index.js.map +1 -1
  32. package/dist/cjs/json.extensions.js +22 -20
  33. package/dist/cjs/json.extensions.js.map +1 -1
  34. package/dist/cjs/map.extensions.js +1 -0
  35. package/dist/cjs/map.extensions.js.map +1 -1
  36. package/dist/cjs/number.extension.js +1 -0
  37. package/dist/cjs/number.extension.js.map +1 -1
  38. package/dist/cjs/object.extensions.d.ts +0 -29
  39. package/dist/cjs/object.extensions.js +218 -243
  40. package/dist/cjs/object.extensions.js.map +1 -1
  41. package/dist/cjs/set.extensions.js +1 -0
  42. package/dist/cjs/set.extensions.js.map +1 -1
  43. package/dist/cjs/string.extensions.js +478 -283
  44. package/dist/cjs/string.extensions.js.map +1 -1
  45. package/dist/cjs/symbol.extensions.js +500 -24
  46. package/dist/cjs/symbol.extensions.js.map +1 -1
  47. package/dist/cjs/utils/copy.object.d.ts +408 -0
  48. package/dist/cjs/utils/copy.object.js +720 -0
  49. package/dist/cjs/utils/copy.object.js.map +1 -0
  50. package/dist/cjs/utils/index.d.ts +1 -0
  51. package/dist/cjs/utils/index.js +19 -0
  52. package/dist/cjs/utils/index.js.map +1 -0
  53. package/dist/cjs/utils/toolkit.d.ts +1897 -0
  54. package/dist/cjs/utils/toolkit.js +1377 -0
  55. package/dist/cjs/utils/toolkit.js.map +1 -0
  56. package/dist/mjs/array.extensions.js +174 -0
  57. package/dist/mjs/array.extensions.js.map +1 -1
  58. package/dist/mjs/big.int.extension.js +1 -0
  59. package/dist/mjs/big.int.extension.js.map +1 -1
  60. package/dist/mjs/classes/descriptor.js +1 -1
  61. package/dist/mjs/classes/descriptor.js.map +1 -1
  62. package/dist/mjs/classes/index.d.ts +1 -0
  63. package/dist/mjs/classes/index.js +3 -0
  64. package/dist/mjs/classes/index.js.map +1 -1
  65. package/dist/mjs/classes/iterable.d.ts +44 -0
  66. package/dist/mjs/classes/iterable.js +64 -0
  67. package/dist/mjs/classes/iterable.js.map +1 -1
  68. package/dist/mjs/classes/param.parser.d.ts +10 -10
  69. package/dist/mjs/classes/property.d.ts +86 -0
  70. package/dist/mjs/classes/property.js +280 -0
  71. package/dist/mjs/classes/property.js.map +1 -0
  72. package/dist/mjs/classes/symkeys.d.ts +68 -11
  73. package/dist/mjs/classes/symkeys.js +103 -17
  74. package/dist/mjs/classes/symkeys.js.map +1 -1
  75. package/dist/mjs/classes/type.d.ts +4 -4
  76. package/dist/mjs/function.extensions.js +1 -0
  77. package/dist/mjs/function.extensions.js.map +1 -1
  78. package/dist/mjs/global.this.js +6 -0
  79. package/dist/mjs/global.this.js.map +1 -1
  80. package/dist/mjs/index.d.ts +2 -0
  81. package/dist/mjs/index.js +4 -0
  82. package/dist/mjs/index.js.map +1 -1
  83. package/dist/mjs/json.extensions.js +22 -20
  84. package/dist/mjs/json.extensions.js.map +1 -1
  85. package/dist/mjs/map.extensions.js +1 -0
  86. package/dist/mjs/map.extensions.js.map +1 -1
  87. package/dist/mjs/number.extension.js +1 -0
  88. package/dist/mjs/number.extension.js.map +1 -1
  89. package/dist/mjs/object.extensions.d.ts +0 -29
  90. package/dist/mjs/object.extensions.js +215 -239
  91. package/dist/mjs/object.extensions.js.map +1 -1
  92. package/dist/mjs/set.extensions.js +1 -0
  93. package/dist/mjs/set.extensions.js.map +1 -1
  94. package/dist/mjs/string.extensions.js +478 -283
  95. package/dist/mjs/string.extensions.js.map +1 -1
  96. package/dist/mjs/symbol.extensions.js +501 -25
  97. package/dist/mjs/symbol.extensions.js.map +1 -1
  98. package/dist/mjs/utils/copy.object.d.ts +408 -0
  99. package/dist/mjs/utils/copy.object.js +702 -0
  100. package/dist/mjs/utils/copy.object.js.map +1 -0
  101. package/dist/mjs/utils/index.d.ts +1 -0
  102. package/dist/mjs/utils/index.js +3 -0
  103. package/dist/mjs/utils/index.js.map +1 -0
  104. package/dist/mjs/utils/toolkit.d.ts +1897 -0
  105. package/dist/mjs/utils/toolkit.js +1372 -0
  106. package/dist/mjs/utils/toolkit.js.map +1 -0
  107. package/package.json +30 -38
  108. package/repl.bootstrap.js +12 -1
  109. package/src/array.extensions.js +191 -1
  110. package/src/big.int.extension.js +3 -1
  111. package/src/classes/descriptor.js +1 -1
  112. package/src/classes/index.js +4 -0
  113. package/src/classes/iterable.js +74 -0
  114. package/src/classes/property.js +333 -0
  115. package/src/classes/symkeys.js +120 -19
  116. package/src/function.extensions.js +2 -0
  117. package/src/global.this.js +8 -0
  118. package/src/index.js +5 -0
  119. package/src/json.extensions.js +21 -21
  120. package/src/map.extensions.js +3 -1
  121. package/src/number.extension.js +3 -1
  122. package/src/object.extensions.js +240 -262
  123. package/src/set.extensions.js +3 -1
  124. package/src/string.extensions.js +531 -306
  125. package/src/symbol.extensions.js +529 -25
  126. package/src/utils/copy.object.js +780 -0
  127. package/src/utils/index.js +2 -0
  128. package/src/utils/toolkit.js +1471 -0
  129. package/tests/arrayextensions.test.js +2 -0
  130. package/tests/index.test.js +1 -0
  131. package/tests/newClasses/asyncIterable.test.js +2 -0
  132. package/tests/newClasses/deferred.test.js +5 -3
  133. package/tests/newClasses/descriptor.test.js +2 -0
  134. package/tests/newClasses/iterable.test.js +2 -0
  135. package/tests/newClasses/refmap.test.js +2 -1
  136. package/tests/newClasses/refset.test.js +2 -0
  137. package/tests/objectextensions.test.js +2 -0
  138. package/tests/setextensions.test.js +2 -0
  139. package/tests/stringextensions.test.js +1 -0
  140. package/tests/utils/toolkit.test.js +223 -0
  141. package/tsconfig.base.json +1 -1
  142. package/vitest.config.js +7 -0
  143. package/dist/@nejs/basic-extensions.bundle.2.7.0.js +0 -19
  144. package/dist/@nejs/basic-extensions.bundle.2.7.0.js.map +0 -7
  145. package/docs/assets/anchor.js +0 -350
  146. package/docs/assets/bass-addons.css +0 -12
  147. package/docs/assets/bass.css +0 -544
  148. package/docs/assets/fonts/EOT/SourceCodePro-Bold.eot +0 -0
  149. package/docs/assets/fonts/EOT/SourceCodePro-Regular.eot +0 -0
  150. package/docs/assets/fonts/LICENSE.txt +0 -93
  151. package/docs/assets/fonts/OTF/SourceCodePro-Bold.otf +0 -0
  152. package/docs/assets/fonts/OTF/SourceCodePro-Regular.otf +0 -0
  153. package/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf +0 -0
  154. package/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf +0 -0
  155. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff +0 -0
  156. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff +0 -0
  157. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff +0 -0
  158. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff +0 -0
  159. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 +0 -0
  160. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 +0 -0
  161. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 +0 -0
  162. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 +0 -0
  163. package/docs/assets/fonts/source-code-pro.css +0 -23
  164. package/docs/assets/github.css +0 -123
  165. package/docs/assets/site.js +0 -168
  166. package/docs/assets/split.css +0 -15
  167. package/docs/assets/split.js +0 -782
  168. package/docs/assets/style.css +0 -147
  169. package/docs/index.html +0 -34965
@@ -0,0 +1,702 @@
1
+ /**
2
+ * Transforms an array into an object using a provided transform
3
+ * function.
4
+ *
5
+ * @function transduceFrom
6
+ * @param {Array} array - The array to transform.
7
+ * @param {Function} transform - The function used to transform each
8
+ * element of the array. It should return an object with 'key' and
9
+ * 'value' properties.
10
+ * @param {Object} [into={}] - The object to transform the array into.
11
+ * @returns {Object} The transformed object.
12
+ * @example
13
+ * const array = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]
14
+ * const transform = (element) => ({ key: element.id, value: element.name })
15
+ * transduceFrom(array, transform)
16
+ * // => { 1: 'John', 2: 'Jane' }
17
+ */
18
+ export function tryIgnore(code) {
19
+ try {
20
+ return code();
21
+ }
22
+ catch (ignore) {
23
+ return undefined;
24
+ }
25
+ }
26
+ export function transduceFrom(array, transform, into = {}) {
27
+ if (typeof transform !== 'function') {
28
+ return into;
29
+ }
30
+ return array.reduce((accumulator, element) => {
31
+ const { key, value } = (transform?.(element) ?? {});
32
+ if (key && value) {
33
+ accumulator[key] = value;
34
+ }
35
+ return accumulator;
36
+ }, into);
37
+ }
38
+ /**
39
+ * Transforms a COHandler instance into an object with 'key' and 'value'
40
+ * properties.
41
+ *
42
+ * @function transduceFromCOHandler
43
+ * @param {COHandler} element - The COHandler instance to transform.
44
+ * @returns {Object} An object with 'key' and 'value' properties, where
45
+ * 'key' is the 'property' of the COHandler instance and 'value' is
46
+ * the COHandler instance itself.
47
+ * @example
48
+ * const handler = new COHandler('foo')
49
+ * transduceFromCOHandler(handler)
50
+ * // => { key: 'foo', value: handler }
51
+ */
52
+ export function transduceFromCOHandler(element) {
53
+ const result = {};
54
+ if (element instanceof COPropertyHandler) {
55
+ result.key = element.property;
56
+ result.value = element;
57
+ }
58
+ return result;
59
+ }
60
+ /**
61
+ * Creates a transducer function by partially applying the 'array' and
62
+ * 'transform' arguments to the 'transduceFrom' function.
63
+ *
64
+ * @function makeTransducer
65
+ * @param {Array} array - The array to transform.
66
+ * @param {Function} transform - The function used to transform each
67
+ * element of the array.
68
+ * @returns {Function} A transducer function that takes an 'into' object
69
+ * and returns the result of calling 'transduceFrom' with the provided
70
+ * 'array', 'transform', and 'into' arguments.
71
+ * @example
72
+ * const array = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]
73
+ * const transform = (element) => ({ key: element.id, value: element.name })
74
+ * const transducer = makeTransducer(array, transform)
75
+ * transducer({ 3: 'Jim' })
76
+ * // => { 1: 'John', 2: 'Jane', 3: 'Jim' }
77
+ */
78
+ export function makeTransducer(array, transform) {
79
+ return transduceFrom.bind(null, array, transform);
80
+ }
81
+ /**
82
+ * A class for handling property descriptors during object copying.
83
+ * @class
84
+ * @example
85
+ * const handler = new COPropertyHandler('foo', (prop, descriptor) => {
86
+ * descriptor.enumerable = false
87
+ * return descriptor
88
+ * })
89
+ * handler.handle('foo', { value: 42, writable: true, enumerable: true })
90
+ * // => { value: 42, writable: true, enumerable: false }
91
+ */
92
+ export class COPropertyHandler {
93
+ /**
94
+ * The name of the property this handler is responsible for.
95
+ * @type {string|undefined}
96
+ */
97
+ property = undefined;
98
+ /**
99
+ * The property handler. When provided and invoked, it will receive
100
+ * a the property name of the value being handled, the current
101
+ * descriptor to transform, and the object into which values are
102
+ * currently being copied into.
103
+ *
104
+ * The result must be a COPropertyHandler response type, which can
105
+ * be made with {@link COPropertyHandler.makeResponse} and which
106
+ * can be validated with {@link COPropertyHandler.isResponse}.
107
+ *
108
+ * The handler should have the following parameters
109
+ * - {string} property - The name of the property being handled.
110
+ * - {Object} curDescriptor - The property descriptor to handle.
111
+ * - {Object} destination - The destination object into which
112
+ * properties are being copied.
113
+ *
114
+ * An should return
115
+ * - {Object} a `COPropertyHandler.Response` type object which
116
+ * can be made with {@link COPropertyHandler.makeResponse}.
117
+ *
118
+ * @type {function|undefined}
119
+ */
120
+ handler = undefined;
121
+ /**
122
+ * Creates a new COPropertyHandler instance.
123
+ * @param {string} [property] - The name of the property to handle.
124
+ * @param {function} [handler] - The function to handle the property
125
+ * descriptor.
126
+ */
127
+ constructor(property, handler) {
128
+ Object.assign(this, { property, handler });
129
+ }
130
+ /**
131
+ * Handles a property descriptor using the registered handler function.
132
+ * @param {string} property - The name of the property being handled.
133
+ * @param {Object} descriptor - The property descriptor to handle.
134
+ * @returns {Object} The resulting property descriptor after handling.
135
+ */
136
+ handle(property, descriptor, destination) {
137
+ if (this.handler) {
138
+ return COPropertyHandler.defaultHandle(property, descriptor, this.handler);
139
+ }
140
+ return descriptor;
141
+ }
142
+ /**
143
+ * The default property descriptor handler.
144
+ *
145
+ * @param {string} property - The name of the property being handled.
146
+ * @param {Object} curDescriptor - The property descriptor to handle.
147
+ * @param {Object} destination - The destination object into which
148
+ * properties are being copied.
149
+ * @param {function} handler - The function to handle the property
150
+ * descriptor.
151
+ * @returns {Object} a `COPropertyHandler.Response` type object which
152
+ * can be made with {@link COPropertyHandler.makeResponse}.
153
+ */
154
+ static defaultHandle(property, curDescriptor, destination, handler) {
155
+ if (typeof handler === 'function') {
156
+ try {
157
+ const { descriptor, flow } = handler(property, curDescriptor, destination);
158
+ return this.makeResponse(descriptor, flow);
159
+ }
160
+ catch (ignore) { }
161
+ }
162
+ return this.makeResponse(curDescriptor);
163
+ }
164
+ /**
165
+ * Creates a COPropertyHandler response object.
166
+ *
167
+ * @param {Object} descriptor - The property descriptor.
168
+ * @param {string} [flow=COPropertyHandler.kNoChange] - The flow control
169
+ * directive. Must be one of the values from
170
+ * {@link COPropertyHandler.flowTypes} if provided.
171
+ * @returns {COPropertyHandler.Response} The response object.
172
+ * @example
173
+ * COPropertyHandler.makeResponse({ value: 42, writable: false })
174
+ * // => {
175
+ * // newDescriptor: { value: 42, writable: false },
176
+ * // flow: 'nochange'
177
+ * // }
178
+ */
179
+ static makeResponse(descriptor, flow) {
180
+ return {
181
+ newDescriptor: descriptor,
182
+ flow: flow ?? this.kNoChange,
183
+ get [Symbol.toStringTag]() { return 'COPropertyHandler.Response'; }
184
+ };
185
+ }
186
+ /**
187
+ * Checks if a value is a valid COPropertyHandler response object.
188
+ * @param {*} value - The value to check.
189
+ * @returns {boolean} `true` if the value is a response object, `false`
190
+ * otherwise.
191
+ * @example
192
+ * COPropertyHandler.isResponse({
193
+ * newDescriptor: { value: 42 },
194
+ * flow: 'nochange'
195
+ * })
196
+ * // => true
197
+ */
198
+ static isResponse(value) {
199
+ return (value && typeof value === 'object' &&
200
+ value[Symbol.toStringTag] === 'COPropertyHandler.Response');
201
+ }
202
+ /**
203
+ * The flow control directive indicating no change in flow.
204
+ * @type {string}
205
+ */
206
+ static get kNoChange() { return 'nochange'; }
207
+ /**
208
+ * The flow control directive indicating to continue the loop.
209
+ * @type {string}
210
+ */
211
+ static get kContinue() { return 'continue'; }
212
+ /**
213
+ * The flow control directive indicating to break the loop.
214
+ * @type {string}
215
+ */
216
+ static get kBreak() { return 'break'; }
217
+ /**
218
+ * An array of all valid flow control directive values.
219
+ * @type {string[]}
220
+ */
221
+ static get flowTypes() {
222
+ return [this.kNoChange, this.kContinue, this.kBreak];
223
+ }
224
+ /**
225
+ * An object mapping flow control directive values to their
226
+ * corresponding string representations.
227
+ * @type {Object.<string, string>}
228
+ */
229
+ static get flowEnum() {
230
+ return {
231
+ [this.kNoChange]: this.kNoChange,
232
+ [this.kContinue]: this.kContinue,
233
+ [this.kBreak]: this.kBreak,
234
+ };
235
+ }
236
+ }
237
+ /**
238
+ * Returns an object containing getter functions that return Symbol
239
+ * values representing different visibility configurations for object
240
+ * properties.
241
+ *
242
+ * @function
243
+ * @name kVisibilityKeys
244
+ * @returns {Object} An object with the following properties:
245
+ * @property {symbol} mutablyHidden - Returns a Symbol representing a
246
+ * property that is not enumerable but is configurable.
247
+ * @property {symbol} mutablyVisible - Returns a Symbol representing a
248
+ * property that is both enumerable and configurable.
249
+ * @property {symbol} immutablyHidden - Returns a Symbol representing
250
+ * a property that is neither enumerable nor configurable.
251
+ * @property {symbol} immutablyVisible - Returns a Symbol representing
252
+ * a property that is enumerable but not configurable.
253
+ * @property {symbol} flexiblyHidden - Returns a Symbol representing a
254
+ * property that is not enumerable, writable and not configurable.
255
+ * @property {symbol} flexiblyVisible - Returns a Symbol representing
256
+ * a property that is both enumerable and writable, but not
257
+ * configurable.
258
+ * @property {Generator} keys - Returns a generator that yields the
259
+ * string keys of the visibility configurations.
260
+ * @property {Generator} symbols - Returns a generator that yields the
261
+ * Symbol values of the visibility configurations.
262
+ * @property {Generator} entries - Returns a generator that yields
263
+ * [key, Symbol] pairs for each visibility configuration.
264
+ * @property {Generator} descriptors - Returns a generator that yields
265
+ * [key, descriptor] pairs for each visibility configuration, where
266
+ * descriptor is the parsed JSON representation of the Symbol's
267
+ * description.
268
+ * @property {Generator} [Symbol.iterator] - Returns the same generator
269
+ * as the symbols property, allowing the object to be iterated over
270
+ * directly to access the Symbol values.
271
+ *
272
+ * @example
273
+ * const { mutablyHidden, mutablyVisible } = kVisibilityKeys()
274
+ *
275
+ * const obj = {
276
+ * [mutablyHidden]: 'hidden value',
277
+ * [mutablyVisible]: 'visible value',
278
+ * }
279
+ *
280
+ * console.log(obj) // { [Symbol()]: 'visible value' }
281
+ * console.log(obj[mutablyHidden]) // 'hidden value'
282
+ * console.log(obj[mutablyVisible]) // 'visible value'
283
+ *
284
+ * @example
285
+ * const visibilityKeys = kVisibilityKeys()
286
+ *
287
+ * for (const key of visibilityKeys.keys()) {
288
+ * console.log(key)
289
+ * }
290
+ * // Output:
291
+ * // 'mutablyHidden'
292
+ * // 'mutablyVisible'
293
+ * // 'immutablyHidden'
294
+ * // 'immutablyVisible'
295
+ * // 'flexiblyHidden'
296
+ * // 'flexiblyVisible'
297
+ *
298
+ * @example
299
+ * const visibilityKeys = kVisibilityKeys()
300
+ *
301
+ * for (const symbol of visibilityKeys) {
302
+ * console.log(symbol)
303
+ * }
304
+ * // Output:
305
+ * // Symbol({"enumerable":false,"configurable":true})
306
+ * // Symbol({"enumerable":true,"configurable":true})
307
+ * // Symbol({"enumerable":false,"configurable":false})
308
+ * // Symbol({"enumerable":true,"configurable":false})
309
+ * // Symbol({"enumerable":false,"writable":true})
310
+ * // Symbol({"enumerable":true,"writable":true})
311
+ */
312
+ export function kVisibilityKeys() {
313
+ const keys = {
314
+ get mutablyHidden() {
315
+ return Symbol.for(JSON.stringify({
316
+ enumerable: false,
317
+ configurable: true,
318
+ }));
319
+ },
320
+ get mutablyVisible() {
321
+ return Symbol.for(JSON.stringify({
322
+ enumerable: true,
323
+ configurable: true,
324
+ }));
325
+ },
326
+ get immutablyHidden() {
327
+ return Symbol.for(JSON.stringify({
328
+ enumerable: false,
329
+ configurable: false,
330
+ }));
331
+ },
332
+ get immutablyVisible() {
333
+ return Symbol.for(JSON.stringify({
334
+ enumerable: true,
335
+ configurable: false,
336
+ }));
337
+ },
338
+ get flexiblyHidden() {
339
+ return Symbol.for(JSON.stringify({
340
+ enumerable: false,
341
+ configurable: false,
342
+ writable: true,
343
+ }));
344
+ },
345
+ get flexiblyVisible() {
346
+ return Symbol.for(JSON.stringify({
347
+ enumerable: true,
348
+ configurable: false,
349
+ writable: true,
350
+ }));
351
+ },
352
+ };
353
+ const enumerated = {
354
+ mutablyHidden: keys.mutablyHidden,
355
+ mutablyVisible: keys.mutablyVisible,
356
+ immutablyHidden: keys.immutablyHidden,
357
+ immutablyVisible: keys.immutablyVisible,
358
+ flexiblyHidden: keys.flexiblyHidden,
359
+ flexiblyVisible: keys.flexiblyVisible,
360
+ };
361
+ function* keyGenerator() {
362
+ for (const key of Object.keys(enumerated)) {
363
+ yield key;
364
+ }
365
+ }
366
+ function* symbolGenerator() {
367
+ for (const value of Object.values(enumerated)) {
368
+ yield value;
369
+ }
370
+ }
371
+ function* entryGenerator() {
372
+ for (const entry of Object.entries(enumerated)) {
373
+ yield entry;
374
+ }
375
+ }
376
+ function* descriptorGenertor() {
377
+ for (const [key, value] of entryGenerator()) {
378
+ yield [key, JSON.parse(value.description)];
379
+ }
380
+ }
381
+ Object.defineProperties(keys, {
382
+ enumeration: { get() { return enumerated; }, enumerable: false },
383
+ keys: { get() { return keyGenerator(); }, enumerable: false },
384
+ symbols: { get() { return symbolGenerator(); }, enumerable: false },
385
+ entries: { get() { return entryGenerator(); }, enumerable: false },
386
+ descriptors: { get() { return descriptorGenertor(); }, enumerable: false },
387
+ descriptorFor: {
388
+ value(symbol) {
389
+ try {
390
+ return JSON.parse(symbol.description);
391
+ }
392
+ catch (ignored) { }
393
+ return undefined;
394
+ },
395
+ enumerable: false
396
+ },
397
+ [Symbol.iterator]: { get() { return symbolGenerator(); } },
398
+ });
399
+ return keys;
400
+ }
401
+ /**
402
+ * An object containing Symbol values representing different visibility
403
+ * configurations for object properties.
404
+ *
405
+ * @constant {Object} VisibilityKeys
406
+ * @property {symbol} mutablyHidden - A Symbol representing a property
407
+ * that is not enumerable but is configurable.
408
+ * @property {symbol} mutablyVisible - A Symbol representing a property
409
+ * that is both enumerable and configurable.
410
+ * @property {symbol} immutablyHidden - A Symbol representing a property
411
+ * that is neither enumerable nor configurable.
412
+ * @property {symbol} immutablyVisible - A Symbol representing a property
413
+ * that is enumerable but not configurable.
414
+ * @property {symbol} flexiblyHidden - A Symbol representing a property
415
+ * that is not enumerable, writable and not configurable.
416
+ * @property {symbol} flexiblyVisible - A Symbol representing a property
417
+ * that is both enumerable and writable, but not configurable.
418
+ */
419
+ export const VisibilityKeys = kVisibilityKeys();
420
+ /**
421
+ * A class for handling property descriptors during object copying based
422
+ * on a specified visibility key.
423
+ *
424
+ * @class VisibilityScopeHandler
425
+ * @extends COPropertyHandler
426
+ * @param {symbol} visibilityKey - The visibility key to use for handling
427
+ * property descriptors.
428
+ * @example
429
+ * const handler = new VisibilityScopeHandler(VisibilityKeys.mutablyHidden)
430
+ * handler.handle('foo', { value: 42, writable: true, enumerable: true })
431
+ * // => { value: 42, writable: true, enumerable: false }
432
+ */
433
+ export class VisibilityScopeHandler extends COPropertyHandler {
434
+ overrides = undefined;
435
+ /**
436
+ * Creates a new VisibilityScopeHandler instance.
437
+ *
438
+ * @constructor
439
+ * @param {symbol} visibilityKey - The visibility key to use for handling
440
+ * property descriptors.
441
+ */
442
+ constructor(visibilityKey) {
443
+ super(visibilityKey, (property, descriptor, dest, source) => {
444
+ let data = descriptor?.value;
445
+ if (!descriptor || typeof descriptor.value !== 'object') {
446
+ return COPropertyHandler.makeResponse(descriptor, 'nochange');
447
+ }
448
+ if (!data && (descriptor?.get || descriptor?.set)) {
449
+ const newDescriptor = this.applyOverridesTo(descriptor);
450
+ return COPropertyHandler.makeResponse(newDescriptor, 'nochange');
451
+ }
452
+ data = customCopyObject({ deep: false }, {}, data ?? {});
453
+ this.walkAndApply(data);
454
+ descriptor.value = data;
455
+ return COPropertyHandler.makeResponse(descriptor, 'continue');
456
+ });
457
+ tryIgnore(() => this.overrides = JSON.parse(property.description));
458
+ }
459
+ applyOverridesTo(existingDescriptor, overwrite = false) {
460
+ const allowed = ['value', 'get', 'set', 'writable', 'configurable', 'enumerable'];
461
+ const output = overwrite ? existingDescriptor : { ...existingDescriptor };
462
+ for (let [key, value] of Object.entries(this.overrides ?? {})) {
463
+ if (!~allowed.indexOf(key)) {
464
+ continue;
465
+ }
466
+ if (!(['get', 'set'].some(k => k === key) &&
467
+ ['undefined', 'function'].some(t => typeof value === t))) {
468
+ continue;
469
+ }
470
+ if (!(['enumerable', 'configurable', 'writable'].some(k => k === key) &&
471
+ typeof value !== 'boolean')) {
472
+ value = !!value;
473
+ }
474
+ delete output[key];
475
+ output[key] = value;
476
+ }
477
+ return output;
478
+ }
479
+ walkAndApply(to) {
480
+ Reflect.ownKeys(to).forEach(key => {
481
+ tryIgnore(() => {
482
+ let result = Object.getOwnPropertyDescriptor(to, key);
483
+ this.applyOverridesTo(result, true);
484
+ Object.defineProperty(to, key, result);
485
+ });
486
+ });
487
+ }
488
+ }
489
+ /**
490
+ * A handler for mutably visible properties during object copying.
491
+ * @class
492
+ * @extends VisibilityScopeHandler
493
+ * @example
494
+ * const handler = new MutablyVisibleHandler()
495
+ * const sharedHandler = MutablyVisibleHandler.shared
496
+ */
497
+ export class MutablyVisibleHandler extends VisibilityScopeHandler {
498
+ constructor() { super(VisibilityKeys.mutablyVisible); }
499
+ static get shared() {
500
+ return this.#singleton ?? (this.#singleton = new this);
501
+ }
502
+ static #singleton;
503
+ }
504
+ /**
505
+ * A handler for mutably hidden properties during object copying.
506
+ * @class
507
+ * @extends VisibilityScopeHandler
508
+ * @example
509
+ * const handler = new MutablyHiddenHandler()
510
+ * const sharedHandler = MutablyHiddenHandler.shared
511
+ */
512
+ export class MutablyHiddenHandler extends VisibilityScopeHandler {
513
+ constructor() { super(VisibilityKeys.mutablyHidden); }
514
+ static get shared() {
515
+ return this.#singleton ?? (this.#singleton = new this);
516
+ }
517
+ static #singleton;
518
+ }
519
+ /**
520
+ * A handler for immutably visible properties during object copying.
521
+ * @class
522
+ * @extends VisibilityScopeHandler
523
+ * @example
524
+ * const handler = new ImmutablyVisibleHandler()
525
+ * const sharedHandler = ImmutablyVisibleHandler.shared
526
+ */
527
+ export class ImmutablyVisibleHandler extends VisibilityScopeHandler {
528
+ constructor() { super(VisibilityKeys.immutablyVisible); }
529
+ static get shared() {
530
+ return this.#singleton ?? (this.#singleton = new this);
531
+ }
532
+ static #singleton;
533
+ }
534
+ /**
535
+ * A handler for immutably hidden properties during object copying.
536
+ * @class
537
+ * @extends VisibilityScopeHandler
538
+ * @example
539
+ * const handler = new ImmutablyHiddenHandler()
540
+ * const sharedHandler = ImmutablyHiddenHandler.shared
541
+ */
542
+ export class ImmutablyHiddenHandler extends VisibilityScopeHandler {
543
+ constructor() { super(VisibilityKeys.immutablyHidden); }
544
+ static get shared() {
545
+ return this.#singleton ?? (this.#singleton = new this);
546
+ }
547
+ static #singleton;
548
+ }
549
+ /**
550
+ * A handler for flexibly visible properties during object copying.
551
+ * @class
552
+ * @extends VisibilityScopeHandler
553
+ * @example
554
+ * const handler = new FlexiblyVisibleHandler()
555
+ * const sharedHandler = FlexiblyVisibleHandler.shared
556
+ */
557
+ export class FlexiblyVisibleHandler extends VisibilityScopeHandler {
558
+ constructor() { super(VisibilityKeys.flexiblyVisible); }
559
+ static get shared() {
560
+ return this.#singleton ?? (this.#singleton = new this);
561
+ }
562
+ static #singleton;
563
+ }
564
+ /**
565
+ * A handler for flexibly hidden properties during object copying.
566
+ * @class
567
+ * @extends VisibilityScopeHandler
568
+ * @example
569
+ * const handler = new FlexiblyHiddenHandler()
570
+ * const sharedHandler = FlexiblyHiddenHandler.shared
571
+ */
572
+ export class FlexiblyHiddenHandler extends VisibilityScopeHandler {
573
+ constructor() { super(VisibilityKeys.flexiblyHidden); }
574
+ static get shared() {
575
+ return this.#singleton ?? (this.#singleton = new this);
576
+ }
577
+ static #singleton;
578
+ }
579
+ Object.defineProperties(COPropertyHandler, {
580
+ MutablyHiddenHandler: { get() { return MutablyHiddenHandler.shared; } },
581
+ MutablyVisibleHandler: { get() { return MutablyVisibleHandler.shared; } },
582
+ ImmutablyHiddenHandler: { get() { return ImmutablyHiddenHandler.shared; } },
583
+ ImmutablyVisibleHandler: { get() { return ImmutablyVisibleHandler.shared; } },
584
+ FlexiblyHiddenHandler: { get() { return FlexiblyHiddenHandler.shared; } },
585
+ FlexiblyVisibleHandler: { get() { return FlexiblyVisibleHandler.shared; } },
586
+ handlers: {
587
+ value: [
588
+ MutablyHiddenHandler, MutablyVisibleHandler, ImmutablyHiddenHandler,
589
+ ImmutablyVisibleHandler, FlexiblyHiddenHandler, FlexiblyVisibleHandler,
590
+ ].map(klass => klass.shared),
591
+ configurable: true,
592
+ enumerable: true
593
+ },
594
+ });
595
+ /**
596
+ * Creates a deep or shallow copy of the provided source objects and merges
597
+ * them into the destination object. The function uses a Set to keep track
598
+ * of visited objects to avoid circular references.
599
+ *
600
+ * @function
601
+ * @name copyObject
602
+ * @param {boolean} deep - If true, performs a deep copy, otherwise performs
603
+ * a shallow copy.
604
+ * @param {object} destination - The object to which properties will be copied.
605
+ * @param {...object} sources - The source object(s) from which properties
606
+ * will be copied.
607
+ * @returns {object} The destination object with the copied properties.
608
+ *
609
+ * @example
610
+ * // Shallow copy
611
+ * const obj1 = { a: 1, b: { c: 2 } };
612
+ * const obj2 = { b: { d: 3 }, e: 4 };
613
+ * const result = copyObject(false, obj1, obj2);
614
+ * console.log(result); // Output: { a: 1, b: { d: 3 }, e: 4 }
615
+ *
616
+ * @example
617
+ * // Deep copy
618
+ * const obj1 = { a: 1, b: { c: 2 } };
619
+ * const obj2 = { b: { d: 3 }, e: 4 };
620
+ * const result = copyObject(true, obj1, obj2);
621
+ * console.log(result); // Output: { a: 1, b: { c: 2, d: 3 }, e: 4 }
622
+ */
623
+ export function copyObject(deep, destination, ...sources) {
624
+ const options = {
625
+ deep: deep || false,
626
+ propertyHandlers: COPropertyHandler?.handlers ?? [],
627
+ };
628
+ return customCopyObject(options, destination, ...sources);
629
+ }
630
+ export function customCopyObject(_options, _destination, ..._sources) {
631
+ const visited = new Set();
632
+ const [options, destination, sources] = ccoParseArgs(_options, _destination, ..._sources);
633
+ let { deep } = options;
634
+ for (const source of sources) {
635
+ if (source === null || typeof source !== 'object' || visited.has(source)) {
636
+ continue;
637
+ }
638
+ visited.add(source);
639
+ const keys = Reflect.ownKeys(source);
640
+ for (let key of keys) {
641
+ let descriptor;
642
+ try {
643
+ descriptor = Object.getOwnPropertyDescriptor(source, key);
644
+ }
645
+ catch (err) {
646
+ console.warn(`Failed to get descriptor for key "${key}": ${err}`);
647
+ continue;
648
+ }
649
+ const isDataDesc = Reflect.has(descriptor, 'value');
650
+ const keyedValue = descriptor?.value;
651
+ const conditionsMet = [
652
+ isDataDesc,
653
+ keyedValue,
654
+ typeof keyedValue === 'object',
655
+ !visited.has(keyedValue)
656
+ ].every(condition => condition);
657
+ if (conditionsMet) {
658
+ visited.add(keyedValue);
659
+ const prototype = Object.getPrototypeOf(keyedValue);
660
+ const descriptors = Object.getOwnPropertyDescriptors(keyedValue);
661
+ const replacement = Object.create(prototype, descriptors);
662
+ descriptor.value = deep
663
+ ? customCopyObject(options, replacement, keyedValue)
664
+ : replacement;
665
+ }
666
+ try {
667
+ Object.defineProperty(destination, key, descriptor);
668
+ }
669
+ catch (err) {
670
+ console.error(`Failed to define property "${key}": ${err}`);
671
+ }
672
+ }
673
+ }
674
+ return destination;
675
+ }
676
+ function ccoParseArgs(options, destination, ...sources) {
677
+ // Parse options
678
+ let { deep = true, propertyHandlers = [] } = options;
679
+ // Ensure boolean'ness
680
+ deep = !!deep;
681
+ // Ensure propertyHandlers are converted for our ease of use
682
+ // Transform 1: Ensure array of COPropertyHandlers at the
683
+ // cost of potentially having none
684
+ propertyHandlers = (Array.isArray(propertyHandlers)
685
+ ? propertyHandlers
686
+ : [propertyHandlers]).filter(element => element instanceof COPropertyHandler);
687
+ // Transform 2: Convert array of handlers into an object keyed
688
+ // as { [handler.property]: handler }
689
+ const transducer = makeTransducer(propertyHandlers, transduceFromCOHandler);
690
+ propertyHandlers = transducer({});
691
+ // Rebuild options in the case that we recurse
692
+ options = { deep, propertyHandlers };
693
+ // Ensure sources have only objects
694
+ sources = sources.filter(source => source && typeof source === 'object');
695
+ // Ensure the destination is not null
696
+ if (!destination) {
697
+ destination = {};
698
+ }
699
+ return [options, destination, sources];
700
+ }
701
+ export default copyObject;
702
+ //# sourceMappingURL=copy.object.js.map