ReviewOS

also looking at this

craft-native/craft

feat(bridge): let the page ask what native actually serves

#60
Merged glennmichael123 wants to merge feat/capabilities into main
20 files +1546 -37
docs/BRIDGE_API.mdmodified+54-0
Changes to docs/BRIDGE_API.md
@@ -11,6 +11,7 @@ The Craft JavaScript Bridge provides a seamless interface for your web applicati
1111- [Global Shortcuts (macOS)](#global-shortcuts-macos)
1212- [Settings and Preferences (macOS)](#settings-and-preferences-macos)
1313- [Headless mode](#headless-mode)
14- [Capabilities](#capabilities)
1415- [Window API](#window-api)
1516- [App API](#app-api)
1617- [TypeScript Support](#typescript-support)
@@ -520,6 +521,58 @@ sockets at all — and `safaridriver` refuses to attach to anything that is not
520521Safari. Driving a craft page from another process needs a control channel craft
521522owns, which does not exist yet.
522523
524## Capabilities
525
526This script is one blob, `@embedFile`d into the binary and injected whole into
527every craft window — the same JavaScript whatever the native side behind it
528implements. So `typeof window.craft.tray.destroy === 'function'` has never been
529evidence that anything is behind it, and three shipped bugs came from assuming
530otherwise. Ask instead.
531
532```javascript
533const caps = await window.craft.capabilities()
534
535caps.namespaces.updater.status // 'unavailable'
536caps.namespaces.updater.reason // 'the Sparkle framework is not linked into this build'
537caps.channels['craft:fs:change'] // false — you could subscribe, it would never fire
538```
539
540Or, for one surface:
541
542```javascript
543if (window.craft.supports('tray.destroy')) { /* … */ }
544```
545
546### Namespace status
547
548| status | means |
549|---|---|
550| `declared` | Audited. The action list is complete, and a conformance test fails the build if it stops matching what the dispatcher serves. |
551| `undeclared` | Routed, but craft has not audited it and **will not claim anything either way**. Treat as "try it and handle failure", not as "missing". |
552| `unavailable` | Reachable and known not to work. `reason` says why. |
553| `unrouted` | Implemented natively but absent from the dispatcher, so no message can reach it. |
554
555Most namespaces are `undeclared` today. Declaring one means refactoring its
556dispatch chain so each action name exists in exactly one place — roughly 279
557names across 47 files — so it is being done in batches, and the conformance test
558holds a ceiling on how many may remain that only ever goes down.
559
560### `channels`
561
562Every `craft:*` event, and whether anything native emits on it. This cannot be
563derived from the action tables — an emitter is a separate piece of code that may
564or may not have been written — so a channel is reported live only because the
565code that emits on it took out a permit at startup. Sixteen channels the JS
566surface subscribes to currently have no emitter at all.
567
568### `supports()` fails open
569
570It returns `true` before capabilities have been fetched, and `true` for an
571`undeclared` namespace. A feature-detection mechanism that breaks working code
572when it cannot see itself would be worse than the gaps it describes. Only an
573`unavailable` or `unrouted` surface — or an unknown action inside a `declared`
574namespace — answers `false`.
575
523576## Window API
524577
525578Control the application window from JavaScript.
@@ -757,6 +810,7 @@ async function onComplete() {
757810| Global Shortcuts | ✅ | �� | �� |
758811| Settings… item | ✅ | �� | �� |
759812| Preferences | ✅ | �� | �� |
813| Capabilities | ✅ | �� | �� |
760814
761815✅ Implemented | �� In Progress | ➖ Not Applicable
762816