@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
@@ -2,17 +2,12 @@ import { Patch } from '@nejs/extension'
2
2
 
3
3
  import { SymbolExtensions } from './symbol.extensions.js';
4
4
  import { Descriptor } from './classes/descriptor.js';
5
+ import { Property } from './classes/property.js';
5
6
 
6
- const { keys: symkeys } = SymbolExtensions.patches
7
+ import { as, has, is, si } from './utils/toolkit.js';
8
+ import { copyObject } from './utils/copy.object.js';
7
9
 
8
- // Avoid circular dependencies; rewrite here for brevity
9
- const isFn = o => typeof o === 'function' || o instanceof Function
10
- const isStr = o => typeof o === 'string' || o instanceof String
11
- const isBool = o => typeof o === 'boolean'
12
- const isTrue = o => isBool(o) && o === true
13
- const isTruthy = o => isTrue(!!o)
14
- const isFalse = o => isBool(o) && o === false
15
- const isFalsy = o => isFalse(!!o)
10
+ const { keys: symkeys } = SymbolExtensions.patches
16
11
 
17
12
  /**
18
13
  * `ObjectExtensions` is a constant that applies a patch to the global
@@ -28,6 +23,128 @@ const isFalsy = o => isFalse(!!o)
28
23
  */
29
24
  export const ObjectExtensions = new Patch(Object, {
30
25
  [Patch.kMutablyHidden]: {
26
+ add(...args) {
27
+ const { isDescriptor } = Descriptor
28
+ const { isObject: isObj } = this
29
+ const { kDescriptorStore } = this
30
+
31
+ let obj, key, value, _get, _set, storage, storageKey
32
+ let _type, _flag, _desc
33
+
34
+ // Check to see if we received multiple arguments or an object
35
+ if (args.length && isObj(args[0])) {
36
+ ({
37
+ to: obj,
38
+ key,
39
+ value,
40
+ get: _get,
41
+ set: _set,
42
+ storage,
43
+ storageKey,
44
+ type: _type = ['accessor', 'data'][1],
45
+ flag: _flag = undefined,
46
+ descriptorBase: _desc = undefined,
47
+ } = args[0])
48
+ }
49
+ else if (args.length > 1) {
50
+ ([
51
+ to,
52
+ _type,
53
+ key,
54
+ getOrValue,
55
+ _set,
56
+ storage,
57
+ storageKey,
58
+ _flag,
59
+ _desc,
60
+ ] = args)
61
+
62
+ obj = to
63
+ _type = (
64
+ ['accessor', 'data'].includes(_type.toLowerCase())
65
+ ? _type.toLowerCase() : 'data'
66
+ )
67
+ _get = _type === 'accessor' ? getOrValue : undefined
68
+ _value = _type === 'data' ? getOrValue : undefined
69
+ }
70
+
71
+ if (!this.isObject(obj)) {
72
+ console.warn('Object.add() must receive an object for `toObject`')
73
+ return obj;
74
+ }
75
+
76
+ const more = isDescriptor(_desc) ? _desc : {}
77
+ const flag = _flag || Object.definitionType.mutablyVisible
78
+ const props = { ...Patch.getDescriptorOverridesFromSymbol(flag), ...more }
79
+ const type = (['accessor', 'data'].includes(_type)
80
+ ? String(_type).toLowerCase() : 'data'
81
+ )
82
+
83
+ switch (type) {
84
+ case 'accessor':
85
+ let store = storage;
86
+ let storeKey = storageKey || key
87
+ let makeStore = false
88
+ let get = _get;
89
+ let set = _set;
90
+
91
+ if (!is.truthy(get) && !is.function(get)) { get = undefined }
92
+ if (!is.truthy(set) && !is.function(set)) { set = undefined }
93
+
94
+ if (isObj(store) ||is.true(store) || is.function(store)) {
95
+ makeStore =is.true(store)
96
+ store = is.fn(store) ? store() : store
97
+ store = is.object(store) ? store : (makeStore && {} || undefined)
98
+ }
99
+ // store should be defined by here: object or undefined
100
+
101
+ if ((!get && !set) && makeStore) {
102
+ // being lazy here, someone has defined we make an accessor but
103
+ // wants the default accessor behaviors with an associated store
104
+ // made by us.
105
+ Object.defineProperty(obj, kDescriptorStore, {
106
+ value: symkeys.add('descriptor.store', store),
107
+ configurable: true,
108
+ enumerable: false,
109
+ writable: true,
110
+ })
111
+
112
+ get = () => this[kDescriptorStore]?.data?.[storeKey]
113
+ set = (value) => { this[kDescriptorStore].data[storeKey] = value }
114
+ }
115
+
116
+ else if (get?.length && set?.length > 1 && store) {
117
+ // if we received a get or set that takes more arguments than
118
+ // expected, assume the last argument should be the store variable
119
+ // so we execute the supplied function with the storage and its
120
+ // results or byproducts are the result to the get/set we define
121
+ const innerGet = get
122
+ const innerSet = set
123
+ get = () => innerGet(store)
124
+ set = (value) => innerSet(value, store)
125
+ }
126
+ // get and set should be in their final state by here
127
+
128
+ Object.defineProperty(obj, key, { ...props, get, set })
129
+ break
130
+
131
+ case 'data':
132
+ Object.defineProperty(obj, key, { ...props, value })
133
+ break
134
+ }
135
+
136
+ return obj
137
+ },
138
+
139
+ addAccessor(to, key, getter, setter, storage) {
140
+ const store = storage ?? (!getter && !setter) ? true : undefined;
141
+ return this.add({ to, key, get: getter, set: setter, storage: store })
142
+ },
143
+
144
+ addData(to, key, value) {
145
+ return this.add({ to, key, value })
146
+ },
147
+
31
148
  /**
32
149
  * Creates a shallow copy of the provided object(s).
33
150
  *
@@ -85,6 +202,34 @@ export const ObjectExtensions = new Patch(Object, {
85
202
  return copyObject(true, destination, ...sources)
86
203
  },
87
204
 
205
+ /**
206
+ * Defines a new property on an object with a specified value and
207
+ * visibility/mutability flag. The flag determines the visibility and
208
+ * mutability of the property. By default, the property is defined as
209
+ * mutably hidden.
210
+ *
211
+ * @param {object} object - The object on which to define the property.
212
+ * @param {string} key - The name of the property to be defined.
213
+ * @param {any} value - The value of the property to be defined.
214
+ * @param {symbol} [flag=Object.definitionType.mutablyHidden] - The
215
+ * visibility/mutability flag for the property. This should be one of the
216
+ * symbols available in `ObjectExtensions.definitionType`.
217
+ * @returns {object} The object with the newly defined property.
218
+ *
219
+ * @example
220
+ * // Define a new mutably hidden property on an object
221
+ * const myObject = {};
222
+ * const myValue = 'Hello, world!';
223
+ * const hiddenSymbol = Object.definitionType.mutablyHidden;
224
+ * Object.define(myObject, 'myProperty', myValue, hiddenSymbol);
225
+ * // myObject now has a mutably hidden property 'myProperty' with value
226
+ * // 'Hello, world!'
227
+ */
228
+ define(object, key, value, flag = Object.definitionType.mutablyHidden) {
229
+ const properties = Patch.getDescriptorOverridesFromSymbol(flag)
230
+ return Object.defineProperty(object, key, { ...properties, value })
231
+ },
232
+
88
233
  /**
89
234
  * A getter property that provides access to the definition types used
90
235
  * for object property definitions. These types are used to control the
@@ -117,34 +262,6 @@ export const ObjectExtensions = new Patch(Object, {
117
262
  }
118
263
  },
119
264
 
120
- /**
121
- * Defines a new property on an object with a specified value and
122
- * visibility/mutability flag. The flag determines the visibility and
123
- * mutability of the property. By default, the property is defined as
124
- * mutably hidden.
125
- *
126
- * @param {object} object - The object on which to define the property.
127
- * @param {string} key - The name of the property to be defined.
128
- * @param {any} value - The value of the property to be defined.
129
- * @param {symbol} [flag=Object.definitionType.mutablyHidden] - The
130
- * visibility/mutability flag for the property. This should be one of the
131
- * symbols available in `ObjectExtensions.definitionType`.
132
- * @returns {object} The object with the newly defined property.
133
- *
134
- * @example
135
- * // Define a new mutably hidden property on an object
136
- * const myObject = {};
137
- * const myValue = 'Hello, world!';
138
- * const hiddenSymbol = Object.definitionType.mutablyHidden;
139
- * Object.define(myObject, 'myProperty', myValue, hiddenSymbol);
140
- * // myObject now has a mutably hidden property 'myProperty' with value
141
- * // 'Hello, world!'
142
- */
143
- define(object, key, value, flag = Object.definitionType.mutablyHidden) {
144
- const properties = Patch.getDescriptorOverridesFromSymbol(flag)
145
- return Object.defineProperty(object, key, { ...properties, value })
146
- },
147
-
148
265
  /**
149
266
  * Defines a new accessor property on an object with specified getter and
150
267
  * setter functions and a visibility/mutability flag. The flag determines
@@ -181,113 +298,6 @@ export const ObjectExtensions = new Patch(Object, {
181
298
  return Object.defineProperty(object, key, { ...properties, get, set })
182
299
  },
183
300
 
184
- add(...args) {
185
- const { isDescriptor } = Descriptor
186
- const { isObject: isObj } = this
187
- const { kDescriptorStore } = this
188
-
189
- let toObject, key, value, _get, _set, storage, storageKey
190
- let _type, _flag, _desc
191
-
192
- // Check to see if we received multiple arguments or an object
193
- if (args.length && isObj(args[0])) {
194
- ({
195
- toObject: obj,
196
- key,
197
- value,
198
- get: _get,
199
- set: _set,
200
- storage,
201
- storageKey,
202
- type: _type = ['accessor', 'data'][1],
203
- flag: _flag = undefined,
204
- descriptorBase: _desc = undefined,
205
- } = args[0])
206
- }
207
- else if (args.length > 1) {
208
- ([
209
- toObject,
210
- _type,
211
- key,
212
- getOrValue,
213
- _set,
214
- storage,
215
- storageKey,
216
- _flag,
217
- _desc,
218
- ] = args)
219
-
220
- _type = (
221
- ['accessor', 'data'].includes(_type.toLowerCase())
222
- ? _type.toLowerCase() : 'data'
223
- )
224
- _get = _type === 'accessor' ? getOrValue : undefined
225
- _value = _type === 'data' ? getOrValue : undefined
226
- }
227
-
228
- const more = isDescriptor(_desc) ? _desc : {}
229
- const flag = _flag || Object.definitionType.mutablyVisible
230
- const props = { ...Patch.getDescriptorOverridesFromSymbol(flag), ...more }
231
- const type = (['accessor', 'data'].includes(_type)
232
- ? String(_type).toLowerCase() : 'data'
233
- )
234
-
235
- switch (type) {
236
- case 'accessor':
237
- let store = storage;
238
- let storeKey = storageKey || key
239
- let makeStore = false
240
- let get = _get;
241
- let set = _set;
242
-
243
- if (!isTruthy(get) && !isFn(get)) { get = undefined }
244
- if (!isTruthy(set) && !isFn(set)) { set = undefined }
245
-
246
- if (isObj(store) || isTrue(store) || isFn(store)) {
247
- makeStore = isTrue(store)
248
- store = isFn(store) ? store() : store
249
- store = isObj(store) ? store : (makeStore && {} || undefined)
250
- }
251
- // store should be defined by here: object or undefined
252
-
253
- if (!get && !set && makeStore) {
254
- // being lazy here, someone has defined we make an accessor but
255
- // wants the default accessor behaviors with an associated store
256
- // made by us.
257
- Object.defineProperty(obj, kDescriptorStore, {
258
- value: symkeys.add('descriptor.store', store),
259
- configurable: true,
260
- enumerable: false,
261
- writable: true,
262
- })
263
-
264
- get = () => this[kDescriptorStore].data[storeKey]
265
- set = (value) => { this[kDescriptorStore].data[storeKey] = value }
266
- }
267
-
268
- else if (get.length && set.length > 1 && store) {
269
- // if we received a get or set that takes more arguments than
270
- // expected, assume the last argument should be the store variable
271
- // so we execute the supplied function with the storage and its
272
- // results or byproducts are the result to the get/set we define
273
- const innerGet = get
274
- const innerSet = set
275
- get = () => innerGet(store)
276
- set = (value) => innerSet(value, store)
277
- }
278
- // get and set should be in their final state by here
279
-
280
- Object.defineProperty(obj, key, { ...props, get, set })
281
- break
282
-
283
- case 'data':
284
- Object.defineProperty(obj, key, { ...props, value })
285
- break
286
- }
287
-
288
- return obj
289
- },
290
-
291
301
  /**
292
302
  * Creates a new object from an array of key-value pairs (entries), with an
293
303
  * optional prototype and reducer function. If no prototype is provided,
@@ -322,12 +332,12 @@ export const ObjectExtensions = new Patch(Object, {
322
332
  * // with prototype { foo: 'bar' }
323
333
  */
324
334
  fromEntriesUsing(entries, prototype = Object.prototype, reducer = undefined) {
325
- if (!Array.isArray(entries)) {
335
+ if (!is.array(entries)) {
326
336
  return undefined;
327
337
  }
328
338
 
329
339
  const entriesToUse = entries.filter(
330
- entry => Array.isArray(entry) && entry.length >= 2
340
+ entry => is.array(entry) && entry.length >= 2
331
341
  );
332
342
 
333
343
  if (!entriesToUse.length) {
@@ -399,7 +409,7 @@ export const ObjectExtensions = new Patch(Object, {
399
409
  * @returns {string} - The string tag of the object, indicating its type.
400
410
  */
401
411
  getStringTag(value, strict = false) {
402
- if (Object.hasStringTag(value)) {
412
+ if (has.stringTag(value)) {
403
413
  return value[Symbol.toStringTag]
404
414
  }
405
415
 
@@ -454,7 +464,7 @@ export const ObjectExtensions = new Patch(Object, {
454
464
  * @returns true if the symbol is defined, false otherwise
455
465
  */
456
466
  hasStringTag(value) {
457
- return Object.isObject(value) && Reflect.has(value, Symbol.toStringTag)
467
+ return has.stringTag(value)
458
468
  },
459
469
 
460
470
  /**
@@ -466,7 +476,7 @@ export const ObjectExtensions = new Patch(Object, {
466
476
  * and `false` otherwise.
467
477
  */
468
478
  isNullDefined(value) {
469
- return value === undefined || value === null
479
+ return is.nullish(value)
470
480
  },
471
481
 
472
482
  /**
@@ -502,7 +512,7 @@ export const ObjectExtensions = new Patch(Object, {
502
512
  * );
503
513
  */
504
514
  ifNullDefined(value, thenValue, elseValue) {
505
- return isThenElse(this.isNullDefined(value), thenValue, elseValue);
515
+ return isThenElse(is.nullish(value), thenValue, elseValue);
506
516
  },
507
517
 
508
518
  /**
@@ -527,21 +537,31 @@ export const ObjectExtensions = new Patch(Object, {
527
537
  * console.log(isObject(null)); // Output: false
528
538
  */
529
539
  isObject(value) {
530
- return value instanceof Object || value && typeof value === 'object'
540
+ return is.object(value)
531
541
  },
532
542
 
533
543
  /**
534
- * Determines if the provided value is an object. This method checks whether
535
- * the value is an instance of `Object` or if its type is 'object'. It's a
536
- * utility method for type-checking, ensuring that a value is an object
537
- * before performing operations that are specific to objects.
544
+ * Executes a conditional function based on whether the provided value
545
+ * is an object or not. This method first checks if the value is an
546
+ * object using the `is.object` method from the toolkit. If it is, it
547
+ * returns the `thenValue`, otherwise it returns the `elseValue`.
538
548
  *
539
- * @param {*} value - The value to be checked.
540
- * @returns {boolean} - Returns `true` if the value is an object,
541
- * otherwise `false`.
542
- },
543
- isObject(value) {
544
- return value && (value instanceof Object || typeof value === 'object');
549
+ * @param {any} value - The value to be checked.
550
+ * @param {function | any} thenValue - The value to return if `value`
551
+ * is an object.
552
+ * @param {function | any} elseValue - The value to return if `value`
553
+ * is not an object.
554
+ * @returns {*} - Returns `thenValue` if the value is an object,
555
+ * otherwise `elseValue`.
556
+ *
557
+ * @example
558
+ * // returns 'Is Object'
559
+ * ifObject({}, 'Is Object', 'Not Object')
560
+ * // returns 'Not Object'
561
+ * ifObject(42, 'Is Object', 'Not Object')
562
+ */
563
+ ifObject(value, thenValue, elseValue) {
564
+ return isThenElse(is.object(value), thenValue, elseValue)
545
565
  },
546
566
 
547
567
  /**
@@ -552,24 +572,7 @@ export const ObjectExtensions = new Patch(Object, {
552
572
  * false otherwise.
553
573
  */
554
574
  isPrimitive(value) {
555
- // Check for null as a special case because typeof null
556
- // is 'object'
557
- if (value === null) {
558
- return true;
559
- }
560
-
561
- // Check for other primitives
562
- switch (typeof value) {
563
- case 'string':
564
- case 'number':
565
- case 'bigint':
566
- case 'boolean':
567
- case 'undefined':
568
- case 'symbol':
569
- return true;
570
- default:
571
- return false;
572
- }
575
+ return is.primitive(value)
573
576
  },
574
577
 
575
578
  /**
@@ -593,7 +596,7 @@ export const ObjectExtensions = new Patch(Object, {
593
596
  * ifPrimitive({a: 'hello'}, 1, 2)
594
597
  */
595
598
  ifPrimitive(value, thenValue, elseValue) {
596
- return isThenElse(this.isPrimitive(value), thenValue, elseValue)
599
+ return isThenElse(is.primitive(value), thenValue, elseValue)
597
600
  },
598
601
 
599
602
  /**
@@ -799,6 +802,61 @@ export const ObjectExtensions = new Patch(Object, {
799
802
 
800
803
  return result;
801
804
  },
805
+
806
+ withProperties(prototype, ...properties) {
807
+ const props = properties.filter(p => p instanceof Property);
808
+ const possible = properties.filter(p => Array.isArray(p))
809
+
810
+ if (possible.length) {
811
+ for (const [key, descriptorOrDataOrAccessorArgs, ...rest] of possible) {
812
+ // if arg[1] is a descriptor
813
+ if (Property.is.descriptor(descriptorOrDataOrAccessorArgs)) {
814
+ props.push(new Property(key, descriptorOrDataOrAccessorArgs))
815
+ }
816
+ else {
817
+ const { get, set } = descriptorOrDataOrAccessorArgs;
818
+ const args = [key, descriptorOrDataOrAccessorArgs, ...rest];
819
+ if (get || set) {
820
+ props.push(Property.accessor(...args))
821
+ }
822
+ else {
823
+ props.push(Property.data(...args))
824
+ }
825
+ }
826
+ }
827
+ }
828
+
829
+ const object = Object.create(prototype ?? Object.prototype);
830
+ const sorted = props.toSorted(
831
+ (a,b) => a.key < b.key ? -1 : (a.key > b.key ? 1 : 0)
832
+ );
833
+ for (const property of sorted) {
834
+ property.apply(object);
835
+ }
836
+
837
+ Property.data(Symbol.for('properties'), sorted).apply(object);
838
+ return object;
839
+ },
840
+
841
+ /**
842
+ * Retrieves a toolkit object containing various utility functions
843
+ * for type checking and introspection.
844
+ *
845
+ * The toolkit includes many functions. It was designed to read as
846
+ * though the toolkit were assigned to the variable `it`.
847
+ *
848
+ * @example
849
+ * const is = ObjectExtensions.patches.toolkit
850
+ * console.log(is.object({})) // Output: true
851
+ * console.log(is.string('hello')) // Output: true
852
+ * console.log(is.number(42)) // Output: true
853
+ *
854
+ * @returns {object} The toolkit object containing various utility
855
+ * functions for type checking and introspection.
856
+ */
857
+ get toolkit() {
858
+ return { as, has, is, si }
859
+ },
802
860
  },
803
861
  });
804
862
 
@@ -1134,89 +1192,9 @@ export const ObjectPrototypeExtensions = new Patch(Object.prototype, {
1134
1192
  // {@see globalThis.isThenElse}
1135
1193
  function isThenElse(bv, tv, ev) {
1136
1194
  if (arguments.length > 1) {
1137
- var _then = isFunction(tv) ? tv(bv) : tv; if (arguments.length > 2) {
1138
- var _else = isFunction(ev) ? tv(bv) : ev; return bv ? _then : _else
1195
+ var _then = is.function(tv) ? tv(bv) : tv; if (arguments.length > 2) {
1196
+ var _else = is.function(ev) ? tv(bv) : ev; return bv ? _then : _else
1139
1197
  } return bv || _then;
1140
1198
  } return bv
1141
1199
  }
1142
1200
 
1143
- /**
1144
- * Creates a deep or shallow copy of the provided source objects and merges
1145
- * them into the destination object. The function uses a Set to keep track
1146
- * of visited objects to avoid circular references.
1147
- *
1148
- * @function
1149
- * @name copyObject
1150
- * @param {boolean} deep - If true, performs a deep copy, otherwise performs
1151
- * a shallow copy.
1152
- * @param {object} destination - The object to which properties will be copied.
1153
- * @param {...object} sources - The source object(s) from which properties
1154
- * will be copied.
1155
- * @returns {object} The destination object with the copied properties.
1156
- *
1157
- * @example
1158
- * // Shallow copy
1159
- * const obj1 = { a: 1, b: { c: 2 } };
1160
- * const obj2 = { b: { d: 3 }, e: 4 };
1161
- * const result = copyObject(false, obj1, obj2);
1162
- * console.log(result); // Output: { a: 1, b: { d: 3 }, e: 4 }
1163
- *
1164
- * @example
1165
- * // Deep copy
1166
- * const obj1 = { a: 1, b: { c: 2 } };
1167
- * const obj2 = { b: { d: 3 }, e: 4 };
1168
- * const result = copyObject(true, obj1, obj2);
1169
- * console.log(result); // Output: { a: 1, b: { c: 2, d: 3 }, e: 4 }
1170
- */
1171
- export function copyObject(deep, destination, ...sources) {
1172
- const visited = new Set()
1173
-
1174
- for (const source of sources) {
1175
- if (source === null || typeof source !== 'object' || visited.has(source)) {
1176
- continue
1177
- }
1178
-
1179
- visited.add(source)
1180
-
1181
- const keys = Reflect.ownKeys(source)
1182
- for (const key of keys) {
1183
- let descriptor
1184
- try {
1185
- descriptor = Object.getOwnPropertyDescriptor(source, key)
1186
- } catch (err) {
1187
- console.warn(`Failed to get descriptor for key "${key}": ${err}`)
1188
- continue
1189
- }
1190
-
1191
- const isDataDesc = Reflect.has(descriptor, 'value')
1192
- const keyedValue = descriptor?.value
1193
-
1194
- const conditionsMet = [
1195
- isDataDesc,
1196
- keyedValue,
1197
- typeof keyedValue === 'object',
1198
- !visited.has(keyedValue)
1199
- ].every(condition => condition)
1200
-
1201
- if (conditionsMet) {
1202
- visited.add(keyedValue)
1203
-
1204
- const prototype = Object.getPrototypeOf(keyedValue)
1205
- const descriptors = Object.getOwnPropertyDescriptors(keyedValue)
1206
- const replacement = Object.create(prototype, descriptors)
1207
-
1208
- descriptor.value = deep
1209
- ? copyObject(deep, replacement, keyedValue)
1210
- : replacement
1211
- }
1212
-
1213
- try {
1214
- Object.defineProperty(destination, key, descriptor)
1215
- } catch (err) {
1216
- console.error(`Failed to define property "${key}": ${err}`)
1217
- }
1218
- }
1219
- }
1220
-
1221
- return destination
1222
- }
@@ -385,9 +385,11 @@ export const SetPrototypeExtensions = new Patch(Set.prototype, {
385
385
  // Object<->Function<->Global occurs. See original source in global.this.js
386
386
  // {@see globalThis.isThenElse}
387
387
  function isThenElse(bv, tv, ev) {
388
+ function isFunction(value) { typeof value === 'function' }
389
+
388
390
  if (arguments.length > 1) {
389
391
  var _then = isFunction(tv) ? tv(bv) : tv; if (arguments.length > 2) {
390
392
  var _else = isFunction(ev) ? tv(bv) : ev; return bv ? _then : _else
391
393
  } return bv || _then;
392
394
  } return bv
393
- }
395
+ }