@eds-fw/utils
Advanced tools
+87
| /** | ||
| * Nicely divides a number into units, tens, hundreds, thousands, etc. Example: `1234567` -> `1 234 567` | ||
| */ | ||
| export declare function formatNumber(x: number): string; | ||
| /** | ||
| * Prints to the console information about the memory usage of the given process. | ||
| */ | ||
| export declare function reportMemory(): void; | ||
| /** | ||
| * Returns pseudo-random number from `min` to `max` | ||
| */ | ||
| export declare function random(min: number, max: number): number; | ||
| /** | ||
| * Returns a random array element | ||
| */ | ||
| export declare function arrRandom<T>(arr: T[]): T; | ||
| /** | ||
| * Returns a random key of the specified object with a chance equal to the value of this key | ||
| * | ||
| * Algorithm: https://github.com/jotson/LootTable.js | ||
| * @param elements object as {"key": chance} | ||
| */ | ||
| export declare function chanceRandom(elements: Record<string, number>): string; | ||
| /** | ||
| * Checks for equality data of primitive and reference types | ||
| */ | ||
| export declare function equal(v1: any, v2: any): boolean; | ||
| /** | ||
| * Fluently compares texts for the presence of the same | ||
| */ | ||
| export declare function quickTextCompare(text1: string, text2: string): boolean; | ||
| /** | ||
| * Checks if an array contains all specified values | ||
| */ | ||
| export declare function includesAll<T extends any[]>(arr: T, values: T): boolean; | ||
| /** | ||
| * Stops code execution for the specified duration | ||
| */ | ||
| export declare function wait(time_ms: number): Promise<void>; | ||
| /** | ||
| * Creates a [deep copy](https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy) of an object | ||
| * | ||
| * Supports only serializable objects (JSON-like) | ||
| */ | ||
| export declare function deepCopy<T extends JSONLikeObj>(source: T): T; | ||
| export declare namespace VersionBits { | ||
| const zeroVersion: number[]; | ||
| const delimiter = "."; | ||
| function from(input: string): number[]; | ||
| function sum(version: number[], to_add: number[]): void; | ||
| function toString(version: number[]): string; | ||
| /** | ||
| * @param majority `0` is 'patch', `1` is 'minor', `2` is 'major' | ||
| */ | ||
| function increase(version: number[], count: number, majority: number): void; | ||
| } | ||
| /** | ||
| * When the number of elements reaches the limit, the `PacketBuffer` is drained | ||
| */ | ||
| export declare class PacketBuffer<T> implements Disposable { | ||
| #private; | ||
| private drain_callback; | ||
| private limit; | ||
| private auto_drain; | ||
| private stack; | ||
| constructor(drain_callback: (items: T[]) => unknown, limit: number, auto_drain?: boolean); | ||
| /** | ||
| * Number of elements for all time | ||
| */ | ||
| get total_elements_count(): number; | ||
| put(item: T): void; | ||
| forceDrain(): Promise<void>; | ||
| private _check_limit; | ||
| [Symbol.dispose](): void; | ||
| } | ||
| /** | ||
| * Splits `[0,1,2,3,4,5,6,7,8,9]` to `[[0,1,2], [3,4,5], [6,7,8], [9]]` (if portionSize=3) | ||
| */ | ||
| export declare function splitIntoPortions<T>(arr: T[], portionSize: number): T[][]; | ||
| /** | ||
| * Expands the tree of the specified folder | ||
| */ | ||
| export declare function expandDir(dir_path: string): string[]; | ||
| type SerializableTypes = string | number | boolean | object | null; | ||
| export type JSONSupported = SerializableTypes | SerializableTypes[]; | ||
| export type JSONLikeObj = Record<string, JSONSupported>; | ||
| export {}; |
+220
| import arr_equal from "array-equal"; | ||
| import obj_equal from "fast-deep-equal"; | ||
| import { readdirSync, statSync } from "fs"; | ||
| import { join as path_join, sep } from "path"; | ||
| import { setTimeout } from "timers/promises"; | ||
| /** | ||
| * Nicely divides a number into units, tens, hundreds, thousands, etc. Example: `1234567` -> `1 234 567` | ||
| */ | ||
| export function formatNumber(x) { | ||
| return x.toString().split('').reverse().map(($, i) => (i + 1) % 3 > 0 ? $ : ' ' + $).reverse().join('').trim(); | ||
| } | ||
| /** | ||
| * Prints to the console information about the memory usage of the given process. | ||
| */ | ||
| export function reportMemory() { | ||
| let prUsage = formatNumber(process.memoryUsage().heapUsed); | ||
| let prTotal = formatNumber(process.memoryUsage().heapTotal); | ||
| let kUsage = formatNumber(Math.floor(process.memoryUsage().heapUsed / 1024)); | ||
| let kTotal = formatNumber(Math.floor(process.memoryUsage().heapTotal / 1024)); | ||
| console.log(" __________________________________________________"); | ||
| console.log(`| ${prUsage} B${" ".repeat(24 - prUsage.split('').length)}/ ${prTotal} B`); | ||
| console.log(`| ${kUsage} KB${" ".repeat(23 - kUsage.split('').length)}/ ${kTotal} KB`); | ||
| console.log("|__________________________________________________"); | ||
| } | ||
| /** | ||
| * Returns pseudo-random number from `min` to `max` | ||
| */ | ||
| export function random(min, max) { | ||
| return Math.floor(Math.random() * (max + 1)) + min; | ||
| } | ||
| /** | ||
| * Returns a random array element | ||
| */ | ||
| export function arrRandom(arr) { | ||
| return arr[random(0, arr.length - 1)]; | ||
| } | ||
| /** | ||
| * Returns a random key of the specified object with a chance equal to the value of this key | ||
| * | ||
| * Algorithm: https://github.com/jotson/LootTable.js | ||
| * @param elements object as {"key": chance} | ||
| */ | ||
| export function chanceRandom(elements) { | ||
| const table = Object.entries(elements); | ||
| let i; | ||
| let totalWeight = 0; | ||
| for (i = 0; i < table.length; i++) | ||
| totalWeight += table[i][1]; | ||
| let choice = 0; | ||
| const randomNumber = Math.floor(Math.random() * totalWeight + 1); | ||
| let weight = 0; | ||
| for (i = 0; i < table.length; i++) { | ||
| weight += table[i][1]; | ||
| if (randomNumber <= weight) { | ||
| choice = i; | ||
| break; | ||
| } | ||
| } | ||
| return table[choice][0]; | ||
| } | ||
| /** | ||
| * Checks for equality data of primitive and reference types | ||
| */ | ||
| export function equal(v1, v2) { | ||
| if (v1 === v2) | ||
| return true; | ||
| else if (Array.isArray(v1) && Array.isArray(v2) && arr_equal(v1, v2)) | ||
| return true; | ||
| else if (typeof v1 == "object" && typeof v2 == "object" && obj_equal(v1, v2)) | ||
| return true; | ||
| else | ||
| return false; | ||
| } | ||
| /** | ||
| * Fluently compares texts for the presence of the same | ||
| */ | ||
| export function quickTextCompare(text1, text2) { | ||
| let v1w = text1.split(' '), v1eq = 0; | ||
| let v2w = text2.split(' '), v2eq = 0; | ||
| let inaccuracy = Math.floor(v1w.length / 15) || 1; | ||
| for (const word of v1w) | ||
| if (v2w.includes(word)) | ||
| v1eq++; | ||
| for (const word of v2w) | ||
| if (v1w.includes(word)) | ||
| v2eq++; | ||
| if (v1eq + inaccuracy >= v2eq | ||
| && v2eq + inaccuracy >= v1eq | ||
| && v1eq + (inaccuracy * 1.5) >= v1w.length | ||
| && v2eq + (inaccuracy * 1.5) >= v2w.length) | ||
| return true; | ||
| else | ||
| return false; | ||
| } | ||
| /** | ||
| * Checks if an array contains all specified values | ||
| */ | ||
| export function includesAll(arr, values) { | ||
| for (const value of values) | ||
| if (!arr.includes(value)) | ||
| return false; | ||
| return true; | ||
| } | ||
| /** | ||
| * Stops code execution for the specified duration | ||
| */ | ||
| export async function wait(time_ms) { | ||
| await setTimeout(time_ms); | ||
| } | ||
| /** | ||
| * Creates a [deep copy](https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy) of an object | ||
| * | ||
| * Supports only serializable objects (JSON-like) | ||
| */ | ||
| export function deepCopy(source) { | ||
| return JSON.parse(JSON.stringify(source)); | ||
| } | ||
| export var VersionBits; | ||
| (function (VersionBits) { | ||
| VersionBits.zeroVersion = [0, 0]; | ||
| VersionBits.delimiter = '.'; | ||
| function from(input) { | ||
| return Object.assign([], VersionBits.zeroVersion, input.split(VersionBits.delimiter).map(_ => Number(_))); | ||
| } | ||
| VersionBits.from = from; | ||
| function sum(version, to_add) { | ||
| Object.assign(version, Object.assign(to_add.map(() => 0), version)); | ||
| console.log(version); | ||
| to_add.forEach((x, i) => version[i] += x); | ||
| } | ||
| VersionBits.sum = sum; | ||
| function toString(version) { | ||
| return version.filter((x, i) => i > 1 ? x != 0 : true).join(VersionBits.delimiter); | ||
| } | ||
| VersionBits.toString = toString; | ||
| /** | ||
| * @param majority `0` is 'patch', `1` is 'minor', `2` is 'major' | ||
| */ | ||
| function increase(version, count, majority) { | ||
| const reversed_majority = version.length - majority - 1; | ||
| version[reversed_majority] += count; | ||
| if (reversed_majority + 1 < version.length) | ||
| for (let i = reversed_majority + 1; i < version.length; i++) | ||
| version[i] = 0; | ||
| } | ||
| VersionBits.increase = increase; | ||
| })(VersionBits || (VersionBits = {})); | ||
| //@ts-expect-error | ||
| Symbol.dispose ??= "__dispose"; | ||
| /** | ||
| * When the number of elements reaches the limit, the `PacketBuffer` is drained | ||
| */ | ||
| export class PacketBuffer { | ||
| drain_callback; | ||
| limit; | ||
| auto_drain; | ||
| #total_elements_count = 0; | ||
| stack = []; | ||
| constructor(drain_callback, limit, auto_drain = true) { | ||
| this.drain_callback = drain_callback; | ||
| this.limit = limit; | ||
| this.auto_drain = auto_drain; | ||
| } | ||
| /** | ||
| * Number of elements for all time | ||
| */ | ||
| get total_elements_count() { return this.#total_elements_count; } | ||
| put(item) { | ||
| this.#total_elements_count++; | ||
| this.stack.push(item); | ||
| this._check_limit(); | ||
| } | ||
| async forceDrain() { | ||
| for (const output_elements of splitIntoPortions(this.stack, this.limit)) | ||
| await this.drain_callback(output_elements); | ||
| this.stack = []; | ||
| } | ||
| _check_limit() { | ||
| if (this.auto_drain && this.stack.length >= this.limit) | ||
| this.forceDrain(); | ||
| } | ||
| [Symbol.dispose]() { | ||
| if (this.stack.length > 0) | ||
| this.forceDrain(); | ||
| } | ||
| } | ||
| /** | ||
| * Splits `[0,1,2,3,4,5,6,7,8,9]` to `[[0,1,2], [3,4,5], [6,7,8], [9]]` (if portionSize=3) | ||
| */ | ||
| export function splitIntoPortions(arr, portionSize) { | ||
| if (arr.length <= portionSize) | ||
| return [arr]; | ||
| const output = [[]]; | ||
| for (let i = 0; i < arr.length; i++) | ||
| if (i % portionSize == 0) | ||
| output.push([arr[i]]); | ||
| else | ||
| output.at(-1)?.push(arr[i]); | ||
| return output; | ||
| } | ||
| /** | ||
| * Expands the tree of the specified folder | ||
| */ | ||
| export function expandDir(dir_path) { | ||
| const buffer = []; | ||
| _expandDir(dir_path, buffer); | ||
| if (dir_path.startsWith('./') || dir_path.startsWith('.\\')) | ||
| return buffer.map(path => '.' + sep + path); | ||
| return buffer; | ||
| } | ||
| function _expandDir(dir_path, /*ref*/ buffer) { | ||
| const files = readdirSync(dir_path); | ||
| files.forEach(file => { | ||
| const filePath = path_join(dir_path, file); | ||
| const fileStat = statSync(filePath); | ||
| buffer.push(filePath); | ||
| if (fileStat.isDirectory()) | ||
| expandDir(filePath); | ||
| }); | ||
| } |
+6
-13
| { | ||
| "type": "module", | ||
| "devDependencies": { | ||
@@ -9,3 +10,3 @@ "@types/array-equal": "^1.0.0", | ||
| "TS_inspect": "npx tsc --noEmit --watch", | ||
| "TS_build": "npx tsc -p tsconfig.cjs.json && npx tsc -p tsconfig.esm.json && npx tsc -p tsconfig.types.json" | ||
| "TS_build": "npx tsc" | ||
| }, | ||
@@ -18,5 +19,5 @@ "dependencies": { | ||
| "name": "@eds-fw/utils", | ||
| "version": "2.0.2", | ||
| "version": "3.0.0", | ||
| "description": "Tiny TypeScript utils: wait(), chanceRandom(), formatNumber(), equal(), quickTextCompare() and more", | ||
| "main": "index", | ||
| "main": "index.mjs", | ||
| "repository": { | ||
@@ -33,3 +34,3 @@ "type": "git", | ||
| "license": "MIT", | ||
| "types": "./dist/index.d.ts", | ||
| "types": "index.d.mts", | ||
| "bugs": { | ||
@@ -39,14 +40,6 @@ "url": "https://github.com/eds-fw/utils/issues" | ||
| "homepage": "https://github.com/eds-fw/utils#readme", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/types/index.d.ts", | ||
| "require": "./dist/cjs/index.js", | ||
| "import": "./dist/esm/index.js", | ||
| "default": "./dist/esm/index.js" | ||
| } | ||
| }, | ||
| "typesVersions": { | ||
| ">=4.2": { | ||
| "*": [ | ||
| "dist/types/index.d.ts" | ||
| "index.d.mts" | ||
| ] | ||
@@ -53,0 +46,0 @@ } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.expandDir = exports.splitIntoPortions = exports.PacketBuffer = exports.VersionBits = exports.deepCopy = exports.wait = exports.includesAll = exports.quickTextCompare = exports.equal = exports.chanceRandom = exports.arrRandom = exports.random = exports.reportMemory = exports.formatNumber = void 0; | ||
| const tslib_1 = require("tslib"); | ||
| const array_equal_1 = tslib_1.__importDefault(require("array-equal")); | ||
| const fast_deep_equal_1 = tslib_1.__importDefault(require("fast-deep-equal")); | ||
| const fs_1 = require("fs"); | ||
| const path_1 = require("path"); | ||
| const promises_1 = require("timers/promises"); | ||
| /** | ||
| * Nicely divides a number into units, tens, hundreds, thousands, etc. Example: `1234567` -> `1 234 567` | ||
| */ | ||
| function formatNumber(x) { | ||
| return x.toString().split('').reverse().map(($, i) => (i + 1) % 3 > 0 ? $ : ' ' + $).reverse().join('').trim(); | ||
| } | ||
| exports.formatNumber = formatNumber; | ||
| /** | ||
| * Prints to the console information about the memory usage of the given process. | ||
| */ | ||
| function reportMemory() { | ||
| let prUsage = formatNumber(process.memoryUsage().heapUsed); | ||
| let prTotal = formatNumber(process.memoryUsage().heapTotal); | ||
| let kUsage = formatNumber(Math.floor(process.memoryUsage().heapUsed / 1024)); | ||
| let kTotal = formatNumber(Math.floor(process.memoryUsage().heapTotal / 1024)); | ||
| console.log(" __________________________________________________"); | ||
| console.log(`| ${prUsage} B${" ".repeat(24 - prUsage.split('').length)}/ ${prTotal} B`); | ||
| console.log(`| ${kUsage} KB${" ".repeat(23 - kUsage.split('').length)}/ ${kTotal} KB`); | ||
| console.log("|__________________________________________________"); | ||
| } | ||
| exports.reportMemory = reportMemory; | ||
| /** | ||
| * Returns pseudo-random number from `min` to `max` | ||
| */ | ||
| function random(min, max) { | ||
| return Math.floor(Math.random() * (max + 1)) + min; | ||
| } | ||
| exports.random = random; | ||
| /** | ||
| * Returns a random array element | ||
| */ | ||
| function arrRandom(arr) { | ||
| return arr[random(0, arr.length - 1)]; | ||
| } | ||
| exports.arrRandom = arrRandom; | ||
| /** | ||
| * Returns a random key of the specified object with a chance equal to the value of this key | ||
| * | ||
| * Algorithm: https://github.com/jotson/LootTable.js | ||
| * @param elements object as {"key": chance} | ||
| */ | ||
| function chanceRandom(elements) { | ||
| const table = Object.entries(elements); | ||
| let i; | ||
| let totalWeight = 0; | ||
| for (i = 0; i < table.length; i++) | ||
| totalWeight += table[i][1]; | ||
| let choice = 0; | ||
| const randomNumber = Math.floor(Math.random() * totalWeight + 1); | ||
| let weight = 0; | ||
| for (i = 0; i < table.length; i++) { | ||
| weight += table[i][1]; | ||
| if (randomNumber <= weight) { | ||
| choice = i; | ||
| break; | ||
| } | ||
| } | ||
| return table[choice][0]; | ||
| } | ||
| exports.chanceRandom = chanceRandom; | ||
| /** | ||
| * Checks for equality data of primitive and reference types | ||
| */ | ||
| function equal(v1, v2) { | ||
| if (v1 === v2) | ||
| return true; | ||
| else if (Array.isArray(v1) && Array.isArray(v2) && (0, array_equal_1.default)(v1, v2)) | ||
| return true; | ||
| else if (typeof v1 == "object" && typeof v2 == "object" && (0, fast_deep_equal_1.default)(v1, v2)) | ||
| return true; | ||
| else | ||
| return false; | ||
| } | ||
| exports.equal = equal; | ||
| /** | ||
| * Fluently compares texts for the presence of the same | ||
| */ | ||
| function quickTextCompare(text1, text2) { | ||
| let v1w = text1.split(' '), v1eq = 0; | ||
| let v2w = text2.split(' '), v2eq = 0; | ||
| let inaccuracy = Math.floor(v1w.length / 15) || 1; | ||
| for (const word of v1w) | ||
| if (v2w.includes(word)) | ||
| v1eq++; | ||
| for (const word of v2w) | ||
| if (v1w.includes(word)) | ||
| v2eq++; | ||
| if (v1eq + inaccuracy >= v2eq | ||
| && v2eq + inaccuracy >= v1eq | ||
| && v1eq + (inaccuracy * 1.5) >= v1w.length | ||
| && v2eq + (inaccuracy * 1.5) >= v2w.length) | ||
| return true; | ||
| else | ||
| return false; | ||
| } | ||
| exports.quickTextCompare = quickTextCompare; | ||
| /** | ||
| * Checks if an array contains all specified values | ||
| */ | ||
| function includesAll(arr, values) { | ||
| for (const value of values) | ||
| if (!arr.includes(value)) | ||
| return false; | ||
| return true; | ||
| } | ||
| exports.includesAll = includesAll; | ||
| /** | ||
| * Stops code execution for the specified duration | ||
| */ | ||
| async function wait(time_ms) { | ||
| await (0, promises_1.setTimeout)(time_ms); | ||
| } | ||
| exports.wait = wait; | ||
| /** | ||
| * Creates a [deep copy](https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy) of an object | ||
| * | ||
| * Supports only serializable objects (JSON-like) | ||
| */ | ||
| function deepCopy(source) { | ||
| return JSON.parse(JSON.stringify(source)); | ||
| } | ||
| exports.deepCopy = deepCopy; | ||
| var VersionBits; | ||
| (function (VersionBits) { | ||
| VersionBits.zeroVersion = [0, 0]; | ||
| VersionBits.delimiter = '.'; | ||
| function from(input) { | ||
| return Object.assign([], VersionBits.zeroVersion, input.split(VersionBits.delimiter).map(_ => Number(_))); | ||
| } | ||
| VersionBits.from = from; | ||
| function sum(version, to_add) { | ||
| Object.assign(version, Object.assign(to_add.map(() => 0), version)); | ||
| console.log(version); | ||
| to_add.forEach((x, i) => version[i] += x); | ||
| } | ||
| VersionBits.sum = sum; | ||
| function toString(version) { | ||
| return version.filter((x, i) => i > 1 ? x != 0 : true).join(VersionBits.delimiter); | ||
| } | ||
| VersionBits.toString = toString; | ||
| /** | ||
| * @param majority `0` is 'patch', `1` is 'minor', `2` is 'major' | ||
| */ | ||
| function increase(version, count, majority) { | ||
| const reversed_majority = version.length - majority - 1; | ||
| version[reversed_majority] += count; | ||
| if (reversed_majority + 1 < version.length) | ||
| for (let i = reversed_majority + 1; i < version.length; i++) | ||
| version[i] = 0; | ||
| } | ||
| VersionBits.increase = increase; | ||
| })(VersionBits || (exports.VersionBits = VersionBits = {})); | ||
| //@ts-expect-error | ||
| Symbol.dispose ??= "__dispose"; | ||
| /** | ||
| * When the number of elements reaches the limit, the `PacketBuffer` is drained | ||
| */ | ||
| class PacketBuffer { | ||
| drain_callback; | ||
| limit; | ||
| auto_drain; | ||
| #total_elements_count = 0; | ||
| stack = []; | ||
| constructor(drain_callback, limit, auto_drain = true) { | ||
| this.drain_callback = drain_callback; | ||
| this.limit = limit; | ||
| this.auto_drain = auto_drain; | ||
| } | ||
| /** | ||
| * Number of elements for all time | ||
| */ | ||
| get total_elements_count() { return this.#total_elements_count; } | ||
| put(item) { | ||
| this.#total_elements_count++; | ||
| this.stack.push(item); | ||
| this._check_limit(); | ||
| } | ||
| async forceDrain() { | ||
| for (const output_elements of splitIntoPortions(this.stack, this.limit)) | ||
| await this.drain_callback(output_elements); | ||
| this.stack = []; | ||
| } | ||
| _check_limit() { | ||
| if (this.auto_drain && this.stack.length >= this.limit) | ||
| this.forceDrain(); | ||
| } | ||
| [Symbol.dispose]() { | ||
| if (this.stack.length > 0) | ||
| this.forceDrain(); | ||
| } | ||
| } | ||
| exports.PacketBuffer = PacketBuffer; | ||
| /** | ||
| * Splits `[0,1,2,3,4,5,6,7,8,9]` to `[[0,1,2], [3,4,5], [6,7,8], [9]]` (if portionSize=3) | ||
| */ | ||
| function splitIntoPortions(arr, portionSize) { | ||
| if (arr.length <= portionSize) | ||
| return [arr]; | ||
| const output = [[]]; | ||
| for (let i = 0; i < arr.length; i++) | ||
| if (i % portionSize == 0) | ||
| output.push([arr[i]]); | ||
| else | ||
| output.at(-1)?.push(arr[i]); | ||
| return output; | ||
| } | ||
| exports.splitIntoPortions = splitIntoPortions; | ||
| /** | ||
| * Expands the tree of the specified folder | ||
| */ | ||
| function expandDir(dir_path) { | ||
| const buffer = []; | ||
| _expandDir(dir_path, buffer); | ||
| if (dir_path.startsWith('./') || dir_path.startsWith('.\\')) | ||
| return buffer.map(path => '.' + path_1.sep + path); | ||
| return buffer; | ||
| } | ||
| exports.expandDir = expandDir; | ||
| function _expandDir(dir_path, /*ref*/ buffer) { | ||
| const files = (0, fs_1.readdirSync)(dir_path); | ||
| files.forEach(file => { | ||
| const filePath = (0, path_1.join)(dir_path, file); | ||
| const fileStat = (0, fs_1.statSync)(filePath); | ||
| buffer.push(filePath); | ||
| if (fileStat.isDirectory()) | ||
| expandDir(filePath); | ||
| }); | ||
| } |
| { "type": "commonjs" } |
| import arr_equal from "array-equal"; | ||
| import obj_equal from "fast-deep-equal"; | ||
| import { readdirSync, statSync } from "fs"; | ||
| import { join as path_join, sep } from "path"; | ||
| import { setTimeout } from "timers/promises"; | ||
| /** | ||
| * Nicely divides a number into units, tens, hundreds, thousands, etc. Example: `1234567` -> `1 234 567` | ||
| */ | ||
| export function formatNumber(x) { | ||
| return x.toString().split('').reverse().map(($, i) => (i + 1) % 3 > 0 ? $ : ' ' + $).reverse().join('').trim(); | ||
| } | ||
| /** | ||
| * Prints to the console information about the memory usage of the given process. | ||
| */ | ||
| export function reportMemory() { | ||
| let prUsage = formatNumber(process.memoryUsage().heapUsed); | ||
| let prTotal = formatNumber(process.memoryUsage().heapTotal); | ||
| let kUsage = formatNumber(Math.floor(process.memoryUsage().heapUsed / 1024)); | ||
| let kTotal = formatNumber(Math.floor(process.memoryUsage().heapTotal / 1024)); | ||
| console.log(" __________________________________________________"); | ||
| console.log(`| ${prUsage} B${" ".repeat(24 - prUsage.split('').length)}/ ${prTotal} B`); | ||
| console.log(`| ${kUsage} KB${" ".repeat(23 - kUsage.split('').length)}/ ${kTotal} KB`); | ||
| console.log("|__________________________________________________"); | ||
| } | ||
| /** | ||
| * Returns pseudo-random number from `min` to `max` | ||
| */ | ||
| export function random(min, max) { | ||
| return Math.floor(Math.random() * (max + 1)) + min; | ||
| } | ||
| /** | ||
| * Returns a random array element | ||
| */ | ||
| export function arrRandom(arr) { | ||
| return arr[random(0, arr.length - 1)]; | ||
| } | ||
| /** | ||
| * Returns a random key of the specified object with a chance equal to the value of this key | ||
| * | ||
| * Algorithm: https://github.com/jotson/LootTable.js | ||
| * @param elements object as {"key": chance} | ||
| */ | ||
| export function chanceRandom(elements) { | ||
| const table = Object.entries(elements); | ||
| let i; | ||
| let totalWeight = 0; | ||
| for (i = 0; i < table.length; i++) | ||
| totalWeight += table[i][1]; | ||
| let choice = 0; | ||
| const randomNumber = Math.floor(Math.random() * totalWeight + 1); | ||
| let weight = 0; | ||
| for (i = 0; i < table.length; i++) { | ||
| weight += table[i][1]; | ||
| if (randomNumber <= weight) { | ||
| choice = i; | ||
| break; | ||
| } | ||
| } | ||
| return table[choice][0]; | ||
| } | ||
| /** | ||
| * Checks for equality data of primitive and reference types | ||
| */ | ||
| export function equal(v1, v2) { | ||
| if (v1 === v2) | ||
| return true; | ||
| else if (Array.isArray(v1) && Array.isArray(v2) && arr_equal(v1, v2)) | ||
| return true; | ||
| else if (typeof v1 == "object" && typeof v2 == "object" && obj_equal(v1, v2)) | ||
| return true; | ||
| else | ||
| return false; | ||
| } | ||
| /** | ||
| * Fluently compares texts for the presence of the same | ||
| */ | ||
| export function quickTextCompare(text1, text2) { | ||
| let v1w = text1.split(' '), v1eq = 0; | ||
| let v2w = text2.split(' '), v2eq = 0; | ||
| let inaccuracy = Math.floor(v1w.length / 15) || 1; | ||
| for (const word of v1w) | ||
| if (v2w.includes(word)) | ||
| v1eq++; | ||
| for (const word of v2w) | ||
| if (v1w.includes(word)) | ||
| v2eq++; | ||
| if (v1eq + inaccuracy >= v2eq | ||
| && v2eq + inaccuracy >= v1eq | ||
| && v1eq + (inaccuracy * 1.5) >= v1w.length | ||
| && v2eq + (inaccuracy * 1.5) >= v2w.length) | ||
| return true; | ||
| else | ||
| return false; | ||
| } | ||
| /** | ||
| * Checks if an array contains all specified values | ||
| */ | ||
| export function includesAll(arr, values) { | ||
| for (const value of values) | ||
| if (!arr.includes(value)) | ||
| return false; | ||
| return true; | ||
| } | ||
| /** | ||
| * Stops code execution for the specified duration | ||
| */ | ||
| export async function wait(time_ms) { | ||
| await setTimeout(time_ms); | ||
| } | ||
| /** | ||
| * Creates a [deep copy](https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy) of an object | ||
| * | ||
| * Supports only serializable objects (JSON-like) | ||
| */ | ||
| export function deepCopy(source) { | ||
| return JSON.parse(JSON.stringify(source)); | ||
| } | ||
| export var VersionBits; | ||
| (function (VersionBits) { | ||
| VersionBits.zeroVersion = [0, 0]; | ||
| VersionBits.delimiter = '.'; | ||
| function from(input) { | ||
| return Object.assign([], VersionBits.zeroVersion, input.split(VersionBits.delimiter).map(_ => Number(_))); | ||
| } | ||
| VersionBits.from = from; | ||
| function sum(version, to_add) { | ||
| Object.assign(version, Object.assign(to_add.map(() => 0), version)); | ||
| console.log(version); | ||
| to_add.forEach((x, i) => version[i] += x); | ||
| } | ||
| VersionBits.sum = sum; | ||
| function toString(version) { | ||
| return version.filter((x, i) => i > 1 ? x != 0 : true).join(VersionBits.delimiter); | ||
| } | ||
| VersionBits.toString = toString; | ||
| /** | ||
| * @param majority `0` is 'patch', `1` is 'minor', `2` is 'major' | ||
| */ | ||
| function increase(version, count, majority) { | ||
| const reversed_majority = version.length - majority - 1; | ||
| version[reversed_majority] += count; | ||
| if (reversed_majority + 1 < version.length) | ||
| for (let i = reversed_majority + 1; i < version.length; i++) | ||
| version[i] = 0; | ||
| } | ||
| VersionBits.increase = increase; | ||
| })(VersionBits || (VersionBits = {})); | ||
| //@ts-expect-error | ||
| Symbol.dispose ??= "__dispose"; | ||
| /** | ||
| * When the number of elements reaches the limit, the `PacketBuffer` is drained | ||
| */ | ||
| export class PacketBuffer { | ||
| drain_callback; | ||
| limit; | ||
| auto_drain; | ||
| #total_elements_count = 0; | ||
| stack = []; | ||
| constructor(drain_callback, limit, auto_drain = true) { | ||
| this.drain_callback = drain_callback; | ||
| this.limit = limit; | ||
| this.auto_drain = auto_drain; | ||
| } | ||
| /** | ||
| * Number of elements for all time | ||
| */ | ||
| get total_elements_count() { return this.#total_elements_count; } | ||
| put(item) { | ||
| this.#total_elements_count++; | ||
| this.stack.push(item); | ||
| this._check_limit(); | ||
| } | ||
| async forceDrain() { | ||
| for (const output_elements of splitIntoPortions(this.stack, this.limit)) | ||
| await this.drain_callback(output_elements); | ||
| this.stack = []; | ||
| } | ||
| _check_limit() { | ||
| if (this.auto_drain && this.stack.length >= this.limit) | ||
| this.forceDrain(); | ||
| } | ||
| [Symbol.dispose]() { | ||
| if (this.stack.length > 0) | ||
| this.forceDrain(); | ||
| } | ||
| } | ||
| /** | ||
| * Splits `[0,1,2,3,4,5,6,7,8,9]` to `[[0,1,2], [3,4,5], [6,7,8], [9]]` (if portionSize=3) | ||
| */ | ||
| export function splitIntoPortions(arr, portionSize) { | ||
| if (arr.length <= portionSize) | ||
| return [arr]; | ||
| const output = [[]]; | ||
| for (let i = 0; i < arr.length; i++) | ||
| if (i % portionSize == 0) | ||
| output.push([arr[i]]); | ||
| else | ||
| output.at(-1)?.push(arr[i]); | ||
| return output; | ||
| } | ||
| /** | ||
| * Expands the tree of the specified folder | ||
| */ | ||
| export function expandDir(dir_path) { | ||
| const buffer = []; | ||
| _expandDir(dir_path, buffer); | ||
| if (dir_path.startsWith('./') || dir_path.startsWith('.\\')) | ||
| return buffer.map(path => '.' + sep + path); | ||
| return buffer; | ||
| } | ||
| function _expandDir(dir_path, /*ref*/ buffer) { | ||
| const files = readdirSync(dir_path); | ||
| files.forEach(file => { | ||
| const filePath = path_join(dir_path, file); | ||
| const fileStat = statSync(filePath); | ||
| buffer.push(filePath); | ||
| if (fileStat.isDirectory()) | ||
| expandDir(filePath); | ||
| }); | ||
| } |
| { "type": "module" } |
| /** | ||
| * Nicely divides a number into units, tens, hundreds, thousands, etc. Example: `1234567` -> `1 234 567` | ||
| */ | ||
| export declare function formatNumber(x: number): string; | ||
| /** | ||
| * Prints to the console information about the memory usage of the given process. | ||
| */ | ||
| export declare function reportMemory(): void; | ||
| /** | ||
| * Returns pseudo-random number from `min` to `max` | ||
| */ | ||
| export declare function random(min: number, max: number): number; | ||
| /** | ||
| * Returns a random array element | ||
| */ | ||
| export declare function arrRandom<T>(arr: T[]): T; | ||
| /** | ||
| * Returns a random key of the specified object with a chance equal to the value of this key | ||
| * | ||
| * Algorithm: https://github.com/jotson/LootTable.js | ||
| * @param elements object as {"key": chance} | ||
| */ | ||
| export declare function chanceRandom(elements: Record<string, number>): string; | ||
| /** | ||
| * Checks for equality data of primitive and reference types | ||
| */ | ||
| export declare function equal(v1: any, v2: any): boolean; | ||
| /** | ||
| * Fluently compares texts for the presence of the same | ||
| */ | ||
| export declare function quickTextCompare(text1: string, text2: string): boolean; | ||
| /** | ||
| * Checks if an array contains all specified values | ||
| */ | ||
| export declare function includesAll<T extends any[]>(arr: T, values: T): boolean; | ||
| /** | ||
| * Stops code execution for the specified duration | ||
| */ | ||
| export declare function wait(time_ms: number): Promise<void>; | ||
| /** | ||
| * Creates a [deep copy](https://developer.mozilla.org/en-US/docs/Glossary/Deep_copy) of an object | ||
| * | ||
| * Supports only serializable objects (JSON-like) | ||
| */ | ||
| export declare function deepCopy<T extends JSONLikeObj>(source: T): T; | ||
| export declare namespace VersionBits { | ||
| const zeroVersion: number[]; | ||
| const delimiter = "."; | ||
| function from(input: string): number[]; | ||
| function sum(version: number[], to_add: number[]): void; | ||
| function toString(version: number[]): string; | ||
| /** | ||
| * @param majority `0` is 'patch', `1` is 'minor', `2` is 'major' | ||
| */ | ||
| function increase(version: number[], count: number, majority: number): void; | ||
| } | ||
| /** | ||
| * When the number of elements reaches the limit, the `PacketBuffer` is drained | ||
| */ | ||
| export declare class PacketBuffer<T> implements Disposable { | ||
| #private; | ||
| private drain_callback; | ||
| private limit; | ||
| private auto_drain; | ||
| private stack; | ||
| constructor(drain_callback: (items: T[]) => unknown, limit: number, auto_drain?: boolean); | ||
| /** | ||
| * Number of elements for all time | ||
| */ | ||
| get total_elements_count(): number; | ||
| put(item: T): void; | ||
| forceDrain(): Promise<void>; | ||
| private _check_limit; | ||
| [Symbol.dispose](): void; | ||
| } | ||
| /** | ||
| * Splits `[0,1,2,3,4,5,6,7,8,9]` to `[[0,1,2], [3,4,5], [6,7,8], [9]]` (if portionSize=3) | ||
| */ | ||
| export declare function splitIntoPortions<T>(arr: T[], portionSize: number): T[][]; | ||
| /** | ||
| * Expands the tree of the specified folder | ||
| */ | ||
| export declare function expandDir(dir_path: string): string[]; | ||
| type SerializableTypes = string | number | boolean | object | null; | ||
| export type JSONSupported = SerializableTypes | SerializableTypes[]; | ||
| export type JSONLikeObj = Record<string, JSONSupported>; | ||
| export {}; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
1
-50%Yes
NaN16464
-33.62%5
-37.5%220
-59.63%1
Infinity%