ultan
v2.1.0
Published
High-performance utility suite for modern JavaScript. Optimized for AI orchestration, HealthTech (FHIR) interoperability, and secure cloud system monitoring.
Maintainers
Readme
Why use Ultan?
Ultan is a utility library that bridges traditional JavaScript development with modern AI, healthcare (FHIR/HL7), and cloud-native architectures. Built for Fortune 500 environments, it provides enterprise-grade functions for string manipulation, array operations, object handling, healthcare data processing, AI prompt management, PHI masking, reactive state management, functional programming patterns, number utilities, and a full date/time toolkit.
Whether you're building HIPAA-compliant healthcare applications, AI-powered workflows, or mission-critical enterprise systems, Ultan delivers production-ready utilities that eliminate boilerplate and accelerate development cycles.
Table of Contents
- Installation
- Quick Start
- Healthcare (FHIR/HL7)
- AI Integration
- String Manipulation
- String Expansion
- Object Utilities
- Object Expansion
- Array Utilities
- Array Expansion
- Function Utilities
- Function Expansion
- Number Utilities
- Number Expansion
- DateTime Utilities
- HTTP/Network
- Miscellaneous
- Regular Expressions
- Constants
- License
Installation
npm install ultanQuick Start
const {
stringFormat,
isValidFhir,
getFhirName,
getAcuityScore,
fillPrompt,
parseAiJson,
maskPHI,
debounce,
generateUUID
} = require('ultan');
const patient = {
resourceType: 'Patient',
id: '12345',
name: [{ use: 'official', given: ['John'], family: 'Doe' }]
};
console.log(isValidFhir(patient));
console.log(getFhirName(patient));Healthcare (FHIR/HL7)
isValidFhir(resource)
Validates if an object is a valid FHIR resource by checking for resourceType and id properties.
isValidFhir({ resourceType: 'Patient', id: '123' }); // true
isValidFhir({ name: 'John' }); // falsegetFhirName(patient)
Extracts the official name from a FHIR Patient resource, falling back to the first name available.
const name = getFhirName(patientResource); // 'John Q. Doe'
getFhirName({}); // 'Unknown'getAcuityScore({ hr, rr, temp, sbp })
Calculates clinical acuity score based on vital signs (heart rate, respiratory rate, temperature, systolic blood pressure).
const score = getAcuityScore({ hr: 120, rr: 26, temp: 98.6, sbp: 85 });maskPHI(string)
Masks Protected Health Information including SSN, phone numbers, and email addresses.
const masked = maskPHI('Contact: [email protected] or 555-123-4567');
// 'Contact: [EMAIL_MASKED] or [PHONE_MASKED]'isZombie(lastHeartbeat, limit = 300000)
Detects stagnant sessions or zombie connections based on heartbeat timestamp.
const stale = isZombie('2024-01-01T10:00:00Z', 300000); // true
isZombie(new Date()); // falseAI Integration
fillPrompt(template, variables)
Replaces {{variable}} placeholders in prompt templates with actual values.
const prompt = fillPrompt('Analyze {{dataType}} for patient {{id}}', {
dataType: 'vitals',
id: '12345'
});
// 'Analyze vitals for patient 12345'parseAiJson(string)
Parses JSON from AI responses, handling markdown code fences and malformed output.
const data = parseAiJson('```json\n{"key": "value"}\n```'); // { key: 'value' }
parseAiJson('invalid'); // nullcreateSignal(initialValue)
Creates a reactive signal with pub/sub pattern for state management.
const counter = createSignal(0);
counter.subscribe(val => console.log('New value:', val));
counter.set(5);
const current = counter.get(); // 5String Manipulation
stringFormat(format, ...args)
Replaces {0}, {1}, etc. placeholders with arguments.
stringFormat('Hello, {0}! Welcome to {1}.', 'Alice', 'Ultan');
// 'Hello, Alice! Welcome to Ultan.'toTitleCase(string)
Converts string to title case.
toTitleCase('hello world'); // 'Hello World'sanitizeString(string)
Escapes HTML special characters.
sanitizeString('<script>alert("xss")</script>');
// '<script>alert("xss")</script>'fromBase64(base64) / toBase64(string)
Base64 encoding and decoding with UTF-8 support.
const encoded = toBase64('Hello World');
const decoded = fromBase64(encoded); // 'Hello World'countOccurrences(string, substring)
Counts substring occurrences.
countOccurrences('hello world hello', 'hello'); // 2String Expansion
camelCase(string)
Converts a string (space-separated, kebab, snake, or PascalCase) to camelCase.
camelCase('the quick brown fox'); // 'theQuickBrownFox'
camelCase('the-quick-brown-fox'); // 'theQuickBrownFox'
camelCase('the_quick_brown_fox'); // 'theQuickBrownFox'kebabCase(string)
Converts a string to kebab-case.
kebabCase('the quick brown fox'); // 'the-quick-brown-fox'
kebabCase('theQuickBrownFox'); // 'the-quick-brown-fox'snakeCase(string)
Converts a string to snake_case.
snakeCase('the quick brown fox'); // 'the_quick_brown_fox'
snakeCase('theQuickBrownFox'); // 'the_quick_brown_fox'pascalCase(string)
Converts a string to PascalCase.
pascalCase('the quick brown fox'); // 'TheQuickBrownFox'
pascalCase('the-quick-brown-fox'); // 'TheQuickBrownFox'truncate(string, length, suffix = '...')
Truncates a string to a maximum length, appending a suffix if truncated. Suffix defaults to '...'.
truncate('hello world', 8); // 'hello...'
truncate('hello world', 8, '!'); // 'hello w!'
truncate('hi', 10); // 'hi'capitalize(string)
Uppercases the first character of a string, leaving the rest unchanged.
capitalize('hello world'); // 'Hello world'
capitalize('HELLO'); // 'HELLO'Object Utilities
isEmpty(value)
Checks if object, array, or string is empty. Returns true for null and undefined.
isEmpty({}); // true
isEmpty([1]); // false
isEmpty(''); // true
isEmpty(null); // truedeepClone(object)
Creates a deep copy using structuredClone with a JSON fallback.
const clone = deepClone({ nested: { data: [1, 2, 3] } });setNestedProperty(object, path, value)
Sets a nested property using dot notation, creating intermediate objects as needed.
const obj = {};
setNestedProperty(obj, 'user.profile.name', 'John');
// obj === { user: { profile: { name: 'John' } } }getNestedProperty(object, path)
Retrieves a nested property using dot notation. Returns null for missing paths.
getNestedProperty(obj, 'user.profile.name'); // 'John'objectToArray(object) / arrayToObject(array)
Converts between objects and key-value pair arrays.
objectToArray({ a: 1, b: 2 }); // [['a', 1], ['b', 2]]
arrayToObject([['a', 1], ['b', 2]]); // { a: 1, b: 2 }Object Expansion
pick(object, keys)
Returns a new object containing only the specified keys.
pick({ a: 1, b: 2, c: 3 }, ['a', 'c']); // { a: 1, c: 3 }omit(object, keys)
Returns a new object with the specified keys excluded.
omit({ a: 1, b: 2, c: 3 }, ['b']); // { a: 1, c: 3 }flipObject(object)
Swaps an object's keys and values.
flipObject({ a: 'x', b: 'y' }); // { x: 'a', y: 'b' }Array Utilities
mergeArrays(array1, array2)
Merges two arrays, removing duplicates.
mergeArrays([1, 2, 3], [3, 4, 5]); // [1, 2, 3, 4, 5]sumArray(array) / averageArray(array)
Calculates the sum or average of a numeric array.
sumArray([1, 2, 3, 4]); // 10
averageArray([10, 20, 30]); // 20arrayDifference(array1, array2)
Returns elements present in array1 but not in array2.
arrayDifference([1, 2, 3], [2, 3, 4]); // [1]removeFalsyValues(array)
Filters out all falsy values (false, 0, '', null, undefined, NaN).
removeFalsyValues([0, 1, false, 2, '', 3, null, undefined]); // [1, 2, 3]groupBy(array, key)
Groups an array of objects by a shared property.
groupBy([{ type: 'A', val: 1 }, { type: 'B', val: 2 }, { type: 'A', val: 3 }], 'type');
// { A: [{ type: 'A', val: 1 }, { type: 'A', val: 3 }], B: [{ type: 'B', val: 2 }] }Array Expansion
flatten(array, depth = Infinity)
Flattens a nested array to a specified depth. Defaults to fully flat.
flatten([[1, [2, 3]], [4]]); // [1, 2, 3, 4]
flatten([[1, [2, [3]]]], 1); // [1, [2, [3]]]partition(array, predicate)
Splits an array into two groups based on a predicate function. Returns [passing, failing].
const [evens, odds] = partition([1, 2, 3, 4, 5], n => n % 2 === 0);
// evens: [2, 4], odds: [1, 3, 5]range(start, end, step = 1)
Generates an array of numbers. When called with one argument, starts from 0.
range(5); // [0, 1, 2, 3, 4]
range(1, 5); // [1, 2, 3, 4]
range(0, 10, 3); // [0, 3, 6, 9]chunk(array, size)
Splits an array into chunks of the given size. The final chunk may be smaller.
chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
chunk([1, 2, 3], 3); // [[1, 2, 3]]intersect(array1, array2)
Returns elements present in both arrays.
intersect([1, 2, 3], [2, 3, 4]); // [2, 3]unique(array)
Removes duplicate values from an array.
unique([1, 2, 2, 3, 3, 3]); // [1, 2, 3]orderBy(array, key, order = 'asc')
Sorts an array of objects by a key (string property name or accessor function). Supports 'asc' and 'desc' order.
const data = [{ n: 3 }, { n: 1 }, { n: 2 }];
orderBy(data, 'n'); // [{ n: 1 }, { n: 2 }, { n: 3 }]
orderBy(data, 'n', 'desc'); // [{ n: 3 }, { n: 2 }, { n: 1 }]
orderBy(data, x => x.n); // function accessor also supportedFunction Utilities
debounce(function, delay = 300)
Delays function execution until after delay milliseconds have elapsed since the last invocation.
const debouncedSearch = debounce(searchFunction, 500);throttle(function, limit)
Ensures a function executes at most once per limit milliseconds.
const throttledScroll = throttle(handleScroll, 100);Function Expansion
once(fn)
Wraps a function so it executes only on the first call. Subsequent calls return the cached result.
const init = once(() => expensiveSetup());
init(); // runs expensiveSetup
init(); // returns cached result, does not re-runmemoize(fn, keyFn?)
Caches function results by argument signature. An optional keyFn can provide a custom cache key.
const expensiveFn = memoize(n => computeHeavy(n));
expensiveFn(5); // computed
expensiveFn(5); // returned from cache
// Custom key function
const memoized = memoize((a, b) => a + b, (a, b) => `${a}-${b}`);pipe(...fns)
Composes functions left to right, passing the output of each as input to the next.
const transform = pipe(
x => x + 1,
x => x * 2,
x => x - 3
);
transform(5); // 9compose(...fns)
Composes functions right to left (standard mathematical composition).
const transform = compose(
x => x - 3,
x => x * 2,
x => x + 1
);
transform(5); // 9Number Utilities
getRandomInRange(min, max)
Returns a random float in the given range (inclusive of min, exclusive of max).
getRandomInRange(1, 10); // e.g. 7.342...round(number, decimals = 2)
Rounds a number to the specified number of decimal places.
round(3.14159, 2); // 3.14
round(1.005, 2); // 1.01generateUUID()
Generates a RFC 4122-compliant UUID v4.
const id = generateUUID(); // 'f47ac10b-58cc-4372-a567-0e02b2c3d479'Number Expansion
clamp(min, val, max)
Constrains a value within an inclusive range.
clamp(1, 5, 10); // 5 (within range)
clamp(1, 0, 10); // 1 (below min, returns min)
clamp(1, 15, 10); // 10 (above max, returns max)isPrime(number)
Returns true if the number is a prime number.
isPrime(2); // true
isPrime(17); // true
isPrime(1); // false
isPrime(10); // falseDateTime Utilities
addTime(date, amount, unit)
Returns a new date with the specified amount of time added. Supports 'millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', and 'year'.
addTime(new Date(2026, 0, 1), 5, 'day'); // Jan 6, 2026
addTime(new Date(2026, 0, 15), 2, 'month'); // Mar 15, 2026
addTime(new Date(2026, 0, 1), 1, 'year'); // Jan 1, 2027subtractTime(date, amount, unit)
Returns a new date with the specified amount of time subtracted. Accepts the same units as addTime.
subtractTime(new Date(2026, 0, 10), 5, 'day'); // Jan 5, 2026startOf(date, unit)
Returns a new date set to the start of the given unit. Supports 'day', 'month', 'year', 'week', and 'hour'.
startOf(new Date(2026, 3, 15, 14, 30), 'day'); // Apr 15, 2026 00:00:00.000
startOf(new Date(2026, 3, 15), 'month'); // Apr 1, 2026 00:00:00.000endOf(date, unit)
Returns a new date set to the end of the given unit. Supports 'day', 'month', 'year', 'week', and 'hour'.
endOf(new Date(2026, 3, 15), 'day'); // Apr 15, 2026 23:59:59.999
endOf(new Date(2026, 3, 15), 'month'); // Apr 30, 2026 23:59:59.999isBefore(date1, date2)
Returns true if date1 is strictly before date2.
isBefore(new Date(2026, 0, 1), new Date(2026, 6, 1)); // trueisAfter(date1, date2)
Returns true if date1 is strictly after date2.
isAfter(new Date(2026, 6, 1), new Date(2026, 0, 1)); // trueisSameDay(date1, date2)
Returns true if both dates fall on the same calendar day regardless of time.
isSameDay(new Date(2026, 3, 15, 10), new Date(2026, 3, 15, 22)); // true
isSameDay(new Date(2026, 3, 15), new Date(2026, 3, 16)); // falsediffDates(date1, date2, unit = 'day')
Returns the difference between two dates in the specified unit. Supports 'day', 'month', and 'year'.
diffDates(new Date(2026, 0, 1), new Date(2026, 0, 11), 'day'); // 10
diffDates(new Date(2026, 0, 1), new Date(2026, 5, 1), 'month'); // 5isWeekend(date)
Returns true if the date falls on a Saturday or Sunday.
isWeekend(new Date(2026, 3, 11)); // true (Saturday)
isWeekend(new Date(2026, 3, 13)); // false (Monday)isLeapYear(year)
Returns true if the given year is a leap year.
isLeapYear(2024); // true
isLeapYear(2026); // false
isLeapYear(2000); // true
isLeapYear(1900); // falsedaysInMonth(year, month)
Returns the number of days in a given month. Month is 1-indexed (January = 1).
daysInMonth(2026, 2); // 28
daysInMonth(2024, 2); // 29 (leap year)
daysInMonth(2026, 1); // 31formatRelative(date)
Returns a human-readable relative time string such as '2 hours ago' or '3 days from now'.
formatRelative(new Date(Date.now() - 90000)); // '1 minute ago'
formatRelative(new Date(Date.now() - 7200000)); // '2 hours ago'
formatRelative(new Date(Date.now() + 86400000)); // '1 day from now'HTTP/Network
reqFlow(url, options = {})
Simplified fetch wrapper that throws on non-OK responses and parses the response body as JSON.
const data = await reqFlow('https://api.example.com/data', {
method: 'POST',
body: JSON.stringify({ key: 'value' })
});Miscellaneous
greet({ name, age })
Console logs a greeting. Parameters are destructured with defaults.
greet({ name: 'Alice', age: 30 }); // 'Hello, Alice! You are 30 years old.'
greet(); // 'Hello, User! You are unknown years old.'getType(value)
Returns a lowercase type string, correctly handling null, arrays, and other edge cases.
getType([]); // 'array'
getType({}); // 'object'
getType(null); // 'null'formatDate(date)
Formats a Date object as MM/DD/YYYY.
formatDate(new Date(2026, 0, 1)); // '01/01/2026'Regular Expressions
Pre-compiled regex patterns accessible via the regexes object:
regexes.email— Email address validationregexes.phone— International phone numbersregexes.url— HTTP/HTTPS URLs
const { regexes } = require('ultan');
regexes.email.test('[email protected]'); // true
regexes.url.test('https://vgs.studio'); // trueConstants
DaysOfWeek
Frozen object with full weekday names.
const { DaysOfWeek } = require('ultan');
console.log(DaysOfWeek.MONDAY); // 'Monday'
console.log(DaysOfWeek.SATURDAY); // 'Saturday'HttpStatus
Frozen object of common HTTP status codes.
const { HttpStatus } = require('ultan');
if (response.status === HttpStatus.NOT_FOUND) { }
if (response.status === HttpStatus.TOO_MANY_REQUESTS) { }
if (response.status === HttpStatus.SERVICE_UNAVAILABLE) { }License
MIT
