Skip to content

Commit

Permalink
refactor: separate files for each module purpose, improved tree-shaking
Browse files Browse the repository at this point in the history
  • Loading branch information
jooy2 committed Dec 5, 2024
1 parent 747afa7 commit f2cf335
Show file tree
Hide file tree
Showing 22 changed files with 1,334 additions and 1,395 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"arrow-parens": 0,
"max-len": 0,
"no-bitwise": 0,
"import/extensions": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/explicit-function-return-type": 2
Expand All @@ -23,7 +24,6 @@
{
"files": ["test/*.test.ts"],
"rules": {
"import/extensions": 0,
"import/no-unresolved": 0,
"no-undef": 0
}
Expand Down
3 changes: 1 addition & 2 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@ CODE_OF_CONDUCT.md

# For development
.git/
.terserrc
terser.config.json
.eslintignore
.eslintrc.json
.prettierignore
.prettierrc
.mocharc.json
.editorconfig
tsconfig.json
tsconfig.prod.json
10 changes: 0 additions & 10 deletions .terserrc

This file was deleted.

4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Change Log

## 1.5.1 (2024--)
## 1.6.0 (2024--)

- **BREAKING CHANGES**: The `qsu` package no longer uses classes, so if you want to import the entire module at once, you must use something like `import * as _ from 'qsu''`. (`_` -> `* as _`)
- **BREAKING CHANGES**: The `objectTo1d` method have been renamed to `objTo1d`
- Separate files for each module purpose. Improved tree-shaking.

## 1.5.0 (2024-10-24)

Expand Down
2 changes: 1 addition & 1 deletion docs/src/en/api/web.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ order: 100

# Methods: Web <Badge type="tip" text="Plugin:qsu-web" />

This method is only available in the `qsu-web` package.
This method is only available in the `qsu-web` (JavaScript) package.

## `isBotAgent`

Expand Down
7 changes: 4 additions & 3 deletions docs/src/en/getting-started/installation-javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ $ pnpm install qsu-web # (Optional) When using the Add-on for Web

## How to Use

### Using named import (Multiple utilities in a single require) - Recommend
일반적으로 각각의 함수를 아래와 같이 부분적으로 import하여 사용할 수 있습니다.

```javascript
import { today, strCount } from 'qsu';
Expand All @@ -38,12 +38,13 @@ function main() {
}
```

### Using whole class (multiple utilities simultaneously with one object)
코드와 모듈의 구분을 위해 아래처럼 언더스코어(`_`)기호 등을 사용하여 메소드를 사용할 수 있습니다. 특별한 경우가 아니면 부분 가져오기를 사용하는 것을 권장합니다.

```javascript
import _ from 'qsu';
import * as _ from 'qsu';

function main() {
console.log(_.today()); // '20xx-xx-xx'
console.log(_.strCount('123412341234', '1')); // 3
}
```
2 changes: 1 addition & 1 deletion docs/src/ko/api/web.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ order: 100

# Methods: Web <Badge type="tip" text="Plugin:qsu-web" />

This method is only available in the `qsu-web` package.
This method is only available in the `qsu-web` (JavaScript) package.

## `isBotAgent`

Expand Down
4 changes: 2 additions & 2 deletions docs/src/ko/getting-started/installation-javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ $ pnpm install qsu-web # (선택적) Web용 추가 유틸을 사용할 때

## 사용 방법

### 명명된 가져오기 사용(단일 요구 사항에 여러 유틸리티 사용) - 권장 사항
In general, you can partially import and use each function as shown below.

```javascript
import { today, strCount } from 'qsu';
Expand All @@ -38,7 +38,7 @@ function main() {
}
```

### 전체 클래스 사용(하나의 객체에 여러 유틸리티를 동시에 사용)
You can use methods with underscore (`_`) symbols to separate code and modules, as shown below. We recommend using partial imports unless there are special cases.

```javascript
import _ from 'qsu';
Expand Down
169 changes: 169 additions & 0 deletions lib/array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import type { NumberValueObject, PositiveNumber } from './types/global';
import { is2dArray, isObject } from './verify';

export function arrShuffle(array: any[]): any[] {
if (array.length === 1) {
return array[0];
}

const newArray = array;

for (let i = array.length - 1; i > 0; i -= 1) {
const j = Math.floor(Math.random() * (i + 1));
[newArray[i], newArray[j]] = [array[j], array[i]];
}

return newArray;
}

export function arrWithDefault(defaultValue: any, length = 0): any[] {
if (length < 1) {
return [];
}

return Array(length).fill(defaultValue);
}

export function arrUnique(array: any[]): any[] {
if (is2dArray(array)) {
return Array.from(new Set(array.map((x) => JSON.stringify(x))), (x) => JSON.parse(x));
}

return [...new Set(array)];
}

export function arrWithNumber(start: number, end: number): number[] {
if (start > end) {
throw new Error('`end` is greater than `start`.');
}

return Array.from({ length: end - start + 1 }, (_, i) => i + start);
}

export function average(array: number[]): number {
return array.reduce((p, c) => p + c, 0) / array.length;
}

export function arrMove<N extends number>(
array: any[],
from: PositiveNumber<N>,
to: PositiveNumber<N>
): any[] {
const arrayLength = array.length;

if (arrayLength <= from || arrayLength <= to) {
throw new Error('Invalid move params');
}

array.splice(to, 0, array.splice(from, 1)[0]);

return array;
}

export function arrTo1dArray(array: any[]): any[] {
const convert1dArray = (arr: any[]): any[] => {
const tempArr = [];
const arrayLength = arr.length;

for (let i = 0; i < arrayLength; i += 1) {
if (typeof arr[i] !== 'object') {
tempArr.push(arr[i]);
} else if (is2dArray(arr[i])) {
tempArr.push(...convert1dArray(arr[i]));
} else {
tempArr.push(...arr[i]);
}
}

return tempArr;
};

return convert1dArray(array);
}

export function arrRepeat<N extends number>(array: any, count: PositiveNumber<N>): any[] {
if (!array || count < 1 || typeof array !== 'object') {
return [];
}

const isObj = isObject(array);
const result: any[] = [];

for (let i = 0, iLen = count; i < iLen; i += 1) {
if (isObj) {
result.push(array);
} else {
result.push(...array);
}
}

return result;
}

export function arrCount(array: string[] | number[]): NumberValueObject {
const result: NumberValueObject = {};

for (let i = 0; i < array.length; i += 1) {
const x = array[i];

result[x] = (result[x] || 0) + 1;
}

return result;
}

export function sortByObjectKey(
array: any[],
key: string,
descending = false,
numerically = false
): any[] {
if (numerically) {
const collator = new Intl.Collator([], { numeric: true });
const result = array.sort((a: any, b: any) => collator.compare(a[key], b[key]));

return descending ? result.reverse() : result;
}

return array.sort((a: any, b: any) => {
if (!descending) {
if (a[key] < b[key]) return -1;
if (a[key] > b[key]) return 1;

return 0;
}

if (a[key] > b[key]) return -1;
if (a[key] < b[key]) return 1;

return 0;
});
}

export function sortNumeric(array: string[], descending = false): string[] {
const collator = new Intl.Collator([], { numeric: true });
const result = array.sort((a: any, b: any) => collator.compare(a, b));

return descending ? result.reverse() : result;
}

export function arrGroupByMaxCount(array: any[], maxLengthPerGroup = 1): any[] {
const result = [];
const arrayLength = array.length;
let tempArray = [];

for (let i = 0; i < arrayLength; i += 1) {
if (tempArray.length === maxLengthPerGroup) {
result.push(tempArray);
tempArray = [];
}

tempArray.push(array[i]);
}

if (tempArray.length > 0) {
result.push(tempArray);
}

return result;
}
85 changes: 85 additions & 0 deletions lib/crypto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { randomBytes, createCipheriv, createDecipheriv, createHash } from 'node:crypto';

export function encrypt(
str: string,
secret: string,
algorithm = 'aes-256-cbc',
ivSize = 16,
toBase64 = false
): string {
if (!str || str.length < 1) {
return '';
}

const iv: Buffer = randomBytes(ivSize);
const cipher = createCipheriv(algorithm, secret, iv);
let enc = cipher.update(str);

enc = Buffer.concat([enc, cipher.final()]);

const encoding: BufferEncoding = toBase64 ? 'base64' : 'hex';

return `${iv.toString(encoding)}:${enc.toString(encoding)}`;
}

export function decrypt(
str: string,
secret: string,
algorithm = 'aes-256-cbc',
toBase64 = false
): string {
if (!str || str.length < 1) {
return '';
}

const encoding: BufferEncoding = toBase64 ? 'base64' : 'hex';
const arrStr: any[] = str.split(':');
const decipher = createDecipheriv(algorithm, secret, Buffer.from(arrStr.shift(), encoding));
let decrypted = decipher.update(Buffer.from(arrStr.join(':'), encoding));

decrypted = Buffer.concat([decrypted, decipher.final()]);

return decrypted.toString();
}

export function objectId(): string {
return (
Math.floor(Date.now() / 1000).toString(16) +
'x'.repeat(16).replace(/x/g, () => Math.floor(Math.random() * 16).toString(16))
);
}

export function md5Hash(str: string): string {
return createHash('md5').update(str).digest('hex');
}

export function sha1Hash(str: string): string {
return createHash('sha1').update(str).digest('hex');
}

export function sha256Hash(str: string): string {
return createHash('sha256').update(str).digest('hex');
}

export function encodeBase64(str: string): string {
return Buffer.from(str, 'utf8').toString('base64');
}

export function decodeBase64(encodedStr: string): string {
return Buffer.from(encodedStr, 'base64').toString('utf8');
}

export function strToNumberHash(str: string): number {
if (!str) {
return 0;
}

let hash = 0;

for (let i = 0; i < str.length; i += 1) {
hash = (hash << 5) - hash + str.charCodeAt(i);
hash |= 0;
}

return hash;
}
Loading

0 comments on commit f2cf335

Please sign in to comment.