@cshah18/sdk 4.7.0 → 4.9.0

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
@@ -236,40 +236,300 @@ The SDK automatically selects the appropriate API endpoint based on the `env` pa
236
236
 
237
237
  The backend URLs are managed internally by the SDK for security.
238
238
 
239
+ ## Performance Configuration
240
+
241
+ The SDK supports optional performance tuning for different network conditions and use cases. Configure these settings when initializing the SDK:
242
+
243
+ ```typescript
244
+ CoBuy.init({
245
+ merchantKey: "your-merchant-key",
246
+ env: "production",
247
+ performance: {
248
+ requestTimeout: 30000, // Default: 30000ms (30 seconds)
249
+ maxRetries: 2, // Default: 2
250
+ animationSpeed: "normal", // Default: "normal" ("fast" | "normal" | "slow")
251
+ },
252
+ });
253
+ ```
254
+
255
+ ### Configuration Options
256
+
257
+ #### `requestTimeout` (number, default: 30000)
258
+
259
+ Maximum time in milliseconds to wait for API requests before timing out.
260
+
261
+ **Use Cases:**
262
+
263
+ - **Slow Networks** (Mobile, poor connections): `60000` or `90000`
264
+ - **Fast Networks** (Fiber, corporate): `10000` or `15000`
265
+ - **Standard** (Default): `30000`
266
+
267
+ **Example - Slow Network:**
268
+
269
+ ```typescript
270
+ CoBuy.init({
271
+ merchantKey: "your-key",
272
+ performance: {
273
+ requestTimeout: 60000, // Wait up to 60 seconds for API responses
274
+ },
275
+ });
276
+ ```
277
+
278
+ #### `maxRetries` (number, default: 2)
279
+
280
+ Number of times to automatically retry failed API requests.
281
+
282
+ **Use Cases:**
283
+
284
+ - **Flaky Networks** (WiFi, variable connectivity): `3` or `4`
285
+ - **Stable Networks** (Fiber, datacenter): `1` or `2`
286
+ - **Offline-First Apps**: `0` (handle retries manually)
287
+
288
+ **Example - Flaky Network:**
289
+
290
+ ```typescript
291
+ CoBuy.init({
292
+ merchantKey: "your-key",
293
+ performance: {
294
+ maxRetries: 4, // Retry up to 4 times on failure
295
+ },
296
+ });
297
+ ```
298
+
299
+ #### `animationSpeed` (string, default: "normal")
300
+
301
+ Controls the speed of widget animations (open/close, transitions, etc).
302
+
303
+ **Options:**
304
+
305
+ - `"fast"` - Reduced animation duration for snappy interactions
306
+ - `"normal"` (default) - Standard animation timing
307
+ - `"slow"` - Extended animation duration for better visibility
308
+
309
+ **Example - Fast Animations:**
310
+
311
+ ```typescript
312
+ CoBuy.init({
313
+ merchantKey: "your-key",
314
+ theme: {
315
+ primaryColor: "#4f46e5",
316
+ },
317
+ performance: {
318
+ animationSpeed: "fast",
319
+ },
320
+ });
321
+ ```
322
+
323
+ ### Complete Example
324
+
325
+ ```typescript
326
+ CoBuy.init({
327
+ merchantKey: "pk_live_abc123xyz",
328
+ env: "production",
329
+ debug: true,
330
+ theme: {
331
+ primaryColor: "#4f46e5",
332
+ borderRadius: "8px",
333
+ },
334
+ performance: {
335
+ requestTimeout: 45000, // 45 seconds for slower connections
336
+ maxRetries: 3, // Retry 3 times on failure
337
+ animationSpeed: "normal", // Standard animation speed
338
+ },
339
+ });
340
+ ```
341
+
342
+ ### Default Behavior
343
+
344
+ If performance config is not provided, the SDK uses sensible defaults optimized for typical production environments:
345
+
346
+ ```typescript
347
+ {
348
+ requestTimeout: 30000,
349
+ maxRetries: 2,
350
+ animationSpeed: "normal"
351
+ }
352
+ ```
353
+
239
354
  ## Error Handling
240
355
 
241
- The SDK includes custom error classes:
356
+ The SDK uses a **standardized error handling approach** for different operation types:
357
+
358
+ ### Error Patterns by Method Type
359
+
360
+ **1. Initialization & Validation Methods** - Throw synchronous errors
361
+
362
+ - `CoBuy.init()` - Throws errors for invalid configuration
363
+ - `ConfigManager.setConfig()` - Throws errors for validation failure
364
+
365
+ **2. Widget Rendering** - Returns Promise that may reject
366
+
367
+ - `CoBuy.renderWidget()` - Returns `Promise<void>` that rejects on rendering errors
368
+ - Can be handled with try/catch OR .catch()
369
+
370
+ **3. API Methods** - Return ApiResponse<T> (no exceptions)
371
+
372
+ - `apiClient.getProductReward()` - Returns `{success: true|false, data?, error?}`
373
+ - Check `response.success` to determine outcome
374
+
375
+ ### Custom Error Classes
242
376
 
243
- ### `CoBuyNotInitializedError`
377
+ #### `CoBuyNotInitializedError`
244
378
 
245
- Thrown when attempting to use the SDK before calling `init()`.
379
+ Thrown when attempting to use SDK features before calling `CoBuy.init()`.
246
380
 
247
381
  ```typescript
248
382
  try {
249
383
  CoBuy.renderWidget({
250
- /* ... */
384
+ productId: "prod_123",
385
+ container: "#widget",
251
386
  });
252
387
  } catch (error) {
253
388
  if (error instanceof CoBuyNotInitializedError) {
254
- console.error("SDK not initialized");
389
+ console.error("SDK must be initialized first");
390
+ CoBuy.init({ merchantKey: "your-key" });
255
391
  }
256
392
  }
257
393
  ```
258
394
 
259
- ### `CoBuyInvalidConfigError`
395
+ #### `CoBuyInvalidConfigError`
260
396
 
261
- Thrown when invalid configuration is provided to `init()`.
397
+ Thrown when invalid configuration is provided to `CoBuy.init()`.
262
398
 
263
399
  ```typescript
264
400
  try {
265
- CoBuy.init({ merchantKey: "" }); // Invalid
401
+ CoBuy.init({
402
+ authMode: "public",
403
+ // Missing required merchantKey
404
+ });
266
405
  } catch (error) {
267
406
  if (error instanceof CoBuyInvalidConfigError) {
268
- console.error("Invalid configuration:", error.message);
407
+ console.error("Config validation failed:", error.message);
408
+ console.error("Error code:", error.code); // "INVALID_CONFIG"
269
409
  }
270
410
  }
271
411
  ```
272
412
 
413
+ #### `CoBuyRenderError`
414
+
415
+ Thrown when widget rendering fails (container not found, DOM issues, etc).
416
+
417
+ ```typescript
418
+ try {
419
+ await CoBuy.renderWidget({
420
+ productId: "prod_123",
421
+ container: "#nonexistent-container",
422
+ });
423
+ } catch (error) {
424
+ if (error instanceof CoBuyRenderError) {
425
+ console.error("Widget render failed:", error.message);
426
+ console.error("Container selector:", error.details?.selector);
427
+ }
428
+ }
429
+ ```
430
+
431
+ #### `CoBuyValidationError`
432
+
433
+ Thrown when input validation fails (invalid product ID, invalid container selector, etc).
434
+
435
+ ```typescript
436
+ try {
437
+ await CoBuy.renderWidget({
438
+ productId: "", // Invalid: empty string
439
+ container: "#widget",
440
+ });
441
+ } catch (error) {
442
+ if (error instanceof CoBuyValidationError) {
443
+ console.error("Input validation failed:", error.message);
444
+ console.error("Details:", error.details); // { productId: '' }
445
+ }
446
+ }
447
+ ```
448
+
449
+ #### `CoBuyApiError`
450
+
451
+ Thrown when API communication fails (network errors, CORS issues, API errors, etc).
452
+
453
+ ```typescript
454
+ const apiClient = CoBuy.getApiClient();
455
+ try {
456
+ const response = await apiClient.getProductReward("prod_123");
457
+ if (!response.success) {
458
+ // API returned error response - check error details
459
+ console.error("API Error:", response.error?.code);
460
+ if (response.error?.statusCode === 429) {
461
+ console.log("Rate limited - retry after delay");
462
+ }
463
+ }
464
+ } catch (error) {
465
+ // This usually doesn't happen as ApiClient returns ApiResponse
466
+ // But some methods may throw CoBuyApiError
467
+ if (error instanceof CoBuyApiError) {
468
+ console.error("API Error:", error.message);
469
+ console.error("Code:", error.code);
470
+ }
471
+ }
472
+ ```
473
+
474
+ ### Error Base Class
475
+
476
+ All custom errors inherit from `CoBuyError` which provides consistent structure:
477
+
478
+ ```typescript
479
+ class CoBuyError extends Error {
480
+ code: string; // Error code for programmatic handling
481
+ details?: unknown; // Additional error details
482
+ }
483
+ ```
484
+
485
+ ### Handling Different Error Types
486
+
487
+ ```typescript
488
+ import {
489
+ CoBuyError,
490
+ CoBuyNotInitializedError,
491
+ CoBuyInvalidConfigError,
492
+ CoBuyRenderError,
493
+ CoBuyValidationError,
494
+ CoBuyApiError,
495
+ } from "@cobuy/sdk";
496
+
497
+ // Universal error handler
498
+ async function renderWithErrorHandling() {
499
+ try {
500
+ await CoBuy.renderWidget({
501
+ productId: "prod_123",
502
+ container: "#widget",
503
+ });
504
+ } catch (error) {
505
+ if (error instanceof CoBuyNotInitializedError) {
506
+ // Handle: SDK not initialized
507
+ console.error("Please call CoBuy.init() first");
508
+ } else if (error instanceof CoBuyInvalidConfigError) {
509
+ // Handle: Bad configuration
510
+ console.error("Check your init options:", error.message);
511
+ } else if (error instanceof CoBuyValidationError) {
512
+ // Handle: Invalid input
513
+ console.error("Input validation failed:", error.details);
514
+ } else if (error instanceof CoBuyRenderError) {
515
+ // Handle: Rendering failed
516
+ console.error("Failed to render widget:", error.message);
517
+ } else if (error instanceof CoBuyApiError) {
518
+ // Handle: API communication failed
519
+ console.error("API error:", error.code);
520
+ } else if (error instanceof CoBuyError) {
521
+ // Handle: Other CoBuy errors
522
+ console.error("SDK error:", error.code);
523
+ } else {
524
+ // Handle: Unexpected error
525
+ console.error("Unexpected error:", error);
526
+ }
527
+ }
528
+ }
529
+ ```
530
+
531
+ > 📖 **Comprehensive Error Reference**: See [ERROR_CODES.md](./docs/ERROR_CODES.md) for complete list of all error codes, handling strategies, and debugging guidance.
532
+
273
533
  ## Debugging
274
534
 
275
535
  Enable debug logging to monitor SDK operations:
@@ -287,6 +547,14 @@ When debug mode is enabled, the SDK logs:
287
547
  - Environment and API base URL
288
548
  - Widget rendering operations
289
549
 
550
+ ## Migration Guide
551
+
552
+ For breaking changes and upgrade steps, see [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md).
553
+
554
+ ## Versioning & Changelog
555
+
556
+ This project follows Semantic Versioning and tracks changes in [CHANGELOG.md](CHANGELOG.md).
557
+
290
558
  ## Project Structure
291
559
 
292
560
  ```
@@ -328,7 +596,7 @@ npm install
328
596
 
329
597
  ### Scripts
330
598
 
331
- ```bash
599
+ ````bash
332
600
  # Build the SDK
333
601
  npm run build
334
602
 
@@ -363,8 +631,9 @@ npm run version:prerelease
363
631
 
364
632
  # After bumping, push manually if desired
365
633
  git push && git push --tags
366
- ```
367
- ```
634
+ ````
635
+
636
+ ````
368
637
 
369
638
  ### Code Quality
370
639
 
@@ -407,7 +676,7 @@ const options: CoBuyInitOptions = {
407
676
  };
408
677
 
409
678
  CoBuy.init(options);
410
- ```
679
+ ````
411
680
 
412
681
  ## Configuration Examples
413
682
 
@@ -461,6 +730,175 @@ CoBuy.renderWidget({
461
730
  });
462
731
  ```
463
732
 
733
+ ## Implementation Status
734
+
735
+ ### ✅ Complete & Stable
736
+
737
+ - **Core Widget Rendering**: Fully implemented with loading states, error handling, and retry logic
738
+ - **Product Reward Display**: Real-time reward data fetching with TTL-based caching
739
+ - **Group Management**: Automatic group creation and joining with progress tracking
740
+ - **Lobby Modal**: Full-featured group coordination UI with sharing, offline redemption, and real-time updates
741
+ - **Authentication**: Support for both public (merchant key) and token-based auth modes
742
+ - **Theme Customization**: Comprehensive theming with colors, animations, and typography
743
+ - **Accessibility (WCAG AA)**:
744
+ - Keyboard navigation and focus management
745
+ - Screen reader support with ARIA labels and live regions
746
+ - Semantic HTML and proper heading hierarchy
747
+ - Color contrast compliance
748
+ - **Input Validation**: Comprehensive validation for colors, product IDs, and auth credentials
749
+ - **Request Optimization**:
750
+ - Response caching with 60s TTL for product rewards
751
+ - Request deduplication for concurrent identical calls
752
+ - Automatic timeout cleanup to prevent memory leaks
753
+ - Debounced group data refreshes
754
+ - **Error Handling**: Custom error classes with descriptive messages
755
+ - **TypeScript Support**: Full type definitions with strict mode enabled
756
+ - **Browser Compatibility**: ES2017+ support (Chrome 51+, Firefox 54+, Safari 10+)
757
+
758
+ ### 🟡 Partial Implementation
759
+
760
+ - **Offline Redemption**: QR code generation and manual code entry supported; SMS/email delivery backend integration pending
761
+
762
+ ---
763
+
764
+ ## Known Limitations
765
+
766
+ ### Technical Limitations
767
+
768
+ 1. **Bundle Size**: ~7.5 KB minified/gzipped (unavoidable due to full modal UI + real-time features)
769
+ 2. **Single Instance Per Container**: Only one widget can render per DOM container; multiple products require multiple containers
770
+ 3. **Modal Stacking**: Only one modal (lobby or group list) can be open simultaneously
771
+ 4. **Network Timeout Guarantees**: Hard timeout of 30 seconds on all API calls; no built-in retry for transient 5xx errors
772
+ 5. **CSS Scoping**: Widget uses CSS custom properties; global CSS may override if specificity is higher
773
+
774
+ ### Browser/Platform Limitations
775
+
776
+ 1. **No IE11 Support**: SDK targets ES2017+ only
777
+ 2. **WebSocket Required**: Real-time features require WebSocket support (unavailable in some corporate networks)
778
+ 3. **Third-Party Cookies**: Social sharing (WhatsApp, Facebook) requires third-party cookie support
779
+ 4. **Offline Mode**: Limited; QR code works offline, but group sync requires network connectivity
780
+
781
+ ### API/Data Limitations
782
+
783
+ 1. **Reward Expiry**: Expired rewards show as inactive; no pre-expiry notifications (planned for v2.0)
784
+ 2. **Group Capacity**: Max 999 participants per group (theoretical limit); recommend splitting larger promotions
785
+ 3. **Concurrency**: Widget serializes renders to prevent race conditions; may add concurrent render support in v2.0
786
+ 4. **Rate Limiting**: No built-in request rate limiting client-side (server enforces)
787
+
788
+ ---
789
+
790
+ ## Performance Improvements
791
+
792
+ - Lazy-load modal components (reduce initial bundle by ~2 KB)
793
+ - Implement virtual scrolling for activity feeds (currently loads all items)
794
+ - Add service worker for offline caching of static assets
795
+
796
+ ## Migration Guide
797
+
798
+ ### From Older SDK Versions (v0.x → v1.0)
799
+
800
+ #### Breaking Changes
801
+
802
+ 1. **API Client Access**
803
+
804
+ **v0.x:**
805
+
806
+ ```typescript
807
+ const client = window.CoBuy.apiClient;
808
+ ```
809
+
810
+ **v1.0:**
811
+
812
+ ```typescript
813
+ const client = window.CoBuy.getApiClient();
814
+ ```
815
+
816
+ 2. **Event Callback Names**
817
+
818
+ **v0.x:**
819
+
820
+ ```typescript
821
+ CoBuy.renderWidget({
822
+ onGroupJoined: (groupId) => {},
823
+ onCheckoutInitiated: (data) => {},
824
+ });
825
+ ```
826
+
827
+ **v1.0:**
828
+
829
+ ```typescript
830
+ CoBuy.renderWidget({
831
+ onCheckout: (data) => {}, // Consolidated
832
+ });
833
+ ```
834
+
835
+ 3. **Error Handling**
836
+
837
+ **v0.x:**
838
+
839
+ ```typescript
840
+ try {
841
+ CoBuy.renderWidget({
842
+ /*...*/
843
+ });
844
+ } catch (error) {
845
+ if (error.code === "INVALID_CONFIG") {
846
+ }
847
+ }
848
+ ```
849
+
850
+ **v1.0:**
851
+
852
+ ```typescript
853
+ try {
854
+ CoBuy.renderWidget({
855
+ /*...*/
856
+ });
857
+ } catch (error) {
858
+ if (error instanceof CoBuyInvalidConfigError) {
859
+ }
860
+ }
861
+ ```
862
+
863
+ #### Migration Steps
864
+
865
+ 1. **Update initialization:**
866
+
867
+ ```typescript
868
+ // v0.x
869
+ CoBuy.initialize({ apiKey: "pk_..." });
870
+
871
+ // v1.0
872
+ CoBuy.init({ merchantKey: "pk_..." });
873
+ ```
874
+
875
+ 2. **Update theme property names:**
876
+
877
+ ```typescript
878
+ // v0.x
879
+ theme: {
880
+ buttonColor: "#...",
881
+ darkBg: false,
882
+ }
883
+
884
+ // v1.0
885
+ theme: {
886
+ primaryColor: "#...",
887
+ // Dark mode coming in v2.0
888
+ }
889
+ ```
890
+
891
+ 3. **Update error handling:**
892
+ - Import error classes: `import { CoBuyInvalidConfigError } from "@cobuy/sdk"`
893
+ - Check `error instanceof ErrorClass` instead of error codes
894
+
895
+ #### Deprecations
896
+
897
+ These will be removed in v2.0:
898
+
899
+ - ❌ `CoBuy.getRawApiClient()` — Use `CoBuy.getApiClient()` instead
900
+ - ❌ `options.onGroupJoined` callback — Use `onCheckout` instead
901
+
464
902
  ## License
465
903
 
466
904
  MIT
@@ -471,5 +909,5 @@ For issues, feature requests, or questions, please contact support@cobuy.app or
471
909
 
472
910
  ---
473
911
 
474
- **Version**: 1.0.0
475
- **Last Updated**: December 2025
912
+ **Version**: 1.0.0
913
+ **Last Updated**: February 2026