Server Setup: Eager Registration
Why Eager Registration Matters
Every format module in RelationalText registers its lexicon and lens lazily — the first call to from('mastodon', ...) or to('mastodon', ...) triggers a synchronous registration step that loads the lexicon into the WASM registry and adds the format's lens to the global lens graph. In a long-running server process, you want this work done once during application startup rather than on the first live request, where the latency would be visible to a user.
Eager registration also populates the lens graph's path cache up front. Without it, the first to('html', ...) call for an unfamiliar source format will pay the cost of a BFS path search; subsequent calls will hit the cache, but the warm-up happens at request time.
Required: initRelationalText()
initRelationalText() must be called and awaited before any other operation — including ensureXxxLexicon() calls. It loads and initializes the WASM binary. Calling it multiple times is safe; initialization only runs once.
import { initRelationalText } from 'relational-text'
await initRelationalText()Startup Block
Call ensureXxxLexicon() for every format your server will handle, directly after initRelationalText():
import { initRelationalText } from 'relational-text'
import { ensureMarkdownLexicon } from 'relational-text/markdown'
import { ensureHtmlLexicon } from 'relational-text/html'
import { ensureMastodonLexicon } from 'relational-text/mastodon'
import { ensureQuillLexicon } from 'relational-text/quill'
import { ensureSlackLexicon } from 'relational-text/slack'
export async function initServer(): Promise<void> {
await initRelationalText()
// Register WASM lexicons and lenses for all formats this server handles.
// These calls are synchronous and idempotent.
ensureMarkdownLexicon() // covers CommonMark and GFM
ensureHtmlLexicon() // WHATWG HTML element set
ensureMastodonLexicon() // Mastodon → RelationalText lens (autoApply)
ensureQuillLexicon() // Quill Delta → RelationalText lens (autoApply)
ensureSlackLexicon() // Slack mrkdwn → RelationalText lens (autoApply)
}Call initServer() once at the top of your entry point and wait for it to resolve before accepting requests:
// server.ts
import { initServer } from './startup.js'
import { createServer } from './app.js'
await initServer()
const server = createServer()
server.listen(3000)What Each ensure Call Does
Each ensureXxxLexicon() function does three things, exactly once:
- Registers the format's lexicon with the WASM runtime (feature classes and expand semantics)
- Registers the format's lens with the global
lensGraphwithautoApply: true - Sets a module-level flag so subsequent calls are no-ops
After ensureMastodonLexicon() returns, the lens graph has a path from org.joinmastodon.facet to org.relationaltext.facet. When to('html', ...) is later called on a Mastodon document, autoTransform finds and applies that path without any additional work.
Importing Is Not Enough
Importing a format module does not register its lens:
import 'relational-text/mastodon'
// The Mastodon lens is NOT yet in the graph.
// You must call ensureMastodonLexicon() explicitly.The ensure function is the only entry point that triggers registration. This is intentional — it gives you full control over what is loaded and when, which matters in edge function environments where you want to minimize cold-start cost by loading only the formats you actually use.
See Also
- Lens Graph — how lazy vs eager registration affects path caching,
autoApply, andautoTransform