@@ -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
305323Create ` .github/workflows/runtime-tests.yml ` :
306324
@@ -310,54 +328,114 @@ name: Runtime Compatibility Tests
310328on : [push, pull_request]
311329
312330jobs :
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