Pier

ePWA bridge reference 3.0

Every method, event, error and permission a Pier app can use. Generated from the machine-readable spec the runtime is tested against, so this page cannot drift from the code.

Types are wire types: string, number, integer, boolean, bytes ({data, encoding}), handle ({id, name, kind}). The result column is what the method returns before the window.epwa wrapper unpacks it — epwa.fs.list hands your code items, not the whole object.

Envelope

Every call is one message in, one message out.

Binary values travel as {data, encoding} with encoding either utf8 or base64; the wrapper turns base64 into a Uint8Array and back. A missing value is an explicit null, never an omitted key.

Window methods

Available without any manifest permission.

epwa.ping

Liveness check of the bridge.

Result
{ pong: boolean }

epwa.getInfo

Runtime, API version, platform and capabilities.

Result
{ runtime: string, apiVersion: string, platform: string, osVersion: string, capabilities: string[], permissions: string[], mode: dev | app | pier }

epwa.setDragRegions

Push the page's --app-region rectangles to the host.

Parameters
drag?: Rect[], noDrag?: Rect[]
Result
{ count: integer }

epwa.drag.setSources

Declare the page areas that can be dragged out of the window.

Parameters
sources?: DragSource[]
Result
{ count: integer }
Errors
E_BAD_PARAMS, E_DENIED

epwa.getTrafficLights

Current traffic-light buttons state.

Result
TrafficLights

epwa.setTrafficLights

Move, hide or recolor the traffic-light buttons.

Parameters
visible?: boolean, offsetX?: number, offsetY?: number, color?: light | dark | auto
Result
TrafficLights

epwa.getTitlebarArea

Titlebar area in CSS px (like env(titlebar-area-*)).

Result
Rect

epwa.getWindowState

Focus, zoom, fullscreen and size of the window.

Result
WindowState

epwa.maximize

Zoom the window to the visible screen frame.

Result
{}

epwa.unmaximize

Return the window to its pre-zoom frame.

Result
{}

epwa.minimize

Miniaturize the window into the Dock.

Result
{}

epwa.close

Close the window; force: true bypasses the close guard.

Parameters
force?: boolean = false
Result
{ closed: boolean }

epwa.setCloseGuard

Intercept window close and ⌘Q; the page gets close-request.

Parameters
enabled?: boolean = false
Result
{ enabled: boolean }

epwa.setBackgroundMode

Closing the window hides it; the process keeps running.

Parameters
enabled?: boolean = false
Result
{ enabled: boolean }

epwa.showWindow

Show a hidden or minimized window and activate the app.

Result
{}

epwa.setMenu

Page menus inserted into the main menu bar.

Parameters
menus?: MenuSpec[]
Result
{ count: integer }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.setDockMenu

Dock icon menu.

Parameters
items?: MenuItem[]
Result
{ count: integer }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.setWindowSize

Content size in points; the top-left corner stays put.

Parameters
width: number, height: number, animate?: boolean = true
Result
{ width: number, height: number }
Errors
E_BAD_PARAMS

epwa.setMinWindowSize

Minimum content size (480×320 by default).

Parameters
width: number, height: number
Result
{ width: number, height: number }
Errors
E_BAD_PARAMS

epwa.useWindowFrame

Window position slot: each mode remembers its own frame.

Parameters
name?: string, width?: number, height?: number, animate?: boolean = true
Result
{ name: string }
Errors
E_BAD_PARAMS

epwa.setAlwaysOnTop

Keep the window above the others.

Parameters
enabled?: boolean = false
Result
{ enabled: boolean }

epwa.setFullScreen

Native full screen; fires fullscreenenter/exit.

Parameters
enabled?: boolean = false
Result
{ enabled: boolean }

epwa.setDockIcon

Dock icon from a page image; '' resets it.

Parameters
url?: string
Result
{ reset: boolean }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.setStatusItem

Menu bar item; null removes it.

Parameters
item?: StatusItemSpec | null
Result
{ visible: boolean }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.setWindowMaterial

Window glass material; null is an ordinary opaque window.

Parameters
material?: hud | popover | menu | sidebar | sheet | titlebar | headerView | underWindow | windowBackground | contentBackground | fullScreenUI | tooltip | clear | null, appearance?: auto | dark | light = "auto"
Result
{ material: string | null }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.getWindowCorners

Current corner radius and the system one.

Result
{ radius: number | null, systemRadius: number }
Errors
E_UNAVAILABLE

epwa.setWindowCorners

Round the window corners; 'system' or null restores the system shape.

Parameters
radius?: number | system | null
Result
{ radius: number | null, systemRadius: number }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.setDockProgress

Progress bar over the Dock icon; null removes it.

Parameters
value?: number | null, color?: string
Result
{ value: number | null }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.setGlobalShortcuts

System-wide hotkeys; the set is replaced as a whole.

Parameters
shortcuts?: ShortcutSpec[]
Result
{ registered: string[], failed: string[] }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.showContextMenu

Native context menu at a page point; resolves after it closes.

Parameters
items?: MenuItem[], x?: number = 0, y?: number = 0
Result
{ id: string | null }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.copyToClipboard

Put text on the general pasteboard.

Parameters
text: string
Result
{ length: integer }
Errors
E_BAD_PARAMS

epwa.haptic

Force Touch trackpad feedback.

Parameters
pattern?: generic | alignment | levelChange | level = "generic"
Result
{ pattern: string }
Errors
E_BAD_PARAMS

epwa.setAbout

Page additions to the About panel.

Parameters
details?: string[], links?: AboutLink[], accent?: string
Result
{ details: integer, links: integer }
Errors
E_BAD_PARAMS, E_UNAVAILABLE

epwa.print

System print dialog for the page.

Result
{}
Errors
E_UNAVAILABLE

epwa.setFindHandling

The page takes ⌘F for its own search; reset to false on navigation.

Parameters
page?: boolean = false
Result
{ page: boolean }

epwa.setSettingsHandling

Standard “Settings…” (⌘,) item in the app menu; choosing it sends the settings event.

Parameters
enabled?: boolean = false
Result
{ enabled: boolean }

epwa.setNavigationGestures

Two-finger back/forward swipes; off by default.

Parameters
enabled?: boolean = false
Result
{ enabled: boolean }

Native modules

permissions.*

What the manifest declares and what the user allowed.

No manifest permission needed.

epwa.permissions.query

State of one permission without asking the user.

Parameters
name: string
Result
PermissionState
Errors
E_BAD_PARAMS

epwa.permissions.request

Ask for consent up front (for permissions that have a question).

Parameters
name: string
Result
PermissionState
Errors
E_BAD_PARAMS

epwa.permissions.list

All known permissions with their states.

Result
{ permissions: PermissionState[] }

dialog.*

System sheets: message, confirmation, text input, open and save panels.

No manifest permission needed.

epwa.dialog.alert

Message with up to 4 buttons.

Parameters
title?: string, message?: string, style?: info | warning | critical = "info", buttons?: string[]
Result
{ button: integer }
Errors
E_BAD_PARAMS

epwa.dialog.confirm

Yes/no question.

Parameters
title?: string, message?: string, ok?: string, cancel?: string, destructive?: boolean = false
Result
{ confirmed: boolean }
Errors
E_BAD_PARAMS

epwa.dialog.prompt

Single-line text input.

Parameters
title?: string, message?: string, defaultValue?: string, placeholder?: string, secure?: boolean = false
Result
{ value: string | null }
Errors
E_BAD_PARAMS

epwa.dialog.open

Open panel; the chosen files or folders become handles.

Parameters
title?: string, message?: string, button?: string, multiple?: boolean = false, directories?: boolean = false, types?: string[]
Result
{ items?: Handle[], cancelled?: boolean }
Permission
files
Errors
E_BAD_PARAMS, E_DENIED

epwa.dialog.save

Save panel; the file may not exist yet.

Parameters
title?: string, message?: string, button?: string, suggestedName?: string, types?: string[]
Result
{ item?: Handle, cancelled?: boolean }
Permission
files
Errors
E_BAD_PARAMS, E_DENIED

fs.*

Files inside handles the user picked and in the app's own folder.

Needs files in the manifest.

epwa.fs.appData

Handle of the app's private folder.

Result
Handle
Permission
files

epwa.fs.handles

Handles issued earlier; they survive restarts.

Result
{ items: Handle[] }
Permission
files

epwa.fs.forget

Drop a stored handle.

Parameters
handle: handle
Result
{}
Permission
files
Errors
E_BAD_PARAMS

epwa.fs.exists

Does the path exist inside the handle.

Parameters
handle: handle, path?: string
Result
{ exists: boolean }
Permission
files
Errors
E_BAD_PARAMS, E_DENIED

epwa.fs.stat

Name, kind, size and dates.

Parameters
handle: handle, path?: string
Result
StatEntry
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.list

Directory contents sorted by name (up to 10 000 entries).

Parameters
handle: handle, path?: string, hidden?: boolean = false
Result
{ items: DirEntry[], truncated: boolean }
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.read

Read a file or a slice of it; up to 64 MB per call.

Parameters
handle: handle, path?: string, as?: utf8 | base64 = "base64", offset?: integer = 0, length?: integer
Result
{ data: string, encoding: utf8 | base64, size: integer }
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.write

Write a file atomically (or append); missing folders are created.

Parameters
handle: handle, path?: string, data: bytes, encoding?: utf8 | base64 = "utf8", append?: boolean = false
Result
{ size: integer }
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.mkdir

Create a directory with its intermediates.

Parameters
handle: handle, path: string
Result
{}
Permission
files
Errors
E_BAD_PARAMS, E_DENIED

epwa.fs.remove

Move to the Trash (or delete for good with trash: false).

Parameters
handle: handle, path?: string, trash?: boolean = true
Result
{}
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.move

Move inside the handle or into another handle.

Parameters
handle: handle, from: string, to: string, toHandle?: handle, overwrite?: boolean = false
Result
{}
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.copy

Copy inside the handle or into another handle.

Parameters
handle: handle, from: string, to: string, toHandle?: handle, overwrite?: boolean = false
Result
{}
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.reveal

Show the item in Finder.

Parameters
handle: handle, path?: string
Result
{}
Permission
files
Errors
E_BAD_PARAMS, E_DENIED

epwa.fs.watch

Watch a folder or file; changes arrive as fs-change. No subfolders.

Parameters
handle: handle, path?: string
Result
{ watch: string }
Permission
files
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.fs.unwatch

Stop watching.

Parameters
watch: string
Result
{}
Permission
files
Errors
E_BAD_PARAMS

launch.*

Files the app was opened with (file_handlers); no "files" permission needed.

No manifest permission needed.

launch.read

Read a launch file by its handle; up to 64 MB.

Used by a shim, not called directly.

Parameters
handle: handle, as?: utf8 | base64 = "base64", offset?: integer = 0, length?: integer
Result
{ data: string, encoding: utf8 | base64, size: integer }
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

net.*

HTTP without CORS, TCP/TLS/UDP sockets, Bonjour discovery, incoming connections, network status.

Needs network in the manifest.

epwa.net.status

Network status; no permission required.

Result
NetStatus

epwa.net.watchStatus

Subscribe to network-change and return the current status.

Result
NetStatus

epwa.net.fetch

HTTP request without CORS; its own in-memory cookies; up to 64 MB.

Parameters
url: string, method?: string = "GET", headers?: map<string, string>, body?: bytes, bodyEncoding?: utf8 | base64 = "utf8", redirect?: follow | manual = "follow", timeout?: number = 60, as?: utf8 | base64 = "utf8"
Result
{ status: integer, url: string, headers: map<string, string>, data: string, encoding: utf8 | base64 }
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.net.connect

Open a TCP/TLS/UDP socket; up to 64 at a time.

Parameters
host: string, port: integer, protocol?: tcp | udp = "tcp", tls?: boolean = false, timeout?: number = 15
Result
{ socket: string }
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.net.send

Send bytes or text into an open socket.

Parameters
socket: string, data: bytes, encoding?: utf8 | base64 = "utf8"
Result
{ sent: integer }
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.net.close

Close a socket; socket-close follows.

Parameters
socket: string
Result
{}
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED

epwa.net.browse

Browse the local network for a Bonjour service type declared in the manifest.

Parameters
type: string, domain?: string
Result
{ browse: string }
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.net.resolve

Resolve a found service to an address, port and TXT record.

Parameters
browse: string, name: string, timeout?: number = 10
Result
{ host: string, port: integer, addresses: string[], txt: map<string, string> }
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.net.stopBrowse

Stop a browse; no more net-service-found events.

Parameters
browse: string
Result
{}
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED

epwa.net.listen

Accept incoming connections; loopback by default, "lan" asks the user separately.

Parameters
port?: integer = 0, protocol?: tcp | udp = "tcp", interface?: loopback | lan = "loopback", advertise?: { name: string, type: string, txt?: map<string, string> }, timeout?: number = 10
Result
{ listener: string, port: integer }
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.net.sendTo

Send a datagram back to a peer the UDP listener already heard from.

Parameters
listener: string, host: string, port: integer, data: bytes, encoding?: utf8 | base64 = "utf8"
Result
{ sent: integer }
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.net.stopListen

Stop a listener; accepted TCP sockets stay open.

Parameters
listener: string
Result
{}
Permission
network, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED

serial.*

Serial ports (USB adapters, Arduino); the user picks the port.

Needs serial in the manifest.

epwa.serial.getPorts

Ports chosen earlier and connected now.

Result
{ ports: SerialPort[] }
Permission
serial
Errors
E_DENIED

epwa.serial.requestPort

Ask the user to pick a port.

Parameters
filters?: UsbFilter[]
Result
SerialPort
Permission
serial
Errors
E_DENIED, E_UNAVAILABLE, E_CANCELLED

epwa.serial.forget

Forget the port choice and close it.

Parameters
port: string
Result
{}
Permission
serial
Errors
E_BAD_PARAMS, E_DENIED

epwa.serial.open

Open the port exclusively; then serial-data / serial-close.

Parameters
port: string, baudRate?: integer = 9600, dataBits?: integer = 8, stopBits?: integer = 1, parity?: none | even | odd = "none", flowControl?: none | hardware | software = "none"
Result
{}
Permission
serial
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.serial.write

Write bytes or text to the port.

Parameters
port: string, data: bytes, encoding?: utf8 | base64 = "utf8"
Result
{ written: integer }
Permission
serial
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.serial.setSignals

Set DTR / RTS / break (an Arduino reset, for example).

Parameters
port: string, dtr?: boolean, rts?: boolean, brk?: boolean
Result
{}
Permission
serial
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.serial.close

Close the port.

Parameters
port: string
Result
{}
Permission
serial
Errors
E_BAD_PARAMS, E_DENIED

usb.*

USB devices without a system driver (like WebUSB).

Needs usb in the manifest.

epwa.usb.getDevices

Devices chosen earlier and connected now.

Result
{ devices: UsbDevice[] }
Permission
usb
Errors
E_DENIED

epwa.usb.requestDevice

Ask the user to pick a device.

Parameters
filters?: UsbFilter[]
Result
UsbDevice
Permission
usb
Errors
E_DENIED, E_UNAVAILABLE, E_CANCELLED

epwa.usb.forget

Forget the device choice.

Parameters
device: string
Result
{}
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.open

Open the device.

Parameters
device: string
Result
{}
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.close

Close the device.

Parameters
device: string
Result
{}
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.selectConfiguration

Select a USB configuration.

Parameters
device: string, value: integer
Result
{}
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.claimInterface

Claim an interface.

Parameters
device: string, interface: integer
Result
{}
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.releaseInterface

Release an interface.

Parameters
device: string, interface: integer
Result
{}
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.controlTransferIn

Control transfer, device → page.

Parameters
device: string, requestType?: standard | class | vendor = "vendor", recipient?: device | interface | endpoint | other = "device", request: integer, value?: integer = 0, index?: integer = 0, length: integer, timeout?: number = 5
Result
Binary
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.controlTransferOut

Control transfer, page → device.

Parameters
device: string, requestType?: standard | class | vendor = "vendor", recipient?: device | interface | endpoint | other = "device", request: integer, value?: integer = 0, index?: integer = 0, data: bytes, encoding?: utf8 | base64 = "base64", timeout?: number = 5
Result
{ written: integer }
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.transferIn

Bulk/interrupt transfer, device → page (endpoint 1…15).

Parameters
device: string, endpoint: integer, length: integer, timeout?: number = 5
Result
Binary
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.usb.transferOut

Bulk/interrupt transfer, page → device.

Parameters
device: string, endpoint: integer, data: bytes, encoding?: utf8 | base64 = "base64", timeout?: number = 5
Result
{ written: integer }
Permission
usb
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

hid.*

HID devices you choose (like WebHID); keyboards, pointing devices and security keys are never offered.

Needs hid in the manifest.

epwa.hid.getDevices

Devices chosen earlier and connected now.

Result
{ devices: HidDevice[] }
Permission
hid
Errors
E_DENIED

epwa.hid.requestDevice

Ask the user to pick a device.

Parameters
filters?: HidFilter[]
Result
HidDevice
Permission
hid
Errors
E_DENIED, E_UNAVAILABLE, E_CANCELLED

epwa.hid.forget

Forget the device choice.

Parameters
device: string
Result
{}
Permission
hid
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.hid.open

Open the device.

Parameters
device: string
Result
{}
Permission
hid
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.hid.close

Close the device.

Parameters
device: string
Result
{}
Permission
hid
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.hid.sendReport

Send an output report.

Parameters
device: string, reportId?: integer = 0, data: bytes, encoding?: utf8 | base64 = "base64"
Result
{ written: integer }
Permission
hid
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.hid.sendFeatureReport

Send a feature report.

Parameters
device: string, reportId?: integer = 0, data: bytes, encoding?: utf8 | base64 = "base64"
Result
{ written: integer }
Permission
hid
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.hid.receiveFeatureReport

Read a feature report.

Parameters
device: string, reportId?: integer = 0
Result
Binary
Permission
hid
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

bluetooth.*

Bluetooth LE, like Web Bluetooth: the user picks the device.

Needs bluetooth in the manifest.

epwa.bluetooth.getAvailability

Is Bluetooth LE available and in what state.

Result
{ available: boolean, state: poweredOn | poweredOff | unauthorized | unsupported | resetting | unknown }
Permission
bluetooth
Errors
E_DENIED, E_UNAVAILABLE

epwa.bluetooth.requestDevice

Scan and let the user pick a device.

Parameters
filters?: BluetoothFilter[], optionalServices?: string[]
Result
BluetoothDevice
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE, E_CANCELLED

epwa.bluetooth.getDevices

Devices chosen earlier.

Result
{ devices: BluetoothDevice[] }
Permission
bluetooth
Errors
E_DENIED, E_UNAVAILABLE

epwa.bluetooth.forget

Forget the device and disconnect.

Parameters
device: string
Result
{}
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.bluetooth.connect

Connect and discover the allowed services.

Parameters
device: string, timeout?: number = 15
Result
{ services: BluetoothService[] }
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.bluetooth.disconnect

Disconnect from the device.

Parameters
device: string
Result
{}
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.bluetooth.read

Read a characteristic value.

Parameters
device: string, service: string, characteristic: string, timeout?: number = 10
Result
Binary
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.bluetooth.write

Write a characteristic value.

Parameters
device: string, service: string, characteristic: string, data: bytes, encoding?: utf8 | base64 = "base64", withResponse?: boolean = true, timeout?: number = 10
Result
{ written: integer }
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.bluetooth.startNotifications

Subscribe to characteristic values (bluetooth-value).

Parameters
device: string, service: string, characteristic: string, timeout?: number = 10
Result
{}
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.bluetooth.stopNotifications

Unsubscribe from characteristic values.

Parameters
device: string, service: string, characteristic: string, timeout?: number = 10
Result
{}
Permission
bluetooth
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

midi.*

MIDI devices through CoreMIDI; the base of the Web MIDI shim.

Needs midi in the manifest.

epwa.midi.access

Port lists and the clock origin; sysex: true asks for a separate consent.

Parameters
sysex?: boolean = false
Result
{ inputs: MidiPort[], outputs: MidiPort[], sysex: boolean, now: number }
Permission
midi, plus a question to the person
Errors
E_DENIED, E_UNAVAILABLE

epwa.midi.open

Open a MIDI input; messages arrive as midi-message. Up to 32 at a time.

Parameters
port: string
Result
{}
Permission
midi, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.midi.close

Close a MIDI input.

Parameters
port: string
Result
{}
Permission
midi, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED

epwa.midi.send

Send messages to an output; up to 64 KB, SysEx only after midi.access({sysex: true}).

Parameters
port: string, data: bytes, encoding?: utf8 | base64 = "base64", timestamp?: number
Result
{ sent: integer }
Permission
midi, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

power.*

Keep the system (or display) awake; power source, battery, user idle time and system events.

No manifest permission needed.

epwa.power.preventSleep

Take a sleep assertion; hold the token while the work lasts.

Parameters
display?: boolean = false, reason?: string
Result
{ token: string }
Errors
E_UNAVAILABLE

epwa.power.allowSleep

Release the assertion.

Parameters
token: string
Result
{}
Errors
E_BAD_PARAMS

epwa.power.status

Power source and battery level.

Result
{ source: ac | battery, battery?: { level: number, charging: boolean } }

epwa.power.idleTime

Seconds since the last user input, rounded and throttled to once a second.

Result
{ seconds: number }

epwa.power.watchSystem

Subscribe to sleep, wake, display and screen-lock events.

Result
{}

epwa.power.unwatchSystem

Unsubscribe from the system events.

Result
{}

location.*

CoreLocation fixes in the W3C shape.

Needs location in the manifest.

epwa.location.getCurrentPosition

One position fix.

Parameters
accuracy?: fine | coarse = "fine", timeout?: number = 15, maximumAge?: number = 0
Result
Position
Permission
location, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.location.watchPosition

Subscribe to location-update / location-error; up to 16 watches.

Parameters
accuracy?: fine | coarse = "fine", timeout?: number = 15, maximumAge?: number = 0
Result
{ token: string }
Permission
location, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.location.clearWatch

Cancel a watch.

Parameters
token: string
Result
{}
Permission
location, plus a question to the person
Errors
E_BAD_PARAMS, E_DENIED

notifications.*

macOS notifications with buttons, a reply field, attachments and scheduling.

Needs notifications in the manifest.

epwa.notifications.getPermission

System notification authorization state.

Result
{ state: granted | denied | prompt }
Permission
notifications
Errors
E_DENIED, E_UNAVAILABLE

epwa.notifications.requestPermission

Ask the system for notification authorization.

Result
{ state: granted | denied | prompt }
Permission
notifications
Errors
E_DENIED, E_UNAVAILABLE

epwa.notifications.show

Show (or schedule) a notification; the same id replaces the previous one.

Parameters
title: string, body?: string, subtitle?: string, sound?: boolean = true, id?: string, actions?: NotificationAction[], replyButton?: { title?: string }, reply?: boolean = false, attachments?: NotificationAttachment[], schedule?: NotificationSchedule
Result
{ id: string }
Permission
notifications
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.notifications.clear

Remove a notification by id, or all of them.

Parameters
id?: string
Result
{}
Permission
notifications
Errors
E_DENIED, E_UNAVAILABLE

secrets.*

Strings in the app's own Keychain service.

No manifest permission needed.

epwa.secrets.set

Store a value (up to 64 KB).

Parameters
key: string, value: string, protected?: boolean = false
Result
{}
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.secrets.get

Read a value; null when there is none.

Parameters
key: string, reason?: string
Result
{ value: string | null }
Errors
E_BAD_PARAMS, E_CANCELLED, E_DENIED, E_UNAVAILABLE

epwa.secrets.delete

Remove a value.

Parameters
key: string
Result
{}
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.secrets.keys

All stored keys, sorted.

Result
{ keys: string[], protected: string[] }
Errors
E_DENIED, E_UNAVAILABLE

auth.*

System owner check (Touch ID, falling back to the account password) — no manifest permission.

No manifest permission needed.

epwa.auth.available

Whether the system can ask (Touch ID or account password).

Result
{ biometry: touchID | none, canAuthenticate: boolean }

epwa.auth.confirm

Ask the system to confirm it's the Mac's owner; the system shows reason.

Parameters
reason?: string
Result
{ ok: boolean }
Errors
E_CANCELLED, E_DENIED, E_UNAVAILABLE

clipboard.*

System pasteboard: multiple representations, reading, file handles.

No manifest permission needed.

epwa.clipboard.write

Replace the clipboard with several representations of the same content.

Parameters
items: ClipboardItem[]
Result
{ count: integer }
Errors
E_BAD_PARAMS

epwa.clipboard.read

Read the clipboard; empty and concealed: true when it holds a password manager's hidden content.

Parameters
types?: string[]
Result
{ items: ClipboardItem[], concealed: boolean }
Permission
clipboard-read, plus a question to the person
Errors
E_DENIED

epwa.clipboard.types

Which representations are available, without reading content.

Result
{ types: string[], concealed: boolean }
Permission
clipboard-read, plus a question to the person
Errors
E_DENIED

epwa.clipboard.clear

Empty the clipboard.

Result
{}

app.*

Dock badge, attention, external links, sharing, launch at login, storage reset.

No manifest permission needed.

epwa.app.setBadge

Dock badge text; empty removes it.

Parameters
text?: string
Result
{ text: string }

epwa.app.requestAttention

Bounce the Dock icon.

Parameters
critical?: boolean = false
Result
{}

epwa.app.openExternal

Open a link in the system: http(s), mailto:, tel:, facetime:, sms:.

Parameters
url: string
Result
{ opened: boolean }
Errors
E_BAD_PARAMS

epwa.app.share

System share sheet at a point of the window.

Parameters
text?: string, url?: string, files?: handle[], x?: number, y?: number
Result
{ items: integer }
Errors
E_BAD_PARAMS, E_DENIED, E_UNAVAILABLE

epwa.app.clearData

Clear the app's whole website storage (all origins).

Parameters
types?: cookies | diskCache | localStorage | sessionStorage | indexedDB | serviceWorkers | cacheStorage[]
Result
{ cleared: integer }
Errors
E_BAD_PARAMS

epwa.app.getLaunchAtLogin

Launch at login state.

Result
LaunchAtLogin
Errors
E_UNAVAILABLE

epwa.app.setLaunchAtLogin

Turn launch at login on or off.

Parameters
enabled?: boolean = false
Result
LaunchAtLogin
Errors
E_UNAVAILABLE

Events

epwa.on(event, handler) returns an unsubscribe function.

EventWhat it meansPayload
readyThe bridge answered the bootstrap handshake.{ apiVersion: string }
titlebarareachangeThe titlebar area changed (resize).Rect
themechangeThe system appearance changed.{ scheme: dark | light }
maximizeThe window was zoomed.{ manual?: boolean }
unmaximizeThe window left the zoomed frame.{ manual?: boolean }
fullscreenenterThe window entered full screen.{}
fullscreenexitThe window left full screen.{}
focusThe window became key.{}
blurThe window lost key status.{}
close-requestClose was intercepted by the close guard. Turned on by setCloseGuard.{ reason: close | quit }
hideThe window was hidden by closing it in background mode. Turned on by setBackgroundMode.{}
showThe window came back.{}
menuA page menu, Dock menu or status item entry was chosen. Turned on by setMenu.{ id: string, source: menu | dock | status }
settingsThe Settings… item (or ⌘,) was chosen. Turned on by setSettingsHandling.{}
shortcutA global hotkey fired. Turned on by setGlobalShortcuts.{ id: string }
notification-clickThe user clicked a notification. Turned on by notifications.show.{ id: string }
notification-actionAn action button was pressed. Turned on by notifications.show.{ id: string, actionId: string }
notification-replyThe user typed a quick reply. Turned on by notifications.show.{ id: string, text: string }
downloadA WebKit download changed state.{ name: string, state: started | finished | failed, error?: string }
popup-blockedwindow.open was blocked.{ url: string, reason: no-user-gesture | too-many-popups | nested-popup | foreign-frame }
launch-filesThe app was opened with files (feeds the launchQueue shim).{ files: Handle[], batch?: string }
files-droppedFiles or folders were dropped on the window (handles for epwa.fs).{ files: Handle[], x: number, y: number }
drag-endA drag session started from the window ended.{ operation: none | copy | move | link }
fs-changeA watched file or folder changed. Turned on by fs.watch.{ watch: string, event: write | delete | rename | attrib }
network-changeThe network path changed. Turned on by net.watchStatus.NetStatus
socket-dataBytes arrived on a socket. Turned on by net.connect.{ socket: string, data: bytes }
socket-closeA socket closed. Turned on by net.connect.{ socket: string, error?: string }
net-service-foundA Bonjour service appeared on the local network. Turned on by net.browse.{ browse: string, service: NetService }
net-service-lostA Bonjour service disappeared. Turned on by net.browse.{ browse: string, service: NetService }
net-connectionA listener accepted an incoming connection. Turned on by net.listen.{ listener: string, socket: string, remote: { host: string, port: integer } }
net-datagramA datagram arrived at a UDP listener. Turned on by net.listen.{ listener: string, data: bytes, remote: { host: string, port: integer } }
serial-dataBytes arrived from a serial port. Turned on by serial.open.{ port: string, data: bytes }
serial-closeThe port closed, including when the adapter was unplugged. Turned on by serial.open.{ port: string, error?: string }
usb-connectA chosen USB device was plugged in. Turned on by usb.getDevices.{ device: UsbDevice }
usb-disconnectA chosen USB device was unplugged. Turned on by usb.getDevices.{ device: UsbDevice }
hid-inputreportAn input report arrived from an open HID device. Turned on by hid.open.{ device: string, reportId: integer, data: bytes }
hid-connectA chosen HID device was plugged in. Turned on by hid.getDevices.{ device: HidDevice }
hid-disconnectA chosen HID device was unplugged. Turned on by hid.getDevices.{ device: HidDevice }
bluetooth-valueA subscribed characteristic sent a value. Turned on by bluetooth.startNotifications.{ device: string, service: string, characteristic: string, data: bytes }
bluetooth-disconnectThe device disconnected. Turned on by bluetooth.connect.{ device: string, error?: string }
midi-messageA message arrived from an open MIDI input. Turned on by midi.open.{ port: string, data: bytes, timestamp: number }
midi-statechangeA MIDI port appeared or disappeared. Turned on by midi.access.{ port: MidiPortState }
location-updateA new position fix for a watch. Turned on by location.watchPosition.{ token: string, coords: Coords, timestamp: number }
location-errorA watch failed. Turned on by location.watchPosition.{ token: string, code: string, message: string }
system-sleepThe Mac is going to sleep. Turned on by power.watchSystem.{}
system-wakeThe Mac woke up. Turned on by power.watchSystem.{}
screens-sleepThe displays went to sleep. Turned on by power.watchSystem.{}
screens-wakeThe displays woke up. Turned on by power.watchSystem.{}
screen-lockThe screen was locked. Turned on by power.watchSystem.{}
screen-unlockThe screen was unlocked. Turned on by power.watchSystem.{}

Error codes

CodeMeaning
E_UNKNOWN_METHODNo such bridge method or namespace.
E_BAD_PARAMSParameters are missing or of the wrong type.
E_UNSUPPORTEDThe host does not support this (for example an API version mismatch).
E_UNAVAILABLETemporarily impossible: no window, device not connected, system refused.
E_DENIEDNot allowed: foreign origin, permission not declared in the manifest, or the user said no.
E_CANCELLEDThe user cancelled the dialog or the device picker.

Manifest permissions

Declared as "epwa": {"permissions": [...]} in manifest.webmanifest.

PermissionThe app may useAsks the person
filesfiles and folders you chooseno
networkdirect connections to servers and devices on the networkyes
bluetoothBluetooth devices you chooseno
usbUSB devices you chooseno
hidHID devices you chooseno
serialserial ports (Arduino and the like) you chooseno
midiMIDI devicesyes
notificationsnotificationsno
camerathe camera, with your permissionyes
microphonethe microphone, with your permissionyes
locationyour location, with your permissionyes
clipboard-readreading the clipboardyes
screenscreen sharing — you pick what to showno

Capabilities

(await epwa.getInfo()).capabilities reports this list plus the namespaces the app actually got.

dragRegions, trafficLights, titlebarArea, window, closeGuard, backgroundMode, menu, dockMenu, mediaSession, windowSize, alwaysOnTop, fullScreen, dockIcon, statusItem, windowMaterial, dockProgress, globalShortcuts, contextMenu, clipboard, haptic, windowFrames, about, print, findHandling, settings, fileDrop, dragSources

Web API shims

Standard APIs Pier implements on top of the bridge.

ReplacesBuilt onWhenNote
window.printprintalwaysWKWebView has window.print but it does nothing, so the shim is installed unconditionally.
navigator.wakeLockpower.preventSleep, power.allowSleeponly if the platform has noneScreen Wake Lock API over epwa.power; sentinels auto-release when the document is hidden.
window.launchQueuelaunch.readonly if the platform has noneLaunch Queue for file_handlers: handles with getFile(); up to 64 MB per file.
window.Notificationnotifications.show, notifications.clear, notifications.getPermission, notifications.requestPermissiononly if the platform has noneNotification API over epwa.notifications; tag maps to the native id.
navigator.setAppBadge / navigator.clearAppBadgeapp.setBadgeonly if the platform has noneBadging API; errors are swallowed the way browsers do.
navigator.shareapp.shareonly if the platform has noneWeb Share API without files; no data is a TypeError.
navigator.geolocationlocation.getCurrentPosition, location.watchPosition, location.clearWatchalwaysInstalled unconditionally: WKWebView has geolocation before macOS 27 but requests never complete.
navigator.requestMIDIAccessmidi.access, midi.open, midi.close, midi.sendonly if the platform has noneWeb MIDI API over epwa.midi: MIDIAccess, MIDIInput/MIDIOutput, onmidimessage.
navigator.hidhid.getDevices, hid.requestDevice, hid.forget, hid.open, hid.close, hid.sendReport, hid.sendFeatureReport, hid.receiveFeatureReportonly if the platform has noneWebHID over epwa.hid: navigator.hid, HIDDevice, inputreport, connect/disconnect.
navigator.mediaDevices.getDisplayMediaalwaysScreen sharing is unavailable: the shim rejects with NotSupportedError instead of WebKit hanging or silently capturing the app's own window.

Structures

Rect

FieldTypeRequired
xnumberyes
ynumberyes
widthnumberyes
heightnumberyes

TrafficLights

FieldTypeRequired
visiblebooleanyes
offsetXnumberyes
offsetYnumberyes
colorlight | dark | autoyes

WindowState

FieldTypeRequired
focusedbooleanyes
maximizedbooleanyes
fullscreenbooleanyes
minimizedbooleanyes
alwaysOnTopbooleanyes
widthnumberyes
heightnumberyes

A menu item, or { separator: true }.

FieldTypeRequired
idstringno
titlestringno
keystringno
modifierscmd | shift | alt | ctrl[]no
enabledbooleanno
checkedbooleanno
separatorbooleanno
FieldTypeRequired
titlestringyes
itemsMenuItem[]yes

StatusItemSpec

FieldTypeRequired
symbolstringno
titlestringno
tooltipstringno
itemsMenuItem[]no

ShortcutSpec

FieldTypeRequired
idstringyes
keystringyes
modifiersstring[]no
FieldTypeRequired
titlestringyes
urlstringyes

Handle

Opaque file handle from dialog.open/save, fs.appData or launch files.

FieldTypeRequired
idstringyes
namestringyes
kindfile | directoryyes

DirEntry

FieldTypeRequired
namestringyes
kindfile | directoryyes
sizeintegeryes
modifiednumberyes

StatEntry

FieldTypeRequired
namestringyes
kindfile | directoryyes
sizeintegeryes
modifiednumberyes
creatednumberyes

NetStatus

FieldTypeRequired
onlinebooleanyes
expensivebooleanyes
constrainedbooleanyes
interfaceswifi | wired | cellular | other[]yes

NetService

A Bonjour service instance found by net.browse.

FieldTypeRequired
namestringyes
typestringyes
domainstringyes

SerialPort

FieldTypeRequired
pathstringyes
namestringyes
vendorIdintegerno
productIdintegerno
serialNumberstringno

UsbDevice

FieldTypeRequired
idstringyes
vendorIdintegeryes
productIdintegeryes
productNamestringno
manufacturerNamestringno
serialNumberstringno
deviceClassintegerno

UsbFilter

FieldTypeRequired
vendorIdintegerno
productIdintegerno
classCodeintegerno

HidReport

A report inside a collection; reportSize is the body length in bytes.

FieldTypeRequired
reportIdintegeryes
reportSizeintegeryes

HidCollection

A top-level collection of the device.

FieldTypeRequired
usagePageintegeryes
usageintegeryes
inputReportsHidReport[]yes
outputReportsHidReport[]yes
featureReportsHidReport[]yes

HidDevice

FieldTypeRequired
idstringyes
vendorIdintegeryes
productIdintegeryes
productNamestringno
serialNumberstringno
collectionsHidCollection[]yes

HidFilter

FieldTypeRequired
vendorIdintegerno
productIdintegerno
usagePageintegerno
usageintegerno

BluetoothDevice

FieldTypeRequired
idstringyes
namestringyes

BluetoothFilter

FieldTypeRequired
servicesstring[]no
namestringno
namePrefixstringno

BluetoothService

FieldTypeRequired
uuidstringyes
characteristics{ uuid: string, properties: string[] }[]yes

MidiPort

A MIDI port as midi.access lists it.

FieldTypeRequired
idstringyes
namestringyes
manufacturerstringyes
connectedbooleanyes

MidiPortState

A MIDI port in a midi-statechange payload: same fields plus its direction.

FieldTypeRequired
idstringyes
namestringyes
manufacturerstringyes
typeinput | outputyes
connectedbooleanyes

Coords

FieldTypeRequired
latitudenumberyes
longitudenumberyes
accuracynumberyes
altitudenumberno
altitudeAccuracynumberno
speednumberno
headingnumberno

Position

FieldTypeRequired
coordsCoordsyes
timestampnumberyes

PermissionState

FieldTypeRequired
namestringyes
declaredbooleanyes
stategranted | prompt | deniedyes

NotificationAction

FieldTypeRequired
idstringyes
titlestringyes
destructivebooleanno

NotificationAttachment

FieldTypeRequired
namestringno
datastringno
handlestringno

NotificationSchedule

FieldTypeRequired
atnumberno
secondsnumberno

LaunchAtLogin

FieldTypeRequired
enabledbooleanyes
stateenabled | disabled | requiresApproval | notFoundyes

AppRecord

FieldTypeRequired
namestringyes
bundleIdstringyes
pathstringyes
startURLstring | nullyes
manifestURLstring | nullyes
permissionsstring[]yes
iconstring | nullyes

DiagnosticsApp

FieldTypeRequired
bundleIdstringyes
namestringyes
runtimeVersionstring | nullyes
hostVersionstring | nullyes
outdatedbooleanyes
permissionsstring[]yes

Binary

Binary payload on the wire.

FieldTypeRequired
datastringyes
encodingutf8 | base64yes

DragItem

Page data for a drag session: a MIME type or UTI and its string payload.

FieldTypeRequired
typestringyes
datastringyes

DragSource

A page area that can be dragged out of the window.

FieldTypeRequired
rectRectyes
fileshandle[]no
itemsDragItem[]no
imagestringno

ClipboardItem

One representation of clipboard content.

FieldTypeRequired
typetext/plain | text/html | image/png | text/uri-list | application/x-epwa-fileyes
datastringno
encodingutf8 | base64no
handleHandleno