@etsoo/shared 1.0.75 → 1.0.79

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.
package/README.md CHANGED
@@ -131,6 +131,8 @@ String and other related utilities
131
131
 
132
132
  |Name|Description|
133
133
  |---:|---|
134
+ |charsToNumber|Base64 chars to number|
135
+ |equals|Two values equal|
134
136
  |formatInitial|Format inital character to lower case or upper case|
135
137
  |formatString|Format string with parameters|
136
138
  |getDataChanges|Get data changed fields with input data updated|
@@ -139,7 +141,10 @@ String and other related utilities
139
141
  |mergeFormData|Merge form data to primary one|
140
142
  |mergeClasses|Merge class names|
141
143
  |newGUID|Create a GUID|
144
+ |numberToChars|Number to base64 chars|
142
145
  |objectEqual|Test two objects are equal or not|
146
+ |objectKeys|Get two object's unqiue properties|
147
+ |objectUpdated|Get the new object's updated fields contrast to the previous object|
143
148
  |parseString|Parse string (JSON) to specific type|
144
149
  |setLabels|Set source with new labels|
145
150
  |snakeNameToWord|Snake name to works, 'snake_name' to 'Snake Name'|
@@ -9,7 +9,8 @@ test('Tests for getDataChanges', () => {
9
9
  price: '6.0',
10
10
  amount: '',
11
11
  enabled: true,
12
- value: undefined
12
+ value: undefined,
13
+ ids: [1, 2]
13
14
  };
14
15
  const initData = {
15
16
  id: 1,
@@ -18,7 +19,8 @@ test('Tests for getDataChanges', () => {
18
19
  brand: 'ETSOO',
19
20
  price: 6,
20
21
  amount: 0,
21
- enabled: true
22
+ enabled: true,
23
+ ids: [1, 2]
22
24
  };
23
25
  const fields = Utils.getDataChanges(input, initData);
24
26
  expect(fields).toStrictEqual(['gender', 'brand', 'amount']);
@@ -67,6 +69,13 @@ test('Tests for newGUID', () => {
67
69
  expect(id1.length).toBe(id2.length);
68
70
  });
69
71
 
72
+ test('Tests for numberToChars and charsToNumber', () => {
73
+ const num = 1638777042242;
74
+ const chars = Utils.numberToChars(num);
75
+ expect(chars).toEqual('QmpkdVgv');
76
+ expect(Utils.charsToNumber(chars)).toEqual(num);
77
+ });
78
+
70
79
  test('Tests for removeNonLetters', () => {
71
80
  const input = '1234-5678@abc.';
72
81
  const result = '12345678abc';
@@ -75,17 +84,26 @@ test('Tests for removeNonLetters', () => {
75
84
  });
76
85
 
77
86
  test('Tests for objectEqual', () => {
78
- const obj1 = { a: 1, b: 'abc', c: true, d: null };
79
- const obj2 = { a: '1', b: 'abc', c: true };
87
+ const obj1 = { a: 1, b: 'abc', c: true, d: null, f: [1, 2] };
88
+ const obj2 = { a: '1', b: 'abc', c: true, f: [1, 2] };
80
89
  expect(Utils.objectEqual(obj1, obj2)).toBeFalsy();
81
90
  expect(Utils.objectEqual(obj1, obj2, [], 0)).toBeTruthy();
82
91
  expect(Utils.objectEqual(obj1, obj2, ['a'])).toBeTruthy();
83
92
  expect(Utils.objectEqual(obj1, obj2, ['a'], 2)).toBeFalsy();
84
93
  });
85
94
 
95
+ test('Tests for objectUpdated', () => {
96
+ const objPrev = { a: 1, b: 'abc', c: true, d: null, f: [1, 2] };
97
+ const objNew = { a: 2, b: 'abc', d: new Date(), f: [1, 2, 3] };
98
+ const fields = Utils.objectUpdated(objNew, objPrev, ['d']);
99
+ expect(fields.sort()).toStrictEqual(['a', 'c', 'f']);
100
+ });
101
+
86
102
  test('Tests for parseString', () => {
87
- expect(Utils.parseString('test', '')).toBe('test');
103
+ expect(Utils.parseString<string>('test')).toBe('test');
88
104
  expect(Utils.parseString('true', false)).toBe(true);
105
+ expect(Utils.parseString('', false)).toBeFalsy();
106
+ expect(Utils.parseString<number>(undefined)).toBeUndefined();
89
107
  expect(Utils.parseString('3.14', 0)).toBe(3.14);
90
108
  expect(Utils.parseString('2021/4/13', new Date())).toStrictEqual(
91
109
  new Date('2021/4/13')
@@ -20,7 +20,7 @@ export declare namespace StorageUtils {
20
20
  * @param key Key name
21
21
  * @param defaultValue Default value
22
22
  */
23
- function getLocalData<T>(key: string, defaultValue: T): T;
23
+ function getLocalData<T>(key: string, defaultValue?: T): T | undefined;
24
24
  /**
25
25
  * Get local storage object data
26
26
  * @param key Key name
@@ -30,7 +30,7 @@ export declare namespace StorageUtils {
30
30
  * Get session storage data
31
31
  * @param key Key name
32
32
  */
33
- function getSessionData<T>(key: string, defaultValue: T): T;
33
+ function getSessionData<T>(key: string, defaultValue?: T): T | undefined;
34
34
  /**
35
35
  * Get session storage object data
36
36
  * @param key Key name
@@ -35,6 +35,19 @@ declare global {
35
35
  * Utilities
36
36
  */
37
37
  export declare namespace Utils {
38
+ /**
39
+ * Base64 chars to number
40
+ * @param base64Chars Base64 chars
41
+ * @returns Number
42
+ */
43
+ function charsToNumber(base64Chars: string): number;
44
+ /**
45
+ * Two values equal
46
+ * @param v1 Value 1
47
+ * @param v2 Value 2
48
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
49
+ */
50
+ function equals(v1: unknown, v2: unknown, strict?: number): boolean;
38
51
  /**
39
52
  * Format inital character to lower case or upper case
40
53
  * @param input Input string
@@ -89,6 +102,12 @@ export declare namespace Utils {
89
102
  * Create a GUID
90
103
  */
91
104
  function newGUID(): string;
105
+ /**
106
+ * Number to base64 chars
107
+ * @param num Input number
108
+ * @returns Result
109
+ */
110
+ function numberToChars(num: number): string;
92
111
  /**
93
112
  * Test two objects are equal or not
94
113
  * @param obj1 Object 1
@@ -99,12 +118,30 @@ export declare namespace Utils {
99
118
  */
100
119
  function objectEqual(obj1: {}, obj2: {}, ignoreFields?: string[], strict?: number): boolean;
101
120
  /**
102
- * Parse string (JSON) to specific type
121
+ * Get two object's unqiue properties
122
+ * @param obj1 Object 1
123
+ * @param obj2 Object 2
124
+ * @param ignoreFields Ignored fields
125
+ * @returns Unique properties
126
+ */
127
+ function objectKeys(obj1: {}, obj2: {}, ignoreFields?: string[]): Set<string>;
128
+ /**
129
+ * Get the new object's updated fields contrast to the previous object
130
+ * @param objNew New object
131
+ * @param objPre Previous object
132
+ * @param ignoreFields Ignored fields
133
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
134
+ * @returns Updated fields
135
+ */
136
+ function objectUpdated(objNew: {}, objPrev: {}, ignoreFields?: string[], strict?: number): string[];
137
+ /**
138
+ * Parse string (JSON) to specific type, no type conversion
139
+ * For type conversion, please use DataTypes.convert
103
140
  * @param input Input string
104
141
  * @param defaultValue Default value
105
142
  * @returns Parsed value
106
143
  */
107
- function parseString<T>(input: string | undefined | null, defaultValue: T): T;
144
+ function parseString<T>(input: string | undefined | null, defaultValue?: T): T | undefined;
108
145
  /**
109
146
  * Remove non letters
110
147
  * @param input Input string
package/lib/cjs/Utils.js CHANGED
@@ -29,6 +29,43 @@ String.prototype.removeNonLetters = function () {
29
29
  */
30
30
  var Utils;
31
31
  (function (Utils) {
32
+ /**
33
+ * Base64 chars to number
34
+ * @param base64Chars Base64 chars
35
+ * @returns Number
36
+ */
37
+ function charsToNumber(base64Chars) {
38
+ const chars = typeof Buffer === 'undefined'
39
+ ? [...atob(base64Chars)].map((char) => char.charCodeAt(0))
40
+ : [...Buffer.from(base64Chars, 'base64')];
41
+ return chars.reduce((previousValue, currentValue, currentIndex) => {
42
+ return previousValue + currentValue * Math.pow(128, currentIndex);
43
+ }, 0);
44
+ }
45
+ Utils.charsToNumber = charsToNumber;
46
+ /**
47
+ * Two values equal
48
+ * @param v1 Value 1
49
+ * @param v2 Value 2
50
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
51
+ */
52
+ function equals(v1, v2, strict = 1) {
53
+ // Null and undefined case
54
+ if (v1 == null || v2 == null) {
55
+ if (strict <= 1 && v1 == v2)
56
+ return true;
57
+ return v1 === v2;
58
+ }
59
+ // For array and object
60
+ if (typeof v1 === 'object')
61
+ return JSON.stringify(v1) === JSON.stringify(v2);
62
+ // 1 and '1' case
63
+ if (strict === 0)
64
+ return v1 == v2;
65
+ // Strict equal
66
+ return v1 === v2;
67
+ }
68
+ Utils.equals = equals;
32
69
  /**
33
70
  * Format inital character to lower case or upper case
34
71
  * @param input Input string
@@ -71,7 +108,7 @@ var Utils;
71
108
  }
72
109
  if (initValue != null) {
73
110
  const newValue = DataTypes_1.DataTypes.convert(value, initValue);
74
- if (newValue === initValue) {
111
+ if (Utils.equals(newValue, initValue)) {
75
112
  Reflect.deleteProperty(input, key);
76
113
  return;
77
114
  }
@@ -149,6 +186,27 @@ var Utils;
149
186
  });
150
187
  }
151
188
  Utils.newGUID = newGUID;
189
+ /**
190
+ * Number to base64 chars
191
+ * @param num Input number
192
+ * @returns Result
193
+ */
194
+ function numberToChars(num) {
195
+ const codes = [];
196
+ while (num > 0) {
197
+ const code = num % 128;
198
+ codes.push(code);
199
+ num = (num - code) / 128;
200
+ }
201
+ if (typeof Buffer === 'undefined') {
202
+ return btoa(String.fromCharCode(...codes));
203
+ }
204
+ else {
205
+ const buffer = Buffer.from(codes);
206
+ return buffer.toString('base64');
207
+ }
208
+ }
209
+ Utils.numberToChars = numberToChars;
152
210
  /**
153
211
  * Test two objects are equal or not
154
212
  * @param obj1 Object 1
@@ -158,37 +216,66 @@ var Utils;
158
216
  * @returns Result
159
217
  */
160
218
  function objectEqual(obj1, obj2, ignoreFields = [], strict = 1) {
161
- // Keys
162
- const keys = new Set([
163
- ...Object.keys(obj1).filter((item) => !ignoreFields.includes(item)),
164
- ...Object.keys(obj2).filter((item) => !ignoreFields.includes(item))
165
- ]);
219
+ // Unique keys
220
+ const keys = Utils.objectKeys(obj1, obj2, ignoreFields);
166
221
  for (const key of keys) {
167
222
  // Values
168
223
  const v1 = Reflect.get(obj1, key);
169
224
  const v2 = Reflect.get(obj2, key);
170
- // Null and undefined case
171
- if (v1 == null && v2 == null && strict <= 1)
172
- continue;
173
- // 1 and '1' case
174
- if (strict === 0 && v1 == v2)
175
- continue;
176
- // Strict equal
177
- if (v1 !== v2)
225
+ if (!Utils.equals(v1, v2, strict))
178
226
  return false;
179
227
  }
180
228
  return true;
181
229
  }
182
230
  Utils.objectEqual = objectEqual;
183
231
  /**
184
- * Parse string (JSON) to specific type
232
+ * Get two object's unqiue properties
233
+ * @param obj1 Object 1
234
+ * @param obj2 Object 2
235
+ * @param ignoreFields Ignored fields
236
+ * @returns Unique properties
237
+ */
238
+ function objectKeys(obj1, obj2, ignoreFields = []) {
239
+ // All keys
240
+ const allKeys = [...Object.keys(obj1), ...Object.keys(obj2)].filter((item) => !ignoreFields.includes(item));
241
+ // Unique keys
242
+ return new Set(allKeys);
243
+ }
244
+ Utils.objectKeys = objectKeys;
245
+ /**
246
+ * Get the new object's updated fields contrast to the previous object
247
+ * @param objNew New object
248
+ * @param objPre Previous object
249
+ * @param ignoreFields Ignored fields
250
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
251
+ * @returns Updated fields
252
+ */
253
+ function objectUpdated(objNew, objPrev, ignoreFields = [], strict = 1) {
254
+ // Fields
255
+ const fields = [];
256
+ // Unique keys
257
+ const keys = Utils.objectKeys(objNew, objPrev, ignoreFields);
258
+ for (const key of keys) {
259
+ // Values
260
+ const vNew = Reflect.get(objNew, key);
261
+ const vPrev = Reflect.get(objPrev, key);
262
+ if (!Utils.equals(vNew, vPrev, strict)) {
263
+ fields.push(key);
264
+ }
265
+ }
266
+ return fields;
267
+ }
268
+ Utils.objectUpdated = objectUpdated;
269
+ /**
270
+ * Parse string (JSON) to specific type, no type conversion
271
+ * For type conversion, please use DataTypes.convert
185
272
  * @param input Input string
186
273
  * @param defaultValue Default value
187
274
  * @returns Parsed value
188
275
  */
189
276
  function parseString(input, defaultValue) {
190
- // Undefined case, return default value
191
- if (input == null)
277
+ // Undefined and empty case, return default value
278
+ if (input == null || input === '')
192
279
  return defaultValue;
193
280
  // String
194
281
  if (typeof defaultValue === 'string')
@@ -206,16 +293,11 @@ var Utils;
206
293
  // Return
207
294
  return json;
208
295
  }
209
- catch (e) {
210
- console.log('Utils.parseString error', e);
296
+ catch {
297
+ if (defaultValue == null)
298
+ return input;
211
299
  return defaultValue;
212
300
  }
213
- /*
214
- finally part will still return the boolean value
215
- finally {
216
- return defaultValue
217
- }
218
- */
219
301
  }
220
302
  Utils.parseString = parseString;
221
303
  /**
@@ -20,7 +20,7 @@ export declare namespace StorageUtils {
20
20
  * @param key Key name
21
21
  * @param defaultValue Default value
22
22
  */
23
- function getLocalData<T>(key: string, defaultValue: T): T;
23
+ function getLocalData<T>(key: string, defaultValue?: T): T | undefined;
24
24
  /**
25
25
  * Get local storage object data
26
26
  * @param key Key name
@@ -30,7 +30,7 @@ export declare namespace StorageUtils {
30
30
  * Get session storage data
31
31
  * @param key Key name
32
32
  */
33
- function getSessionData<T>(key: string, defaultValue: T): T;
33
+ function getSessionData<T>(key: string, defaultValue?: T): T | undefined;
34
34
  /**
35
35
  * Get session storage object data
36
36
  * @param key Key name
@@ -35,6 +35,19 @@ declare global {
35
35
  * Utilities
36
36
  */
37
37
  export declare namespace Utils {
38
+ /**
39
+ * Base64 chars to number
40
+ * @param base64Chars Base64 chars
41
+ * @returns Number
42
+ */
43
+ function charsToNumber(base64Chars: string): number;
44
+ /**
45
+ * Two values equal
46
+ * @param v1 Value 1
47
+ * @param v2 Value 2
48
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
49
+ */
50
+ function equals(v1: unknown, v2: unknown, strict?: number): boolean;
38
51
  /**
39
52
  * Format inital character to lower case or upper case
40
53
  * @param input Input string
@@ -89,6 +102,12 @@ export declare namespace Utils {
89
102
  * Create a GUID
90
103
  */
91
104
  function newGUID(): string;
105
+ /**
106
+ * Number to base64 chars
107
+ * @param num Input number
108
+ * @returns Result
109
+ */
110
+ function numberToChars(num: number): string;
92
111
  /**
93
112
  * Test two objects are equal or not
94
113
  * @param obj1 Object 1
@@ -99,12 +118,30 @@ export declare namespace Utils {
99
118
  */
100
119
  function objectEqual(obj1: {}, obj2: {}, ignoreFields?: string[], strict?: number): boolean;
101
120
  /**
102
- * Parse string (JSON) to specific type
121
+ * Get two object's unqiue properties
122
+ * @param obj1 Object 1
123
+ * @param obj2 Object 2
124
+ * @param ignoreFields Ignored fields
125
+ * @returns Unique properties
126
+ */
127
+ function objectKeys(obj1: {}, obj2: {}, ignoreFields?: string[]): Set<string>;
128
+ /**
129
+ * Get the new object's updated fields contrast to the previous object
130
+ * @param objNew New object
131
+ * @param objPre Previous object
132
+ * @param ignoreFields Ignored fields
133
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
134
+ * @returns Updated fields
135
+ */
136
+ function objectUpdated(objNew: {}, objPrev: {}, ignoreFields?: string[], strict?: number): string[];
137
+ /**
138
+ * Parse string (JSON) to specific type, no type conversion
139
+ * For type conversion, please use DataTypes.convert
103
140
  * @param input Input string
104
141
  * @param defaultValue Default value
105
142
  * @returns Parsed value
106
143
  */
107
- function parseString<T>(input: string | undefined | null, defaultValue: T): T;
144
+ function parseString<T>(input: string | undefined | null, defaultValue?: T): T | undefined;
108
145
  /**
109
146
  * Remove non letters
110
147
  * @param input Input string
package/lib/mjs/Utils.js CHANGED
@@ -26,6 +26,43 @@ String.prototype.removeNonLetters = function () {
26
26
  */
27
27
  export var Utils;
28
28
  (function (Utils) {
29
+ /**
30
+ * Base64 chars to number
31
+ * @param base64Chars Base64 chars
32
+ * @returns Number
33
+ */
34
+ function charsToNumber(base64Chars) {
35
+ const chars = typeof Buffer === 'undefined'
36
+ ? [...atob(base64Chars)].map((char) => char.charCodeAt(0))
37
+ : [...Buffer.from(base64Chars, 'base64')];
38
+ return chars.reduce((previousValue, currentValue, currentIndex) => {
39
+ return previousValue + currentValue * Math.pow(128, currentIndex);
40
+ }, 0);
41
+ }
42
+ Utils.charsToNumber = charsToNumber;
43
+ /**
44
+ * Two values equal
45
+ * @param v1 Value 1
46
+ * @param v2 Value 2
47
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
48
+ */
49
+ function equals(v1, v2, strict = 1) {
50
+ // Null and undefined case
51
+ if (v1 == null || v2 == null) {
52
+ if (strict <= 1 && v1 == v2)
53
+ return true;
54
+ return v1 === v2;
55
+ }
56
+ // For array and object
57
+ if (typeof v1 === 'object')
58
+ return JSON.stringify(v1) === JSON.stringify(v2);
59
+ // 1 and '1' case
60
+ if (strict === 0)
61
+ return v1 == v2;
62
+ // Strict equal
63
+ return v1 === v2;
64
+ }
65
+ Utils.equals = equals;
29
66
  /**
30
67
  * Format inital character to lower case or upper case
31
68
  * @param input Input string
@@ -68,7 +105,7 @@ export var Utils;
68
105
  }
69
106
  if (initValue != null) {
70
107
  const newValue = DataTypes.convert(value, initValue);
71
- if (newValue === initValue) {
108
+ if (Utils.equals(newValue, initValue)) {
72
109
  Reflect.deleteProperty(input, key);
73
110
  return;
74
111
  }
@@ -146,6 +183,27 @@ export var Utils;
146
183
  });
147
184
  }
148
185
  Utils.newGUID = newGUID;
186
+ /**
187
+ * Number to base64 chars
188
+ * @param num Input number
189
+ * @returns Result
190
+ */
191
+ function numberToChars(num) {
192
+ const codes = [];
193
+ while (num > 0) {
194
+ const code = num % 128;
195
+ codes.push(code);
196
+ num = (num - code) / 128;
197
+ }
198
+ if (typeof Buffer === 'undefined') {
199
+ return btoa(String.fromCharCode(...codes));
200
+ }
201
+ else {
202
+ const buffer = Buffer.from(codes);
203
+ return buffer.toString('base64');
204
+ }
205
+ }
206
+ Utils.numberToChars = numberToChars;
149
207
  /**
150
208
  * Test two objects are equal or not
151
209
  * @param obj1 Object 1
@@ -155,37 +213,66 @@ export var Utils;
155
213
  * @returns Result
156
214
  */
157
215
  function objectEqual(obj1, obj2, ignoreFields = [], strict = 1) {
158
- // Keys
159
- const keys = new Set([
160
- ...Object.keys(obj1).filter((item) => !ignoreFields.includes(item)),
161
- ...Object.keys(obj2).filter((item) => !ignoreFields.includes(item))
162
- ]);
216
+ // Unique keys
217
+ const keys = Utils.objectKeys(obj1, obj2, ignoreFields);
163
218
  for (const key of keys) {
164
219
  // Values
165
220
  const v1 = Reflect.get(obj1, key);
166
221
  const v2 = Reflect.get(obj2, key);
167
- // Null and undefined case
168
- if (v1 == null && v2 == null && strict <= 1)
169
- continue;
170
- // 1 and '1' case
171
- if (strict === 0 && v1 == v2)
172
- continue;
173
- // Strict equal
174
- if (v1 !== v2)
222
+ if (!Utils.equals(v1, v2, strict))
175
223
  return false;
176
224
  }
177
225
  return true;
178
226
  }
179
227
  Utils.objectEqual = objectEqual;
180
228
  /**
181
- * Parse string (JSON) to specific type
229
+ * Get two object's unqiue properties
230
+ * @param obj1 Object 1
231
+ * @param obj2 Object 2
232
+ * @param ignoreFields Ignored fields
233
+ * @returns Unique properties
234
+ */
235
+ function objectKeys(obj1, obj2, ignoreFields = []) {
236
+ // All keys
237
+ const allKeys = [...Object.keys(obj1), ...Object.keys(obj2)].filter((item) => !ignoreFields.includes(item));
238
+ // Unique keys
239
+ return new Set(allKeys);
240
+ }
241
+ Utils.objectKeys = objectKeys;
242
+ /**
243
+ * Get the new object's updated fields contrast to the previous object
244
+ * @param objNew New object
245
+ * @param objPre Previous object
246
+ * @param ignoreFields Ignored fields
247
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
248
+ * @returns Updated fields
249
+ */
250
+ function objectUpdated(objNew, objPrev, ignoreFields = [], strict = 1) {
251
+ // Fields
252
+ const fields = [];
253
+ // Unique keys
254
+ const keys = Utils.objectKeys(objNew, objPrev, ignoreFields);
255
+ for (const key of keys) {
256
+ // Values
257
+ const vNew = Reflect.get(objNew, key);
258
+ const vPrev = Reflect.get(objPrev, key);
259
+ if (!Utils.equals(vNew, vPrev, strict)) {
260
+ fields.push(key);
261
+ }
262
+ }
263
+ return fields;
264
+ }
265
+ Utils.objectUpdated = objectUpdated;
266
+ /**
267
+ * Parse string (JSON) to specific type, no type conversion
268
+ * For type conversion, please use DataTypes.convert
182
269
  * @param input Input string
183
270
  * @param defaultValue Default value
184
271
  * @returns Parsed value
185
272
  */
186
273
  function parseString(input, defaultValue) {
187
- // Undefined case, return default value
188
- if (input == null)
274
+ // Undefined and empty case, return default value
275
+ if (input == null || input === '')
189
276
  return defaultValue;
190
277
  // String
191
278
  if (typeof defaultValue === 'string')
@@ -203,16 +290,11 @@ export var Utils;
203
290
  // Return
204
291
  return json;
205
292
  }
206
- catch (e) {
207
- console.log('Utils.parseString error', e);
293
+ catch {
294
+ if (defaultValue == null)
295
+ return input;
208
296
  return defaultValue;
209
297
  }
210
- /*
211
- finally part will still return the boolean value
212
- finally {
213
- return defaultValue
214
- }
215
- */
216
298
  }
217
299
  Utils.parseString = parseString;
218
300
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/shared",
3
- "version": "1.0.75",
3
+ "version": "1.0.79",
4
4
  "description": "TypeScript shared utilities and functions",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -55,13 +55,13 @@
55
55
  "dependencies": {},
56
56
  "devDependencies": {
57
57
  "@types/jest": "^27.0.3",
58
- "@typescript-eslint/eslint-plugin": "^5.4.0",
59
- "@typescript-eslint/parser": "^5.4.0",
60
- "eslint": "^8.2.0",
58
+ "@typescript-eslint/eslint-plugin": "^5.8.0",
59
+ "@typescript-eslint/parser": "^5.8.0",
60
+ "eslint": "^8.5.0",
61
61
  "eslint-config-airbnb-base": "^15.0.0",
62
62
  "eslint-plugin-import": "^2.25.3",
63
- "jest": "^27.3.1",
64
- "ts-jest": "^27.0.7",
65
- "typescript": "^4.5.2"
63
+ "jest": "^27.4.5",
64
+ "ts-jest": "^27.1.2",
65
+ "typescript": "^4.5.4"
66
66
  }
67
67
  }
@@ -49,7 +49,7 @@ export namespace StorageUtils {
49
49
  * @param key Key name
50
50
  * @param defaultValue Default value
51
51
  */
52
- export function getLocalData<T>(key: string, defaultValue: T) {
52
+ export function getLocalData<T>(key: string, defaultValue?: T) {
53
53
  // Get storage
54
54
  const data = localStorage.getItem(key);
55
55
 
@@ -72,7 +72,7 @@ export namespace StorageUtils {
72
72
  * Get session storage data
73
73
  * @param key Key name
74
74
  */
75
- export function getSessionData<T>(key: string, defaultValue: T) {
75
+ export function getSessionData<T>(key: string, defaultValue?: T) {
76
76
  // Get storage
77
77
  const data = sessionStorage.getItem(key);
78
78
 
package/src/Utils.ts CHANGED
@@ -77,6 +77,46 @@ String.prototype.removeNonLetters = function (this: string) {
77
77
  * Utilities
78
78
  */
79
79
  export namespace Utils {
80
+ /**
81
+ * Base64 chars to number
82
+ * @param base64Chars Base64 chars
83
+ * @returns Number
84
+ */
85
+ export function charsToNumber(base64Chars: string) {
86
+ const chars =
87
+ typeof Buffer === 'undefined'
88
+ ? [...atob(base64Chars)].map((char) => char.charCodeAt(0))
89
+ : [...Buffer.from(base64Chars, 'base64')];
90
+
91
+ return chars.reduce((previousValue, currentValue, currentIndex) => {
92
+ return previousValue + currentValue * Math.pow(128, currentIndex);
93
+ }, 0);
94
+ }
95
+
96
+ /**
97
+ * Two values equal
98
+ * @param v1 Value 1
99
+ * @param v2 Value 2
100
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
101
+ */
102
+ export function equals(v1: unknown, v2: unknown, strict = 1) {
103
+ // Null and undefined case
104
+ if (v1 == null || v2 == null) {
105
+ if (strict <= 1 && v1 == v2) return true;
106
+ return v1 === v2;
107
+ }
108
+
109
+ // For array and object
110
+ if (typeof v1 === 'object')
111
+ return JSON.stringify(v1) === JSON.stringify(v2);
112
+
113
+ // 1 and '1' case
114
+ if (strict === 0) return v1 == v2;
115
+
116
+ // Strict equal
117
+ return v1 === v2;
118
+ }
119
+
80
120
  /**
81
121
  * Format inital character to lower case or upper case
82
122
  * @param input Input string
@@ -126,7 +166,7 @@ export namespace Utils {
126
166
 
127
167
  if (initValue != null) {
128
168
  const newValue = DataTypes.convert(value, initValue);
129
- if (newValue === initValue) {
169
+ if (Utils.equals(newValue, initValue)) {
130
170
  Reflect.deleteProperty(input, key);
131
171
  return;
132
172
  }
@@ -218,6 +258,27 @@ export namespace Utils {
218
258
  });
219
259
  }
220
260
 
261
+ /**
262
+ * Number to base64 chars
263
+ * @param num Input number
264
+ * @returns Result
265
+ */
266
+ export function numberToChars(num: number) {
267
+ const codes = [];
268
+ while (num > 0) {
269
+ const code = num % 128;
270
+ codes.push(code);
271
+ num = (num - code) / 128;
272
+ }
273
+
274
+ if (typeof Buffer === 'undefined') {
275
+ return btoa(String.fromCharCode(...codes));
276
+ } else {
277
+ const buffer = Buffer.from(codes);
278
+ return buffer.toString('base64');
279
+ }
280
+ }
281
+
221
282
  /**
222
283
  * Test two objects are equal or not
223
284
  * @param obj1 Object 1
@@ -232,42 +293,87 @@ export namespace Utils {
232
293
  ignoreFields: string[] = [],
233
294
  strict = 1
234
295
  ) {
235
- // Keys
236
- const keys = new Set([
237
- ...Object.keys(obj1).filter((item) => !ignoreFields.includes(item)),
238
- ...Object.keys(obj2).filter((item) => !ignoreFields.includes(item))
239
- ]);
296
+ // Unique keys
297
+ const keys = Utils.objectKeys(obj1, obj2, ignoreFields);
240
298
 
241
299
  for (const key of keys) {
242
300
  // Values
243
301
  const v1 = Reflect.get(obj1, key);
244
302
  const v2 = Reflect.get(obj2, key);
245
303
 
246
- // Null and undefined case
247
- if (v1 == null && v2 == null && strict <= 1) continue;
304
+ if (!Utils.equals(v1, v2, strict)) return false;
305
+ }
306
+
307
+ return true;
308
+ }
309
+
310
+ /**
311
+ * Get two object's unqiue properties
312
+ * @param obj1 Object 1
313
+ * @param obj2 Object 2
314
+ * @param ignoreFields Ignored fields
315
+ * @returns Unique properties
316
+ */
317
+ export function objectKeys(
318
+ obj1: {},
319
+ obj2: {},
320
+ ignoreFields: string[] = []
321
+ ) {
322
+ // All keys
323
+ const allKeys = [...Object.keys(obj1), ...Object.keys(obj2)].filter(
324
+ (item) => !ignoreFields.includes(item)
325
+ );
248
326
 
249
- // 1 and '1' case
250
- if (strict === 0 && v1 == v2) continue;
327
+ // Unique keys
328
+ return new Set(allKeys);
329
+ }
251
330
 
252
- // Strict equal
253
- if (v1 !== v2) return false;
331
+ /**
332
+ * Get the new object's updated fields contrast to the previous object
333
+ * @param objNew New object
334
+ * @param objPre Previous object
335
+ * @param ignoreFields Ignored fields
336
+ * @param strict Strict level, 0 with ==, 1 === but null equal undefined, 2 ===
337
+ * @returns Updated fields
338
+ */
339
+ export function objectUpdated(
340
+ objNew: {},
341
+ objPrev: {},
342
+ ignoreFields: string[] = [],
343
+ strict = 1
344
+ ) {
345
+ // Fields
346
+ const fields: string[] = [];
347
+
348
+ // Unique keys
349
+ const keys = Utils.objectKeys(objNew, objPrev, ignoreFields);
350
+
351
+ for (const key of keys) {
352
+ // Values
353
+ const vNew = Reflect.get(objNew, key);
354
+ const vPrev = Reflect.get(objPrev, key);
355
+
356
+ if (!Utils.equals(vNew, vPrev, strict)) {
357
+ fields.push(key);
358
+ }
254
359
  }
255
360
 
256
- return true;
361
+ return fields;
257
362
  }
258
363
 
259
364
  /**
260
- * Parse string (JSON) to specific type
365
+ * Parse string (JSON) to specific type, no type conversion
366
+ * For type conversion, please use DataTypes.convert
261
367
  * @param input Input string
262
368
  * @param defaultValue Default value
263
369
  * @returns Parsed value
264
370
  */
265
371
  export function parseString<T>(
266
372
  input: string | undefined | null,
267
- defaultValue: T
268
- ): T {
269
- // Undefined case, return default value
270
- if (input == null) return defaultValue;
373
+ defaultValue?: T
374
+ ): T | undefined {
375
+ // Undefined and empty case, return default value
376
+ if (input == null || input === '') return defaultValue;
271
377
 
272
378
  // String
273
379
  if (typeof defaultValue === 'string') return <any>input;
@@ -285,16 +391,10 @@ export namespace Utils {
285
391
 
286
392
  // Return
287
393
  return <T>json;
288
- } catch (e) {
289
- console.log('Utils.parseString error', e);
394
+ } catch {
395
+ if (defaultValue == null) return <any>input;
290
396
  return defaultValue;
291
397
  }
292
- /*
293
- finally part will still return the boolean value
294
- finally {
295
- return defaultValue
296
- }
297
- */
298
398
  }
299
399
 
300
400
  /**