Skip to content

Commit

Permalink
Merge pull request #39 from vodyani/beta
Browse files Browse the repository at this point in the history
Beta
  • Loading branch information
ChoGathK authored Sep 7, 2022
2 parents d319f38 + 2eb066e commit 5538b93
Show file tree
Hide file tree
Showing 22 changed files with 415 additions and 454 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## [8.5.2-beta.1](https://github.com/vodyani/utils/compare/v8.5.1...v8.5.2-beta.1) (2022-09-07)


### Bug Fixes

* delete unnecessary types ([768cd62](https://github.com/vodyani/utils/commit/768cd62ff21aef09fb69fecab35b0ce9ef0d4040))
* simplify naming and method calls ([57fc440](https://github.com/vodyani/utils/commit/57fc440e997ad1d8f4a2e67c128e8c89a2faed5d))

## [8.5.1](https://github.com/vodyani/utils/compare/v8.5.0...v8.5.1) (2022-08-31)


Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@vodyani/utils",
"license": "MIT",
"version": "8.5.1",
"version": "8.5.2-beta.1",
"author": "ChoGathK",
"description": "🏃🏻‍♀️ utils provides common utility functions used in server-side development.",
"homepage": "https://github.com/vodyani/utils#readme",
Expand Down
31 changes: 31 additions & 0 deletions src/common.ts
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;
}
2 changes: 0 additions & 2 deletions src/common/index.ts

This file was deleted.

49 changes: 0 additions & 49 deletions src/common/interface.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/common/type.ts

This file was deleted.

30 changes: 30 additions & 0 deletions src/method/circular.ts
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 };
}
110 changes: 110 additions & 0 deletions src/method/convert.ts
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)),
});
}
8 changes: 6 additions & 2 deletions src/method/index.ts
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';
110 changes: 110 additions & 0 deletions src/method/object.ts
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;
}
Loading

0 comments on commit 5538b93

Please sign in to comment.