@realitycollective/service-framework-client 1.0.1 → 1.0.2-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -4,6 +4,27 @@ Change log for the Reality Collective Service Framework for TypeScript. All pack
4
4
 
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Preview builds are not listed separately. The entry for a version accumulates while its previews are published, and is dated when that version is released.
6
6
 
7
+ ## [1.0.2]
8
+
9
+ A native platform, beside IWSDK, three.js and Babylon.js, and byte I/O that works the same on the web and on a native host.
10
+
11
+ ### Added
12
+
13
+ - `@realitycollective/service-framework-native`, the binding for a native XR app that embeds a JavaScript engine such as Hermes. The app owns the session, the frame loop, rendering and physics, and installs one host object, `globalThis.__rcHost`, before it evaluates the bundle. Everything crosses that object as plain values. `NativeRuntimeAdapter` publishes the app's frames and session through the same `RuntimeAdapter` seam as the other bindings, with the session facet, and passes `runtimeAdapterContractCases()`. It derives capabilities from the OpenXR session state, the enabled extensions, system hand tracking support and the blend mode. It keeps the same sticky `setCapabilities` override, `clearCapabilityOverrides()` and `refreshCapabilities()` the other adapters have. Given a `scheduler`, it emits `renderTick` with `source: "native"`. `createNativeHostIO()` returns a `HostIO` over the host's `io` slice. The host object's shape was proven on a Quest 3 and in the visionOS Simulator by the team that built the first native host. The package README documents it, including the slices the other families' native packages read.
14
+ - `HostIO` in the core, with `createWebHostIO()` over `fetch` and `DecompressionStream`. A service that reads assets takes a `HostIO` and never reaches for a global, so the same code runs on the web and on a native host. The globals are read when a method is called, so a host without them fails only if it uses them. Helpers that work on both: `fetchText`, `fetchJson`, `fetchMaybeGzipped` (gunzips only bytes that carry the gzip magic number, since hosts differ on whether they undo `Content-Encoding`), `decodeUtf8` (no `TextDecoder`, which Hermes lacks), `isGzip` and `concatBytes`. This is transport only. Decoding images, audio and models stays with the engine.
15
+ - A "Host requirements" section in the core package README. It names every global the core expects from its host beyond the ECMAScript language: `setTimeout` and `clearTimeout` for `resolveAsync`, `waitUntilInitialized` and the mock adapter's session request, and `setInterval` and `clearInterval` for a `TimerScheduler` built without injected timers. It names the two globals used only when present, `AbortController` (with a built-in fallback) and the `fetch` and `DecompressionStream` behind `createWebHostIO()`, and states that nothing else is assumed. A host that embeds a bare engine, such as Hermes in a native app, can now supply exactly that list. `test/host-requirements.test.ts` checks the table against the source, so a new host global fails the suite until it is listed.
16
+ - The capability override rule, stated in the README and on the `RuntimeAdapter` doc comment. Every adapter exposes `setCapabilities(partial)` as a sticky override over what it derives, and an adapter that derives also exposes `clearCapabilityOverrides()`. Every in-repo adapter already did, and every conformance driver already wired its `capabilities` hook to it. The rule was never written down, so an adapter written elsewhere that only derived from its host failed the capability-change case. The method stays off the `RuntimeAdapter` interface, because services must not call it. The same test checks that every in-repo adapter still exposes it.
17
+
18
+ - `hostIOContractCases()` and `renderTickContractCases()`, shared conformance suites shipped as data, like `runtimeAdapterContractCases()`. Clients only ever use the core: a service reads assets through `HostIO` and subscribes to `renderTick` on the core scheduler, and never asks which platform is underneath. That only holds if every platform behaves the same way, so every platform now runs the same checks. `hostIOContractCases()` runs against `createWebHostIO()` and `createNativeHostIO()`: served bytes come back exactly, a missing resource rejects, gunzip restores and rejects non-gzip, and the core helpers read plain and gzipped JSON alike. It needs no `CompressionStream` or `TextEncoder`, so a native app can run it on device. `renderTickContractCases()` runs against `ThreeRenderLoopBridge`, `WebXRRuntimeAdapter`, `BabylonRenderLoopBridge`, `BabylonRuntimeAdapter`, the IWSDK service bridge system and `NativeRuntimeAdapter`: one tick per frame, frames counted from 1, a stable source, and `timestamp` and `deltaTime` in milliseconds.
19
+ - `LifecycleContext` now documents its units: `timestamp` and `deltaTime` in milliseconds, `frame` counted from 1, and `source` naming the binding.
20
+
21
+ ### Fixed
22
+
23
+ - The IWSDK bridge reported `timestamp` in seconds. IWSDK calls a system's `update(delta, time)` with `time` as elapsed seconds from three.js `Clock`, and the bridge passed it straight into `FrameInfo.timestamp` and `LifecycleContext.timestamp`, which are milliseconds on every other platform. A service reading `timestamp` got a value a thousand times smaller on IWSDK, which is a platform conditional a client should never need. The bridge now converts it, and `renderTickContractCases()` fails a binding that does not. The `FrameInfo` doc no longer cites IWSDK as the source of its unit. Code that read the IWSDK timestamp as seconds must now read milliseconds.
24
+ - `createWebHostIO().gunzip` left the stream's write-side error unhandled when given bytes that are not gzip, so a host logged an unhandled rejection besides the rejection the caller received. It now rejects once. The new `HostIO` suite found it.
25
+ - `TimerScheduler` counted frames on one counter shared by all four of its channels, and named `source` after the channel. A service counting render frames therefore saw gaps that depended on how often the other channels fired, where every engine binding counts 1, 2, 3. Each channel now counts its own ticks from 1, and every context names `"timer"` as its source, as a binding names itself. The timer now runs the shared `renderTickContractCases()` suite, which fails on the old shared counter.
26
+ - `ServiceManager` no longer needs a global `AbortController`. Every service record created one unconditionally to hand the service its `signal`, so a host without it failed to boot any profile before client code ran. Hermes, the engine a native host embeds, is such a host: `ReferenceError: Property 'AbortController' doesn't exist`. The manager now uses the global when it exists and otherwise falls back to a small internal controller. Its signal carries `aborted`, `reason`, `onabort`, `addEventListener("abort")` and `removeEventListener`, and `abort()` fires once. Web and Node behaviour is unchanged, because both have the global. `ServiceActivationContext.signal` is still typed `AbortSignal`, and nothing was added to the public exports.
27
+
7
28
  ## [1.0.1] - 2026-09-17
8
29
 
9
30
  Packaging, tooling and documentation, plus additive runtime API: the engine-free adapter contracts move into the core, the IWSDK adapter derives capabilities from the live session and gains a session facet, and the three.js and Babylon.js packages gain runtime adapters so a three.js, Babylon or desktop app reaches the same seam. Nothing that existed was removed, and one interface changed shape: `AdapterCapabilities` gains a required `environmentBlendMode` key, so code that builds the whole object by hand - an adapter of your own, or a test fake - has one more field to supply. Code that only reads capabilities is unaffected.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@realitycollective/service-framework-client",
3
- "version": "1.0.1",
3
+ "version": "1.0.2-preview.0",
4
4
  "description": "Base React and three.js client composition package for the Reality Collective TypeScript Service Framework.",
5
5
  "author": "Reality Collective",
6
6
  "license": "MIT",
@@ -36,9 +36,9 @@
36
36
  "url": "https://github.com/realitycollective/com.realitycollective.service-framework.ts/issues"
37
37
  },
38
38
  "dependencies": {
39
- "@realitycollective/service-framework": "^1.0.1",
40
- "@realitycollective/service-framework-react": "^1.0.1",
41
- "@realitycollective/service-framework-three": "^1.0.1"
39
+ "@realitycollective/service-framework": "^1.0.2-preview.0",
40
+ "@realitycollective/service-framework-react": "^1.0.2-preview.0",
41
+ "@realitycollective/service-framework-three": "^1.0.2-preview.0"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "react": "^19.2.0"