umt
v5.1.0
Published
UMT Main Package is written in TypeScript and is a collection of useful functions for various tasks.
Maintainers
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 umtv5 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 numberString 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 (& < > " ' ' / ` =) plus decimal / hex numeric references (A, A). A (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 & Jerry"); // "Tom & Jerry"
unescapeHtml("�"); // "�" (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"); // falseWasm 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
- arraysJoin
- binarySearch
- checkFlagAlignment
- chunk
- compact
- countBy
- drop
- dualPivotQuickSort
- first
- generateNumberArray
- getArraysCommon
- getArraysDiff
- groupBy
- insertionSort
- mergeSort
- partition
- pop
- quickSort
- randomSelect
- range
- shuffle
- shuffle2DArray
- sliding
- sum
- timSort
- ultraNumberSort
- uniqBy
- unique
- zip
- zipLongest
Async
- debounceAsync
- DebouncedAsyncFunction
- defer
- Deferred
- mapSeries
- parallel
- pSettled
- retry
- RetryOptions
- SettledResult
- sleep
- throttleAsync
- ThrottledAsyncFunction
- timeout
- waitFor
- WaitForOptions
Color
Consts
- HttpClientErrorStatus
- HttpInformationalStatus
- HttpRedirectionStatus
- HttpServerErrorStatus
- HttpStatus
- HttpSuccessStatus
- OneDayMs
- OneHourMs
- OneMinuteMs
- OneMonthMs
- OneMonthMs28
- OneMonthMs29
- OneMonthMs31
- OneSecondMs
- OneWeekMs
- OneYearMs
- OneYearMs366
Crypto
DataStructure
Date
- addBusinessDays
- addDuration
- birthday
- DateBoundaryUnit
- DateInclusivity
- dateRange
- DayList
- dayOfWeek
- diff
- DurationUnit
- endOf
- format
- formatRelative
- fromUnix
- getDay
- getQuarter
- getTimezoneOffsetString
- isBetween
- isBusinessDay
- isLeapYear
- isSame
- isSameDay
- isWeekend
- newDateInt
- newDateString
- now
- startOf
- subBusinessDays
- subDuration
- toUnix
- UnixTimeUnit
- weekOfYear
Decorator
- addFieldRule
- collectRules
- FieldMeta
- FieldRule
- getFieldMeta
- IsArray
- IsBoolean
- IsNumber
- IsString
- LengthBetween
- markNullable
- markOptional
- Max
- Min
- Nullable
- Optional
- Schema
- storage
- Validatable
- validateField
- validateInstance
- ValidationIssue
Error
- errorFunction
- ErrorType
- flatMapResult
- mapResult
- matchResult
- Result
- safeExecute
- safeExecuteAsync
- successFunction
- SuccessType
Function
- curry
- debounce
- DebouncedFunction
- DebounceOptions
- memoize
- MemoizedFunction
- MemoizeOptions
- once
- throttle
- ThrottledFunction
IP
- cidrToLong
- cidrToSubnetMask
- getIpClass
- getNetworkAddress
- ipToBinaryString
- ipToLong
- isInRange
- isPrivateIp
- longToIp
- subnetMaskToCidr
Iterator
Map
Math
- addition
- average
- bitwise
- calculator
- calculatorCore
- calculatorInitialization
- clamp
- convertCurrency
- correlationCoefficient
- degToRad
- deviationValue
- division
- factorial
- factorize
- flexibleNumberConversion
- gcd
- getDecimalLength
- inRange
- lcm
- linearCongruentialGenerator
- literalExpression
- mathConverter
- mathSeparator
- max
- median
- min
- mode
- multiples
- multiplication
- nCr
- nHr
- nPr
- percentile
- primeFactorization
- quotient
- radToDeg
- random
- reduce
- repeatedTrial
- roundOf
- solveEquation
- standardDeviation
- subtract
- sumPrecise
- toBaseN
- toCelsius
- toKelvin
- uuidv7
- valueSwap
- xoshiro256
Number
Object
- deepClone
- flattenObject
- get
- getObjectsCommon
- getObjectsDiff
- has
- invert
- isEmpty
- isPlainObject
- Iteratee
- IterateeFunction
- keyBy
- mapKeys
- mapValues
- merge
- mergeDeep
- omit
- omitBy
- pathSegments
- pick
- pickBy
- pickDeep
- PropertyName
- removePrototype
- removePrototypeDeep
- removePrototypeMap
- removePrototypeMapDeep
- set
- unflattenObject
Predicate
Random
Simple
String
- camelCase
- capitalize
- capitalizeWord
- constantCase
- countOccurrences
- deburr
- dedent
- deleteSpaces
- ensurePrefix
- ensureSuffix
- escapeHtml
- formatString
- fromBase64
- fuzzySearch
- hasNoLetters
- kebabCase
- levenshteinDistance
- mask
- MaskOptions
- normalizeWhitespace
- padEnd
- padStart
- pascalCase
- randomString
- randomStringInitialization
- removePrefix
- removeSuffix
- reverseString
- sanitizeString
- slugify
- snakeCase
- splitByLength
- stringSimilarity
- stripAnsi
- stripTags
- swapCase
- titleCase
- toBase64
- toFullWidth
- toHalfWidth
- trimCharacters
- trimEndCharacters
- trimStartCharacters
- truncate
- uncapitalize
- unescapeHtml
- wordCount
- words
Time
Tool
UA
Unit
URL
Validate
- _Types
- _Types2
- _Types3
- _ValidateType
- _ValidateType2
- _ValidateType3
- any
- AnyReturnType
- arrayOf
- ArrayOfExtractValidatedType
- attachStandard
- bigint
- BigIntReturnType
- boolean
- BuildTemplateLiteral
- Constructor
- date
- double
- even
- exactLength
- ExtractInput
- ExtractOutput
- ExtractValidatorTag
- file
- func
- FunctionAnyValidator
- FunctionExtractValidatedType
- FunctionReturnType
- FunctionSchema
- FunctionValidator
- InferFunction
- InferInputs
- InferObject
- InferOutput
- instanceOf
- intersection
- IntersectionExtractValidatedType
- IntersectValidatedTypes
- isArray
- isBrowser
- isBun
- isDeepEqual
- IsDeepEqualOptions
- isDictionaryObject
- isDouble
- isEqual
- isNode
- isNodeWebkit
- isNotEmpty
- isNumber
- isPerfectSquare
- isPrimeNumber
- isString
- isValueNaN
- LiteralBrand
- map
- MapExtractValidatedType
- maxLength
- maxValue
- minLength
- minValue
- never
- NeverReturnType
- nullable
- NullReturn
- number
- numberString
- object
- ObjectShape
- ObjectShapeProperties
- ObjectValidator
- odd
- omitKeys
- oneOf
- OneOfReturnType
- optional
- OptionalKeys
- OptionalValidator
- parseEmail
- ParseEmailLevel
- ParseEmailOptions
- partial
- PartialShape
- PartToTemplate
- pickKeys
- prime
- regexMatch
- required
- RequiredShape
- SchemaToInterface
- SetExtractValidatedType
- setOf
- STANDARD_SCHEMA_VENDOR
- StandardSchemaV1
- StandardSchemaV1FailureResult
- StandardSchemaV1InferInput
- StandardSchemaV1InferOutput
- StandardSchemaV1Issue
- StandardSchemaV1PathSegment
- StandardSchemaV1Properties
- StandardSchemaV1Result
- StandardSchemaV1SuccessResult
- StandardSchemaV1Types
- string
- TagToTemplate
- templateLiteral
- TemplateLiteralAnyValidator
- TemplateLiteralPart
- TemplateLiteralReturnType
- Types
- UmtValidatorResult
- UndefinedReturn
- union
- UnionExtractValidatedType
- unknown
- UnknownReturnType
- UnwrapOptional
- uuid
- ValidateCoreReturnType
- validateEmail
- ValidateFunctionType
- ValidateReturnType
- ValidateType
