Skip to content

Commit ee84188

Browse files
committed
plan updates
1 parent 512ff2c commit ee84188

File tree

1 file changed

+188
-110
lines changed

1 file changed

+188
-110
lines changed

plan_universal_runtime_compatibility.md

Lines changed: 188 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -148,103 +148,121 @@ export default defineConfig({
148148
});
149149
```
150150

151-
### Phase 2: Testing Infrastructure
151+
### Phase 2: Testing Infrastructure (Industry-Standard Pattern)
152152

153-
#### 2.1 Runtime Test Scripts
153+
Based on analysis of major universal libraries (OpenAI SDK, Drizzle ORM, Miniflare), implement the proven pattern used across the ecosystem.
154154

155-
Create `scripts/test-runtimes.js`:
155+
#### 2.1 Single Portable Test Harness
156156

157-
```javascript
158-
#!/usr/bin/env node
157+
Keep runtime tests in standard Jest/Vitest format using ESM syntax:
159158

160-
const { spawn } = require('child_process');
161-
const path = require('path');
162-
163-
const tests = [
164-
{
165-
name: 'Node.js CJS',
166-
cmd: 'node',
167-
args: ['-e', 'const { WorkOS } = require("./lib/index.cjs"); console.log("✅ CJS:", typeof WorkOS);']
168-
},
169-
{
170-
name: 'Node.js ESM',
171-
cmd: 'node',
172-
args: ['-e', 'import("./lib/index.js").then(({ WorkOS }) => console.log("✅ ESM:", typeof WorkOS));']
173-
},
174-
{
175-
name: 'Deno ESM',
176-
cmd: 'deno',
177-
args: ['run', '--allow-read', './lib/index.js']
178-
},
179-
{
180-
name: 'Bun CJS',
181-
cmd: 'bun',
182-
args: ['-e', 'const { WorkOS } = require("./lib/index.cjs"); console.log("✅ Bun CJS:", typeof WorkOS);']
183-
},
184-
{
185-
name: 'Bun ESM',
186-
cmd: 'bun',
187-
args: ['-e', 'import("./lib/index.js").then(({ WorkOS }) => console.log("✅ Bun ESM:", typeof WorkOS));']
188-
}
189-
];
190-
191-
async function runTest(test) {
192-
return new Promise((resolve) => {
193-
const child = spawn(test.cmd, test.args, { stdio: 'pipe' });
194-
let stdout = '';
195-
let stderr = '';
196-
197-
child.stdout.on('data', (data) => stdout += data);
198-
child.stderr.on('data', (data) => stderr += data);
199-
200-
child.on('close', (code) => {
201-
resolve({
202-
name: test.name,
203-
success: code === 0,
204-
stdout,
205-
stderr
206-
});
207-
});
159+
```typescript
160+
// tests/runtime-compatibility.spec.ts
161+
import { WorkOS } from '../lib/esm/index.js';
162+
163+
describe('Runtime Compatibility', () => {
164+
test('WorkOS constructor exists and is callable', () => {
165+
expect(typeof WorkOS).toBe('function');
166+
const workos = new WorkOS('test-key');
167+
expect(workos).toBeInstanceOf(WorkOS);
208168
});
209-
}
210169

211-
async function main() {
212-
console.log('🧪 Testing runtime compatibility...\n');
213-
214-
for (const test of tests) {
215-
try {
216-
const result = await runTest(test);
217-
if (result.success) {
218-
console.log(`${result.name}: PASSED`);
219-
if (result.stdout.trim()) console.log(` ${result.stdout.trim()}`);
220-
} else {
221-
console.log(`${result.name}: FAILED`);
222-
if (result.stderr.trim()) console.log(` ${result.stderr.trim()}`);
223-
}
224-
} catch (error) {
225-
console.log(`${test.name}: ERROR - ${error.message}`);
226-
}
227-
}
228-
}
229-
230-
main();
170+
test('Basic API methods are available', () => {
171+
const workos = new WorkOS('test-key');
172+
expect(typeof workos.sso).toBe('object');
173+
expect(typeof workos.directorySync).toBe('object');
174+
expect(typeof workos.userManagement).toBe('object');
175+
});
176+
});
231177
```
232178

233-
#### 2.2 Add npm Scripts
179+
#### 2.2 Runtime-Specific Test Scripts
234180

235-
Update `package.json`:
181+
Add wrapper scripts that hide runtime CLI differences:
236182

237183
```json
238184
{
239185
"scripts": {
240-
"test:runtimes": "node scripts/test-runtimes.js",
241-
"test:all": "pnpm test && pnpm test:runtimes",
242-
"prebuild": "pnpm clean",
243-
"postbuild": "pnpm test:runtimes"
186+
"test:node": "jest tests/runtime-compatibility.spec.ts",
187+
"test:deno": "deno test --allow-read tests/runtime-compatibility.spec.ts",
188+
"test:bun": "bun test tests/runtime-compatibility.spec.ts",
189+
"test:edge": "jest tests/worker.spec.ts --testEnvironment=miniflare",
190+
"test:runtimes": "pnpm test:node && echo '✅ Node.js passed'"
244191
}
245192
}
246193
```
247194

195+
#### 2.3 Edge/Workers Testing via Miniflare
196+
197+
For Cloudflare Workers compatibility without network calls:
198+
199+
```typescript
200+
// tests/worker.spec.ts
201+
import { Miniflare } from 'miniflare';
202+
203+
describe('Worker Environment', () => {
204+
test('SDK loads in worker context', async () => {
205+
const mf = new Miniflare({
206+
script: `
207+
import { WorkOS } from './lib/esm/index.worker.js';
208+
addEventListener('fetch', event => {
209+
const workos = new WorkOS('test-key');
210+
event.respondWith(new Response(workos.constructor.name));
211+
});
212+
`,
213+
modules: true,
214+
});
215+
216+
const res = await mf.dispatchFetch('http://localhost/');
217+
expect(await res.text()).toBe('WorkOSNode');
218+
});
219+
});
220+
```
221+
222+
#### 2.4 Manual Testing Commands (Current Phase) ✅ COMPLETE
223+
224+
**Ecosystem Check Script**: `scripts/ecosystem-check.ts`
225+
226+
A single comprehensive test runner based on industry patterns from OpenAI SDK, TanStack, and others:
227+
228+
```bash
229+
# Run all runtime compatibility checks
230+
pnpm check:runtimes
231+
232+
# Individual runtime tests
233+
pnpm test:node # Node.js CJS + ESM
234+
pnpm test:deno # Deno ESM
235+
pnpm test:bun # Bun CJS
236+
```
237+
238+
**Manual validation commands**:
239+
240+
```bash
241+
# Node.js CJS
242+
node -e "console.log('CJS:', require('./lib/cjs/index.cjs').WorkOS.name)"
243+
244+
# Node.js ESM
245+
node -e "import('./lib/esm/index.js').then(m => console.log('ESM:', m.WorkOS.name))"
246+
247+
# Deno
248+
deno eval "import('./lib/esm/index.js').then(m => console.log('Deno:', m.WorkOS.name))"
249+
250+
# Bun
251+
bun -e "console.log('Bun:', require('./lib/cjs/index.cjs').WorkOS.name)"
252+
```
253+
254+
**Test Results** (Current Status):
255+
- ✅ Node.js CJS: `WorkOSNode`
256+
- ✅ Node.js ESM: `WorkOSNode`
257+
- ✅ Deno: `WorkOSNode` (with TypeScript config warnings)
258+
- ✅ Bun CJS: `WorkOSNode`
259+
- ✅ Bun ESM: `WorkOSNode`
260+
- ✅ Worker: `WorkOS import successful` (module resolution test)
261+
262+
**Dependencies Added**:
263+
- `tsx@^4.19.0` - TypeScript execution for ecosystem check script
264+
- `miniflare@^3.20250408.2` - Worker environment testing (optional)
265+
248266
### Phase 3: Enhanced Package.json Configuration
249267

250268
#### 3.1 Improved Exports
@@ -298,9 +316,9 @@ Ensure optimal runtime selection:
298316
}
299317
```
300318

301-
### Phase 4: CI/CD Integration
319+
### Phase 4: CI/CD Integration (Industry Best Practices)
302320

303-
#### 4.1 GitHub Actions Workflow
321+
#### 4.1 GitHub Actions Workflow (Based on OpenAI SDK Pattern)
304322

305323
Create `.github/workflows/runtime-tests.yml`:
306324

@@ -310,54 +328,114 @@ name: Runtime Compatibility Tests
310328
on: [push, pull_request]
311329

312330
jobs:
313-
test-runtimes:
331+
runtimes:
314332
runs-on: ubuntu-latest
333+
strategy:
334+
matrix:
335+
os: [ubuntu-latest]
336+
node: [18, 20]
337+
include:
338+
- runner: deno
339+
- runner: bun
315340

316341
steps:
317342
- uses: actions/checkout@v4
318343

319-
- name: Setup Node.js
344+
# Setup Node.js for matrix versions
345+
- if: matrix.runner != 'deno' && matrix.runner != 'bun'
320346
uses: actions/setup-node@v4
321347
with:
322-
node-version: '18'
323-
324-
- name: Setup Deno
325-
uses: denoland/setup-deno@v1
348+
node-version: ${{ matrix.node }}
349+
350+
# Setup Deno
351+
- if: matrix.runner == 'deno'
352+
uses: denoland/setup-deno@v2
326353
with:
327354
deno-version: v1.x
328-
329-
- name: Setup Bun
330-
uses: oven-sh/setup-bun@v1
355+
356+
# Setup Bun
357+
- if: matrix.runner == 'bun'
358+
uses: oven-sh/setup-bun@v2
331359

332360
- name: Install dependencies
333361
run: pnpm install
334362

335363
- name: Build
336364
run: pnpm build
337365

338-
- name: Test runtimes
339-
run: pnpm test:runtimes
366+
# Run runtime-specific tests
367+
- name: Test Node.js
368+
if: matrix.runner != 'deno' && matrix.runner != 'bun'
369+
run: pnpm test:node
370+
371+
- name: Test Deno
372+
if: matrix.runner == 'deno'
373+
run: pnpm test:deno
374+
375+
- name: Test Bun
376+
if: matrix.runner == 'bun'
377+
run: pnpm test:bun
378+
379+
- name: Test Edge/Workers
380+
if: matrix.runner != 'deno' && matrix.runner != 'bun'
381+
run: pnpm test:edge
382+
383+
# Fail-fast smoke tests (similar to OpenAI's ecosystem-tests)
384+
smoke-tests:
385+
runs-on: ubuntu-latest
386+
steps:
387+
- uses: actions/checkout@v4
388+
- uses: actions/setup-node@v4
389+
with:
390+
node-version: '20'
391+
- uses: denoland/setup-deno@v2
392+
with:
393+
deno-version: v1.x
394+
- uses: oven-sh/setup-bun@v2
395+
396+
- name: Install and build
397+
run: |
398+
pnpm install
399+
pnpm build
400+
401+
- name: Quick compatibility check
402+
run: |
403+
# Node.js
404+
node -e "console.log('✅ Node CJS:', require('./lib/cjs/index.cjs').WorkOS.name)"
405+
node -e "import('./lib/esm/index.js').then(m => console.log('✅ Node ESM:', m.WorkOS.name))"
406+
407+
# Deno
408+
deno run --allow-read -e "import('./lib/esm/index.js').then(m => console.log('✅ Deno:', m.WorkOS.name))"
409+
410+
# Bun
411+
bun -e "console.log('✅ Bun:', require('./lib/cjs/index.cjs').WorkOS.name)"
340412
```
341413
342414
## Implementation Timeline
343415
344-
### Week 1: Core Fix Implementation
345-
- [ ] Install and configure import rewriting solution
346-
- [ ] Update tsup configuration
347-
- [ ] Test basic functionality across runtimes
348-
- [ ] Fix any immediate issues
349-
350-
### Week 2: Testing & Validation
351-
- [ ] Implement comprehensive runtime tests
352-
- [ ] Validate Next.js/bundler compatibility still works
353-
- [ ] Test edge cases and error scenarios
354-
- [ ] Performance testing
355-
356-
### Week 3: CI/CD & Documentation
357-
- [ ] Set up automated runtime testing
358-
- [ ] Update documentation with runtime requirements
359-
- [ ] Create migration guide for users
360-
- [ ] Prepare release notes
416+
### Phase 1: Core Fix Implementation ✅ COMPLETE
417+
- [x] Install and configure import rewriting solution (`fixImportsPlugin`)
418+
- [x] Update tsup configuration with dual-build pattern
419+
- [x] Test basic functionality across runtimes
420+
- [x] Verify build outputs have correct extensions
421+
422+
### Phase 2: Testing Infrastructure ✅ COMPLETE
423+
- [x] Manual smoke tests for Node.js CJS/ESM
424+
- [x] Create runtime compatibility test suite (ecosystem-check.ts)
425+
- [x] Add runtime-specific npm scripts
426+
- [x] Test core runtimes: Node.js, Deno, Bun (5/5 passing)
427+
- [x] Install and configure testing dependencies (tsx, miniflare)
428+
429+
### Phase 3: Enhanced Package.json
430+
- [x] Basic dual-build exports structure
431+
- [ ] Add runtime-specific export conditions (`deno`, `bun`, `node`)
432+
- [ ] Optimize export map for performance
433+
434+
### Phase 4: Automated CI (Future)
435+
- [ ] Implement GitHub Actions matrix workflow
436+
- [ ] Add fail-fast smoke tests
437+
- [ ] Make runtime tests required for merge
438+
- [ ] Document CI setup for team
361439

362440
## Success Criteria
363441

0 commit comments

Comments
 (0)