@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
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { SingletonAsync } from 'src/singleton/async'
|
|
2
|
-
import { timeout } from 'src/timeout'
|
|
3
|
-
|
|
4
|
-
describe('SingletonAsync', () => {
|
|
5
|
-
const fakeResult = { sucessful: true }
|
|
6
|
-
const fake_asyncFactoryFn = jest.fn()
|
|
7
|
-
const fake_asyncRejectFactoryFn = jest.fn()
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
jest.useFakeTimers()
|
|
10
|
-
fake_asyncFactoryFn.mockImplementation(async (): Promise<{ sucessful: boolean }> => {
|
|
11
|
-
await timeout(1000)
|
|
12
|
-
|
|
13
|
-
return fakeResult
|
|
14
|
-
})
|
|
15
|
-
fake_asyncRejectFactoryFn.mockImplementation(async (): Promise<{ sucessful: boolean }> => {
|
|
16
|
-
await timeout(1000)
|
|
17
|
-
throw new Error()
|
|
18
|
-
})
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
jest.clearAllTimers()
|
|
23
|
-
jest.useRealTimers()
|
|
24
|
-
jest.resetAllMocks()
|
|
25
|
-
})
|
|
26
|
-
describe('promise', () => {
|
|
27
|
-
it('should return promised value', async () => {
|
|
28
|
-
const singletonImplementation = new SingletonAsync(fake_asyncFactoryFn)
|
|
29
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
30
|
-
const promise = singletonImplementation.promise()
|
|
31
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
32
|
-
jest.runAllTimers()
|
|
33
|
-
expect(await promise).toBe(fakeResult)
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('should subscribe multiple calls to the same promise if promise still not resolved', async () => {
|
|
37
|
-
const singletonImplementation = new SingletonAsync(fake_asyncFactoryFn)
|
|
38
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
39
|
-
const promise1 = singletonImplementation.promise()
|
|
40
|
-
const promise2 = singletonImplementation.promise()
|
|
41
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
42
|
-
|
|
43
|
-
jest.runAllTimers()
|
|
44
|
-
expect(await promise1).toBe(fakeResult)
|
|
45
|
-
expect(await promise2).toBe(fakeResult)
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
it('should second call after promise is resolved should return cache value', async () => {
|
|
49
|
-
const singletonImplementation = new SingletonAsync(fake_asyncFactoryFn)
|
|
50
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
51
|
-
const promise1 = singletonImplementation.promise()
|
|
52
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
53
|
-
|
|
54
|
-
jest.runAllTimers()
|
|
55
|
-
expect(await promise1).toBe(fakeResult)
|
|
56
|
-
|
|
57
|
-
const promise2 = singletonImplementation.promise()
|
|
58
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
59
|
-
jest.runAllTimers()
|
|
60
|
-
expect(await promise2).toBe(fakeResult)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('should reject all subscribers to promise if it is rejected', async () => {
|
|
64
|
-
const singletonImplementation = new SingletonAsync(fake_asyncRejectFactoryFn)
|
|
65
|
-
expect(fake_asyncRejectFactoryFn).not.toHaveBeenCalled()
|
|
66
|
-
const promise1 = singletonImplementation.promise()
|
|
67
|
-
const promise2 = singletonImplementation.promise()
|
|
68
|
-
expect(fake_asyncRejectFactoryFn).toHaveBeenCalledTimes(1)
|
|
69
|
-
|
|
70
|
-
jest.runAllTimers()
|
|
71
|
-
await promise1.then(() => expect.fail('test failed')).catch(() => undefined)
|
|
72
|
-
await promise2.then(() => expect.fail('test failed')).catch(() => undefined)
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
describe('cached', () => {
|
|
76
|
-
it('should return undefined if promise is never called', () => {
|
|
77
|
-
const singletonImplementation = new SingletonAsync(fake_asyncFactoryFn)
|
|
78
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
79
|
-
expect(singletonImplementation.cached()).toBeUndefined()
|
|
80
|
-
})
|
|
81
|
-
it('should cache result of the promise', async () => {
|
|
82
|
-
const singletonImplementation = new SingletonAsync(fake_asyncFactoryFn)
|
|
83
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
84
|
-
|
|
85
|
-
const promise = singletonImplementation.promise()
|
|
86
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
87
|
-
jest.runAllTimers()
|
|
88
|
-
expect(await promise).toBe(fakeResult)
|
|
89
|
-
expect(singletonImplementation.cached()).toBe(fakeResult)
|
|
90
|
-
})
|
|
91
|
-
})
|
|
92
|
-
describe('cleanCache', () => {
|
|
93
|
-
it('should reject all subscribers to the promise if cleanCache is called before promise is resolved', async () => {
|
|
94
|
-
const singletonImplementation = new SingletonAsync(fake_asyncFactoryFn)
|
|
95
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
96
|
-
const promise1 = singletonImplementation.promise().catch(() => undefined)
|
|
97
|
-
const promise2 = singletonImplementation.promise().catch(() => undefined)
|
|
98
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
99
|
-
singletonImplementation.cleanCache()
|
|
100
|
-
jest.runAllTimers()
|
|
101
|
-
await promise1.then(() => expect.fail('test failed'))
|
|
102
|
-
await promise2.then(() => expect.fail('test failed'))
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('should clean cache and after the clean cache factory should be called again on promise', async () => {
|
|
106
|
-
const singletonImplementation = new SingletonAsync(fake_asyncFactoryFn)
|
|
107
|
-
expect(fake_asyncFactoryFn).not.toHaveBeenCalled()
|
|
108
|
-
const promise1 = singletonImplementation.promise()
|
|
109
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(1)
|
|
110
|
-
jest.runAllTimers()
|
|
111
|
-
expect(await promise1).toBe(fakeResult)
|
|
112
|
-
expect(singletonImplementation.cached()).toBe(fakeResult)
|
|
113
|
-
singletonImplementation.cleanCache()
|
|
114
|
-
expect(singletonImplementation.cached()).toBeUndefined()
|
|
115
|
-
|
|
116
|
-
const promise2 = singletonImplementation.promise()
|
|
117
|
-
expect(fake_asyncFactoryFn).toHaveBeenCalledTimes(2)
|
|
118
|
-
jest.runAllTimers()
|
|
119
|
-
expect(await promise2).toBe(fakeResult)
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
})
|
package/src/singleton/async.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { AnyFunctionPromiseNoParams } from 'src/types/any-function/promise-no-params'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* This is a singleton wrapper that is used to wrap around async function. We have additional functionality to clear the cache
|
|
5
|
-
* and reject any subscriptions to initial promise. And we can also check if there is anything i cache
|
|
6
|
-
* @example
|
|
7
|
-
* export const configSingleton = new SingletonAsync(async () => {
|
|
8
|
-
* await timeout(3000)
|
|
9
|
-
* return {
|
|
10
|
-
* env: process.env.NODE_ENV
|
|
11
|
-
* } as const
|
|
12
|
-
* })
|
|
13
|
-
*
|
|
14
|
-
* // using
|
|
15
|
-
* // cache value before we call promise
|
|
16
|
-
* console.log(configSingleton().cache()) // undefined
|
|
17
|
-
* console.log('NODE_ENV: ', await configSingleton().promise().env) // NODE_ENV: prod
|
|
18
|
-
* // cache value after we call promise
|
|
19
|
-
* console.log(configSingleton().cache()) // { env: 'prod' }
|
|
20
|
-
*/
|
|
21
|
-
export class SingletonAsync<T> {
|
|
22
|
-
protected _cache: {
|
|
23
|
-
singleton?: T
|
|
24
|
-
promises?: { resolve: (value: T | PromiseLike<T>) => void; reject: (reason?: any) => void }[]
|
|
25
|
-
} = {}
|
|
26
|
-
|
|
27
|
-
protected _factory: AnyFunctionPromiseNoParams<T>
|
|
28
|
-
|
|
29
|
-
constructor(factory: AnyFunctionPromiseNoParams<T>) {
|
|
30
|
-
this._factory = factory
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Empty cached value and reject any subscribed promise that is waiting for the initial promise to be resolved.
|
|
35
|
-
*/
|
|
36
|
-
cleanCache(): void {
|
|
37
|
-
delete this._cache.singleton
|
|
38
|
-
this._rejectPromises({ error: new Error('Cache was cleaned') })
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
protected _rejectPromises(params: { error: Error }): void {
|
|
42
|
-
const { error } = params
|
|
43
|
-
|
|
44
|
-
if (this._cache.promises) {
|
|
45
|
-
this._cache.promises.forEach((promise) => promise.reject(error))
|
|
46
|
-
}
|
|
47
|
-
delete this._cache.promises
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Return singleton value in a promise. If there is no cached value then try to get it from factory.
|
|
52
|
-
* @template T
|
|
53
|
-
* @returns {Promise<T>}
|
|
54
|
-
*/
|
|
55
|
-
async promise(): Promise<T> {
|
|
56
|
-
if ('singleton' in this._cache) {
|
|
57
|
-
return this._cache.singleton!
|
|
58
|
-
}
|
|
59
|
-
if ('promises' in this._cache) {
|
|
60
|
-
return new Promise<T>((resolve, reject) => {
|
|
61
|
-
this._cache.promises!.push({ reject, resolve })
|
|
62
|
-
})
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
this._cache.promises = []
|
|
66
|
-
const result = await this._factory().catch((error) => {
|
|
67
|
-
this._rejectPromises({ error })
|
|
68
|
-
throw error
|
|
69
|
-
})
|
|
70
|
-
this._cache.singleton = result
|
|
71
|
-
|
|
72
|
-
this._cache.promises.forEach((promise) => promise.resolve(result))
|
|
73
|
-
delete this._cache.promises
|
|
74
|
-
|
|
75
|
-
return result
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Return cached value, if there is no value cached return undefined.
|
|
80
|
-
* @template T
|
|
81
|
-
* @returns {T | undefined}
|
|
82
|
-
*/
|
|
83
|
-
cached(): T | undefined {
|
|
84
|
-
if ('singleton' in this._cache) {
|
|
85
|
-
return this._cache.singleton!
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return undefined
|
|
89
|
-
}
|
|
90
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { singletonPattern } from 'src/singleton/pattern'
|
|
2
|
-
|
|
3
|
-
describe('singletonPattern', () => {
|
|
4
|
-
it('should call factory function only once', () => {
|
|
5
|
-
const factoryResult = { successful: true }
|
|
6
|
-
const factoryFn = jest.fn().mockImplementation(() => {
|
|
7
|
-
return factoryResult
|
|
8
|
-
})
|
|
9
|
-
const singletonImplementation = singletonPattern(factoryFn)
|
|
10
|
-
expect(factoryFn).not.toHaveBeenCalled()
|
|
11
|
-
expect(singletonImplementation()).toBe(factoryResult)
|
|
12
|
-
expect(factoryFn).toHaveBeenCalledTimes(1)
|
|
13
|
-
expect(singletonImplementation()).toBe(factoryResult)
|
|
14
|
-
expect(factoryFn).toHaveBeenCalledTimes(1)
|
|
15
|
-
})
|
|
16
|
-
})
|
package/src/string-util.test.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { regexUtil } from 'src/regex-util'
|
|
2
|
-
import { stringUtil } from 'src/string-util'
|
|
3
|
-
|
|
4
|
-
describe('stringUtil', () => {
|
|
5
|
-
it.each([
|
|
6
|
-
[stringUtil.generateUUID()],
|
|
7
|
-
[stringUtil.generateUUID()],
|
|
8
|
-
[stringUtil.generateUUID()],
|
|
9
|
-
[stringUtil.generateUUID()],
|
|
10
|
-
[stringUtil.generateUUID()],
|
|
11
|
-
[stringUtil.generateUUID()],
|
|
12
|
-
[stringUtil.generateUUID()],
|
|
13
|
-
[stringUtil.generateUUID()],
|
|
14
|
-
[stringUtil.generateUUID()],
|
|
15
|
-
])('%#. should generate valid uuid %s', (uuid) => {
|
|
16
|
-
expect(new RegExp(regexUtil.uuid).test(uuid)).toBeTruthy()
|
|
17
|
-
})
|
|
18
|
-
})
|
package/src/string-util.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export const stringUtil = {
|
|
2
|
-
/**
|
|
3
|
-
* Generate random UUID
|
|
4
|
-
* @return {string}
|
|
5
|
-
* @example
|
|
6
|
-
* console.log(stringUtil.uuid()) // "69bfda25-df3f-46b4-8bbb-955cf5193426"
|
|
7
|
-
*/
|
|
8
|
-
generateUUID: (): string => {
|
|
9
|
-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
10
|
-
const r = (Math.random() * 16) | 0
|
|
11
|
-
if (c == 'x') {
|
|
12
|
-
return r.toString(16)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return ((r & 0x3) | 0x8).toString(16)
|
|
16
|
-
})
|
|
17
|
-
},
|
|
18
|
-
}
|
package/src/time-util.test.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { DurationUnit, DurationUnitType, TimeUtil } from 'src/time-util'
|
|
2
|
-
|
|
3
|
-
describe('TimeUtil', () => {
|
|
4
|
-
const constantNowDate = new Date('2022-01-01T00:00:00.000Z')
|
|
5
|
-
const constantNowUnix = 1640995200000 // 2022-01-01T00:00:00 UTC
|
|
6
|
-
const constantNowUnixSec = 1640995200 // 2022-01-01T00:00:00 UTC
|
|
7
|
-
const timeUtil = new TimeUtil()
|
|
8
|
-
|
|
9
|
-
beforeAll(() => {
|
|
10
|
-
jest.useFakeTimers('modern' as any)
|
|
11
|
-
jest.setSystemTime(constantNowDate.getTime())
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
afterAll(() => {
|
|
15
|
-
jest.useRealTimers()
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
describe('now', () => {
|
|
19
|
-
it('should return mocked date', () => {
|
|
20
|
-
expect(timeUtil.now().toISOString()).toEqual(constantNowDate.toISOString())
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
describe('dateToUnix', () => {
|
|
25
|
-
it('should convert constant date to constant unix', () => {
|
|
26
|
-
expect(timeUtil.dateToUnix(timeUtil.now())).toEqual(constantNowUnix)
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
describe('dateToUnixSec', () => {
|
|
31
|
-
it('should convert constant date to constant unixSec', () => {
|
|
32
|
-
expect(timeUtil.dateToUnixSec(timeUtil.now())).toEqual(constantNowUnixSec)
|
|
33
|
-
})
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
describe('unixToDate', () => {
|
|
37
|
-
it('should convert constant date to constant unix', () => {
|
|
38
|
-
expect(timeUtil.unixToDate(constantNowUnix)).toEqual(timeUtil.now())
|
|
39
|
-
})
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
describe('unixSecToDate', () => {
|
|
43
|
-
it('should convert constant date to constant unixSec', () => {
|
|
44
|
-
expect(timeUtil.unixSecToDate(constantNowUnixSec)).toEqual(timeUtil.now())
|
|
45
|
-
})
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
describe('addToDate', () => {
|
|
49
|
-
it.each([
|
|
50
|
-
[DurationUnit.MILLISECOND, 1, new Date('2022-01-01T00:00:00.001Z')],
|
|
51
|
-
[DurationUnit.SECOND, 1, new Date('2022-01-01T00:00:01.000Z')],
|
|
52
|
-
[DurationUnit.MINUTE, 1, new Date('2022-01-01T00:01:00.000Z')],
|
|
53
|
-
[DurationUnit.HOUR, 1, new Date('2022-01-01T01:00:00.000Z')],
|
|
54
|
-
[DurationUnit.DAY, 1, new Date('2022-01-02T00:00:00.000Z')],
|
|
55
|
-
[DurationUnit.WEEK, 1, new Date('2022-01-08T00:00:00.000Z')],
|
|
56
|
-
[DurationUnit.MONTH, 1, new Date('2022-02-01T00:00:00.000Z')],
|
|
57
|
-
[DurationUnit.YEAR, 1, new Date('2023-01-01T00:00:00.000Z')],
|
|
58
|
-
[DurationUnit.MILLISECOND, -1, new Date('2021-12-31T23:59:59.999Z')],
|
|
59
|
-
[DurationUnit.SECOND, -1, new Date('2021-12-31T23:59:59.000Z')],
|
|
60
|
-
[DurationUnit.MINUTE, -1, new Date('2021-12-31T23:59:00.000Z')],
|
|
61
|
-
[DurationUnit.HOUR, -1, new Date('2021-12-31T23:00:00.000Z')],
|
|
62
|
-
[DurationUnit.DAY, -1, new Date('2021-12-31T00:00:00.000Z')],
|
|
63
|
-
[DurationUnit.WEEK, -1, new Date('2021-12-25T00:00:00.000Z')],
|
|
64
|
-
[DurationUnit.MONTH, -1, new Date('2021-12-01T00:00:00.000Z')],
|
|
65
|
-
[DurationUnit.YEAR, -1, new Date('2021-01-01T00:00:00.000Z')],
|
|
66
|
-
['MILLISECOND', 1, new Date('2022-01-01T00:00:00.001Z')],
|
|
67
|
-
['SECOND', 1, new Date('2022-01-01T00:00:01.000Z')],
|
|
68
|
-
['MINUTE', 1, new Date('2022-01-01T00:01:00.000Z')],
|
|
69
|
-
['HOUR', 1, new Date('2022-01-01T01:00:00.000Z')],
|
|
70
|
-
['DAY', 1, new Date('2022-01-02T00:00:00.000Z')],
|
|
71
|
-
['WEEK', 1, new Date('2022-01-08T00:00:00.000Z')],
|
|
72
|
-
['MONTH', 1, new Date('2022-02-01T00:00:00.000Z')],
|
|
73
|
-
['YEAR', 1, new Date('2023-01-01T00:00:00.000Z')],
|
|
74
|
-
['MILLISECOND', -1, new Date('2021-12-31T23:59:59.999Z')],
|
|
75
|
-
['SECOND', -1, new Date('2021-12-31T23:59:59.000Z')],
|
|
76
|
-
['MINUTE', -1, new Date('2021-12-31T23:59:00.000Z')],
|
|
77
|
-
['HOUR', -1, new Date('2021-12-31T23:00:00.000Z')],
|
|
78
|
-
['DAY', -1, new Date('2021-12-31T00:00:00.000Z')],
|
|
79
|
-
['WEEK', -1, new Date('2021-12-25T00:00:00.000Z')],
|
|
80
|
-
['MONTH', -1, new Date('2021-12-01T00:00:00.000Z')],
|
|
81
|
-
['YEAR', -1, new Date('2021-01-01T00:00:00.000Z')],
|
|
82
|
-
] as [DurationUnitType | DurationUnit, number, Date][])(
|
|
83
|
-
'%#. should increase date by unit %s and value %s and get date $s',
|
|
84
|
-
(unit, value, expected) => {
|
|
85
|
-
expect(timeUtil.addToDate({ date: timeUtil.now(), unit, value })).toEqual(expected)
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
})
|
|
89
|
-
})
|
package/src/time-util.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import add from 'date-fns/add'
|
|
2
|
-
import addMilliseconds from 'date-fns/addMilliseconds'
|
|
3
|
-
import format from 'date-fns/format'
|
|
4
|
-
import parse from 'date-fns/parse'
|
|
5
|
-
|
|
6
|
-
export enum DurationUnit {
|
|
7
|
-
MILLISECOND = 'MILLISECOND',
|
|
8
|
-
SECOND = 'SECOND',
|
|
9
|
-
MINUTE = 'MINUTE',
|
|
10
|
-
HOUR = 'HOUR',
|
|
11
|
-
DAY = 'DAY',
|
|
12
|
-
WEEK = 'WEEK',
|
|
13
|
-
MONTH = 'MONTH',
|
|
14
|
-
YEAR = 'YEAR',
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export type DurationUnitType = `${DurationUnit}`
|
|
18
|
-
|
|
19
|
-
export class TimeUtil {
|
|
20
|
-
/**
|
|
21
|
-
* return date object with the current time
|
|
22
|
-
* @return {Date}
|
|
23
|
-
* @example
|
|
24
|
-
* console.log(new TimeUtil().now().toISOString()) // 2023-03-08T19:45:01.991Z
|
|
25
|
-
*/
|
|
26
|
-
now(): Date {
|
|
27
|
-
return new Date()
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Convert date object to unix timestamp (milliseconds)
|
|
32
|
-
* @param {Date} date
|
|
33
|
-
* @return {number}
|
|
34
|
-
* @example
|
|
35
|
-
* // timeUtil.now().toISOString() === 2023-03-08T19:45:01.991Z
|
|
36
|
-
* const timeUtil = new TimeUtil()
|
|
37
|
-
* console.log(timeUtil.dateToUnix(timeUtil.now())) // 1678304701991
|
|
38
|
-
*/
|
|
39
|
-
dateToUnix(date: Date): number {
|
|
40
|
-
return +format(date, 'T')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Convert date object to unix timestamp (seconds)
|
|
45
|
-
* @param {Date} date
|
|
46
|
-
* @return {number}
|
|
47
|
-
* @example
|
|
48
|
-
* // timeUtil.now().toISOString() === 2023-03-08T19:45:01.991Z
|
|
49
|
-
* const timeUtil = new TimeUtil()
|
|
50
|
-
* console.log(timeUtil.dateToUnix(timeUtil.now())) // 1678304701
|
|
51
|
-
*/
|
|
52
|
-
dateToUnixSec(date: Date): number {
|
|
53
|
-
return +format(date, 't')
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Convert unix timestamp (milliseconds) to date object
|
|
58
|
-
* @param {number} unix
|
|
59
|
-
* @return {Date}
|
|
60
|
-
* @example
|
|
61
|
-
* const timeUtil = new TimeUtil()
|
|
62
|
-
* console.log(timeUtil.unixToDate(1678304701991).toISOString()) // 2023-03-08T19:45:01.991Z
|
|
63
|
-
*/
|
|
64
|
-
unixToDate(unix: number): Date {
|
|
65
|
-
return parse(unix.toString(), 'T', this.now())
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Convert unix timestamp (seconds) to date object
|
|
70
|
-
* @param {number} unix
|
|
71
|
-
* @return {Date}
|
|
72
|
-
* @example
|
|
73
|
-
* const timeUtil = new TimeUtil()
|
|
74
|
-
* console.log(timeUtil.unixToDate(1678304701).toISOString()) // 2023-03-08T19:45:01.000Z
|
|
75
|
-
*/
|
|
76
|
-
unixSecToDate(unix: number): Date {
|
|
77
|
-
return parse(unix.toString(), 't', this.now())
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Change the value of date by unit/value pare.
|
|
82
|
-
* @param {{units: DurationUnitType, value: number, date: Date}} params
|
|
83
|
-
* @return {Date}
|
|
84
|
-
* @example
|
|
85
|
-
* // timeUtil.now().toISOString() === 2023-03-08T19:45:01.991Z
|
|
86
|
-
* const timeUtil = new TimeUtil()
|
|
87
|
-
* console.log(timeUtil.addToDate({date: timeUtil.now(), unit: 'DAY', value: 1 }).toISOString()) // 2023-03-09T19:45:01.991Z
|
|
88
|
-
* console.log(timeUtil.addToDate({date: timeUtil.now(), unit: DurationUnit.MONTH, value: -1 }).toISOString()) //2023-02-08T19:45:01.991Z
|
|
89
|
-
*/
|
|
90
|
-
addToDate(params: { unit: DurationUnitType | DurationUnit; value: number; date: Date }): Date {
|
|
91
|
-
const { date, unit, value } = params
|
|
92
|
-
if (`${unit}` === 'MILLISECOND') {
|
|
93
|
-
return addMilliseconds(date, value)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return add(date, { [`${unit.toLowerCase()}s`]: value })
|
|
97
|
-
}
|
|
98
|
-
}
|
package/src/timeout.test.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { timeout } from 'src/timeout'
|
|
2
|
-
|
|
3
|
-
describe('timeout', () => {
|
|
4
|
-
const fn_one = jest.fn()
|
|
5
|
-
const fn_two = jest.fn()
|
|
6
|
-
const fn_three = jest.fn()
|
|
7
|
-
const fn_onResolve = jest.fn()
|
|
8
|
-
|
|
9
|
-
const timeoutImplementation = async (): Promise<void> => {
|
|
10
|
-
fn_one()
|
|
11
|
-
await timeout(1000)
|
|
12
|
-
fn_two()
|
|
13
|
-
await timeout(1000)
|
|
14
|
-
fn_three()
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
beforeEach(() => {
|
|
18
|
-
jest.useFakeTimers()
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
jest.clearAllTimers()
|
|
23
|
-
jest.useRealTimers()
|
|
24
|
-
jest.resetAllMocks()
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('should function one by one with pause of 1000ms', async () => {
|
|
28
|
-
expect(fn_one).toHaveBeenCalledTimes(0)
|
|
29
|
-
expect(fn_two).toHaveBeenCalledTimes(0)
|
|
30
|
-
expect(fn_three).toHaveBeenCalledTimes(0)
|
|
31
|
-
expect(fn_onResolve).toHaveBeenCalledTimes(0)
|
|
32
|
-
|
|
33
|
-
const promise1 = timeoutImplementation().then(() => {
|
|
34
|
-
return fn_onResolve()
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
expect(fn_one).toHaveBeenCalledTimes(1)
|
|
38
|
-
expect(fn_two).toHaveBeenCalledTimes(0)
|
|
39
|
-
expect(fn_three).toHaveBeenCalledTimes(0)
|
|
40
|
-
expect(fn_onResolve).toHaveBeenCalledTimes(0)
|
|
41
|
-
|
|
42
|
-
jest.advanceTimersByTime(1000)
|
|
43
|
-
await Promise.resolve()
|
|
44
|
-
|
|
45
|
-
expect(fn_one).toHaveBeenCalledTimes(1)
|
|
46
|
-
expect(fn_two).toHaveBeenCalledTimes(1)
|
|
47
|
-
expect(fn_three).toHaveBeenCalledTimes(0)
|
|
48
|
-
expect(fn_onResolve).toHaveBeenCalledTimes(0)
|
|
49
|
-
|
|
50
|
-
jest.advanceTimersByTime(1000)
|
|
51
|
-
await Promise.resolve()
|
|
52
|
-
|
|
53
|
-
expect(fn_one).toHaveBeenCalledTimes(1)
|
|
54
|
-
expect(fn_two).toHaveBeenCalledTimes(1)
|
|
55
|
-
expect(fn_three).toHaveBeenCalledTimes(1)
|
|
56
|
-
expect(fn_onResolve).toHaveBeenCalledTimes(0)
|
|
57
|
-
|
|
58
|
-
await promise1
|
|
59
|
-
|
|
60
|
-
expect(fn_one).toHaveBeenCalledTimes(1)
|
|
61
|
-
expect(fn_two).toHaveBeenCalledTimes(1)
|
|
62
|
-
expect(fn_three).toHaveBeenCalledTimes(1)
|
|
63
|
-
expect(fn_onResolve).toHaveBeenCalledTimes(1)
|
|
64
|
-
})
|
|
65
|
-
})
|
package/src/type-util.test.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { typeUtil } from 'src/type-util'
|
|
2
|
-
|
|
3
|
-
describe('typeUtil', () => {
|
|
4
|
-
describe('exhaustiveMessage', () => {
|
|
5
|
-
it('should return string', () => {
|
|
6
|
-
const testMessage = 'testMessage'
|
|
7
|
-
// @ts-ignore
|
|
8
|
-
expect(typeUtil.exhaustiveMessage(testMessage, '')).toEqual(testMessage)
|
|
9
|
-
})
|
|
10
|
-
})
|
|
11
|
-
describe('exhaustiveError', () => {
|
|
12
|
-
it('should return string', () => {
|
|
13
|
-
const testMessage = 'testMessage'
|
|
14
|
-
// @ts-ignore
|
|
15
|
-
const error = typeUtil.exhaustiveError(testMessage, '')
|
|
16
|
-
expect(error).toBeInstanceOf(Error)
|
|
17
|
-
expect(error.message).toEqual(testMessage)
|
|
18
|
-
})
|
|
19
|
-
})
|
|
20
|
-
})
|
package/src/type-util.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export const typeUtil = {
|
|
2
|
-
/**
|
|
3
|
-
* This is the similar to exhaustiveMessage, but instead of message we are returning error so we can throw it
|
|
4
|
-
* @param {string} message
|
|
5
|
-
* @param {never} _
|
|
6
|
-
* @return {Error}
|
|
7
|
-
* @example
|
|
8
|
-
* export type Animal = 'cat' | 'dog' | 'bird';
|
|
9
|
-
*
|
|
10
|
-
* export const makeSound = (animal: Animal): string => {
|
|
11
|
-
* switch (animal) {
|
|
12
|
-
* case 'cat':
|
|
13
|
-
* return 'Meow'
|
|
14
|
-
* case 'dog':
|
|
15
|
-
* return 'Woof'
|
|
16
|
-
* case 'bird':
|
|
17
|
-
* return 'Tweet'
|
|
18
|
-
* default:
|
|
19
|
-
* throw typeUtil.exhaustiveError('Unknown animal [animal]', animal)
|
|
20
|
-
* }
|
|
21
|
-
* }
|
|
22
|
-
*/
|
|
23
|
-
exhaustiveError: (message: string, _: never): Error => {
|
|
24
|
-
return new Error(message)
|
|
25
|
-
},
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* In TypeScript, exhaustiveMessage is a technique that can be used with switch statements to ensure that all possible cases are handled.
|
|
29
|
-
*
|
|
30
|
-
* When using switch statements, it is common to have a default case that handles any unanticipated cases. However, sometimes it is important to ensure that all cases are explicitly handled to avoid potential errors or bugs in the code.
|
|
31
|
-
* @param {string} message
|
|
32
|
-
* @param {never} _
|
|
33
|
-
* @return {string}
|
|
34
|
-
* @example
|
|
35
|
-
* export type Animal = 'cat' | 'dog' | 'bird';
|
|
36
|
-
*
|
|
37
|
-
* export const makeSound = (animal: Animal): string => {
|
|
38
|
-
* switch (animal) {
|
|
39
|
-
* case 'cat':
|
|
40
|
-
* return 'Meow'
|
|
41
|
-
* case 'dog':
|
|
42
|
-
* return 'Woof'
|
|
43
|
-
* case 'bird':
|
|
44
|
-
* return 'Tweet'
|
|
45
|
-
* default:
|
|
46
|
-
* console.error(new TypeUtil().exhaustiveMessage('Unknown animal [animal]', animal))
|
|
47
|
-
* return 'unknown sound'
|
|
48
|
-
* }
|
|
49
|
-
* }
|
|
50
|
-
*/
|
|
51
|
-
exhaustiveMessage: (message: string, _: never): string => {
|
|
52
|
-
return message
|
|
53
|
-
},
|
|
54
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type AnyFunction<T> = (...args: any[]) => T
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type AnyFunctionNoParams<T> = () => T
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type AnyFunctionPromiseNoParams<T> = () => Promise<T>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export type AnyFunctionPromise<T> = (...args: any[]) => Promise<T>
|
package/src/types/types.d.ts
DELETED