@xyo-network/xl1-browser-system
v5.5.4
Published
Config-driven XL1 provider actor systems for browser runtimes
Downloads
4,361
Keywords
Readme
@xyo-network/xl1-browser-system
Config-driven XL1 provider actor systems for browser pages, workers, service workers, and extension background realms.
The package adapts XL1's provider catalog to browser-kit's neutral planner.
Configuration is resolved once, one XL1 ProviderFactoryLocator is provisioned
in the owner realm, and every selected actor receives that same resolved
provider system with its own actor configuration.
Install
Install the XL1 integration and only the realm adapters the application uses:
pnpm add @xyo-network/xl1-browser-system \
@ariestools/browser-kit-page \
@ariestools/browser-kit-worker \
@ariestools/browser-kit-service-worker \
@ariestools/browser-kit-pluginConfiguration
Create the configuration as data. The host selects which realm constructs the actor; it does not select a different provider graph for that actor.
import { createXl1RestBrowserSystemConfig } from '@xyo-network/xl1-browser-system'
export function xl1ConfigFor(host: string) {
return createXl1RestBrowserSystemConfig({
endpoint: 'https://sample.mainnet.xyo.space',
host,
})
}For an RPC-backed viewer, use the complete RPC URL:
import { createXl1RpcBrowserSystemConfig } from '@xyo-network/xl1-browser-system'
const config = createXl1RpcBrowserSystemConfig({
endpoint: 'https://api.example/rpc',
host: 'worker',
})The resulting object contains actor selections, named connections, and provider bindings. It contains no module paths or executable code.
Compile the data before acquiring runtime resources, then launch that exact plan:
import {
compileXl1BrowserSystem,
launchCompiledXl1BrowserSystem,
} from '@xyo-network/xl1-browser-system'
const compiled = compileXl1BrowserSystem({ config })
const session = await launchCompiledXl1BrowserSystem({ compiled })Compilation parses the XL1 config, selects actor declarations, and resolves one provider plan without constructing providers or actors. The compiled value retains the actor catalog and exact provider registrations, so it is an owner-realm artifact rather than structured-clone data. Attached realms receive only browser-kit's descriptor-free manifest and typed proxies.
launchXl1BrowserSystem remains the one-step convenience that composes compile
and launch. launchCompiledXl1BrowserSystem accepts runtime context, host,
identity, and readiness options, but cannot substitute another provider catalog
or registration set.
For local gateways that publish buckets under one path-based origin rather than
the standard blocks.*, state.*, and indexes.* subdomains, set
layout: 'path':
const localConfig = createXl1RestBrowserSystemConfig({
endpoint: 'https://chain.aries.test:8791',
host: 'page',
layout: 'path',
})Read-only and signed gateway systems
launchXl1BrowserGatewaySystem is the stock launcher for all four gateway
plans: REST or RPC, each read-only or signed. It creates the serializable config
once, supplies non-serializable signing state through runtime homes, launches
one provider system, and exposes its actor and gateway.
import { Account } from '@xyo-network/sdk'
import { launchXl1BrowserGatewaySystem } from '@xyo-network/xl1-browser-system'
const account = await Account.random()
const session = await launchXl1BrowserGatewaySystem({
endpoint: 'https://sample.mainnet.xyo.space',
host: 'page',
rpcUrl: 'https://sample.mainnet.xyo.space/rpc',
signerAccount: account,
transport: 'rest',
})
await session.gateway.connection.viewer?.block.currentBlockNumber()
if (session.gateway.moniker === 'XyoGatewayRunner') {
await session.gateway.signer.address()
}For an injected or remote signer, pass signerTransport; for a custom local
signer implementation, pass signerFactory and a bundle-stable
signerProviderId. Precedence is signerFactory, then signerAccount, then
signerTransport. Accounts, transports, and factories never enter the config.
The lower-level createXl1RestBrowserSystemConfig,
createXl1RpcBrowserSystemConfig, compileXl1BrowserSystem,
launchCompiledXl1BrowserSystem, and launchXl1BrowserSystem APIs remain
available when an application supplies its own actors or provider catalog.
When adding a custom provider candidate, pass a stable explicit identifier to
providerCandidateFromClass. Constructor names can be changed by production
minifiers and must not become configuration identifiers:
const candidate = providerCandidateFromClass(
MyBrowserProvider,
'com.example.my-browser-provider',
)Page
The page owns the system until navigation or discard:
import { bindPageLifecycle } from '@ariestools/browser-kit-page'
import {
compileXl1BrowserSystem,
launchCompiledXl1BrowserSystem,
Xl1BrowserSystemActor,
} from '@xyo-network/xl1-browser-system'
import { xl1ConfigFor } from './xl1Config.ts'
const compiled = compileXl1BrowserSystem({
config: xl1ConfigFor('page'),
})
const session = await launchCompiledXl1BrowserSystem({
compiled,
host: 'page',
})
bindPageLifecycle(session, {
onStopError: error => console.error('XL1 page system failed to stop', error),
})
const actor = session.actors.find(actor => actor instanceof Xl1BrowserSystemActor)
if (actor === undefined) throw new Error('XL1 page system actor was not created')
const gateway = await actor.getGateway()
const blockNumber = await gateway.connection.viewer?.block.currentBlockNumber()See the executable page example.
Web worker
The worker launches the same system and binds explicit shutdown handling:
/// <reference lib="webworker" />
import { bindWorkerShutdown } from '@ariestools/browser-kit-worker'
import {
compileXl1BrowserSystem,
launchCompiledXl1BrowserSystem,
} from '@xyo-network/xl1-browser-system'
import { xl1ConfigFor } from './xl1Config.ts'
const compiled = compileXl1BrowserSystem({
config: xl1ConfigFor('worker'),
})
const session = await launchCompiledXl1BrowserSystem({
compiled,
host: 'worker',
})
bindWorkerShutdown(self, session, {
onStopError: error => console.error('XL1 worker system failed to stop', error),
})Create it from the owning page with a module worker. Send
{ type: 'browser-kit:shutdown' } when the worker should stop and wait for the
browser-kit:stopped acknowledgement before terminating it.
const worker = new Worker(new URL('./xl1.worker.ts', import.meta.url), {
type: 'module',
})See the executable worker owner and page client.
Service worker
A service worker reconstructs the system once per browser-managed worker incarnation. Attach every operation to the triggering event lifetime:
/// <reference lib="webworker" />
import { ServiceWorkerSystemHost } from '@ariestools/browser-kit-service-worker'
import {
compileXl1BrowserSystem,
launchCompiledXl1BrowserSystem,
Xl1BrowserSystemActor,
} from '@xyo-network/xl1-browser-system'
import { xl1ConfigFor } from './xl1Config.ts'
const compiled = compileXl1BrowserSystem({
config: xl1ConfigFor('service-worker'),
})
const systemHost = new ServiceWorkerSystemHost(async () =>
await launchCompiledXl1BrowserSystem({
compiled,
host: 'service-worker',
identity: {
planId: 'my-xl1-service-worker:v1',
systemInstanceId: crypto.randomUUID(),
},
}))
self.addEventListener('message', (event) => {
if (event.data?.type !== 'xl1-current-block') return
void systemHost.dispatch(event, async (session) => {
const actor = session.actors.find(actor => actor instanceof Xl1BrowserSystemActor)
if (actor === undefined) throw new Error('XL1 service-worker actor was not created')
const gateway = await actor.getGateway()
event.source?.postMessage({
blockNumber: await gateway.connection.viewer?.block.currentBlockNumber(),
type: 'xl1-current-block-result',
})
})
})Register the module service worker from a page and communicate with its active
instance. Browser termination discards resident memory; the next event launches
the same plan with a new systemInstanceId.
import serviceWorkerUrl from './xl1.service-worker.ts?worker&url'
const registration = await navigator.serviceWorker.register(
serviceWorkerUrl,
{ type: 'module' },
)
registration.active?.postMessage({ type: 'xl1-current-block' })Timers are not durable service-worker triggers. Use browser events, alarms, or sync APIs, and keep durable state in providers rather than worker globals. See the executable service worker and registration client.
Browser plugin or extension
The extension background service worker owns the XL1 locator. Popups, side panels, and content scripts attach through an authorized extension port; they do not resolve a second provider system.
import { bindExtensionRuntimeBrowserSystemHost } from '@ariestools/browser-kit-plugin'
import { ServiceWorkerSystemHost } from '@ariestools/browser-kit-service-worker'
import type { XyoGateway } from '@xyo-network/xl1-sdk'
import { XyoGatewayMoniker } from '@xyo-network/xl1-sdk'
import {
compileXl1BrowserSystem,
launchCompiledXl1BrowserSystem,
} from '@xyo-network/xl1-browser-system'
const compiled = compileXl1BrowserSystem({ config })
const systemHost = new ServiceWorkerSystemHost(async () =>
await launchCompiledXl1BrowserSystem({
compiled,
host: 'extension-background',
identity: {
planId: 'my-extension-xl1:v1',
systemInstanceId: crypto.randomUUID(),
},
}))
bindExtensionRuntimeBrowserSystemHost(chrome.runtime, {
authorize: port =>
(port.sender as { id?: string } | undefined)?.id === chrome.runtime.id,
channelName: 'my-extension-xl1',
getSession: async () => await systemHost.session(),
handlers: {
[XyoGatewayMoniker]: {
currentBlockNumber: async ({ instance }) =>
await (instance as XyoGateway).connection.viewer?.block.currentBlockNumber(),
},
},
onError: error => console.error('XL1 extension system failed', error),
})The required authorize callback is application policy. planId expresses
compatibility and systemInstanceId detects stale clients; neither value
authenticates a caller. Only explicitly registered provider operations cross
the port.
The complete Manifest V3 fixture includes both sides of the connection:
Custody, permissions, storage, operation schemas, and sender policy remain application concerns.
Run the real-browser examples
The repository includes a production-minified Vite build and Playwright suite. It performs a typed block-number read in every realm and forces Chromium to terminate and reconstruct both the standard and extension service workers:
pnpm --filter @xyo-network/xl1-browser-system test:e2eBrowser-kit owns realm lifecycle and transport. This package owns only the XL1 provider catalog, locator provisioning, standard actor, and XL1 configuration helpers.
