@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,229 @@
1
+ import { Patch } from '@nejs/extension'
2
+
3
+ import { ObjectExtensions } from './object.extensions.js'
4
+ import { StringExtensions } from './string.extensions.js'
5
+
6
+ import { Symkeys } from './classes/symkeys.js'
7
+
8
+ const { isObject } = ObjectExtensions.patches
9
+ const { isString } = StringExtensions.patches
10
+
11
+ const keys = new Symkeys('nejs.proxy')
12
+
13
+ export const ProxyExtensions = new Patch(Proxy, {
14
+ [Patch.kImmutablyHidden]: {
15
+ /**
16
+ * Getter method for the 'keys' property.
17
+ *
18
+ * This method returns the 'keys' object which is an instance of the
19
+ * Symkeys class. The Symkeys class provides a way to easily generate
20
+ * Symbol.for elements that follow a particular pattern and also allows
21
+ * associated data storage with each generated key.
22
+ *
23
+ * @returns {Symkeys} The 'keys' object.
24
+ *
25
+ * @example
26
+ * const proxyExtensions = new ProxyExtensions();
27
+ * const kCustomKeyForMyProxy = Proxy.keys.add('mything', { thing: ... })
28
+ *
29
+ * new Proxy(object, {
30
+ * get(target, property, receiver) {
31
+ * if (property === kCustomKeyForMyProxy) {
32
+ * // use associated data
33
+ * return kCustomKeyForMyProxy.data.thing
34
+ * }
35
+ * return Reflect.get(target, property, receiver)
36
+ * }
37
+ * })
38
+ */
39
+ get keys() {
40
+ return keys
41
+ },
42
+ },
43
+
44
+ [Patch.kMutablyHidden]: {
45
+ /**
46
+ * This method generates an object based on the trap type and values
47
+ * provided. The trap type is a string that corresponds to a Proxy handler
48
+ * method, and the values are either an array or an object that maps to
49
+ * the parameters of the handler method.
50
+ *
51
+ * If the trap type is not a valid Proxy handler method, the function
52
+ * returns undefined. If the values are an array, they are mapped to the
53
+ * parameters of the handler method in order. If the values are an object,
54
+ * only the entries that correspond to the parameters of the handler
55
+ * method are used.
56
+ *
57
+ * @param {array | string} trapType - Either a key into the Proxy.types
58
+ * object or the value that such a key might point to (i.e. an array of
59
+ * string names, in order, that the trap of the same name expects)
60
+ * @param {array | object} values - The values to be used for the trap
61
+ * parameters.
62
+ * @returns {object} An object that maps the trap parameters to the
63
+ * provided values.
64
+ *
65
+ * @example
66
+ * // note that when values is an array, the order needs to match the
67
+ * // order of expected parameters for the trap function or the behavior
68
+ * // is undefined.
69
+ * trapParams('get', [
70
+ * 'target',
71
+ * 'property',
72
+ * 'receiver'
73
+ * ])
74
+ * // Returns: {
75
+ * // target: 'target', property: 'property', receiver: 'receiver'
76
+ * // }
77
+ *
78
+ * trapParams(Proxy.types.get, {
79
+ * target: 'target',
80
+ * property: 'property',
81
+ * receiver: 'receiver'
82
+ * })
83
+ * // Returns: {
84
+ * // target: 'target', property: 'property', receiver: 'receiver'
85
+ * // }
86
+ */
87
+ trapParams(trapType, values) {
88
+ if (
89
+ (isString(trapType) && !(~Proxy.types.indexOf(trapType))) ||
90
+ !Array.isArray(trapType)
91
+ ) {
92
+ return undefined
93
+ }
94
+
95
+ let argumentNames = isString(trapType)
96
+ ? Proxy.types[trapType]
97
+ : trapType.map(element => String(element))
98
+
99
+ let object = Object.create(Object.prototype)
100
+
101
+ if (!Array.isArray(values) && !Object.isObject(values)) {
102
+ values = [values]
103
+ for (let i = 1; i < argumentNames.length; i++) {
104
+ values.push(undefined)
105
+ }
106
+ }
107
+
108
+ if (Array.isArray(values)) {
109
+ argumentNames.reduce((acc, argName, index) => {
110
+ acc[argName] = values?.[index]
111
+ }, object)
112
+ }
113
+ else if (isObject(values)) {
114
+ for (let [key, value] of Object.entries(values)) {
115
+ if (key in argumentNames) {
116
+ object[key] = value
117
+ }
118
+ }
119
+ }
120
+
121
+ return object
122
+ },
123
+
124
+ types: {
125
+ /**
126
+ * The handler.apply() method is a trap for the [[Call]] object internal
127
+ * method, which is used by operations such as function calls.
128
+ * MDN link: https://t.ly/orBsG
129
+ */
130
+ get apply() { return ['target', 'thisArg', 'argumentsList'] },
131
+
132
+ /**
133
+ * The handler.construct() method is a trap for the [[Construct]] object
134
+ * internal method, which is used by operations such as the new operator.
135
+ * In order for the new operation to be valid on the resulting Proxy
136
+ * object, the target used to initialize the proxy must itself be a
137
+ * valid constructor.
138
+ * MDN link: https://t.ly/1LukS
139
+ */
140
+ get construct() { return ['target', 'args'] },
141
+
142
+ /**
143
+ * The handler.defineProperty() method is a trap for the
144
+ * [[DefineOwnProperty]] object internal method, which is used by
145
+ * operations such as Object.defineProperty().
146
+ * MDN link: https://t.ly/3Ml9y
147
+ */
148
+ get defineProperty() { return ['target', 'key', 'descriptor'] },
149
+
150
+ /**
151
+ * The handler.deleteProperty() method is a trap for the [[Delete]]
152
+ * object internal method, which is used by operations such as the
153
+ * delete operator.
154
+ * MDN link: https://t.ly/neu2H
155
+ */
156
+ get deleteProperty() { return ['target', 'property'] },
157
+
158
+ /**
159
+ * The handler.get() method is a trap for the [[Get]] object internal
160
+ * method, which is used by operations such as property accessors.
161
+ * MDN link: https://t.ly/E419x
162
+ */
163
+ get get() { return ['target', 'property', 'receiver'] },
164
+
165
+ /**
166
+ * The handler.getOwnPropertyDescriptor() method is a trap for the
167
+ * [[GetOwnProperty]] object internal method, which is used by operations
168
+ * such as Object.getOwnPropertyDescriptor().
169
+ * MDN link: https://t.ly/wzPTX
170
+ */
171
+ get getOwnPropertyDescriptor() { return ['target', 'property'] },
172
+
173
+ /**
174
+ * The handler.getPrototypeOf() method is a trap for the
175
+ * [[GetPrototypeOf]] object internal method, which is used by operations
176
+ * such as Object.getPrototypeOf().
177
+ * MDN link: https://t.ly/Ww4S1
178
+ */
179
+ get getPrototypeOf() { return ['target'] },
180
+
181
+ /**
182
+ * The handler.has() method is a trap for the [[HasProperty]] object
183
+ * internal method, which is used by operations such as the in operator.
184
+ * MDN link: https://t.ly/UcJL-
185
+ */
186
+ get has() { return ['target', 'prototype'] },
187
+
188
+ /**
189
+ * The handler.isExtensible() method is a trap for the [[IsExtensible]]
190
+ * object internal method, which is used by operations such as
191
+ * Object.isExtensible().
192
+ * MDN link: https://t.ly/MkdIK
193
+ */
194
+ get isExtensible() { return ['target'] },
195
+
196
+ /**
197
+ * The handler.ownKeys() method is a trap for the [[OwnPropertyKeys]]
198
+ * object internal method, which is used by operations such as
199
+ * Object.keys(), Reflect.ownKeys(), etc.
200
+ * MDN link: https://t.ly/QkiTI
201
+ */
202
+ get ownKeys() { return ['target'] },
203
+
204
+ /**
205
+ * The handler.preventExtensions() method is a trap for the
206
+ * [[PreventExtensions]] object internal method, which is used by
207
+ * operations such as Object.preventExtensions().
208
+ * MDN link: https://t.ly/nvfjJ
209
+ */
210
+ get preventExtensions() { return ['target'] },
211
+
212
+ /**
213
+ * The handler.set() method is a trap for the [[Set]] object internal
214
+ * method, which is used by operations such as using property accessors
215
+ * to set a property's value.
216
+ * MDN link: https://t.ly/FDWcl
217
+ */
218
+ get set() { return ['target', 'property', 'value', 'receiver'] },
219
+
220
+ /**
221
+ * The handler.setPrototypeOf() method is a trap for the
222
+ * [[SetPrototypeOf]] object internal method, which is used by operations
223
+ * such as Object.setPrototypeOf().
224
+ * MDN link: https://t.ly/pS8ej
225
+ */
226
+ get setPrototypeOf() { return ['target', 'prototype'] },
227
+ },
228
+ }
229
+ })
@@ -0,0 +1,346 @@
1
+ import { Patch } from '@nejs/extension'
2
+
3
+ /**
4
+ * The `ReflectExtensions` class is a patch applied to the built-in JavaScript
5
+ * `Reflect` object. It extends `Reflect` with additional utility methods that
6
+ * enhance its capabilities. These methods provide more advanced ways of
7
+ * interacting with object properties, such as checking for the presence of
8
+ * multiple keys at once (`hasAll`) or verifying if at least one specified key
9
+ * exists in an object (`hasSome`). This class is part of the `@nejs/extension`
10
+ * library and is designed to offer these extended functionalities in a way
11
+ * that is consistent with the existing `Reflect` API, making it intuitive for
12
+ * developers who are already familiar with standard reflection methods in
13
+ * JavaScript.
14
+ */
15
+ export const ReflectExtensions = new Patch(Reflect, {
16
+ /**
17
+ * The function checks if an object has all the specified keys.
18
+ *
19
+ * @param object - The `object` parameter is the object that we want to
20
+ * check if it has all the specified keys.
21
+ * @param keys - The `keys` parameter is a rest parameter, which means
22
+ * it can accept any number of arguments. In this case, it is expected
23
+ * to receive multiple keys as arguments.
24
+ * @returns a boolean value.
25
+ */
26
+ hasAll(object, ...keys) {
27
+ return Object.isObject(object) && (keys.flat(Infinity)
28
+ .map(key => Reflect.has(object, key))
29
+ .every(has => has)
30
+ )
31
+ },
32
+
33
+ /**
34
+ * The function checks if an object has at least one of the specified keys.
35
+ *
36
+ * @param object - The `object` parameter is the object that we want to check
37
+ * for the presence of certain keys.
38
+ * @param keys - The `keys` parameter is a rest parameter, which means it can
39
+ * accept any number of arguments. These arguments are the keys that we want
40
+ * to check if they exist in the `object`.
41
+ * @returns The function `hasSome` returns a boolean value indicating whether
42
+ * at least one of the keys provided as arguments exists in the given object.
43
+ */
44
+ hasSome(object, ...keys) {
45
+ return isObject(object) && (keys.flat(Infinity)
46
+ .map(key => Reflect.has(object, key))
47
+ .some(has => has)
48
+ )
49
+ },
50
+
51
+ /**
52
+ * The `metadata` method retrieves metadata about a property of an object.
53
+ * It returns an object containing information about the property, such as
54
+ * its value, descriptor, and whether it is read-only, assignable, an
55
+ * accessor, or a data descriptor.
56
+ *
57
+ * @param {string} key - The name of the property.
58
+ * @param {object} [owner=globalThis] - The object that owns the property.
59
+ * If not provided, it defaults to the global object.
60
+ * @returns {object|undefined} An object containing metadata about the
61
+ * property, or `undefined` if the property does not exist or the owner is
62
+ * not an object.
63
+ *
64
+ * @example
65
+ * const obj = { foo: 'bar' }
66
+ * const meta = ReflectExtensions.metadata('foo', obj)
67
+ * console.log(meta.value) // Outputs: 'bar'
68
+ * console.log(meta.isReadOnly) // Outputs: false
69
+ */
70
+ metadata(key, owner = globalThis) {
71
+ const args = [{key}, {owner}]
72
+ const variants = applyVariants(args)()
73
+ if (variants.check(0)) {
74
+ key = variants.object.key
75
+ owner = variants.object.owner
76
+ }
77
+
78
+ const descriptor = isObject(owner) && isValidKey(key)
79
+ ? Object.getOwnPropertyDescriptor(owner, key)
80
+ : undefined
81
+
82
+ const value = () => descriptor?.get?.bind(owner)?.() ?? owner[key]
83
+
84
+ if (!descriptor) {
85
+ return undefined
86
+ }
87
+
88
+ const meta = {
89
+ /**
90
+ * A getter method that returns the owner of the property.
91
+ * The owner is the object that owns the property.
92
+ *
93
+ * @returns {object} The owner of the property.
94
+ *
95
+ * @example
96
+ * const obj = { foo: 'bar' }
97
+ * const meta = Reflect.metadata('foo', obj)
98
+ * console.log(meta.owner) // Outputs: obj
99
+ */
100
+ get owner() { return owner },
101
+
102
+ /**
103
+ * A getter method that returns the key of the property.
104
+ * The key is the name of the property.
105
+ *
106
+ * @returns {string} The key of the property.
107
+ *
108
+ * @example
109
+ * const obj = { foo: 'bar' }
110
+ * const meta = Reflect.metadata('foo', obj)
111
+ * console.log(meta.key) // Outputs: 'foo'
112
+ */
113
+ get key() { return key },
114
+
115
+ /**
116
+ * A getter method that returns the value of the property.
117
+ * The value is obtained by invoking the `value` function.
118
+ *
119
+ * @returns {*} The value of the property.
120
+ *
121
+ * @example
122
+ * const obj = { foo: 'bar' }
123
+ * const meta = Reflect.metadata('foo', obj)
124
+ * console.log(meta.value) // Outputs: 'bar'
125
+ */
126
+ get value() { return value() },
127
+
128
+ /**
129
+ * A getter method that returns the descriptor of the property.
130
+ * The descriptor is an object that describes a property's configuration.
131
+ * It includes properties like value, writable, enumerable, configurable,
132
+ * get, and set.
133
+ *
134
+ * @returns {object} The descriptor of the property.
135
+ *
136
+ * @example
137
+ * const obj = { foo: 'bar' }
138
+ * const meta = Reflect.metadata('foo', obj)
139
+ * console.log(meta.descriptor)
140
+ *
141
+ * // Outputs: {
142
+ * // value: 'bar',
143
+ * // writable: true,
144
+ * // enumerable: true,
145
+ * // configurable: true
146
+ * // }
147
+ */
148
+ get descriptor() { return descriptor },
149
+
150
+ /**
151
+ * A getter method that checks if the property is read-only.
152
+ * A property is considered read-only if it is an accessor property
153
+ * (i.e., it has a getter or a setter) and it does not have a setter.
154
+ * This means that the property can be read, but not written to.
155
+ *
156
+ * @returns {boolean} `true` if the property is read-only,
157
+ * `false` otherwise.
158
+ *
159
+ * @example
160
+ * const obj = {
161
+ * get foo() { return 'bar' }
162
+ * }
163
+ * const meta = Reflect.metadata('foo', obj)
164
+ * console.log(meta.isReadOnly) // Outputs: true
165
+ */
166
+ get isReadOnly() {
167
+ return this.isAccessor && !descriptor?.set
168
+ },
169
+
170
+ /**
171
+ * A getter method that checks if the property is assignable.
172
+ * A property is considered assignable if it is either configurable
173
+ * or writable. Configurable properties can be modified and deleted,
174
+ * while writable properties can have their values changed.
175
+ *
176
+ * @returns {boolean} `true` if the property is assignable,
177
+ * `false` otherwise.
178
+ *
179
+ * @example
180
+ * const obj = { foo: 'bar' }
181
+ * const meta = Reflect.metadata('foo', obj)
182
+ * console.log(meta.isAssignable) // Outputs: true
183
+ */
184
+ get isAssignable() {
185
+ return descriptor?.configurable ?? descriptor?.writable
186
+ },
187
+
188
+ /**
189
+ * A getter method that checks if the property is an accessor.
190
+ * An accessor property is a property that has a getter method, a setter
191
+ * method, or both. This method returns `true` if the property has either
192
+ * a getter or a setter, and `false` otherwise.
193
+ *
194
+ * @returns {boolean} `true` if the property is an accessor,
195
+ * `false` otherwise.
196
+ *
197
+ * @example
198
+ * const obj = {
199
+ * get foo() { return 'bar' },
200
+ * set foo(value) { console.log('Setting foo to', value) }
201
+ * }
202
+ * const meta = Reflect.metadata('foo', obj)
203
+ * console.log(meta.isAccessor) // Outputs: true
204
+ */
205
+ get isAccessor() {
206
+ return !!(this?.descriptor?.get || this?.descriptor?.set)
207
+ },
208
+
209
+ /**
210
+ * A getter method that checks if the property is a data property.
211
+ * A data property is a property that has a value and can be written to.
212
+ * This method returns `true` if the property has a value or is writable,
213
+ * and `false` otherwise.
214
+ *
215
+ * @returns {boolean} `true` if the property is a data property,
216
+ * `false` otherwise.
217
+ *
218
+ * @example
219
+ * const obj = { foo: 'bar' }
220
+ * const meta = Reflect.metadata('foo', obj)
221
+ * console.log(meta.isData) // Outputs: true
222
+ */
223
+ get isData() {
224
+ return !!(this?.descriptor?.value || this?.descriptor?.writable)
225
+ },
226
+ }
227
+
228
+ return meta
229
+ },
230
+
231
+ /**
232
+ * Fetches all descriptors of an object, including those mapped to a
233
+ * symbol descriptor value.
234
+ *
235
+ * @param {object} object the object from whose descriptors need to be
236
+ * retrieved.
237
+ * @returns {object} with keys mapped to object descriptors
238
+ * @throws {TypeError} if the supplied `object` is null or not an object
239
+ * a TypeError exception will be thrown
240
+ */
241
+ ownDescriptors(object) {
242
+ if (!isObject(object)) {
243
+ throw new TypeError('The supplied object must be non-null and an object')
244
+ }
245
+
246
+ const result = {}
247
+
248
+ const keys = Reflect.ownKeys(object)
249
+
250
+ for (const key of keys) {
251
+ result[key] = Object.getOwnPropertyDescriptor(key)
252
+ }
253
+
254
+ return result
255
+ },
256
+
257
+ /**
258
+ * Retrieves an array of [key, descriptor] pairs for each property of the
259
+ * provided object. This method is akin to `Object.entries` but includes
260
+ * property descriptors instead of the property values. It's useful for cases
261
+ * where you need detailed information about properties, including their
262
+ * configurability, enumerability, and accessors.
263
+ *
264
+ * @param {object} object - The object whose property entries are to be
265
+ * retrieved.
266
+ * @returns {Array} An array of [key, descriptor] pairs, where each pair
267
+ * consists of the property name (key) and its descriptor. Returns an empty
268
+ * array if the input is not a valid object.
269
+ */
270
+ entries(object) {
271
+ if (!object || typeof object !== 'object') { return [] }
272
+
273
+ return Reflect.ownKeys(object).map(key => [
274
+ key, Object.getOwnPropertyDescriptor(object, key)
275
+ ])
276
+ },
277
+
278
+ /**
279
+ * Retrieves an array of values from the property descriptors of the given
280
+ * object. This method works similarly to `Object.values` but operates on
281
+ * property descriptors instead. It's useful when you need the values of
282
+ * properties including getters, setters, and other descriptor-specific
283
+ * attributes.
284
+ *
285
+ * @param {object} object - The object whose property values are to be
286
+ * retrieved.
287
+ * @returns {Array} An array of values extracted from the object's property
288
+ * descriptors. The values correspond to the `value` attribute in each
289
+ * property's descriptor. Returns an empty array if the input is not a valid
290
+ * object.
291
+ */
292
+ values(object) {
293
+ return Reflect.entries.map(([,value]) => value)
294
+ },
295
+ })
296
+
297
+ function isObject(value) {
298
+ return value && typeof value === 'object'
299
+ }
300
+
301
+ function isValidKey(value) {
302
+ return ['string', 'symbol'].some(type => typeof value === type)
303
+ }
304
+
305
+ function applyVariants(thisArg) {
306
+ return ((function variants() {
307
+ const keys = this.map(o => Object.keys(o)?.[0])
308
+ const entries = this.map(o => Object.entries(o)?.[0])
309
+ const object = entries.reduce((acc,[key, value]) => {
310
+ acc[key] = value;
311
+ return acc;
312
+ }, {})
313
+
314
+ const result = {
315
+ order: keys,
316
+ entries: entries,
317
+ object: object,
318
+ }
319
+
320
+ Object.defineProperty(result, 'check', {
321
+ value(position) {
322
+ if (
323
+ typeof position !== 'number' &&
324
+ position >= 0 &&
325
+ position < this.order.length
326
+ ) {
327
+ return false
328
+ }
329
+
330
+ const value = this.entries[position][1]
331
+
332
+ if (typeof value === 'object' && value) {
333
+ if (Object.keys(value).every(key => ~this.order.indexOf(key))) {
334
+ return true
335
+ }
336
+ }
337
+
338
+ return false
339
+ },
340
+ enumerable: false,
341
+ configurable: true
342
+ })
343
+
344
+ return result
345
+ }).bind(thisArg))
346
+ }