| name | cross-platform-development |
| description | Use when working with native dependencies, handling platform differences, or when build/install/test issues arise on non-Windows platforms |
Cross-Platform Development
Why the mock exists
@iracedeck/iracing-native wraps the iRacing SDK (Windows-only C++ N-API addon). Without the mock layer, pnpm install, pnpm build, and pnpm test all fail on macOS/Linux because:
node-gyp can't compile the Windows-specific C++ code
keysender (native keyboard module) is Windows-only
- Package
"os" restrictions blocked installation entirely
Architecture
Platform detection in iracing-native/src/index.ts
platform() === "win32"?
├── Yes → try loading native .node addon
│ ├── Success → use real addon
│ └── Failure → fall back to IRacingNativeMock
└── No → use IRacingNativeMock (never attempts to load .node)
platform() check is the primary guard
try/catch around require() is the safety net
- No top-level await — synchronous module loading preserved
IRacingNative class delegates to either addon or IRacingNativeMock transparently
Forcing mock mode on Windows
For development/testing without iRacing running, mock mode can be forced on Windows:
- File-based (recommended for Stream Deck): Create an empty
.mock file in the sdPlugin folder (e.g., com.iracedeck.sd.core.sdPlugin/.mock). Delete it to return to native mode.
- Environment variable: Set
IRACEDECK_MOCK=1 before launching (useful for CLI/terminal testing).
The .mock file is gitignored. The mock rotates through telemetry snapshots (including flag states) every 5 seconds.
Native dependencies
keysender is in optionalDependencies — silently fails to install on macOS
- A type shim at
iracing-plugin-stream-deck/src/shared/keysender.d.ts provides TypeScript types when keysender isn't installed
node-gyp is skipped on non-Windows via iracing-native/scripts/build.mjs
When adding new native methods
You must update the mock alongside the native addon:
addon.cc — C++ implementation
src/index.ts — Add delegation in IRacingNative class (both addon and getMock() paths)
src/mock-impl.ts — Add mock implementation to IRacingNativeMock
- Continue with the standard cross-package sync (keyboard-service, plugin.ts, tests, rules)
Mock data
Located in packages/iracing-native/src/mock-data/:
| File | Content |
|---|
session-info.ts | YAML string — Spa practice, 3 drivers |
telemetry.ts | Variable headers with computed offsets, buildTelemetryBuffer() |
snapshots.ts | 6 rotating snapshots (mid-straight, braking, pit entry, yellow flag, blue flag, yellow+blue) |
Mock data is placeholder. To update with real telemetry, capture snapshots on Windows using the telemetry-snapshot CLI tool in @iracedeck/iracing-sdk.
Build scripts
| Script | Behavior |
|---|
pnpm build (root) | Runs turbo run build. On Windows, automatically stops Stream Deck before building and restarts it after (only if it was running). |
iracing-native build | Runs node-gyp rebuild on Windows, skips on other platforms; always runs tsc |
Design doc
See docs/plans/2026-03-01-cross-platform-native-mock-design.md for the full design rationale.