@beecode/msh-util 1.2.1 → 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.
- package/dist/array-util.d.ts +23 -0
- package/dist/array-util.d.ts.map +1 -0
- package/dist/array-util.js +27 -0
- package/{src/class-factory-pattern.ts → dist/class-factory-pattern.d.ts} +5 -9
- package/dist/class-factory-pattern.d.ts.map +1 -0
- package/dist/class-factory-pattern.js +26 -0
- package/{src/express/error-handler.ts → dist/express/error-handler.d.ts} +2 -10
- package/dist/express/error-handler.d.ts.map +1 -0
- package/dist/express/error-handler.js +26 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/joi-util.d.ts +47 -0
- package/dist/joi-util.d.ts.map +1 -0
- package/dist/joi-util.js +62 -0
- package/{src/memoize-factory.ts → dist/memoize-factory.d.ts} +3 -14
- package/dist/memoize-factory.d.ts.map +1 -0
- package/dist/memoize-factory.js +24 -0
- package/dist/object-util.d.ts +72 -0
- package/dist/object-util.d.ts.map +1 -0
- package/dist/object-util.js +115 -0
- package/dist/regex-util.d.ts +12 -0
- package/dist/regex-util.d.ts.map +1 -0
- package/dist/regex-util.js +12 -0
- package/dist/single-threshold-promise.d.ts +31 -0
- package/dist/single-threshold-promise.d.ts.map +1 -0
- package/dist/single-threshold-promise.js +46 -0
- package/dist/singleton/async.d.ts +50 -0
- package/dist/singleton/async.d.ts.map +1 -0
- package/dist/singleton/async.js +75 -0
- package/{src/singleton/pattern.ts → dist/singleton/pattern.d.ts} +3 -13
- package/dist/singleton/pattern.d.ts.map +1 -0
- package/dist/singleton/pattern.js +41 -0
- package/dist/string-util.d.ts +10 -0
- package/dist/string-util.d.ts.map +1 -0
- package/dist/string-util.js +18 -0
- package/dist/time-util.d.ts +74 -0
- package/dist/time-util.d.ts.map +1 -0
- package/dist/time-util.js +90 -0
- package/dist/time-zone.d.ts +467 -0
- package/dist/time-zone.d.ts.map +1 -0
- package/dist/time-zone.js +468 -0
- package/{src/timeout.ts → dist/timeout.d.ts} +2 -3
- package/dist/timeout.d.ts.map +1 -0
- package/dist/timeout.js +17 -0
- package/dist/type-util.d.ts +50 -0
- package/dist/type-util.d.ts.map +1 -0
- package/dist/type-util.js +54 -0
- package/lib/array-util.d.ts.map +1 -1
- package/lib/array-util.js +30 -28
- package/lib/class-factory-pattern.d.ts.map +1 -1
- package/lib/class-factory-pattern.js +17 -8
- package/lib/express/error-handler.d.ts.map +1 -1
- package/lib/express/error-handler.js +15 -11
- package/lib/index.d.ts +16 -13
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +107 -29
- package/lib/joi-util.d.ts.map +1 -1
- package/lib/joi-util.js +66 -22
- package/lib/memoize-factory.d.ts +1 -1
- package/lib/memoize-factory.d.ts.map +1 -1
- package/lib/memoize-factory.js +19 -13
- package/lib/object-util.d.ts.map +1 -1
- package/lib/object-util.js +110 -55
- package/lib/package.json +1 -0
- package/lib/regex-util.js +15 -13
- package/lib/single-threshold-promise.d.ts +1 -1
- package/lib/single-threshold-promise.d.ts.map +1 -1
- package/lib/single-threshold-promise.js +74 -28
- package/lib/singleton/async.d.ts +1 -1
- package/lib/singleton/async.d.ts.map +1 -1
- package/lib/singleton/async.js +105 -45
- package/lib/singleton/pattern.d.ts +1 -1
- package/lib/singleton/pattern.d.ts.map +1 -1
- package/lib/singleton/pattern.js +13 -12
- package/lib/string-util.js +21 -19
- package/lib/time-util.js +69 -39
- package/lib/time-zone.d.ts +467 -0
- package/lib/time-zone.d.ts.map +1 -0
- package/lib/time-zone.js +473 -0
- package/lib/timeout.js +9 -6
- package/lib/type-util.js +57 -55
- package/lib/types/global.d.js +5 -0
- package/lib/types/types.d.js +3 -0
- package/package.json +188 -134
- package/lib/array-util.js.map +0 -1
- package/lib/class-factory-pattern.js.map +0 -1
- package/lib/express/error-handler.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/joi-util.js.map +0 -1
- package/lib/memoize-factory.js.map +0 -1
- package/lib/object-util.js.map +0 -1
- package/lib/regex-util.js.map +0 -1
- package/lib/single-threshold-promise.js.map +0 -1
- package/lib/singleton/async.js.map +0 -1
- package/lib/singleton/pattern.js.map +0 -1
- package/lib/string-util.js.map +0 -1
- package/lib/time-util.js.map +0 -1
- package/lib/timeout.js.map +0 -1
- package/lib/type-util.js.map +0 -1
- package/lib/types/any-function/index.d.ts +0 -2
- package/lib/types/any-function/index.d.ts.map +0 -1
- package/lib/types/any-function/index.js +0 -3
- package/lib/types/any-function/index.js.map +0 -1
- package/lib/types/any-function/no-params.d.ts +0 -2
- package/lib/types/any-function/no-params.d.ts.map +0 -1
- package/lib/types/any-function/no-params.js +0 -3
- package/lib/types/any-function/no-params.js.map +0 -1
- package/lib/types/any-function/promise-no-params.d.ts +0 -2
- package/lib/types/any-function/promise-no-params.d.ts.map +0 -1
- package/lib/types/any-function/promise-no-params.js +0 -3
- package/lib/types/any-function/promise-no-params.js.map +0 -1
- package/lib/types/any-function/promise.d.ts +0 -2
- package/lib/types/any-function/promise.d.ts.map +0 -1
- package/lib/types/any-function/promise.js +0 -3
- package/lib/types/any-function/promise.js.map +0 -1
- package/src/array-util.test.ts +0 -50
- package/src/array-util.ts +0 -26
- package/src/class-factory-pattern.test.ts +0 -39
- package/src/express/error-handler.test.ts +0 -44
- package/src/index.ts +0 -25
- package/src/joi-util.test.ts +0 -192
- package/src/joi-util.ts +0 -65
- package/src/memoize-factory.test.ts +0 -40
- package/src/object-util.test.ts +0 -360
- package/src/object-util.ts +0 -127
- package/src/regex-util.test.ts +0 -25
- package/src/regex-util.ts +0 -11
- package/src/single-threshold-promise.test.ts +0 -91
- package/src/single-threshold-promise.ts +0 -56
- package/src/singleton/async.test.ts +0 -122
- package/src/singleton/async.ts +0 -90
- package/src/singleton/pattern.test.ts +0 -16
- package/src/string-util.test.ts +0 -18
- package/src/string-util.ts +0 -18
- package/src/time-util.test.ts +0 -89
- package/src/time-util.ts +0 -98
- package/src/timeout.test.ts +0 -65
- package/src/type-util.test.ts +0 -20
- package/src/type-util.ts +0 -54
- package/src/types/any-function/index.ts +0 -1
- package/src/types/any-function/no-params.ts +0 -1
- package/src/types/any-function/promise-no-params.ts +0 -1
- package/src/types/any-function/promise.ts +0 -1
- package/src/types/types.d.ts +0 -2
package/src/object-util.test.ts
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import { ObjectUtil } from 'src/object-util'
|
|
2
|
-
|
|
3
|
-
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
4
|
-
describe('objectUtil', () => {
|
|
5
|
-
const objectUtil = new ObjectUtil()
|
|
6
|
-
|
|
7
|
-
const everyType = {
|
|
8
|
-
number: 1,
|
|
9
|
-
decimal: 1.12345,
|
|
10
|
-
string: 'string',
|
|
11
|
-
undefined: undefined,
|
|
12
|
-
notANumber: NaN,
|
|
13
|
-
emptyObj: {},
|
|
14
|
-
date: new Date('2020-01-01'),
|
|
15
|
-
boolean: true,
|
|
16
|
-
nestedObject: { obj: 'test' },
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const everyTypeReversed = {
|
|
20
|
-
nestedObject: { obj: 'test' },
|
|
21
|
-
boolean: true,
|
|
22
|
-
date: new Date('2020-01-01'),
|
|
23
|
-
emptyObj: {},
|
|
24
|
-
notANumber: NaN,
|
|
25
|
-
undefined: undefined,
|
|
26
|
-
string: 'string',
|
|
27
|
-
decimal: 1.12345,
|
|
28
|
-
number: 1,
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
describe('deepClone', () => {
|
|
32
|
-
it.each([
|
|
33
|
-
[{ test: 'string' }],
|
|
34
|
-
[{ deep: { test: 'string' } }],
|
|
35
|
-
[{ deeper: { deep: { test: 'string' } } }],
|
|
36
|
-
[everyType],
|
|
37
|
-
[{ deep: everyType }],
|
|
38
|
-
[{ deeper: { deep: everyType } }],
|
|
39
|
-
])('%#. should clone %j', (obj) => {
|
|
40
|
-
expect(objectUtil.deepClone(obj)).not.toBe(obj)
|
|
41
|
-
})
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
describe('pickByList', () => {
|
|
45
|
-
it.each([
|
|
46
|
-
[['a', 'b'], { a: 1, b: '2', c: 3 }, { a: 1, b: '2' }],
|
|
47
|
-
[['a', 'c'], { a: 1, b: '2', c: 3 }, { a: 1, c: 3 }],
|
|
48
|
-
])('%#. should pick only this properties [%s] from object %s and return object %s', (propList, obj, result) => {
|
|
49
|
-
expect(objectUtil.pickByList(obj, propList)).toEqual(result)
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
describe('pickByObjectKeys', () => {
|
|
54
|
-
it.each([
|
|
55
|
-
[
|
|
56
|
-
{ a: 1, b: '2', c: 3 },
|
|
57
|
-
{ a: '', b: '' },
|
|
58
|
-
{ a: 1, b: '2' },
|
|
59
|
-
],
|
|
60
|
-
[
|
|
61
|
-
{ a: 1, b: '2', c: 3 },
|
|
62
|
-
{ a: '', c: '' },
|
|
63
|
-
{ a: 1, c: 3 },
|
|
64
|
-
],
|
|
65
|
-
])('%#. should pick form this %s using keys from %s and return %s', (obj, objWithPickKeys, result) => {
|
|
66
|
-
expect(objectUtil.pickByObjectKeys(obj, objWithPickKeys)).toEqual(result)
|
|
67
|
-
})
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
describe('deepStringify', () => {
|
|
71
|
-
it.each([
|
|
72
|
-
[{}, '{}'],
|
|
73
|
-
[{ a: 1, b: 2 }, `{ a: 1, b: 2 }`],
|
|
74
|
-
[
|
|
75
|
-
everyType,
|
|
76
|
-
`{ boolean: true, date: 2020-01-01T00:00:00.000Z, decimal: 1.12345, emptyObj: {}, nestedObject: { obj: 'test' }, notANumber: NaN, number: 1, string: 'string', undefined: undefined }`,
|
|
77
|
-
],
|
|
78
|
-
[
|
|
79
|
-
{ deep: everyType },
|
|
80
|
-
`{ deep: { boolean: true, date: 2020-01-01T00:00:00.000Z, decimal: 1.12345, emptyObj: {}, nestedObject: { obj: 'test' }, notANumber: NaN, number: 1, string: 'string', undefined: undefined } }`,
|
|
81
|
-
],
|
|
82
|
-
[
|
|
83
|
-
{ deeper: { deep: everyType } },
|
|
84
|
-
`{ deeper: { deep: { boolean: true, date: 2020-01-01T00:00:00.000Z, decimal: 1.12345, emptyObj: {}, nestedObject: { obj: 'test' }, notANumber: NaN, number: 1, string: 'string', undefined: undefined } } }`,
|
|
85
|
-
],
|
|
86
|
-
])('%#. should compare %j and sort with result %j', (value, expected) => {
|
|
87
|
-
expect(objectUtil.deepStringify(value, { isSorted: true })).toEqual(expected)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
it.each([
|
|
91
|
-
[{ b: 2, a: 1 }, `{ a: 1, b: 2 }`],
|
|
92
|
-
[
|
|
93
|
-
everyType,
|
|
94
|
-
`{ boolean: true, date: 2020-01-01T00:00:00.000Z, decimal: 1.12345, emptyObj: {}, nestedObject: { obj: 'test' }, notANumber: NaN, number: 1, string: 'string', undefined: undefined }`,
|
|
95
|
-
],
|
|
96
|
-
[
|
|
97
|
-
{ deep: everyType },
|
|
98
|
-
`{ deep: { boolean: true, date: 2020-01-01T00:00:00.000Z, decimal: 1.12345, emptyObj: {}, nestedObject: { obj: 'test' }, notANumber: NaN, number: 1, string: 'string', undefined: undefined } }`,
|
|
99
|
-
],
|
|
100
|
-
[
|
|
101
|
-
{ deeper: { deep: everyType } },
|
|
102
|
-
`{ deeper: { deep: { boolean: true, date: 2020-01-01T00:00:00.000Z, decimal: 1.12345, emptyObj: {}, nestedObject: { obj: 'test' }, notANumber: NaN, number: 1, string: 'string', undefined: undefined } } }`,
|
|
103
|
-
],
|
|
104
|
-
])('%#. should compare %j with result %j and not be equal because it is not sorted', (value, expected) => {
|
|
105
|
-
expect(objectUtil.deepStringify(value, { isSorted: true })).toEqual(expected)
|
|
106
|
-
expect(objectUtil.deepStringify(value)).not.toEqual(expected)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it.each([
|
|
110
|
-
[null, 'null'],
|
|
111
|
-
[undefined, 'undefined'],
|
|
112
|
-
[123, '123'],
|
|
113
|
-
[[123], `[ 123 ]`],
|
|
114
|
-
['test', "'test'"],
|
|
115
|
-
(() => {
|
|
116
|
-
const date = new Date()
|
|
117
|
-
|
|
118
|
-
return [date, date.toISOString()]
|
|
119
|
-
})(),
|
|
120
|
-
])('%#. should compare %j with result %j with compact enabled', (value, expected) => {
|
|
121
|
-
expect(objectUtil.deepStringify(value)).toEqual(expected)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it.each([
|
|
125
|
-
[['d', 'c', 'b', 'a'], `[ 'a', 'b', 'c', 'd' ]`, `[ 'd', 'c', 'b', 'a' ]`],
|
|
126
|
-
[{ a: ['d', 'c', 'b', 'a'] }, `{ a: [ 'a', 'b', 'c', 'd' ]`, `{ a: [ 'd', 'c', 'b', 'a' ] }`],
|
|
127
|
-
])('%# should not sort arrays', (arr, expectSorted, expectUnsorted) => {
|
|
128
|
-
expect(objectUtil.deepStringify(arr, { isSorted: true })).not.toEqual(expectSorted)
|
|
129
|
-
expect(objectUtil.deepStringify(arr, { isSorted: true })).toEqual(expectUnsorted)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it.each([
|
|
133
|
-
[
|
|
134
|
-
0,
|
|
135
|
-
`{
|
|
136
|
-
a: {
|
|
137
|
-
a1: {
|
|
138
|
-
a2: {
|
|
139
|
-
a3: {
|
|
140
|
-
a4: {
|
|
141
|
-
a5: 'level 5'
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
},
|
|
147
|
-
b: {
|
|
148
|
-
b1: {
|
|
149
|
-
b2: {
|
|
150
|
-
b3: {
|
|
151
|
-
b4: 'level 4'
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
},
|
|
156
|
-
c: [
|
|
157
|
-
'c0',
|
|
158
|
-
[
|
|
159
|
-
'c1',
|
|
160
|
-
[
|
|
161
|
-
'c2',
|
|
162
|
-
[
|
|
163
|
-
'c3',
|
|
164
|
-
[
|
|
165
|
-
'c4',
|
|
166
|
-
[
|
|
167
|
-
'c5'
|
|
168
|
-
]
|
|
169
|
-
]
|
|
170
|
-
]
|
|
171
|
-
]
|
|
172
|
-
]
|
|
173
|
-
]
|
|
174
|
-
}`,
|
|
175
|
-
],
|
|
176
|
-
[
|
|
177
|
-
1,
|
|
178
|
-
`{
|
|
179
|
-
a: {
|
|
180
|
-
a1: {
|
|
181
|
-
a2: {
|
|
182
|
-
a3: {
|
|
183
|
-
a4: { a5: 'level 5' }
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
b: {
|
|
189
|
-
b1: {
|
|
190
|
-
b2: {
|
|
191
|
-
b3: { b4: 'level 4' }
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
},
|
|
195
|
-
c: [
|
|
196
|
-
'c0',
|
|
197
|
-
[
|
|
198
|
-
'c1',
|
|
199
|
-
[
|
|
200
|
-
'c2',
|
|
201
|
-
[
|
|
202
|
-
'c3',
|
|
203
|
-
[
|
|
204
|
-
'c4',
|
|
205
|
-
[ 'c5' ]
|
|
206
|
-
]
|
|
207
|
-
]
|
|
208
|
-
]
|
|
209
|
-
]
|
|
210
|
-
]
|
|
211
|
-
}`,
|
|
212
|
-
],
|
|
213
|
-
[
|
|
214
|
-
2,
|
|
215
|
-
`{
|
|
216
|
-
a: {
|
|
217
|
-
a1: {
|
|
218
|
-
a2: {
|
|
219
|
-
a3: { a4: { a5: 'level 5' } }
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
},
|
|
223
|
-
b: {
|
|
224
|
-
b1: {
|
|
225
|
-
b2: { b3: { b4: 'level 4' } }
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
c: [
|
|
229
|
-
'c0',
|
|
230
|
-
[
|
|
231
|
-
'c1',
|
|
232
|
-
[
|
|
233
|
-
'c2',
|
|
234
|
-
[
|
|
235
|
-
'c3',
|
|
236
|
-
[ 'c4', [ 'c5' ] ]
|
|
237
|
-
]
|
|
238
|
-
]
|
|
239
|
-
]
|
|
240
|
-
]
|
|
241
|
-
}`,
|
|
242
|
-
],
|
|
243
|
-
[
|
|
244
|
-
3,
|
|
245
|
-
`{
|
|
246
|
-
a: {
|
|
247
|
-
a1: {
|
|
248
|
-
a2: { a3: { a4: { a5: 'level 5' } } }
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
b: {
|
|
252
|
-
b1: { b2: { b3: { b4: 'level 4' } } }
|
|
253
|
-
},
|
|
254
|
-
c: [
|
|
255
|
-
'c0',
|
|
256
|
-
[
|
|
257
|
-
'c1',
|
|
258
|
-
[
|
|
259
|
-
'c2',
|
|
260
|
-
[ 'c3', [ 'c4', [ 'c5' ] ] ]
|
|
261
|
-
]
|
|
262
|
-
]
|
|
263
|
-
]
|
|
264
|
-
}`,
|
|
265
|
-
],
|
|
266
|
-
[
|
|
267
|
-
4,
|
|
268
|
-
`{
|
|
269
|
-
a: {
|
|
270
|
-
a1: { a2: { a3: { a4: { a5: 'level 5' } } } }
|
|
271
|
-
},
|
|
272
|
-
b: { b1: { b2: { b3: { b4: 'level 4' } } } },
|
|
273
|
-
c: [
|
|
274
|
-
'c0',
|
|
275
|
-
[
|
|
276
|
-
'c1',
|
|
277
|
-
[ 'c2', [ 'c3', [ 'c4', [ 'c5' ] ] ] ]
|
|
278
|
-
]
|
|
279
|
-
]
|
|
280
|
-
}`,
|
|
281
|
-
],
|
|
282
|
-
[
|
|
283
|
-
5,
|
|
284
|
-
`{
|
|
285
|
-
a: { a1: { a2: { a3: { a4: { a5: 'level 5' } } } } },
|
|
286
|
-
b: { b1: { b2: { b3: { b4: 'level 4' } } } },
|
|
287
|
-
c: [
|
|
288
|
-
'c0',
|
|
289
|
-
[ 'c1', [ 'c2', [ 'c3', [ 'c4', [ 'c5' ] ] ] ] ]
|
|
290
|
-
]
|
|
291
|
-
}`,
|
|
292
|
-
],
|
|
293
|
-
[
|
|
294
|
-
6,
|
|
295
|
-
`{
|
|
296
|
-
a: { a1: { a2: { a3: { a4: { a5: 'level 5' } } } } },
|
|
297
|
-
b: { b1: { b2: { b3: { b4: 'level 4' } } } },
|
|
298
|
-
c: [ 'c0', [ 'c1', [ 'c2', [ 'c3', [ 'c4', [ 'c5' ] ] ] ] ] ]
|
|
299
|
-
}`,
|
|
300
|
-
],
|
|
301
|
-
])('%# should take object with 5 levels and compact it to level $s', (level, expected) => {
|
|
302
|
-
const obj = {
|
|
303
|
-
a: { a1: { a2: { a3: { a4: { a5: 'level 5' } } } } },
|
|
304
|
-
b: { b1: { b2: { b3: { b4: 'level 4' } } } },
|
|
305
|
-
c: ['c0', ['c1', ['c2', ['c3', ['c4', ['c5']]]]]],
|
|
306
|
-
}
|
|
307
|
-
expect(objectUtil.deepStringify(obj, { isPrettyPrinted: true, prettyPrintCompactLevel: level })).toEqual(expected)
|
|
308
|
-
})
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
describe('deepEqual', () => {
|
|
312
|
-
it.each([
|
|
313
|
-
[null, null],
|
|
314
|
-
[undefined, undefined],
|
|
315
|
-
[{}, {}],
|
|
316
|
-
[everyType, everyType],
|
|
317
|
-
[{ deep: everyType }, { deep: everyType }],
|
|
318
|
-
[{ deeper: { deep: everyType } }, { deeper: { deep: everyType } }],
|
|
319
|
-
])('%#. should be deep equal compare %j with result %j', (value, result) => {
|
|
320
|
-
expect(objectUtil.deepEqual(value, result)).toBeTruthy()
|
|
321
|
-
})
|
|
322
|
-
|
|
323
|
-
it.each([
|
|
324
|
-
[{}, { a: 1 }],
|
|
325
|
-
[everyType, { ...everyType, a: 1 }],
|
|
326
|
-
[{ deep: everyType }, { a: 1, deep: everyType }],
|
|
327
|
-
[{ deeper: { deep: everyType } }, { a: 1, deeper: { deep: everyType } }],
|
|
328
|
-
])('%#. should not deep equal compare %j with result %j', (value, result) => {
|
|
329
|
-
expect(objectUtil.deepEqual(value, result)).toBeFalsy()
|
|
330
|
-
})
|
|
331
|
-
|
|
332
|
-
it.each([
|
|
333
|
-
[
|
|
334
|
-
{ a: 1, b: 2 },
|
|
335
|
-
{ a: 1, b: 2 },
|
|
336
|
-
],
|
|
337
|
-
[
|
|
338
|
-
{ a: { a: 1, b: 2 }, b: everyType },
|
|
339
|
-
{ a: { a: 1, b: 2 }, b: everyTypeReversed },
|
|
340
|
-
],
|
|
341
|
-
])('%#. should be deep equal even if in different order compare %j with result %j', (value, result) => {
|
|
342
|
-
expect(objectUtil.deepEqual(value, result)).toBeTruthy()
|
|
343
|
-
})
|
|
344
|
-
})
|
|
345
|
-
|
|
346
|
-
describe('deepNullToUndefined', () => {
|
|
347
|
-
it.each([
|
|
348
|
-
[{ test: undefined }, { test: undefined }],
|
|
349
|
-
[{ test: null }, { test: undefined }],
|
|
350
|
-
[{ deep: { test: null } }, { deep: { test: undefined } }],
|
|
351
|
-
[{ deeper: { deep: { test: null } } }, { deeper: { deep: { test: undefined } } }],
|
|
352
|
-
[everyType, everyType],
|
|
353
|
-
[{ deep: everyType }, { deep: everyType }],
|
|
354
|
-
[{ deeper: { deep: everyType } }, { deeper: { deep: everyType } }],
|
|
355
|
-
])('%#. should convert null to undefined for %j', (withNulls, withUndefined) => {
|
|
356
|
-
expect(objectUtil.deepNullToUndefined(withNulls)).toEqual(withUndefined)
|
|
357
|
-
})
|
|
358
|
-
})
|
|
359
|
-
})
|
|
360
|
-
/* eslint-enable sort-keys-fix/sort-keys-fix */
|
package/src/object-util.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import cloneDeep from 'lodash.clonedeep'
|
|
2
|
-
import util from 'util'
|
|
3
|
-
|
|
4
|
-
export type ObjectType = Record<string, any>
|
|
5
|
-
|
|
6
|
-
export class ObjectUtil {
|
|
7
|
-
/**
|
|
8
|
-
* Deep clone object. Returned object will have no references to the object passed through params
|
|
9
|
-
* @template T
|
|
10
|
-
* @param {T} objectToClone
|
|
11
|
-
* @return {T}
|
|
12
|
-
*/
|
|
13
|
-
deepClone<T extends ObjectType>(objectToClone: T): T {
|
|
14
|
-
return cloneDeep(objectToClone)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Pick only properties from the property list. It is only allowed to pick properties from the first level
|
|
19
|
-
* @template T
|
|
20
|
-
* @template L
|
|
21
|
-
* @param {T} obj
|
|
22
|
-
* @param {L[]} keyList
|
|
23
|
-
* @return {Pick<T, L>}
|
|
24
|
-
*/
|
|
25
|
-
pickByList<T extends object, L extends keyof T>(obj: T, keyList: (L | string)[]): Pick<T, L> {
|
|
26
|
-
return keyList.reduce((pickedObj, key) => {
|
|
27
|
-
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
28
|
-
pickedObj[key as L] = obj[key as L]
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return pickedObj
|
|
32
|
-
}, {} as Pick<T, L>) // eslint-disable-line @typescript-eslint/prefer-reduce-type-parameter
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Pick objects properties using keys from the second object.
|
|
37
|
-
* @template T
|
|
38
|
-
* @template L
|
|
39
|
-
* @param {T} obj
|
|
40
|
-
* @param {Partial<T>} objWithPickKeys
|
|
41
|
-
* @return {Pick<T, L>}
|
|
42
|
-
*/
|
|
43
|
-
pickByObjectKeys<T extends object, L extends keyof T>(obj: T, objWithPickKeys: Partial<T> | ObjectType): Pick<T, L> {
|
|
44
|
-
const keys = Object.keys(objWithPickKeys) as L[]
|
|
45
|
-
|
|
46
|
-
return this.pickByList<T, L>(obj, keys)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* This function will do stringify deeper that JSON.stringify.
|
|
51
|
-
* @param {any} entity - entity thant needs to be stringify
|
|
52
|
-
* @param {object} [options] - available options
|
|
53
|
-
* @param {boolean} [options.isSortable=false] - if object property should be sorted
|
|
54
|
-
* @param {boolean} [options.isPrettyPrinted=false] - if object and array properties should be printed in a new row
|
|
55
|
-
* @param {number} [options.prettyPrintCompactLevel=0] - if pretty print is on define the level of deepest children that are not
|
|
56
|
-
* going to be pretty. It doesn't matter if the siblings doesn't have the same depth.
|
|
57
|
-
* @return {string} - strung result
|
|
58
|
-
* @example
|
|
59
|
-
* console.log(new ObjectUtil().deepStringify(null)) // 'null'
|
|
60
|
-
* console.log(new ObjectUtil().deepStringify(undefined)) // 'undefined'
|
|
61
|
-
* console.log(new ObjectUtil().deepStringify({ a: 1 })) // '{\n\ta: 1\n}'
|
|
62
|
-
* // `{
|
|
63
|
-
* // a:1
|
|
64
|
-
* // }`
|
|
65
|
-
* console.log(new ObjectUtil().deepStringify({ b: 1, a: 2 }, {isSorted:true, compact: true})) // { a: 2, b: 1 }
|
|
66
|
-
*/
|
|
67
|
-
deepStringify(
|
|
68
|
-
entity: any,
|
|
69
|
-
options?: { isSorted?: boolean; isPrettyPrinted?: boolean; prettyPrintCompactLevel?: number }
|
|
70
|
-
): string {
|
|
71
|
-
const { isSorted = false, isPrettyPrinted = false, prettyPrintCompactLevel = 0 } = options ?? {}
|
|
72
|
-
|
|
73
|
-
const compact = this._deepStringifyCompact({ isPrettyPrinted, prettyPrintCompactLevel })
|
|
74
|
-
|
|
75
|
-
return util.inspect(entity, {
|
|
76
|
-
breakLength: Infinity,
|
|
77
|
-
compact,
|
|
78
|
-
depth: Infinity,
|
|
79
|
-
maxArrayLength: Infinity,
|
|
80
|
-
maxStringLength: Infinity,
|
|
81
|
-
sorted: isSorted,
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
protected _deepStringifyCompact(params: { isPrettyPrinted: boolean; prettyPrintCompactLevel: number }): number | boolean {
|
|
86
|
-
const { isPrettyPrinted, prettyPrintCompactLevel } = params
|
|
87
|
-
|
|
88
|
-
if (!isPrettyPrinted) {
|
|
89
|
-
return true
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return prettyPrintCompactLevel
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* We are converting objects to string (or null or undefined) and comparing if the result is equal
|
|
97
|
-
* @param a
|
|
98
|
-
* @param b
|
|
99
|
-
* @return {boolean}
|
|
100
|
-
*/
|
|
101
|
-
deepEqual(a: any, b: any): boolean {
|
|
102
|
-
return this.deepStringify(a, { isSorted: true }) === this.deepStringify(b, { isSorted: true })
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* This function is going to convert any null to undefined in the object that is passed to it.
|
|
107
|
-
* @template T
|
|
108
|
-
* @param {T} objectWithNulls
|
|
109
|
-
* @return {T}
|
|
110
|
-
* @example
|
|
111
|
-
* console.log(new ObjectUtil().deepNullToUndefined({ a: null, b: { c: null } })) // { a: undefined, b: { c: undefined } }
|
|
112
|
-
*/
|
|
113
|
-
deepNullToUndefined<T extends ObjectType>(objectWithNulls: T): T {
|
|
114
|
-
return Object.entries(objectWithNulls).reduce<any>((acc, cur) => {
|
|
115
|
-
const [key, value] = cur
|
|
116
|
-
if (value === null) {
|
|
117
|
-
acc[key] = undefined
|
|
118
|
-
} else if (typeof value === 'object' && !(value instanceof Date)) {
|
|
119
|
-
acc[key] = this.deepNullToUndefined(value)
|
|
120
|
-
} else {
|
|
121
|
-
acc[key] = value
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return acc
|
|
125
|
-
}, {})
|
|
126
|
-
}
|
|
127
|
-
}
|
package/src/regex-util.test.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { regexUtil } from 'src/regex-util'
|
|
2
|
-
|
|
3
|
-
describe('regexUtil', () => {
|
|
4
|
-
it.each([
|
|
5
|
-
['00000000-0000-0000-0000-000000000000'],
|
|
6
|
-
['b40c3094-a238-4c21-a744-f19b9e476abf'],
|
|
7
|
-
['7d39e0a8-4ca2-41ff-9ded-312fb08f4dda'],
|
|
8
|
-
['f9ea83de-c69f-42ff-8764-a6e88d59d75d'],
|
|
9
|
-
['33f13db5-d427-4ea4-b028-6fc30a84d827'],
|
|
10
|
-
['f04ec90e-2ff5-4b88-beb3-23b348b8e33b'],
|
|
11
|
-
['83ad915b-645a-4132-b8c1-ab398701ba66'],
|
|
12
|
-
['3510e9f1-08f6-4c5a-86a9-66e91c6093b7'],
|
|
13
|
-
['02f243d8-3225-460b-9df7-30380d96971d'],
|
|
14
|
-
['f27571d4-8c4a-4c9a-8899-932d0fa7a68c'],
|
|
15
|
-
['b87a9f9c-c7c2-4aa2-85af-87221cebce9d'],
|
|
16
|
-
])('%#. should pass regex expression check %s', (uuidString) => {
|
|
17
|
-
expect(new RegExp(regexUtil.uuid).test(uuidString)).toBeTruthy()
|
|
18
|
-
})
|
|
19
|
-
it.each([['a'], ['test'], [123], [{}], [{ uuid: '3510e9f1-08f6-4c5a-86a9-66e91c6093b7' }], [new Date()]])(
|
|
20
|
-
'%#. should pass regex expression check %s',
|
|
21
|
-
(uuidString) => {
|
|
22
|
-
expect(new RegExp(regexUtil.uuid).test(uuidString.toString())).toBeFalsy()
|
|
23
|
-
}
|
|
24
|
-
)
|
|
25
|
-
})
|
package/src/regex-util.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const regexUtil = {
|
|
2
|
-
/**
|
|
3
|
-
* This is a UUID regex expression. This is usually used in express router to constrict the values passed as a path parameter (if you are using UUID as your identifier).
|
|
4
|
-
* @return {string}
|
|
5
|
-
* @example
|
|
6
|
-
* const { uuid } = regexUtil
|
|
7
|
-
* router.route(`/users/:userId(${uuid})`).get(getUsersById)
|
|
8
|
-
* //...
|
|
9
|
-
*/
|
|
10
|
-
uuid: `\\b[0-9a-f]{8}\\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\\b[0-9a-f]{12}\\b` as const,
|
|
11
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { SingleThresholdPromise } from 'src/single-threshold-promise'
|
|
2
|
-
import { timeout } from 'src/timeout'
|
|
3
|
-
|
|
4
|
-
describe('SingleThresholdPromise', () => {
|
|
5
|
-
describe('promise', () => {
|
|
6
|
-
let callCounter = 0
|
|
7
|
-
const fake_asyncFactoryFn = jest.fn()
|
|
8
|
-
const fake_asyncRejectFactoryFn = jest.fn()
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
callCounter = 0
|
|
12
|
-
jest.useFakeTimers()
|
|
13
|
-
fake_asyncFactoryFn.mockImplementation(async (): Promise<{ callCount: number }> => {
|
|
14
|
-
await timeout(1000)
|
|
15
|
-
|
|
16
|
-
return { callCount: ++callCounter }
|
|
17
|
-
})
|
|
18
|
-
fake_asyncRejectFactoryFn.mockImplementation(async (): Promise<{ callCount: number }> => {
|
|
19
|
-
await timeout(1000)
|
|
20
|
-
throw new Error()
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
afterEach(() => {
|
|
25
|
-
jest.clearAllTimers()
|
|
26
|
-
jest.useRealTimers()
|
|
27
|
-
jest.resetAllMocks()
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should return result of the factory function when promise called', async () => {
|
|
31
|
-
const singleThresholdPromiseImplementation = new SingleThresholdPromise(fake_asyncFactoryFn)
|
|
32
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
33
|
-
|
|
34
|
-
const promise = singleThresholdPromiseImplementation.promise()
|
|
35
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
36
|
-
jest.runAllTimers()
|
|
37
|
-
expect(await promise).toEqual({ callCount: 1 })
|
|
38
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('should return the same promise result to multiple calls before the first promise is resolved ', async () => {
|
|
42
|
-
const expected = { callCount: 1 }
|
|
43
|
-
|
|
44
|
-
const singleThresholdPromiseImplementation = new SingleThresholdPromise(fake_asyncFactoryFn)
|
|
45
|
-
const promise1 = singleThresholdPromiseImplementation.promise()
|
|
46
|
-
const promise2 = singleThresholdPromiseImplementation.promise()
|
|
47
|
-
const promise3 = singleThresholdPromiseImplementation.promise()
|
|
48
|
-
|
|
49
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
50
|
-
jest.runAllTimers()
|
|
51
|
-
expect(await promise1).toEqual(expected)
|
|
52
|
-
expect(await promise2).toEqual(expected)
|
|
53
|
-
expect(await promise3).toEqual(expected)
|
|
54
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('should return different promise result to multiple calls if they are called after the promise is resolved', async () => {
|
|
58
|
-
const singleThresholdPromiseImplementation = new SingleThresholdPromise(fake_asyncFactoryFn)
|
|
59
|
-
|
|
60
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
61
|
-
|
|
62
|
-
const promise1 = singleThresholdPromiseImplementation.promise()
|
|
63
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
64
|
-
jest.runAllTimers()
|
|
65
|
-
expect(await promise1).toEqual({ callCount: 1 })
|
|
66
|
-
|
|
67
|
-
const promise2 = singleThresholdPromiseImplementation.promise()
|
|
68
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(2)
|
|
69
|
-
jest.runAllTimers()
|
|
70
|
-
expect(await promise2).toEqual({ callCount: 2 })
|
|
71
|
-
|
|
72
|
-
const promise3 = singleThresholdPromiseImplementation.promise()
|
|
73
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(3)
|
|
74
|
-
jest.runAllTimers()
|
|
75
|
-
expect(await promise3).toEqual({ callCount: 3 })
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
it('should reject all if promise is rejected', async () => {
|
|
79
|
-
const singleThresholdPromiseImplementation = new SingleThresholdPromise(fake_asyncRejectFactoryFn)
|
|
80
|
-
const promise1 = singleThresholdPromiseImplementation.promise()
|
|
81
|
-
const promise2 = singleThresholdPromiseImplementation.promise()
|
|
82
|
-
const promise3 = singleThresholdPromiseImplementation.promise()
|
|
83
|
-
expect(fake_asyncRejectFactoryFn).toHaveBeenCalledTimes(1)
|
|
84
|
-
jest.runAllTimers()
|
|
85
|
-
await promise1.then(() => expect.fail('test failed')).catch(() => undefined)
|
|
86
|
-
await promise2.then(() => expect.fail('test failed')).catch(() => undefined)
|
|
87
|
-
await promise3.then(() => expect.fail('test failed')).catch(() => undefined)
|
|
88
|
-
expect(fake_asyncRejectFactoryFn).toHaveBeenCalledTimes(1)
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
})
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { AnyFunctionPromiseNoParams } from 'src/types/any-function/promise-no-params'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* SingleThresholdPromise returns a single promise, and subsequent calls made before the promise resolves will return the same promise.
|
|
5
|
-
* @example
|
|
6
|
-
* export const refreshTokenSingleThreshold = new SingleThresholdPromise(async () => {
|
|
7
|
-
* const oldRefreshToken = await refreshTokenService.get()
|
|
8
|
-
* const { accessToken, refreshToken } = await authService.refreshToken({
|
|
9
|
-
* refreshToken: oldRefreshToken,
|
|
10
|
-
* })
|
|
11
|
-
* return { accessToken, refreshToken }
|
|
12
|
-
* })
|
|
13
|
-
*
|
|
14
|
-
* export const authService = {
|
|
15
|
-
* refreshToken: async (): Promise<{ accessToken: string; refreshToken:string }> => {
|
|
16
|
-
* return refreshTokenSingleThreshold.promise()
|
|
17
|
-
* }
|
|
18
|
-
* }
|
|
19
|
-
*/
|
|
20
|
-
export class SingleThresholdPromise<T> {
|
|
21
|
-
protected _cache: {
|
|
22
|
-
promises?: { resolve: (value: T | PromiseLike<T>) => void; reject: (reason?: any) => void }[]
|
|
23
|
-
} = {}
|
|
24
|
-
|
|
25
|
-
protected _factoryFn: AnyFunctionPromiseNoParams<T>
|
|
26
|
-
|
|
27
|
-
constructor(factoryFn: AnyFunctionPromiseNoParams<T>) {
|
|
28
|
-
this._factoryFn = factoryFn
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
protected _rejectPromises(): void {
|
|
32
|
-
if (this._cache.promises) {
|
|
33
|
-
this._cache.promises.forEach((promise) => promise.reject(new Error('Cache was cleaned')))
|
|
34
|
-
}
|
|
35
|
-
delete this._cache.promises
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async promise(): Promise<T> {
|
|
39
|
-
if ('promises' in this._cache) {
|
|
40
|
-
return new Promise<T>((resolve, reject) => {
|
|
41
|
-
this._cache.promises!.push({ reject, resolve })
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
this._cache.promises = []
|
|
46
|
-
const result = await this._factoryFn().catch((err) => {
|
|
47
|
-
this._rejectPromises()
|
|
48
|
-
throw err
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
this._cache.promises.forEach((promise) => promise.resolve(result))
|
|
52
|
-
delete this._cache.promises
|
|
53
|
-
|
|
54
|
-
return result
|
|
55
|
-
}
|
|
56
|
-
}
|