@cl3m/corekit

Utilities for
every project

A TypeScript-first general-purpose utility library covering strings, arrays, objects, and dates. Zero dependencies. Works everywhere.

TypeScript-first Zero dependencies ESM + CJS Browser + Node
$ npm install @cl3m/corekit
39
utility functions
4
core modules
0
dependencies
10
CLI commands
Quickstart
ESM
CJS
Subpath imports
import { strings, arrays, objects, dates } from '@cl3m/corekit';

strings.slugify('Hello World!');          // "hello-world"
strings.toCamelCase('hello-world');      // "helloWorld"

arrays.chunk([1,2,3,4,5], 2);            // [[1,2],[3,4],[5]]
arrays.groupBy(users, u => u.role);      // { admin: [...], user: [...] }

objects.pick({ a:1, b:2, c:3 }, ['a','c']);  // { a:1, c:3 }
objects.deepMerge(defaults, overrides);   // deep merged object

dates.timeAgo(new Date('2024-01-01'));    // "X months ago"
dates.formatDate(now, 'YYYY-MM-DD');     // "2026-03-05"
const { strings, arrays } = require('@cl3m/corekit');

strings.capitalize('hello');  // "Hello"
arrays.unique([1,2,2,3]);      // [1, 2, 3]
// Import only what you need — better tree-shaking
import { slugify, truncate } from '@cl3m/corekit/strings';
import { chunk, groupBy }   from '@cl3m/corekit/arrays';
import { pick, omit }       from '@cl3m/corekit/objects';
import { formatDate }        from '@cl3m/corekit/dates';
🌐

Browser Support

All core modules are browser-compatible. The CLI is Node.js only.

📦 CDN (script tag)
<script src="https://cdn.jsdelivr.net/npm/
  @cl3m/corekit/dist/browser.global.js"></script>
<script>
  corekit.strings.slugify('Hello!');
  corekit.arrays.range(1, 5);
</script>
⚡ ESM (modern browser)
<script type="module">
import { strings } from
  'cdn.jsdelivr.net/.../browser.esm.js';

strings.toCamelCase('hello-world');
</script>
🔧 Bundler (Vite / Webpack)
import { strings, dates }
  from '@cl3m/corekit/browser';
✅ Compatibility
// Targets ES2017+
// Chrome 67+, Firefox 60+
// Safari 11+, Edge 18+
// Node.js 18+
⌨️

CLI

Run utilities directly from your terminal. Install globally or use with npx.

# Install globally
npm install -g @cl3m/corekit

# Or run without installing
npx @cl3m/corekit --help
$ corekit slugify "Hello World!" hello-world
$ corekit camel "hello-world" helloWorld
$ corekit chunk 3 a b c d e f [["a","b","c"],["d","e","f"]]
$ corekit range 1 10 [1,2,3,4,5,6,7,8,9,10]
$ corekit format 2024-03-15 YYYY/MM/DD 2024/03/15
$ corekit timeago 2024-01-01 14 months ago
str

strings

Import: import { strings } from '@cl3m/corekit'  or  import { ... } from '@cl3m/corekit/strings'

capitalize(str: string) → string
Capitalize the first letter of a string.
Example
capitalize("hello world")  // → "Hello world"
capitalize("")             // → ""
toCamelCase(str: string) → string
Convert a string to camelCase. Handles hyphens, underscores, and spaces.
toCamelCase("hello-world")    // → "helloWorld"
toCamelCase("foo_bar_baz")    // → "fooBarBaz"
toCamelCase("hello world")    // → "helloWorld"
toKebabCase(str: string) → string
Convert a string to kebab-case.
toKebabCase("helloWorld")   // → "hello-world"
toKebabCase("foo_bar")      // → "foo-bar"
toSnakeCase(str: string) → string
Convert a string to snake_case.
toSnakeCase("helloWorld")   // → "hello_world"
toSnakeCase("hello-world")  // → "hello_world"
truncate(str: string, maxLength: number, ellipsis?: string) → string
Truncate a string to a max length, appending an ellipsis if needed. Default ellipsis is "...".
truncate("Hello, world!", 8)           // → "Hello..."
truncate("Hi", 8)                    // → "Hi"
truncate("Long text here", 7, "…")    // → "Long t…"
slugify(str: string) → string
Convert a string to a URL-safe slug. Normalizes unicode, removes special chars.
slugify("Hello World!")     // → "hello-world"
slugify("Héllo Wörld")     // → "hello-world"
slugify("  Foo  Bar  ")    // → "foo-bar"
countOccurrences(str: string, sub: string) → number
Count non-overlapping occurrences of a substring.
countOccurrences("banana", "an")    // → 2
countOccurrences("hello", "")      // → 0
isEmail(str: string) → boolean
Check if a string is a valid email address format.
isEmail("user@example.com")   // → true
isEmail("not-an-email")       // → false
reverseString(str: string) → string
Reverse a string. Unicode-safe (handles emoji and multi-byte chars).
reverseString("hello")    // → "olleh"
reverseString("racecar")  // → "racecar"
arr

arrays

Import: import { arrays } from '@cl3m/corekit'  or  import { ... } from '@cl3m/corekit/arrays'

unique<T>(arr: T[]) → T[]
Remove duplicate values from an array. Uses Set internally.
unique([1, 2, 2, 3, 3])              // → [1, 2, 3]
unique(['a', 'b', 'a', 'c'])         // → ["a", "b", "c"]
chunk<T>(arr: T[], size: number) → T[][]
Split an array into chunks of a given size. Last chunk may be smaller.
chunk([1,2,3,4,5], 2)    // → [[1,2],[3,4],[5]]
chunk([1,2,3], 3)         // → [[1,2,3]]
flatten<T>(arr: (T | T[])[], deep?: boolean) → T[]
Flatten a nested array by one level, or deeply if deep=true.
flatten([[1,2],[3,[4]]])        // → [1, 2, 3, [4]]
flatten([[1,2],[3,[4]]], true) // → [1, 2, 3, 4]
intersection<T>(a: T[], b: T[]) → T[]
Return elements present in both arrays.
intersection([1,2,3], [2,3,4])    // → [2, 3]
difference<T>(a: T[], b: T[]) → T[]
Return elements in a that are not in b.
difference([1,2,3], [2,3,4])    // → [1]
groupBy<T>(arr: T[], keyFn: (item: T) => string) → Record<string, T[]>
Group array elements into an object by a key derived from a callback function.
const users = [
  { name: 'Alice', role: 'admin' },
  { name: 'Bob',   role: 'user' },
  { name: 'Carol', role: 'admin' },
];

groupBy(users, u => u.role);
// → { admin: [Alice, Carol], user: [Bob] }
shuffle<T>(arr: T[]) → T[]
Shuffle an array using Fisher-Yates. Returns a new array, does not mutate.
shuffle([1, 2, 3, 4, 5])   // → [3, 1, 5, 2, 4] (random)
sum(arr: number[]) → number
Sum all numbers in an array.
sum([1, 2, 3, 4])   // → 10
sum([])             // → 0
minMax(arr: number[]) → {'{ min: number; max: number }'}
Get the minimum and maximum values of a numeric array in one pass.
minMax([3, 1, 4, 1, 5, 9])   // → { min: 1, max: 9 }
range(start: number, end: number, step?: number) → number[]
Generate an array of numbers from start to end (inclusive), with optional step.
range(1, 5)        // → [1, 2, 3, 4, 5]
range(0, 10, 2)   // → [0, 2, 4, 6, 8, 10]
obj

objects

Import: import { objects } from '@cl3m/corekit'  or  import { ... } from '@cl3m/corekit/objects'

deepClone<T>(obj: T) → T
Deep clone a plain object or array via JSON serialization. Does not handle functions, Dates, or circular refs.
const original = { a: { b: 1 } };
const clone = deepClone(original);
clone.a.b = 99;
original.a.b;  // → 1 (unchanged)
deepMerge<T>(target: T, source: Partial<T>) → T
Recursively merge two objects. Nested objects are merged; arrays are replaced.
deepMerge(
  { x: 1, y: { z: 2, w: 3 } },
  { y: { z: 99 } }
)
// → { x: 1, y: { z: 99, w: 3 } }
pick<T, K>(obj: T, keys: K[]) → Pick<T, K>
Create a new object with only the specified keys. Fully type-safe.
pick({ a:1, b:2, c:3 }, ['a', 'c'])   // → { a:1, c:3 }
omit<T, K>(obj: T, keys: K[]) → Omit<T, K>
Create a new object excluding the specified keys. Complement of pick.
omit({ a:1, b:2, c:3 }, ['b'])   // → { a:1, c:3 }
flattenObject(obj: Record<string, unknown>, prefix?: string) → Record<string, unknown>
Flatten a deeply nested object using dot-notation keys.
flattenObject({ a: { b: { c: 1 }, d: 2 } })
// → { 'a.b.c': 1, 'a.d': 2 }
invertObject(obj: Record<string, string>) → Record<string, string>
Swap all keys and values of an object.
invertObject({ a: '1', b: '2' })   // → { '1': 'a', '2': 'b' }
getByPath(obj: Record<string, unknown>, path: string) → unknown
Safely get a nested value using a dot-notation path. Returns undefined if path doesn't exist.
getByPath({ a: { b: 42 } }, 'a.b')     // → 42
getByPath({ a: {} }, 'a.b.c')         // → undefined
isEmpty(obj: Record<string, unknown>) → boolean
Check if an object has no own enumerable keys.
isEmpty({})          // → true
isEmpty({ a: 1 })   // → false
dt

dates

Import: import { dates } from '@cl3m/corekit'  or  import { ... } from '@cl3m/corekit/dates'

formatDate(date: Date, template: string) → string
Format a date using a template. Tokens: YYYY MM DD HH mm ss.
const d = new Date('2024-03-15T09:05:00');
formatDate(d, 'YYYY-MM-DD')      // → "2024-03-15"
formatDate(d, 'DD/MM/YYYY')      // → "15/03/2024"
formatDate(d, 'HH:mm:ss')        // → "09:05:00"
addToDate(date: Date, amount: number, unit: 'days' | 'months' | 'years') → Date
Add a duration to a date. Returns a new Date object without mutating the original.
const d = new Date('2024-01-15');
addToDate(d, 10, 'days')    // → 2024-01-25
addToDate(d, 2, 'months')  // → 2024-03-15
addToDate(d, 1, 'years')   // → 2025-01-15
diffDates(a: Date, b: Date, unit: 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days') → number
Get the difference between two dates in the specified unit. Can be negative.
const a = new Date('2024-01-01');
const b = new Date('2024-01-11');
diffDates(a, b, 'days')    // → 10
diffDates(a, b, 'hours')   // → 240
timeAgo(date: Date, now?: Date) → string
Return a human-readable relative time string. Handles both past and future dates.
timeAgo(new Date(Date.now() - 30000))    // → "just now"
timeAgo(new Date(Date.now() - 3600000))   // → "1 hour ago"
timeAgo(new Date('2024-01-01'))          // → "14 months ago"
timeAgo(new Date(Date.now() + 86400000))  // → "in 1 day"
isBetween(date: Date, start: Date, end: Date) → boolean
Check if a date falls within a range, inclusive of both endpoints.
isBetween(
  new Date('2024-06-15'),
  new Date('2024-01-01'),
  new Date('2024-12-31')
)  // → true
isSameDay(a: Date, b: Date) → boolean
Check if two dates fall on the same calendar day, regardless of time.
isSameDay(new Date('2024-03-15'), new Date('2024-03-15'))  // → true
isSameDay(new Date('2024-03-15'), new Date('2024-03-16'))  // → false
startOf(date: Date, unit: 'day' | 'month' | 'year') → Date
Get the start of a day, month, or year for a given date.
const d = new Date('2024-03-15T14:30:00');
startOf(d, 'day')    // → 2024-03-15 00:00:00
startOf(d, 'month')  // → 2024-03-01 00:00:00
startOf(d, 'year')   // → 2024-01-01 00:00:00
isValidDate(val: unknown) → val is Date
Type guard that checks if a value is a valid, non-NaN Date object.
isValidDate(new Date())             // → true
isValidDate(new Date('invalid'))    // → false
isValidDate('2024-01-01')          // → false