Drift & cross-repo delivery
In a real deployment the JS bundle and the native binaries ship independently — the bundle is often renovate-ignored. Skew is the steady state, not an error condition. BridgeKit treats it as a first-class concern.
The contract hash
Section titled “The contract hash”A 32-bit hash over the normalized descriptor is baked into both the generated native binding and the JS descriptor. At bind / first-resolution time the router diffs member sets:
- Missing members → one structured warning naming the missing members and both hashes.
- Full hash mismatch on identical member sets → tolerated (this is additive evolution).
- Calls to a removed member → fail with
METHOD_NOT_FOUNDcarrying the diff context.
So a newer bundle talking to an older native descriptor degrades gracefully and loudly, never silently.
bridgekit.lock
Section titled “bridgekit.lock”A generated contract id → hash map, committed next to the generated bindings in the consuming
repo. It lets the native repo’s CI verify internal consistency without a Node toolchain —
no need to run the TypeScript generator on the native CI.
The lock carries a platform field recording which emitter produced it:
{ "descriptorVersion": 1, "platform": "kotlin", // or "swift" "contracts": { "axion.host": { "hash": "8e552bd7", "members": { "methods.getAppVersion": "71ff3fa0", "methods.getCountryAndLanguage": "27aee930", "methods.getLiteral": "494175a7", "methods.openUrl": "fb545690", "methods.trackEvent": "99cf4370" } } }}Each platform (Kotlin, Swift) has its own lock file in its own output directory.
--into <path> — tool-owned cross-repo copy
Section titled “--into <path> — tool-owned cross-repo copy”When the contracts live in one repo and the generated bindings must land in another (e.g.
Android.Application/features/lia/bridgekit/), --into makes that copy tool-owned rather
than a manual cp:
axion bridgekit generate \ --contracts 'src/**/*.contract.ts' \ --out-dir bridgekit/generated \ --into ../Android.Application/features/lia/bridgekitThe same applies to Swift:
axion bridgekit generate \ --platform swift \ --out-dir ios/contracts/generated \ --into ../iOS.Application/lia/contractsEvolution rule: additive only
Section titled “Evolution rule: additive only”The documented, --check-enforced rule:
Additive only. New optional fields, new methods, new streams, new state keys are fine. Removals and renames require a new contract id.
--check compares against the last generated descriptors and fails CI on a non-additive
change. This is what lets two independently-deployed artifacts evolve without a lockstep
release.
Feature detection at runtime
Section titled “Feature detection at runtime”When you genuinely need to branch on whether a member exists across a skew boundary, use the readiness/provision APIs rather than catching errors:
- JS:
useBridgeReady(Contract)/isProvided(Contract) - Kotlin:
isProvided(contract)/awaitProvided(contract, timeout) - Swift:
BridgeKitRuntime.default.isProvided(Contract())/awaitProvided(Contract(), timeoutMs:)