danholibraryjs 1.10.0 → 2.0.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 (158) hide show
  1. package/dist/Classes/DanhoLogger.d.ts +23 -0
  2. package/dist/Classes/DanhoLogger.js +65 -0
  3. package/dist/Classes/Events/EventEmitter.d.ts +1 -1
  4. package/dist/Classes/Events/EventEmitter.js +1 -1
  5. package/dist/Classes/Time/Date.d.ts +1 -0
  6. package/dist/Classes/Time/Date.js +4 -1
  7. package/dist/Classes/Time/Time.d.ts +5 -4
  8. package/dist/Classes/Time/Time.js +7 -4
  9. package/dist/Classes/index.d.ts +1 -0
  10. package/dist/Classes/index.js +1 -0
  11. package/dist/Classes/store.d.ts +5 -9
  12. package/dist/Extensions/Array/array.extension.d.ts +42 -0
  13. package/dist/Extensions/Array/array.extension.js +57 -0
  14. package/dist/Extensions/Array/crud.extension.d.ts +24 -0
  15. package/dist/Extensions/Array/crud.extension.js +28 -0
  16. package/dist/Extensions/Array/index.d.ts +20 -0
  17. package/dist/Extensions/Array/index.js +40 -0
  18. package/dist/Extensions/Array/loop.extension.d.ts +18 -0
  19. package/dist/Extensions/Array/loop.extension.js +23 -0
  20. package/dist/Extensions/Array/random.extension.d.ts +23 -0
  21. package/dist/Extensions/Array/random.extension.js +35 -0
  22. package/dist/Extensions/Array/sort.extension.d.ts +27 -0
  23. package/dist/Extensions/Array/sort.extension.js +31 -0
  24. package/dist/Extensions/Array/string.extension.d.ts +13 -0
  25. package/dist/Extensions/Array/string.extension.js +14 -0
  26. package/dist/Extensions/Array.d.ts +17 -3
  27. package/dist/Extensions/Array.js +0 -12
  28. package/dist/Extensions/Function.d.ts +17 -2
  29. package/dist/Extensions/Function.js +15 -2
  30. package/dist/Extensions/Number.d.ts +13 -0
  31. package/dist/Extensions/Number.js +40 -0
  32. package/dist/Extensions/Object/arrays.extension.d.ts +17 -0
  33. package/dist/Extensions/Object/arrays.extension.js +13 -0
  34. package/dist/Extensions/Object/booleans.extension.d.ts +18 -0
  35. package/dist/Extensions/Object/booleans.extension.js +37 -0
  36. package/dist/Extensions/Object/extracts.extension.d.ts +38 -0
  37. package/dist/Extensions/Object/extracts.extension.js +72 -0
  38. package/dist/Extensions/Object/index.d.ts +8 -47
  39. package/dist/Extensions/Object/index.js +31 -33
  40. package/dist/Extensions/Object/properties.extension.d.ts +6 -0
  41. package/dist/Extensions/Object/properties.extension.js +4 -0
  42. package/dist/Extensions/Object/properties.js +1 -2
  43. package/dist/Extensions/String/case.extension.d.ts +12 -0
  44. package/dist/Extensions/String/case.extension.js +55 -0
  45. package/dist/Extensions/String/index.d.ts +4 -0
  46. package/dist/Extensions/String/index.js +30 -0
  47. package/dist/Extensions/index.d.ts +1 -12
  48. package/dist/Extensions/index.js +1 -9
  49. package/dist/Types/Able.d.ts +16 -0
  50. package/dist/Types/Able.js +2 -0
  51. package/dist/Types/Array.d.ts +6 -0
  52. package/dist/Types/Array.js +2 -0
  53. package/dist/Types/C#.d.ts +8 -0
  54. package/dist/Types/C#.js +2 -0
  55. package/dist/Types/Date.d.ts +1 -1
  56. package/dist/Types/Events.d.ts +2 -2
  57. package/dist/Types/Function.d.ts +5 -0
  58. package/dist/Types/Function.js +2 -0
  59. package/dist/Types/Object.d.ts +4 -0
  60. package/dist/Types/Object.js +2 -0
  61. package/dist/Types/PropertiesWith.d.ts +21 -0
  62. package/dist/Types/String.d.ts +1 -0
  63. package/dist/Types/String.js +2 -0
  64. package/dist/Types/TransformTypes.d.ts +9 -0
  65. package/dist/Types/index.d.ts +6 -28
  66. package/dist/Types/index.js +6 -0
  67. package/dist/Utils/ApiUtil/ApiTypes.d.ts +15 -0
  68. package/dist/Utils/ApiUtil/ApiTypes.js +15 -0
  69. package/dist/Utils/ApiUtil/RequestUtil.d.ts +19 -0
  70. package/dist/Utils/ApiUtil/RequestUtil.js +73 -0
  71. package/dist/Utils/ApiUtil/index.d.ts +20 -0
  72. package/dist/Utils/ApiUtil/index.js +33 -0
  73. package/dist/Utils/ApiUtils/ApiTypes.d.ts +15 -0
  74. package/dist/Utils/ApiUtils/ApiTypes.js +15 -0
  75. package/dist/Utils/ApiUtils/RequestUtil.d.ts +19 -0
  76. package/dist/Utils/ApiUtils/RequestUtil.js +73 -0
  77. package/dist/Utils/ApiUtils/index.d.ts +20 -0
  78. package/dist/Utils/ApiUtils/index.js +33 -0
  79. package/dist/Utils/ColorUtils.d.ts +11 -0
  80. package/dist/Utils/ColorUtils.js +93 -0
  81. package/dist/Utils/FormUtil.d.ts +6 -0
  82. package/dist/Utils/FormUtil.js +35 -0
  83. package/dist/Utils/FormUtils.d.ts +6 -0
  84. package/dist/Utils/FormUtils.js +35 -0
  85. package/dist/Utils/NumberUtils.d.ts +1 -0
  86. package/dist/Utils/NumberUtils.js +7 -0
  87. package/dist/Utils/PatcherUtils.d.ts +6 -0
  88. package/dist/Utils/PatcherUtils.js +80 -0
  89. package/dist/Utils/StringUtils.d.ts +3 -0
  90. package/dist/Utils/StringUtils.js +47 -0
  91. package/dist/Utils/TimeUtils/debounce.util.d.ts +22 -0
  92. package/dist/Utils/TimeUtils/debounce.util.js +78 -0
  93. package/dist/Utils/TimeUtils/functions.util.d.ts +4 -0
  94. package/dist/Utils/TimeUtils/functions.util.js +21 -0
  95. package/dist/Utils/TimeUtils/index.d.ts +15 -0
  96. package/dist/Utils/TimeUtils/index.js +34 -0
  97. package/dist/Utils/TimeUtils/throttle.util.d.ts +15 -0
  98. package/dist/Utils/TimeUtils/throttle.util.js +43 -0
  99. package/dist/Utils/index.d.ts +7 -0
  100. package/dist/Utils/index.js +23 -0
  101. package/package.json +4 -2
  102. package/src/Classes/DanhoLogger.ts +78 -0
  103. package/src/Classes/Events/Event.ts +96 -96
  104. package/src/Classes/Events/EventCollection.ts +90 -90
  105. package/src/Classes/Events/EventEmitter.ts +68 -68
  106. package/src/Classes/Time/Date.ts +219 -216
  107. package/src/Classes/Time/Time.ts +109 -104
  108. package/src/Classes/Time/TimeSpan.ts +171 -171
  109. package/src/Classes/index.ts +1 -0
  110. package/src/Classes/store.ts +22 -22
  111. package/src/Extensions/Array/array.extension.ts +103 -0
  112. package/src/Extensions/Array/crud.extension.ts +46 -0
  113. package/src/Extensions/Array/index.ts +15 -0
  114. package/src/Extensions/Array/loop.extension.ts +38 -0
  115. package/src/Extensions/Array/random.extension.ts +56 -0
  116. package/src/Extensions/Array/sort.extension.ts +52 -0
  117. package/src/Extensions/Array/string.extension.ts +22 -0
  118. package/src/Extensions/Document.ts +39 -39
  119. package/src/Extensions/Function.ts +37 -10
  120. package/src/Extensions/Map.ts +56 -56
  121. package/src/Extensions/Number.ts +50 -0
  122. package/src/Extensions/Object/arrays.extension.ts +27 -0
  123. package/src/Extensions/Object/booleans.extension.ts +46 -0
  124. package/src/Extensions/Object/extracts.extension.ts +102 -0
  125. package/src/Extensions/Object/index.ts +9 -80
  126. package/src/Extensions/Object/properties.extension.ts +11 -0
  127. package/src/Extensions/Object/properties.ts +35 -36
  128. package/src/Extensions/String/case.extension.ts +95 -0
  129. package/src/Extensions/String/index.ts +5 -0
  130. package/src/Extensions/index.ts +2 -20
  131. package/src/Interfaces/ElementOptions.ts +7 -7
  132. package/src/Interfaces/IReplacement.ts +2 -2
  133. package/src/Types/Able.ts +22 -0
  134. package/src/Types/Array.ts +7 -0
  135. package/src/Types/C#.ts +9 -0
  136. package/src/Types/Date.ts +1 -1
  137. package/src/Types/Events.ts +12 -12
  138. package/src/Types/Function.ts +10 -0
  139. package/src/Types/Object.ts +4 -0
  140. package/src/Types/PropertiesWith.ts +35 -4
  141. package/src/Types/String.ts +1 -0
  142. package/src/Types/TransformTypes.ts +23 -5
  143. package/src/Types/index.ts +7 -41
  144. package/src/Utils/ApiUtils/ApiTypes.ts +43 -0
  145. package/src/Utils/ApiUtils/RequestUtil.ts +87 -0
  146. package/src/Utils/ApiUtils/index.ts +39 -0
  147. package/src/Utils/ColorUtils.ts +102 -0
  148. package/src/Utils/FormUtils.ts +33 -0
  149. package/src/Utils/NumberUtils.ts +3 -0
  150. package/src/Utils/PatcherUtils.ts +111 -0
  151. package/src/Utils/StringUtils.ts +44 -0
  152. package/src/Utils/TimeUtils/debounce.util.ts +85 -0
  153. package/src/Utils/TimeUtils/functions.util.ts +18 -0
  154. package/src/Utils/TimeUtils/index.ts +9 -0
  155. package/src/Utils/TimeUtils/throttle.util.ts +44 -0
  156. package/src/Utils/index.ts +8 -0
  157. package/src/Extensions/Array.ts +0 -95
  158. package/src/Extensions/String.ts +0 -54
@@ -1,88 +1,88 @@
1
1
  declare global {
2
- interface Map<K, V> {
3
- /**
4
- * Converts into Array<[Key, Value]>
5
- */
6
- array(): Array<[K, V]>
7
- /**
8
- * Maps values into new types of generics
9
- * @param callback Callbacking function to map values
10
- */
11
- map<EK, EV>(callback: (value: V, key: K, index: number, self: this) => [EK, EV]): Map<EK, EV>
12
- /**
13
- * Returns array of "accepted" values. Criteria defined in callback param
14
- * @param callback Callbacking function to filter away unwanted values
15
- */
16
- filter(callback: (value: V, key: K, index: number, self: this) => boolean): Map<K, V>
17
- /**
18
- * Returns array of keys
19
- */
20
- keyArr(): Array<K>
21
- /**
22
- * Returns array of values
23
- */
24
- valueArr(): Array<V>
25
- /**
26
- * Returns first [key, value] match to callback param. Returns undefined if nothing found
27
- * @param callback Callbacking function to find KeyValuePair
28
- */
29
- find(callback: (value: V, key: K, index: number, self: this) => boolean): [K, V] | undefined
30
- /**
31
- * Whether or not map includes a value. Returns true if it does, false if not ¯\_(ツ)_/¯
32
- * @param value Value that may be includded in map
33
- * @param fromIndex Start looking for value from specific index+. Default: 0
34
- */
35
- includes(value: V, fromIndex?: number): boolean
36
- }
2
+ interface Map<K, V> {
3
+ /**
4
+ * Converts into Array<[Key, Value]>
5
+ */
6
+ array(): Array<[K, V]>;
7
+ /**
8
+ * Maps values into new types of generics
9
+ * @param callback Callbacking function to map values
10
+ */
11
+ map<EK, EV>(callback: (value: V, key: K, index: number, self: this) => [EK, EV]): Map<EK, EV>;
12
+ /**
13
+ * Returns array of "accepted" values. Criteria defined in callback param
14
+ * @param callback Callbacking function to filter away unwanted values
15
+ */
16
+ filter(callback: (value: V, key: K, index: number, self: this) => boolean): Map<K, V>;
17
+ /**
18
+ * Returns array of keys
19
+ */
20
+ keyArr(): Array<K>;
21
+ /**
22
+ * Returns array of values
23
+ */
24
+ valueArr(): Array<V>;
25
+ /**
26
+ * Returns first [key, value] match to callback param. Returns undefined if nothing found
27
+ * @param callback Callbacking function to find KeyValuePair
28
+ */
29
+ find(callback: (value: V, key: K, index: number, self: this) => boolean): [K, V] | undefined;
30
+ /**
31
+ * Whether or not map includes a value. Returns true if it does, false if not ¯\_(ツ)_/¯
32
+ * @param value Value that may be includded in map
33
+ * @param fromIndex Start looking for value from specific index+. Default: 0
34
+ */
35
+ includes(value: V, fromIndex?: number): boolean;
36
+ }
37
37
  }
38
38
 
39
39
  function array<K, V>(this: Map<K, V>): Array<[K, V]> {
40
- let result = new Array<[K, V]>();
41
- for (const kvp of this) {
42
- result.push(kvp);
43
- }
44
- return result;
40
+ let result = new Array<[K, V]>();
41
+ for (const kvp of this) {
42
+ result.push(kvp);
43
+ }
44
+ return result;
45
45
  }
46
46
  Map.prototype.array = array;
47
47
 
48
48
  function map<K, V, EK, EV>(this: Map<K, V>, callback: (value: V, key: K, index: number, map: Map<K, V>) => [EK, EV]): Map<EK, EV> {
49
- return this.array()
50
- .map(([k, v], i) => callback(v, k, i, this))
51
- .reduce((map, [key, value]) =>
52
- map.set(key, value),
53
- new Map<EK, EV>())
49
+ return this.array()
50
+ .map(([k, v], i) => callback(v, k, i, this))
51
+ .reduce((map, [key, value]) =>
52
+ map.set(key, value),
53
+ new Map<EK, EV>());
54
54
  }
55
55
  Map.prototype.map = map;
56
56
 
57
57
  function filter<K, V>(this: Map<K, V>, callback: (value: V, key: K, index: number, map: Map<K, V>) => boolean): Map<K, V> {
58
- return this.array()
59
- .filter(([k, v], i) => callback(v, k, i, this))
60
- .reduce((map, [key, value]) =>
61
- map.set(key, value),
62
- new Map<K, V>())
58
+ return this.array()
59
+ .filter(([k, v], i) => callback(v, k, i, this))
60
+ .reduce((map, [key, value]) =>
61
+ map.set(key, value),
62
+ new Map<K, V>());
63
63
  }
64
64
  Map.prototype.filter = filter;
65
65
 
66
66
  function keyArr<K, V>(this: Map<K, V>): Array<K> {
67
- return this.array().map(([k]) => k);
67
+ return this.array().map(([k]) => k);
68
68
  }
69
69
  Map.prototype.keyArr = keyArr;
70
70
 
71
71
  function valueArr<K, V>(this: Map<K, V>): Array<V> {
72
- return this.array().map(([_, v]) => v);
72
+ return this.array().map(([_, v]) => v);
73
73
  }
74
74
  Map.prototype.valueArr = valueArr;
75
75
 
76
76
  function find<K, V>(this: Map<K, V>, callback: (value: V, key: K, index: number, map: Map<K, V>) => boolean) {
77
- return this.array().find(([k, v], i) => callback(v, k, i, this));
77
+ return this.array().find(([k, v], i) => callback(v, k, i, this));
78
78
  }
79
79
  Map.prototype.find = find;
80
80
 
81
81
  function includes<K, V>(this: Map<K, V>, item: V, fromIndex?: number) {
82
- return this.valueArr().includes(item, fromIndex);
82
+ return this.valueArr().includes(item, fromIndex);
83
83
  }
84
84
  Map.prototype.includes = includes;
85
85
 
86
86
  export const MapExtensions = {
87
- array, map, filter, keyArr, valueArr, find, includes
88
- }
87
+ array, map, filter, keyArr, valueArr, find, includes
88
+ };
@@ -0,0 +1,50 @@
1
+ type Separators = {
2
+ thousand: string;
3
+ decimal: string;
4
+ }
5
+
6
+ declare global {
7
+ interface Number {
8
+ toSeparationString(separators: Partial<Separators>): string;
9
+ toRomanNumeral(): string;
10
+ }
11
+ }
12
+
13
+ export function toSeparationString(this: number, separators: Partial<Separators>): string {
14
+ const { thousand = '.', decimal = '.' } = separators;
15
+ const [integerPart, decimalPart] = this.toString().split('.');
16
+ const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousand);
17
+ return decimalPart ? `${formattedInteger}${decimal}${decimalPart}` : formattedInteger;
18
+ }
19
+ Number.prototype.toSeparationString = toSeparationString;
20
+
21
+ export function toRomanNumeral(this: number): string {
22
+ if (this <= 0 || this >= 4000) throw new RangeError('Number must be between 1 and 3999 to convert to Roman numeral');
23
+
24
+ const numeralMap: [number, string][] = [
25
+ [1000, 'M'],
26
+ [900, 'CM'],
27
+ [500, 'D'],
28
+ [400, 'CD'],
29
+ [100, 'C'],
30
+ [90, 'XC'],
31
+ [50, 'L'],
32
+ [40, 'XL'],
33
+ [10, 'X'],
34
+ [9, 'IX'],
35
+ [5, 'V'],
36
+ [4, 'IV'],
37
+ [1, 'I']
38
+ ];
39
+
40
+ let value = this;
41
+ return numeralMap.reduce((acc, [numeralValue, numeral]) => {
42
+ while (value >= numeralValue) {
43
+ acc += numeral;
44
+ value -= numeralValue;
45
+ }
46
+
47
+ return acc;
48
+ }, '');
49
+ }
50
+ Number.prototype.toRomanNumeral = toRomanNumeral;
@@ -0,0 +1,27 @@
1
+ import { ValueOf } from "../../Types";
2
+
3
+ declare global {
4
+ interface ObjectConstructor {
5
+ /**
6
+ * Destructures object into array of [property, value]
7
+ * @param from Object to destruct
8
+ */
9
+ array<From extends {} = {}>(from: From): Array<[keyof From, ValueOf<From>]>;
10
+
11
+ /**
12
+ * Destructures object into array of property keys
13
+ * @param from Object to destruct
14
+ */
15
+ keysOf<From extends {} = {}>(from: From): Array<keyof From>;
16
+ }
17
+ }
18
+
19
+ export function array<From extends {} = {}>(this: object, from: From): Array<[keyof From, ValueOf<From>]> {
20
+ return Object.entries(from) as Array<[keyof From, ValueOf<From>]>;
21
+ }
22
+ Object.array = array;
23
+
24
+ export function keysOf<From extends {} = {}>(this: object, from: From): Array<keyof From> {
25
+ return Object.keys(from) as Array<keyof From>;
26
+ }
27
+ Object.keysOf = keysOf;
@@ -0,0 +1,46 @@
1
+ declare global {
2
+ interface ObjectConstructor {
3
+ /**
4
+ * Returns true if objects are equal by comparing their properties and values recursively. Does not compare functions.
5
+ * @param a First object
6
+ * @param b Second object
7
+ * @returns true if objects are equal, false otherwise
8
+ */
9
+ areEqual<T extends object | null>(a?: T, b?: T): boolean;
10
+
11
+ /**
12
+ * Returns true if object is empty
13
+ * @param obj Object to check
14
+ */
15
+ isNullOrUndefined(obj: any): obj is null | undefined;
16
+ }
17
+ }
18
+
19
+ export function areEqual<T extends object | null>(a?: T, b?: T): boolean {
20
+ if (a === b) return true;
21
+ if (typeof a !== typeof b) return false;
22
+ if (isNullOrUndefined(a) && isNullOrUndefined(b)) return true;
23
+
24
+ const keysA = Object.keys(a ?? {});
25
+ const keysB = Object.keys(b ?? {});
26
+ if (keysA.length !== keysB.length) return false;
27
+
28
+ try {
29
+ const jsonA = JSON.stringify(a);
30
+ const jsonB = JSON.stringify(b);
31
+ if (jsonA === jsonB) return true;
32
+ } catch {
33
+ for (const key of keysA) {
34
+ if (!keysB.includes(key)) return false;
35
+ if (!areEqual((a as any)[key], (b as any)[key])) return false;
36
+ }
37
+ }
38
+
39
+ return true;
40
+ }
41
+ Object.areEqual = areEqual;
42
+
43
+ export function isNullOrUndefined(obj: any): obj is null | undefined {
44
+ return obj === null || obj === undefined;
45
+ }
46
+ Object.isNullOrUndefined = isNullOrUndefined;
@@ -0,0 +1,102 @@
1
+ declare global {
2
+ interface ObjectConstructor {
3
+ /**
4
+ * Get a copy of object without specified properties or partial versions.
5
+ * @param from Object to extract properties from
6
+ * @param props Properties to extract/Omit
7
+ */
8
+ omit<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Omit<From, Props>;
9
+
10
+ /**
11
+ * Get a copy of object with only specified properties or partial versions.
12
+ * @param from Object to extract properties from
13
+ * @param props Properties to extract/Pick
14
+ */
15
+ pick<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Pick<From, Props>;
16
+
17
+ /**
18
+ * Receive an object with properties that are not in union of source and target objects
19
+ * @param source Source object
20
+ * @param target Target object
21
+ * @param exclude Properties to exclude from difference
22
+ * @returns Object with properties that are not in union of source and target objects, excluding specified properties
23
+ */
24
+ difference<T extends object>(source: T, target: T, ...exclude: Array<keyof T>): Omit<T, keyof T>;
25
+
26
+ /**
27
+ * Deeply combines objects, with later objects in parameters taking precedence over earlier ones. Does not combine arrays.
28
+ * @param objects Objects to combine
29
+ * @returns Combined object
30
+ */
31
+ combine<T extends Record<string, any | undefined>>(...objects: Array<Partial<T> | undefined>): T;
32
+ }
33
+ }
34
+
35
+
36
+ export function omit<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Omit<From, Props> {
37
+ return props.reduce((result, prop) => {
38
+ if (typeof prop === "object") {
39
+ const keys = Object.keysOf(prop);
40
+ keys.forEach(key => delete (result as Partial<From>)[key]);
41
+ } else {
42
+ delete (result as Partial<From>)[prop];
43
+ }
44
+
45
+ return result;
46
+ }, { ...from } as Omit<From, Props>);
47
+ }
48
+ Object.omit = omit;
49
+
50
+ export function pick<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Pick<From, Props> {
51
+ return props.reduce((result, prop) => {
52
+ if (typeof prop === "object") {
53
+ const keys = Object.keysOf(prop);
54
+ keys.forEach(key => (result as Partial<From>)[key] = from[key]);
55
+ } else {
56
+ (result as Partial<From>)[prop] = from[prop];
57
+ }
58
+ return result;
59
+ }, {} as Pick<From, Props>);
60
+ }
61
+ Object.pick = pick;
62
+
63
+ export function difference<T extends object>(source: T, target: T, ...exclude: Array<keyof T>): Omit<T, keyof T> {
64
+ const diffKeys = new Set([...Object.keysOf(source), ...Object.keysOf(target)]);
65
+ exclude?.forEach(key => diffKeys.delete(key));
66
+
67
+ return [...diffKeys.values()].reduce((acc, key, i, arr) => {
68
+ const sourceValue = JSON.stringify(source[key]);
69
+ const targetValue = JSON.stringify(target[key]);
70
+ if (sourceValue !== targetValue) acc[key] = target[key];
71
+ return acc;
72
+ }, {} as T);
73
+ }
74
+ Object.difference = difference;
75
+
76
+ type Combinable<T extends Record<string, any>> = {
77
+ [key in keyof T]?: T[key] extends Record<string, any> ? Combinable<T[key]> : T[key];
78
+ };
79
+
80
+ export function combine<T extends Record<string, any | undefined>>(...objects: Array<Combinable<T> | undefined>): T {
81
+ return objects.reduce((acc: T, obj) => {
82
+ if (!obj) return acc;
83
+
84
+ for (const key in obj) {
85
+ if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
86
+ try {
87
+ acc[key] = combine(acc[key] as T, obj[key] as T) as any;
88
+ } catch (err) {
89
+ const error = err as Error;
90
+ if (error.message.includes('Maximum call stack size exceeded')) {
91
+ acc[key] = obj[key] as any;
92
+ } else throw err;
93
+ }
94
+ } else if (obj[key] !== undefined && obj[key] !== null && obj[key] !== '') {
95
+ // @ts-ignore
96
+ (acc[key] as Combinable<T>) = obj[key];
97
+ }
98
+ }
99
+ return acc;
100
+ }, {} as T) as T;
101
+ }
102
+ Object.combine = combine;
@@ -1,82 +1,11 @@
1
- import { ValueOf } from "../../Types";
2
- import { Properties, properties } from "./properties";
3
-
4
- declare global {
5
- interface ObjectConstructor {
6
- /**
7
- * Destructures object into array of [property, value]
8
- * @param from Object to destruct
9
- */
10
- array<From extends {} = {}>(from: From): Array<[keyof From, ValueOf<From>]>
11
-
12
- /**
13
- * Omits properties from object, but for some reason the correct term is "extract"
14
- * @param from Object to extract properties from
15
- * @param props Properties to extract/Omit
16
- */
17
- extract<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Omit<From, Props>
18
-
19
- /**
20
- * Pick properties from object, but for some reason the correct term is "exclude"
21
- * @param from Object to exclude properties from
22
- * @param props Properties to exclude/pick
23
- */
24
- exclude<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Pick<From, Props>
25
-
26
- /**
27
- * Returns true if object is empty
28
- * @param obj Object to check
29
- */
30
- isNullOrUndefined(obj: any): obj is null | undefined
31
-
32
- /**
33
- * Destructures object into array of property keys
34
- * @param from Object to destruct
35
- */
36
- keysOf<From extends {} = {}>(from: From): Array<keyof From>
37
-
38
- omit<From extends {}, Exclude extends keyof From>(from: From, ...exclude: Exclude[]): Omit<From, Exclude>;
39
-
40
- properties: Properties
41
- }
42
- }
43
-
44
- function array<From extends {} = {}>(this: object, from: From): Array<[keyof From, ValueOf<From>]> {
45
- return Object.keysOf(from).map(prop => [prop, from[prop]]) as Array<[keyof From, ValueOf<From>]>;
46
- }
47
- Object.array = array;
48
-
49
- function extract<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Omit<From, Props> {
50
- // If props are Array<keyof From>, Array<Partial<From>>, or Array<keyof From | Partial<From>>, ensure _props as Array<keyof From>
51
- const _props = props.map(prop => typeof prop === "object" ? Object.keysOf(prop) : prop).flat();
52
- _props.forEach(prop => delete from[prop as keyof From]);
53
- return from;
54
- }
55
- Object.extract = extract;
56
-
57
- function exclude<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Pick<From, Props> {
58
- // If props are Array<keyof From>, Array<Partial<From>>, or Array<keyof From | Partial<From>>, ensure _props as Array<keyof From>
59
- const _props = props.map(prop => typeof prop === "object" ? Object.keysOf(prop) : prop).flat();
60
- return Object.keysOf(from).reduce((result, prop) => {
61
- if (_props.includes(prop as Props)) delete result[prop];
62
- return result;
63
- }, from);
64
- }
65
- Object.exclude = exclude;
66
-
67
- function isNullOrUndefined(obj: any): obj is null | undefined {
68
- return obj === null || obj === undefined;
69
- }
70
- Object.isNullOrUndefined = isNullOrUndefined;
71
-
72
- function keysOf<From extends {} = {}>(this: object, from: From): Array<keyof From> {
73
- return Object.keys(from) as Array<keyof From>;
74
- }
75
- Object.keysOf = keysOf;
76
-
77
- Object.properties = properties;
1
+ import * as Array from './arrays.extension';
2
+ import * as Booleans from './booleans.extension';
3
+ import * as Extracts from './extracts.extension';
4
+ import * as Properties from './properties.extension';
78
5
 
79
6
  export const ObjectExtensions = {
80
- properties,
81
- array, extract, exclude, isNullOrUndefined, keysOf,
82
- };
7
+ ...Array,
8
+ ...Booleans,
9
+ ...Extracts,
10
+ ...Properties
11
+ };
@@ -0,0 +1,11 @@
1
+ import { Properties, properties } from "./properties";
2
+
3
+ declare global {
4
+ interface ObjectConstructor {
5
+ properties: Properties;
6
+ }
7
+ }
8
+
9
+
10
+
11
+ Object.properties = properties;
@@ -1,22 +1,21 @@
1
1
  import { PropertiesWith, If } from '../../Types';
2
- import { StringExtensions } from '../String';
3
2
 
4
3
  type PrimitiveMap = {
5
- string: string;
6
- number: number;
7
- boolean: boolean;
8
- undefined: undefined;
9
- null: null;
10
- object: object;
11
- function: Function;
12
- any: any;
13
- Date: Date;
14
- RegExp: RegExp;
15
- Promise: Promise<any>;
16
- Array: Array<any>;
17
- Map: Map<any, any>;
18
- Set: Set<any>;
19
- }
4
+ string: string;
5
+ number: number;
6
+ boolean: boolean;
7
+ undefined: undefined;
8
+ null: null;
9
+ object: object;
10
+ function: Function;
11
+ any: any;
12
+ Date: Date;
13
+ RegExp: RegExp;
14
+ Promise: Promise<any>;
15
+ Array: Array<any>;
16
+ Map: Map<any, any>;
17
+ Set: Set<any>;
18
+ };
20
19
 
21
20
  /**
22
21
  * Object with getPrimitiveTypes<Source, AllowFunctions extends boolean>(
@@ -25,27 +24,27 @@ type PrimitiveMap = {
25
24
  * ): Object with properties from source that matches primitive type
26
25
  */
27
26
  export type Properties = {
28
- [Key in keyof PrimitiveMap as `get${Capitalize<Key>}s`]:
29
- <Source extends {}, AllowFunctions extends boolean = false>(source: Source, withFunctions?: AllowFunctions) =>
30
- If<AllowFunctions,
31
- PropertiesWith<PrimitiveMap[Key] | ((...args: any[]) => PrimitiveMap[Key]), Source>,
32
- PropertiesWith<PrimitiveMap[Key], Source>
33
- >
34
- }
27
+ [Key in keyof PrimitiveMap as `get${Capitalize<Key>}s`]:
28
+ <Source extends {}, AllowFunctions extends boolean = false>(source: Source, withFunctions?: AllowFunctions) =>
29
+ If<AllowFunctions,
30
+ PropertiesWith<PrimitiveMap[Key] | ((...args: any[]) => PrimitiveMap[Key]), Source>,
31
+ PropertiesWith<PrimitiveMap[Key], Source>
32
+ >
33
+ };
35
34
 
36
35
  export const properties: Properties = [
37
- 'string', 'number', 'boolean', 'undefined', 'null',
38
- 'object', 'function', 'any',
39
- 'Date', 'RegExp', 'Promise', 'Array', 'Map', 'Set'
36
+ 'string', 'number', 'boolean', 'undefined', 'null',
37
+ 'object', 'function', 'any',
38
+ 'Date', 'RegExp', 'Promise', 'Array', 'Map', 'Set'
40
39
  ].reduce((result, primitive) => {
41
- result[`get${StringExtensions.toPascalCase.bind(primitive)()}s` as keyof Properties] = function<Source extends {}, AllowFunctions extends boolean = false>(source: Source, withFunctions: AllowFunctions = false as AllowFunctions) {
42
- return Object.keysOf<Source>(source).reduce((result, key) => {
43
- if ((source[key] as any).constructor.name === primitive ||
44
- (withFunctions && typeof source[key] === 'function' && source[key] as any).constructor.name === primitive) {
45
- result[key] = source[key];
46
- }
47
- return result;
48
- }, {} as any);
49
- }
50
- return result;
40
+ result[`get${primitive.convertCase('camel', 'pascal')}s` as keyof Properties] = function <Source extends {}, AllowFunctions extends boolean = false>(source: Source, withFunctions: AllowFunctions = false as AllowFunctions) {
41
+ return Object.keysOf<Source>(source).reduce((result, key) => {
42
+ if ((source[key] as any).constructor.name === primitive ||
43
+ (withFunctions && typeof source[key] === 'function' && source[key] as any).constructor.name === primitive) {
44
+ result[key] = source[key];
45
+ }
46
+ return result;
47
+ }, {} as any);
48
+ };
49
+ return result;
51
50
  }, {} as Properties);
@@ -0,0 +1,95 @@
1
+ export type Case = 'camel' | 'pascal' | 'snake' | 'kebab' | 'lower' | 'upper';
2
+
3
+ declare global {
4
+ interface String {
5
+ /**
6
+ * Converts string from one case to another.
7
+ * @param from Case to convert from
8
+ * @param to Cases to convert to, in order. If multiple cases are provided, they will be applied in order
9
+ */
10
+ convertCase<To extends Array<Case>, Return extends To extends [...Array<Case>, infer To] ? To : Case>(
11
+ from: Case,
12
+ ...to: To
13
+ ): (
14
+ Return extends 'upper' ? Uppercase<string>
15
+ : Return extends 'lower' ? Lowercase<string>
16
+ : Return extends 'pascal' ? Capitalize<string>
17
+ : Return extends 'camel' ? Uncapitalize<string>
18
+ : string
19
+ );
20
+ }
21
+ }
22
+
23
+ const caseMap: Record<Case, Record<Case, (str: string) => string>> = {
24
+ camel: {
25
+ camel: (str) => str,
26
+ lower: (str: string) => str.toLowerCase(),
27
+ upper: (str: string) => str.toUpperCase(),
28
+
29
+ pascal: (str: string) => str[0].toUpperCase() + str.replace(/([A-Z])/g, (match) => ` ${match}`).slice(1),
30
+ snake: (str: string) => str.replace(/([A-Z])/g, (match) => `_${match.toLowerCase()}`),
31
+ kebab: (str: string) => str.replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`),
32
+ },
33
+ pascal: {
34
+ pascal: (str) => str,
35
+ lower: (str: string) => str.toLowerCase(),
36
+ upper: (str: string) => str.toUpperCase(),
37
+
38
+ camel: (str: string) => str[0].toLowerCase() + str.slice(1),
39
+ snake: (str: string) => str.replace(/([A-Z])/g, (match) => `_${match.toLowerCase()}`),
40
+ kebab: (str: string) => str.replace(/([A-Z])/g, (match) => `-${match.toLowerCase()}`),
41
+ },
42
+ snake: {
43
+ snake: (str) => str,
44
+ lower: (str: string) => str.toLowerCase(),
45
+ upper: (str: string) => str.toUpperCase(),
46
+
47
+ camel: (str: string) => str.replace(/(_\w)/g, (match) => match[1].toUpperCase()),
48
+ pascal: (str: string) => str[0].toUpperCase() + str.substring(1, str.length).replace(/(_\w)/g, (match) => match[1].toUpperCase()),
49
+ kebab: (str: string) => str.replace(/_/g, '-'),
50
+ },
51
+ kebab: {
52
+ kebab: (str) => str,
53
+ lower: (str: string) => str.toLowerCase(),
54
+ upper: (str: string) => str.toUpperCase(),
55
+
56
+ camel: (str: string) => str.replace(/(-\w)/g, (match) => match[1].toUpperCase()),
57
+ pascal: (str: string) => str[0].toUpperCase() + str.substring(1, str.length).replace(/(-\w)/g, (match) => match[1].toUpperCase()),
58
+ snake: (str: string) => str.replace(/-/g, '_'),
59
+ },
60
+
61
+ lower: {
62
+ lower: (str) => str.toLowerCase(),
63
+ upper: (str: string) => str.toUpperCase(),
64
+
65
+ camel: (str: string) => str,
66
+ pascal: (str: string) => str[0].toUpperCase() + str.slice(1),
67
+ snake: (str: string) => str,
68
+ kebab: (str: string) => str,
69
+ },
70
+
71
+ upper: {
72
+ upper: (str) => str.toUpperCase(),
73
+ camel: (str: string) => str[0].toLowerCase() + str.slice(1),
74
+ pascal: (str: string) => str[0].toUpperCase() + str.toLowerCase().slice(1),
75
+ snake: (str: string) => str.replace(/ /g, '_'),
76
+ kebab: (str: string) => str.replace(/ /g, '-'),
77
+ lower: (str: string) => str.toLowerCase(),
78
+ }
79
+ };
80
+
81
+ export const convertCase = <
82
+ TValue extends string,
83
+ To extends Array<Case>,
84
+ Return extends To extends [...Array<Case>, infer To] ? To : Case
85
+ >(
86
+ value: TValue,
87
+ from: Case,
88
+ ...to: To
89
+ ): (
90
+ Return extends 'upper' ? Uppercase<TValue>
91
+ : Return extends 'lower' ? Lowercase<TValue>
92
+ : Return extends 'pascal' ? Capitalize<TValue>
93
+ : Return extends 'camel' ? Uncapitalize<TValue>
94
+ : string
95
+ ) => to.reduce((str, toCase) => caseMap[from][toCase](str), value as string) as any;
@@ -0,0 +1,5 @@
1
+ import * as Case from './case.extension';
2
+
3
+ export const StringUtils = {
4
+ ...Case,
5
+ }