@akadenia/helpers
Version:
Akadenia helpers
780 lines (531 loc) • 18.1 kB
Markdown
<div align="center">
<img src="https://cdn.akadenia.com/images/akadenia-webp/logo/horizontal-logo.svg" alt="Akadenia" width="200" />
<h2><code>@akadenia/helpers</code></h2>
<img src="https://cdn.akadenia.com/images/badges/npm-version-helpers.svg" alt="npm version" />
<img src="https://cdn.akadenia.com/images/badges/license-mit.svg" alt="License: MIT" />
<img src="https://cdn.akadenia.com/images/badges/typescript.svg" alt="TypeScript" />
A zero-dependency TypeScript utility library covering the common ground every project needs — dates, strings, objects, geography, files, and more. Modular by design, so you only import what you use.
[Documentation](https://akadenia.com/packages/akadenia-helpers) · [GitHub](https://github.com/akadenia/AkadeniaHelpers) · [Issues](https://github.com/akadenia/AkadeniaHelpers/issues)
</div>
## Installation
```bash
npm install @akadenia/helpers
```
## Usage
```typescript
import { DateHelpers, TextHelpers, ObjectHelpers, MapHelpers, GenericHelpers, FileHelpers } from '@akadenia/helpers'
```
## Table of Contents
- [DateHelpers](#datehelpers)
- [TextHelpers](#texthelpers)
- [ObjectHelpers](#objecthelpers)
- [MapHelpers](#maphelpers)
- [GenericHelpers](#generichelpers)
- [FileHelpers](#filehelpers)
- [Contributing](#contributing)
## DateHelpers
### `getReadableDateTime(datetime?)`
Returns the date in `yyyy-mm-dd hh:mm:ss` format.
**Parameters:**
- `datetime` (optional): `Date` — The date to convert. Defaults to current date.
**Example:**
```typescript
import { DateHelpers } from '@akadenia/helpers'
DateHelpers.getReadableDateTime()
// "2026-02-27 15:30:25"
DateHelpers.getReadableDateTime(new Date('2024-01-15T10:30:00Z'))
// "2024-01-15 10:30:00"
```
### `getReadableDate(datetime?)`
Returns the date in `yyyy-mm-dd` format.
**Parameters:**
- `datetime` (optional): `Date` — The date to convert. Defaults to current date.
**Example:**
```typescript
DateHelpers.getReadableDate()
// "2026-02-27"
DateHelpers.getReadableDate(new Date('2024-01-15T10:30:00Z'))
// "2024-01-15"
```
### `getDateString(date)`
Returns a locale-formatted date string.
**Parameters:**
- `date`: `string | Date` — The date to convert.
**Example:**
```typescript
DateHelpers.getDateString('2024-01-15')
// "1/15/2024" (locale-dependent)
```
### `formatDateTime(date, options, localTimezone?)`
Returns a formatted date string using `Intl.DateTimeFormat` options.
**Parameters:**
- `date`: `string | Date` — The date to format.
- `options`: `Intl.DateTimeFormatOptions` — Formatting options.
- `localTimezone` (optional): `string | Intl.Locale` — Locale. Defaults to `"en-US"`.
**Example:**
```typescript
DateHelpers.formatDateTime(
new Date('2024-01-15T10:30:00Z'),
{ year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit' },
'en-US'
)
// "January 15, 2024 at 10:30 AM"
```
### `parseDate(date)`
Parses a string or Date into a `Date` object. Throws on invalid input.
**Parameters:**
- `date`: `string | Date` — The date to parse.
**Example:**
```typescript
DateHelpers.parseDate('2024-01-15')
// Date object
DateHelpers.parseDate('invalid-date')
// throws Error: Cannot parse date: "invalid-date"
```
### `getShortOrdinalDate(date, appendTime?)`
Returns a date in short ordinal format, e.g. `"Feb 27th 2026"`.
**Parameters:**
- `date`: `string | Date` — The date to format.
- `appendTime` (optional): `boolean` — Whether to include time. Defaults to `false`.
**Example:**
```typescript
DateHelpers.getShortOrdinalDate('2024-01-15')
// "Jan 15th 2024"
DateHelpers.getShortOrdinalDate('2024-01-15T10:30:00Z', true)
// "Jan 15th 2024 10:30:00"
```
---
## TextHelpers
### `uuidv4()`
Generates a random UUID v4 string.
**Example:**
```typescript
TextHelpers.uuidv4()
// "f47ac10b-58cc-4372-a567-0e02b2c3d479"
```
### `formatPosition(position)`
Returns a position number with the appropriate ordinal suffix.
**Parameters:**
- `position`: `number` — The position.
**Example:**
```typescript
TextHelpers.formatPosition(1) // "1st"
TextHelpers.formatPosition(2) // "2nd"
TextHelpers.formatPosition(3) // "3rd"
TextHelpers.formatPosition(4) // "4th"
TextHelpers.formatPosition(21) // "21st"
```
### `truncateText(text, characterLimit)`
Truncates text to the character limit, appending `"..."`.
**Parameters:**
- `text`: `string` — Text to truncate.
- `characterLimit`: `number` — Maximum number of characters.
**Example:**
```typescript
TextHelpers.truncateText("Hello World", 5) // "He..."
TextHelpers.truncateText("Hello World", 20) // "Hello World"
```
### `fileNameFromPath(path)`
Extracts the filename from a file path.
**Parameters:**
- `path`: `string` — The file path.
**Example:**
```typescript
TextHelpers.fileNameFromPath('/uploads/documents/file.pdf') // "file.pdf"
```
### `replaceSpacesWithUnderscore(s?)`
Replaces spaces with underscores.
**Example:**
```typescript
TextHelpers.replaceSpacesWithUnderscore("hello world") // "hello_world"
```
### `replaceUnderscoreWithSpaces(s?)`
Replaces underscores with spaces.
**Example:**
```typescript
TextHelpers.replaceUnderscoreWithSpaces("hello_world") // "hello world"
```
### `pluralizeOnCondition(word, condition)`
Pluralizes a word when the condition is `true`. Handles common English rules (`-y → -ies`, `-s/-sh/-ch/-x → -es`).
**Parameters:**
- `word`: `string` — The word to pluralize.
- `condition`: `boolean` — Whether to pluralize.
**Example:**
```typescript
TextHelpers.pluralizeOnCondition("item", true) // "items"
TextHelpers.pluralizeOnCondition("address", true) // "addresses"
TextHelpers.pluralizeOnCondition("library", true) // "libraries"
TextHelpers.pluralizeOnCondition("item", false) // "item"
```
### `convertSnakeToCamelCase(data)`
Converts `snake_case` to `camelCase` for strings, objects, or arrays of objects (deep).
**Example:**
```typescript
TextHelpers.convertSnakeToCamelCase("hello_world")
// "helloWorld"
TextHelpers.convertSnakeToCamelCase({ first_name: "John", user_info: { phone_number: "123" } })
// { firstName: "John", userInfo: { phoneNumber: "123" } }
```
### `convertCamelToSnakeCase(data)`
Converts `camelCase` to `snake_case` for strings, objects, or arrays of objects (deep).
**Example:**
```typescript
TextHelpers.convertCamelToSnakeCase("helloWorld")
// "hello_world"
TextHelpers.convertCamelToSnakeCase({ firstName: "John", userInfo: { phoneNumber: "123" } })
// { first_name: "John", user_info: { phone_number: "123" } }
```
### `convertCamelToKebabCase(word)`
Converts `camelCase` to `kebab-case`.
**Example:**
```typescript
TextHelpers.convertCamelToKebabCase("helloWorld") // "hello-world"
TextHelpers.convertCamelToKebabCase("XMLHttpRequest") // "xml-http-request"
```
### `convertKebabToCamelCase(word)`
Converts `kebab-case` to `CamelCase`.
**Example:**
```typescript
TextHelpers.convertKebabToCamelCase("hello-world") // "HelloWorld"
TextHelpers.convertKebabToCamelCase("xml-http-request") // "XmlHttpRequest"
```
### `convertCamelCaseToReadableText(name)`
Converts `camelCase` to a space-separated readable string.
**Example:**
```typescript
TextHelpers.convertCamelCaseToReadableText("helloWorld") // "Hello World"
TextHelpers.convertCamelCaseToReadableText("XMLHttpRequest") // "XML Http Request"
```
### `generateAcronym(term)`
Generates an acronym from the first letter of each word.
**Example:**
```typescript
TextHelpers.generateAcronym("Hyper Text Markup Language") // "HTML"
TextHelpers.generateAcronym("Application Programming Interface") // "API"
```
### `isAcronym(word)`
Returns `true` if the word is all uppercase (i.e. an acronym).
**Example:**
```typescript
TextHelpers.isAcronym("HTML") // true
TextHelpers.isAcronym("JavaScript") // false
```
### `acronymToKebabCase(word)`
Converts an acronym to kebab-case. Throws if input is not an acronym.
**Example:**
```typescript
TextHelpers.acronymToKebabCase("HTML") // "h-t-m-l"
TextHelpers.acronymToKebabCase("API") // "a-p-i"
TextHelpers.acronymToKebabCase("html") // throws Error
```
### `handleNullDisplay(value, defaultValue?)`
Returns the value, or a default string if `null` or `undefined`.
**Parameters:**
- `value`: `string | null | undefined`
- `defaultValue` (optional): `string` — Defaults to `"N/A"`.
**Example:**
```typescript
TextHelpers.handleNullDisplay("Hello") // "Hello"
TextHelpers.handleNullDisplay(null) // "N/A"
TextHelpers.handleNullDisplay(null, "—") // "—"
```
### `capitalizeText(text?)`
Capitalizes the first letter, lowercases the rest.
**Example:**
```typescript
TextHelpers.capitalizeText("hello world") // "Hello world"
TextHelpers.capitalizeText("HELLO") // "Hello"
TextHelpers.capitalizeText() // ""
```
### `enforceCharacterLimit({ text, characterLimit, onCharacterLimit })`
Truncates text to the limit and calls a callback when the limit is hit.
**Example:**
```typescript
TextHelpers.enforceCharacterLimit({
text: "This is a long text",
characterLimit: 10,
onCharacterLimit: () => console.log("Limit hit!"),
})
// "This is a" (and logs "Limit hit!")
```
### `isValidEmail(email)`
Validates an email address against RFC-compliant rules.
**Example:**
```typescript
TextHelpers.isValidEmail("user@example.com") // true
TextHelpers.isValidEmail("user@domain.co.uk") // true
TextHelpers.isValidEmail("invalid-email") // false
TextHelpers.isValidEmail("") // false
```
### `generateIDFromWord(text)`
Converts a phrase to a lowercase hyphenated ID.
**Example:**
```typescript
TextHelpers.generateIDFromWord("My Awesome Feature") // "my-awesome-feature"
```
### `generateWordFromId(id, customList?)`
Converts a hyphenated ID back to a readable title. Supports a custom lookup map.
**Example:**
```typescript
TextHelpers.generateWordFromId("hello-world-test")
// "Hello World Test"
TextHelpers.generateWordFromId("api", { api: "Application Programming Interface" })
// "Application Programming Interface"
```
### `generateSlugFromWordsWithID(id, ...words)`
Generates a URL-safe slug combining words and an ID.
**Example:**
```typescript
TextHelpers.generateSlugFromWordsWithID("123", "Blog Post", "Tech")
// "blog-post-tech-123"
```
### `extractIDfromSlug(slug)`
Extracts the last segment of a hyphenated slug (the ID).
**Example:**
```typescript
TextHelpers.extractIDfromSlug("my-blog-post-42") // "42"
TextHelpers.extractIDfromSlug("") // throws Error
```
### `abbreviateNumber(number)`
Abbreviates large numbers with K / M / B suffixes.
**Example:**
```typescript
TextHelpers.abbreviateNumber(500) // "500"
TextHelpers.abbreviateNumber(1500) // "1.5K"
TextHelpers.abbreviateNumber(1500000) // "1.5M"
TextHelpers.abbreviateNumber(1500000000) // "1.5B"
TextHelpers.abbreviateNumber(null) // null
```
## ObjectHelpers
### `isPureObject(object)`
Returns `true` if the value is a plain object (not an array, Date, or function).
**Example:**
```typescript
ObjectHelpers.isPureObject({}) // true
ObjectHelpers.isPureObject([]) // false
ObjectHelpers.isPureObject(new Date()) // false
ObjectHelpers.isPureObject(() => {}) // false
```
### `parseCookie(str)`
Parses a `Cookie` header string into a key-value object.
**Example:**
```typescript
ObjectHelpers.parseCookie("name=John; age=30; city=New York")
// { name: "John", age: "30", city: "New York" }
```
### `filterObjectsByProperty(array, propertyName, propertyValue)`
Filters an array of objects by a specific property value.
**Example:**
```typescript
const users = [
{ id: 1, name: "John", role: "admin" },
{ id: 2, name: "Jane", role: "user" },
{ id: 3, name: "Bob", role: "admin" },
]
ObjectHelpers.filterObjectsByProperty(users, "role", "admin")
// [{ id: 1, ... }, { id: 3, ... }]
```
### `containsSubObject(mainObject, subObject)`
Returns `true` if the main object contains all the key-value pairs of the sub-object.
**Example:**
```typescript
const user = { id: 1, name: "John", age: 30, city: "New York" }
ObjectHelpers.containsSubObject(user, { name: "John", age: 30 }) // true
ObjectHelpers.containsSubObject(user, { name: "Jane" }) // false
```
### `findObjectBySubObject(array, subObject)`
Finds the first object in an array containing the specified sub-object. Returns `null` if not found.
**Example:**
```typescript
const users = [
{ id: 1, name: "John", city: "New York" },
{ id: 2, name: "Jane", city: "Boston" },
]
ObjectHelpers.findObjectBySubObject(users, { city: "Boston" })
// { id: 2, name: "Jane", city: "Boston" }
ObjectHelpers.findObjectBySubObject(users, { name: "Alice" })
// null
```
### `filterObjectsBySubObject(array, subObject)`
Filters an array of objects to those containing the specified sub-object.
**Example:**
```typescript
const users = [
{ id: 1, name: "John", age: 30 },
{ id: 2, name: "Jane", age: 25 },
{ id: 3, name: "Bob", age: 30 },
]
ObjectHelpers.filterObjectsBySubObject(users, { age: 30 })
// [{ id: 1, ... }, { id: 3, ... }]
```
### `objectPropHasValue({ object, propName, value })`
Checks if a specific property on an object equals a given value.
**Example:**
```typescript
const user = { id: 1, name: "John", age: 30 }
ObjectHelpers.objectPropHasValue({ object: user, propName: "name", value: "John" }) // true
ObjectHelpers.objectPropHasValue({ object: user, propName: "age", value: 25 }) // false
```
### `findEntry(array, predicate)`
Returns the first array entry satisfying the predicate, or `null`.
**Example:**
```typescript
ObjectHelpers.findEntry([1, 2, 3, 4], (n) => n % 2 === 0) // 2
ObjectHelpers.findEntry([1, 2, 3], (n) => n > 10) // null
```
### `convertArrayToMap(arrayData, keyProp)`
Converts an array of objects into a keyed map using a specified property.
**Example:**
```typescript
const users = [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" },
]
ObjectHelpers.convertArrayToMap(users, "id")
// { "1": { id: 1, name: "John" }, "2": { id: 2, name: "Jane" } }
```
### `convertObjectKeysToKebabCase(obj)`
Converts all camelCase keys of an object to kebab-case. Returns `undefined` for `undefined` input.
**Example:**
```typescript
ObjectHelpers.convertObjectKeysToKebabCase({ firstName: "John", lastName: "Doe" })
// { "first-name": "John", "last-name": "Doe" }
ObjectHelpers.convertObjectKeysToKebabCase(undefined)
// undefined
```
## MapHelpers
### `getDistanceBetweenPoints(point1, point2)`
Calculates the distance between two `[lat, lng]` points using the [Haversine formula](https://en.wikipedia.org/wiki/Haversine_formula). Returns metres, or `null` for undefined input.
**Example:**
```typescript
// New York → Los Angeles
MapHelpers.getDistanceBetweenPoints([40.7128, -74.006], [34.0522, -118.2437])
// ~3,944,419 metres (~3,944 km)
MapHelpers.getDistanceBetweenPoints([40.7128, -74.006], undefined)
// null
```
### `compareLocations(location1, location2, precision?)`
Compares two `[lat, lng]` coordinates within a decimal precision. Throws if either is `undefined`.
**Parameters:**
- `precision` (optional): `number` — Decimal places. Defaults to `6`.
**Example:**
```typescript
MapHelpers.compareLocations([51.5074, -0.1278], [51.5074, -0.1278]) // true
MapHelpers.compareLocations([51.5074, -0.1278], [51.5074001, -0.127801]) // true (within 6 decimals)
MapHelpers.compareLocations([51.5074, -0.1278], [51.51, -0.13], 2) // false
```
### `getBearingToCoordinate({ startCoordinate, endCoordinate })`
Returns the compass bearing (0–360°) from start to end coordinate. Throws if either is `undefined`.
**Example:**
```typescript
// New York → Los Angeles
MapHelpers.getBearingToCoordinate({
startCoordinate: [40.7128, -74.006],
endCoordinate: [34.0522, -118.2437],
})
// ~277.5 (roughly west)
```
## GenericHelpers
### `delay(ms)`
Async sleep for the specified number of milliseconds.
**Example:**
```typescript
await GenericHelpers.delay(1000) // wait 1 second
```
### `getPreferredUriScheme(host)`
Returns `"http"` for local/private hosts, `"https"` for everything else.
**Example:**
```typescript
GenericHelpers.getPreferredUriScheme("api.example.com") // "https"
GenericHelpers.getPreferredUriScheme("localhost") // "http"
GenericHelpers.getPreferredUriScheme("192.168.1.1") // "http"
GenericHelpers.getPreferredUriScheme("10.0.0.1") // "http"
```
## FileHelpers
### `checkFileExtension(filePath, validExtensions)`
Returns `true` if the file has one of the allowed extensions.
**Example:**
```typescript
FileHelpers.checkFileExtension("report.pdf", ["pdf", "docx"]) // true
FileHelpers.checkFileExtension("data.geojson", ["geojson"]) // true
FileHelpers.checkFileExtension("photo.txt", ["jpg", "png"]) // false
```
### `formatFileSize(bytes)`
Formats a byte count into a human-readable size string.
**Example:**
```typescript
FileHelpers.formatFileSize(512) // "512 B"
FileHelpers.formatFileSize(1024) // "1.0 KB"
FileHelpers.formatFileSize(1024 * 1024 * 2) // "2.0 MB"
FileHelpers.formatFileSize(0) // "0 B"
FileHelpers.formatFileSize(null) // "0 B"
```
## Contributing
We welcome contributions! Please feel free to submit a Pull Request.
### Development Setup
```bash
git clone https://github.com/akadenia/AkadeniaHelpers.git
cd AkadeniaHelpers
pnpm install
pnpm run build
pnpm test
```
### Commit Message Guidelines
We follow [Conventional Commits](https://www.conventionalcommits.org/). Scope is required.
```text
type(scope): description
```
**Common scopes:** `date` · `text` · `object` · `map` · `generic` · `file` · `docs` · `deps` · `test` · `build` · `ci`
**Types:** `feat` · `fix` · `docs` · `style` · `refactor` · `test` · `chore`
## Requirements
- Node.js >= 20
- Zero runtime dependencies
## License
[MIT](LICENSE)