Skip to content

ensureEngineReady

ensureEngineReady loads the engine, the one deterministic automaton compiled from Google’s metadata, exactly once per process. The automaton’s compiled tables load once; every later call reads them synchronously.

The engine-gate functions import from @telixon/core. The package’s export conditions resolve the entry for your environment automatically: node picks the Node entry, browser picks the browser entry, and workerd / edge-light / worker pick the edge entry.

import { ensureEngineReady, isEngineReady, EngineNotReadyError } from '@telixon/core';

The synchronous initializer lives on a separate entry, so bundlers embed the engine payload only when you import it. Its node condition resolves the native-decode variant automatically.

import { ensureEngineReadySync } from '@telixon/core/sync-init';
export function ensureEngineReady(): Promise<void>;
export function ensureEngineReadySync(): void;
export function isEngineReady(): boolean;
export class EngineNotReadyError extends Error {
readonly name = 'EngineNotReadyError';
}

None. The initializers take no arguments; the entry point you import from selects the loading and decode strategy.

Function Returns Meaning
ensureEngineReady Promise<void> Resolves once the engine is decoded and ready.
ensureEngineReadySync void The engine is ready when the call returns.
isEngineReady boolean true after either initializer has completed.
import { ensureEngineReady, isEngineReady, parsePhoneNumber } from '@telixon/core';
isEngineReady(); // false
await ensureEngineReady();
isEngineReady(); // true
parsePhoneNumber('+14155550132').formatE164(); // '+14155550132'

Every query API throws EngineNotReadyError when called before an initializer has completed. The full message:

Telixon engine is not initialized.
Initialization is explicit. Call ensureEngineReady() before the first API call:
import { ensureEngineReady, parsePhoneNumber } from '@telixon/core';
await ensureEngineReady();
parsePhoneNumber('+12015550123');
For synchronous initialization, import ensureEngineReadySync from '@telixon/core/sync-init'.
Docs: https://github.com/martsinlabs/telixon/blob/main/docs/initialization.md

ensureEngineReady itself never throws EngineNotReadyError. It rejects when loading fails (for example, a failed fetch of an engine chunk in the browser); the rejection clears the in-flight state, so the next call starts a fresh load instead of returning the failed one.

  • Idempotent. The first call starts the load; concurrent calls await the same in-flight load rather than starting a second one. Once the engine is ready, every later call resolves immediately:

    await ensureEngineReady();
    let settled = false;
    void ensureEngineReady().then(() => {
    settled = true;
    });
    await Promise.resolve();
    settled; // true: after readiness, the promise settles on the next microtask
  • One engine per process. Both initializers ready the same process-wide engine, so ensureEngineReadySync at a CLI’s entry point and ensureEngineReady in a library it calls do not load twice. The mechanism is described in Engine.

  • Off-thread decode where the environment allows. The engine ships as gzipped layers; inflating them is the measurable part of initialization, and each entry point uses the fastest decode path its runtime offers:

    • Native: Node’s zlib, run off the libuv threadpool so the event loop never blocks.
    • Stream: DecompressionStream on the web and edge, inflating off the main thread; falls back to the pure path where the API is absent.
    • Pure: pure-JS base64 and gunzip that run in any runtime; the floor, and the default for the sync entry outside Node.
  • Loading is consumer-triggered. No entry point loads the engine as an import side effect; nothing happens until you call an initializer.

Environment Import Loading Decode path Choose when
Node @telixon/core dynamic import of the engine modules native zlib, off the libuv threadpool Server startup where you can await once.
Browser @telixon/core fetches code-split engine chunks on demand DecompressionStream, off the main thread Web apps; the engine stays out of the initial bundle and you pick the load moment.
Edge @telixon/core dynamic import inside a request DecompressionStream workerd, edge-light, and worker runtimes that allow async work per request.
Sync entry @telixon/core/sync-init engine modules statically bundled native zlib on Node, pure JS elsewhere CLIs, tests, edge global scope, or any code path that cannot await.

Await once at startup, then query freely:

import { ensureEngineReady, parsePhoneNumber } from '@telixon/core';
await ensureEngineReady();
parsePhoneNumber('+14155550132').formatE164(); // '+14155550132'

Synchronous initialization for CLIs and tests. The static import embeds the engine payload in the bundle and the decode blocks the current thread, so reserve this entry for code that cannot await:

import { ensureEngineReadySync } from '@telixon/core/sync-init';
import { parsePhoneNumber } from '@telixon/core';
ensureEngineReadySync();
parsePhoneNumber('+14155550132').formatNational(); // '(415) 555-0132'

Guard a conditional flow with isEngineReady when a code path may run before initialization completes:

import { isEngineReady, parsePhoneNumber } from '@telixon/core';
function tryFormatNational(raw: string): string {
if (!isEngineReady()) return raw;
return parsePhoneNumber(raw, { defaultRegion: 'US' }).formatNational();
}
tryFormatNational('415 555 0132'); // '415 555 0132' while the engine is loading
// after await ensureEngineReady():
tryFormatNational('415 555 0132'); // '(415) 555-0132'

Pitfall: a query at module scope runs at import time, before any initializer has had a chance to complete:

import { parsePhoneNumber } from '@telixon/core';
// Runs during module evaluation: throws EngineNotReadyError.
const formatted = parsePhoneNumber('+14155550132').formatE164();
  • parsePhoneNumber: the batch query on the shared resolve layer; it is the API most commonly called right after the gate.
  • The model: why initialization is a single explicit gate rather than lazy per-call loading.
  • Engine: what the compiled tables contain and how the layers are assembled.