From fca0133dbe67529779db837f472530707548a3d9 Mon Sep 17 00:00:00 2001 From: KaKa Date: Thu, 18 Jan 2024 15:30:33 +0800 Subject: [PATCH 1/3] feat(crypto): initial commit --- .github/workflows/ci-crypto.yml | 115 ++++++++ packages/crypto/.eslintrc | 24 ++ packages/crypto/lib/aes.ts | 86 ++++++ packages/crypto/lib/base64.ts | 60 +++++ packages/crypto/lib/hash.ts | 43 +++ packages/crypto/lib/index.ts | 5 + packages/crypto/lib/mjs/package.json | 3 + packages/crypto/lib/scrypt.ts | 32 +++ packages/crypto/lib/utils.ts | 22 ++ packages/crypto/package.json | 53 ++++ packages/crypto/test/aes.test.ts | 170 ++++++++++++ packages/crypto/test/base64.test.ts | 185 +++++++++++++ packages/crypto/test/hash.test.ts | 109 ++++++++ packages/crypto/test/index.test.ts | 30 +++ packages/crypto/test/scrypt.test.ts | 41 +++ packages/crypto/test/utils.test.ts | 39 +++ packages/crypto/tsconfig.cjs.json | 8 + packages/crypto/tsconfig.json | 26 ++ packages/crypto/tsconfig.mjs.json | 11 + packages/utils/package.json | 1 - packages/utils/test/index.test.ts | 142 +++++----- pnpm-lock.yaml | 378 +++------------------------ 22 files changed, 1172 insertions(+), 411 deletions(-) create mode 100644 .github/workflows/ci-crypto.yml create mode 100644 packages/crypto/.eslintrc create mode 100644 packages/crypto/lib/aes.ts create mode 100644 packages/crypto/lib/base64.ts create mode 100644 packages/crypto/lib/hash.ts create mode 100644 packages/crypto/lib/index.ts create mode 100644 packages/crypto/lib/mjs/package.json create mode 100644 packages/crypto/lib/scrypt.ts create mode 100644 packages/crypto/lib/utils.ts create mode 100644 packages/crypto/package.json create mode 100644 packages/crypto/test/aes.test.ts create mode 100644 packages/crypto/test/base64.test.ts create mode 100644 packages/crypto/test/hash.test.ts create mode 100644 packages/crypto/test/index.test.ts create mode 100644 packages/crypto/test/scrypt.test.ts create mode 100644 packages/crypto/test/utils.test.ts create mode 100644 packages/crypto/tsconfig.cjs.json create mode 100644 packages/crypto/tsconfig.json create mode 100644 packages/crypto/tsconfig.mjs.json diff --git a/.github/workflows/ci-crypto.yml b/.github/workflows/ci-crypto.yml new file mode 100644 index 00000000..5d72e5eb --- /dev/null +++ b/.github/workflows/ci-crypto.yml @@ -0,0 +1,115 @@ +name: Continuous Integration - Crypto + +on: + push: + paths: + - ".github/workflows/ci-crypto.yml" + - "packages/crypto/**" + pull_request: + paths: + - ".github/workflows/ci-crypto.yml" + - "packages/crypto/**" + +jobs: + linter: + name: Lint Code + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Check out repo + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - uses: actions/cache@v4 + name: Setup pnpm cache + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Lint code + run: pnpm --filter "./packages/crypto" run lint + + test: + name: Test + runs-on: ${{ matrix.os }} + permissions: + contents: read + strategy: + matrix: + node-version: [18, 20] + os: [macos-latest, ubuntu-latest, windows-latest] + steps: + - name: Check out repo + uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Setup Node ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - uses: actions/cache@v4 + name: Setup pnpm cache + with: + path: ${{ env.STORE_PATH }} + key: ${{ runner.os }}-${{ matrix.node-version }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.node-version }}-pnpm-store- + + - name: Install dependencies + run: pnpm install + + - name: Run tests + run: pnpm --filter "./packages/crypto" run test + + automerge: + name: Automerge Dependabot PRs + if: > + github.event_name == 'pull_request' && + github.event.pull_request.user.login == 'dependabot[bot]' + needs: test + permissions: + pull-requests: write + contents: write + runs-on: ubuntu-latest + steps: + - uses: fastify/github-action-merge-dependabot@v3 + with: + exclude: ${{ inputs.auto-merge-exclude }} + github-token: ${{ secrets.GITHUB_TOKEN }} + target: major diff --git a/packages/crypto/.eslintrc b/packages/crypto/.eslintrc new file mode 100644 index 00000000..ea67ea7d --- /dev/null +++ b/packages/crypto/.eslintrc @@ -0,0 +1,24 @@ +{ + "extends": "standard-with-typescript", + "parserOptions": { + "project": "./tsconfig.json" + }, + "rules": { + // conflict between standard and standard-typescript + "no-void": ["error", { "allowAsStatement": true }] + }, + "overrides": [ + { + "files": ["**/*.test.ts"], + "rules": { + "@typescript-eslint/no-floating-promises": "off" + } + }, + { + "files": ["scripts/*.mjs"], + "rules": { + "@typescript-eslint/explicit-function-return-type": "off" + } + } + ] +} diff --git a/packages/crypto/lib/aes.ts b/packages/crypto/lib/aes.ts new file mode 100644 index 00000000..2eab88f8 --- /dev/null +++ b/packages/crypto/lib/aes.ts @@ -0,0 +1,86 @@ +import { createCipheriv, createDecipheriv, scryptSync, type BinaryLike, type CipherCCMTypes, type CipherGCM, type CipherGCMTypes, type DecipherGCM } from 'crypto' +import { randomBytes } from './utils' + +export function computeKeySize (algorithm: CipherCCMTypes | CipherGCMTypes = 'aes-256-gcm'): number { + switch (algorithm) { + case 'aes-128-ccm': + case 'aes-128-gcm': + return 16 + case 'aes-192-ccm': + case 'aes-192-gcm': + return 24 + case 'aes-256-ccm': + case 'aes-256-gcm': + case 'chacha20-poly1305': + default: + return 32 + } +} + +export function computeIVSize (algorithm: CipherCCMTypes | CipherGCMTypes = 'aes-256-gcm'): number { + switch (algorithm) { + case 'chacha20-poly1305': + return 12 + case 'aes-128-ccm': + case 'aes-128-gcm': + case 'aes-192-ccm': + case 'aes-192-gcm': + case 'aes-256-ccm': + case 'aes-256-gcm': + default: + return 16 + } +} + +export interface EncryptionResult { + value: string + iv: string + authTag: string + secret: BinaryLike + salt: BinaryLike +} + +export function encrypt ( + token: string, + algorithm: CipherCCMTypes | CipherGCMTypes = 'aes-256-gcm', + secret: BinaryLike = randomBytes(32, 'hex'), + salt: BinaryLike = randomBytes(32, 'hex'), + authTagLength = 16 +): EncryptionResult { + const key: Buffer = scryptSync(secret, salt, computeKeySize(algorithm)) + const ivSize = computeIVSize(algorithm) + const iv: Buffer = Buffer.alloc(ivSize, randomBytes(ivSize), 'binary') + const option: any = [algorithm, key, iv, { authTagLength }] + const cipher: CipherGCM = createCipheriv.apply(createCipheriv, option) as CipherGCM + cipher.setAAD(Buffer.from(`${String(secret)}${String(salt)}`)) + + let value = cipher.update(token, 'utf8', 'hex') + value += cipher.final('hex') + return { + value, + iv: iv.toString('hex'), + authTag: cipher.getAuthTag().toString('hex'), + secret, + salt + } +} + +export function decrypt ( + encrypted: string, + iv: Buffer, + authTag: Buffer, + algorithm: CipherCCMTypes | CipherGCMTypes, + secret: BinaryLike, + salt: BinaryLike, + authTagLength = 16 +): string { + const key: Buffer = scryptSync(secret, salt, computeKeySize(algorithm)) + const option: any = [algorithm, key, iv, { authTagLength }] + const decipher = createDecipheriv.apply(createDecipheriv, option) as DecipherGCM + decipher.setAAD(Buffer.from(`${String(secret)}${String(salt)}`)) + decipher.setAuthTag(authTag) + + let value = decipher.update(encrypted, 'hex', 'utf8') + value += decipher.final('utf8') + return value +} diff --git a/packages/crypto/lib/base64.ts b/packages/crypto/lib/base64.ts new file mode 100644 index 00000000..cd65fcb3 --- /dev/null +++ b/packages/crypto/lib/base64.ts @@ -0,0 +1,60 @@ +export const CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' +export const URLCHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_ ' + +export type Base64Charset = 'default' | 'url' | 'custom' + +export function encodeReplaceCharset ( + value: string, + charset: Base64Charset = 'default', + custom: string = URLCHARSET +): string { + if (charset === 'default') return value + const replaced = [] + for (let i = value.length - 1; i >= 0; i--) { + const char = value.charAt(i) + const indexOf = CHARSET.indexOf(char) + replaced.push(custom.charAt(indexOf)) + } + return replaced + .reverse() + .join('') + .trim() +} + +export function encode ( + value: string | Buffer | Uint8Array, + charset: Base64Charset = 'default', + custom: string = URLCHARSET +): string { + // Cast Uint8Array to Buffer + if (value instanceof Uint8Array) { + value = Buffer.from(value) + } + // Allocate Buffer + value = Buffer.alloc(value.length, value as Buffer | string) + return encodeReplaceCharset(value.toString('base64'), charset, custom) +} + +export function decodeReplaceCharset ( + value: string, + charset: Base64Charset = 'default', + custom: string = URLCHARSET +): string { + if (charset === 'default') return value + let replaced: string[] | string = [] + for (let i = value.length - 1; i >= 0; i--) { + const char = value[i] + const indexOf = custom.indexOf(char) + replaced.push(CHARSET[indexOf]) + } + replaced = replaced.reverse().join('') + while (replaced.length % 4 > 0) { + replaced += '=' + } + return replaced +} + +export function decode (value: string, charset: Base64Charset = 'default', custom: string = URLCHARSET): string { + const val = Buffer.from(decodeReplaceCharset(value, charset, custom), 'base64') + return val.toString('utf8') +} diff --git a/packages/crypto/lib/hash.ts b/packages/crypto/lib/hash.ts new file mode 100644 index 00000000..ad3e7cb5 --- /dev/null +++ b/packages/crypto/lib/hash.ts @@ -0,0 +1,43 @@ +import { createHash, type BinaryLike, type BinaryToTextEncoding } from 'crypto' + +export function hash ( + value: BinaryLike, + encoding: BinaryToTextEncoding = 'hex', + algorithm = 'sha512' +): string { + const hash = createHash(algorithm) + hash.update(value) + return hash.digest(encoding) +} + +export function md5 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'md5') +} + +export function sha1 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'sha1') +} + +export function sha224 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'sha224') +} + +export function sha256 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'sha256') +} + +export function sha384 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'sha384') +} + +export function sha512 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'sha512') +} + +export function shake128 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'shake128') +} + +export function shake256 (value: string, encoding: BinaryToTextEncoding = 'hex'): string { + return hash(value, encoding, 'shake256') +} diff --git a/packages/crypto/lib/index.ts b/packages/crypto/lib/index.ts new file mode 100644 index 00000000..f57fe155 --- /dev/null +++ b/packages/crypto/lib/index.ts @@ -0,0 +1,5 @@ +export * as AES from './aes' +export * as Base64 from './base64' +export * from './hash' +export * as Scrypt from './scrypt' +export * from './utils' diff --git a/packages/crypto/lib/mjs/package.json b/packages/crypto/lib/mjs/package.json new file mode 100644 index 00000000..3dbc1ca5 --- /dev/null +++ b/packages/crypto/lib/mjs/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/packages/crypto/lib/scrypt.ts b/packages/crypto/lib/scrypt.ts new file mode 100644 index 00000000..1f95b1c8 --- /dev/null +++ b/packages/crypto/lib/scrypt.ts @@ -0,0 +1,32 @@ +import { randomBytes, scrypt, timingSafeEqual } from 'crypto' + +export async function hash (value: string, keylen = 32, cost = 65536, blockSize = 8, parallelization = 1): Promise { + // salt is limited to at least 16 bytes long + const salt = randomBytes(Math.min(16, keylen / 2)) + const maxmem = 128 * cost * blockSize * 2 + return await new Promise(function (resolve, reject) { + scrypt(value, salt, Number(keylen), { cost, blockSize, parallelization, maxmem }, function (error, key) { + /* istanbul ignore next */ + if (error !== null) reject(error) + resolve(`$scrypt$L=${String(keylen)}$N=${String(Math.log2(cost))},r=${String(blockSize)},p=${String(parallelization)}$${salt.toString('base64url')}$${key.toString('base64url')}`) + }) + }) +} + +export const REGEXP = /^\$scrypt\$L=(\d+)\$N=(\d+),r=(\d+),p=(\d+)\$([A-Za-z0-9_-]+)\$([A-Za-z0-9_-]+)$/ + +export async function compare (value: string, hashed: string): Promise { + const array = REGEXP.exec(hashed) + if (array === null) throw new Error('Invalid Scrypt Hash Format.') + const [,keylen, cost, blockSize, parallelization, salt, hash] = array + const maxmem = 128 * Math.pow(2, Number(cost)) * Number(blockSize) * 2 + return await new Promise(function (resolve, reject) { + scrypt(value, Buffer.from(salt, 'base64url'), Number(keylen), { + cost: Math.pow(2, Number(cost)), blockSize: Number(blockSize), parallelization: Number(parallelization), maxmem + }, function (error, key) { + /* istanbul ignore next */ + if (error !== null) reject(error) + resolve(timingSafeEqual(key, Buffer.from(hash, 'base64url'))) + }) + }) +} diff --git a/packages/crypto/lib/utils.ts b/packages/crypto/lib/utils.ts new file mode 100644 index 00000000..cc4a12a5 --- /dev/null +++ b/packages/crypto/lib/utils.ts @@ -0,0 +1,22 @@ +import * as crypto from 'crypto' + +export type RandomBytesEncode = BufferEncoding | 'buffer' + +export function randomBytes (size: number, encoding?: 'buffer'): Buffer +export function randomBytes (size: number, encoding: BufferEncoding): string +export function randomBytes (size: number, encoding: RandomBytesEncode = 'buffer'): string | Buffer { + const randomBytes = crypto.randomBytes(size) + if (encoding === 'buffer') { + return randomBytes + } else { + return randomBytes.toString(encoding) + } +} + +export function randomNum (digit: number = 6): string { + return crypto.randomInt(0, Math.pow(10, digit)).toString().padStart(digit, '0') +} + +export function randomUUID (): string { + return crypto.randomUUID() +} diff --git a/packages/crypto/package.json b/packages/crypto/package.json new file mode 100644 index 00000000..0d6f81e8 --- /dev/null +++ b/packages/crypto/package.json @@ -0,0 +1,53 @@ +{ + "name": "@kakang/crypto", + "version": "1.1.1", + "description": "", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "exports": { + ".": { + "import": "./lib/mjs/index.js", + "require": "./lib/index.js" + } + }, + "directories": { + "lib": "lib" + }, + "scripts": { + "clean": "node ../../scripts/build.mjs --clean", + "lint": "eslint --ext .ts lib test", + "lint:fix": "npm run lint -- --fix", + "build": "node ../../scripts/build.mjs --build=\"all\"", + "build:cjs": "node ../../scripts/build.mjs --build='cjs'", + "build:mjs": "node ../../scripts/build.mjs --build='mjs'", + "unit": "node --require ts-node/register ../../scripts/test.mjs", + "test": "npm run lint && npm run unit", + "coverage": "c8 node --require ts-node/register ./test/run.ts", + "prepublishOnly": "npm run build", + "postpublish": "npm run clean" + }, + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "repository": { + "type": "git", + "url": "https://github.com/kaka-ng/nodejs.git" + }, + "author": "KaKa ", + "license": "GPL-3.0", + "devDependencies": { + "@types/node": "^20.11.5", + "@typescript-eslint/eslint-plugin": "6.19.0", + "@typescript-eslint/parser": "6.19.0", + "eslint": "^8.56.0", + "eslint-config-standard-with-typescript": "^43.0.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^16.6.1", + "eslint-plugin-promise": "^6.1.1", + "rimraf": "^5.0.5", + "ts-node": "^10.9.2", + "tsc-alias": "^1.8.8", + "typescript": "~5.3.3" + } +} diff --git a/packages/crypto/test/aes.test.ts b/packages/crypto/test/aes.test.ts new file mode 100644 index 00000000..1fddb056 --- /dev/null +++ b/packages/crypto/test/aes.test.ts @@ -0,0 +1,170 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import * as AES from '../lib/aes' + +test('computeKeySize()', async function (t) { + await t.test('default', function (t) { + assert.equal(AES.computeKeySize(), 32) + }) + + await t.test('aes-256-ccm', function (t) { + assert.equal(AES.computeKeySize('aes-256-ccm'), 32) + }) + + await t.test('aes-256-gcm', function (t) { + assert.equal(AES.computeKeySize('aes-256-gcm'), 32) + }) + + await t.test('chacha20-poly1305', function (t) { + assert.equal(AES.computeKeySize('chacha20-poly1305'), 32) + }) + + await t.test('aes-192-ccm', function (t) { + assert.equal(AES.computeKeySize('aes-192-ccm'), 24) + }) + + await t.test('aes-192-gcm', function (t) { + assert.equal(AES.computeKeySize('aes-192-gcm'), 24) + }) + + await t.test('aes-128-ccm', function (t) { + assert.equal(AES.computeKeySize('aes-128-ccm'), 16) + }) + + await t.test('aes-128-gcm', function (t) { + assert.equal(AES.computeKeySize('aes-128-gcm'), 16) + }) +}) + +test('computeIVSize()', async function (t) { + await t.test('default', function (t) { + assert.equal(AES.computeIVSize(), 16) + }) + + await t.test('aes-256-ccm', function (t) { + assert.equal(AES.computeIVSize('aes-256-ccm'), 16) + }) + + await t.test('aes-256-gcm', function (t) { + assert.equal(AES.computeIVSize('aes-256-gcm'), 16) + }) + + await t.test('chacha20-poly1305', function (t) { + assert.equal(AES.computeIVSize('chacha20-poly1305'), 12) + }) + + await t.test('aes-192-ccm', function (t) { + assert.equal(AES.computeIVSize('aes-192-ccm'), 16) + }) + + await t.test('aes-192-gcm', function (t) { + assert.equal(AES.computeIVSize('aes-192-gcm'), 16) + }) + + await t.test('aes-128-ccm', function (t) { + assert.equal(AES.computeIVSize('aes-128-ccm'), 16) + }) + + await t.test('aes-128-gcm', function (t) { + assert.equal(AES.computeIVSize('aes-128-gcm'), 16) + }) +}) + +test('encrypt()', async function (t) { + const SECRET = 'bar' + const SALT = 'baz' + + await t.test('encrypt(foo)', function (t) { + const encrypted = AES.encrypt('foo') + assert.equal('value' in encrypted, true) + assert.equal('iv' in encrypted, true) + assert.equal('authTag' in encrypted, true) + assert.equal('secret' in encrypted, true) + assert.equal('salt' in encrypted, true) + }) + + await t.test('encrypt(foo, aes-256-gcm, bar, baz)', function (t) { + const encrypted = AES.encrypt('foo', 'aes-256-gcm', SECRET, SALT) + assert.equal('value' in encrypted, true) + assert.equal('iv' in encrypted, true) + assert.equal('authTag' in encrypted, true) + assert.equal('secret' in encrypted, true) + assert.equal('salt' in encrypted, true) + }) + + await t.test('encrypt(foo, chacha20-poly1305, bar, baz)', function (t) { + const encrypted = AES.encrypt('foo', 'chacha20-poly1305', SECRET, SALT) + assert.equal('value' in encrypted, true) + assert.equal('iv' in encrypted, true) + assert.equal('authTag' in encrypted, true) + assert.equal('secret' in encrypted, true) + assert.equal('salt' in encrypted, true) + }) +}) + +test('decrypt()', async function (t) { + await t.test('decrypt(foo)', function (t) { + const encrypted = AES.encrypt('foo') + const decrypted = AES.decrypt( + encrypted.value, + Buffer.from(encrypted.iv, 'hex'), + Buffer.from(encrypted.authTag, 'hex'), + 'aes-256-gcm', + encrypted.secret, + encrypted.salt + ) + assert.equal(decrypted, 'foo') + }) + + await t.test('decrypt(foo, aes-128-gcm)', function (t) { + const encrypted = AES.encrypt('foo', 'aes-128-gcm') + const decrypted = AES.decrypt( + encrypted.value, + Buffer.from(encrypted.iv, 'hex'), + Buffer.from(encrypted.authTag, 'hex'), + 'aes-128-gcm', + encrypted.secret, + encrypted.salt + ) + assert.equal(decrypted, 'foo') + }) + + await t.test('decrypt(foo, aes-192-gcm)', function (t) { + const encrypted = AES.encrypt('foo', 'aes-192-gcm') + const decrypted = AES.decrypt( + encrypted.value, + Buffer.from(encrypted.iv, 'hex'), + Buffer.from(encrypted.authTag, 'hex'), + 'aes-192-gcm', + encrypted.secret, + encrypted.salt + ) + assert.equal(decrypted, 'foo') + }) + + await t.test('decrypt(foo, aes-256-gcm)', function (t) { + const encrypted = AES.encrypt('foo', 'aes-256-gcm') + const decrypted = AES.decrypt( + encrypted.value, + Buffer.from(encrypted.iv, 'hex'), + Buffer.from(encrypted.authTag, 'hex'), + 'aes-256-gcm', + encrypted.secret, + encrypted.salt + ) + assert.equal(decrypted, 'foo') + }) + + await t.test('decrypt(foo, chacha20-poly1305)', function (t) { + const encrypted = AES.encrypt('foo', 'chacha20-poly1305') + const decrypted = AES.decrypt( + encrypted.value, + Buffer.from(encrypted.iv, 'hex'), + Buffer.from(encrypted.authTag, 'hex'), + 'chacha20-poly1305', + encrypted.secret, + encrypted.salt + ) + assert.equal(decrypted, 'foo') + }) +}) diff --git a/packages/crypto/test/base64.test.ts b/packages/crypto/test/base64.test.ts new file mode 100644 index 00000000..c11250fe --- /dev/null +++ b/packages/crypto/test/base64.test.ts @@ -0,0 +1,185 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import * as Base64 from '../lib/base64' + +const CUSTOMCHARSET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=' +const decoded = { + default: ['Zm9vYmFyYmF6', 'Zm9vYg=='], + url: ['Zm9vYmFyYmF6', 'Zm9vYg'], + custom: ['zM9VyMfYyMf6', 'zM9VyG=='] +} +const encoded = { + string: ['foobarbaz', 'foob'], + buffer: [] as Buffer[], + Uint8Array: [] as Uint8Array[] +} +encoded.buffer = [Buffer.from(encoded.string[0]), Buffer.from(encoded.string[1])] +encoded.Uint8Array = [new Uint8Array(encoded.buffer[0]), new Uint8Array(encoded.buffer[1])] + +test('encode(*)', async function (t) { + await t.test('foobarbaz', function (t) { + assert.equal(Base64.encode(encoded.string[0]), decoded.default[0]) + }) + + await t.test('foob', function (t) { + assert.equal(Base64.encode(encoded.string[1]), decoded.default[1]) + }) + + await t.test('Buffer(foobarbaz)', function (t) { + assert.equal(Base64.encode(encoded.buffer[0]), decoded.default[0]) + }) + + await t.test('Buffer(foob)', function (t) { + assert.equal(Base64.encode(encoded.buffer[1]), decoded.default[1]) + }) + + await t.test('Uint8Array(foobarbaz)', function (t) { + assert.equal(Base64.encode(encoded.Uint8Array[0]), decoded.default[0]) + }) + + await t.test('Uint8Array(foob)', function (t) { + assert.equal(Base64.encode(encoded.Uint8Array[1]), decoded.default[1]) + }) +}) + +test('encode(*, "url")', async function (t) { + await t.test('foobarbaz', function (t) { + assert.equal(Base64.encode(encoded.string[0], 'url'), decoded.url[0]) + }) + + await t.test('foob', function (t) { + assert.equal(Base64.encode(encoded.string[1], 'url'), decoded.url[1]) + }) + + await t.test('Buffer(foobarbaz)', function (t) { + assert.equal(Base64.encode(encoded.buffer[0], 'url'), decoded.url[0]) + }) + + await t.test('Buffer(foob)', function (t) { + assert.equal(Base64.encode(encoded.buffer[1], 'url'), decoded.url[1]) + }) + + await t.test('Uint8Array(foobarbaz)', function (t) { + assert.equal(Base64.encode(encoded.Uint8Array[0], 'url'), decoded.url[0]) + }) + + await t.test('Uint8Array(foob)', function (t) { + assert.equal(Base64.encode(encoded.Uint8Array[1], 'url'), decoded.url[1]) + }) +}) + +test('encode(*, "custom", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=")', async function (t) { + await t.test('foobarbaz', function (t) { + assert.equal(Base64.encode(encoded.string[0], 'custom', CUSTOMCHARSET), decoded.custom[0]) + }) + + await t.test('foob', function (t) { + assert.equal(Base64.encode(encoded.string[1], 'custom', CUSTOMCHARSET), decoded.custom[1]) + }) + + await t.test('Buffer(foobarbaz)', function (t) { + assert.equal(Base64.encode(encoded.buffer[0], 'custom', CUSTOMCHARSET), decoded.custom[0]) + }) + + await t.test('Buffer(foob)', function (t) { + assert.equal(Base64.encode(encoded.buffer[1], 'custom', CUSTOMCHARSET), decoded.custom[1]) + }) + + await t.test('Uint8Array(foobarbaz)', function (t) { + assert.equal(Base64.encode(encoded.Uint8Array[0], 'custom', CUSTOMCHARSET), decoded.custom[0]) + }) + + await t.test('Uint8Array(foob)', function (t) { + assert.equal(Base64.encode(encoded.Uint8Array[1], 'custom', CUSTOMCHARSET), decoded.custom[1]) + }) +}) + +test('encodeReplaceCharset(*)', async function (t) { + await t.test('Zm9vYmFyYmF6', function (t) { + assert.equal(Base64.encodeReplaceCharset(decoded.default[0]), decoded.default[0]) + }) + + await t.test('Zm9vYg==', function (t) { + assert.equal(Base64.encodeReplaceCharset(decoded.default[1]), decoded.default[1]) + }) +}) + +test('encodeReplaceCharset(*, "url")', async function (t) { + await t.test('Zm9vYmFyYmF6', function (t) { + assert.equal(Base64.encodeReplaceCharset(decoded.default[0], 'url'), decoded.url[0]) + }) + + await t.test('Zm9vYg==', function (t) { + assert.equal(Base64.encodeReplaceCharset(decoded.default[1], 'url'), decoded.url[1]) + }) +}) + +test('encodeReplaceCharset(*, "custom", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=")', async function (t) { + await t.test('Zm9vYmFyYmF6', function (t) { + assert.equal(Base64.encodeReplaceCharset(decoded.default[0], 'custom', CUSTOMCHARSET), decoded.custom[0]) + }) + + await t.test('Zm9vYg==', function (t) { + assert.equal(Base64.encodeReplaceCharset(decoded.default[1], 'custom', CUSTOMCHARSET), decoded.custom[1]) + }) +}) + +test('decode(*)', async function (t) { + await t.test('foobarbaz', function (t) { + assert.equal(Base64.decode(decoded.default[0]), encoded.string[0]) + }) + + await t.test('foob', function (t) { + assert.equal(Base64.decode(decoded.default[1]), encoded.string[1]) + }) +}) + +test('encode(*, "url")', async function (t) { + await t.test('foobarbaz', function (t) { + assert.equal(Base64.decode(decoded.url[0], 'url'), encoded.string[0]) + }) + + await t.test('foob', function (t) { + assert.equal(Base64.decode(decoded.url[1], 'url'), encoded.string[1]) + }) +}) + +test('decode(*, "custom", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=")', async function (t) { + await t.test('foobarbaz', function (t) { + assert.equal(Base64.decode(decoded.custom[0], 'custom', CUSTOMCHARSET), encoded.string[0]) + }) + + await t.test('foob', function (t) { + assert.equal(Base64.decode(decoded.custom[1], 'custom', CUSTOMCHARSET), encoded.string[1]) + }) +}) + +test('decodeReplaceCharset(*)', async function (t) { + await t.test('Zm9vYmFyYmF6', function (t) { + assert.equal(Base64.decodeReplaceCharset(decoded.default[0]), decoded.default[0]) + }) + + await t.test('Zm9vYg==', function (t) { + assert.equal(Base64.decodeReplaceCharset(decoded.default[1]), decoded.default[1]) + }) +}) + +test('decodeReplaceCharset(*, "url")', async function (t) { + await t.test('Zm9vYmFyYmF6', function (t) { + assert.equal(Base64.decodeReplaceCharset(decoded.url[0], 'url'), decoded.default[0]) + }) + + await t.test('Zm9vYg==', function (t) { + assert.equal(Base64.decodeReplaceCharset(decoded.url[1], 'url'), decoded.default[1]) + }) +}) + +test('decodeReplaceCharset(*, "custom", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=")', async function (t) { + await t.test('Zm9vYmFyYmF6', function (t) { + assert.equal(Base64.decodeReplaceCharset(decoded.custom[0], 'custom', CUSTOMCHARSET), decoded.default[0]) + }) + + await t.test('Zm9vYg==', function (t) { + assert.equal(Base64.decodeReplaceCharset(decoded.custom[1], 'custom', CUSTOMCHARSET), decoded.default[1]) + }) +}) diff --git a/packages/crypto/test/hash.test.ts b/packages/crypto/test/hash.test.ts new file mode 100644 index 00000000..bd268973 --- /dev/null +++ b/packages/crypto/test/hash.test.ts @@ -0,0 +1,109 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import * as Hash from '../lib/hash' + +test('hash', async function (t) { + await t.test('hash(foo)', function (t) { + assert.equal(Hash.hash('foo'), + 'f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7' + ) + }) + + await t.test('hash(foo, base64)', function (t) { + assert.equal(Hash.hash('foo', 'base64'), + '9/u6bgY2+JDlb7vzKD5STG+jIErimDgtYkdB0NxmODJuKCxBvl5CVNiCB3LFUYosWowMf37aGVlKfrU5RT4e1w==' + ) + }) +}) + +test('md5', async function (t) { + await t.test('md5(foo)', function (t) { + assert.equal(Hash.md5('foo'), 'acbd18db4cc2f85cedef654fccc4a4d8') + }) + + await t.test('md5(foo, base64)', function (t) { + assert.equal(Hash.md5('foo', 'base64'), 'rL0Y20zC+Fzt72VPzMSk2A==') + }) +}) + +test('sha1', async function (t) { + await t.test('sha1(foo)', function (t) { + assert.equal(Hash.sha1('foo'), '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33') + }) + + await t.test('sha1(foo, base64)', function (t) { + assert.equal(Hash.sha1('foo', 'base64'), 'C+7Hteo/D9vJXQ3UfzxbwnXaijM=') + }) +}) + +test('sha224', async function (t) { + await t.test('sha224(foo)', function (t) { + assert.equal(Hash.sha224('foo'), '0808f64e60d58979fcb676c96ec938270dea42445aeefcd3a4e6f8db') + }) + + await t.test('sha224(foo, base64)', function (t) { + assert.equal(Hash.sha224('foo', 'base64'), 'CAj2TmDViXn8tnbJbsk4Jw3qQkRa7vzTpOb42w==') + }) +}) + +test('sha256', async function (t) { + await t.test('sha256(foo)', function (t) { + assert.equal(Hash.sha256('foo'), '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae') + }) + + await t.test('sha256(foo, base64)', function (t) { + assert.equal(Hash.sha256('foo', 'base64'), 'LCa0a2j/xo/5m0U8HTBBNBNCLXBkg7+g+YpeiGJm564=') + }) +}) + +test('sha384', async function (t) { + await t.test('sha384(foo)', function (t) { + assert.equal(Hash.sha384('foo'), '98c11ffdfdd540676b1a137cb1a22b2a70350c9a44171d6b1180c6be5cbb2ee3f79d532c8a1dd9ef2e8e08e752a3babb') + }) + + await t.test('sha384(foo, base64)', function (t) { + assert.equal(Hash.sha384('foo', 'base64'), 'mMEf/f3VQGdrGhN8saIrKnA1DJpEFx1rEYDGvly7LuP3nVMsih3Z7y6OCOdSo7q7') + }) +}) + +test('sha512', async function (t) { + await t.test('sha512(foo)', function (t) { + assert.equal(Hash.sha512('foo'), + 'f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7' + ) + }) + + await t.test('sha512(foo, base64)', function (t) { + assert.equal(Hash.sha512('foo', 'base64'), + '9/u6bgY2+JDlb7vzKD5STG+jIErimDgtYkdB0NxmODJuKCxBvl5CVNiCB3LFUYosWowMf37aGVlKfrU5RT4e1w==' + ) + }) +}) + +test('shake128', async function (t) { + await t.test('shake128(foo)', function (t) { + assert.equal(Hash.shake128('foo'), + 'f84e95cb5fbd2038863ab27d3cdeac29' + ) + }) + + await t.test('shake128(foo, base64)', function (t) { + assert.equal(Hash.shake128('foo', 'base64'), + '+E6Vy1+9IDiGOrJ9PN6sKQ==' + ) + }) +}) + +test('shake256', async function (t) { + await t.test('shake256(foo)', function (t) { + assert.equal(Hash.shake256('foo'), + '1af97f7818a28edfdfce5ec66dbdc7e871813816d7d585fe1f12475ded5b6502' + ) + }) + + await t.test('shake256(foo, base64)', function (t) { + assert.equal(Hash.shake256('foo', 'base64'), + 'Gvl/eBiijt/fzl7Gbb3H6HGBOBbX1YX+HxJHXe1bZQI=' + ) + }) +}) diff --git a/packages/crypto/test/index.test.ts b/packages/crypto/test/index.test.ts new file mode 100644 index 00000000..7ffbfa88 --- /dev/null +++ b/packages/crypto/test/index.test.ts @@ -0,0 +1,30 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import * as crypto from '../lib/index' +import { AES, Base64, md5, randomBytes, Scrypt, sha1, sha224, sha256, sha512 } from '../lib/index' + +test('import', async function (t) { + await t.test('import * as', function (t) { + assert.equal('AES' in crypto, true) + assert.equal('Base64' in crypto, true) + assert.equal('Scrypt' in crypto, true) + assert.equal('md5' in crypto, true) + assert.equal('sha1' in crypto, true) + assert.equal('sha224' in crypto, true) + assert.equal('sha256' in crypto, true) + assert.equal('sha512' in crypto, true) + assert.equal('randomBytes' in crypto, true) + }) + + await t.test('import {} from', function (t) { + assert.ok(AES) + assert.ok(Base64) + assert.ok(Scrypt) + assert.ok(md5) + assert.ok(sha1) + assert.ok(sha224) + assert.ok(sha256) + assert.ok(sha512) + assert.ok(randomBytes) + }) +}) diff --git a/packages/crypto/test/scrypt.test.ts b/packages/crypto/test/scrypt.test.ts new file mode 100644 index 00000000..ad0ddcfa --- /dev/null +++ b/packages/crypto/test/scrypt.test.ts @@ -0,0 +1,41 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import * as Scrypt from '../lib/scrypt' + +test('scrypt', async function (t) { + await t.test('hash(foo)', async function (t) { + const hashed = await Scrypt.hash('foo') + assert.equal(Scrypt.REGEXP.test(hashed), true) + }) + + await t.test('hash(foo, 10)', async function (t) { + const hashed = await Scrypt.hash('foo', 10) + assert.equal(Scrypt.REGEXP.test(hashed), true) + }) + + await t.test('hash(foo, 64, 2^15, 8, 2)', async function (t) { + const hashed = await Scrypt.hash('foo', 64, 32768, 8, 2) + assert.equal(Scrypt.REGEXP.test(hashed), true) + }) + + await t.test('compare(foo, foo)', async function (t) { + const hashed = await Scrypt.hash('foo') + const result = await Scrypt.compare('foo', hashed) + assert.equal(result, true) + }) + + await t.test('compare(bar, foo)', async function (t) { + const hashed = await Scrypt.hash('foo') + const result = await Scrypt.compare('bar', hashed) + assert.equal(result, false) + }) + + await t.test('compare(bar, invalid)', async function (t) { + try { + await Scrypt.compare('bar', '$scrypt$') + assert.ok(false, 'should not reach here') + } catch (err) { + assert.ok(err) + } + }) +}) diff --git a/packages/crypto/test/utils.test.ts b/packages/crypto/test/utils.test.ts new file mode 100644 index 00000000..d9a69ba1 --- /dev/null +++ b/packages/crypto/test/utils.test.ts @@ -0,0 +1,39 @@ +import assert from 'node:assert/strict' +import { test } from 'node:test' +import { randomBytes, randomNum, randomUUID } from '../lib/utils' + +test('randomBytes()', async function (t) { + await t.test('randomByes(16)', function (t) { + const result = randomBytes(16) + + assert.equal(result instanceof Buffer, true) + assert.equal(result.length, 16) + }) + + await t.test('randomByes(16, "hex")', function (t) { + const result = randomBytes(16, 'hex') + + assert.equal(typeof result, 'string') + assert.equal(result.length, 32) + }) +}) + +test('randomNum()', async function (t) { + await t.test('randomNum()', function (t) { + const result = randomNum() + + assert.equal(typeof result, 'string') + assert.equal(result.length, 6) + }) + + await t.test('randomNum(8)', function (t) { + const result = randomNum(8) + + assert.equal(typeof result, 'string') + assert.equal(result.length, 8) + }) +}) + +test('randomUUID', async function (t) { + assert.equal(/[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}/i.test(randomUUID()), true) +}) diff --git a/packages/crypto/tsconfig.cjs.json b/packages/crypto/tsconfig.cjs.json new file mode 100644 index 00000000..fa161c25 --- /dev/null +++ b/packages/crypto/tsconfig.cjs.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "removeComments": true, + "outDir": "lib" + }, + "include": ["lib/**/*"] +} diff --git a/packages/crypto/tsconfig.json b/packages/crypto/tsconfig.json new file mode 100644 index 00000000..f03615f6 --- /dev/null +++ b/packages/crypto/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "lib": ["ESNext"], + "module": "CommonJS", + "target": "ES2018", + "moduleResolution": "Node", + + "resolveJsonModule": true, + + "removeComments": false, + "preserveConstEnums": true, + + "sourceMap": true, + + "declaration": true, + + "strict": true, + "noImplicitAny": true, + "noImplicitThis": true, + + "skipLibCheck": true, + "esModuleInterop": true + }, + "include": ["lib/**/*", "test/**/*"], + "exclude": ["node_modules"] +} diff --git a/packages/crypto/tsconfig.mjs.json b/packages/crypto/tsconfig.mjs.json new file mode 100644 index 00000000..c119ce6b --- /dev/null +++ b/packages/crypto/tsconfig.mjs.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "outDir": "lib/mjs" + }, + "include": ["lib/**/*"], + "tsc-alias": { + "resolveFullPaths": true + } +} diff --git a/packages/utils/package.json b/packages/utils/package.json index 7e4b6a5a..b974cc54 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -45,7 +45,6 @@ "eslint-plugin-import": "^2.29.1", "eslint-plugin-n": "^16.6.1", "eslint-plugin-promise": "^6.1.1", - "fastify": "^4.24.3", "rimraf": "^5.0.5", "ts-node": "^10.9.2", "tsc-alias": "^1.8.8", diff --git a/packages/utils/test/index.test.ts b/packages/utils/test/index.test.ts index ba172bdd..8df3b63a 100644 --- a/packages/utils/test/index.test.ts +++ b/packages/utils/test/index.test.ts @@ -3,216 +3,216 @@ import { test } from 'node:test' import { clone, removeEmptyProps, slugify } from '../lib' test('removeEmptyProps', async function (t) { - await t.test('{}', function (t) { + await await t.test('{}', function (t) { const o = removeEmptyProps({}) assert.deepEqual(o, {}) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('[]', function (t) { + await await t.test('[]', function (t) { const o = removeEmptyProps([]) assert.deepEqual(o, []) - assert.equal(typeof o, 'object') - assert.equal(Array.isArray(o), true) + asserassert.equal(typeof o, 'object') + asserassert.equal(Array.isArray(o), true) }) - await t.test('{ foo: bar }', function (t) { + await await t.test('{ foo: bar }', function (t) { const o = removeEmptyProps({ foo: 'bar' }) assert.deepEqual(o, { foo: 'bar' }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: bar }', function (t) { + await await t.test('{ foo: bar }', function (t) { const o = removeEmptyProps({ foo: ' bar ' }) assert.deepEqual(o, { foo: 'bar' }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: "" }', function (t) { + await await t.test('{ foo: "" }', function (t) { const o = removeEmptyProps({ foo: '' }) assert.deepEqual(o, {}) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: "" }, true', function (t) { + await await t.test('{ foo: "" }, true', function (t) { const o = removeEmptyProps({ foo: '' }, true) assert.deepEqual(o, { foo: '' }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: 1 }', function (t) { + await await t.test('{ foo: 1 }', function (t) { const o = removeEmptyProps({ foo: 1 }) assert.deepEqual(o, { foo: 1 }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: true }', function (t) { + await await t.test('{ foo: true }', function (t) { const o = removeEmptyProps({ foo: true }) assert.deepEqual(o, { foo: true }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: undefined }', function (t) { + await await t.test('{ foo: undefined }', function (t) { const o = removeEmptyProps({ foo: undefined }) assert.deepEqual(o, { }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: Date }', function (t) { + await await t.test('{ foo: Date }', function (t) { const obj = { foo: new Date() } const o = removeEmptyProps(obj) assert.deepEqual(o, obj) - assert.equal(typeof o, 'object') - assert.equal(o.foo instanceof Date, true) + asserassert.equal(typeof o, 'object') + asserassert.equal(o.foo instanceof Date, true) }) - await t.test('{ foo: null }', function (t) { + await await t.test('{ foo: null }', function (t) { const o = removeEmptyProps({ foo: null }) assert.deepEqual(o, { }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: {} }', function (t) { + await await t.test('{ foo: {} }', function (t) { const o = removeEmptyProps({ foo: {} }) assert.deepEqual(o, { }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: { bar: Date } }', function (t) { + await await t.test('{ foo: { bar: Date } }', function (t) { const obj = { foo: { bar: new Date() } } const o = removeEmptyProps(obj) assert.deepEqual(o, obj) - assert.equal(typeof o, 'object') - assert.equal(o.foo.bar instanceof Date, true) + asserassert.equal(typeof o, 'object') + asserassert.equal(o.foo.bar instanceof Date, true) }) - await t.test('{ foo: {} }, true', function (t) { + await await t.test('{ foo: {} }, true', function (t) { const o = removeEmptyProps({ foo: {} }, true) assert.deepEqual(o, { foo: {} }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: [] }', function (t) { + await await t.test('{ foo: [] }', function (t) { const o = removeEmptyProps({ foo: [] }) assert.deepEqual(o, { }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: [] }, true', function (t) { + await await t.test('{ foo: [] }, true', function (t) { const o = removeEmptyProps({ foo: [] }, true) assert.deepEqual(o, { foo: [] }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: [""] }, true', function (t) { + await await t.test('{ foo: [""] }, true', function (t) { const o = removeEmptyProps({ foo: [''] }, true) assert.deepEqual(o, { foo: [] }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) - await t.test('{ foo: { bar: "" } }, true', function (t) { + await await t.test('{ foo: { bar: "" } }, true', function (t) { const o = removeEmptyProps({ foo: { bar: '' } }, true) assert.deepEqual(o, { foo: { bar: '' } }) - assert.equal(typeof o, 'object') + asserassert.equal(typeof o, 'object') }) }) test('slugify', async function (t) { - await t.test('HelloWorld', function (t) { + await await t.test('HelloWorld', function (t) { const o = slugify('HelloWorld') - assert.equal(o, 'helloworld') + asserassert.equal(o, 'helloworld') }) - await t.test('Hello World', function (t) { + await await t.test('Hello World', function (t) { const o = slugify('Hello World') - assert.equal(o, 'hello-world') + asserassert.equal(o, 'hello-world') }) - await t.test('Exceed Limit', function (t) { + await await t.test('Exceed Limit', function (t) { const o = slugify('I am a super long string that will exceed the limit hahahahahahahahahahahahahahahahahahahahahahahahahahaahhaha') - assert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaha') + asserassert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaha') }) - await t.test('Exceed Limit and End with Dash', function (t) { + await await t.test('Exceed Limit and End with Dash', function (t) { const o = slugify('I am a super long string that will exceed the limit hahahahahahahahahaa a') - assert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaa') + asserassert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaa') }) - await t.test('Include Unicode Character', function (t) { + await await t.test('Include Unicode Character', function (t) { const o = slugify('訂閱計劃 Subscription Plan 1 Month') - assert.equal(o, '訂閱計劃-subscription-plan-1-month') + asserassert.equal(o, '訂閱計劃-subscription-plan-1-month') }) - await t.test('Exclude Unicode Character', function (t) { + await await t.test('Exclude Unicode Character', function (t) { const o = slugify('訂閱計劃 Subscription Plan 1 Month', { unicode: false }) - assert.equal(o, 'subscription-plan-1-month') + asserassert.equal(o, 'subscription-plan-1-month') }) - await t.test('Limit to 1', function (t) { + await await t.test('Limit to 1', function (t) { const o = slugify('I am a super long string that will exceed the limit hahahahahahahahahaa a', { limit: 1 }) - assert.equal(o, 'i') + asserassert.equal(o, 'i') }) - await t.test('should use pinyin', function (t) { + await await t.test('should use pinyin', function (t) { const o = slugify('訂閱計劃', { pinyin: true }) - assert.equal(o, 'ding-yue-ji-hua') + asserassert.equal(o, 'ding-yue-ji-hua') }) - await t.test('should use pinyin', function (t) { + await await t.test('should use pinyin', function (t) { const o = slugify('訂閱計劃 Subscription Plan 1 Month', { pinyin: true }) - assert.equal(o, 'ding-yue-ji-hua-subscription-plan-1-month') + asserassert.equal(o, 'ding-yue-ji-hua-subscription-plan-1-month') }) - await t.test('should use pinyin but all englush', function (t) { + await await t.test('should use pinyin but all englush', function (t) { const o = slugify('Subscription Plan 1 Month', { pinyin: true }) - assert.equal(o, 'subscription-plan-1-month') + asserassert.equal(o, 'subscription-plan-1-month') }) - await t.test('should use default generator', function (t) { + await await t.test('should use default generator', function (t) { const o = slugify('訂閱計劃', { unicode: false }) - assert.equal(o.length <= 16, true) + asserassert.equal(o.length <= 16, true) }) - await t.test('should use custom generator', function (t) { + await await t.test('should use custom generator', function (t) { const o = slugify('訂閱計劃', { unicode: false, generator () { return 'custom' } }) - assert.equal(o, 'custom') + asserassert.equal(o, 'custom') }) }) test('clone', async function (t) { - await t.test('{ foo: null }', function (t) { + await await t.test('{ foo: null }', function (t) { const o = clone({ foo: null }) assert.deepEqual(o, { foo: null }) }) - await t.test('{ foo: string }', function (t) { + await await t.test('{ foo: string }', function (t) { const o = clone({ foo: 'bar' }) assert.deepEqual(o, { foo: 'bar' }) }) - await t.test('[string]', function (t) { + await await t.test('[string]', function (t) { const o = clone(['foo', 'bar']) assert.deepEqual(o, ['foo', 'bar']) }) - await t.test('string', function (t) { + await await t.test('string', function (t) { const o = clone('foo') - assert.equal(o, 'foo') + asserassert.equal(o, 'foo') }) - await t.test('{ foo: Date }', function (t) { + await await t.test('{ foo: Date }', function (t) { const ref = { foo: new Date() } const o = clone(ref) assert.deepEqual(o, ref) }) - await t.test('Map { foo: bar }', function (t) { + await await t.test('Map { foo: bar }', function (t) { const ref = new Map([['foo', 'bar']]) const o = clone(ref) assert.deepEqual(o, ref) }) - await t.test('Set { foo }', function (t) { + await await t.test('Set { foo }', function (t) { const ref = new Set(['foo']) const o = clone(ref) assert.deepEqual(o, ref) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1a57f7a3..0a4fe872 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,45 @@ importers: .: {} + packages/crypto: + devDependencies: + '@types/node': + specifier: ^20.11.5 + version: 20.11.5 + '@typescript-eslint/eslint-plugin': + specifier: 6.19.0 + version: 6.19.0(@typescript-eslint/parser@6.19.0)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': + specifier: 6.19.0 + version: 6.19.0(eslint@8.56.0)(typescript@5.3.3) + eslint: + specifier: ^8.56.0 + version: 8.56.0 + eslint-config-standard-with-typescript: + specifier: ^43.0.0 + version: 43.0.0(@typescript-eslint/eslint-plugin@6.19.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3) + eslint-plugin-import: + specifier: ^2.29.1 + version: 2.29.1(@typescript-eslint/parser@6.19.0)(eslint@8.56.0) + eslint-plugin-n: + specifier: ^16.6.1 + version: 16.6.2(eslint@8.56.0) + eslint-plugin-promise: + specifier: ^6.1.1 + version: 6.1.1(eslint@8.56.0) + rimraf: + specifier: ^5.0.5 + version: 5.0.5 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + tsc-alias: + specifier: ^1.8.8 + version: 1.8.8 + typescript: + specifier: ~5.3.3 + version: 5.3.3 + packages/utils: dependencies: pinyin-pro: @@ -38,9 +77,6 @@ importers: eslint-plugin-promise: specifier: ^6.1.1 version: 6.1.1(eslint@8.56.0) - fastify: - specifier: ^4.24.3 - version: 4.25.2 rimraf: specifier: ^5.0.5 version: 5.0.5 @@ -105,28 +141,6 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@fastify/ajv-compiler@3.5.0: - resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} - dependencies: - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - fast-uri: 2.3.0 - dev: true - - /@fastify/deepmerge@1.3.0: - resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==} - dev: true - - /@fastify/error@3.4.1: - resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} - dev: true - - /@fastify/fast-json-stringify-compiler@4.3.0: - resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} - dependencies: - fast-json-stringify: 5.10.0 - dev: true - /@humanwhocodes/config-array@0.11.14: resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} @@ -373,17 +387,6 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true - /abort-controller@3.0.0: - resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} - engines: {node: '>=6.5'} - dependencies: - event-target-shim: 5.0.1 - dev: true - - /abstract-logging@2.0.1: - resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} - dev: true - /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -403,17 +406,6 @@ packages: hasBin: true dev: true - /ajv-formats@2.1.1(ajv@8.12.0): - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - dependencies: - ajv: 8.12.0 - dev: true - /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: @@ -423,15 +415,6 @@ packages: uri-js: 4.4.1 dev: true - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -462,10 +445,6 @@ packages: picomatch: 2.3.1 dev: true - /archy@1.0.0: - resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} - dev: true - /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true @@ -541,34 +520,15 @@ packages: is-shared-array-buffer: 1.0.2 dev: true - /atomic-sleep@1.0.0: - resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} - engines: {node: '>=8.0.0'} - dev: true - /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} dev: true - /avvio@8.2.1: - resolution: {integrity: sha512-TAlMYvOuwGyLK3PfBb5WKBXZmXz2fVCgv23d6zZFdle/q3gPjmxBaeuC0pY0Dzs5PWMSgfqqEZkrye19GlDTgw==} - dependencies: - archy: 1.0.0 - debug: 4.3.4 - fastq: 1.16.0 - transitivePeerDependencies: - - supports-color - dev: true - /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -594,13 +554,6 @@ packages: fill-range: 7.0.1 dev: true - /buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - /builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -668,11 +621,6 @@ packages: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} dev: true - /cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} - engines: {node: '>= 0.6'} - dev: true - /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true @@ -1097,24 +1045,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /event-target-shim@5.0.1: - resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} - engines: {node: '>=6'} - dev: true - - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: true - - /fast-content-type-parse@1.1.0: - resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} - dev: true - - /fast-decode-uri-component@1.0.1: - resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} - dev: true - /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -1134,60 +1064,10 @@ packages: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true - /fast-json-stringify@5.10.0: - resolution: {integrity: sha512-fu1BhzPzgOdvK+sVhSPFzm06DQl0Dwbo+NQxWm21k03ili2wsJExXbGZ9qsD4Lsn7zFGltF8h9I1fuhk4JPnrQ==} - dependencies: - '@fastify/deepmerge': 1.3.0 - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - fast-deep-equal: 3.1.3 - fast-uri: 2.3.0 - json-schema-ref-resolver: 1.0.1 - rfdc: 1.3.0 - dev: true - /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true - /fast-querystring@1.1.2: - resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} - dependencies: - fast-decode-uri-component: 1.0.1 - dev: true - - /fast-redact@3.3.0: - resolution: {integrity: sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==} - engines: {node: '>=6'} - dev: true - - /fast-uri@2.3.0: - resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==} - dev: true - - /fastify@4.25.2: - resolution: {integrity: sha512-SywRouGleDHvRh054onj+lEZnbC1sBCLkR0UY3oyJwjD4BdZJUrxBqfkfCaqn74pVCwBaRHGuL3nEWeHbHzAfw==} - dependencies: - '@fastify/ajv-compiler': 3.5.0 - '@fastify/error': 3.4.1 - '@fastify/fast-json-stringify-compiler': 4.3.0 - abstract-logging: 2.0.1 - avvio: 8.2.1 - fast-content-type-parse: 1.1.0 - fast-json-stringify: 5.10.0 - find-my-way: 7.7.0 - light-my-request: 5.11.0 - pino: 8.17.2 - process-warning: 3.0.0 - proxy-addr: 2.0.7 - rfdc: 1.3.0 - secure-json-parse: 2.7.0 - semver: 7.5.4 - toad-cache: 3.7.0 - transitivePeerDependencies: - - supports-color - dev: true - /fastq@1.16.0: resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==} dependencies: @@ -1208,15 +1088,6 @@ packages: to-regex-range: 5.0.1 dev: true - /find-my-way@7.7.0: - resolution: {integrity: sha512-+SrHpvQ52Q6W9f3wJoJBbAQULJuNEEQwBvlvYwACDhBTLOTMiQ0HYWh4+vC3OivGP2ENcTI1oKlFA2OepJNjhQ==} - engines: {node: '>=14'} - dependencies: - fast-deep-equal: 3.1.3 - fast-querystring: 1.1.2 - safe-regex2: 2.0.0 - dev: true - /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -1252,11 +1123,6 @@ packages: signal-exit: 4.1.0 dev: true - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: true - /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -1422,10 +1288,6 @@ packages: function-bind: 1.1.2 dev: true - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: true - /ignore@5.3.0: resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} engines: {node: '>= 4'} @@ -1464,11 +1326,6 @@ packages: side-channel: 1.0.4 dev: true - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: true - /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -1631,20 +1488,10 @@ packages: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true - /json-schema-ref-resolver@1.0.1: - resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} - dependencies: - fast-deep-equal: 3.1.3 - dev: true - /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true @@ -1670,14 +1517,6 @@ packages: type-check: 0.4.0 dev: true - /light-my-request@5.11.0: - resolution: {integrity: sha512-qkFCeloXCOMpmEdZ/MV91P8AT4fjwFXWaAFz3lUeStM8RcoM1ks4J/F8r1b3r6y/H4u3ACEJ1T+Gv5bopj7oDA==} - dependencies: - cookie: 0.5.0 - process-warning: 2.3.2 - set-cookie-parser: 2.6.0 - dev: true - /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -1808,11 +1647,6 @@ packages: es-abstract: 1.22.3 dev: true - /on-exit-leak-free@2.1.2: - resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} - engines: {node: '>=14.0.0'} - dev: true - /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -1889,34 +1723,6 @@ packages: engines: {node: '>=8.6'} dev: true - /pino-abstract-transport@1.1.0: - resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} - dependencies: - readable-stream: 4.5.2 - split2: 4.2.0 - dev: true - - /pino-std-serializers@6.2.2: - resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==} - dev: true - - /pino@8.17.2: - resolution: {integrity: sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==} - hasBin: true - dependencies: - atomic-sleep: 1.0.0 - fast-redact: 3.3.0 - on-exit-leak-free: 2.1.2 - pino-abstract-transport: 1.1.0 - pino-std-serializers: 6.2.2 - process-warning: 3.0.0 - quick-format-unescaped: 4.0.4 - real-require: 0.2.0 - safe-stable-stringify: 2.4.3 - sonic-boom: 3.8.0 - thread-stream: 2.4.1 - dev: true - /pinyin-pro@3.19.2: resolution: {integrity: sha512-1mYXHJIht8QJaPaVzzcYxOszDRIgrt6Aw0NYrmkerSYAAA1tsI+gtOMrPXoQDLyBbUCc23tEt/bSXmRAcDzMyQ==} dev: false @@ -1933,27 +1739,6 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /process-warning@2.3.2: - resolution: {integrity: sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==} - dev: true - - /process-warning@3.0.0: - resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} - dev: true - - /process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: true - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: true - /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -1968,21 +1753,6 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true - /quick-format-unescaped@4.0.4: - resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - dev: true - - /readable-stream@4.5.2: - resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - abort-controller: 3.0.0 - buffer: 6.0.3 - events: 3.3.0 - process: 0.11.10 - string_decoder: 1.3.0 - dev: true - /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1990,11 +1760,6 @@ packages: picomatch: 2.3.1 dev: true - /real-require@0.2.0: - resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} - engines: {node: '>= 12.13.0'} - dev: true - /regexp.prototype.flags@1.5.1: resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} engines: {node: '>= 0.4'} @@ -2004,11 +1769,6 @@ packages: set-function-name: 2.0.1 dev: true - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2027,20 +1787,11 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true - /ret@0.2.2: - resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} - engines: {node: '>=4'} - dev: true - /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: true - /rfdc@1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - dev: true - /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true @@ -2072,10 +1823,6 @@ packages: isarray: 2.0.5 dev: true - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - /safe-regex-test@1.0.2: resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==} engines: {node: '>= 0.4'} @@ -2085,21 +1832,6 @@ packages: is-regex: 1.1.4 dev: true - /safe-regex2@2.0.0: - resolution: {integrity: sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==} - dependencies: - ret: 0.2.2 - dev: true - - /safe-stable-stringify@2.4.3: - resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} - engines: {node: '>=10'} - dev: true - - /secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - dev: true - /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2113,10 +1845,6 @@ packages: lru-cache: 6.0.0 dev: true - /set-cookie-parser@2.6.0: - resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} - dev: true - /set-function-length@1.2.0: resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==} engines: {node: '>= 0.4'} @@ -2167,17 +1895,6 @@ packages: engines: {node: '>=8'} dev: true - /sonic-boom@3.8.0: - resolution: {integrity: sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==} - dependencies: - atomic-sleep: 1.0.0 - dev: true - - /split2@4.2.0: - resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} - engines: {node: '>= 10.x'} - dev: true - /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2221,12 +1938,6 @@ packages: es-abstract: 1.22.3 dev: true - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - /strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2267,12 +1978,6 @@ packages: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true - /thread-stream@2.4.1: - resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==} - dependencies: - real-require: 0.2.0 - dev: true - /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2280,11 +1985,6 @@ packages: is-number: 7.0.0 dev: true - /toad-cache@3.7.0: - resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} - engines: {node: '>=12'} - dev: true - /ts-api-utils@1.0.3(typescript@5.3.3): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} From 43194b6aa1bd8d874af88b45476a11057fb42a8d Mon Sep 17 00:00:00 2001 From: KaKa Date: Thu, 18 Jan 2024 15:33:40 +0800 Subject: [PATCH 2/3] chore: fix lint --- packages/crypto/lib/aes.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/crypto/lib/aes.ts b/packages/crypto/lib/aes.ts index 2eab88f8..fde702f6 100644 --- a/packages/crypto/lib/aes.ts +++ b/packages/crypto/lib/aes.ts @@ -50,7 +50,7 @@ export function encrypt ( const key: Buffer = scryptSync(secret, salt, computeKeySize(algorithm)) const ivSize = computeIVSize(algorithm) const iv: Buffer = Buffer.alloc(ivSize, randomBytes(ivSize), 'binary') - const option: any = [algorithm, key, iv, { authTagLength }] + const option: Parameters = [algorithm, key, iv, { authTagLength } as any] const cipher: CipherGCM = createCipheriv.apply(createCipheriv, option) as CipherGCM cipher.setAAD(Buffer.from(`${String(secret)}${String(salt)}`)) @@ -75,7 +75,7 @@ export function decrypt ( authTagLength = 16 ): string { const key: Buffer = scryptSync(secret, salt, computeKeySize(algorithm)) - const option: any = [algorithm, key, iv, { authTagLength }] + const option: Parameters = [algorithm, key, iv, { authTagLength } as any] const decipher = createDecipheriv.apply(createDecipheriv, option) as DecipherGCM decipher.setAAD(Buffer.from(`${String(secret)}${String(salt)}`)) decipher.setAuthTag(authTag) From 9befe90605e0479dc2fbcd4398c0c96e7a7ea5a6 Mon Sep 17 00:00:00 2001 From: KaKa Date: Thu, 18 Jan 2024 15:35:18 +0800 Subject: [PATCH 3/3] refactor: unintented changes --- packages/utils/test/index.test.ts | 142 +++++++++++++++--------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/packages/utils/test/index.test.ts b/packages/utils/test/index.test.ts index 8df3b63a..ba172bdd 100644 --- a/packages/utils/test/index.test.ts +++ b/packages/utils/test/index.test.ts @@ -3,216 +3,216 @@ import { test } from 'node:test' import { clone, removeEmptyProps, slugify } from '../lib' test('removeEmptyProps', async function (t) { - await await t.test('{}', function (t) { + await t.test('{}', function (t) { const o = removeEmptyProps({}) assert.deepEqual(o, {}) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('[]', function (t) { + await t.test('[]', function (t) { const o = removeEmptyProps([]) assert.deepEqual(o, []) - asserassert.equal(typeof o, 'object') - asserassert.equal(Array.isArray(o), true) + assert.equal(typeof o, 'object') + assert.equal(Array.isArray(o), true) }) - await await t.test('{ foo: bar }', function (t) { + await t.test('{ foo: bar }', function (t) { const o = removeEmptyProps({ foo: 'bar' }) assert.deepEqual(o, { foo: 'bar' }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: bar }', function (t) { + await t.test('{ foo: bar }', function (t) { const o = removeEmptyProps({ foo: ' bar ' }) assert.deepEqual(o, { foo: 'bar' }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: "" }', function (t) { + await t.test('{ foo: "" }', function (t) { const o = removeEmptyProps({ foo: '' }) assert.deepEqual(o, {}) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: "" }, true', function (t) { + await t.test('{ foo: "" }, true', function (t) { const o = removeEmptyProps({ foo: '' }, true) assert.deepEqual(o, { foo: '' }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: 1 }', function (t) { + await t.test('{ foo: 1 }', function (t) { const o = removeEmptyProps({ foo: 1 }) assert.deepEqual(o, { foo: 1 }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: true }', function (t) { + await t.test('{ foo: true }', function (t) { const o = removeEmptyProps({ foo: true }) assert.deepEqual(o, { foo: true }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: undefined }', function (t) { + await t.test('{ foo: undefined }', function (t) { const o = removeEmptyProps({ foo: undefined }) assert.deepEqual(o, { }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: Date }', function (t) { + await t.test('{ foo: Date }', function (t) { const obj = { foo: new Date() } const o = removeEmptyProps(obj) assert.deepEqual(o, obj) - asserassert.equal(typeof o, 'object') - asserassert.equal(o.foo instanceof Date, true) + assert.equal(typeof o, 'object') + assert.equal(o.foo instanceof Date, true) }) - await await t.test('{ foo: null }', function (t) { + await t.test('{ foo: null }', function (t) { const o = removeEmptyProps({ foo: null }) assert.deepEqual(o, { }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: {} }', function (t) { + await t.test('{ foo: {} }', function (t) { const o = removeEmptyProps({ foo: {} }) assert.deepEqual(o, { }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: { bar: Date } }', function (t) { + await t.test('{ foo: { bar: Date } }', function (t) { const obj = { foo: { bar: new Date() } } const o = removeEmptyProps(obj) assert.deepEqual(o, obj) - asserassert.equal(typeof o, 'object') - asserassert.equal(o.foo.bar instanceof Date, true) + assert.equal(typeof o, 'object') + assert.equal(o.foo.bar instanceof Date, true) }) - await await t.test('{ foo: {} }, true', function (t) { + await t.test('{ foo: {} }, true', function (t) { const o = removeEmptyProps({ foo: {} }, true) assert.deepEqual(o, { foo: {} }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: [] }', function (t) { + await t.test('{ foo: [] }', function (t) { const o = removeEmptyProps({ foo: [] }) assert.deepEqual(o, { }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: [] }, true', function (t) { + await t.test('{ foo: [] }, true', function (t) { const o = removeEmptyProps({ foo: [] }, true) assert.deepEqual(o, { foo: [] }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: [""] }, true', function (t) { + await t.test('{ foo: [""] }, true', function (t) { const o = removeEmptyProps({ foo: [''] }, true) assert.deepEqual(o, { foo: [] }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) - await await t.test('{ foo: { bar: "" } }, true', function (t) { + await t.test('{ foo: { bar: "" } }, true', function (t) { const o = removeEmptyProps({ foo: { bar: '' } }, true) assert.deepEqual(o, { foo: { bar: '' } }) - asserassert.equal(typeof o, 'object') + assert.equal(typeof o, 'object') }) }) test('slugify', async function (t) { - await await t.test('HelloWorld', function (t) { + await t.test('HelloWorld', function (t) { const o = slugify('HelloWorld') - asserassert.equal(o, 'helloworld') + assert.equal(o, 'helloworld') }) - await await t.test('Hello World', function (t) { + await t.test('Hello World', function (t) { const o = slugify('Hello World') - asserassert.equal(o, 'hello-world') + assert.equal(o, 'hello-world') }) - await await t.test('Exceed Limit', function (t) { + await t.test('Exceed Limit', function (t) { const o = slugify('I am a super long string that will exceed the limit hahahahahahahahahahahahahahahahahahahahahahahahahahaahhaha') - asserassert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaha') + assert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaha') }) - await await t.test('Exceed Limit and End with Dash', function (t) { + await t.test('Exceed Limit and End with Dash', function (t) { const o = slugify('I am a super long string that will exceed the limit hahahahahahahahahaa a') - asserassert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaa') + assert.equal(o, 'i-am-a-super-long-string-that-will-exceed-the-limit-hahahahahahahahahaa') }) - await await t.test('Include Unicode Character', function (t) { + await t.test('Include Unicode Character', function (t) { const o = slugify('訂閱計劃 Subscription Plan 1 Month') - asserassert.equal(o, '訂閱計劃-subscription-plan-1-month') + assert.equal(o, '訂閱計劃-subscription-plan-1-month') }) - await await t.test('Exclude Unicode Character', function (t) { + await t.test('Exclude Unicode Character', function (t) { const o = slugify('訂閱計劃 Subscription Plan 1 Month', { unicode: false }) - asserassert.equal(o, 'subscription-plan-1-month') + assert.equal(o, 'subscription-plan-1-month') }) - await await t.test('Limit to 1', function (t) { + await t.test('Limit to 1', function (t) { const o = slugify('I am a super long string that will exceed the limit hahahahahahahahahaa a', { limit: 1 }) - asserassert.equal(o, 'i') + assert.equal(o, 'i') }) - await await t.test('should use pinyin', function (t) { + await t.test('should use pinyin', function (t) { const o = slugify('訂閱計劃', { pinyin: true }) - asserassert.equal(o, 'ding-yue-ji-hua') + assert.equal(o, 'ding-yue-ji-hua') }) - await await t.test('should use pinyin', function (t) { + await t.test('should use pinyin', function (t) { const o = slugify('訂閱計劃 Subscription Plan 1 Month', { pinyin: true }) - asserassert.equal(o, 'ding-yue-ji-hua-subscription-plan-1-month') + assert.equal(o, 'ding-yue-ji-hua-subscription-plan-1-month') }) - await await t.test('should use pinyin but all englush', function (t) { + await t.test('should use pinyin but all englush', function (t) { const o = slugify('Subscription Plan 1 Month', { pinyin: true }) - asserassert.equal(o, 'subscription-plan-1-month') + assert.equal(o, 'subscription-plan-1-month') }) - await await t.test('should use default generator', function (t) { + await t.test('should use default generator', function (t) { const o = slugify('訂閱計劃', { unicode: false }) - asserassert.equal(o.length <= 16, true) + assert.equal(o.length <= 16, true) }) - await await t.test('should use custom generator', function (t) { + await t.test('should use custom generator', function (t) { const o = slugify('訂閱計劃', { unicode: false, generator () { return 'custom' } }) - asserassert.equal(o, 'custom') + assert.equal(o, 'custom') }) }) test('clone', async function (t) { - await await t.test('{ foo: null }', function (t) { + await t.test('{ foo: null }', function (t) { const o = clone({ foo: null }) assert.deepEqual(o, { foo: null }) }) - await await t.test('{ foo: string }', function (t) { + await t.test('{ foo: string }', function (t) { const o = clone({ foo: 'bar' }) assert.deepEqual(o, { foo: 'bar' }) }) - await await t.test('[string]', function (t) { + await t.test('[string]', function (t) { const o = clone(['foo', 'bar']) assert.deepEqual(o, ['foo', 'bar']) }) - await await t.test('string', function (t) { + await t.test('string', function (t) { const o = clone('foo') - asserassert.equal(o, 'foo') + assert.equal(o, 'foo') }) - await await t.test('{ foo: Date }', function (t) { + await t.test('{ foo: Date }', function (t) { const ref = { foo: new Date() } const o = clone(ref) assert.deepEqual(o, ref) }) - await await t.test('Map { foo: bar }', function (t) { + await t.test('Map { foo: bar }', function (t) { const ref = new Map([['foo', 'bar']]) const o = clone(ref) assert.deepEqual(o, ref) }) - await await t.test('Set { foo }', function (t) { + await t.test('Set { foo }', function (t) { const ref = new Set(['foo']) const o = clone(ref) assert.deepEqual(o, ref)