Skip to main content
jg-packages

Search

    Utilities

    jg-utilities

    Validations, formatters, secure random generators, pagination cursors, and collection, async, and environment helpers.

    v1.4.0UniversalESMMIT

    npm install jg-utilities

    Usage

    Validate input before using it:

    ts
    import { isBigIntStringValid, isEmailValid, isIntegerValid, isStringValid } from 'jg-utilities';
    
    isStringValid(name, 1, 100); // a non-blank string of 1 to 100 characters
    isIntegerValid(page, 1); // an integer of at least 1
    isEmailValid(email); // a valid address without a forbidden extension
    isBigIntStringValid(id, 1n); // a positive integer string that fits PostgreSQL's BIGINT

    Format values for people:

    ts
    import {
      escapeHtml,
      pluralize,
      prettifyDate,
      prettifyFileSize,
      prettifyNumber,
      toSlug,
    } from 'jg-utilities';
    
    prettifyNumber(1234567.891); // '1,234,567.89'
    prettifyNumber(-5, { prefix: '$' }); // '-$5'
    prettifyFileSize(1536); // '1.50 kB'
    prettifyDate(createdAt, 'date-medium'); // 'October 17, 2026'
    toSlug('Héllo, World! 2026'); // 'hello-world-2026'
    `${count} ${pluralize(count, 'file')}`; // '1 file', '3 files'
    escapeHtml(name); // safe to put into HTML, such as an email's body

    Send someone back where they were after signing in, only within the site and never back to the sign-in page:

    ts
    import { resolveSafeInternalPath } from 'jg-utilities';
    
    const returnTo = resolveSafeInternalPath(searchParams.get('returnTo'), ['/sign-in']) ?? '/';

    Keep secrets out of logs, and read the YouTube links people paste:

    ts
    import {
      parseYouTubeVideoId,
      redactSecrets,
      redactUrlQueryParams,
      toYouTubeEmbedUrl,
    } from 'jg-utilities';
    
    redactUrlQueryParams(request.url, ['token']); // the path alone when the query holds a token
    redactSecrets(logLine).text; // GitHub tokens, sk- keys, and private keys become [redacted]
    
    const videoId = parseYouTubeVideoId(pastedUrl); // the id, or null for anything but one video
    const embedUrl = videoId === null ? undefined : toYouTubeEmbedUrl(videoId);

    Generate secure random values, IDs, and timestamps:

    ts
    import { createTimestamp, generateRandomString, generateUuid } from 'jg-utilities';
    
    generateRandomString(16); // drawn with crypto.getRandomValues, fit for secrets
    generateUuid(7); // a time-ordered UUID
    createTimestamp(); // '2026-10-17T08:30:00.000Z'

    Work with UTC calendar dates, such as the days a report covers, and fit text into a byte budget, such as a push notification’s payload limit:

    ts
    import {
      generateUtcDateSequence,
      getTrailingUtcDateRange,
      toUtcDate,
      truncateToUtf8Bytes,
    } from 'jg-utilities';
    
    toUtcDate(createdAt); // '2026-10-17', the UTC day of an instant
    const range = getTrailingUtcDateRange(30); // the last 30 UTC days, today included
    generateUtcDateSequence(range); // one 'YYYY-MM-DD' per day, oldest first
    truncateToUtf8Bytes(body, 2048); // whole code points only, at most 2048 bytes in UTF-8

    Run side effects away from the code that triggers them with an in-process event bus:

    ts
    import { createEventBus } from 'jg-utilities';
    
    type IAppEvents = { userSignedUp: { userId: string } };
    
    const events = createEventBus<IAppEvents>({ onError: (error) => logger.error(error) });
    events.subscribe('userSignedUp', ({ userId }) => sendWelcomeEmail(userId));
    events.emit('userSignedUp', { userId }); // returns at once; each handler runs later, on its own

    Paginate with opaque cursors, and wait or retry with timing in seconds:

    ts
    import { decodeCursor, encodeCursor, retryAsyncFunction, waitUntil } from 'jg-utilities';
    
    const cursor = encodeCursor({ createdAt: lastRow.createdAt, id: lastRow.id });
    const continuation = decodeCursor(cursorFromClient); // throws INVALID_CURSOR for anything else
    
    await retryAsyncFunction(() => fetchData(), [3, 5]); // retries after 3, then 5 seconds
    await waitUntil(() => readStatus() === 'ready' || undefined, { timeoutSeconds: 30 });

    Give each list a cursor codec that validates its cursors and accepts them only for the filters they were made for, and keep a rate-limited API’s requests within its limits:

    ts
    import { createCursorCodec, createRequestCoordinator } from 'jg-utilities';
    
    const paymentCursors = createCursorCodec({ schema: PaymentCursorSchema }); // a Zod schema, say
    const after = paymentCursors.decode(request.query.cursor, { status }); // INVALID_CURSOR otherwise
    
    const github = createRequestCoordinator({ maxConcurrent: 4, maxQueued: 64 });
    const issues = await github.run(() => fetchIssues(), {
      caller: installationId,
      maxQueuedForCaller: 8,
    });
    github.deferUntil(retryAt); // queued requests wait out a Retry-After, without holding a slot

    Generated from TSDoc

    API reference

    Every export of [email protected], 125 in all, with its signature, its errors, and an example.

    Functions

    applyDefaults

    function

    Applies non-nullish overrides to a defaults object and returns a new shallow object.

    Signature
    applyDefaults<T extends Record<string, unknown>>(
      defaults: T,
      overrides: { [Key in string | number | symbol]?: T[Key] | null },
    ): T

    Parameters

    defaultsT

    The object containing the default properties and values.

    overrides{ [Key in string | number | symbol]?: T[Key] | null }

    The values that should replace matching defaults when they are not nullish.

    Returns

    T

    A new object containing the default keys and resolved values.

    Example
    import { applyDefaults } from 'jg-utilities';
    
    applyDefaults({ retries: 3, timeout: 15 }, { retries: 5, timeout: null }); // => { retries: 5, timeout: 15 }

    applySubstitutions

    function

    Applies substitutions to a string based on a provided object. The string can contain placeholders in the format of {{key}}, which will be replaced by the corresponding value from the substitutions object. If a placeholder does not have a corresponding key in the substitutions object, it will remain unchanged in the output string.

    Signature
    applySubstitutions(
      input: string,
      substitutions?: Record<string, unknown>,
      options?: ISubstitutionOptions,
    ): string

    Parameters

    inputstring

    The input string containing placeholders in the format of {{key}}.

    substitutions?Record<string, unknown>

    No description.

    Defaults to {}.

    options?ISubstitutionOptions

    No description.

    Defaults to ....

    Returns

    string

    A string with the placeholders replaced by their corresponding values from the substitutions object.

    Example
    import { applySubstitutions } from 'jg-utilities';
    
    applySubstitutions('Hi {{name}}, you have {{count}} messages.', { name: 'Ada', count: 3 }); // => 'Hi Ada, you have 3 messages.'

    capitalizeFirst

    function

    Capitalizes the first letter of a string and returns the new value.

    Signature
    capitalizeFirst(value: string): string

    Parameters

    valuestring

    The string value to capitalize.

    Returns

    string

    A string with the first letter capitalized.

    Example
    import { capitalizeFirst } from 'jg-utilities';
    
    capitalizeFirst('hello world'); // => 'Hello world'

    createCursorCodec

    function

    Creates a codec for a list's pagination cursors: encode validates a continuation, such as the last row's sort keys and the list's filters, with the schema and encodes it as an opaque base64url cursor; decode reverses that for a cursor a client sent, and accepts it only for the list it came from. Without matchesScope, every key of the scope must equal the payload's.

    decode returns undefined for a missing cursor, meaning the first page, and throws INVALID_CURSOR for any cursor it refuses, with data.reason saying whether its encoding, its shape, or its scope was wrong, and the schema's own error, if any, as cause: for a client, a cursor that fails its schema is the same mistake as a malformed one.

    Signature
    createCursorCodec<TPayload extends { [key: string]: IJsonValue }, TScope extends object = Partial<TPayload>>(
      options: ICursorCodecOptions<TPayload, TScope>,
    ): ICursorCodec<TPayload, TScope>

    Parameters

    optionsICursorCodecOptions<TPayload, TScope>

    The schema, the longest cursor, and the scope rule.

    Returns

    ICursorCodec<TPayload, TScope>

    The codec.

    Throws

    • CURSOR_TOO_LONGThe cursor is longer than the codec's maximum length.
    • INVALID_CURSORThe cursor is not valid for this list.
    Example
    import { createCursorCodec } from 'jg-utilities';
    
    type IPostCursor = { authorId: string; lastId: number };
    const isPostCursor = (value: unknown): value is IPostCursor =>
      typeof value === 'object' && value !== null && 'authorId' in value && 'lastId' in value;
    
    const postCursors = createCursorCodec<IPostCursor, { authorId: string }>({
      schema: {
        parse: (value) => {
          if (!isPostCursor(value)) {
            throw new TypeError('Not a post cursor.');
          }
          return value;
        },
      },
    });
    const cursor = postCursors.encode({ authorId: 'ada', lastId: 42 });
    postCursors.decode(cursor, { authorId: 'ada' }); // => { authorId: 'ada', lastId: 42 }
    postCursors.decode(undefined, { authorId: 'ada' }); // => undefined

    createEventBus

    function

    Creates an in-process event bus that decouples the code that emits an event from the handlers that react to it, such as sending a welcome email after a sign-up. emit returns at once, and each event is delivered later, in the order it was emitted. Each handler runs on its own, so one that throws or rejects doesn't stop the others: its error goes to onError. A handler unsubscribed before it's called isn't called, and subscribing the same handler twice to one event registers it once. Declare the event map with type, because an interface has no index signature.

    Signature
    createEventBus<TEvents extends Record<string, unknown>>(
      options: IEventBusOptions<TEvents>,
    ): IEventBus<TEvents>

    Parameters

    optionsIEventBusOptions<TEvents>

    The onError that receives each handler's error.

    Returns

    IEventBus<TEvents>

    The bus.

    Example
    import { createEventBus } from 'jg-utilities';
    
    type IAppEvents = { userSignedUp: { userId: string } };
    
    const events = createEventBus<IAppEvents>({
      onError: (error, { name }) => console.error(`A ${String(name)} handler failed`, error),
    });
    const welcomedUserIds: string[] = [];
    const unsubscribe = events.subscribe('userSignedUp', ({ userId }) => {
      welcomedUserIds.push(userId);
    });
    
    // emit returns at once, and the handler runs later
    events.emit('userSignedUp', { userId: '42' });
    welcomedUserIds; // => []
    
    // once the handler is no longer needed
    setTimeout(unsubscribe, 1_000);

    createRequestCoordinator

    function

    Creates a coordinator that runs tasks, such as requests to a rate-limited API, at most maxConcurrent at a time, and queues the rest, first in, first out, up to maxQueued. A caller can be capped too, with caller and maxQueuedForCaller, so one caller can't fill the queue.

    deferUntil starts a cooldown, such as from a Retry-After header: queued tasks wait until it ends, without holding a slot, and tasks run with rejectDuringCooldown reject at once instead. A task whose signal aborts while it waits leaves the queue. A task's own result or error passes through unchanged, and its slot is released either way. No timer is left once nothing waits.

    run rejects with REQUEST_QUEUE_FULL when the queue, or the caller's share of it, is full, with REQUEST_COOLDOWN_ACTIVE when the task may not wait out a cooldown, with REQUEST_COORDINATOR_CLOSED after close, and with INVALID_QUEUE_LIMIT for a maxQueuedForCaller that isn't an integer of at least 0. deferUntil throws INVALID_DATE for a deadline that isn't a valid date.

    Signature
    createRequestCoordinator(
      options: IRequestCoordinatorOptions,
    ): IRequestCoordinator

    Parameters

    optionsIRequestCoordinatorOptions

    The concurrency and queue limits.

    Returns

    IRequestCoordinator

    The coordinator.

    Throws

    • INVALID_CONCURRENCY_LIMITThe concurrency limit must be an integer of at least 1.
    • INVALID_QUEUE_LIMITThe queue limit must be an integer of at least 0.
    Example
    import { createRequestCoordinator } from 'jg-utilities';
    
    const github = createRequestCoordinator({ maxConcurrent: 4, maxQueued: 64 });
    const fetchIssues = (): Promise<Response> =>
      github.run(() => fetch('https://api.github.com/repos/octocat/hello-world/issues'));

    createTimestamp

    function

    Creates an ISO 8601 timestamp, in UTC, from a date, a millisecond epoch, or a date string, or from the current time when no value is given.

    Signature
    createTimestamp(value?: string | number | Date): string

    Parameters

    value?string | number | Date

    The moment to format. Defaults to now.

    Returns

    string

    The timestamp, such as 2026-10-17T08:30:00.000Z.

    Throws

    • ErrorInvalid time value
    Example
    import { createTimestamp } from 'jg-utilities';
    
    createTimestamp(); // the current time, such as '2026-10-17T08:30:00.000Z'
    createTimestamp(0); // => '1970-01-01T00:00:00.000Z'

    decodeBase64Url

    function

    Decodes a base64url value, without padding, into the UTF-8 string it encodes. Only the canonical encoding of a string is accepted, so every string has exactly one valid encoding.

    Signature
    decodeBase64Url(value: string): string

    Parameters

    valuestring

    The base64url value to decode.

    Returns

    string

    The decoded string.

    Throws

    • INVALID_BASE64URLif the value isn't a string of base64url characters with a valid length.
    • INVALID_BASE64URLif the decoded bytes aren't valid UTF-8.
    • INVALID_BASE64URLif the value isn't the canonical encoding of its result.
    Example
    import { decodeBase64Url } from 'jg-utilities';
    
    decodeBase64Url('eyJwYWdlIjoyfQ'); // => '{"page":2}'

    decodeCursor

    function

    Decodes a cursor made by encodeCursor. The cursor comes from a client, so it's validated before decoding: a non-empty base64url string no longer than maxLength. The caller still validates the decoded value's shape, such as with a schema.

    Signature
    decodeCursor(cursor: string, maxLength?: number): ICursorValue

    Parameters

    cursorstring

    The cursor to decode.

    maxLength?number

    The longest cursor accepted, in characters.

    Defaults to 2048.

    Returns

    ICursorValue

    The decoded object or array.

    Throws

    • INVALID_CURSORThe cursor is not a valid encoded value.
    Example
    import { decodeCursor } from 'jg-utilities';
    
    const searchParams = new URLSearchParams('?cursor=eyJpZCI6NDJ9');
    decodeCursor(searchParams.get('cursor') ?? ''); // => { id: 42 }

    delay

    function

    Creates an asynchronous delay that resolves once the provided seconds have passed.

    Signature
    delay(seconds: number, options?: IDelayOptions): Promise<void>

    Parameters

    secondsnumber

    The number of seconds to delay before the promise resolves.

    options?IDelayOptions

    No description.

    Returns

    Promise<void>

    A promise that resolves after the specified number of seconds has passed.

    Throws

    • ErrorThe signal's reason when the signal is already aborted or aborts during the wait.
    Example
    import { delay } from 'jg-utilities';
    
    await delay(0.5); // resumes after half a second
    await delay(10, { signal: AbortSignal.timeout(100) }).catch(() => 'stopped'); // => 'stopped'

    encodeBase64Url

    function

    Encodes a string as UTF-8 base64url without padding. For ASCII input, the output equals the btoa-based and Buffer-based base64url encodings.

    Signature
    encodeBase64Url(value: string): string

    Parameters

    valuestring

    The string to encode.

    Returns

    string

    The base64url encoding of the string's UTF-8 bytes.

    Example
    import { encodeBase64Url } from 'jg-utilities';
    
    encodeBase64Url('{"page":2}'); // => 'eyJwYWdlIjoyfQ'

    encodeCursor

    function

    Encodes a pagination continuation, such as the sort keys of the last row, as an opaque cursor: its JSON in base64url, safe for URLs and query strings.

    Signature
    encodeCursor(value: ICursorValue): string

    Parameters

    valueICursorValue

    The object or array to encode.

    Returns

    string

    The cursor.

    Throws

    • UNSUPPORTED_DATA_TYPEif the value isn't an object or an array
    • UNABLE_TO_SERIALIZE_JSONif the value contains data that cannot be serialized
    Example
    import { encodeCursor } from 'jg-utilities';
    
    encodeCursor({ id: 42 }); // => 'eyJpZCI6NDJ9'

    escapeHtml

    function

    Escapes text for HTML, so it shows as written instead of becoming markup, such as a name in an email template or a Telegram message. It's safe in element content and quoted attribute values, not in a URL, a script, or a style.

    Signature
    escapeHtml(text: string): string

    Parameters

    textstring

    The text.

    Returns

    string

    The escaped text.

    Example
    import { escapeHtml } from 'jg-utilities';
    
    escapeHtml('<b>"Tom" & Jerry\'s</b>'); // => '&lt;b&gt;&quot;Tom&quot; &amp; Jerry&#39;s&lt;/b&gt;'

    estimateReadingTime

    function

    Estimates how long text takes to read at 200 words per minute.

    Signature
    estimateReadingTime(text: unknown): number

    Parameters

    textunknown

    The text whose reading time will be estimated.

    Returns

    number

    The estimated reading time in milliseconds, or 0 for non-string or empty input.

    Example
    import { estimateReadingTime, prettifyTime } from 'jg-utilities';
    
    const article = 'word '.repeat(600);
    estimateReadingTime(article); // milliseconds, about 3 minutes for 600 words
    prettifyTime(estimateReadingTime(article)); // => '3m'

    extractEmailUsername

    function

    Validates the format of an email address and extracts the username from it.

    Signature
    extractEmailUsername(email: string): string

    Parameters

    emailstring

    The email address to validate and extract the username from.

    Returns

    string

    The extracted username from the email address.

    Throws

    • INVALID_EMAIL_ADDRESSIf the email address is not valid or has a forbidden extension.
    Example
    import { extractEmailUsername } from 'jg-utilities';
    
    extractEmailUsername('[email protected]'); // => 'ada.lovelace'

    extractFirstMarkdownHeadingName

    function

    Extracts the name of the first markdown heading in the given content.

    Signature
    extractFirstMarkdownHeadingName(markdownContent: string): string | null

    Parameters

    markdownContentstring

    The markdown-formatted content.

    Returns

    string | null

    The first markdown heading text found in the content, or null if none is found.

    Example
    import { extractFirstMarkdownHeadingName } from 'jg-utilities';
    
    extractFirstMarkdownHeadingName('Intro\n\n## Getting started\n\nText'); // => 'Getting started'

    extractSubstitutionPlaceholderNames

    function

    Extracts the names of substitution placeholders in the given text.

    Signature
    extractSubstitutionPlaceholderNames(text: string): string[]

    Parameters

    textstring

    The text containing substitution placeholders.

    Returns

    string[]

    An array of substitution placeholder names.

    Example
    import { extractSubstitutionPlaceholderNames } from 'jg-utilities';
    
    extractSubstitutionPlaceholderNames('Hi {{name}}, you have {{count}} messages, {{name}}.'); // => ['name', 'count']

    extractTokenFromAuthorizationHeader

    function

    Validates the format of an authorization header and extracts the token from it.

    Signature
    extractTokenFromAuthorizationHeader(header: string): string

    Parameters

    headerstring

    The authorization header to validate and extract the token from.

    Returns

    string

    The extracted token from the authorization header.

    Throws

    • INVALID_AUTHORIZATION_HEADERIf the header does not comply with the expected format.
    Example
    import { extractTokenFromAuthorizationHeader } from 'jg-utilities';
    
    extractTokenFromAuthorizationHeader('Bearer eyJhbGciOi.payload.signature'); // => 'eyJhbGciOi.payload.signature'

    filterByQuery

    function

    Filters an array of primitives based on a given query and returns a shallow copy.

    Signature
    filterByQuery<T>(
      items: T[],
      query: string,
      options?: IFilterByQueryOptions<T>,
    ): T[]

    Parameters

    itemsT[]

    The array of items to be filtered by the query.

    querystring

    The query string to filter the items by.

    options?IFilterByQueryOptions<T>

    No description.

    Returns

    T[]

    A new array containing the items that match the query based on the provided options.

    Example
    import { filterByQuery } from 'jg-utilities';
    
    filterByQuery([{ name: 'Ada' }, { name: 'Alan' }, { name: 'Grace' }], 'al', { queryProp: 'name' }); // => [{ name: 'Alan' }]

    generateDateId

    function

    Generates a date ID string in the format "YYYY_MM_DD".

    Signature
    generateDateId(value?: IDateValue): string

    Parameters

    value?IDateValue

    The date value to generate the ID from. Defaults to the current date if not provided.

    Returns

    string

    The generated date ID string.

    Example
    import { generateDateId } from 'jg-utilities';
    
    generateDateId(new Date(2026, 9, 17)); // => '2026_10_17'
    generateDateId(); // today's ID

    generateRandomFloat

    function

    Generates a random decimal in a range, with 53 bits of randomness from crypto.getRandomValues.

    Signature
    generateRandomFloat(min: number, max: number): number

    Parameters

    minnumber

    The lowest value, included.

    maxnumber

    The highest value, excluded.

    Returns

    number

    A random number greater than or equal to min and less than max.

    Example
    import { generateRandomFloat } from 'jg-utilities';
    
    generateRandomFloat(0, 1); // 0.7312...

    generateRandomInteger

    function

    Generates a random integer in an inclusive range. Each integer is equally likely: values come from crypto.getRandomValues with rejection sampling.

    Signature
    generateRandomInteger(min: number, max: number): number

    Parameters

    minnumber

    The lowest value, included.

    maxnumber

    The highest value, included.

    Returns

    number

    A random integer from min to max.

    Example
    import { generateRandomInteger } from 'jg-utilities';
    
    generateRandomInteger(1, 6); // such as 4

    generateRandomString

    function

    Generates a string of characters picked at random from a set. Each character is drawn with crypto.getRandomValues and rejection sampling, so every character in the set is equally likely and the result is fit for secrets such as passwords.

    Signature
    generateRandomString(length: number, characters?: string): string

    Parameters

    lengthnumber

    The length of the string.

    characters?string

    The characters to pick from. Defaults to ASCII letters and digits.

    Defaults to 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.

    Returns

    string

    The random string, or an empty string when the length or the set is empty.

    Example
    import { generateRandomString } from 'jg-utilities';
    
    generateRandomString(12); // such as 'aZ3kPq9TbW0x'
    generateRandomString(6, '0123456789'); // such as '402913'

    generateSequence

    function

    Generates a sequence of numbers within a range based on a number of steps.

    Signature
    generateSequence(start: number, stop: number, step?: number): number[]

    Parameters

    startnumber

    The starting value of the sequence.

    stopnumber

    The ending value of the sequence.

    step?number

    No description.

    Defaults to 1.

    Returns

    number[]

    An array of numbers representing the sequence.

    Example
    import { generateSequence } from 'jg-utilities';
    
    generateSequence(1, 5); // => [1, 2, 3, 4, 5]
    generateSequence(0, 10, 5); // => [0, 5, 10]

    generateUtcDateSequence

    function

    Lists every UTC calendar date in an inclusive range, in ascending order, such as the days of a chart's axis. It gives one entry per day, so bound the range before passing one from a client.

    Signature
    generateUtcDateSequence(range: IUtcDateRange): string[]

    Parameters

    rangeIUtcDateRange

    The first and last dates, as YYYY-MM-DD.

    Returns

    string[]

    The dates, from fromDate to toDate.

    Throws

    • INVALID_DATE_RANGEThe range must hold two real dates as YYYY-MM-DD, the first no later than the second.
    Example
    import { generateUtcDateSequence } from 'jg-utilities';
    
    generateUtcDateSequence({ fromDate: '2028-02-28', toDate: '2028-03-01' }); // => ['2028-02-28', '2028-02-29', '2028-03-01']

    generateUuid

    function

    Generates a UUID based on a version.

    Signature
    generateUuid(version: IUuidVersion): string

    Parameters

    versionIUuidVersion

    The version of the UUID to be generated.

    Returns

    string

    A UUID string of the specified version.

    Example
    import { generateUuid } from 'jg-utilities';
    
    generateUuid(4); // such as '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
    generateUuid(7); // time-ordered, so later IDs sort after earlier ones

    getInitials

    function

    Extracts a string of initials from the provided value.

    Signature
    getInitials(value: string, initialsCount?: number): string

    Parameters

    valuestring

    The string value from which to extract initials.

    initialsCount?number

    No description.

    Defaults to 1.

    Returns

    string

    A string with up to the requested number of letter-only initials, or "A" if none exist.

    Example
    import { getInitials } from 'jg-utilities';
    
    getInitials('Ada Lovelace'); // => 'A'
    getInitials('Ada Lovelace', 2); // => 'AL'

    getNextPageParam

    function

    Gets the value of a property from the last item when the array length reaches the initial page size.

    Signature
    getNextPageParam<T extends object, K extends string | number | symbol>(
      propName: K,
      items: T[],
      initialPageSize: number,
    ): T[K] | undefined

    Parameters

    propNameK

    The property name to read from the last item.

    itemsT[]

    The array of items from which to read the last property value.

    initialPageSizenumber

    The expected page size required before reading the last property value.

    Returns

    T[K] | undefined

    The last item's property value, or undefined when the array length is below the initial page size.

    Example
    import { getNextPageParam } from 'jg-utilities';
    
    // with a page size of 2, a full page means there may be more
    getNextPageParam('id', [{ id: 1 }, { id: 2 }], 2); // => 2
    getNextPageParam('id', [{ id: 3 }], 2); // => undefined

    getTrailingUtcDateRange

    function

    Gives the inclusive range of the last dayCount UTC days, ending on the UTC date of an instant, such as the 30 days a report covers.

    Signature
    getTrailingUtcDateRange(dayCount: number, value?: IDateValue): IUtcDateRange

    Parameters

    dayCountnumber

    The number of days, a positive safe integer; 1 gives a range of one day.

    value?IDateValue

    No description.

    Returns

    IUtcDateRange

    The first and last UTC dates, as YYYY-MM-DD.

    Throws

    • INVALID_DAY_COUNTThe day count must be a positive safe integer whose range starts in the year 0000 or later.
    • INVALID_DATEThe value is not a valid date in the years 0000 to 9999.
    Example
    import { getTrailingUtcDateRange } from 'jg-utilities';
    
    getTrailingUtcDateRange(7, '2026-10-17T08:30:00.000Z'); // => { fromDate: '2026-10-11', toDate: '2026-10-17' }
    getTrailingUtcDateRange(30); // the last 30 days, today included

    hasNavigator

    function

    Checks whether a global navigator object exists. It reports presence only and doesn't identify a browser: Node.js 21 and later define a global navigator too.

    Signature
    hasNavigator(): boolean

    Returns

    boolean

    True when the navigator global is defined.

    Example
    import { hasNavigator } from 'jg-utilities';
    
    hasNavigator(); // true in browsers and in Node.js 21 or later

    hasWindow

    function

    Checks whether a global window object exists. It reports presence only and doesn't identify a browser.

    Signature
    hasWindow(): boolean

    Returns

    boolean

    True when the window global is defined.

    Example
    import { hasWindow } from 'jg-utilities';
    
    hasWindow(); // true in a browser, false in Node.js

    isArrayValid

    function

    Verifies if a value is an array. It also validates if it has elements inside (optional).

    Signature
    isArrayValid(value: unknown, allowEmpty?: boolean): value is any[]

    Parameters

    valueunknown

    The value to be validated.

    allowEmpty?boolean

    No description.

    Returns

    value is any[]

    A boolean indicating whether the value is a valid array and meets the element requirements (if provided).

    Example
    import { isArrayValid } from 'jg-utilities';
    
    isArrayValid([1]); // => true
    isArrayValid([]); // => false
    isArrayValid([], true); // => true

    isAuthorizationHeaderValid

    function

    Verifies if a value has a valid Authorization Header format based on the RFC6750. Example: Authorization: Bearer eyJhbGciOiJIUzI1NiIXVCJ9TJV...r7E20RMHrHDcEfxjoYZgeFONFh7HgQ More info: - https://stackoverflow.com/questions/33265812/best-http-authorization-header-type-for-jwt - https://www.rfc-editor.org/rfc/rfc6750

    Signature
    isAuthorizationHeaderValid(value: unknown): value is string

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is string

    A boolean indicating whether the value is a valid Authorization header.

    Example
    import { isAuthorizationHeaderValid } from 'jg-utilities';
    
    isAuthorizationHeaderValid('Bearer eyJhbGciOi.payload.signature'); // => true
    isAuthorizationHeaderValid('Basic dXNlcg=='); // => false

    isBigIntStringValid

    function

    Verifies that a value is an integer written in plain decimal digits, as PostgreSQL returns a BIGINT, and that it fits a range: a signed 64-bit integer by default. Leading zeros, a plus sign, -0, decimals, exponents, and padding are rejected, so one number has one spelling.

    Signature
    isBigIntStringValid(value: unknown, min?: bigint, max?: bigint): value is string

    Parameters

    valueunknown

    The value to be validated.

    min?bigint

    No description.

    Defaults to INT64_MIN.

    max?bigint

    No description.

    Defaults to INT64_MAX.

    Returns

    value is string

    A boolean indicating whether the value is such a string, within the range.

    Example
    import { isBigIntStringValid } from 'jg-utilities';
    
    isBigIntStringValid('9223372036854775807'); // => true
    isBigIntStringValid('9223372036854775808'); // => false
    isBigIntStringValid('007'); // => false
    isBigIntStringValid('5', 1n); // => true

    isEmailValid

    function

    Verifies if a value is a valid email address with a maximum length of 320 characters. Important: when providing forbiddenExtensions, ensure to include the dot (.) at the beginning. For example, to forbid .con, use ['.con'].

    Signature
    isEmailValid(value: unknown, forbiddenExtensions?: string[]): value is string

    Parameters

    valueunknown

    The value to be validated.

    forbiddenExtensions?string[]

    No description.

    Defaults to ....

    Returns

    value is string

    A boolean indicating whether the value is a valid email address and does not have a forbidden extension.

    Example
    import { isEmailValid } from 'jg-utilities';
    
    isEmailValid('[email protected]'); // => true
    isEmailValid('[email protected]'); // => false

    isEqual

    function

    Compares two values. Primitives, null, and undefined are compared with Object.is, so NaN equals NaN and 0 doesn't equal -0. Two objects or arrays are compared deeply, ignoring key order, through their deterministic JSON. An object never equals a primitive.

    Signature
    isEqual(firstValue: unknown, secondValue: unknown): boolean

    Parameters

    firstValueunknown

    The first value.

    secondValueunknown

    The second value.

    Returns

    boolean

    Whether the values are equal.

    Throws

    • UNABLE_TO_SERIALIZE_JSONif either object contains data that cannot be serialized
    Example
    import { isEqual } from 'jg-utilities';
    
    isEqual({ a: 1, b: [2] }, { b: [2], a: 1 }); // => true
    isEqual('a', 'a'); // => true
    isEqual({}, null); // => false

    isFileNameValid

    function

    Verifies if a value is a file name that is valid on Windows, macOS and Linux: one path component whose UTF-8 size is between 1 and maxBytes. It rejects ".", "..", control characters, the characters < > : " / \ | ? *, a trailing space or period, and Windows device names such as "con" or "lpt1.txt", in any letter case.

    Signature
    isFileNameValid(value: unknown, maxBytes?: number): value is string

    Parameters

    valueunknown

    The value to be validated.

    maxBytes?number

    No description.

    Defaults to MAX_FILE_NAME_BYTES.

    Returns

    value is string

    A boolean indicating whether the value is a portable file name.

    Example
    import { isFileNameValid } from 'jg-utilities';
    
    isFileNameValid('notes.md'); // => true
    isFileNameValid('con.txt'); // => false
    isFileNameValid('a/b.txt'); // => false

    isIndexedDbAvailable

    function

    Checks whether the IndexedDB API exists in the current environment.

    Signature
    isIndexedDbAvailable(): boolean

    Returns

    boolean

    True when the indexedDB global is defined.

    Example
    import { isIndexedDbAvailable } from 'jg-utilities';
    
    isIndexedDbAvailable(); // true in browsers that support IndexedDB

    isIntegerValid

    function

    Verifies if a value is a valid integer and is within a range (optional). If a range is not provided, it will use the properties Number.MIN_SAFE_INTEGER & Number.MAX_SAFE_INTEGER.

    Signature
    isIntegerValid(value: unknown, min?: number, max?: number): value is number

    Parameters

    valueunknown

    The value to be validated.

    min?number

    No description.

    max?number

    No description.

    Returns

    value is number

    A boolean indicating whether the value is a valid integer and within the specified range.

    Example
    import { isIntegerValid } from 'jg-utilities';
    
    isIntegerValid(5); // => true
    isIntegerValid(5.5); // => false
    isIntegerValid(5, 1, 3); // => false

    isJwtValid

    function

    Verifies if a value has a correct JWT Format: [Base64-URL Encoded Header].[Base64-URL Encoded Payload].[Signature]

    Signature
    isJwtValid(value: unknown): value is string

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is string

    A boolean indicating whether the value is a valid JWT.

    Example
    import { isJwtValid } from 'jg-utilities';
    
    isJwtValid('eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.c2lnbmF0dXJl'); // => true
    isJwtValid('not-a-token'); // => false

    isNumberValid

    function

    Verifies if a value is a valid number and is within a range (optional). The minimum value defaults to Number.MIN_SAFE_INTEGER (-9007199254740991) while the maximum value defaults to Number.MAX_SAFE_INTEGER (9007199254740991).

    Signature
    isNumberValid(value: unknown, min?: number, max?: number): value is number

    Parameters

    valueunknown

    The value to be validated.

    min?number

    No description.

    Defaults to Number.MIN_SAFE_INTEGER.

    max?number

    No description.

    Defaults to Number.MAX_SAFE_INTEGER.

    Returns

    value is number

    A boolean indicating whether the value is a valid number and within the specified range.

    Example
    import { isNumberValid } from 'jg-utilities';
    
    isNumberValid(12.5); // => true
    isNumberValid(Number.NaN); // => false
    isNumberValid(5, 10); // => false

    isNumeric

    function

    Verifies if a value is a valid numeric string.

    Signature
    isNumeric(value: string): boolean

    Parameters

    valuestring

    The value to be validated.

    Returns

    boolean

    A boolean indicating whether the value is a valid numeric string.

    Example
    import { isNumeric } from 'jg-utilities';
    
    isNumeric('-12.5'); // => true
    isNumeric('1,000'); // => false

    isObjectValid

    function

    Verifies if a value is an actual object. It also validates if it has keys (optional).

    Signature
    isObjectValid(
      value: unknown,
      allowEmpty?: boolean,
    ): value is Record<string, any>

    Parameters

    valueunknown

    The value to be validated.

    allowEmpty?boolean

    No description.

    Returns

    value is Record<string, any>

    A boolean indicating whether the value is a valid object and meets the key requirements (if provided).

    Example
    import { isObjectValid } from 'jg-utilities';
    
    isObjectValid({ id: 1 }); // => true
    isObjectValid({}); // => false
    isObjectValid({}, true); // => true
    isObjectValid([]); // => false

    isOTPSecretValid

    function

    Verifies if a value has the correct OTP Secret Format.

    Signature
    isOTPSecretValid(value: unknown): value is string

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is string

    A boolean indicating whether the value is a valid OTP secret.

    Example
    import { isOTPSecretValid } from 'jg-utilities';
    
    isOTPSecretValid('JBSWY3DPEHPK3PXP'); // => true

    isOTPTokenValid

    function

    Verifies if a value has the correct OTP Token Format.

    Signature
    isOTPTokenValid(value: unknown): value is string

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is string

    A boolean indicating whether the value is a valid OTP token.

    Example
    import { isOTPTokenValid } from 'jg-utilities';
    
    isOTPTokenValid('123456'); // => true
    isOTPTokenValid('12345'); // => false

    isPasswordValid

    function

    Verifies if a password meets the following requirements: - Meets a length range (Defaults to 8 - 2048) - At least one uppercase letter - At least one lowercase letter - At least one number - At least one special character

    Signature
    isPasswordValid(
      value: unknown,
      minLength?: number,
      maxLength?: number,
    ): value is string

    Parameters

    valueunknown

    The value to be validated.

    minLength?number

    No description.

    Defaults to 8.

    maxLength?number

    No description.

    Defaults to 2048.

    Returns

    value is string

    A boolean indicating whether the value is a valid password.

    Example
    import { isPasswordValid } from 'jg-utilities';
    
    isPasswordValid('Sup3r$ecret'); // => true
    isPasswordValid('password'); // => false

    isSemverValid

    function

    Verifies if a value complies with semantic versioning.

    Signature
    isSemverValid(value: unknown): value is string

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is string

    A boolean indicating whether the value is a valid semantic version.

    Example
    import { isSemverValid } from 'jg-utilities';
    
    isSemverValid('1.2.0'); // => true
    isSemverValid('1.2'); // => false

    isSlugValid

    function

    Verifies that a slug contains lowercase letters or digits separated by single hyphens and meets a length range.

    Signature
    isSlugValid(
      value: unknown,
      minLength?: number,
      maxLength?: number,
    ): value is string

    Parameters

    valueunknown

    The value to be validated.

    minLength?number

    No description.

    Defaults to 2.

    maxLength?number

    No description.

    Defaults to 16.

    Returns

    value is string

    A boolean indicating whether the value is a valid slug.

    Example
    import { isSlugValid } from 'jg-utilities';
    
    isSlugValid('jg-utilities'); // => true
    isSlugValid('JG Utils'); // => false

    isStringValid

    function

    Verifies if a value is a valid string and its length is within a range (optional).

    Signature
    isStringValid(
      value: unknown,
      minLength?: number,
      maxLength?: number,
      disallowWhitespaceOnly?: boolean,
    ): value is string

    Parameters

    valueunknown

    The value to be validated.

    minLength?number

    No description.

    Defaults to 1.

    maxLength?number

    No description.

    disallowWhitespaceOnly?boolean

    No description.

    Defaults to true.

    Returns

    value is string

    A boolean indicating whether the value is a valid string and meets the length requirements (if provided).

    Example
    import { isStringValid } from 'jg-utilities';
    
    isStringValid('hello'); // => true
    isStringValid('   '); // => false
    isStringValid('hello', 1, 3); // => false

    isTimestampValid

    function

    Verifies if a value is a valid unix timestamp in milliseconds. The smallest value is set for the beginning of the Unix epoch (January 1st, 1970 - 14400000) while the largest value is based on the numeric limit established by JavaScript (9007199254740991).

    Signature
    isTimestampValid(value: unknown): value is number

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is number

    A boolean indicating whether the value is a valid unix timestamp in milliseconds.

    Example
    import { isTimestampValid } from 'jg-utilities';
    
    isTimestampValid(Date.UTC(2026, 9, 17)); // => true
    isTimestampValid(-1); // => false

    isUrlValid

    function

    Verifies if a value is a valid URL.

    Signature
    isUrlValid(value: unknown): value is string

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is string

    A boolean indicating whether the value is a valid URL.

    Example
    import { isUrlValid } from 'jg-utilities';
    
    isUrlValid('https://jg-packages.jesusgraterol.dev'); // => true
    isUrlValid('not a url'); // => false

    isUuidValid

    function

    Verifies if a value is a valid UUID and that it matches a specific version.

    Signature
    isUuidValid(value: unknown, version: IUuidVersion): value is string

    Parameters

    valueunknown

    The value to be validated.

    versionIUuidVersion

    The UUID version to be validated against.

    Returns

    value is string

    A boolean indicating whether the value is a valid UUID of the specified version.

    Example
    import { isUuidValid } from 'jg-utilities';
    
    isUuidValid('0199f5e2-8f5a-7b3c-9d2e-4f1a6b8c0d7e', 7); // => true
    isUuidValid('0199f5e2-8f5a-7b3c-9d2e-4f1a6b8c0d7e', 4); // => false

    isYouTubeVideoIdValid

    function

    Verifies if a value is a YouTube video id: 11 characters of letters, digits, -, and _.

    Signature
    isYouTubeVideoIdValid(value: unknown): value is string

    Parameters

    valueunknown

    The value to be validated.

    Returns

    value is string

    A boolean indicating whether the value is a YouTube video id.

    Example
    import { isYouTubeVideoIdValid } from 'jg-utilities';
    
    isYouTubeVideoIdValid('M7lc1UVf-VE'); // => true
    isYouTubeVideoIdValid('M7lc1UVf-V'); // => false

    maskMiddle

    function

    Masks the middle of a string, keeping a specified number of visible characters at the start and end.

    Signature
    maskMiddle(text: string, visibleChars: number, mask?: string): string

    Parameters

    textstring

    The string value to mask.

    visibleCharsnumber

    The number of characters to keep visible at the start and end of the string.

    mask?string

    No description.

    Defaults to '...'.

    Returns

    string

    A string with the middle masked, keeping the specified number of visible characters at the start.

    Example
    import { maskMiddle } from 'jg-utilities';
    
    maskMiddle('0x1234567890abcdef', 4); // => '0x12...cdef'

    normalizeQuery

    function

    Normalizes a query string by removing control characters, zero-width characters, and extra spaces, then converts it to lowercase. Optionally, it can truncate the string to a specified maximum length.

    Signature
    normalizeQuery(query: string, maxLength?: number): string

    Parameters

    querystring

    The query string to normalize.

    maxLength?number

    No description.

    Returns

    string

    The normalized query string.

    Example
    import { normalizeQuery } from 'jg-utilities';
    
    normalizeQuery('  Héllo   WORLD  '); // => 'héllo world'

    omitProps

    function

    Omits a list of properties from an object and returns a new object (shallow) with only those keys that weren't omitted

    Signature
    omitProps<T extends object, K extends string | number | symbol>(
      input: T,
      propKeys: K[],
    ): Omit<T, K>

    Parameters

    inputT

    The object from which to omit properties.

    propKeysK[]

    The keys of the properties to omit.

    Returns

    Omit<T, K>

    A new object containing only the properties that were not omitted.

    Throws

    • INVALID_OR_EMPTY_OBJECTif the input is not a valid object or it is empty
    • INVALID_OR_EMPTY_ARRAYif the keys to be omitted are not a valid array or it is empty
    Example
    import { omitProps } from 'jg-utilities';
    
    omitProps({ id: 1, name: 'Ada', email: '[email protected]' }, ['email']); // => { id: 1, name: 'Ada' }

    parseJson

    function

    Deserializes a JSON string with the JSON.parse method.

    Signature
    parseJson<T>(value: string): T

    Parameters

    valuestring

    The JSON string to be deserialized.

    Returns

    T

    The deserialized object or array.

    Throws

    • UNSUPPORTED_DATA_TYPEif the provided value is not a non-empty string
    • UNABLE_TO_DESERIALIZE_JSONif the result of JSON.parse is not a valid object or array
    • UNABLE_TO_DESERIALIZE_JSONif an error is thrown during parsing
    Example
    import { parseJson } from 'jg-utilities';
    
    const user = parseJson<{ id: number }>('{"id":1}'); // { id: 1 }

    parseYouTubeVideoId

    function

    Reads the id of the single YouTube video a URL points at, such as one a user pasted. It accepts https URLs without credentials or a port, on these hosts and paths, and ignores the query, apart from v, and the hash: - youtu.be/<id> - youtube.com/watch?v=<id>, /shorts/<id>, /embed/<id>, and /live/<id> - m.youtube.com/watch?v=<id> - youtube-nocookie.com/embed/<id>

    The www. form of each host works too. Anything else, such as a playlist, a channel, or a value that isn't a URL, returns null rather than throwing.

    Signature
    parseYouTubeVideoId(url: unknown): string | null

    Parameters

    urlunknown

    The value to read, trimmed when it's a string.

    Returns

    string | null

    The 11-character video id, or null.

    Example
    import { parseYouTubeVideoId } from 'jg-utilities';
    
    parseYouTubeVideoId('https://youtu.be/M7lc1UVf-VE'); // => 'M7lc1UVf-VE'
    parseYouTubeVideoId('https://www.youtube.com/watch?v=M7lc1UVf-VE&t=30'); // => 'M7lc1UVf-VE'
    parseYouTubeVideoId('https://www.youtube.com/playlist?list=PL123'); // => null

    pickProps

    function

    Picks a list of properties from an object and returns a new object (shallow) with the provided keys.

    Signature
    pickProps<T extends object, K extends string | number | symbol>(
      input: T,
      propKeys: K[],
    ): Pick<T, K>

    Parameters

    inputT

    The object from which to pick properties.

    propKeysK[]

    The keys of the properties to pick.

    Returns

    Pick<T, K>

    A new object containing only the picked properties.

    Throws

    • INVALID_OR_EMPTY_OBJECTif the input is not a valid object or it is empty
    • INVALID_OR_EMPTY_ARRAYif the keys to be picked are not a valid array or it is empty
    Example
    import { pickProps } from 'jg-utilities';
    
    pickProps({ id: 1, name: 'Ada', email: '[email protected]' }, ['id', 'name']); // => { id: 1, name: 'Ada' }

    pluralize

    function

    Picks the singular or plural form of a word for a count, such as "1 file" and "3 files".

    Signature
    pluralize(count: number, singular: string, plural?: string): string

    Parameters

    countnumber

    The count.

    singularstring

    The word for exactly one.

    plural?string

    The word for any other count. Defaults to the singular with an "s".

    Defaults to ....

    Returns

    string

    The word alone, so other words can sit between it and the count.

    Example
    import { pluralize } from 'jg-utilities';
    
    pluralize(1, 'file'); // => 'file'
    pluralize(0, 'file'); // => 'files'
    pluralize(2, 'entry', 'entries'); // => 'entries'

    prefersReducedMotion

    function

    Checks whether the user asked the system to reduce motion. The view defaults to the global window when one exists; pass another one, such as an element's ownerDocument.defaultView, to check a different window.

    Signature
    prefersReducedMotion(view?: IMediaQueryView | null): boolean

    Parameters

    view?IMediaQueryView | null

    No description.

    Defaults to ....

    Returns

    boolean

    True only when the view reports a reduced-motion preference.

    Example
    import { prefersReducedMotion } from 'jg-utilities';
    
    prefersReducedMotion(); // true when the user asked the system to reduce motion

    prettifyBadgeCount

    function

    Formats the number that will be inserted in a badge so it doesn't take too much space. If the current count is 0, it returns undefined as the badge shouldn't be displayed.

    Signature
    prettifyBadgeCount(value: number, maxValue?: number): string | undefined

    Parameters

    valuenumber

    The current count to be displayed in the badge.

    maxValue?number

    The maximum value to display before showing a "+" sign. Defaults to 9.

    Defaults to 9.

    Returns

    string | undefined

    A string representing the formatted badge count or undefined if the count is 0.

    Example
    import { prettifyBadgeCount } from 'jg-utilities';
    
    prettifyBadgeCount(3); // => '3'
    prettifyBadgeCount(42); // => '9+'
    prettifyBadgeCount(0); // => undefined

    prettifyDate

    function

    Formats a date instance based on a template. The output is always en-US, whatever the runtime's locale, and hours have no leading zero. - date-short: 12/05/2024 (Default) - date-medium: December 5, 2024 - date-long: Thursday, December 5, 2024 - time-short: 9:05 PM - time-medium: 9:05:20 PM - datetime-short: 12/5/2024, 9:05 PM - datetime-medium: December 5, 2024 at 9:05 PM - datetime-long: Thursday, December 5, 2024 at 9:05:20 PM

    Without a time zone, the runtime's local zone is used, so a server and a browser can format the same instant differently. Pass 'UTC' for calendar dates and for data defined in UTC periods, and an explicit time zone for server-rendered output. Templates with a time end with the zone's short name when a time zone is given, for example "December 5, 2024 at 11:30 PM UTC". Prefer date-medium, datetime-medium and time-medium in UI text over the numeric templates.

    Signature
    prettifyDate(
      value: IDateValue,
      template?: IDateTemplate,
      timeZone?: string,
    ): string

    Parameters

    valueIDateValue

    The date value to be formatted. It can be a Date object, a timestamp, or a date string.

    template?IDateTemplate

    The template to use for formatting the date. Defaults to date-short.

    Defaults to 'date-short'.

    timeZone?string

    No description.

    Returns

    string

    A string representing the formatted date.

    Throws

    • ErrorA RangeError if the time zone is unknown.
    Example
    import { prettifyDate } from 'jg-utilities';
    
    prettifyDate('2026-10-17T08:30:00.000Z', 'date-medium', 'UTC'); // => 'October 17, 2026'
    prettifyDate('2026-10-17T08:30:00.000Z', 'datetime-short', 'UTC'); // => '10/17/2026, 8:30 AM UTC'

    prettifyFileSize

    function

    Formats a bytes value into a human readable format. Bigints, such as BIGINT database values, are accepted too; values beyond Number.MAX_SAFE_INTEGER are formatted without losing precision.

    Signature
    prettifyFileSize(value: number | bigint, decimalPlaces?: number): string

    Parameters

    valuenumber | bigint

    The bytes value to be formatted, as a number or a bigint.

    decimalPlaces?number

    The number of decimal places to include. Defaults to 2.

    Defaults to 2.

    Returns

    string

    A string representing the formatted file size.

    Example
    import { prettifyFileSize } from 'jg-utilities';
    
    prettifyFileSize(1536); // => '1.50 kB'
    prettifyFileSize(3_250_000_000, 1); // => '3.0 GB'

    prettifyNumber

    function

    Formats a numeric value based on the user's default language. A negative value's sign goes before the prefix, as in -$5.

    Signature
    prettifyNumber(
      value: number,
      configuration?: Partial<INumberFormatConfig>,
    ): string

    Parameters

    valuenumber

    The number to be formatted.

    configuration?Partial<INumberFormatConfig>

    No description.

    Returns

    string

    A string representing the formatted number.

    Example
    import { prettifyNumber } from 'jg-utilities';
    
    prettifyNumber(1234567.891); // => '1,234,567.89'
    prettifyNumber(19.5, { minimumFractionDigits: 2, prefix: '$' }); // => '$19.50'
    prettifyNumber(-5, { prefix: '$' }); // => '-$5'

    prettifyPercentage

    function

    Formats a numeric value as a percentage based on the user's default language.

    Signature
    prettifyPercentage(
      value: number,
      configuration?: Partial<INumberFormatConfig>,
    ): string

    Parameters

    valuenumber

    The number to be formatted as a percentage - whole value (e.g., 50 for 50%)

    configuration?Partial<INumberFormatConfig>

    No description.

    Returns

    string

    A string representing the formatted percentage.

    Example
    import { prettifyPercentage } from 'jg-utilities';
    
    prettifyPercentage(12.345); // => '12.35%'
    prettifyPercentage(-3); // => '-3%'

    prettifyTime

    function

    Formats a duration in milliseconds into a human-readable string.

    Signature
    prettifyTime(milliseconds: number): string

    Parameters

    millisecondsnumber

    The duration in milliseconds.

    Returns

    string

    A string representing the formatted duration.

    Example
    import { prettifyTime } from 'jg-utilities';
    
    prettifyTime(3_725_000); // => '1h 2m'
    prettifyTime(45_000); // => '45s'

    pruneJson

    function

    Removes null, undefined, empty objects, and empty arrays from the given data recursively.

    Signature
    pruneJson<T extends IJsonValue>(value: T): T | null

    Parameters

    valueT

    The value to be pruned. It should be an object, array, or primitive value.

    Returns

    T | null

    The pruned value, or null if the value is empty or invalid.

    Example
    import { pruneJson } from 'jg-utilities';
    
    pruneJson({ a: 1, b: null, c: {}, d: [], e: { f: [] } }); // => { a: 1 }

    redactSecrets

    function

    Replaces the secrets in free text, such as a log line or a file headed for an AI model: complete PEM private key blocks first, then every match of the token patterns, which default to SECRET_TOKEN_PATTERNS. It runs in linear time over the key blocks, matches each pattern globally whatever its flags, and never throws for any text, so a logger can call it safely.

    With preserveLineBreaks, a private key becomes the replacement followed by its line breaks, or preceded by them when it ends the text, so line numbers in the text stay the same.

    Signature
    redactSecrets(
      text: string,
      options?: IRedactSecretsOptions,
    ): IRedactSecretsResult

    Parameters

    textstring

    The text to redact.

    options?IRedactSecretsOptions

    The patterns, the replacement, and whether key blocks keep their line breaks.

    Defaults to {}.

    Returns

    IRedactSecretsResult

    The redacted text, and how many secrets were replaced.

    Example
    import { redactSecrets } from 'jg-utilities';
    
    redactSecrets('auth: ghp_abcdefghijklmnopqrstuvwxyz'); // => { text: 'auth: [redacted]', count: 1 }
    redactSecrets('port: 3000'); // => { text: 'port: 3000', count: 0 }

    redactUrlQueryParams

    function

    Removes a URL's query and fragment when the query holds any of the named parameters, such as a token, so the URL can be logged. A name matches exactly, after decoding, or as the start of an array parameter, such as token[]. A name that can't be decoded could hide one of them, so the whole URL becomes [redacted], as does a URL that is only a query.

    Signature
    redactUrlQueryParams(url: string, names: readonly string[]): string

    Parameters

    urlstring

    The request target or absolute URL.

    namesreadonly string[]

    The names of the parameters that make the query unsafe to log.

    Returns

    string

    The URL when it holds none of them, otherwise the part before its query.

    Example
    import { redactUrlQueryParams } from 'jg-utilities';
    
    redactUrlQueryParams('/reset?token=abc#form', ['token']); // => '/reset'
    redactUrlQueryParams('/reset?tok%65n=abc', ['token']); // => '/reset'
    redactUrlQueryParams('/search?q=shoes', ['token']); // => '/search?q=shoes'

    resolveSafeInternalPath

    function

    Checks an untrusted path, such as a returnTo parameter after sign-in, and returns it only when it stays on the same site and outside the excluded paths, so a link can't send someone to another site or back into a sign-in loop. It must start with one /; a protocol-relative URL, an absolute URL, a backslash, or a path that can't be decoded is rejected. An excluded path matches itself and everything under it, by whole segments, case-insensitively, and after decoding, as a router matches routes.

    Signature
    resolveSafeInternalPath(
      candidate: unknown,
      excludedPaths?: readonly string[],
    ): string | null

    Parameters

    candidateunknown

    The untrusted value.

    excludedPaths?readonly string[]

    Paths it must not lead to, such as ['/sign-in'].

    Defaults to [].

    Returns

    string | null

    The path, normalized, with its query and fragment, or null when it isn't safe.

    Example
    import { resolveSafeInternalPath } from 'jg-utilities';
    
    resolveSafeInternalPath('/projects/a?tab=files', ['/sign-in']); // => '/projects/a?tab=files'
    resolveSafeInternalPath('//evil.example', ['/sign-in']); // => null
    resolveSafeInternalPath('/sign-in/step', ['/sign-in']); // => null
    resolveSafeInternalPath('/sign-in-help', ['/sign-in']); // => '/sign-in-help'

    retryAsyncFunction

    function

    Executes an asynchronous function persistently, retrying on error with incremental delays defined in retryScheduleDuration (seconds). When the signal aborts, the returned promise rejects immediately, even while an attempt is pending. The attempt's own work isn't cancelled; pass the signal into it as well when it supports one.

    Signature
    retryAsyncFunction<T>(
      fn: () => Promise<T>,
      retryScheduleDuration?: number[],
      options?: IRetryAsyncFunctionOptions,
    ): Promise<T>

    Parameters

    fn() => Promise<T>

    The asynchronous function to be executed persistently.

    retryScheduleDuration?number[]

    No description.

    Defaults to ....

    options?IRetryAsyncFunctionOptions

    No description.

    Returns

    Promise<T>

    A promise that resolves with the result of the asynchronous function or rejects with the last encountered error.

    Throws

    • ErrorThe last error thrown by the function, or the first one shouldRetry declines to retry.
    • ErrorThe signal's reason when the signal aborts.
    Example
    import { retryAsyncFunction } from 'jg-utilities';
    
    let attempts = 0;
    const readRate = async (): Promise<number> => {
      attempts += 1;
      if (attempts < 2) {
        throw new Error('The service is busy.');
      }
      return 1.08;
    };
    
    // up to 3 attempts, 0.1 and 0.5 seconds apart
    await retryAsyncFunction(readRate, [0.1, 0.5]); // => 1.08
    attempts; // => 2

    shuffleArray

    function

    Creates a shallow copy of the input array and shuffles it with the Fisher-Yates algorithm, drawing each position with crypto.getRandomValues, so every order is equally likely.

    Signature
    shuffleArray<T>(input: T[]): T[]

    Parameters

    inputT[]

    The array to be shuffled.

    Returns

    T[]

    A new array with the values of the input array in a random order.

    Throws

    • INVALID_OR_EMPTY_ARRAYif the input is not array or it is empty
    Example
    import { shuffleArray } from 'jg-utilities';
    
    shuffleArray([1, 2, 3, 4]); // a new array, such as [3, 1, 4, 2]

    sortPrimitives

    function

    Sorts a list of primitive values based on their type and a sort direction.

    Signature
    sortPrimitives(
      direction: ISortDirection,
    ): (firstValue: T, secondValue: T) => number

    Parameters

    directionISortDirection

    The direction to sort the values.

    Returns

    (firstValue: T, secondValue: T) => number

    A number indicating the sort order based on the primitive type.

    Throws

    • MIXED_OR_UNSUPPORTED_DATA_TYPESif the values are mixed or are different to string | number | bigint
    Example
    import { sortPrimitives } from 'jg-utilities';
    
    [3, 1, 2].sort(sortPrimitives('asc')); // => [1, 2, 3]
    ['b', 'c', 'a'].sort(sortPrimitives('desc')); // => ['c', 'b', 'a']

    sortRecords

    function

    Sorts a list of record values by key based on their type and a sort direction.

    Signature
    sortRecords(
      key: string,
      direction: ISortDirection,
    ): (firstRecord: T, secondRecord: T) => number

    Parameters

    keystring

    The key of the record to sort by.

    directionISortDirection

    The direction to sort the values.

    Returns

    (firstRecord: T, secondRecord: T) => number

    A number indicating the sort order based on the primitive type.

    Throws

    • MIXED_OR_UNSUPPORTED_DATA_TYPESif the values are mixed or are different to string | number | bigint
    Example
    import { sortRecords } from 'jg-utilities';
    
    [{ age: 40 }, { age: 25 }].sort(sortRecords('age', 'asc')); // => [{ age: 25 }, { age: 40 }]

    sortRecordsWithBigIntString

    function

    Sorts a list of record values by key, treating stringified bigints as actual bigints, based on a sort direction.

    Signature
    sortRecordsWithBigIntString<T extends Record<string, unknown>>(
      key: keyof T,
      direction: ISortDirection,
    ): (firstRecord: T, secondRecord: T) => number

    Parameters

    keykeyof T

    The key of the record to sort by.

    directionISortDirection

    The direction to sort the values.

    Returns

    (firstRecord: T, secondRecord: T) => number

    A number indicating the sort order based on the primitive type.

    Throws

    • MIXED_OR_UNSUPPORTED_DATA_TYPESif the values are mixed or are different to string | number | bigint
    Example
    import { sortRecordsWithBigIntString } from 'jg-utilities';
    
    [{ amount: '900000000000000000001' }, { amount: '5' }].sort(sortRecordsWithBigIntString('amount', 'asc')); // => [{ amount: '5' }, { amount: '900000000000000000001' }]

    sortRecordsWithDateValue

    function

    Sorts a list of record values by key, treating date values as actual Date objects, based on a sort direction.

    Signature
    sortRecordsWithDateValue<T extends Record<string, unknown>>(
      key: keyof T,
      direction: ISortDirection,
    ): (firstRecord: T, secondRecord: T) => number

    Parameters

    keykeyof T

    The key of the record to sort by.

    directionISortDirection

    The direction to sort the values.

    Returns

    (firstRecord: T, secondRecord: T) => number

    A number indicating the sort order based on the date values.

    Throws

    • MIXED_OR_UNSUPPORTED_DATA_TYPESif either record has a missing, null, or invalid date value
    Example
    import { sortRecordsWithDateValue } from 'jg-utilities';
    
    [{ at: '2026-10-17' }, { at: '2025-01-01' }].sort(sortRecordsWithDateValue('at', 'asc')); // => [{ at: '2025-01-01' }, { at: '2026-10-17' }]

    splitArrayIntoBatches

    function

    Splits an array into smaller arrays (batches) of a given size.

    Signature
    splitArrayIntoBatches<T>(items: T[], batchSize: number): T[][]

    Parameters

    itemsT[]

    The array to be split into batches.

    batchSizenumber

    The size of each batch.

    Returns

    T[][]

    An array of arrays, where each inner array is a batch of the specified size.

    Throws

    • INVALID_BATCH_SIZEif the batch size is not a valid integer greater than 0
    Example
    import { splitArrayIntoBatches } from 'jg-utilities';
    
    splitArrayIntoBatches([1, 2, 3, 4, 5], 2); // => [[1, 2], [3, 4], [5]]

    stringifyJson

    function

    Serializes a JSON object with the JSON.stringify method.

    Signature
    stringifyJson<T>(value: T): string

    Parameters

    valueT

    The value to be serialized. It should be an object or an array.

    Returns

    string

    A string representing the serialized JSON object.

    Throws

    • UNSUPPORTED_DATA_TYPEif the provided value is not an object or an array
    • UNABLE_TO_SERIALIZE_JSONif the result of JSON.stringify is not a valid string
    • UNABLE_TO_SERIALIZE_JSONif an error is thrown during stringification
    Example
    import { stringifyJson } from 'jg-utilities';
    
    stringifyJson({ id: 1, tags: ['a'] }); // => '{"id":1,"tags":["a"]}'

    stringifyJsonDeterministically

    function

    Stringifies a JSON object in a deterministic way, ensuring that the keys are sorted and the output is consistent.

    Signature
    stringifyJsonDeterministically<T>(value: T): string

    Parameters

    valueT

    The value to be serialized. It should be an object or an array.

    Returns

    string

    A string representing the serialized JSON object with sorted keys.

    Throws

    • UNSUPPORTED_DATA_TYPEif the provided value is not an object or an array
    • UNABLE_TO_SERIALIZE_JSONif the result of JSON.stringify is not a valid string
    • UNABLE_TO_SERIALIZE_JSONif an error is thrown during stringification
    Example
    import { stringifyJsonDeterministically } from 'jg-utilities';
    
    stringifyJsonDeterministically({ b: 1, a: { d: 2, c: 3 } }); // => '{"a":{"c":3,"d":2},"b":1}'

    stringifyValue

    function

    Converts any value into a string. If the value is an object or an array, it will be stringified with JSON.stringify.

    Signature
    stringifyValue(value: unknown, jsonIndent?: number): string

    Parameters

    valueunknown

    The value to convert into a string.

    jsonIndent?number

    No description.

    Defaults to 0.

    Returns

    string

    A string representation of the value.

    Example
    import { stringifyValue } from 'jg-utilities';
    
    stringifyValue({ id: 1 }); // => '{"id":1}'
    stringifyValue(42); // => '42'
    stringifyValue(null); // => 'null'

    toDate

    function

    Creates an instance of Date based on a value.

    Signature
    toDate(value: IDateValue): Date

    Parameters

    valueIDateValue

    The value to create a Date instance from. It can be a Date object, a timestamp, or a date string.

    Returns

    Date

    A Date instance.

    Example
    import { toDate } from 'jg-utilities';
    
    toDate('2026-10-17T08:30:00.000Z'); // a Date for that instant
    toDate(1_792_217_505_000); // a Date from a millisecond epoch

    toMS

    function

    Converts a time string into milliseconds. The time string should be in the format of "{value} {unit}", where the value is a number and the unit can be milliseconds, seconds, minutes, hours, days, weeks, months, or years. For example: "2 days", "5 minutes", "2 hours".

    Signature
    toMS(
      str: `${number} years` | `${number} year` | `${number} months` | `${number} month` | `${number} weeks` | `${number} week` | `${number} days` | `${number} day` | `${number} hours` | `${number} hour` | `${number} minutes` | `${number} minute` | `${number} seconds` | `${number} second` | `${number} milliseconds` | `${number} millisecond`,
    ): number

    Parameters

    str`${number} years` | `${number} year` | `${number} months` | `${number} month` | `${number} weeks` | `${number} week` | `${number} days` | `${number} day` | `${number} hours` | `${number} hour` | `${number} minutes` | `${number} minute` | `${number} seconds` | `${number} second` | `${number} milliseconds` | `${number} millisecond`

    The time string to convert into milliseconds.

    Returns

    number

    The equivalent time in milliseconds.

    Throws

    • INVALID_TIME_STRINGif the provided time string is not a valid string.
    • INVALID_TIME_STRINGif the chunks do not match the expected format.
    • INVALID_TIME_STRINGif the value is not a valid positive integer.
    • INVALID_TIME_STRINGif the unit is not one of the accepted values.
    Example
    import { toMS } from 'jg-utilities';
    
    toMS('2 days'); // => 172800000
    toMS('30 minutes'); // => 1800000

    toSlug

    function

    Converts a string value into a slug, meeting the following requirements: - lowercase - removes accents/diacritics - replaces spaces and separators with "-" - removes invalid URL characters - collapses repeated "-" - trims leading/trailing "-"

    Signature
    toSlug(value: string): string

    Parameters

    valuestring

    The string value to convert.

    Returns

    string

    A string converted to a slug.

    Throws

    • UNABLE_TO_SLUGIFY_STRINGif the resulting slug is empty after processing the input string
    Example
    import { toSlug } from 'jg-utilities';
    
    toSlug('Héllo, World! 2026'); // => 'hello-world-2026'

    toTitleCase

    function

    Converts a string value into Title Case.

    Signature
    toTitleCase(value: string): string

    Parameters

    valuestring

    The string value to convert.

    Returns

    string

    A string converted to Title Case.

    Example
    import { toTitleCase } from 'jg-utilities';
    
    toTitleCase('the QUICK brown fox'); // => 'The Quick Brown Fox'

    toUtcDate

    function

    Gives the UTC calendar date of an instant, as YYYY-MM-DD, such as the day a UTC report or analytics period counts it in. The instant must fall in the years 0000 to 9999.

    Signature
    toUtcDate(value?: IDateValue): string

    Parameters

    value?IDateValue

    No description.

    Returns

    string

    The UTC date, such as 2026-10-17.

    Throws

    • INVALID_DATEThe value is not a valid date in the years 0000 to 9999.
    Example
    import { toUtcDate } from 'jg-utilities';
    
    toUtcDate('2026-10-17T23:30:00.000-05:00'); // => '2026-10-18'
    toUtcDate(0); // => '1970-01-01'
    toUtcDate(); // today's UTC date

    toYouTubeEmbedUrl

    function

    Builds the URL that embeds a YouTube video in an iframe, on YouTube's privacy-enhanced domain, which sets no cookies until the video plays.

    Signature
    toYouTubeEmbedUrl(videoId: string): string

    Parameters

    videoIdstring

    The video id, such as one parseYouTubeVideoId read.

    Returns

    string

    The URL, https://www.youtube-nocookie.com/embed/<id>.

    Throws

    • INVALID_YOUTUBE_VIDEO_IDThe YouTube video id must be 11 letters, digits, '-', or '_'.
    Example
    import { toYouTubeEmbedUrl } from 'jg-utilities';
    
    toYouTubeEmbedUrl('M7lc1UVf-VE'); // => 'https://www.youtube-nocookie.com/embed/M7lc1UVf-VE'

    toYouTubeWatchUrl

    function

    Builds the canonical watch page URL of a YouTube video, such as for a link.

    Signature
    toYouTubeWatchUrl(videoId: string): string

    Parameters

    videoIdstring

    The video id, such as one parseYouTubeVideoId read.

    Returns

    string

    The URL, https://www.youtube.com/watch?v=<id>.

    Throws

    • INVALID_YOUTUBE_VIDEO_IDThe YouTube video id must be 11 letters, digits, '-', or '_'.
    Example
    import { toYouTubeWatchUrl } from 'jg-utilities';
    
    toYouTubeWatchUrl('M7lc1UVf-VE'); // => 'https://www.youtube.com/watch?v=M7lc1UVf-VE'

    truncateText

    function

    Truncates a string to a specified length and appends an ellipsis if it exceeds that length.

    Signature
    truncateText(text: string, maxLength: number): string

    Parameters

    textstring

    The string value to truncate.

    maxLengthnumber

    The maximum length of the string before truncation.

    Returns

    string

    A string truncated to the specified length with an ellipsis if necessary.

    Example
    import { truncateText } from 'jg-utilities';
    
    truncateText('The quick brown fox jumps', 12); // => 'The quick...'

    truncateToUtf8Bytes

    function

    Shortens a string to the longest prefix of whole code points that fits a number of UTF-8 bytes, such as a push notification's body under the provider's payload limit. A character made of several code points, such as an emoji with a skin tone, can lose its last ones, but a code point is never split.

    Signature
    truncateToUtf8Bytes(text: string, maxBytes: number): string

    Parameters

    textstring

    The string.

    maxBytesnumber

    The most bytes the result may take in UTF-8, a non-negative safe integer.

    Returns

    string

    The string itself when it fits, otherwise its longest prefix that does.

    Throws

    • INVALID_BYTE_LIMITThe byte limit must be a non-negative safe integer.
    Example
    import { truncateToUtf8Bytes } from 'jg-utilities';
    
    truncateToUtf8Bytes('Hello, world', 5); // => 'Hello'
    truncateToUtf8Bytes('café au lait', 4); // => 'caf'
    truncateToUtf8Bytes('café au lait', 5); // => 'café'

    waitUntil

    function

    Probes a condition until it returns a value other than null, undefined or false, and resolves with that value. It probes immediately, then after every interval, and one final time at the deadline. The timeout bounds the whole call, so it rejects even while a probe is still pending. A running probe isn't cancelled when the call stops waiting; pass your own signal into it when it supports one.

    Signature
    waitUntil<T>(
      probe: () => T | Promise<T>,
      options: IWaitUntilOptions,
    ): Promise<Exclude<T, false | null | undefined>>

    Parameters

    probe() => T | Promise<T>

    The function that checks the condition.

    optionsIWaitUntilOptions

    The timeout, the interval between probes and the signal that stops the wait.

    Returns

    Promise<Exclude<T, false | null | undefined>>

    A promise that resolves with the first ready value.

    Throws

    • WAIT_UNTIL_TIMED_OUTif the condition isn't met before the timeout.
    • ErrorThe probe's error when a probe throws or rejects.
    • ErrorThe signal's reason when the signal aborts.
    Example
    import { waitUntil } from 'jg-utilities';
    
    const startedAt = Date.now();
    const readStatus = (): string => (Date.now() - startedAt > 200 ? 'ready' : 'starting');
    
    // the probe runs every 0.1 seconds until it returns something other than undefined
    await waitUntil(() => (readStatus() === 'ready' ? readStatus() : undefined), {
      timeoutSeconds: 5,
      intervalSeconds: 0.1,
    }); // => 'ready'

    Constants

    ERRORS

    const

    the codes for all the errors thrown by the library

    Declaration
    const ERRORS: { MIXED_OR_UNSUPPORTED_DATA_TYPES: "MIXED_OR_UNSUPPORTED_DATA_TYPES"; UNSUPPORTED_DATA_TYPE: "UNSUPPORTED_DATA_TYPE"; INVALID_OR_EMPTY_ARRAY: "INVALID_OR_EMPTY_ARRAY"; INVALID_OR_EMPTY_OBJECT: "INVALID_OR_EMPTY_OBJECT"; UNABLE_TO_SERIALIZE_JSON: "UNABLE_TO_SERIALIZE_JSON"; UNABLE_TO_DESERIALIZE_JSON: "UNABLE_TO_DESERIALIZE_JSON"; INVALID_BATCH_SIZE: "INVALID_BATCH_SIZE"; UNABLE_TO_SLUGIFY_STRING: "UNABLE_TO_SLUGIFY_STRING"; INVALID_TIME_STRING: "INVALID_TIME_STRING"; INVALID_AUTHORIZATION_HEADER: "INVALID_AUTHORIZATION_HEADER"; INVALID_EMAIL_ADDRESS: "INVALID_EMAIL_ADDRESS"; INVALID_BASE64URL: "INVALID_BASE64URL"; WAIT_UNTIL_TIMED_OUT: "WAIT_UNTIL_TIMED_OUT"; INVALID_CURSOR: "INVALID_CURSOR"; INVALID_DATE: "INVALID_DATE"; INVALID_DAY_COUNT: "INVALID_DAY_COUNT"; INVALID_DATE_RANGE: "INVALID_DATE_RANGE"; INVALID_BYTE_LIMIT: "INVALID_BYTE_LIMIT"; INVALID_YOUTUBE_VIDEO_ID: "INVALID_YOUTUBE_VIDEO_ID"; INVALID_CONCURRENCY_LIMIT: "INVALID_CONCURRENCY_LIMIT"; INVALID_QUEUE_LIMIT: "INVALID_QUEUE_LIMIT"; REQUEST_QUEUE_FULL: "REQUEST_QUEUE_FULL"; REQUEST_COOLDOWN_ACTIVE: "REQUEST_COOLDOWN_ACTIVE"; REQUEST_COORDINATOR_CLOSED: "REQUEST_COORDINATOR_CLOSED"; CURSOR_TOO_LONG: "CURSOR_TOO_LONG" }

    MAX_EMAIL_LENGTH

    const

    the maximum length for an email address according to the standard (RFC 5321)

    Declaration
    const MAX_EMAIL_LENGTH: 320

    ONE_MONTH_IN_MILLISECONDS

    const

    one average month, a twelfth of an average year, in milliseconds

    Declaration
    const ONE_MONTH_IN_MILLISECONDS: number

    ONE_YEAR_IN_MILLISECONDS

    const

    one average year, of 365.25 days, in milliseconds

    Declaration
    const ONE_YEAR_IN_MILLISECONDS: number

    SECRET_TOKEN_PATTERNS

    const

    The single-line secrets redactSecrets finds by default: GitHub's personal, OAuth, user, server, and refresh tokens, its fine-grained personal access tokens, and sk- API keys, such as OpenAI's, each with at least 20 characters after its prefix.

    Declaration
    const SECRET_TOKEN_PATTERNS: readonly RegExp[]

    Types

    ICursorCodec

    type

    encodes a list's continuation as a cursor, and decodes one only for the list it came from

    Declaration
    type ICursorCodec<TPayload, TScope> = {
        encode: (payload: TPayload) => string;
        decode: (cursor: string | null | undefined, scope: TScope) => TPayload | undefined;
    };

    Members

    • encodeproperty
      (payload: TPayload) => string
    • decodeproperty
      (cursor: string | null | undefined, scope: TScope) => TPayload | undefined

    ICursorCodecOptions

    type

    the options of createCursorCodec

    Declaration
    type ICursorCodecOptions<TPayload, TScope> = {
        schema: ISchema<TPayload>;
        maxLength?: number;
        matchesScope?: (payload: TPayload, scope: TScope) => boolean;
    };

    Members

    • schemaproperty
      ISchema<TPayload>

      validates the payload when it's encoded and when a cursor is decoded

    • maxLengthproperty
      number

      the longest cursor, in characters, that's encoded or decoded. Defaults to 2048

    • matchesScopeproperty
      (payload: TPayload, scope: TScope) => boolean

      Whether a decoded payload belongs to the list being read. Without it, every key of the scope must equal the payload's, with null and undefined counting as the same value.

    ICursorValue

    type

    the JSON a cursor can hold: an object or an array, as pagination continuations are

    Declaration
    type ICursorValue = {
        [key: string]: IJsonValue;
    } | IJsonValue[];

    IDateTemplate

    type

    Date Template A date can be prettified by choosing a template that meets the user's requirements. - date-short: 12/05/2024 - date-medium: December 5, 2024 - date-long: Thursday, December 5, 2024 - time-short: 9:05 PM - time-medium: 9:05:20 PM - datetime-short: 12/5/2024, 9:05 PM - datetime-medium: December 5, 2024 at 9:05 PM - datetime-long: Thursday, December 5, 2024 at 9:05:20 PM

    Declaration
    type IDateTemplate = 'date-short' | 'date-medium' | 'date-long' | 'time-short' | 'time-medium' | 'datetime-short' | 'datetime-medium' | 'datetime-long';

    IDateValue

    type

    the value that can be used to create a Date instance

    Declaration
    type IDateValue = Date | number | string;

    IDelayOptions

    type

    the options that can be passed to the delay function

    Declaration
    type IDelayOptions = {
        signal?: AbortSignal | undefined;
    };

    Members

    • signalproperty
      AbortSignal

      aborts the wait and rejects with the signal's reason

    IEventBus

    type

    an in-process event bus, whose events and their payloads are the keys and values of TEvents

    Declaration
    type IEventBus<TEvents extends Record<string, unknown>> = {
        emit: <TName extends keyof TEvents>(name: TName, event: TEvents[TName]) => void;
        subscribe: <TName extends keyof TEvents>(name: TName, handler: (event: TEvents[TName]) => unknown) => () => void;
        close: () => void;
    };

    Members

    • emitproperty
      (name: TName, event: TEvents[TName]) => void

      delivers the event to its handlers later, and returns at once

    • subscribeproperty
      (name: TName, handler: (event: TEvents[TName]) => unknown) => () => void

      registers a handler for an event, and returns the function that unsubscribes it

    • closeproperty
      () => void

      drops the pending deliveries and every handler, and ignores later emits and subscriptions

    IEventBusOptions

    type

    what an event bus calls with each error a handler throws or rejects with

    Declaration
    type IEventBusOptions<TEvents extends Record<string, unknown>> = {
        onError: (error: unknown, context: {
            name: keyof TEvents;
            event: TEvents[keyof TEvents];
        }) => void;
    };

    Members

    • onErrorproperty
      (error: unknown, context: { name: keyof TEvents; event: TEvents[keyof TEvents] }) => void

      receives the error and the event the handler was handling; anything it throws is swallowed

    IFilterByQueryOptions

    type

    the options that can be used to filter items by a query

    Declaration
    type IFilterByQueryOptions<T> = {
        queryProp?: keyof T;
        limit?: number;
    };

    Members

    • queryPropproperty
      keyof T

      the property to filter by, if not provided, the whole item will be used

    • limitproperty
      number

      the maximum number of items to return

    IJsonValue

    type

    A value that survives a trip through JSON. An object's values may also be undefined, because JSON.stringify drops them, so an object with optional fields fits. Interfaces and classes don't fit, because they have no index signature: pass an interface-typed value as { ...value }, or declare its type with type.

    Declaration
    type IJsonValue = string | number | boolean | null | IJsonValue[] | {
        [key: string]: IJsonValue | undefined;
    };

    INumberFormatConfig

    type

    Number Format Configuration The configuration that will be used to prettify a number.

    Declaration
    type INumberFormatConfig = {
        minimumFractionDigits: number;
        maximumFractionDigits: number;
        prefix: string;
        suffix: string;
    };

    Members

    • minimumFractionDigitsproperty
      number
    • maximumFractionDigitsproperty
      number
    • prefixproperty
      string
    • suffixproperty
      string

    IRedactSecretsOptions

    type

    the options accepted by redactSecrets

    Declaration
    type IRedactSecretsOptions = {
        patterns?: readonly RegExp[];
        replacement?: string;
        preserveLineBreaks?: boolean;
    };

    Members

    • patternsproperty
      readonly RegExp[]

      the secrets to find, after the private keys. Defaults to SECRET_TOKEN_PATTERNS

    • replacementproperty
      string

      what each secret becomes. Defaults to '[redacted]'

    • preserveLineBreaksproperty
      boolean

      whether a private key keeps its line breaks, so the text's line numbers stay the same

    IRedactSecretsResult

    type

    the text redactSecrets returns, and how many secrets it replaced

    Declaration
    type IRedactSecretsResult = {
        text: string;
        count: number;
    };

    Members

    • textproperty
      string
    • countproperty
      number

    IRequestCoordinator

    type

    runs tasks within a concurrency limit and a bounded queue, and pauses them during a cooldown

    Declaration
    type IRequestCoordinator = {
        run: <T>(task: () => Promise<T>, options?: IRunRequestOptions) => Promise<T>;
        deferUntil: (deadline: Date | number) => void;
        isIdle: () => boolean;
        close: () => void;
    };

    Members

    • runproperty
      (task: () => Promise<T>, options?: IRunRequestOptions) => Promise<T>

      runs the task once a slot is free and no cooldown is active, and settles as it does

    • deferUntilproperty
      (deadline: Date | number) => void

      pauses queued tasks until the deadline, a Date or epoch milliseconds, keeping a later one

    • isIdleproperty
      () => boolean

      whether no task runs or waits and no cooldown is active, such as before discarding it

    • closeproperty
      () => void

      rejects the waiting tasks and every later run, and lets the running ones finish

    IRequestCoordinatorOptions

    type

    the limits of createRequestCoordinator

    Declaration
    type IRequestCoordinatorOptions = {
        maxConcurrent: number;
        maxQueued: number;
    };

    Members

    • maxConcurrentproperty
      number

      how many tasks run at once, at least 1

    • maxQueuedproperty
      number

      how many tasks can wait for a slot, across every caller, at least 0

    IRetryAsyncFunctionOptions

    type

    the options that can be passed to the retryAsyncFunction function

    Declaration
    type IRetryAsyncFunctionOptions = {
        signal?: AbortSignal;
        shouldRetry?: (error: unknown) => boolean;
    };

    Members

    • signalproperty
      AbortSignal

      stops retrying and rejects with the signal's reason, even while an attempt is pending

    • shouldRetryproperty
      (error: unknown) => boolean

      decides whether a failed attempt is retried; returning false rethrows the error immediately

    IRunRequestOptions

    type

    the options of one task a request coordinator runs

    Declaration
    type IRunRequestOptions = {
        signal?: AbortSignal;
        caller?: unknown;
        maxQueuedForCaller?: number;
        rejectDuringCooldown?: boolean;
    };

    Members

    • signalproperty
      AbortSignal

      removes the task from the queue and rejects with the signal's reason when it aborts first

    • callerproperty
      unknown

      who the task runs for, compared with ===, so maxQueuedForCaller can limit each caller

    • maxQueuedForCallerproperty
      number

      how many of this caller's tasks can wait at once, at least 0

    • rejectDuringCooldownproperty
      boolean

      rejects with REQUEST_COOLDOWN_ACTIVE during a cooldown, instead of waiting it out

    ISchema

    type

    a validator for data from outside the program, such as a Zod schema: parse returns the data, or throws when it doesn't fit

    Declaration
    type ISchema<T> = {
        parse(value: unknown): T;
    };

    Members

    • parsemethod
      parse(value: unknown): T

    ISortDirection

    type

    the sort direction that can be applied to a list

    Declaration
    type ISortDirection = 'asc' | 'desc';

    ISubstitutionOptions

    type

    the options that can be passed to the applySubstitutions function

    Declaration
    type ISubstitutionOptions = {
        jsonIndent: number;
    };

    Members

    • jsonIndentproperty
      number

    ITimeString

    type

    a duration such as '2 days' or '30 minutes', which toMS converts to milliseconds

    Declaration
    type ITimeString = `${number} ${IUnit}`;

    IUtcDateRange

    type

    an inclusive range of UTC calendar dates, each as YYYY-MM-DD

    Declaration
    type IUtcDateRange = {
        fromDate: string;
        toDate: string;
    };

    Members

    • fromDateproperty
      string
    • toDateproperty
      string

    IUuidVersion

    type

    UUID Version The UUID versions supported by this library.

    Declaration
    type IUuidVersion = 4 | 7;

    IWaitUntilOptions

    type

    the options that can be passed to the waitUntil function

    Declaration
    type IWaitUntilOptions = {
        timeoutSeconds: number;
        intervalSeconds?: number;
        signal?: AbortSignal;
    };

    Members

    • timeoutSecondsproperty
      number

      the maximum number of seconds the whole call can take

    • intervalSecondsproperty
      number

      the number of seconds to wait between probes. Defaults to 1

    • signalproperty
      AbortSignal

      stops waiting and rejects with the signal's reason, even while a probe is pending