@nejs/basic-extensions 2.21.0 → 2.22.6

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 (270) hide show
  1. package/.idea/markdown.xml +8 -0
  2. package/.idea/modules.xml +8 -0
  3. package/.idea/ne-basic-extensions.iml +8 -0
  4. package/.idea/vcs.xml +6 -0
  5. package/CODE_STYLE.md +393 -0
  6. package/CODING_PHILOSOPHY.md +36 -0
  7. package/DOCUMENTATION_GUIDELINES.md +221 -0
  8. package/README.md +78 -4
  9. package/dist/@nejs/basic-extensions.bundle.2.22.6.js +25 -0
  10. package/dist/@nejs/basic-extensions.bundle.2.22.6.js.map +7 -0
  11. package/dist/cjs/classes/index.cjs +11129 -0
  12. package/dist/cjs/classes/index.cjs.map +7 -0
  13. package/dist/cjs/index.cjs +15191 -0
  14. package/dist/cjs/index.cjs.map +7 -0
  15. package/dist/cjs/utils/index.cjs +3954 -0
  16. package/dist/cjs/utils/index.cjs.map +7 -0
  17. package/dist/esm/basic-extensions.mjs +25 -0
  18. package/dist/esm/basic-extensions.mjs.map +7 -0
  19. package/package.json +16 -22
  20. package/repl.bootstrap.js +4 -7
  21. package/repl.history +30 -30
  22. package/src/big.int.extension.js +171 -45
  23. package/src/classes/enumeration.js +466 -0
  24. package/src/classes/index.js +5 -1
  25. package/src/index.js +5 -1
  26. package/src/math.extension.js +73 -0
  27. package/src/number.extension.js +18 -0
  28. package/src/regular.expression.extensions.js +0 -35
  29. package/src/utils/toolkit.js +699 -516
  30. package/tests/arrayextensions.test.js +3 -3
  31. package/tests/index.test.js +3 -1
  32. package/tests/newClasses/asyncIterable.test.js +3 -3
  33. package/tests/newClasses/deferred.test.js +3 -3
  34. package/tests/newClasses/descriptor.test.js +3 -3
  35. package/tests/newClasses/iterable.test.js +3 -3
  36. package/tests/newClasses/refmap.test.js +3 -3
  37. package/tests/newClasses/refset.test.js +3 -3
  38. package/tests/objectextensions.test.js +3 -3
  39. package/tests/setextensions.test.js +3 -3
  40. package/tests/stringextensions.test.js +3 -2
  41. package/tests/utils/descriptor.utils.test.js +1 -1
  42. package/tests/utils/toolkit.test.js +429 -163
  43. package/.esdoc.json +0 -9
  44. package/.vscode/settings.json +0 -5
  45. package/bin/build +0 -27
  46. package/bin/clean +0 -14
  47. package/bin/esbuild +0 -91
  48. package/bin/fixup +0 -13
  49. package/bin/repl.basics.js +0 -584
  50. package/bin/repl.signature.js +0 -63
  51. package/bin/version +0 -100
  52. package/dist/@nejs/basic-extensions.bundle.2.21.0.js +0 -25
  53. package/dist/@nejs/basic-extensions.bundle.2.21.0.js.map +0 -7
  54. package/dist/cjs/array.extensions.d.ts +0 -39
  55. package/dist/cjs/array.extensions.js +0 -477
  56. package/dist/cjs/array.extensions.js.map +0 -1
  57. package/dist/cjs/big.int.extension.d.ts +0 -31
  58. package/dist/cjs/big.int.extension.js +0 -165
  59. package/dist/cjs/big.int.extension.js.map +0 -1
  60. package/dist/cjs/classes/asyncIterable.d.ts +0 -126
  61. package/dist/cjs/classes/asyncIterable.js +0 -209
  62. package/dist/cjs/classes/asyncIterable.js.map +0 -1
  63. package/dist/cjs/classes/deferred.d.ts +0 -146
  64. package/dist/cjs/classes/deferred.js +0 -291
  65. package/dist/cjs/classes/deferred.js.map +0 -1
  66. package/dist/cjs/classes/descriptor.d.ts +0 -334
  67. package/dist/cjs/classes/descriptor.js +0 -537
  68. package/dist/cjs/classes/descriptor.js.map +0 -1
  69. package/dist/cjs/classes/enum.d.ts +0 -50
  70. package/dist/cjs/classes/enum.js +0 -405
  71. package/dist/cjs/classes/enum.js.map +0 -1
  72. package/dist/cjs/classes/index.d.ts +0 -15
  73. package/dist/cjs/classes/index.js +0 -63
  74. package/dist/cjs/classes/index.js.map +0 -1
  75. package/dist/cjs/classes/introspector.d.ts +0 -20
  76. package/dist/cjs/classes/introspector.js +0 -130
  77. package/dist/cjs/classes/introspector.js.map +0 -1
  78. package/dist/cjs/classes/iterable.d.ts +0 -169
  79. package/dist/cjs/classes/iterable.js +0 -268
  80. package/dist/cjs/classes/iterable.js.map +0 -1
  81. package/dist/cjs/classes/param.parser.d.ts +0 -221
  82. package/dist/cjs/classes/param.parser.js +0 -242
  83. package/dist/cjs/classes/param.parser.js.map +0 -1
  84. package/dist/cjs/classes/pluggable.proxy.d.ts +0 -153
  85. package/dist/cjs/classes/pluggable.proxy.js +0 -444
  86. package/dist/cjs/classes/pluggable.proxy.js.map +0 -1
  87. package/dist/cjs/classes/property.d.ts +0 -79
  88. package/dist/cjs/classes/property.js +0 -284
  89. package/dist/cjs/classes/property.js.map +0 -1
  90. package/dist/cjs/classes/refmap.d.ts +0 -238
  91. package/dist/cjs/classes/refmap.js +0 -421
  92. package/dist/cjs/classes/refmap.js.map +0 -1
  93. package/dist/cjs/classes/refset.d.ts +0 -186
  94. package/dist/cjs/classes/refset.js +0 -370
  95. package/dist/cjs/classes/refset.js.map +0 -1
  96. package/dist/cjs/classes/symkeys.d.ts +0 -349
  97. package/dist/cjs/classes/symkeys.js +0 -510
  98. package/dist/cjs/classes/symkeys.js.map +0 -1
  99. package/dist/cjs/classes/type.d.ts +0 -56
  100. package/dist/cjs/classes/type.js +0 -405
  101. package/dist/cjs/classes/type.js.map +0 -1
  102. package/dist/cjs/function.extensions.d.ts +0 -12
  103. package/dist/cjs/function.extensions.js +0 -758
  104. package/dist/cjs/function.extensions.js.map +0 -1
  105. package/dist/cjs/global.this.d.ts +0 -2
  106. package/dist/cjs/global.this.js +0 -300
  107. package/dist/cjs/global.this.js.map +0 -1
  108. package/dist/cjs/index.d.ts +0 -31
  109. package/dist/cjs/index.js +0 -226
  110. package/dist/cjs/index.js.map +0 -1
  111. package/dist/cjs/json.extensions.d.ts +0 -2
  112. package/dist/cjs/json.extensions.js +0 -109
  113. package/dist/cjs/json.extensions.js.map +0 -1
  114. package/dist/cjs/map.extensions.d.ts +0 -3
  115. package/dist/cjs/map.extensions.js +0 -143
  116. package/dist/cjs/map.extensions.js.map +0 -1
  117. package/dist/cjs/number.extension.d.ts +0 -44
  118. package/dist/cjs/number.extension.js +0 -261
  119. package/dist/cjs/number.extension.js.map +0 -1
  120. package/dist/cjs/object.extensions.d.ts +0 -33
  121. package/dist/cjs/object.extensions.js +0 -1091
  122. package/dist/cjs/object.extensions.js.map +0 -1
  123. package/dist/cjs/package.json +0 -3
  124. package/dist/cjs/proxy.extensions.d.ts +0 -2
  125. package/dist/cjs/proxy.extensions.js +0 -207
  126. package/dist/cjs/proxy.extensions.js.map +0 -1
  127. package/dist/cjs/reflect.extensions.d.ts +0 -14
  128. package/dist/cjs/reflect.extensions.js +0 -316
  129. package/dist/cjs/reflect.extensions.js.map +0 -1
  130. package/dist/cjs/regular.expression.extensions.d.ts +0 -2
  131. package/dist/cjs/regular.expression.extensions.js +0 -423
  132. package/dist/cjs/regular.expression.extensions.js.map +0 -1
  133. package/dist/cjs/set.extensions.d.ts +0 -40
  134. package/dist/cjs/set.extensions.js +0 -355
  135. package/dist/cjs/set.extensions.js.map +0 -1
  136. package/dist/cjs/string.extensions.d.ts +0 -23
  137. package/dist/cjs/string.extensions.js +0 -704
  138. package/dist/cjs/string.extensions.js.map +0 -1
  139. package/dist/cjs/symbol.extensions.d.ts +0 -11
  140. package/dist/cjs/symbol.extensions.js +0 -735
  141. package/dist/cjs/symbol.extensions.js.map +0 -1
  142. package/dist/cjs/utils/copy.object.d.ts +0 -408
  143. package/dist/cjs/utils/copy.object.js +0 -720
  144. package/dist/cjs/utils/copy.object.js.map +0 -1
  145. package/dist/cjs/utils/descriptor.utils.d.ts +0 -298
  146. package/dist/cjs/utils/descriptor.utils.js +0 -889
  147. package/dist/cjs/utils/descriptor.utils.js.map +0 -1
  148. package/dist/cjs/utils/index.d.ts +0 -75
  149. package/dist/cjs/utils/index.js +0 -61
  150. package/dist/cjs/utils/index.js.map +0 -1
  151. package/dist/cjs/utils/stdout.d.ts +0 -742
  152. package/dist/cjs/utils/stdout.js +0 -1042
  153. package/dist/cjs/utils/stdout.js.map +0 -1
  154. package/dist/cjs/utils/toolkit.d.ts +0 -1898
  155. package/dist/cjs/utils/toolkit.js +0 -1378
  156. package/dist/cjs/utils/toolkit.js.map +0 -1
  157. package/dist/cjs/weakref.extensions.d.ts +0 -2
  158. package/dist/cjs/weakref.extensions.js +0 -19
  159. package/dist/cjs/weakref.extensions.js.map +0 -1
  160. package/dist/mjs/array.extensions.d.ts +0 -39
  161. package/dist/mjs/array.extensions.js +0 -474
  162. package/dist/mjs/array.extensions.js.map +0 -1
  163. package/dist/mjs/big.int.extension.d.ts +0 -31
  164. package/dist/mjs/big.int.extension.js +0 -162
  165. package/dist/mjs/big.int.extension.js.map +0 -1
  166. package/dist/mjs/classes/asyncIterable.d.ts +0 -126
  167. package/dist/mjs/classes/asyncIterable.js +0 -204
  168. package/dist/mjs/classes/asyncIterable.js.map +0 -1
  169. package/dist/mjs/classes/deferred.d.ts +0 -146
  170. package/dist/mjs/classes/deferred.js +0 -287
  171. package/dist/mjs/classes/deferred.js.map +0 -1
  172. package/dist/mjs/classes/descriptor.d.ts +0 -334
  173. package/dist/mjs/classes/descriptor.js +0 -533
  174. package/dist/mjs/classes/descriptor.js.map +0 -1
  175. package/dist/mjs/classes/enum.d.ts +0 -50
  176. package/dist/mjs/classes/enum.js +0 -400
  177. package/dist/mjs/classes/enum.js.map +0 -1
  178. package/dist/mjs/classes/index.d.ts +0 -15
  179. package/dist/mjs/classes/index.js +0 -46
  180. package/dist/mjs/classes/index.js.map +0 -1
  181. package/dist/mjs/classes/introspector.d.ts +0 -20
  182. package/dist/mjs/classes/introspector.js +0 -126
  183. package/dist/mjs/classes/introspector.js.map +0 -1
  184. package/dist/mjs/classes/iterable.d.ts +0 -169
  185. package/dist/mjs/classes/iterable.js +0 -263
  186. package/dist/mjs/classes/iterable.js.map +0 -1
  187. package/dist/mjs/classes/param.parser.d.ts +0 -221
  188. package/dist/mjs/classes/param.parser.js +0 -238
  189. package/dist/mjs/classes/param.parser.js.map +0 -1
  190. package/dist/mjs/classes/pluggable.proxy.d.ts +0 -153
  191. package/dist/mjs/classes/pluggable.proxy.js +0 -438
  192. package/dist/mjs/classes/pluggable.proxy.js.map +0 -1
  193. package/dist/mjs/classes/property.d.ts +0 -79
  194. package/dist/mjs/classes/property.js +0 -280
  195. package/dist/mjs/classes/property.js.map +0 -1
  196. package/dist/mjs/classes/refmap.d.ts +0 -238
  197. package/dist/mjs/classes/refmap.js +0 -417
  198. package/dist/mjs/classes/refmap.js.map +0 -1
  199. package/dist/mjs/classes/refset.d.ts +0 -186
  200. package/dist/mjs/classes/refset.js +0 -366
  201. package/dist/mjs/classes/refset.js.map +0 -1
  202. package/dist/mjs/classes/symkeys.d.ts +0 -349
  203. package/dist/mjs/classes/symkeys.js +0 -506
  204. package/dist/mjs/classes/symkeys.js.map +0 -1
  205. package/dist/mjs/classes/type.d.ts +0 -56
  206. package/dist/mjs/classes/type.js +0 -401
  207. package/dist/mjs/classes/type.js.map +0 -1
  208. package/dist/mjs/function.extensions.d.ts +0 -12
  209. package/dist/mjs/function.extensions.js +0 -755
  210. package/dist/mjs/function.extensions.js.map +0 -1
  211. package/dist/mjs/global.this.d.ts +0 -2
  212. package/dist/mjs/global.this.js +0 -264
  213. package/dist/mjs/global.this.js.map +0 -1
  214. package/dist/mjs/index.d.ts +0 -31
  215. package/dist/mjs/index.js +0 -204
  216. package/dist/mjs/index.js.map +0 -1
  217. package/dist/mjs/json.extensions.d.ts +0 -2
  218. package/dist/mjs/json.extensions.js +0 -106
  219. package/dist/mjs/json.extensions.js.map +0 -1
  220. package/dist/mjs/map.extensions.d.ts +0 -3
  221. package/dist/mjs/map.extensions.js +0 -140
  222. package/dist/mjs/map.extensions.js.map +0 -1
  223. package/dist/mjs/number.extension.d.ts +0 -44
  224. package/dist/mjs/number.extension.js +0 -258
  225. package/dist/mjs/number.extension.js.map +0 -1
  226. package/dist/mjs/object.extensions.d.ts +0 -33
  227. package/dist/mjs/object.extensions.js +0 -1088
  228. package/dist/mjs/object.extensions.js.map +0 -1
  229. package/dist/mjs/package.json +0 -3
  230. package/dist/mjs/proxy.extensions.d.ts +0 -2
  231. package/dist/mjs/proxy.extensions.js +0 -204
  232. package/dist/mjs/proxy.extensions.js.map +0 -1
  233. package/dist/mjs/reflect.extensions.d.ts +0 -14
  234. package/dist/mjs/reflect.extensions.js +0 -313
  235. package/dist/mjs/reflect.extensions.js.map +0 -1
  236. package/dist/mjs/regular.expression.extensions.d.ts +0 -2
  237. package/dist/mjs/regular.expression.extensions.js +0 -420
  238. package/dist/mjs/regular.expression.extensions.js.map +0 -1
  239. package/dist/mjs/set.extensions.d.ts +0 -40
  240. package/dist/mjs/set.extensions.js +0 -352
  241. package/dist/mjs/set.extensions.js.map +0 -1
  242. package/dist/mjs/string.extensions.d.ts +0 -23
  243. package/dist/mjs/string.extensions.js +0 -701
  244. package/dist/mjs/string.extensions.js.map +0 -1
  245. package/dist/mjs/symbol.extensions.d.ts +0 -11
  246. package/dist/mjs/symbol.extensions.js +0 -732
  247. package/dist/mjs/symbol.extensions.js.map +0 -1
  248. package/dist/mjs/utils/copy.object.d.ts +0 -408
  249. package/dist/mjs/utils/copy.object.js +0 -702
  250. package/dist/mjs/utils/copy.object.js.map +0 -1
  251. package/dist/mjs/utils/descriptor.utils.d.ts +0 -298
  252. package/dist/mjs/utils/descriptor.utils.js +0 -875
  253. package/dist/mjs/utils/descriptor.utils.js.map +0 -1
  254. package/dist/mjs/utils/index.d.ts +0 -75
  255. package/dist/mjs/utils/index.js +0 -45
  256. package/dist/mjs/utils/index.js.map +0 -1
  257. package/dist/mjs/utils/stdout.d.ts +0 -742
  258. package/dist/mjs/utils/stdout.js +0 -1037
  259. package/dist/mjs/utils/stdout.js.map +0 -1
  260. package/dist/mjs/utils/toolkit.d.ts +0 -1898
  261. package/dist/mjs/utils/toolkit.js +0 -1373
  262. package/dist/mjs/utils/toolkit.js.map +0 -1
  263. package/dist/mjs/weakref.extensions.d.ts +0 -2
  264. package/dist/mjs/weakref.extensions.js +0 -16
  265. package/dist/mjs/weakref.extensions.js.map +0 -1
  266. package/jsdoc-config.json +0 -31
  267. package/tsconfig.base.json +0 -28
  268. package/tsconfig.cjs.json +0 -8
  269. package/tsconfig.esm.json +0 -8
  270. package/vitest.config.js +0 -7
@@ -1,1088 +0,0 @@
1
- import { Patch } from '@nejs/extension';
2
- import { SymbolExtensions } from './symbol.extensions.js';
3
- import { Descriptor } from './classes/descriptor.js';
4
- import { Property } from './classes/property.js';
5
- import { as, has, is, si } from './utils/toolkit.js';
6
- import { copyObject } from './utils/copy.object.js';
7
- const { keys: symkeys } = SymbolExtensions.patches;
8
- /**
9
- * `ObjectExtensions` is a constant that applies a patch to the global
10
- * `Object` constructor. This patch extends the `Object` with additional
11
- * methods and properties, enhancing its functionality.
12
- *
13
- * The `Patch` function takes two arguments: the target object to be patched
14
- * (in this case, `Object`), and an object containing the methods and
15
- * properties to be added to the target object.
16
- *
17
- * @type {Patch}
18
- * @memberof module:object.extensions
19
- */
20
- export const ObjectExtensions = new Patch(Object, {
21
- [Patch.kMutablyHidden]: {
22
- add(...args) {
23
- const { isDescriptor } = Descriptor;
24
- const { isObject: isObj } = this;
25
- const { kDescriptorStore } = this;
26
- let obj, key, value, _get, _set, storage, storageKey;
27
- let _type, _flag, _desc;
28
- // Check to see if we received multiple arguments or an object
29
- if (args.length && isObj(args[0])) {
30
- ({
31
- to: obj,
32
- key,
33
- value,
34
- get: _get,
35
- set: _set,
36
- storage,
37
- storageKey,
38
- type: _type = ['accessor', 'data'][1],
39
- flag: _flag = undefined,
40
- descriptorBase: _desc = undefined,
41
- } = args[0]);
42
- }
43
- else if (args.length > 1) {
44
- ([
45
- to,
46
- _type,
47
- key,
48
- getOrValue,
49
- _set,
50
- storage,
51
- storageKey,
52
- _flag,
53
- _desc,
54
- ] = args);
55
- obj = to;
56
- _type = (['accessor', 'data'].includes(_type.toLowerCase())
57
- ? _type.toLowerCase() : 'data');
58
- _get = _type === 'accessor' ? getOrValue : undefined;
59
- _value = _type === 'data' ? getOrValue : undefined;
60
- }
61
- if (!this.isObject(obj)) {
62
- console.warn('Object.add() must receive an object for `toObject`');
63
- return obj;
64
- }
65
- const more = isDescriptor(_desc) ? _desc : {};
66
- const flag = _flag || Object.definitionType.mutablyVisible;
67
- const props = { ...Patch.getDescriptorOverridesFromSymbol(flag), ...more };
68
- const type = (['accessor', 'data'].includes(_type)
69
- ? String(_type).toLowerCase() : 'data');
70
- switch (type) {
71
- case 'accessor':
72
- let store = storage;
73
- let storeKey = storageKey || key;
74
- let makeStore = false;
75
- let get = _get;
76
- let set = _set;
77
- if (!is.truthy(get) && !is.function(get)) {
78
- get = undefined;
79
- }
80
- if (!is.truthy(set) && !is.function(set)) {
81
- set = undefined;
82
- }
83
- if (isObj(store) || is.true(store) || is.function(store)) {
84
- makeStore = is.true(store);
85
- store = is.fn(store) ? store() : store;
86
- store = is.object(store) ? store : (makeStore && {} || undefined);
87
- }
88
- // store should be defined by here: object or undefined
89
- if ((!get && !set) && makeStore) {
90
- // being lazy here, someone has defined we make an accessor but
91
- // wants the default accessor behaviors with an associated store
92
- // made by us.
93
- Object.defineProperty(obj, kDescriptorStore, {
94
- value: symkeys.add('descriptor.store', store),
95
- configurable: true,
96
- enumerable: false,
97
- writable: true,
98
- });
99
- get = () => this[kDescriptorStore]?.data?.[storeKey];
100
- set = (value) => { this[kDescriptorStore].data[storeKey] = value; };
101
- }
102
- else if (get?.length && set?.length > 1 && store) {
103
- // if we received a get or set that takes more arguments than
104
- // expected, assume the last argument should be the store variable
105
- // so we execute the supplied function with the storage and its
106
- // results or byproducts are the result to the get/set we define
107
- const innerGet = get;
108
- const innerSet = set;
109
- get = () => innerGet(store);
110
- set = (value) => innerSet(value, store);
111
- }
112
- // get and set should be in their final state by here
113
- Object.defineProperty(obj, key, { ...props, get, set });
114
- break;
115
- case 'data':
116
- Object.defineProperty(obj, key, { ...props, value });
117
- break;
118
- }
119
- return obj;
120
- },
121
- addAccessor(to, key, getter, setter, storage) {
122
- const store = storage ?? (!getter && !setter) ? true : undefined;
123
- return this.add({ to, key, get: getter, set: setter, storage: store });
124
- },
125
- addData(to, key, value) {
126
- return this.add({ to, key, value });
127
- },
128
- /**
129
- * Creates a shallow copy of the provided object(s).
130
- *
131
- * This method uses the `copyObject` function with the `deep` parameter
132
- * set to `false`, indicating a shallow copy. It takes a destination
133
- * object and any number of source objects, and copies the properties
134
- * from the source objects to the destination object. If a property
135
- * already exists on the destination object, it will be overwritten.
136
- *
137
- * Note: This method does not copy nested objects or arrays. They are
138
- * copied by reference, not by value. To create a deep copy, use the
139
- * `deepCopy` method instead.
140
- *
141
- * @param {object} destination - The object to which properties will be
142
- * copied.
143
- * @param {...object} sources - The source object(s) from which
144
- * properties will be copied.
145
- * @returns {object} The destination object with the copied properties.
146
- *
147
- * @example
148
- * const obj1 = { a: 1, b: 2 };
149
- * const obj2 = { b: 3, c: 4 };
150
- * const result = ObjectExtensions.copy(obj1, obj2);
151
- * console.log(result); // Output: { a: 1, b: 3, c: 4 }
152
- */
153
- copy(destination, ...sources) {
154
- return copyObject(false, destination, ...sources);
155
- },
156
- /**
157
- * Creates a deep copy of the provided object(s).
158
- *
159
- * This method uses the `copyObject` function with the `deep` parameter
160
- * set to `true`, indicating a deep copy. It takes a destination
161
- * object and any number of source objects, and copies the properties
162
- * from the source objects to the destination object. If a property
163
- * already exists on the destination object, it will be overwritten.
164
- *
165
- * Note: This method copies nested objects or arrays by value, not by
166
- * reference. To create a shallow copy, use the `copy` method instead.
167
- *
168
- * @param {object} destination - The object to which properties will be
169
- * copied.
170
- * @param {...object} sources - The source object(s) from which
171
- * properties will be copied.
172
- * @returns {object} The destination object with the copied properties.
173
- *
174
- * @example
175
- * const obj1 = { a: 1, b: { c: 2 } };
176
- * const obj2 = { b: { d: 3 }, e: 4 };
177
- * const result = ObjectExtensions.deepCopy(obj1, obj2);
178
- * console.log(result); // Output: { a: 1, b: { d: 3 }, e: 4 }
179
- */
180
- deepCopy(destination, ...sources) {
181
- return copyObject(true, destination, ...sources);
182
- },
183
- /**
184
- * Defines a new property on an object with a specified value and
185
- * visibility/mutability flag. The flag determines the visibility and
186
- * mutability of the property. By default, the property is defined as
187
- * mutably hidden.
188
- *
189
- * @param {object} object - The object on which to define the property.
190
- * @param {string} key - The name of the property to be defined.
191
- * @param {any} value - The value of the property to be defined.
192
- * @param {symbol} [flag=Object.definitionType.mutablyHidden] - The
193
- * visibility/mutability flag for the property. This should be one of the
194
- * symbols available in `ObjectExtensions.definitionType`.
195
- * @returns {object} The object with the newly defined property.
196
- *
197
- * @example
198
- * // Define a new mutably hidden property on an object
199
- * const myObject = {};
200
- * const myValue = 'Hello, world!';
201
- * const hiddenSymbol = Object.definitionType.mutablyHidden;
202
- * Object.define(myObject, 'myProperty', myValue, hiddenSymbol);
203
- * // myObject now has a mutably hidden property 'myProperty' with value
204
- * // 'Hello, world!'
205
- */
206
- define(object, key, value, flag = Object.definitionType.mutablyHidden) {
207
- const properties = Patch.getDescriptorOverridesFromSymbol(flag);
208
- return Object.defineProperty(object, key, { ...properties, value });
209
- },
210
- /**
211
- * A getter property that provides access to the definition types used
212
- * for object property definitions. These types are used to control the
213
- * visibility and mutability of object properties.
214
- *
215
- * @returns {Object} An object with getter properties for each definition
216
- * type. The properties are:
217
- * - `mutablyHidden`: A symbol representing a mutably hidden property,
218
- * non-enumerable, but configurable.
219
- * - `mutablyVisible`: A symbol representing a mutably visible property,
220
- * enumerable, configurable
221
- * - `immutablyHidden`: A symbol representing an immutably hidden property,
222
- * non-enumerable, non-configurable.
223
- * - `immutablyVisible`: A symbol representing an immutably visible
224
- * property, enumerable, non-configurable.
225
- *
226
- * @example
227
- * // Get the symbol for a mutably hidden property
228
- * const hiddenSymbol = Object.definitionType.mutablyHidden;
229
- *
230
- * // Define a new mutably hidden property on an object
231
- * Object.define(myObject, 'myProperty', myValue, hiddenSymbol);
232
- */
233
- get definitionType() {
234
- return {
235
- get mutablyHidden() { return Patch.kMutablyHidden; },
236
- get mutablyVisible() { return Patch.kMutablyVisible; },
237
- get immutablyHidden() { return Patch.kImmutablyHidden; },
238
- get immutablyVisible() { return Patch.kImmutablyVisible; },
239
- };
240
- },
241
- /**
242
- * Defines a new accessor property on an object with specified getter and
243
- * setter functions and a visibility/mutability flag. The flag determines
244
- * the visibility and mutability of the property. By default, the property
245
- * is defined as mutably hidden.
246
- *
247
- * @param {object} object - The object on which to define the property.
248
- * @param {string} key - The name of the property to be defined.
249
- * @param {function} get - The getter function for the property.
250
- * @param {function} set - The setter function for the property.
251
- * @param {symbol} [flag=Object.definitionType.mutablyHidden] - The
252
- * visibility/mutability flag for the property. This should be one of the
253
- * symbols available in `ObjectExtensions.definitionType`.
254
- * @returns {object} The object with the newly defined property.
255
- *
256
- * @example
257
- * // Define a new mutably hidden accessor property on an object
258
- * const myObject = {};
259
- * const hiddenSymbol = ObjectExtensions.definitionType.mutablyHidden;
260
- * ObjectExtensions.defineAccessor(
261
- * myObject,
262
- * 'myProperty',
263
- * () => 'Hello, world!',
264
- * (value) => console.log(`Setting value: ${value}`),
265
- * hiddenSymbol
266
- * );
267
- * // myObject now has a mutably hidden property 'myProperty' with getter
268
- * // and setter functions
269
- */
270
- defineAccessor(object, key, get, set, flag = Object.definitionType.mutablyHidden) {
271
- const properties = Patch.getDescriptorOverridesFromSymbol(flag);
272
- return Object.defineProperty(object, key, { ...properties, get, set });
273
- },
274
- /**
275
- * Creates a new object from an array of key-value pairs (entries), with an
276
- * optional prototype and reducer function. If no prototype is provided,
277
- * the default Object.prototype is used. If no reducer is provided, a
278
- * default reducer is used that assigns each value to its corresponding key.
279
- *
280
- * @param {Array} entries - An array of key-value pairs. Each entry should
281
- * be an array where the first element is the key and the second element is
282
- * the value. Non-conforming entries are ignored.
283
- * @param {object} [prototype=Object.prototype] - The prototype to use for
284
- * the new object. If not provided, Object.prototype is used.
285
- * @param {Function} [reducer] - An optional reducer function to use when
286
- * creating the new object. If not provided, a default reducer is used that
287
- * assigns each value to its corresponding key.
288
- * @returns {object|undefined} - The new object created from the entries, or
289
- * undefined if the entries array is not valid or contains no valid entries.
290
- *
291
- * @example
292
- * // Create an object with a custom prototype and reducer
293
- * const myPrototype = { foo: 'bar' };
294
- * const myReducer = (obj, [key, value]) => {
295
- * obj[key] = value.toUpperCase();
296
- * return obj;
297
- * };
298
- *
299
- * const myEntries = [['name', 'John'], ['age', '30']];
300
- * const myObject = Object.fromEntriesUsing(
301
- * myEntries, myPrototype, myReducer
302
- * );
303
- *
304
- * // myObject is now { name: 'JOHN', age: '30' }
305
- * // with prototype { foo: 'bar' }
306
- */
307
- fromEntriesUsing(entries, prototype = Object.prototype, reducer = undefined) {
308
- if (!is.array(entries)) {
309
- return undefined;
310
- }
311
- const entriesToUse = entries.filter(entry => is.array(entry) && entry.length >= 2);
312
- if (!entriesToUse.length) {
313
- return undefined;
314
- }
315
- const useReducer = reducer instanceof Function
316
- ? reducer
317
- : (accumulator, [key, value]) => {
318
- accumulator[key] = value;
319
- return accumulator;
320
- };
321
- return entriesToUse.reduce(useReducer, Object.create(prototype ?? Object.prototype));
322
- },
323
- /**
324
- * Retrieves the prototype chain entries of a given object.
325
- *
326
- * This method traverses the prototype chain of the provided object and
327
- * collects an array of entries. Each entry is a pair consisting of the
328
- * prototype object and its property descriptors.
329
- *
330
- * The property descriptors are obtained using the `Reflect.ownKeys`
331
- * method and the `Object.getOwnPropertyDescriptor` function.
332
- *
333
- * @param {Object} object - The object whose prototype chain entries are
334
- * to be retrieved.
335
- * @returns {Array} An array of entries, where each entry is a pair
336
- * consisting of a prototype object and its property descriptors.
337
- *
338
- * @example
339
- * const obj = Object.create({ foo: 'bar' });
340
- * console.log(getPrototypeChainEntries(obj));
341
- * // Output: [[{ foo: 'bar' }, { foo: { value: 'bar', writable: true,
342
- * // enumerable: true, configurable: true } }], [Object.prototype, { ... }]]
343
- */
344
- getPrototypeChainEntries(object) {
345
- const entries = [];
346
- let prototype = Object.getPrototypeOf(object);
347
- while (prototype) {
348
- const descriptors = Reflect.ownKeys(prototype).reduce((acc, key) => {
349
- acc[key] = Object.getOwnPropertyDescriptor(prototype, key);
350
- return acc;
351
- }, {});
352
- entries.push([prototype, descriptors]);
353
- prototype = Object.getPrototypeOf(prototype);
354
- }
355
- return entries;
356
- },
357
- /**
358
- * Retrieves the string tag of an object. The string tag is a representation
359
- * of the object's type, as defined by its `Object.prototype.toString`
360
- * method. This utility method is helpful for getting a more descriptive
361
- * type of an object than what is returned by the `typeof` operator,
362
- * especially for custom objects.
363
- *
364
- * @param {*} value - The object whose string tag is to be retrieved.
365
- * @param {boolean} strict - if this is set to true, undefined will be
366
- * returned whenever a supplied object does not have a
367
- * `Symbol.toStringTag` defined, period. if false, the default,
368
- * @returns {string} - The string tag of the object, indicating its type.
369
- */
370
- getStringTag(value, strict = false) {
371
- if (has.stringTag(value)) {
372
- return value[Symbol.toStringTag];
373
- }
374
- if (strict) {
375
- return undefined;
376
- }
377
- if (value && (typeof value === 'function')) {
378
- return value.name;
379
- }
380
- return /\s(.+)]/.exec(Object.prototype.toString.call(value))[1];
381
- },
382
- /**
383
- * Determines the type of the given value based on its string tag. This method
384
- * uses `Object.getStringTag` to obtain the string tag of the value, which
385
- * represents its more specific type (e.g., Array, Map, Set) rather than just
386
- * 'object'. The method then maps this string tag to the corresponding type
387
- * present in the provided `owner` object, which defaults to `globalThis`.
388
- * This utility method is especially useful for identifying the specific
389
- * constructor or class of an object, beyond the basic types identified by
390
- * the `typeof` operator.
391
- *
392
- * @param {any} value - The value whose type is to be determined.
393
- * @param {object} [owner=globalThis] - The object in which to look up the
394
- * constructor corresponding to the string tag. Defaults to `globalThis`,
395
- * which covers global constructors like `Array`, `Object`, etc.
396
- * @returns {Function|object|null|undefined} - Returns the constructor or
397
- * type of the value based on its string tag. For 'Null' and 'Undefined',
398
- * it returns `null` and `undefined`, respectively. For other types, it
399
- * returns the corresponding constructor (e.g., `Array` for arrays) if
400
- * available in the `owner` object.
401
- */
402
- getType(value, owner = globalThis) {
403
- const stringTag = Object.getStringTag(value);
404
- switch (stringTag) {
405
- case 'Null': return null;
406
- case 'Undefined': return undefined;
407
- default:
408
- return owner[stringTag];
409
- }
410
- },
411
- /**
412
- * Checks to see if the supplied `value` is both an object, and has the
413
- * appropriate symbol defined.
414
- *
415
- * @param {any} value the value to determine if it contains a defined
416
- * `Symbol.toStringTag` defined.
417
- * @returns true if the symbol is defined, false otherwise
418
- */
419
- hasStringTag(value) {
420
- return has.stringTag(value);
421
- },
422
- /**
423
- * The function checks if a value is either `undefined` or `null`.
424
- *
425
- * @param {any} value - The parameter "value" is a variable that can hold
426
- * any value.
427
- * @returns {boolean} `true` if the value is either `undefined` or `null`,
428
- * and `false` otherwise.
429
- */
430
- isNullDefined(value) {
431
- return is.nullish(value);
432
- },
433
- /**
434
- * The `ifNullDefined` function checks if a given value is either `null` or
435
- * `undefined` and returns one of two provided values based on the result.
436
- * This function is a convenience method for performing conditional
437
- * operations based on the type of a value.
438
- *
439
- * @param {any} value - The value to be checked. If this is either `null`
440
- * or `undefined`, `thenValue` is returned, otherwise `elseValue`
441
- * is returned.
442
- * @param {function | any} thenValue - The value to be returned if `value`
443
- * is either `null` or `undefined`.
444
- * @param {function | any} elseValue - The value to be returned if `value`
445
- * is not either `null` or `undefined`.
446
- * @returns {*} Returns `thenValue` if `value` is either `null` or
447
- * `undefined`, otherwise returns `elseValue`.
448
- *
449
- * @example
450
- * // Suppose we have a null value and a defined value
451
- * let nullValue = null;
452
- * let definedValue = "I'm defined";
453
- *
454
- * // Using ifNullDefined
455
- * // Output: 'Null or Undefined'
456
- * console.log(
457
- * Object.ifNullDefined(nullValue, 'Null or Undefined', 'Defined')
458
- * );
459
- *
460
- * // Output: 'Defined'
461
- * console.log(
462
- * Object.ifNullDefined(definedValue, 'Null or Undefined', 'Defined')
463
- * );
464
- */
465
- ifNullDefined(value, thenValue, elseValue) {
466
- return isThenElse(is.nullish(value), thenValue, elseValue);
467
- },
468
- /**
469
- * Checks if the provided value is an object.
470
- *
471
- * This function checks if the provided value is an instance of an Object
472
- * or if the value is truthy and its type is 'object'. This is used to
473
- * determine if a value can have properties and methods like an object.
474
- *
475
- * @param {any} value - The value to be checked.
476
- * @returns {boolean} Returns `true` if the value is an object, `false`
477
- * otherwise.
478
- *
479
- * @example
480
- * // Using a string
481
- * console.log(isObject('Hello, world!')); // Output: false
482
- *
483
- * // Using an object
484
- * console.log(isObject({ key: 'value' })); // Output: true
485
- *
486
- * // Using null
487
- * console.log(isObject(null)); // Output: false
488
- */
489
- isObject(value) {
490
- return is.object(value);
491
- },
492
- /**
493
- * Executes a conditional function based on whether the provided value
494
- * is an object or not. This method first checks if the value is an
495
- * object using the `is.object` method from the toolkit. If it is, it
496
- * returns the `thenValue`, otherwise it returns the `elseValue`.
497
- *
498
- * @param {any} value - The value to be checked.
499
- * @param {function | any} thenValue - The value to return if `value`
500
- * is an object.
501
- * @param {function | any} elseValue - The value to return if `value`
502
- * is not an object.
503
- * @returns {*} - Returns `thenValue` if the value is an object,
504
- * otherwise `elseValue`.
505
- *
506
- * @example
507
- * // returns 'Is Object'
508
- * ifObject({}, 'Is Object', 'Not Object')
509
- * // returns 'Not Object'
510
- * ifObject(42, 'Is Object', 'Not Object')
511
- */
512
- ifObject(value, thenValue, elseValue) {
513
- return isThenElse(is.object(value), thenValue, elseValue);
514
- },
515
- /**
516
- * Checks to see if the supplied value is a primitive value.
517
- *
518
- * @param {any} value the value to test to see if it is a primitive value type
519
- * @returns true if the object is considered widely to be a primitive value,
520
- * false otherwise.
521
- */
522
- isPrimitive(value) {
523
- return is.primitive(value);
524
- },
525
- /**
526
- * Executes a conditional function based on whether the provided value is
527
- * primitive or not. This method first checks if the value is primitive
528
- * using the `isPrimitive` method. If it is, it returns the `thenValue`,
529
- * otherwise it returns the `elseValue`.
530
- *
531
- * @param {any} value - The value to be checked.
532
- * @param {function | any} thenValue - The value to return if `value` is
533
- * primitive.
534
- * @param {function | any} elseValue - The value to return if `value` is
535
- * not primitive.
536
- * @returns {*} - Returns `thenValue` if the value is primitive, otherwise
537
- * `elseValue`.
538
- *
539
- * @example
540
- * // returns 1
541
- * ifPrimitive('hello', 1, 2)
542
- * // returns 2
543
- * ifPrimitive({a: 'hello'}, 1, 2)
544
- */
545
- ifPrimitive(value, thenValue, elseValue) {
546
- return isThenElse(is.primitive(value), thenValue, elseValue);
547
- },
548
- /**
549
- * Checks if the given value is a valid key for an object. In JavaScript, a
550
- * valid key can be either a string or a symbol. This method is useful for
551
- * validating object keys before using them in operations like setting or
552
- * getting object properties.
553
- *
554
- * @param {*} value - The value to be checked.
555
- * @returns {boolean} - Returns `true` if the value is a valid object key
556
- * (string or symbol), otherwise `false`.
557
- */
558
- isValidKey(value) {
559
- return (typeof value === 'string' || typeof value === 'symbol');
560
- },
561
- /**
562
- * Executes a conditional function based on whether the provided
563
- * value is a valid key for an object. This method first checks if
564
- * the value is a valid key using the `isValidKey` method. If it is,
565
- * it returns the `thenValue`, otherwise it returns the `elseValue`.
566
- *
567
- * @param {any} value - The value to be checked.
568
- * @param {function | any} thenValue - The value to return if
569
- * `value` is a valid key.
570
- * @param {function | any} elseValue - The value to return if
571
- * `value` is not a valid key.
572
- * @returns {any} - Returns `thenValue` if the value is a valid key,
573
- * otherwise `elseValue`.
574
- *
575
- * @example
576
- * // returns 1
577
- * ifValidKey('name', 1, 2)
578
- * // returns 2
579
- * ifValidKey(123, 1, 2)
580
- */
581
- ifValidKey(value, thenValue, elseValue) {
582
- return isThenElse(this.isValidKey(value), thenValue, elseValue);
583
- },
584
- /**
585
- * A symbol constant defined on Object that can be used to reference
586
- * storage for an accessor descriptor created with Object.add() or
587
- * other descriptor assigning and creation methods used by this extension.
588
- *
589
- * The value assigned here is actually another symbol but one generated
590
- * by {@link Symkeys} for uniqueness and has access to data storage.
591
- *
592
- * @returns {Symbol} - Returns a symbol for the descriptor storage.
593
- *
594
- * @example
595
- * // returns Symbol(@nejs.object.descriptor.storage)
596
- * kDescriptorStore
597
- *
598
- * // add descriptor value to an object
599
- * const object = {}
600
- * Object.add({object, key: 'name', type: 'accessor'})
601
- * object.name = 'Jane Doe'
602
- *
603
- * // Value assigned here is another symbol with its own storage generated
604
- * // by Symkeys. Description might be '@nejs.descriptor.store #234sdafj'
605
- * object[Object.kDescriptorStore]
606
- *
607
- * // But its nested data can be accessed using the '.data' getter
608
- * object[Object.kDescriptorStore].data // { name: 'Jane Doe' }
609
- */
610
- get kDescriptorStore() {
611
- return Symbol.for('@nejs.object.descriptor.storage');
612
- },
613
- /**
614
- * Creates an object with predefined keys and descriptors. This method is
615
- * useful for creating objects with specific properties and behaviors.
616
- *
617
- * @param {Array|Object} keys - An array of keys or an object where keys
618
- * are the object's own properties. If an array is provided, each key will
619
- * be assigned the `defaultValue`. If an object is provided, its own
620
- * properties will be used as keys and their corresponding values as values.
621
- * @param {*} [defaultValue=undefined] - The default value for each key.
622
- * @param {string} [definedAs='data'] - Defines how the properties are
623
- * defined. If 'data', properties are defined with a value. If 'accessor',
624
- * properties are defined with get and set accessors.
625
- * @param {Object} [accessorMeta={ get: undefined, set: undefined,
626
- * thisArg: undefined }] - An object containing the get and set accessors
627
- * and the `thisArg` to bind to the accessors.
628
- * @param {Object} [descriptorBase={ enumerable: true, configurable: true }]
629
- * - The base descriptor for the properties.
630
- * @param {Object} [extraDescriptors=undefined] - Extra descriptors to be
631
- * added to the object.
632
- * @param {Object} [prototype=Object.prototype] - The prototype of the
633
- * created object.
634
- * @returns {Object} - Returns the created object.
635
- *
636
- * @example
637
- * // returns { name: undefined }
638
- * prekeyed(['name'])
639
- * // returns { name: 'John' }
640
- * prekeyed({ name: 'John' })
641
- * // returns { name: 'John' }
642
- * prekeyed(['name'], 'John')
643
- */
644
- prekeyed(keys, defaultValue = undefined, definedAs = ['data', 'accessor'][0], accessorMeta = { get: undefined, set: undefined, thisArg: undefined }, descriptorBase = { enumerable: true, configurable: true }, extraDescriptors = undefined, prototype = Object.prototype) {
645
- const object = Object.create(prototype, extraDescriptors);
646
- let mapped = {};
647
- if (Array.isArray(keys)) {
648
- mapped = keys.reduce((a, k) => ({ ...a, [k]: defaultValue }), {});
649
- }
650
- else if (keys && typeof keys === 'object') {
651
- Object.assign(mapped, keys);
652
- }
653
- else {
654
- console.warn('skipping');
655
- return object;
656
- }
657
- for (const [key, value] of Object.entries(mapped)) {
658
- let symKey = Symbol.for(`${key}#${Math.random().toString(36).slice(2)}`);
659
- let suppliedValue = mapped[key] ?? defaultValue;
660
- if (definedAs === 'accessor' && accessorMeta.get === undefined) {
661
- Object.defineProperty(object, symKey, {
662
- value: suppliedValue, enumerable: false, configurable: true
663
- });
664
- accessorMeta.thisArg = object;
665
- }
666
- let descriptorRest = definedAs === 'data'
667
- ? { value: value ?? defaultValue, writable: true }
668
- : {
669
- get: accessorMeta.get ?? function () { return this[symKey]; },
670
- set: accessorMeta.set ?? function (v) { this[symKey] = v; }
671
- };
672
- if (accessorMeta.thisArg) {
673
- descriptorRest.get = descriptorRest.get.bind(accessorMeta.thisArg);
674
- descriptorRest.set = descriptorRest.set.bind(accessorMeta.thisArg);
675
- }
676
- Object.defineProperty(object, key, { ...descriptorBase, ...descriptorRest });
677
- }
678
- return object;
679
- },
680
- /**
681
- * Strips an object down to only the keys specified. Optionally, any
682
- * accessors can be made to retain their context on the source object.
683
- *
684
- * @param {object} object the object to pare down
685
- * @param {Array<string|symbol>} keys the keys that should appear in the
686
- * final reduced object
687
- * @param {boolean} [bindAccessors = true] if this value is true then any
688
- * accessors from the source object will continue to have their `this`
689
- * value bound to the source. If the getter or setter on that object is
690
- * defined using an arrow function, this will not work as intended.
691
- * @returns {object} an object containing only the keys and symbols
692
- * specified in the `keys` parameter.
693
- */
694
- stripTo(object, keys, bindAccessors = true) {
695
- if (!object || typeof object !== 'object') {
696
- throw new TypeError('Object.stripTo requires an object to strip. Received', object);
697
- }
698
- const result = {};
699
- if (!Array.isArray(keys)) {
700
- return result;
701
- }
702
- for (let key of keys) {
703
- if (Reflect.has(object, key)) {
704
- const originalDescriptor = Object.getOwnPropertyDescriptor(object, key);
705
- const descriptor = { ...originalDescriptor };
706
- if (typeof descriptor.get === 'function' ||
707
- typeof descriptor.set === 'function') {
708
- if (bindAccessors) {
709
- descriptor.get = descriptor.get?.bind(object);
710
- descriptor.set = descriptor.set?.bind(object);
711
- }
712
- }
713
- Object.defineProperty(result, key, descriptor);
714
- }
715
- }
716
- return result;
717
- },
718
- withProperties(prototype, ...properties) {
719
- const props = properties.filter(p => p instanceof Property);
720
- const possible = properties.filter(p => Array.isArray(p));
721
- if (possible.length) {
722
- for (const [key, descriptorOrDataOrAccessorArgs, ...rest] of possible) {
723
- // if arg[1] is a descriptor
724
- if (Property.is.descriptor(descriptorOrDataOrAccessorArgs)) {
725
- props.push(new Property(key, descriptorOrDataOrAccessorArgs));
726
- }
727
- else {
728
- const { get, set } = descriptorOrDataOrAccessorArgs;
729
- const args = [key, descriptorOrDataOrAccessorArgs, ...rest];
730
- if (get || set) {
731
- props.push(Property.accessor(...args));
732
- }
733
- else {
734
- props.push(Property.data(...args));
735
- }
736
- }
737
- }
738
- }
739
- const object = Object.create(prototype ?? Object.prototype);
740
- const sorted = props.toSorted((a, b) => a.key < b.key ? -1 : (a.key > b.key ? 1 : 0));
741
- for (const property of sorted) {
742
- property.apply(object);
743
- }
744
- Property.data(Symbol.for('properties'), sorted).apply(object);
745
- return object;
746
- },
747
- /**
748
- * Retrieves a toolkit object containing various utility functions
749
- * for type checking and introspection.
750
- *
751
- * The toolkit includes many functions. It was designed to read as
752
- * though the toolkit were assigned to the variable `it`.
753
- *
754
- * @example
755
- * const is = ObjectExtensions.patches.toolkit
756
- * console.log(is.object({})) // Output: true
757
- * console.log(is.string('hello')) // Output: true
758
- * console.log(is.number(42)) // Output: true
759
- *
760
- * @returns {object} The toolkit object containing various utility
761
- * functions for type checking and introspection.
762
- */
763
- get toolkit() {
764
- return { as, has, is, si };
765
- },
766
- },
767
- });
768
- const { isObject: pIsObject, ifObject: pIfObject, isNullDefined: pIsNullDefined, ifNullDefined: pIfNullDefined, isPrimitive: pIsPrimitive, ifPrimitive: pIfPrimitive, isValidKey: pIsValidKey, ifValidKey: pIfValidKey, hasStringTag: pHasStringTag, getStringTag: pGetStringTag, stripTo: pStripTo, } = ObjectExtensions.patches;
769
- /**
770
- * `ObjectPrototypeExtensions` is a constant that applies a patch to the
771
- * Object prototype. This patch extends the Object prototype with additional
772
- * methods and properties, enhancing its functionality.
773
- *
774
- * The `Patch` function takes two arguments: the target object to be patched
775
- * (in this case, `Object.prototype`), and an object containing the methods
776
- * and properties to be added to the target object.
777
- *
778
- * @example
779
- * // Using a method added by ObjectPrototypeExtensions
780
- * const obj = {};
781
- * console.log(obj.isObject()); // Output: true
782
- *
783
- * @const
784
- * @type {Patch}
785
- * @memberof module:object.extensions
786
- */
787
- export const ObjectPrototypeExtensions = new Patch(Object.prototype, {
788
- [Patch.kMutablyHidden]: {
789
- /**
790
- * Retrieves the prototype chain entries of the current object.
791
- *
792
- * This method traverses the prototype chain of the current object
793
- * (`this`) and collects an array of entries. Each entry is a pair
794
- * consisting of the prototype object and its property descriptors.
795
- *
796
- * The property descriptors are obtained using the `Reflect.ownKeys`
797
- * method and the `Object.getOwnPropertyDescriptor` function.
798
- *
799
- * @returns {Array} An array of entries, where each entry is a pair
800
- * consisting of a prototype object and its property descriptors.
801
- *
802
- * @example
803
- * const obj = Object.create({ foo: 'bar' });
804
- * console.log(obj.getPrototypeChainEntries());
805
- * // Output: [[{ foo: 'bar' }, { foo: { value: 'bar', writable: true, enumerable: true, configurable: true } }], [Object.prototype, { ... }]]
806
- */
807
- getPrototypeChainEntries() {
808
- return ObjectExtensions.patches.getPrototypeChainEntries(this);
809
- },
810
- /**
811
- * Determines if the current value is an object.
812
- *
813
- * This method checks whether the current value is an object,
814
- * excluding null. It is a convenience wrapper around the
815
- * `pIsObject` function from the `ObjectExtensions` patch.
816
- *
817
- * @name isObject
818
- * @type {function}
819
- * @memberof Object.prototype
820
- * @returns {boolean} `true` if the current value is an object
821
- * (excluding null), `false` otherwise.
822
- *
823
- * @example
824
- * const obj = {};
825
- * console.log(obj.isObject());
826
- * // Output: true
827
- *
828
- * const str = "hello";
829
- * console.log(str.isObject());
830
- * // Output: false
831
- *
832
- * console.log(null.isObject());
833
- * // Output: false
834
- */
835
- get isObject() {
836
- return pIsObject(this);
837
- },
838
- /**
839
- * Checks if the current value is an object and returns one of two
840
- * provided values based on the result. This function is a convenience
841
- * method for performing conditional operations based on the type of
842
- * the current value.
843
- *
844
- * @name ifObject
845
- * @type {function}
846
- * @memberof Object.prototype
847
- * @param {function | any} thenValue - The value to be returned if the
848
- * current value is an object (excluding null).
849
- * @param {function | any} elseValue - The value to be returned if the
850
- * current value is not an object or is null.
851
- * @returns {*} Returns `thenValue` if the current value is an object
852
- * (excluding null), otherwise returns `elseValue`.
853
- *
854
- * @example
855
- * const obj = {};
856
- * console.log(obj.ifObject('Object', 'Not an object'));
857
- * // Output: 'Object'
858
- *
859
- * const str = "hello";
860
- * console.log(str.ifObject('Object', 'Not an object'));
861
- * // Output: 'Not an object'
862
- *
863
- * console.log(null.ifObject('Object', 'Not an object'));
864
- * // Output: 'Not an object'
865
- */
866
- ifObject(thenValue, elseValue) {
867
- return pIfObject(this, thenValue, elseValue);
868
- },
869
- /**
870
- * Checks if the current value is either `null` or `undefined`.
871
- *
872
- * @name isNullDefined
873
- * @type {boolean}
874
- * @memberof Object.prototype
875
- * @returns {boolean} Returns `true` if the current value is either
876
- * `null` or `undefined`, `false` otherwise.
877
- *
878
- * @example
879
- * const obj = null;
880
- * console.log(obj.isNullDefined);
881
- * // Output: true
882
- *
883
- * const str = "hello";
884
- * console.log(str.isNullDefined);
885
- * // Output: false
886
- */
887
- get isNullDefined() {
888
- return pIsNullDefined(this);
889
- },
890
- /**
891
- * Checks if the current value is either `null` or `undefined` and
892
- * returns one of two provided values based on the result.
893
- *
894
- * @name ifNullDefined
895
- * @type {function}
896
- * @memberof Object.prototype
897
- * @param {function | any} thenValue - The value to be returned if the
898
- * current value is either `null` or `undefined`.
899
- * @param {function | any} elseValue - The value to be returned if the
900
- * current value is not `null` or `undefined`.
901
- * @returns {*} Returns `thenValue` if the current value is either
902
- * `null` or `undefined`, otherwise returns `elseValue`.
903
- *
904
- * @example
905
- * const obj = null
906
- * console.log(obj.ifNullDefined('Null or Undefined', 'Defined'))
907
- * // Output: 'Null or Undefined'
908
- *
909
- * const str = "hello"
910
- * console.log(str.ifNullDefined('Null or Undefined', 'Defined'))
911
- * // Output: 'Defined'
912
- */
913
- ifNullDefined(thenValue, elseValue) {
914
- return pIfNullDefined(this, thenValue, elseValue);
915
- },
916
- /**
917
- * Checks if the current value is a primitive type.
918
- *
919
- * Primitive types in JavaScript include `string`, `number`,
920
- * `bigint`, `boolean`, `undefined`, `symbol`, and `null`.
921
- *
922
- * @name isPrimitive
923
- * @type {boolean}
924
- * @memberof Object.prototype
925
- * @returns {boolean} Returns `true` if the current value is a
926
- * primitive type, `false` otherwise.
927
- *
928
- * @example
929
- * const str = "hello"
930
- * console.log(str.isPrimitive)
931
- * // Output: true
932
- *
933
- * const obj = { key: "value" }
934
- * console.log(obj.isPrimitive)
935
- * // Output: false
936
- */
937
- get isPrimitive() {
938
- return pIsPrimitive(this);
939
- },
940
- /**
941
- * Checks if the current value is a primitive type and returns one
942
- * of two provided values based on the result.
943
- *
944
- * Primitive types in JavaScript include `string`, `number`,
945
- * `bigint`, `boolean`, `undefined`, `symbol`, and `null`.
946
- *
947
- * @name ifPrimitive
948
- * @type {function}
949
- * @memberof Object.prototype
950
- * @param {function | any} thenValue - The value to be returned if
951
- * the current value is a primitive type.
952
- * @param {function | any} elseValue - The value to be returned if
953
- * the current value is not a primitive type.
954
- * @returns {*} Returns `thenValue` if the current value is a
955
- * primitive type, otherwise returns `elseValue`.
956
- *
957
- * @example
958
- * const str = "hello"
959
- * console.log(str.ifPrimitive('Primitive', 'Not Primitive'))
960
- * // Output: 'Primitive'
961
- *
962
- * const obj = { key: "value" }
963
- * console.log(obj.ifPrimitive('Primitive', 'Not Primitive'))
964
- * // Output: 'Not Primitive'
965
- */
966
- ifPrimitive(thenValue, elseValue) {
967
- return pIfPrimitive(this, thenValue, elseValue);
968
- },
969
- /**
970
- * Determines if the current value is a valid key for an object.
971
- *
972
- * A valid key is either a string or a symbol. This method is a
973
- * convenience wrapper around the `pIsValidKey` function from the
974
- * `ObjectExtensions` patch.
975
- *
976
- * @name isValidKey
977
- * @type {boolean}
978
- * @memberof Object.prototype
979
- * @returns {boolean} `true` if the current value is a valid key for
980
- * an object (i.e., a string or symbol), `false` otherwise.
981
- *
982
- * @example
983
- * const str = "key"
984
- * console.log(str.isValidKey)
985
- * // Output: true
986
- *
987
- * const sym = Symbol("key")
988
- * console.log(sym.isValidKey)
989
- * // Output: true
990
- *
991
- * const num = 42
992
- * console.log(num.isValidKey)
993
- * // Output: false
994
- */
995
- get isValidKey() {
996
- return pIsValidKey(this);
997
- },
998
- /**
999
- * Checks if the current value is a valid key for an object and returns
1000
- * one of two provided values based on the result. This function is a
1001
- * convenience method for performing conditional operations based on
1002
- * the type of the current value.
1003
- *
1004
- * A valid key is either a string or a symbol.
1005
- *
1006
- * @name ifValidKey
1007
- * @type {function}
1008
- * @memberof Object.prototype
1009
- * @param {function | any} thenValue - The value to be returned if the
1010
- * current value is a valid key for an object.
1011
- * @param {function | any} elseValue - The value to be returned if the
1012
- * current value is not a valid key for an object.
1013
- * @returns {*} Returns `thenValue` if the current value is a valid key
1014
- * for an object, otherwise returns `elseValue`.
1015
- *
1016
- * @example
1017
- * const str = "key"
1018
- * console.log(str.ifValidKey('Valid Key', 'Not a Valid Key'))
1019
- * // Output: 'Valid Key'
1020
- *
1021
- * const num = 42
1022
- * console.log(num.ifValidKey('Valid Key', 'Not a Valid Key'))
1023
- * // Output: 'Not a Valid Key'
1024
- */
1025
- ifValidKey(thenValue, elseValue) {
1026
- return pIfValidKey(this, thenValue, elseValue);
1027
- },
1028
- /**
1029
- * Checks to see if the supplied `value` is both an object, and has the
1030
- * appropriate symbol defined.
1031
- *
1032
- * @param {any} value the value to determine if it contains a defined
1033
- * `Symbol.toStringTag` defined.
1034
- * @returns true if the symbol is defined, false otherwise
1035
- */
1036
- get hasStringTag() {
1037
- return pHasStringTag(this);
1038
- },
1039
- /**
1040
- * Retrieves the string tag of an object. The string tag is a representation
1041
- * of the object's type, as defined by its `Object.prototype.toString`
1042
- * method. This utility method is helpful for getting a more descriptive
1043
- * type of an object than what is returned by the `typeof` operator,
1044
- * especially for custom objects.
1045
- *
1046
- * @param {*} value - The object whose string tag is to be retrieved.
1047
- * @param {boolean} strict - if this is set to true, undefined will be
1048
- * returned whenever a supplied object does not have a
1049
- * `Symbol.toStringTag` defined, period. if false, the default,
1050
- * @returns {string} - The string tag of the object, indicating its type.
1051
- */
1052
- getStringTag(strict = false) {
1053
- return pGetStringTag(this, strict);
1054
- },
1055
- /**
1056
- * Strips an object down to only the keys specified. Optionally, any
1057
- * accessors can be made to retain their context on the source object.
1058
- * This is a passthrough to the static {@link Object.stripTo} function
1059
- *
1060
- * @param {Array<string|symbol>} keys the keys that should appear in the
1061
- * final reduced object
1062
- * @param {boolean} [bindAccessors = true] if this value is true then any
1063
- * accessors from the source object will continue to have their `this`
1064
- * value bound to the source. If the getter or setter on that object is
1065
- * defined using an arrow function, this will not work as intended.
1066
- * @returns {object} an object containing only the keys and symbols
1067
- * specified in the `keys` parameter.
1068
- */
1069
- stripTo(keys, bindAccessors = true) {
1070
- return pStripTo(this, keys, bindAccessors);
1071
- },
1072
- },
1073
- });
1074
- // NOTE to self; this is repeated here otherwise a circular reference from
1075
- // Object<->Function<->Global occurs. See original source in global.this.js
1076
- // {@see globalThis.isThenElse}
1077
- function isThenElse(bv, tv, ev) {
1078
- if (arguments.length > 1) {
1079
- var _then = is.function(tv) ? tv(bv) : tv;
1080
- if (arguments.length > 2) {
1081
- var _else = is.function(ev) ? tv(bv) : ev;
1082
- return bv ? _then : _else;
1083
- }
1084
- return bv || _then;
1085
- }
1086
- return bv;
1087
- }
1088
- //# sourceMappingURL=object.extensions.js.map