Helpers
Set of useful helper functions.
Encryption and Hashing Helpers
All encryption, hashing, and cryptographic utilities are available under the Enc namespace:
import { Enc } from "@devbro/neko-helper";
// Usage examples
const hash = Enc.hash.sha256("hello world");
const encrypted = await Enc.password.encryptPassword("myPassword");
const token = Enc.jwt.sign({ userId: 123 }, "secret");
Hash Functions (Enc.hash)
The Enc.hash namespace provides common cryptographic hashing algorithms.
Enc.hash.md5(data: string): string
Generates an MD5 hash of the input string.
Enc.hash.md5("hello world");
// Returns: '5eb63bbbe01eeed093cb22bb8f5acdc3'
Enc.hash.sha1(data: string): string
Generates a SHA-1 hash of the input string.
Enc.hash.sha1("hello world");
// Returns: '2aae6c35c94fcfb415dbe95f408b9ce91ee846ed'
Enc.hash.sha256(data: string): string
Generates a SHA-256 hash of the input string.
Enc.hash.sha256("hello world");
// Returns: 'b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9'
Enc.hash.sha512(data: string): string
Generates a SHA-512 hash of the input string.
Enc.hash.sha512("hello world");
// Returns: '309ecc489c12d6eb4cc40f50c902f2b4d0ed77ee511a7c7a9bcd3ca86d4cd86f...'
Enc.hash.sha3_256(data: string): string
Generates a SHA3-256 hash of the input string.
Enc.hash.sha3_256("hello world");
// Returns: '644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938'
Enc.hash.sha3_512(data: string): string
Generates a SHA3-512 hash of the input string.
Enc.hash.sha3_512("hello world");
// Returns: '840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a...'
Password Management (Enc.password)
The Enc.password namespace provides bcrypt-based password hashing utilities.
Enc.password.isBcryptHash(str: string): boolean
Checks if a string is a valid bcrypt hash. Supports $2a, $2b, and $2y versions.
Enc.password.isBcryptHash(
"$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy",
);
// Returns: true
Enc.password.isBcryptHash("not a hash");
// Returns: false
Enc.password.encryptPassword(password: string, rounds?: number): Promise<string>
Encrypts a password using bcrypt. Default rounds is 10.
const hash = await Enc.password.encryptPassword("mySecurePassword");
// Returns: '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy'
// With custom rounds
const hash = await Enc.password.encryptPassword("myPassword", 12);
Enc.password.comparePassword(password: string, hash: string): Promise<boolean>
Compares a plain text password with a bcrypt hash.
const isMatch = await Enc.password.comparePassword("myPassword", hash);
// Returns: true or false
Key Generation (Enc.keys)
The Enc.keys namespace provides cryptographic key pair generation.
Enc.keys.rsa(modulusLength?: number): { publicKey: string; privateKey: string }
Generates an RSA key pair. Default modulus length is 2048 bits.
const { publicKey, privateKey } = Enc.keys.rsa();
// Returns PEM-formatted keys
// With custom modulus length
const keys = Enc.keys.rsa(4096);
Enc.keys.ed25519(): Promise<{ publicKey: string; privateKey: string }>
Generates an Ed25519 key pair for modern cryptography.
const { publicKey, privateKey } = await Enc.keys.ed25519();
// Returns hex-encoded keys (64 characters each)
JWT Operations (Enc.jwt)
The Enc.jwt namespace provides JSON Web Token utilities.
Enc.jwt.sign(payload: string | object | Buffer, secret: string, options?: SignOptions): string
Signs a JWT with the provided payload and secret.
const token = Enc.jwt.sign({ userId: 123, name: "John" }, "mySecret");
// Returns: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
// With expiration
const token = Enc.jwt.sign({ userId: 123 }, "secret", { expiresIn: "1h" });
// With algorithm
const token = Enc.jwt.sign({ data: "test" }, "secret", { algorithm: "HS256" });
Enc.jwt.verify(token: string, secret: string, options?: VerifyOptions): string | JwtPayload
Verifies a JWT token and returns the decoded payload. Throws an error if verification fails.
try {
const payload = Enc.jwt.verify(token, "mySecret");
console.log(payload); // { userId: 123, iat: 1234567890, exp: 1234571490 }
} catch (err) {
console.error("Invalid token");
}
Enc.jwt.decode(token: string, options?: DecodeOptions): null | string | JwtPayload
Decodes a JWT token without verifying its signature.
const payload = Enc.jwt.decode(token);
// Returns decoded payload or null if invalid
Digital Signatures (Enc.sign)
The Enc.sign namespace provides Ed25519 signature operations.
Enc.sign.ed25519(privateKey: string, data: string): Promise<string>
Signs data using an Ed25519 private key.
const { privateKey } = await Enc.keys.ed25519();
const signature = await Enc.sign.ed25519(privateKey, "message to sign");
// Returns: hex-encoded signature (128 characters)
Enc.sign.verifyEd25519(publicKey: string, signature: string, data: string): Promise<boolean>
Verifies an Ed25519 signature.
const { publicKey, privateKey } = await Enc.keys.ed25519();
const signature = await Enc.sign.ed25519(privateKey, "message");
const isValid = await Enc.sign.verifyEd25519(publicKey, signature, "message");
// Returns: true or false
Legacy Functions
For backward compatibility, these functions are still available at the root level:
getEnv(key: string, defaultValue?: any): any
Get environment variable value by key. If not found, return defaultValue. If defaultValue is not provided, throw an error.
isBcryptHash(str: string): boolean
Check if a string is a valid bcrypt hash. Deprecated: Use Enc.password.isBcryptHash() instead.
encryptPassword(password: string): Promise<string>
Encrypt a password using bcrypt. Deprecated: Use Enc.password.encryptPassword() instead.
compareBcrypt(password: string, hash: string): Promise<boolean>
Compare a password with a bcrypt hash. Deprecated: Use Enc.password.comparePassword() instead.
Time Helpers
sleep(ms: number): Promise<void>
Sleep for a given number of milliseconds.
Number Helpers
All number utility functions are available under the Num namespace:
import { Num } from "@devbro/neko-helper";
// Usage examples
Num.abbreviate(1500); // "1.5K"
Num.currencyFormat(1234.56); // "$1,234.56"
Num.fileSize(1024); // "1 KB"
Num.abbreviate(num: number): string
Abbreviates large numbers with appropriate suffixes (K, M, B, T, etc.).
import { Num } from "@devbro/neko-helper";
Num.abbreviate(1000); // "1K"
Num.abbreviate(1500); // "1.5K"
Num.abbreviate(1000000); // "1M"
Num.abbreviate(2500000); // "2.5M"
Num.clamp(num: number, min: number, max: number): number
Clamps a number between minimum and maximum values.
import { Num } from "@devbro/neko-helper";
Num.clamp(5, 1, 10); // 5
Num.clamp(-5, 1, 10); // 1
Num.clamp(15, 1, 10); // 10
Num.currencyFormat(num: number, currency?: string): string
Formats a number as currency with proper locale formatting. Default currency is USD.
import { Num } from "@devbro/neko-helper";
Num.currencyFormat(1234.56); // "$1,234.56"
Num.currencyFormat(1234.56, "EUR"); // "€1,234.56"
Num.currencyFormat(1000, "GBP"); // "£1,000.00"
Num.fileSize(num: number): string
Formats a number of bytes into a human-readable file size string.
import { Num } from "@devbro/neko-helper";
Num.fileSize(1024); // "1 KB"
Num.fileSize(1536); // "1.5 KB"
Num.fileSize(1048576); // "1 MB"
Num.fileSize(500); // "500 B"
Num.format(num: number, decimalPlaces?: number): string
Formats a number with specified decimal places and thousands separators. Default is 2 decimal places.
import { Num } from "@devbro/neko-helper";
Num.format(1234.5678); // "1,234.57"
Num.format(1234.5678, 1); // "1,234.6"
Num.format(1000000); // "1,000,000.00"
Num.format(42, 0); // "42"
Num.ordinal(num: number): string
Converts a number to its ordinal string representation (1st, 2nd, 3rd, etc.).
import { Num } from "@devbro/neko-helper";
Num.ordinal(1); // "1st"
Num.ordinal(2); // "2nd"
Num.ordinal(3); // "3rd"
Num.ordinal(21); // "21st"
Num.ordinal(101); // "101st"
Num.parse(str: string | number | undefined): number | undefined
Parses a string or number to extract a numeric value. Returns undefined if parsing fails. Properly handles zero values.
import { Num } from "@devbro/neko-helper";
Num.parse("123"); // 123
Num.parse("123.45"); // 123.45
Num.parse("-42"); // -42
Num.parse("1,234"); // 1234
Num.parse("0"); // 0
Num.parse(0); // 0
Num.parse(42); // 42
Num.parse("not a number"); // undefined
Num.parse(""); // undefined
Num.spell(num: number): string
Converts a number to its written English word representation.
import { Num } from "@devbro/neko-helper";
Num.spell(42); // "forty-two"
Num.spell(100); // "one hundred"
Num.spell(1001); // "one thousand one"
Num.spell(-5); // "minus five"
Num.spell(0); // "zero"
Num.spellOrdinal(num: number): string
Converts a number to its written English ordinal word representation.
import { Num } from "@devbro/neko-helper";
Num.spellOrdinal(1); // "first"
Num.spellOrdinal(2); // "second"
Num.spellOrdinal(3); // "third"
Num.spellOrdinal(21); // "twenty-first"
Num.spellOrdinal(100); // "one hundredth"
Array Helpers
All array utility functions are available under the Arr namespace:
import { Arr } from "@devbro/neko-helper";
// Usage examples
Arr.intersperse([1, 2, 3], 0); // [1, 0, 2, 0, 3]
Arr.flatten([
[1, 2],
[3, 4],
]); // [1, 2, 3, 4]
Arr.get([1, 2, 3], -1); // 3
Arr.intersperse<T, S>(arr: T[], sep: S): (T | S)[]
Intersperses a separator element between each element of an array.
Arr.intersperse([1, 2, 3], 0); // [1, 0, 2, 0, 3]
Arr.intersperse(["a", "b", "c"], "-"); // ['a', '-', 'b', '-', 'c']
Arr.intersperse([1], 0); // [1]
Arr.intersperse([], 0); // []
Arr.flatten<T>(arr: T[][]): T[]
Flattens a nested array by one level.
Arr.flatten([[1, 2], [3, 4], [5]]); // [1, 2, 3, 4, 5]
Arr.flatten([["a", "b"], ["c"], ["d", "e"]]); // ['a', 'b', 'c', 'd', 'e']
Arr.flatten([[], [1, 2], []]); // [1, 2]
Arr.crossJoin<T, U>(arr1: T[], arr2: U[]): [T, U][]
Creates a cross join (Cartesian product) of two arrays.
Arr.crossJoin([1, 2], ["a", "b"]); // [[1, 'a'], [1, 'b'], [2, 'a'], [2, 'b']]
Arr.crossJoin(["x"], [1, 2, 3]); // [['x', 1], ['x', 2], ['x', 3]]
Arr.crossJoin([], [1, 2]); // []
Arr.get<T, D>(arr: T[], index: number, defaultValue?: D): T | D | undefined
Gets an element from an array at the specified index. Supports negative indices to count from the end.
Arr.get([1, 2, 3, 4], 1); // 2
Arr.get([1, 2, 3, 4], -1); // 4
Arr.get([1, 2, 3], 10, "default"); // 'default'
Arr.get([], 0, "empty"); // 'empty'
Arr.first<T, D>(arr: T[], defaultValue?: D): T | D | undefined
Gets the first element of an array.
Arr.first([1, 2, 3]); // 1
Arr.first(["a", "b", "c"]); // 'a'
Arr.first([], "default"); // 'default'
Arr.first([]); // undefined
Arr.last<T, D>(arr: T[], defaultValue?: D): T | D | undefined
Gets the last element of an array.
Arr.last([1, 2, 3]); // 3
Arr.last(["a", "b", "c"]); // 'c'
Arr.last([], "default"); // 'default'
Arr.last([]); // undefined
Arr.split<T>(arr: T[], sizeOrFunc: number | ((item: T, index: number) => boolean)): T[][]
Splits an array into chunks based on size or a predicate function.
// Split by size
Arr.split([1, 2, 3, 4, 5, 6], 2); // [[1, 2], [3, 4], [5, 6]]
Arr.split([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
// Split by predicate
Arr.split([1, 2, 3, 4, 5, 6], (item) => item % 3 === 0);
// [[1, 2], [3, 4, 5], [6]]
Arr.random<T>(arr: T[]): T | undefined
Returns a random element from an array.
Arr.random([1, 2, 3, 4, 5]); // any element from array (e.g., 3)
Arr.random(["apple", "banana", "cherry"]); // any string (e.g., 'banana')
Arr.random([]); // undefined
Arr.random(["single"]); // 'single'
Arr.shuffle<T>(arr: T[]): T[]
Returns a new array with elements shuffled in random order using Fisher-Yates algorithm.
Arr.shuffle([1, 2, 3, 4, 5]); // [3, 1, 5, 2, 4] (random order)
Arr.shuffle(["a", "b", "c"]); // ['c', 'a', 'b'] (random order)
Arr.shuffle([]); // []
Arr.shuffle(["single"]); // ['single']
Pattern helpers
export function createSingleton<T>(func: (...args: any[]) => T): (label?: string, ...args: any[]) => T
Create a singleton instance using a method. It will return a function that will return the singleton instance. each singleton is identified by a label. if label is not provided, it will be a default singleton. if the function is called again with the same label, it will return the same instance.
class FlexibleFactory<T>
A factory class that can create instances of a class with different configurations. you first need to register different functions that will create the instance. then you can create the instance by calling the create method with the label of the function.
import { FlexibleFactory } from "@devbro/pashmak/helpers";
class MailerProviderFactory extends FlexibleFactory<Mailer> {}
MailerProviderFactory.register("smtp", (config) => new SmtpMailer(config));
MailerProviderFactory.register(
"sendgrid",
(config) => new SendgridMailer(config),
);
const mailer = MailerProviderFactory.create("smtp", {
host: "smtp.example.com",
});