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.
Import
Section titled “Import”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';Signature
Section titled “Signature”export function ensureEngineReady(): Promise<void>;
export function ensureEngineReadySync(): void;
export function isEngineReady(): boolean;
export class EngineNotReadyError extends Error { readonly name = 'EngineNotReadyError';}Parameters
Section titled “Parameters”None. The initializers take no arguments; the entry point you import from selects the loading and decode strategy.
Returns
Section titled “Returns”| 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(); // trueparsePhoneNumber('+14155550132').formatE164(); // '+14155550132'Errors
Section titled “Errors”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.mdensureEngineReady 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.
Behavior
Section titled “Behavior”-
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
ensureEngineReadySyncat a CLI’s entry point andensureEngineReadyin 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:
DecompressionStreamon 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.
- Native: Node’s
-
Loading is consumer-triggered. No entry point loads the engine as an import side effect; nothing happens until you call an initializer.
Environment matrix
Section titled “Environment matrix”| 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. |
Examples
Section titled “Examples”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();Used in guides
Section titled “Used in guides”- Getting started: the first call in every setup.
- Load the engine: choosing an entry point and a load moment per environment.
- Drive an input: gating controller creation on engine readiness.
See also
Section titled “See also”- 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.