This project supports multiple runtime platforms (Browser, Node.js, React Native, and Universal), with separate entry points for each. To ensure the build artifacts work correctly, platform-specific code must not be mixed.
Every non-test source file MUST export a __platforms array to declare which platforms it supports. This is enforced by ESLint and validated at build time.
All files must include a __platforms export:
For universal files (all platforms):
export const __platforms = ['__universal__'];For platform-specific files:
export const __platforms = ['browser']; // Browser only
export const __platforms = ['node']; // Node.js only
export const __platforms = ['react_native']; // React Native onlyFor multi-platform files:
// lib/utils/web-features.ts
export const __platforms = ['browser', 'react_native'];
// Your code that works on both browser and react_native
export function makeHttpRequest() {
// Implementation that works on both platforms
}Valid platform identifiers: 'browser', 'node', 'react_native', '__universal__'
Important: Only files that explicitly include '__universal__' in their __platforms array are considered universal. Files that list all concrete platforms (e.g., ['browser', 'node', 'react_native']) are treated as multi-platform files, NOT universal files. They must still ensure imports support all their declared platforms.
While not enforced, you should use file name suffixes for clarity:
.browser.ts- Typically browser-specific.node.ts- Typically Node.js-specific.react_native.ts- Typically React Native-specific.ts(no suffix) - Typically universal
Note: The validator currently enforces only the __platforms export declaration. File naming is informational and not validated. The __platforms export is the source of truth.
Each platform-specific file can only import from:
- Universal files (no platform restrictions)
- Compatible platform files (files that support ALL the required platforms)
- External packages (node_modules)
A file is compatible if:
- It's universal (no platform restrictions)
- For single-platform files: The import supports at least that platform
- For multi-platform files: The import supports ALL of those platforms
Core Principle: When file A imports file B, file B must support ALL platforms that file A runs on.
Universal File (__platforms = ['__universal__'])
- ✅ Can import from: universal files (with
__universal__) - ❌ Cannot import from: any platform-specific files, even
['browser', 'node', 'react_native'] - Why: Universal files run everywhere, so all imports must explicitly be universal
- Note: Listing all platforms like
['browser', 'node', 'react_native']is NOT considered universal
Single Platform File (__platforms = ['browser'])
- ✅ Can import from: universal files, files with
['browser'], multi-platform files that include browser like['browser', 'react_native'] - ❌ Cannot import from: files without browser support like
['node']or['react_native']only - Why: The import must support the browser platform
Multi-Platform File (__platforms = ['browser', 'react_native'])
- ✅ Can import from: universal files, files with
['browser', 'react_native'], supersets like['browser', 'node', 'react_native'] - ❌ Cannot import from: files missing any platform like
['browser']only or['node'] - Why: The import must support BOTH browser AND react_native
All-Platforms File (__platforms = ['browser', 'node', 'react_native'])
- ✅ Can import from: universal files, files with exactly
['browser', 'node', 'react_native'] - ❌ Cannot import from: any subset like
['browser'],['browser', 'react_native'], etc. - Why: This is NOT considered universal - imports must support all three platforms
- Note: If your code truly works everywhere, use
['__universal__']instead
✅ Valid Imports
// In lib/index.browser.ts (Browser platform only)
import { Config } from './shared_types'; // ✅ Universal file
import { BrowserRequestHandler } from './utils/http_request_handler/request_handler.browser'; // ✅ browser + react_native (supports browser)
import { uuid } from 'uuid'; // ✅ External package// In lib/index.node.ts (Node platform only)
import { Config } from './shared_types'; // ✅ Universal file
import { NodeRequestHandler } from './utils/http_request_handler/request_handler.node'; // ✅ Same platform// In lib/vuid/vuid_manager_factory.react_native.ts (React Native platform only)
import { AsyncStorageCache } from '../utils/cache/async_storage_cache.react_native'; // ✅ Compatible (react_native only)// In lib/event_processor/event_processor_factory.browser.ts (Browser platform only)
import { Config } from '../shared_types'; // ✅ Universal file
import defaultEventDispatcher from './event_dispatcher/default_dispatcher.browser'; // ✅ Compatible (browser + react_native, includes browser)// In lib/event_processor/event_dispatcher/default_dispatcher.browser.ts (Multi-platform: browser + react_native)
import { Config } from '../../shared_types'; // ✅ Universal file
import { BrowserRequestHandler } from '../../utils/http_request_handler/request_handler.browser'; // ✅ Compatible (also browser + react_native)❌ Invalid Imports
// In lib/index.browser.ts (Browser platform only)
import { NodeRequestHandler } from './utils/http_request_handler/request_handler.node'; // ❌ Node-only file// In lib/index.node.ts (Node platform only)
import { BrowserRequestHandler } from './utils/http_request_handler/request_handler.browser'; // ❌ browser + react_native, doesn't support node// In lib/shared_types.ts (Universal file)
import { AsyncStorageCache } from './utils/cache/async_storage_cache.react_native'; // ❌ React Native only, universal file needs imports that work everywhere// In lib/event_processor/event_dispatcher/default_dispatcher.browser.ts
import { NodeRequestHandler } from '../../utils/http_request_handler/request_handler.node'; // ❌ Node-only, doesn't support browser or react_native
// This file needs imports that work in BOTH browser AND react_nativePlatform isolation is enforced automatically during the build process.
# Run validation manually
npm run validate-platform-isolation
# Validation runs automatically before build
npm run buildThe validation script (scripts/validate-platform-isolation.js):
- Scans all TypeScript/JavaScript files configured in the in the
.platform-isolation.config.jsconfig file. - Verifies every file has a
__platformsexport - fails immediately if any file is missing this - Validates all platform values - ensures values in
__platformsarrays are valid (read from Platform type) - Parses import statements using TypeScript AST (ES6 imports, require, dynamic imports)
- Checks import compatibility: For each import, verifies that the imported file supports ALL platforms that the importing file runs on
- Fails the build if violations are found or if any file lacks
__platformsexport
ESLint Integration: The require-platform-declaration ESLint rule also enforces the __platforms export requirement during development.
The validation is integrated into the build process:
{
"scripts": {
"build": "npm run validate-platform-isolation && tsc --noEmit && ..."
}
}If platform isolation is violated, the build will fail with a detailed error message showing:
- Which files have violations
- The line numbers of problematic imports
- What platform the file belongs to
- What platform it's incorrectly importing from
For code that works across all platforms, use ['__universal__']:
Example: Universal utility function
// lib/utils/string-helpers.ts
export const __platforms = ['__universal__'];
// Pure JavaScript that works everywhere
export function capitalize(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1);
}
export function sanitizeKey(key: string): string {
return key.replace(/[^a-zA-Z0-9_]/g, '_');
}Single Platform
- Add
__platformsexport declaring the platform (e.g.,export const __platforms = ['browser'];) - Name the file with a platform suffix for clarity (e.g.,
my-feature.browser.ts) - Only import from universal or compatible platform files
Example:
// lib/features/my-feature.ts (universal interface)
export const __platforms = ['__universal__'];
export interface MyFeature {
doSomething(): void;
}
// lib/features/my-feature.browser.ts
export const __platforms = ['browser'];
export class BrowserMyFeature implements MyFeature {
doSomething(): void {
// Browser-specific implementation
}
}
// lib/features/my-feature.node.ts
export const __platforms = ['node'];
export class NodeMyFeature implements MyFeature {
doSomething(): void {
// Node.js-specific implementation
}
}Multiple Platforms (But Not Universal)
For code that works on multiple platforms but is not universal, use the __platforms export to declare the list of supported platforms:
Example: Browser + React Native only
// lib/utils/http-helpers.ts
export const __platforms = ['browser', 'react_native'];
// This code works on both browser and react_native, but not node
export function makeRequest(url: string): Promise<string> {
// XMLHttpRequest is available in both browser and react_native
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(new Error('Request failed'));
xhr.send();
});
}- ✅ Prevents runtime errors from platform-incompatible code
- ✅ Catches issues at build time, not in production
- ✅ Makes platform boundaries explicit and maintainable
- ✅ Ensures each bundle only includes relevant code