-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #39 from vodyani/beta
Beta
- Loading branch information
Showing
22 changed files
with
415 additions
and
454 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
export interface ConvertOptions { | ||
/** | ||
* When the received value does not correspond to expectations, this value is returned. | ||
* | ||
* @default null | ||
*/ | ||
default?: any; | ||
/** | ||
* The conversion is carried out if the outcome of the conditional validation function execution is true. | ||
* | ||
* @empale (num: number) => num > 0 | ||
*/ | ||
condition?: (...args: any[]) => boolean; | ||
/** | ||
* The process that carries out the transition. | ||
* | ||
* @empale (data: any) => Number(data) | ||
*/ | ||
transformer?: Function; | ||
} | ||
|
||
export class PriorityElement<T = any> { | ||
/** | ||
* Priority Indicates the weight of the queue. | ||
*/ | ||
public weight: number; | ||
/** | ||
* The actual content. | ||
*/ | ||
public value: T; | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* Create a recurring scheduled task. | ||
* | ||
* @param callback A callback function that needs to be called periodically. | ||
* @param interval number The cycle time, default 1000 (The time unit is milliseconds). | ||
* @param args any[] The callback argument. | ||
* | ||
* @publicApi | ||
*/ | ||
export function circular(callback: Function, interval: number, ...args: any[]) { | ||
let timer: NodeJS.Timeout = null; | ||
|
||
const close = () => { | ||
if (timer) clearTimeout(timer); | ||
}; | ||
|
||
const regularly = () => { | ||
close(); | ||
timer = setTimeout(regularlyHandler, interval); | ||
}; | ||
|
||
const regularlyHandler = () => { | ||
callback(...args); | ||
regularly(); | ||
}; | ||
|
||
regularly(); | ||
|
||
return { close }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { isEmpty, isMap, isNil } from 'lodash'; | ||
|
||
import { ConvertOptions } from '../common'; | ||
|
||
import { isValid, isValidArray, isValidDict } from './validate'; | ||
|
||
/** | ||
* Formatting properties of the object in the data. | ||
* | ||
* @param data The source data (`Array`|`Object`|`Map`). | ||
* @param transformer A callback function used to convert properties. | ||
* @returns any | ||
* | ||
* @publicApi | ||
* | ||
* @tips Because this method uses recursion, it can cause stack overflows when the hierarchy is too deep ! | ||
*/ | ||
export function toDeepConvertProperty(data: any, transformer: Function): any { | ||
if (isNil(data)) return data; | ||
|
||
let result = null; | ||
|
||
const pipe = [ | ||
{ | ||
isAllowUse: isMap(data), | ||
use: () => { | ||
const result = new Map(); | ||
(data as Map<any, any>).forEach((v, k) => result.set(transformer(k), v)); | ||
return result; | ||
}, | ||
}, | ||
{ | ||
isAllowUse: isValidArray(data), | ||
use: () => { | ||
return data.map((item: any) => toDeepConvertProperty(item, transformer)); | ||
}, | ||
}, | ||
{ | ||
isAllowUse: isValidDict(data), | ||
use: () => { | ||
const result = Object(); | ||
Object.keys(data).forEach((key: any) => { | ||
result[transformer(key)] = toDeepConvertProperty(data[key], transformer); | ||
}); | ||
return result; | ||
}, | ||
}, | ||
]; | ||
|
||
for (const { isAllowUse, use } of pipe) { | ||
if (isAllowUse) { | ||
result = use(); | ||
break; | ||
} | ||
|
||
result = data; | ||
} | ||
|
||
return result; | ||
} | ||
/** | ||
* The process that carries out the transition. | ||
* | ||
* @tips There are two outcomes that return the `default`: `default` is entered and either the condition fails or the value is null. | ||
* | ||
* @param data Data that needs to be transformed. | ||
* @param options Options in transformation processing. | ||
* | ||
* @publicApi | ||
*/ | ||
export function toConvert<T = any>(data: any, options?: ConvertOptions): T { | ||
const { condition, transformer, default: value } = options || Object(); | ||
|
||
if (condition) { | ||
if (transformer && condition(data)) return transformer(data); | ||
if (isValid(value)) return value; | ||
} | ||
|
||
return isNil(data) && isValid(value) ? value : data; | ||
} | ||
/** | ||
* Convert data to string. | ||
* | ||
* @param data Data that needs to be transformed. | ||
* @param defaultValue This value is returned when the incoming value does not match expectations. | ||
* | ||
* @publicApi | ||
*/ | ||
export function toString(data: any, defaultValue = ''): string { | ||
return toConvert(data, { | ||
transformer: String, | ||
default: defaultValue, | ||
condition: (data) => isValid(data) && !isEmpty(String(data)), | ||
}); | ||
} | ||
/** | ||
* Convert data to number. | ||
* | ||
* @param data Data that needs to be transformed. | ||
* @param defaultValue This value is returned when the incoming value does not match expectations. | ||
* | ||
* @publicApi | ||
*/ | ||
export function toNumber(data: any, defaultValue = 0): number { | ||
return toConvert(data, { | ||
transformer: Number, | ||
default: defaultValue, | ||
condition: (data) => isValid(data) && Number.isSafeInteger(Number(data)), | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
export * from './transform'; | ||
export * from './promise'; | ||
export * from './circular'; | ||
export * from './convert'; | ||
export * from './object'; | ||
export * from './retry'; | ||
export * from './sleep'; | ||
export * from './stream'; | ||
export * from './validate'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { deepmerge } from 'deepmerge-ts'; | ||
import { isNil, isObject } from 'lodash'; | ||
|
||
import { isValid, isValidDict, isValidString } from './validate'; | ||
|
||
/** | ||
* Walks deeply through the object and returns the property value corresponding to the specified parameter. | ||
* | ||
* @param obj The object to judge. | ||
* @param token The properties of the object and splice them with `rule`. | ||
* @param rule The rules for splicing, by default, are `.`. | ||
* @returns T | ||
* | ||
* @example | ||
* ```ts | ||
* toDeepMatch({ job: { name: 'job' }}, 'job.name') // 'job' | ||
* ``` | ||
* | ||
* @publicApi | ||
*/ | ||
export function toDeepMatch<T = any>(obj: any, token: string, rule = '.'): T { | ||
if (!isValidString(rule) || !isValidDict(obj)) return null; | ||
|
||
const stack = []; | ||
const factors = token.split(rule); | ||
|
||
let node; | ||
let nodeResult = null; | ||
let nodeDeepLevel = 0; | ||
|
||
stack.push(obj); | ||
|
||
while (stack.length > 0) { | ||
node = stack.pop(); | ||
|
||
if (nodeDeepLevel === factors.length) { | ||
nodeResult = node; | ||
break; | ||
} | ||
|
||
if (isValidDict(node)) { | ||
for (const key of Object.keys(node)) { | ||
const indexResult = factors.indexOf(key); | ||
const factorResult = factors[nodeDeepLevel]; | ||
|
||
if (key === factorResult && indexResult === nodeDeepLevel) { | ||
stack.push(node[key]); | ||
nodeDeepLevel += 1; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return nodeResult; | ||
} | ||
/** | ||
* Restores to the corresponding object based on the depth of the specified property and property value. | ||
* | ||
* @param value The object properties value. | ||
* @param token The properties of the object and splice them with `rule`. | ||
* @param rule The rules for splicing, by default, are `.`. | ||
* @returns T | ||
* | ||
* @example | ||
* ```ts | ||
* toDeepRestore('job', 'job.name') // { job: { name: 'job' }} | ||
* ``` | ||
* | ||
* @publicApi | ||
*/ | ||
export function toDeepRestore<T = object>(value: any, token: string, rule = '.'): T { | ||
if (isNil(token) || !isValidString(token)) return null; | ||
|
||
const object = Object(); | ||
const factors = token.split(rule); | ||
|
||
let node = object; | ||
|
||
while (factors.length > 0) { | ||
const key = factors.shift(); | ||
|
||
node[key] = Object(); | ||
|
||
if (factors.length === 0) { | ||
node[key] = value; | ||
} else { | ||
node = node[key]; | ||
} | ||
} | ||
|
||
return object; | ||
} | ||
/** | ||
* Deep comparison and fusion are performed on the two incoming data. | ||
* | ||
* @tips `base` will be deeply copied before merging, so it will not be changed. | ||
* | ||
* @param base The underlying data being compared. | ||
* @param source New data merged into the underlying data. | ||
* @returns `T` | `any` | ||
* | ||
* @publicApi | ||
*/ | ||
export function toDeepMerge<T = any>(base: any, source: any): T { | ||
if (isValid(base) && isNil(source)) return base; | ||
if (!(isObject(base) && isObject(source))) return source; | ||
|
||
return deepmerge(base, source) as any; | ||
} |
Oops, something went wrong.