1. 1 : /* eslint-disable @typescript-eslint/no-unused-vars */
  2. 2 : /* eslint-disable no-prototype-builtins */
  3. 3 : /* eslint-disable @typescript-eslint/triple-slash-reference */
  4. 4 : const __global = (typeof window != 'undefined' ? window : global) /* node */ as any;
  5. 5 :
  6. 6 : interface Object {
  7. 7 : length: number;
  8. 8 :
  9. 9 : /**
  10. 10 : * Dynamic Key
  11. 11 : */
  12. 12 : [str: string]: any;
  13. 13 :
  14. 14 : /**
  15. 15 : * Merge this object with another object
  16. 16 : */
  17. 17 : merge: (...other: Record<any, unknown>[]) => Record<any, unknown>;
  18. 18 :
  19. 19 : /**
  20. 20 : * Iterate Object
  21. 21 : * @param callback function each element
  22. 22 : * @example
  23. 23 : * var a = {'a','n'};
  24. 24 : * a.each(function(el){
  25. 25 : * console.log(el); //a, n each iteration
  26. 26 : * })
  27. 27 : */
  28. 28 : each(callback: (arg0: any) => any): any;
  29. 29 :
  30. 30 : /**
  31. 31 : * Check is empty
  32. 32 : */
  33. 33 : isEmpty(): boolean;
  34. 34 :
  35. 35 : replaceKeyFrom(anotherObj: any): any;
  36. 36 : }
  37. 37 :
  38. 38 : interface ObjectConstructor {
  39. 39 : /**
  40. 40 : * Dynamic Key
  41. 41 : */
  42. 42 : [str: string]: any;
  43. 43 :
  44. 44 : /**
  45. 45 : * Count size length of object
  46. 46 : */
  47. 47 : size: (obj: any) => number;
  48. 48 :
  49. 49 : //[pair: string|number]: any;
  50. 50 :
  51. 51 : /**
  52. 52 : * Is Object Has Property of key ?
  53. 53 : * @param key
  54. 54 : */
  55. 55 : hasOwnProperty(key: any): boolean;
  56. 56 :
  57. 57 : /**
  58. 58 : * check if has child and go for callback
  59. 59 : * @param str match child property
  60. 60 : * @param callback function callback
  61. 61 : * @author Dimas Lanjaka <dimaslanjaka@gmail.com>
  62. 62 : */
  63. 63 : child(str: string | number, callback: (arg: any) => any): any;
  64. 64 :
  65. 65 : /**
  66. 66 : * check object has child, if not exist return alternative value
  67. 67 : * @param str match child property
  68. 68 : * @param alternative default value callback
  69. 69 : * @author Dimas Lanjaka <dimaslanjaka@gmail.com>
  70. 70 : */
  71. 71 : alt(str: any, alternative: string | number | boolean): any;
  72. 72 :
  73. 73 : /**
  74. 74 : * Check object has child
  75. 75 : * @param str
  76. 76 : */
  77. 77 : has(str: string | number): any;
  78. 78 : }
  79. 79 :
  80. 80 : Object.size = function (obj) {
  81. 81 : let size = 0,
  82. 82 : key: any;
  83. 83 : for (key in obj) {
  84. 84 : if (obj.hasOwnProperty(key)) size++;
  85. 85 : }
  86. 86 : return size;
  87. 87 : };
  88. 88 :
  89. 89 : Object.child = function (str, callback) {
  90. 90 : const self: object = this;
  91. 91 : if (self.hasOwnProperty(str)) {
  92. 92 : if (typeof callback == 'function') {
  93. 93 : return callback(self[str]);
  94. 94 : } else {
  95. 95 : return true;
  96. 96 : }
  97. 97 : } else {
  98. 98 : return undefined;
  99. 99 : }
  100. 100 : };
  101. 101 :
  102. 102 : Object.alt = function (str, alternative) {
  103. 103 : const self: any = this;
  104. 104 : if (self.hasOwnProperty(str)) {
  105. 105 : return self[str];
  106. 106 : } else {
  107. 107 : return alternative;
  108. 108 : }
  109. 109 : };
  110. 110 :
  111. 111 : Object.has = function (str: string | number) {
  112. 112 : return this.hasOwnProperty(str);
  113. 113 : };
  114. 114 :
  115. 115 : Object.each = function (callback) {
  116. 116 : for (const key in this) {
  117. 117 : //callback.call(scope, key, this[key]);
  118. 118 : callback.call(this[key]);
  119. 119 : }
  120. 120 : };
  121. 121 :
  122. 122 : Object.isEmpty = function () {
  123. 123 : return this.length === 0;
  124. 124 : };
  125. 125 :
  126. 126 : Object.replaceKeyFrom = function (anotherObj) {
  127. 127 : return Object.entries(this).reduce((op, [key, value]) => {
  128. 128 : const newKey = anotherObj[key];
  129. 129 : op[newKey || key] = value;
  130. 130 : return op;
  131. 131 : }, {});
  132. 132 : /*if (typeof anotherObj == 'object') {
  133. 133 : for (const key in anotherObj) {
  134. 134 : if (Object.prototype.hasOwnProperty.call(anotherObj, key)) {
  135. 135 : const element = anotherObj[key];
  136. 136 : def[key] = element;
  137. 137 : }
  138. 138 : }
  139. 139 : }*/
  140. 140 : };
  141. 141 :
  142. 142 : Object.prototype.merge = function (this: Record<any, unknown>, ...others) {
  143. 143 : const hasReadOnlyProp = Object.keys(this).some((property) => {
  144. 144 : return isObjectWritable(this, property);
  145. 145 : });
  146. 146 : if (!hasReadOnlyProp) return mergeDeep(this, ...others);
  147. 147 : return Object.assign({ ...this }, ...others);
  148. 148 : };
  149. 149 :
  150. 150 : /**
  151. 151 : * is Object Writable?
  152. 152 : * @param obj
  153. 153 : * @param key
  154. 154 : * @returns
  155. 155 : */
  156. 156 : function isObjectWritable<T extends Record<any, unknown>>(obj: T, key: keyof T) {
  157. 157 : const desc = Object.getOwnPropertyDescriptor(obj, key) || {};
  158. 158 : return Boolean(desc.writable);
  159. 159 : }
  160. 160 : __global.isObjectWritable = isObjectWritable;
  161. 161 :
  162. 162 : /**
  163. 163 : * Join object to separated string
  164. 164 : * * [].join() equivalent
  165. 165 : * @param obj Object
  166. 166 : * @param separator default comma(,)
  167. 167 : * @returns Joined string
  168. 168 : */
  169. 169 : function object_join(obj: Record<any, unknown>, separator = ',') {
  170. 170 : return Object.keys(obj)
  171. 171 : .map(function (k) {
  172. 172 : return obj[k];
  173. 173 : })
  174. 174 : .join(separator);
  175. 175 : }
  176. 176 : __global.object_join = object_join;
  177. 177 :
  178. 178 : /**
  179. 179 : * Simple object check.
  180. 180 : * @param item
  181. 181 : * @returns
  182. 182 : * @example
  183. 183 : * ```js
  184. 184 : * console.log(isObject({a:'a'})); // true
  185. 185 : * console.log(isObject(['a','b'])); // false
  186. 186 : * ```
  187. 187 : */
  188. 188 : function isObject(item: any): boolean {
  189. 189 : return item && typeof item === 'object' && !Array.isArray(item);
  190. 190 : }
  191. 191 : __global.isObject = isObject;
  192. 192 :
  193. 193 : /**
  194. 194 : * Deep merge two objects.
  195. 195 : * @param target
  196. 196 : * @param ...sources
  197. 197 : * @see {@link https://bit.ly/3v1vlXu}
  198. 198 : */
  199. 199 : function mergeDeep(target: Record<any, any>, ...sources: Record<any, any>[]) {
  200. 200 : if (!sources.length) return target;
  201. 201 : const source = sources.shift();
  202. 202 :
  203. 203 : if (isObject(target) && isObject(source)) {
  204. 204 : for (const key in source) {
  205. 205 : if (isObject(source[key])) {
  206. 206 : if (!target[key]) Object.assign(target, { [key]: {} });
  207. 207 : mergeDeep(target[key], <any>source[key]);
  208. 208 : } else {
  209. 209 : // @fixme writable property
  210. 210 : Object.assign(target, { [key]: source[key] });
  211. 211 : // @fixme readonly property
  212. 212 : //target = { ...target, [key]: source[key] };
  213. 213 : }
  214. 214 : }
  215. 215 : }
  216. 216 :
  217. 217 : return mergeDeep(target, ...sources);
  218. 218 : }
  219. 219 : __global.mergeDeep = mergeDeep;