@nejs/basic-extensions 2.6.0 → 2.8.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 (271) hide show
  1. package/.vscode/settings.json +5 -0
  2. package/README.md +6129 -1574
  3. package/dist/@nejs/basic-extensions.bundle.2.7.0.js +19 -0
  4. package/dist/@nejs/basic-extensions.bundle.2.7.0.js.map +7 -0
  5. package/dist/cjs/array.extensions.d.ts +39 -0
  6. package/dist/cjs/array.extensions.js +303 -0
  7. package/dist/cjs/array.extensions.js.map +1 -0
  8. package/dist/cjs/big.int.extension.d.ts +31 -0
  9. package/dist/cjs/big.int.extension.js +164 -0
  10. package/dist/cjs/big.int.extension.js.map +1 -0
  11. package/dist/cjs/{newClasses → classes}/asyncIterable.js +32 -44
  12. package/dist/cjs/classes/asyncIterable.js.map +1 -0
  13. package/dist/cjs/{newClasses → classes}/deferred.js +66 -138
  14. package/dist/cjs/classes/deferred.js.map +1 -0
  15. package/dist/cjs/{newClasses → classes}/descriptor.js +56 -90
  16. package/dist/cjs/classes/descriptor.js.map +1 -0
  17. package/dist/cjs/classes/index.d.ts +13 -0
  18. package/dist/cjs/classes/index.js +57 -0
  19. package/dist/cjs/classes/index.js.map +1 -0
  20. package/dist/cjs/classes/introspector.d.ts +20 -0
  21. package/dist/cjs/classes/introspector.js +130 -0
  22. package/dist/cjs/classes/introspector.js.map +1 -0
  23. package/dist/cjs/{newClasses → classes}/iterable.js +42 -63
  24. package/dist/cjs/classes/iterable.js.map +1 -0
  25. package/dist/cjs/classes/param.parser.d.ts +227 -0
  26. package/dist/cjs/classes/param.parser.js +242 -0
  27. package/dist/cjs/classes/param.parser.js.map +1 -0
  28. package/dist/cjs/classes/pluggable.proxy.d.ts +152 -0
  29. package/dist/cjs/classes/pluggable.proxy.js +444 -0
  30. package/dist/cjs/classes/pluggable.proxy.js.map +1 -0
  31. package/dist/cjs/{newClasses → classes}/refmap.js +18 -30
  32. package/dist/cjs/classes/refmap.js.map +1 -0
  33. package/dist/cjs/{newClasses → classes}/refset.js +28 -47
  34. package/dist/cjs/classes/refset.js.map +1 -0
  35. package/dist/cjs/classes/symkeys.d.ts +292 -0
  36. package/dist/cjs/classes/symkeys.js +424 -0
  37. package/dist/cjs/classes/symkeys.js.map +1 -0
  38. package/dist/cjs/classes/type.d.ts +56 -0
  39. package/dist/cjs/classes/type.js +405 -0
  40. package/dist/cjs/classes/type.js.map +1 -0
  41. package/dist/cjs/function.extensions.js +757 -0
  42. package/dist/cjs/function.extensions.js.map +1 -0
  43. package/dist/cjs/global.this.js +261 -0
  44. package/dist/cjs/global.this.js.map +1 -0
  45. package/dist/cjs/index.d.ts +4 -3
  46. package/dist/cjs/index.js +62 -32
  47. package/dist/cjs/index.js.map +1 -1
  48. package/dist/cjs/json.extensions.d.ts +2 -0
  49. package/dist/cjs/json.extensions.js +107 -0
  50. package/dist/cjs/json.extensions.js.map +1 -0
  51. package/dist/{mjs/mapextensions.d.ts → cjs/map.extensions.d.ts} +1 -0
  52. package/dist/cjs/map.extensions.js +142 -0
  53. package/dist/cjs/map.extensions.js.map +1 -0
  54. package/dist/cjs/number.extension.d.ts +44 -0
  55. package/dist/cjs/number.extension.js +260 -0
  56. package/dist/cjs/number.extension.js.map +1 -0
  57. package/dist/cjs/object.extensions.d.ts +62 -0
  58. package/dist/cjs/object.extensions.js +1116 -0
  59. package/dist/cjs/object.extensions.js.map +1 -0
  60. package/dist/cjs/proxy.extensions.d.ts +2 -0
  61. package/dist/cjs/proxy.extensions.js +207 -0
  62. package/dist/cjs/proxy.extensions.js.map +1 -0
  63. package/dist/cjs/reflect.extensions.js +316 -0
  64. package/dist/cjs/reflect.extensions.js.map +1 -0
  65. package/dist/cjs/regular.expression.extensions.d.ts +2 -0
  66. package/dist/cjs/regular.expression.extensions.js +423 -0
  67. package/dist/cjs/regular.expression.extensions.js.map +1 -0
  68. package/dist/cjs/set.extensions.d.ts +40 -0
  69. package/dist/cjs/{setextensions.js → set.extensions.js} +150 -2
  70. package/dist/cjs/set.extensions.js.map +1 -0
  71. package/dist/cjs/string.extensions.js +471 -0
  72. package/dist/cjs/string.extensions.js.map +1 -0
  73. package/dist/{mjs/symbolextensions.d.ts → cjs/symbol.extensions.d.ts} +1 -0
  74. package/dist/cjs/symbol.extensions.js +259 -0
  75. package/dist/cjs/symbol.extensions.js.map +1 -0
  76. package/dist/cjs/{weakrefextensions.js → weakref.extensions.js} +1 -1
  77. package/dist/cjs/weakref.extensions.js.map +1 -0
  78. package/dist/mjs/array.extensions.d.ts +39 -0
  79. package/dist/mjs/array.extensions.js +300 -0
  80. package/dist/mjs/array.extensions.js.map +1 -0
  81. package/dist/mjs/big.int.extension.d.ts +31 -0
  82. package/dist/mjs/big.int.extension.js +161 -0
  83. package/dist/mjs/big.int.extension.js.map +1 -0
  84. package/dist/mjs/classes/asyncIterable.js.map +1 -0
  85. package/dist/mjs/classes/deferred.js.map +1 -0
  86. package/dist/mjs/{newClasses → classes}/descriptor.js +7 -4
  87. package/dist/mjs/classes/descriptor.js.map +1 -0
  88. package/dist/mjs/classes/index.d.ts +13 -0
  89. package/dist/mjs/classes/index.js +40 -0
  90. package/dist/mjs/classes/index.js.map +1 -0
  91. package/dist/mjs/classes/introspector.d.ts +20 -0
  92. package/dist/mjs/classes/introspector.js +126 -0
  93. package/dist/mjs/classes/introspector.js.map +1 -0
  94. package/dist/mjs/classes/iterable.js.map +1 -0
  95. package/dist/mjs/classes/param.parser.d.ts +227 -0
  96. package/dist/mjs/classes/param.parser.js +238 -0
  97. package/dist/mjs/classes/param.parser.js.map +1 -0
  98. package/dist/mjs/classes/pluggable.proxy.d.ts +152 -0
  99. package/dist/mjs/classes/pluggable.proxy.js +438 -0
  100. package/dist/mjs/classes/pluggable.proxy.js.map +1 -0
  101. package/dist/mjs/{newClasses → classes}/refmap.js +3 -3
  102. package/dist/mjs/classes/refmap.js.map +1 -0
  103. package/dist/mjs/classes/refset.js.map +1 -0
  104. package/dist/mjs/classes/symkeys.d.ts +292 -0
  105. package/dist/mjs/classes/symkeys.js +420 -0
  106. package/dist/mjs/classes/symkeys.js.map +1 -0
  107. package/dist/mjs/classes/type.d.ts +56 -0
  108. package/dist/mjs/classes/type.js +401 -0
  109. package/dist/mjs/classes/type.js.map +1 -0
  110. package/dist/mjs/function.extensions.js +754 -0
  111. package/dist/mjs/function.extensions.js.map +1 -0
  112. package/dist/mjs/global.this.js +258 -0
  113. package/dist/mjs/global.this.js.map +1 -0
  114. package/dist/mjs/index.d.ts +4 -3
  115. package/dist/mjs/index.js +49 -19
  116. package/dist/mjs/index.js.map +1 -1
  117. package/dist/mjs/json.extensions.d.ts +2 -0
  118. package/dist/mjs/json.extensions.js +104 -0
  119. package/dist/mjs/json.extensions.js.map +1 -0
  120. package/dist/{cjs/mapextensions.d.ts → mjs/map.extensions.d.ts} +1 -0
  121. package/dist/mjs/map.extensions.js +139 -0
  122. package/dist/mjs/map.extensions.js.map +1 -0
  123. package/dist/mjs/number.extension.d.ts +44 -0
  124. package/dist/mjs/number.extension.js +257 -0
  125. package/dist/mjs/number.extension.js.map +1 -0
  126. package/dist/mjs/object.extensions.d.ts +62 -0
  127. package/dist/mjs/object.extensions.js +1112 -0
  128. package/dist/mjs/object.extensions.js.map +1 -0
  129. package/dist/mjs/proxy.extensions.d.ts +2 -0
  130. package/dist/mjs/proxy.extensions.js +204 -0
  131. package/dist/mjs/proxy.extensions.js.map +1 -0
  132. package/dist/mjs/reflect.extensions.js +313 -0
  133. package/dist/mjs/reflect.extensions.js.map +1 -0
  134. package/dist/mjs/regular.expression.extensions.d.ts +2 -0
  135. package/dist/mjs/regular.expression.extensions.js +420 -0
  136. package/dist/mjs/regular.expression.extensions.js.map +1 -0
  137. package/dist/mjs/set.extensions.d.ts +40 -0
  138. package/dist/mjs/{setextensions.js → set.extensions.js} +149 -1
  139. package/dist/mjs/set.extensions.js.map +1 -0
  140. package/dist/mjs/string.extensions.js +468 -0
  141. package/dist/mjs/string.extensions.js.map +1 -0
  142. package/dist/{cjs/symbolextensions.d.ts → mjs/symbol.extensions.d.ts} +1 -0
  143. package/dist/mjs/symbol.extensions.js +256 -0
  144. package/dist/mjs/symbol.extensions.js.map +1 -0
  145. package/dist/mjs/{weakrefextensions.js → weakref.extensions.js} +1 -1
  146. package/dist/mjs/weakref.extensions.js.map +1 -0
  147. package/docs/index.html +24045 -5805
  148. package/package.json +6 -4
  149. package/repl.bootstrap.js +21 -0
  150. package/src/array.extensions.js +322 -0
  151. package/src/big.int.extension.js +163 -0
  152. package/src/{newClasses → classes}/descriptor.js +16 -12
  153. package/src/classes/index.js +51 -0
  154. package/src/classes/introspector.js +167 -0
  155. package/src/classes/param.parser.js +253 -0
  156. package/src/classes/pluggable.proxy.js +485 -0
  157. package/src/{newClasses → classes}/refmap.js +5 -3
  158. package/src/classes/symkeys.js +464 -0
  159. package/src/classes/type.js +427 -0
  160. package/src/function.extensions.js +818 -0
  161. package/src/global.this.js +304 -0
  162. package/src/index.js +56 -23
  163. package/src/json.extensions.js +108 -0
  164. package/src/map.extensions.js +144 -0
  165. package/src/number.extension.js +273 -0
  166. package/src/object.extensions.js +1222 -0
  167. package/src/proxy.extensions.js +229 -0
  168. package/src/reflect.extensions.js +346 -0
  169. package/src/regular.expression.extensions.js +451 -0
  170. package/src/{setextensions.js → set.extensions.js} +151 -2
  171. package/src/string.extensions.js +515 -0
  172. package/src/symbol.extensions.js +268 -0
  173. package/tests/newClasses/refmap.test.js +3 -2
  174. package/tsconfig.base.json +5 -3
  175. package/tsconfig.cjs.json +2 -2
  176. package/tsconfig.esm.json +2 -2
  177. package/dist/@nejs/basic-extensions.bundle.2.5.0.js +0 -8
  178. package/dist/@nejs/basic-extensions.bundle.2.5.0.js.map +0 -7
  179. package/dist/cjs/arrayextensions.d.ts +0 -10
  180. package/dist/cjs/arrayextensions.js +0 -73
  181. package/dist/cjs/arrayextensions.js.map +0 -1
  182. package/dist/cjs/functionextensions.js +0 -202
  183. package/dist/cjs/functionextensions.js.map +0 -1
  184. package/dist/cjs/globals.js +0 -166
  185. package/dist/cjs/globals.js.map +0 -1
  186. package/dist/cjs/mapextensions.js +0 -32
  187. package/dist/cjs/mapextensions.js.map +0 -1
  188. package/dist/cjs/newClasses/asyncIterable.js.map +0 -1
  189. package/dist/cjs/newClasses/deferred.js.map +0 -1
  190. package/dist/cjs/newClasses/descriptor.js.map +0 -1
  191. package/dist/cjs/newClasses/iterable.js.map +0 -1
  192. package/dist/cjs/newClasses/refmap.js.map +0 -1
  193. package/dist/cjs/newClasses/refset.js.map +0 -1
  194. package/dist/cjs/objectextensions.d.ts +0 -11
  195. package/dist/cjs/objectextensions.js +0 -232
  196. package/dist/cjs/objectextensions.js.map +0 -1
  197. package/dist/cjs/reflectextensions.js +0 -111
  198. package/dist/cjs/reflectextensions.js.map +0 -1
  199. package/dist/cjs/setextensions.d.ts +0 -2
  200. package/dist/cjs/setextensions.js.map +0 -1
  201. package/dist/cjs/stringextensions.js +0 -158
  202. package/dist/cjs/stringextensions.js.map +0 -1
  203. package/dist/cjs/symbolextensions.js +0 -69
  204. package/dist/cjs/symbolextensions.js.map +0 -1
  205. package/dist/cjs/weakrefextensions.js.map +0 -1
  206. package/dist/mjs/arrayextensions.d.ts +0 -10
  207. package/dist/mjs/arrayextensions.js +0 -70
  208. package/dist/mjs/arrayextensions.js.map +0 -1
  209. package/dist/mjs/functionextensions.js +0 -199
  210. package/dist/mjs/functionextensions.js.map +0 -1
  211. package/dist/mjs/globals.js +0 -163
  212. package/dist/mjs/globals.js.map +0 -1
  213. package/dist/mjs/mapextensions.js +0 -29
  214. package/dist/mjs/mapextensions.js.map +0 -1
  215. package/dist/mjs/newClasses/asyncIterable.js.map +0 -1
  216. package/dist/mjs/newClasses/deferred.js.map +0 -1
  217. package/dist/mjs/newClasses/descriptor.js.map +0 -1
  218. package/dist/mjs/newClasses/iterable.js.map +0 -1
  219. package/dist/mjs/newClasses/refmap.js.map +0 -1
  220. package/dist/mjs/newClasses/refset.js.map +0 -1
  221. package/dist/mjs/objectextensions.d.ts +0 -11
  222. package/dist/mjs/objectextensions.js +0 -229
  223. package/dist/mjs/objectextensions.js.map +0 -1
  224. package/dist/mjs/reflectextensions.js +0 -108
  225. package/dist/mjs/reflectextensions.js.map +0 -1
  226. package/dist/mjs/setextensions.d.ts +0 -2
  227. package/dist/mjs/setextensions.js.map +0 -1
  228. package/dist/mjs/stringextensions.js +0 -155
  229. package/dist/mjs/stringextensions.js.map +0 -1
  230. package/dist/mjs/symbolextensions.js +0 -66
  231. package/dist/mjs/symbolextensions.js.map +0 -1
  232. package/dist/mjs/weakrefextensions.js.map +0 -1
  233. package/src/arrayextensions.js +0 -75
  234. package/src/functionextensions.js +0 -225
  235. package/src/globals.js +0 -196
  236. package/src/mapextensions.js +0 -32
  237. package/src/objectextensions.js +0 -256
  238. package/src/reflectextensions.js +0 -118
  239. package/src/stringextensions.js +0 -166
  240. package/src/symbolextensions.js +0 -69
  241. /package/dist/cjs/{newClasses → classes}/asyncIterable.d.ts +0 -0
  242. /package/dist/cjs/{newClasses → classes}/deferred.d.ts +0 -0
  243. /package/dist/cjs/{newClasses → classes}/descriptor.d.ts +0 -0
  244. /package/dist/cjs/{newClasses → classes}/iterable.d.ts +0 -0
  245. /package/dist/cjs/{newClasses → classes}/refmap.d.ts +0 -0
  246. /package/dist/cjs/{newClasses → classes}/refset.d.ts +0 -0
  247. /package/dist/cjs/{functionextensions.d.ts → function.extensions.d.ts} +0 -0
  248. /package/dist/cjs/{globals.d.ts → global.this.d.ts} +0 -0
  249. /package/dist/cjs/{reflectextensions.d.ts → reflect.extensions.d.ts} +0 -0
  250. /package/dist/cjs/{stringextensions.d.ts → string.extensions.d.ts} +0 -0
  251. /package/dist/cjs/{weakrefextensions.d.ts → weakref.extensions.d.ts} +0 -0
  252. /package/dist/mjs/{newClasses → classes}/asyncIterable.d.ts +0 -0
  253. /package/dist/mjs/{newClasses → classes}/asyncIterable.js +0 -0
  254. /package/dist/mjs/{newClasses → classes}/deferred.d.ts +0 -0
  255. /package/dist/mjs/{newClasses → classes}/deferred.js +0 -0
  256. /package/dist/mjs/{newClasses → classes}/descriptor.d.ts +0 -0
  257. /package/dist/mjs/{newClasses → classes}/iterable.d.ts +0 -0
  258. /package/dist/mjs/{newClasses → classes}/iterable.js +0 -0
  259. /package/dist/mjs/{newClasses → classes}/refmap.d.ts +0 -0
  260. /package/dist/mjs/{newClasses → classes}/refset.d.ts +0 -0
  261. /package/dist/mjs/{newClasses → classes}/refset.js +0 -0
  262. /package/dist/mjs/{functionextensions.d.ts → function.extensions.d.ts} +0 -0
  263. /package/dist/mjs/{globals.d.ts → global.this.d.ts} +0 -0
  264. /package/dist/mjs/{reflectextensions.d.ts → reflect.extensions.d.ts} +0 -0
  265. /package/dist/mjs/{stringextensions.d.ts → string.extensions.d.ts} +0 -0
  266. /package/dist/mjs/{weakrefextensions.d.ts → weakref.extensions.d.ts} +0 -0
  267. /package/src/{newClasses → classes}/asyncIterable.js +0 -0
  268. /package/src/{newClasses → classes}/deferred.js +0 -0
  269. /package/src/{newClasses → classes}/iterable.js +0 -0
  270. /package/src/{newClasses → classes}/refset.js +0 -0
  271. /package/src/{weakrefextensions.js → weakref.extensions.js} +0 -0
@@ -0,0 +1,304 @@
1
+ import { Patch } from '@nejs/extension'
2
+ import { FunctionExtensions } from './function.extensions.js'
3
+
4
+ const { isClass, isFunction } = FunctionExtensions.patches
5
+ const CustomInspect = Symbol.for('nodejs.util.inspect.custom')
6
+
7
+ export const GlobalFunctionsAndProps = new Patch(globalThis, {
8
+ [Patch.kMutablyHidden]: {
9
+ /**
10
+ * The `isThenElse` function is a utility function that behaves like a
11
+ * ternary operator. It takes three arguments: `boolValue`, `thenValue`,
12
+ * and `elseValue`.
13
+ *
14
+ * It first checks the truthiness of `boolValue`.
15
+ *
16
+ * If `boolValue` is truthy, it returns `thenValue`; otherwise,
17
+ * it returns `elseValue`.
18
+ *
19
+ * If `thenValue` or `elseValue` is a function, it will be invoked with
20
+ * `boolValue` as an argument.
21
+ *
22
+ * If `elseValue` is not provided, it returns `boolValue` or `thenValue`
23
+ * depending on the truthiness of `boolValue`.
24
+ *
25
+ * If only `boolValue` is provided, it simply returns `boolValue`.
26
+ *
27
+ * @param {any} boolValue - Any object or value that is tested for
28
+ * truthiness.
29
+ * @param {function | any} [thenValue] - The value to return if `boolValue`
30
+ * is truthy. If a function, it's invoked with `boolValue`.
31
+ * @param {function | any} [elseValue] - The value to return if `boolValue`
32
+ * is falsy. If a function, it's invoked with `boolValue`.
33
+ * @returns {boolean | any} The result of the ternary operation.
34
+ *
35
+ * @example
36
+ * // Using values
37
+ * isThenElse(true, 'yes', 'no'); // Returns: 'yes'
38
+ * isThenElse(false, 'yes', 'no'); // Returns: 'no'
39
+ *
40
+ * // Using functions
41
+ * isThenElse(true, val => val ? 'yes' : 'no'); // Returns: 'yes'
42
+ * isThenElse(false, val => val ? 'yes' : 'no'); // Returns: 'no'
43
+ */
44
+ isThenElse(boolValue, thenValue, elseValue) {
45
+ if (arguments.length > 1) {
46
+ const _then = isFunction(thenValue) ? thenValue(boolValue) : thenValue
47
+
48
+ if (arguments.length > 2) {
49
+ const _else = isFunction(elseValue) ? thenValue(boolValue) : elseValue
50
+
51
+ return boolValue ? _then : _else
52
+ }
53
+
54
+ return boolValue || _then
55
+ }
56
+
57
+ return boolValue
58
+ },
59
+
60
+ /**
61
+ * Transforms an object to mimic a specified prototype, altering its type
62
+ * conversion and inspection behaviors. This function is especially useful
63
+ * for creating objects that need to behave like different primitive types
64
+ * under various operations.
65
+ *
66
+ * @param {Object} object - The object to be transformed.
67
+ * @param {Function|Object} [prototype=String.prototype] - The prototype or
68
+ * class to emulate. If a function is provided, its prototype is used.
69
+ * Defaults to String.prototype.
70
+ * @param {Function} [toPrimitive=(hint, val) => String(val)] - A function
71
+ * defining how the object should be converted to a primitive value. It
72
+ * receives a type hint ('number', 'string', or 'default') and the object,
73
+ * returning the primitive value.
74
+ * @returns {Object|null} The transformed object, or null if neither a class
75
+ * nor a prototype could be derived from the provided prototype parameter.
76
+ */
77
+ maskAs(object, classPrototype, options) {
78
+ const {
79
+ prototype,
80
+ toPrimitive
81
+ } = GenericMask({...options, prototype: classPrototype})
82
+
83
+ const base = { configurable: true, enumerable: false }
84
+ const proto = isFunction(prototype) ? prototype.prototype : prototype
85
+ const klass = isClass(prototype) ? prototype : proto?.constructor
86
+
87
+ if (!klass && !proto) {
88
+ return null
89
+ }
90
+
91
+ Object.setPrototypeOf(object, proto)
92
+ Object.defineProperties(object, {
93
+ valueOf: {
94
+ value() { return String(toPrimitive('default', object)) }, ...base },
95
+
96
+ [Symbol.toPrimitive]: {
97
+ value(hint) { return toPrimitive(hint, object) }, ...base
98
+ },
99
+ [Symbol.toStringTag]: { value: klass.name, ...base },
100
+ [Symbol.species]: { get() { return klass }, ...base },
101
+ [CustomInspect]: { ...base, value(depth, opts, inspect) {
102
+ return inspect(this[Symbol.toPrimitive](), { ...opts, depth })
103
+ }}
104
+ })
105
+
106
+ return object
107
+ },
108
+
109
+ /**
110
+ * Masks an object as a string-like object by setting its prototype to
111
+ * String and defining how it converts to primitive types. This is
112
+ * particularly useful when an object needs to behave like a string in
113
+ * certain contexts, such as type coercion or logging.
114
+ *
115
+ * @param {Object} object - The object to be masked as a string.
116
+ * @param {string} [stringKey='value'] - The object property key used for
117
+ * the string representation. Defaults to 'value'.
118
+ * @param {Function} [toPrimitive] - Optional custom function for primitive
119
+ * conversion. If omitted, a default function handling various conversion
120
+ * hints is used.
121
+ * @returns {Object|null} The string-masked object, or null if the object
122
+ * doesn't have the specified stringKey property.
123
+ */
124
+ maskAsString(
125
+ object,
126
+ stringKey,
127
+ toPrimitive
128
+ ) {
129
+ if (object && Reflect.has(object, stringKey)) {
130
+ return maskAs(object, StringMask(stringKey ?? 'value', toPrimitive))
131
+ }
132
+
133
+ return null
134
+ },
135
+
136
+ /**
137
+ * Masks an object as a number-like object. This allows the object to
138
+ * behave like a number in operations like arithmetic and type coercion.
139
+ * It sets the prototype to Number and defines custom conversion behavior.
140
+ *
141
+ * @param {Object} object - The object to be masked as a number
142
+ * representation. Defaults to 'value'.
143
+ * @param {Function} [toPrimitive] - Optional custom function for primitive
144
+ * conversion. If not provided, a default function handling different
145
+ * conversion hints is used.
146
+ * @returns {Object|null} The number-masked object, or null if the object
147
+ * doesn't have the specified numberKey property.
148
+ */
149
+ maskAsNumber(
150
+ object,
151
+ numberKey,
152
+ toPrimitive
153
+ ) {
154
+ if (object && Reflect.has(object, numberKey)) {
155
+ return maskAs(object, NumberMask(numberKey ?? 'value', toPrimitive))
156
+ }
157
+
158
+ return null
159
+ },
160
+
161
+ /**
162
+ * Generates options for generic masking of an object, providing defaults for
163
+ * prototype and toPrimitive function if not specified.
164
+ *
165
+ * @param {Object} options - The options object including prototype,
166
+ * targetKey, and toPrimitive function.
167
+ * @returns {Object} The options object with defaults applied as necessary.
168
+ */
169
+ GenericMask({ prototype, targetKey = 'value', toPrimitive }) {
170
+ const options = { targetKey, toPrimitive, prototype };
171
+
172
+ if (!isFunction(toPrimitive)) {
173
+ options.toPrimitive = (hint, object) => {
174
+ let property = object[targetKey];
175
+ let isNum = (
176
+ (typeof property === 'number' && Number.isFinite(property)) ||
177
+ (typeof property === 'string' &&
178
+ !isNaN(parseFloat(property)) && isFinite(property)
179
+ )
180
+ );
181
+
182
+ switch (hint) {
183
+ case 'string':
184
+ return isNum ? String(property) : (property ?? String(object));
185
+ case 'number':
186
+ return isNum ? Number(property) : NaN;
187
+ case 'default':
188
+ default:
189
+ return isNum ? Number(property) : property;
190
+ }
191
+ }
192
+ }
193
+
194
+ return options;
195
+ },
196
+
197
+ /**
198
+ * Generates options for string masking of an object, providing a default
199
+ * toPrimitive function if not specified.
200
+ *
201
+ * @param {string} targetKey - The object property key for string
202
+ * representation.
203
+ * @param {Function} toPrimitive - Custom function for primitive conversion.
204
+ * @returns {Object} Options for string masking.
205
+ */
206
+ StringMask(targetKey, toPrimitive) {
207
+ const options = { targetKey, toPrimitive, prototype: String.prototype }
208
+
209
+ if (!isFunction(toPrimitive)) {
210
+ options.toPrimitive = function toPrimitive(hint, object) {
211
+ switch (hint) {
212
+ case 'default': return object[targetKey]
213
+ case 'number': return parseInt(object[targetKey], 36)
214
+ case 'string': return String(object[targetKey])
215
+ default: return object
216
+ }
217
+ }
218
+ }
219
+
220
+ return options
221
+ },
222
+
223
+ /**
224
+ * Generates options for number masking of an object, providing a default
225
+ * toPrimitive function if not specified.
226
+ *
227
+ * @param {string} targetKey - The object property key for number
228
+ * representation.
229
+ * @param {Function} toPrimitive - Custom function for primitive conversion.
230
+ * @returns {Object} Options for number masking.
231
+ */
232
+ NumberMask(targetKey, toPrimitive) {
233
+ const options = { targetKey, toPrimitive, prototype: Number.prototype }
234
+
235
+ if (!isFunction(toPrimitive)) {
236
+ options.toPrimitive = function toPrimitive(hint, object) {
237
+ switch (hint) {
238
+ case 'default': return object[targetKey]
239
+ case 'number': return Number(object[targetKey])
240
+ case 'string': return String(object[targetKey])
241
+ default: return object
242
+ }
243
+ }
244
+ }
245
+
246
+ return options
247
+ },
248
+
249
+ /**
250
+ * Blends the properties of multiple objects into a new object. This
251
+ * function creates a new object that inherits the prototype from the
252
+ * root object and the properties of the other objects and their parent
253
+ * prototypes.
254
+ *
255
+ * @param {Object} root - The root object to blend prototypes into.
256
+ * @param {...Object} objects - The objects whose prototypes to blend.
257
+ * @returns {Object} The new object with blended prototypes.
258
+ *
259
+ * @example
260
+ * // Define some objects with properties
261
+ * const obj1 = { prop1: 'value1' }
262
+ * const obj2 = { prop2: 'value2' }
263
+ * const obj3 = { prop3: 'value3' }
264
+ *
265
+ * // Blend the prototypes of obj2 and obj3 into obj1
266
+ * const blended = blendProtos(obj1, obj2, obj3)
267
+ *
268
+ * // Now blended has properties from obj1, obj2, and obj3
269
+ * console.log(blended.prop1) // Outputs: 'value1'
270
+ * console.log(blended.prop2) // Outputs: 'value2'
271
+ * console.log(blended.prop3) // Outputs: 'value3'
272
+ */
273
+ blendProtos(root, ...objects) {
274
+ const descriptor = (o, k) => Object.getOwnPropertyDescriptor(o,k)
275
+ const parent = o => Object.getPrototypeOf(o)
276
+ const all = o => (Reflect
277
+ .ownKeys(o)
278
+ .reduce((a, k)=>({ ...a, [k]: descriptor(o,k) }), { })
279
+ )
280
+
281
+ const newRoot = Object.create(parent(root), objects.reduce)
282
+ const protos = objects.map(object => parent(object))
283
+
284
+ let descriptors = Object.create(null)
285
+ let uniques = new Set
286
+
287
+ for (let object of protos) {
288
+ let current = object
289
+
290
+ while (current) {
291
+ if (!uniques.has(current)) {
292
+ uniques.add(current)
293
+ descriptors = { ...descriptors, ...all(current) }
294
+ }
295
+ current = parent(current)
296
+ }
297
+ }
298
+
299
+ const blendedPrototype = Object.create(parent(root), descriptors)
300
+
301
+ return Object.setPrototypeOf(newRoot, blendedPrototype)
302
+ },
303
+ },
304
+ })
package/src/index.js CHANGED
@@ -1,42 +1,62 @@
1
- import { FunctionExtensions, FunctionPrototypeExtensions } from './functionextensions.js'
2
- import { ObjectExtensions, ObjectPrototypeExtensions } from './objectextensions.js'
3
- import { MapPrototypeExtensions } from './mapextensions.js'
4
- import { SetPrototypeExtensions } from './setextensions.js'
5
- import { ReflectExtensions } from './reflectextensions.js'
6
- import { StringExtensions, StringPrototypeExtensions } from './stringextensions.js'
7
- import { SymbolExtensions } from './symbolextensions.js'
8
- import { ArrayPrototypeExtensions } from './arrayextensions.js'
9
- import { DescriptorExtensions, Descriptor } from './newClasses/descriptor.js'
10
- import { GlobalFunctionsAndProps } from './globals.js'
11
- import { RefSetExtensions } from './newClasses/refset.js'
12
- import { RefMapExtensions } from './newClasses/refmap.js'
13
- import { DeferredExtension } from './newClasses/deferred.js'
1
+ import { ArrayExtensions, ArrayPrototypeExtensions } from './array.extensions.js'
2
+ import { BigIntExtensions, BigIntPrototypeExtensions } from './big.int.extension.js'
3
+ import { FunctionExtensions, FunctionPrototypeExtensions } from './function.extensions.js'
4
+ import { GlobalFunctionsAndProps } from './global.this.js'
5
+ import { JSONExtensions } from './json.extensions.js'
6
+ import { MapExtensions, MapPrototypeExtensions } from './map.extensions.js'
7
+ import { NumberExtensions, NumberPrototypeExtensions } from './number.extension.js'
8
+ import { ObjectExtensions, ObjectPrototypeExtensions } from './object.extensions.js'
9
+ import { ReflectExtensions } from './reflect.extensions.js'
10
+ import { RegExpExtensions } from './regular.expression.extensions.js'
11
+ import { SetExtensions, SetPrototypeExtensions } from './set.extensions.js'
12
+ import { StringExtensions, StringPrototypeExtensions } from './string.extensions.js'
13
+ import { SymbolExtensions, SymbolPrototypeExtensions } from './symbol.extensions.js'
14
+
15
+ import { DeferredExtension } from './classes/deferred.js'
16
+ import { DescriptorExtensions, Descriptor } from './classes/descriptor.js'
17
+ import { IntrospectorExtensions } from './classes/introspector.js'
18
+ import { IteratorExtensions, IterableExtensions } from './classes/iterable.js'
19
+ import { ParamParserExtensions } from './classes/param.parser.js'
20
+ import {
21
+ PluggableProxyExtensions,
22
+ ProxyHandlerExtensions,
23
+ PluggableProxyExtensionSet
24
+ } from './classes/pluggable.proxy.js'
25
+ import { RefMapExtensions } from './classes/refmap.js'
26
+ import { RefSetExtensions } from './classes/refset.js'
27
+ import { SymkeysExtension } from './classes/symkeys.js'
28
+ import { TypeExtensions } from './classes/type.js'
14
29
 
15
30
  import {
16
31
  AsyncIteratorExtensions,
17
32
  AsyncIterableExtensions
18
- } from './newClasses/asyncIterable.js'
19
-
20
- import {
21
- IteratorExtensions,
22
- IterableExtensions
23
- } from './newClasses/iterable.js'
33
+ } from './classes/asyncIterable.js'
24
34
 
25
35
  const StaticPatches = [
26
- [Object, ObjectExtensions, Object.name],
36
+ [Array, ArrayExtensions, Array.name],
37
+ [BigInt, BigIntExtensions, BigInt.name],
27
38
  [Function, FunctionExtensions, Function.name],
39
+ [JSON, JSONExtensions, 'JSON'], // Missing a .name property
40
+ [Map, MapExtensions, Map.name],
41
+ [Number, NumberExtensions, Number.name],
42
+ [Object, ObjectExtensions, Object.name],
28
43
  [Reflect, ReflectExtensions, 'Reflect'], // Missing a .name property
44
+ [RegExp, RegExpExtensions, RegExp.name],
45
+ [Set, SetExtensions, Set.name],
29
46
  [String, StringExtensions, String.name],
30
47
  [Symbol, SymbolExtensions, 'Symbol'], // Missing a .name property
31
48
  ]
32
49
 
33
50
  const InstancePatches = [
34
- [Object.prototype, ObjectPrototypeExtensions, Object.name],
35
- [String.prototype, StringPrototypeExtensions, String.name],
36
- [Function.prototype, FunctionPrototypeExtensions, Function.name],
37
51
  [Array.prototype, ArrayPrototypeExtensions, Array.name],
52
+ [BigInt.prototype, BigIntPrototypeExtensions, BigInt.name],
53
+ [Function.prototype, FunctionPrototypeExtensions, Function.name],
38
54
  [Map.prototype, MapPrototypeExtensions, Map.name],
55
+ [Number.prototype, NumberPrototypeExtensions, Number.name],
56
+ [Object.prototype, ObjectPrototypeExtensions, Object.name],
39
57
  [Set.prototype, SetPrototypeExtensions, Set.name],
58
+ [String.prototype, StringPrototypeExtensions, String.name],
59
+ [Symbol.prototype, SymbolPrototypeExtensions, Symbol.name],
40
60
  ]
41
61
 
42
62
  const Patches = new Map([
@@ -49,12 +69,25 @@ const Extensions = {
49
69
  [AsyncIteratorExtensions.key]: AsyncIteratorExtensions,
50
70
  [DeferredExtension.key]: DeferredExtension,
51
71
  [DescriptorExtensions.key]: DescriptorExtensions,
72
+ [IntrospectorExtensions.key]: IntrospectorExtensions,
52
73
  [IterableExtensions.key]: IterableExtensions,
53
74
  [IteratorExtensions.key]: IteratorExtensions,
75
+ [ParamParserExtensions.key]: ParamParserExtensions,
76
+ [PluggableProxyExtensions.key]: PluggableProxyExtensions,
77
+ [ProxyHandlerExtensions.key]: ProxyHandlerExtensions,
54
78
  [RefMapExtensions.key]: RefMapExtensions,
55
79
  [RefSetExtensions.key]: RefSetExtensions,
80
+ [SymkeysExtension.key]: SymkeysExtension,
81
+ [TypeExtensions.key]: TypeExtensions,
56
82
  }
57
83
 
84
+ export const Classes = {}
85
+ for (const extension of Object.values(Extensions)) {
86
+ const fnOrClass = extension.class || extension.function
87
+ Classes[fnOrClass.name] = fnOrClass
88
+ }
89
+
90
+
58
91
  const Controls = {}
59
92
 
60
93
  Object.assign(Controls, {
@@ -0,0 +1,108 @@
1
+ import { Patch } from '@nejs/extension'
2
+
3
+ export const JSONExtensions = new Patch(JSON, {
4
+ [Patch.kMutablyHidden]: {
5
+ /**
6
+ * The `extractFrom` method attempts to extract a JSON object from a string.
7
+ * It uses a regular expression to identify potential JSON objects in the
8
+ * string and attempts to parse them. If a valid JSON object is found, it is
9
+ * returned. If no valid JSON object is found, the method returns undefined.
10
+ *
11
+ * NOTE: This method will only find JSON from an iterated upon start spot
12
+ * until the end of the string. So `'JSON follows {"count": 0}'` will
13
+ * return `{count: 0}` but `'JSON follows {"count": 0} and more'` will
14
+ * fail to locate any JSON in the String. You've been warned.
15
+ *
16
+ * @param {string} string - The string from which to extract a JSON object.
17
+ * @returns {Object|undefined} - The first valid JSON object found in the
18
+ * string, or undefined if no valid JSON object is found.
19
+ *
20
+ * @example
21
+ * // Suppose we have a string with embedded JSON
22
+ * const str1 = 'Hello {"name":"John", "age":30} World'
23
+ * const str2 = 'Hello {"name": "John", "age": 30}'
24
+ *
25
+ * // Using `extractFrom`
26
+ * console.log(JSON.extractFrom(str1)) // Output: undefined
27
+ * console.log(JSON.extractFrom(str2)) // Output: {name: 'John', age: 30}
28
+ */
29
+ extractFrom(string) {
30
+ const pattern = /([\w\{\[\"]+) ?/g
31
+ const decoder = part => {
32
+ try { return JSON.parse(part) } catch (_) { return undefined }
33
+ }
34
+
35
+ for (
36
+ let part = pattern.exec(string);
37
+ part;
38
+ part = pattern.exec(string)
39
+ ) {
40
+ if (part && part?.index) {
41
+ const decoded = decoder(string.substring(part.index))
42
+ if (decoded) {
43
+ return decoded
44
+ }
45
+ }
46
+ }
47
+
48
+ return undefined
49
+ },
50
+
51
+ /**
52
+ * The `mightContain` method checks if a string might contain a JSON object.
53
+ * It uses the `JSONStartPattern` regular expression to search for potential
54
+ * JSON objects in the string. If a potential JSON object is found, the method
55
+ * returns true. If no potential JSON object is found, the method returns false.
56
+ *
57
+ * @param {string} string - The string to check for potential JSON objects.
58
+ * @returns {boolean} - Returns true if the string might contain a JSON object,
59
+ * false otherwise.
60
+ *
61
+ * @example
62
+ * // Suppose we have a string with embedded JSON
63
+ * const str = 'Hello {"name":"John", "age":30} World'
64
+ *
65
+ * // Using `mightContain`
66
+ * console.log(JSON.mightContain(str)) // Output: true
67
+ */
68
+ mightContain(string) {
69
+ return !!this.JSONStartPattern.exec(string)
70
+ },
71
+
72
+ /**
73
+ * Getter method for the JSONStartPattern.
74
+ *
75
+ * This method constructs a regular expression pattern that is used to
76
+ * identify potential JSON objects in a string. The pattern is designed
77
+ * to match various JSON data types including null, boolean, number,
78
+ * string, object, and array.
79
+ *
80
+ * The pattern is constructed using an array of strings, each representing
81
+ * a part of the pattern. The array is then joined into a single string
82
+ * and passed to the RegExp constructor to create the pattern.
83
+ *
84
+ * @returns {RegExp} - The constructed regular expression pattern.
85
+ *
86
+ * @example
87
+ * // Using `JSONStartPattern`
88
+ * const pattern = JSONStartPattern;
89
+ * const str = 'Hello {"name":"John", "age":30} World';
90
+ * const match = pattern.exec(str);
91
+ * console.log(match[0]); // Output: '{"name":"John", "age":30}'
92
+ */
93
+ get JSONStartPattern() {
94
+ const pattern = new RegExp([
95
+ '(?:', // Start with a non-capturing group and match
96
+ '(null)|', // ...a null
97
+ '(true|false)|', // ...a bool
98
+ '(\\d+\\.?\\d*)|', // ...a number (including floats)
99
+ '("[^\\"]*(?:[^:])")|', // ...a double quote (start of string)
100
+ '((?:\\{.*\\})+)|', // ...an open curly brace (object)
101
+ '((?:\\[.*\\]+))', // ...an open square bracket (array)
102
+ ')+', // End of the groups
103
+ ].join(''), 'gm')
104
+
105
+ return pattern
106
+ },
107
+ }
108
+ })
@@ -0,0 +1,144 @@
1
+ import { Patch } from '@nejs/extension'
2
+
3
+ export const MapExtensions = new Patch(Map, {
4
+ [Patch.kMutablyHidden]: {
5
+ /**
6
+ * Determines if the supplied `value` is a `Map` object. This check
7
+ * is performed by first looking for the `Symbol.toStringTag` on the
8
+ * `value` and checking to see if it is equal to the string "Map".
9
+ * If that check fails, `instanceof` is used as a fallback to check
10
+ * the prototype chain.
11
+ *
12
+ * @param {any} value the value that needs to be checked to determine
13
+ * if it is a `Map` object or not
14
+ * @returns {boolean} `true` if the supplied `value` is a `Map`
15
+ * object, `false` otherwise
16
+ *
17
+ * @example
18
+ * const map = new Map()
19
+ * isMap(map) // true
20
+ * isMap(new Set()) // false
21
+ * isMap([]) // false
22
+ * isMap({}) // false
23
+ */
24
+ isMap(value) {
25
+ return value?.[Symbol.toStringTag] === Map.name && value instanceof Map
26
+ },
27
+
28
+ /**
29
+ * Conditionally returns a value based on whether the supplied
30
+ * `value` is a `Map` object or not. If the `value` is a `Map`
31
+ * object, the `thenValue` will be returned. If it is not a `Map`
32
+ * object, the `elseValue` will be returned instead.
33
+ *
34
+ * @param {any} value the value to check to determine if it is a
35
+ * `Map` object
36
+ * @param {any} thenValue the value to return if the supplied
37
+ * `value` is a `Map` object
38
+ * @param {any} elseValue the value to return if the supplied
39
+ * `value` is not a `Map` object
40
+ * @returns {any} either the `thenValue` or `elseValue` depending
41
+ * on if the supplied `value` is a `Map` object
42
+ *
43
+ * @example
44
+ * const map = new Map()
45
+ * const set = new Set()
46
+ * ifMap(map, 'is a map', 'not a map') // 'is a map'
47
+ * ifMap(set, 'is a map', 'not a map') // 'not a map'
48
+ */
49
+ ifMap(value, thenValue, elseValue) {
50
+ return isThenElse(this.isMap(value), thenValue, elseValue)
51
+ },
52
+ }
53
+ })
54
+
55
+ const { isMap: pIsMap, ifMap: pIfMap } = MapExtensions.patches
56
+
57
+ export const MapPrototypeExtensions = new Patch(Map.prototype, {
58
+ [Patch.kMutablyHidden]: {
59
+ /**
60
+ * Determines if the current object is a `Map` object
61
+ *
62
+ * This is a getter that uses the `isMap` function from the
63
+ * `MapExtensions` patch to check if the current object (`this`) is
64
+ * a `Map` object
65
+ *
66
+ * @type {boolean}
67
+ * @readonly
68
+ *
69
+ * @example
70
+ * const map = new Map()
71
+ * console.log(map.isMap) // Output: true
72
+ *
73
+ * const notMap = {}
74
+ * console.log(notMap.isMap) // Output: false
75
+ */
76
+ get isMap() {
77
+ return pIsMap(this)
78
+ },
79
+
80
+ /**
81
+ * Conditionally returns a value based on whether the current
82
+ * object is a `Map` object or not
83
+ *
84
+ * If the current object is a `Map` object, the `thenValue` will
85
+ * be returned. If it is not a `Map` object, the `elseValue` will
86
+ * be returned instead.
87
+ *
88
+ * @param {any} thenValue the value to return if the current
89
+ * object is a `Map` object
90
+ * @param {any} elseValue the value to return if the current
91
+ * object is not a `Map` object
92
+ * @returns {any} either the `thenValue` or `elseValue` depending
93
+ * on if the current object is a `Map` object
94
+ *
95
+ * @example
96
+ * const map = new Map()
97
+ * map.ifMap('is a map', 'not a map') // 'is a map'
98
+ *
99
+ * const notMap = {}
100
+ * notMap.ifMap('is a map', 'not a map') // 'not a map'
101
+ */
102
+ ifMap(thenValue, elseValue) {
103
+ return pIfMap(this, thenValue, elseValue)
104
+ },
105
+
106
+ /**
107
+ * The function `getKey` returns the key associated with a given value
108
+ * in a map.
109
+ *
110
+ * @param {any} value - The value parameter is the value that you want to
111
+ * find the corresponding key for in the map.
112
+ * @param [strict=true] - The "strict" parameter is a boolean value that
113
+ * determines whether strict equality (===) or loose equality (==) should
114
+ * be used when comparing the "value" parameter with the values in the
115
+ * entries of the object. If "strict" is set to true, strict equality will
116
+ * be used.
117
+ * @returns the key associated with the given value. If a matching key is
118
+ * found, it is returned. If no matching key is found, null is returned.
119
+ */
120
+ getKey(value, strict = true) {
121
+ for (const [key, entryValue] of this) {
122
+ if (
123
+ (strict && value === entryValue) &&
124
+ (!strict && value == entryValue)
125
+ ) {
126
+ return key
127
+ }
128
+
129
+ return null
130
+ }
131
+ },
132
+ },
133
+ })
134
+
135
+ // NOTE to self; this is repeated here otherwise a circular reference from
136
+ // Object<->Function<->Global occurs. See original source in global.this.js
137
+ // {@see globalThis.isThenElse}
138
+ function isThenElse(bv, tv, ev) {
139
+ if (arguments.length > 1) {
140
+ var _then = isFunction(tv) ? tv(bv) : tv; if (arguments.length > 2) {
141
+ var _else = isFunction(ev) ? tv(bv) : ev; return bv ? _then : _else
142
+ } return bv || _then;
143
+ } return bv
144
+ }