npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

umt

v5.1.0

Published

UMT Main Package is written in TypeScript and is a collection of useful functions for various tasks.

Readme

UMT Main Package

UMT Main Package is written in TypeScript and is a collection of useful functions for various tasks.

Install

npm install umt

# or

yarn add umt

# or

pnpm add umt

# or

bun add umt

v5 is ESM-only. Use import; require("umt") is not supported. Runtime matrix and migration notes: COMPATIBILITY.md.

import { isBetween, addBusinessDays, fromUnix } from "umt";
// or a subpath:
import { weekOfYear } from "umt/Date";

Date helpers

Local-time calendar helpers. Week boundaries are Sunday-start (JavaScript Date#getDay() 0). There are no UTC variants.

| Function | Behavior | | --- | --- | | isBetween(date, start, end, unit?, inclusivity?) | Default inclusivity is "()" (exclusive both ends, matching dayjs). Ranges are not swapped: if start is after end, the result is false. Omit unit for millisecond timestamps; with a unit, all three dates are truncated via startOf first. | | isSame(left, right, unit?) | Same truncation rules as isBetween. Omit unit for exact getTime() equality. | | addBusinessDays(date, amount, holidays?) / subBusinessDays | Walks calendar days until amount weekdays (minus optional holidays compared with isSameDay) have been counted. The start date is not counted: Friday + 1 is Monday, Saturday + 1 is Monday. 0 returns a clone and does not snap to a business day. Does not mutate the input. | | getQuarter(date) | Local month → 1–4 (Jan–Mar = 1), matching startOf(..., "quarter"). | | weekOfYear(date) | Sunday-start week index. Week 1 contains January 1 of that local year. Uses day-count rounding so DST does not shift the week number. Not ISO-8601 (Monday-start) week numbering. | | fromUnix(value, unit?) / toUnix(date, unit?) | Default unit is "s". toUnix(..., "s") is Math.floor(date.getTime() / 1000). | | format(date, formatString?) | Token formatter on local Date fields. Default pattern is "YYYY-MM-DDTHH:mm:ssZ". [text] is copied as-is. Z / ZZ use date's timezone offset. Throws TypeError("Invalid Date in format") if date is not a Date. |

DateInclusivity is "()" | "[]" | "[)" | "(]". UnixTimeUnit is "s" | "ms". DateBoundaryUnit is second | minute | hour | day | week | month | quarter | year.

import {
  addBusinessDays,
  format,
  fromUnix,
  getQuarter,
  isBetween,
  toUnix,
  weekOfYear,
} from "umt/Date";

const start = new Date(2025, 3, 10);
const mid = new Date(2025, 3, 15);
const end = new Date(2025, 3, 20);

isBetween(mid, start, end); // true
isBetween(start, start, end); // false (exclusive default)
isBetween(start, start, end, undefined, "[]"); // true

addBusinessDays(new Date(2025, 3, 18), 1); // 2025-04-21 (Monday)
getQuarter(new Date(2025, 3, 15)); // 2
weekOfYear(new Date(2025, 0, 1)); // 1
weekOfYear(new Date(2025, 0, 5)); // 2 (Sunday)

fromUnix(0).getTime(); // 0
toUnix(new Date(1_700_000_000_999)); // 1700000000

format(new Date(2023, 5, 10, 15, 30, 45), "YYYY-MM-DD"); // "2023-06-10"
format(new Date(2023, 5, 10, 15, 30, 45), "[Year:] YYYY"); // "Year: 2023"

Python and Rust ports of these helpers live in package/umt_python and package/umt_rust. Rust treats DateTime<Utc> calendar fields as wall-clock values except fromUnix / toUnix, which use real epoch timestamps. isSame exists in TypeScript only. Date format is not ported to Python. Rust umt_format takes an explicit timezone_offset_minutes (no default pattern; use umt_format_iso for the ISO-like default). Go FormatDate has the same tokens except it has no Z / ZZ. Wasm skips umt_format (DateTime<Utc>).

IP helpers

IPv4 dotted-decimal only (no IPv6). Numeric results are unsigned 32-bit values. getNetworkAddress returns a number, not a dotted string — pass it through longToIp.

Input validation is the caller's responsibility. These functions do not throw on malformed strings (see COMPATIBILITY.md). Python and Rust ports do validate.

| Function | Behavior | | --- | --- | | ipToLong(ip) / longToIp(long) | Pack or unpack four octets. Leading zeros in an octet are accepted ("192.168.01.1" equals "192.168.1.1"). | | cidrToLong(cidr) / cidrToSubnetMask(cidr) | Prefix length 0–32 to a mask number / dotted mask. CIDR 0 is 0 ("0.0.0.0"). | | subnetMaskToCidr(mask) | Counts set bits. Does not require a contiguous mask: "255.0.255.0" returns 16. | | isInRange(ip, network, cidr) | (ip & mask) === (network & mask). CIDR 0 matches every IPv4 address. | | isPrivateIp(ip) | RFC 1918 only: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16. Loopback (127.0.0.1) and link-local (169.254.0.0/16) are not private. | | getIpClass(ip) | Classful first-octet lookup (A–E). 0.0.0.0 and malformed input return "". | | getNetworkAddress(ip, mask) | ipToLong(ip) & cidrToLong(subnetMaskToCidr(mask)) as an unsigned 32-bit number. | | ipToBinaryString(ip) | 32-character 0/1 string, eight bits per octet. |

import {
  cidrToSubnetMask,
  getNetworkAddress,
  ipToLong,
  isInRange,
  isPrivateIp,
  longToIp,
} from "umt/IP";

ipToLong("192.168.1.1"); // 3232235777
longToIp(3232235777); // "192.168.1.1"
cidrToSubnetMask(24); // "255.255.255.0"
isInRange("192.168.1.2", "192.168.1.0", 24); // true
isPrivateIp("10.0.0.1"); // true
isPrivateIp("127.0.0.1"); // false
longToIp(getNetworkAddress("192.168.1.1", "255.255.255.0")); // "192.168.1.0"

Python and Rust ports live in package/umt_python and package/umt_rust. Those ports raise / return Err on malformed input and reject non-contiguous subnet masks. They are not exposed through umt-plugin-wasm: Rust IP functions are not named umt_*, so wasm codegen ignores them.

Validate and Standard Schema

Validator factories in umt/Validate (string(), number(), object(), arrayOf(), union(), …) implement Standard Schema V1. Each factory return value has a ~standard property:

| Field | Value | | --- | --- | | version | 1 | | vendor | "umt" (STANDARD_SCHEMA_VENDOR) | | validate(value) | Synchronous. On success { value } is the original input (validators do not transform). On failure { issues: [{ message }] } with a single issue. |

attachStandard() is how factories advertise the spec. It does not set ~standard.types. Consume validators through ~standard.validate, @hono/standard-validator's sValidator, or any other Standard Schema V1 host (Zod / Valibot schemas are interchangeable with UMT on that interface).

import { number, object, string } from "umt/Validate";

const user = object({ name: string(), age: number() });
user["~standard"].vendor; // "umt"

const ok = user["~standard"].validate({ name: "Ada", age: 1 });
// { value: { name: "Ada", age: 1 } }

const ng = user["~standard"].validate({ name: "Ada" });
// { issues: [{ message: ... }] }

UMT validators never return a Promise from ~standard.validate.

Decorator

Class-field validation in umt/Decorator. Rules live on the prototype chain (validateInstance includes inherited fields). @Validatable wraps the constructor and throws after super(...), so it sees initialized class fields.

| Decorator | Behavior | | --- | --- | | @IsString / @IsArray / @IsBoolean | Type checks. @IsNumber rejects numeric strings ("1"). | | @Min(n) / @Max(n) | Inclusive numeric bounds. Non-numbers fail. | | @LengthBetween(min, max) | Inclusive length on strings and arrays. | | @Optional | Skip other rules when the value is undefined. | | @Nullable | Skip other rules when the value is null. | | @Schema(schema) | Any Standard Schema V1 validator (UMT, Zod, Valibot). Async validate results are treated as failure. | | @Validatable | Throws Error joining all messages with "; " if any field fails. |

validateInstance(instance) returns a Result: success carries the instance; error carries { path, message }[].

import {
  IsNumber,
  IsString,
  Optional,
  Schema,
  Validatable,
  validateInstance,
} from "umt/Decorator";
import { number } from "umt/Validate";

class Profile {
  @IsString name = "alice";
  @Optional
  @IsNumber
  age?: number;
}

validateInstance(new Profile()).type; // "success"

@Validatable
class Product {
  @Schema(number()) price = 100;
}
new Product(); // succeeds; throws `Error` if `price` is not a number

String helpers

Unicode-aware string utilities in umt/String. Python, Rust, and Go ports exist (strip_ansi / umt_strip_ansi / StripAnsi, and the same mapping for tags and words).

| Function | Behavior | | --- | --- | | stripAnsi(string) | Removes CSI sequences (colors, cursor movement, including C1 U+009B) and OSC sequences (BEL or ST terminated). Incomplete CSI with no final byte is left unchanged. Unlike sanitizeString, other non-printables stay. | | stripTags(string) | Deletes HTML/XML tags (<[^<>]*>), repeating until stable so "<sc<script>ript>" becomes "". Self-closing tags are removed without inserting a separator ("line1<br/>line2" → "line1line2"). | | words(string, pattern?) | Default: insert spaces on camelCase / acronym boundaries, then split on non-letter/number separators. CJK and other letters are kept. If pattern is passed, returns string.match(pattern) or []. | | normalizeWhitespace(string) | Collapses Unicode \s+ to a single space and trims. Unlike deleteSpaces, words stay separated. All-whitespace input → "". | | unescapeHtml(string) | Named entities (&amp; &lt; &gt; &quot; &#39; &#x27; &#x2F; &#x60; &#x3D;) plus decimal / hex numeric references (&#65;, &#x41;). &#X41; (uppercase X) is left unchanged. Dangerous code points are not decoded (NULL, C0 except TAB/LF/CR, DEL, C1, surrogates, >0x10FFFF). Python / Rust / Go do not apply those extra filters. | | camelCase(string) | Replaces non-alphanumeric runs, then lowercases only the first character. Does not split acronyms: "HELLO" → "hELLO", "XMLHttpRequest" → "xMLHttpRequest". | | kebabCase(string) | Inserts dashes on aB / ABc boundaries, replaces spaces / underscores / other non-alphanumerics, lowercases. Splits acronyms: "XMLHttpRequest" → "xml-http-request". |

import { stripAnsi, stripTags, words } from "umt/String";

stripAnsi("\u001B[31mred\u001B[0m"); // "red"
stripTags("<p>Hello <b>World</b></p>"); // "Hello World"
stripTags("<sc<script>ript>"); // ""
words("XMLHttpRequest"); // ["XML", "Http", "Request"]
words("foo-bar_baz"); // ["foo", "bar", "baz"]
words("a1 b2 c3", /[a-z]\d/g); // ["a1", "b2", "c3"]
normalizeWhitespace("  hello   world \t\n foo "); // "hello world foo"
unescapeHtml("Tom &amp; Jerry"); // "Tom & Jerry"
unescapeHtml("&#0;"); // "&#0;" (NULL left unchanged)
camelCase("hello-world"); // "helloWorld"
camelCase("HELLO"); // "hELLO"
kebabCase("XMLHttpRequest"); // "xml-http-request"

Go splits the custom-pattern case into Words vs WordsWithPattern.

Color and URL helpers

hexaToRgba (umt/Color) and isAbsoluteUrl (umt/URL). Python, Rust, and Go ports exist.

| Function | Behavior | | --- | --- | | hexaToRgba(hex) | # plus 3, 6, or 8 hex digits → { r, g, b, a }. r/g/b are 0–255; a is 0–1 rounded to 2 decimals (#FF000080 → 0.5). TypeScript does not validate; malformed input can yield NaN. Python / Rust / Go require the # + hex pattern and error otherwise. | | isAbsoluteUrl(url) | RFC 3986 scheme check: letter, then letters / digits / + / . / -, then :. mailto: and tel: are absolute. Protocol-relative ("//example.com"), relative paths, and schemes starting with a digit are not. |

import { hexaToRgba } from "umt/Color";
import { isAbsoluteUrl } from "umt/URL";

hexaToRgba("#FF0000"); // { r: 255, g: 0, b: 0, a: 1 }
hexaToRgba("#F00"); // { r: 255, g: 0, b: 0, a: 1 }
hexaToRgba("#FF000080"); // { r: 255, g: 0, b: 0, a: 0.5 }

isAbsoluteUrl("https://example.com"); // true
isAbsoluteUrl("mailto:user@host"); // true
isAbsoluteUrl("/path/to/page"); // false
isAbsoluteUrl("//example.com"); // false

Wasm codegen skips umt_hexa_to_rgba (custom Result) and generates isAbsoluteUrl / normalizeWhitespace / unescapeHtml / camelCase.

Array, Async, and Error helpers

These TypeScript helpers are not ported to Python, Rust, or Go yet.

| Function | Behavior | | --- | --- | | countBy(array, iteratee) | Counts elements by iteratee key (string | number). Empty input → {}. Iteratee receives (value, index, array). | | partition(array, predicate) | [pass, fail] in original order. Does not mutate the input. Predicate receives (value, index, array). | | sliding(array, size, step?) | Fixed-size windows. Default step is 1. Incomplete trailing windows are omitted. size larger than length → []. Does not mutate the input. | | mapSeries(items, fn) | Awaits each mapper before starting the next (never overlapping). Returns results in input order. Rejects if any task rejects; it does not swallow errors. | | safeExecuteAsync(callback) | try/await/catch into Result: { type: "success", value } or { type: "error", error }. Accepts a sync return or a Promise. Sync throws and rejected promises both become type: "error". Never throws. |

import { countBy, partition, sliding } from "umt/Array";
import { mapSeries } from "umt/Async";
import { safeExecuteAsync } from "umt/Error";

countBy(["one", "two", "three"], (s) => s.length); // { 3: 2, 5: 1 }
partition([1, 2, 3, 4], (n) => n % 2 === 0); // [[2, 4], [1, 3]]
sliding([1, 2, 3, 4, 5], 3); // [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
sliding([1, 2, 3, 4, 5], 3, 2); // [[1, 2, 3], [3, 4, 5]]

await mapSeries([1, 2, 3], async (n) => n * 2); // [2, 4, 6]
await safeExecuteAsync(async () => 42); // { type: "success", value: 42 }

Function List

Advance

Array

Async

Color

Consts

Crypto

DataStructure

Date

Decorator

Error

Function

IP

Iterator

Map

Math

Number

Object

Predicate

Random

Simple

String

Time

Tool

UA

Unit

URL

Validate