The bridge, web side

The bridge, web side

The web half imports @peko/client. Importing it connects the bridge and sets window.peko, so one side-effect import is enough:

import '@peko/client'

The package is not on npm. The CLI stages it from the installed pekoui into .peko/client/pekoui/ and registers it in package.json on every build.

Calling native

import { peko } from '@peko/client'

const result = await peko.invoke('ide.projects.open', { path })

invoke waits for the connection, sends the call, and resolves with the parsed result. Errors reject with an Error carrying a code.

The namespace shorthand

peko is a proxy. Any property that is not a known member becomes a namespace, and any method on it becomes an invoke:

await peko.storage.get({ key: 'theme' })   // invokes "storage.get"
await peko.ide.build.start({})             // invokes "ide.build.start"

No client-side declaration is needed for a native handler.

One consequence: a property that is a known member shadows the shorthand. invoke, on, off, ready, connect, platform, bridgeStatus, titlebar, toolbar, menu, noDrag, control, window, and windows are all taken. A native namespace with one of those names needs the long form, peko.invoke("window.foo", params).

Subscribing to events

const off = peko.on('ide.fs.change', (data) => {
  console.log(data.path)
})
// later
off()

on returns its own unsubscribe function.

The payload is already parsed. Calling JSON.parse on it throws.

This is worth stating plainly because of how it fails. The dispatch loop wraps each listener in a try/catch so one bad listener cannot break the others, which means your exception is swallowed. The symptom is not an error in the console; it is events appearing never to arrive.

peko.on('menu', (data) => {
  const id = data?.id          // right
})

peko.on('menu', (raw) => {
  const d = JSON.parse(raw)    // wrong, and silently so
})

What else the SDK does at load

  • Applies platform classes to the root element and a viewport-fit meta on mobile.
  • Registers the peko-toolbar and peko-menu custom elements and the chrome styles.
  • Patches history.pushState and replaceState and listens for popstate, so every client-side navigation is reported to native. That is what makes App.route() accurate.
  • Reconnects with backoff, and refreshes the hosted bridge token periodically.

platform

peko.platform describes the host: os, mobile, desktop, frameless, nativeControls, windowControls, titlebarInset, and nativeMenu. Use it to decide whether to draw your own window controls.

Framework adapters

@peko/client/react provides usePlatform, useWindowControls, usePekoEvent, useNavigate, and Toolbar and Menu components. @peko/client/vue mirrors it. Both are optional; the attributes below work without them.