fetchguard 2.1.2 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -516,67 +516,96 @@ await api.login(...) // has X-Client-Version, X-Platform, Accept-Langua
516
516
  2. `provider.headers` (auth requests only)
517
517
  3. Per-request headers (highest priority)
518
518
 
519
- ### Advanced: Custom Providers via Registry
519
+ ### Advanced: Custom Providers with workerFactory
520
520
 
521
- For complex auth flows, you can create custom providers and register them:
521
+ For complex auth flows with custom parsers or strategies, use `workerFactory` to create a custom worker:
522
+
523
+ **Step 1: Create custom worker file (my-worker.ts)**
522
524
 
523
525
  ```ts
524
- import { registerProvider, createClient, createProvider } from 'fetchguard'
525
- import { createIndexedDBStorage } from 'fetchguard'
526
- import { ok } from 'ts-micro-result'
526
+ // my-worker.ts
527
+ // IMPORTANT: Import from 'fetchguard/worker' to ensure same registry instance!
528
+ import {
529
+ registerProvider,
530
+ createProvider,
531
+ createIndexedDBStorage
532
+ } from 'fetchguard/worker'
527
533
 
528
- // Create custom provider
529
- const myProvider = createProvider({
534
+ // Register custom provider INSIDE the worker
535
+ registerProvider('my-custom-auth', createProvider({
530
536
  refreshStorage: createIndexedDBStorage('MyApp', 'refreshToken'),
531
537
  parser: {
532
538
  async parse(response: Response) {
533
539
  const data = await response.json()
540
+ // Custom response format
534
541
  return {
535
- token: data.accessToken,
536
- refreshToken: data.refreshToken,
537
- expiresAt: data.expiresAt,
538
- user: data.user
542
+ token: data.result.accessToken,
543
+ refreshToken: data.result.refreshToken,
544
+ expiresAt: data.result.exp * 1000,
545
+ user: data.result.profile
539
546
  }
540
547
  }
541
548
  },
542
549
  strategy: {
543
- async refreshToken(refreshToken: string | null) {
544
- const res = await fetch('https://api.example.com/auth/refresh', {
550
+ async refresh(refreshToken: string | null) {
551
+ return fetch('https://api.example.com/auth/refresh', {
545
552
  method: 'POST',
546
553
  headers: { 'Content-Type': 'application/json' },
547
554
  body: JSON.stringify({ refreshToken })
548
555
  })
549
- return res
550
556
  },
551
557
  async login(payload: unknown) {
552
- const res = await fetch('https://api.example.com/auth/login', {
558
+ return fetch('https://api.example.com/auth/login', {
553
559
  method: 'POST',
554
560
  headers: { 'Content-Type': 'application/json' },
555
561
  body: JSON.stringify(payload)
556
562
  })
557
- return res
558
563
  },
559
564
  async logout(payload?: unknown) {
560
- const res = await fetch('https://api.example.com/auth/logout', {
565
+ return fetch('https://api.example.com/auth/logout', {
561
566
  method: 'POST',
562
567
  headers: { 'Content-Type': 'application/json' },
563
568
  body: JSON.stringify(payload || {})
564
569
  })
565
- return res
570
+ },
571
+ async exchangeToken(accessToken: string, url: string, options?: { method?: string; payload?: unknown; headers?: Record<string, string> }) {
572
+ return fetch(url, {
573
+ method: options?.method || 'POST',
574
+ headers: {
575
+ 'Content-Type': 'application/json',
576
+ ...options?.headers,
577
+ 'Authorization': `Bearer ${accessToken}`
578
+ },
579
+ body: options?.payload ? JSON.stringify(options.payload) : undefined
580
+ })
566
581
  }
567
582
  }
568
- })
583
+ }))
584
+ ```
585
+
586
+ **Step 2: Use workerFactory in main thread**
569
587
 
570
- // Register provider
571
- registerProvider('my-custom-auth', myProvider)
588
+ ```ts
589
+ // main.ts
590
+ import { createClient } from 'fetchguard'
572
591
 
573
- // Use registered provider
574
592
  const api = createClient({
575
- provider: 'my-custom-auth', // Reference by name
593
+ provider: 'my-custom-auth', // Reference registered provider by name
594
+ workerFactory: () => new Worker(
595
+ new URL('./my-worker.ts', import.meta.url),
596
+ { type: 'module' }
597
+ ),
576
598
  allowedDomains: ['api.example.com']
577
599
  })
578
600
  ```
579
601
 
602
+ **Why workerFactory?**
603
+
604
+ - Functions cannot be serialized via `postMessage` (causes `DataCloneError`)
605
+ - `registerProvider` in main thread doesn't affect Worker (separate registries)
606
+ - Custom worker file bundles your provider code into the Worker context
607
+ - Full control over parser logic, strategy implementation, and storage
608
+
580
609
 
581
610
  ### Custom Auth Methods (Advanced)
582
611