Skip to content

Commit bfcb365

Browse files
committed
init
1 parent 860fca0 commit bfcb365

File tree

4 files changed

+427
-1
lines changed

4 files changed

+427
-1
lines changed

docs/PLATFORM_ISOLATION.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Platform Isolation
2+
3+
## Overview
4+
5+
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.
6+
7+
## Naming Convention
8+
9+
Platform-specific files use a suffix pattern:
10+
- `.browser.ts` - Browser-specific implementation
11+
- `.node.ts` - Node.js-specific implementation
12+
- `.react_native.ts` - React Native-specific implementation
13+
- `.ts` (no suffix) - Universal code (works across all platforms)
14+
15+
## Import Rules
16+
17+
Each platform-specific file can **only** import from:
18+
19+
1. **Universal files** (no platform suffix)
20+
2. **Same-platform files** (matching platform suffix)
21+
3. **External packages** (node_modules)
22+
23+
### Examples
24+
25+
**Valid Imports**
26+
27+
```typescript
28+
// In lib/index.browser.ts
29+
import { Config } from './shared_types'; // ✅ Universal file
30+
import { BrowserRequestHandler } from './utils/http_request_handler/request_handler.browser'; // ✅ Same platform
31+
import { uuid } from 'uuid'; // ✅ External package
32+
```
33+
34+
```typescript
35+
// In lib/index.node.ts
36+
import { Config } from './shared_types'; // ✅ Universal file
37+
import { NodeRequestHandler } from './utils/http_request_handler/request_handler.node'; // ✅ Same platform
38+
```
39+
40+
**Invalid Imports**
41+
42+
```typescript
43+
// In lib/index.browser.ts
44+
import { NodeRequestHandler } from './utils/http_request_handler/request_handler.node'; // ❌ Different platform
45+
```
46+
47+
```typescript
48+
// In lib/index.node.ts
49+
import { BrowserRequestHandler } from './utils/http_request_handler/request_handler.browser'; // ❌ Different platform
50+
```
51+
52+
## Automatic Validation
53+
54+
Platform isolation is enforced automatically during the build process.
55+
56+
### Running Validation
57+
58+
```bash
59+
# Run validation manually
60+
npm run validate-platform-isolation
61+
62+
# Validation runs automatically before build
63+
npm run build
64+
```
65+
66+
### How It Works
67+
68+
The validation script (`scripts/validate-platform-isolation.js`):
69+
70+
1. Scans all source files in the `lib/` directory
71+
2. Identifies platform-specific files by their suffix
72+
3. Parses import statements (ES6 imports, require, dynamic imports)
73+
4. Checks that each import follows the platform isolation rules
74+
5. Fails the build if violations are found
75+
76+
### Build Integration
77+
78+
The validation is integrated into the build process:
79+
80+
```json
81+
{
82+
"scripts": {
83+
"build": "npm run validate-platform-isolation && tsc --noEmit && ..."
84+
}
85+
}
86+
```
87+
88+
If platform isolation is violated, the build will fail with a detailed error message showing:
89+
- Which files have violations
90+
- The line numbers of problematic imports
91+
- What platform the file belongs to
92+
- What platform it's incorrectly importing from
93+
94+
## Creating New Platform-Specific Code
95+
96+
When creating new platform-specific implementations:
97+
98+
1. Name the file with the appropriate platform suffix (e.g., `my-feature.browser.ts`)
99+
2. Only import from universal or same-platform files
100+
3. Create a universal factory or interface if multiple platforms need different implementations
101+
102+
### Example: Creating a Platform-Specific Feature
103+
104+
```typescript
105+
// lib/features/my-feature.ts (universal interface)
106+
export interface MyFeature {
107+
doSomething(): void;
108+
}
109+
110+
// lib/features/my-feature.browser.ts
111+
export class BrowserMyFeature implements MyFeature {
112+
doSomething(): void {
113+
// Browser-specific implementation
114+
}
115+
}
116+
117+
// lib/features/my-feature.node.ts
118+
export class NodeMyFeature implements MyFeature {
119+
doSomething(): void {
120+
// Node.js-specific implementation
121+
}
122+
}
123+
124+
// lib/features/factory.browser.ts
125+
import { BrowserMyFeature } from './my-feature.browser';
126+
export const createMyFeature = () => new BrowserMyFeature();
127+
128+
// lib/features/factory.node.ts
129+
import { NodeMyFeature } from './my-feature.node';
130+
export const createMyFeature = () => new NodeMyFeature();
131+
```
132+
133+
## Troubleshooting
134+
135+
If you encounter a platform isolation error:
136+
137+
1. **Check the error message** - It will tell you which file and line has the violation
138+
2. **Identify the issue** - Look at the import statement on that line
139+
3. **Fix the import**:
140+
- If the code should be universal, remove the platform suffix from the imported file
141+
- If the code must be platform-specific, create separate implementations for each platform
142+
- Use factory patterns to abstract platform-specific instantiation
143+
144+
## Benefits
145+
146+
- ✅ Prevents runtime errors from platform-incompatible code
147+
- ✅ Catches issues at build time, not in production
148+
- ✅ Makes platform boundaries explicit and maintainable
149+
- ✅ Ensures each bundle only includes relevant code
150+
- ✅ Works independently of linting tools (ESLint, Biome, etc.)

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"clean": "rm -rf dist",
5858
"clean:win": "(if exist dist rd /s/q dist)",
5959
"lint": "tsc --noEmit && eslint 'lib/**/*.js' 'lib/**/*.ts'",
60+
"validate-platform-isolation": "node scripts/validate-platform-isolation.js",
6061
"test-vitest": "vitest run",
6162
"test-mocha": "TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register -r tsconfig-paths/register -r lib/tests/exit_on_unhandled_rejection.js 'lib/**/*.tests.ts' 'lib/**/*.tests.js'",
6263
"test": "npm run test-mocha && npm run test-vitest",
@@ -66,7 +67,7 @@
6667
"test-umdbrowser": "npm run build-browser-umd && karma start karma.umd.conf.js --single-run",
6768
"test-karma-local": "karma start karma.local_chrome.bs.conf.js && npm run build-browser-umd && karma start karma.local_chrome.umd.conf.js",
6869
"prebuild": "npm run clean",
69-
"build": "tsc --noEmit && npm run genmsg && rollup -c && cp dist/index.browser.d.ts dist/index.d.ts",
70+
"build": "npm run validate-platform-isolation && tsc --noEmit && npm run genmsg && rollup -c && cp dist/index.browser.d.ts dist/index.d.ts",
7071
"build:win": "tsc --noEmit && npm run genmsg && rollup -c && type nul > dist/optimizely.lite.es.d.ts && type nul > dist/optimizely.lite.es.min.d.ts && type nul > dist/optimizely.lite.min.d.ts",
7172
"build-browser-umd": "rollup -c --config-umd",
7273
"coveralls": "nyc --reporter=lcov npm test",

0 commit comments

Comments
 (0)