@felixgeelhaar/govee-api-client 1.1.0 โ†’ 2.0.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.
Files changed (68) hide show
  1. package/README.md +160 -7
  2. package/dist/GoveeClient.d.ts +31 -0
  3. package/dist/GoveeClient.d.ts.map +1 -1
  4. package/dist/GoveeClient.js +33 -0
  5. package/dist/GoveeClient.js.map +1 -1
  6. package/dist/errors/GoveeApiError.d.ts +1 -1
  7. package/dist/errors/GoveeApiError.d.ts.map +1 -1
  8. package/dist/errors/GoveeApiError.js +9 -2
  9. package/dist/errors/GoveeApiError.js.map +1 -1
  10. package/dist/errors/ValidationError.d.ts +28 -0
  11. package/dist/errors/ValidationError.d.ts.map +1 -0
  12. package/dist/errors/ValidationError.js +44 -0
  13. package/dist/errors/ValidationError.js.map +1 -0
  14. package/dist/errors/index.d.ts +1 -0
  15. package/dist/errors/index.d.ts.map +1 -1
  16. package/dist/errors/index.js +1 -0
  17. package/dist/errors/index.js.map +1 -1
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/infrastructure/GoveeDeviceRepository.d.ts.map +1 -1
  23. package/dist/infrastructure/GoveeDeviceRepository.js +26 -3
  24. package/dist/infrastructure/GoveeDeviceRepository.js.map +1 -1
  25. package/dist/infrastructure/SlidingWindowRateLimiter.d.ts +83 -0
  26. package/dist/infrastructure/SlidingWindowRateLimiter.d.ts.map +1 -0
  27. package/dist/infrastructure/SlidingWindowRateLimiter.js +218 -0
  28. package/dist/infrastructure/SlidingWindowRateLimiter.js.map +1 -0
  29. package/dist/infrastructure/index.d.ts +2 -0
  30. package/dist/infrastructure/index.d.ts.map +1 -1
  31. package/dist/infrastructure/index.js +2 -0
  32. package/dist/infrastructure/index.js.map +1 -1
  33. package/dist/infrastructure/response-schemas.d.ts +82 -0
  34. package/dist/infrastructure/response-schemas.d.ts.map +1 -0
  35. package/dist/infrastructure/response-schemas.js +59 -0
  36. package/dist/infrastructure/response-schemas.js.map +1 -0
  37. package/dist/infrastructure/retry/IntegrationGuide.d.ts +133 -0
  38. package/dist/infrastructure/retry/IntegrationGuide.d.ts.map +1 -0
  39. package/dist/infrastructure/retry/IntegrationGuide.js +295 -0
  40. package/dist/infrastructure/retry/IntegrationGuide.js.map +1 -0
  41. package/dist/infrastructure/retry/RetryConfigPresets.d.ts +114 -0
  42. package/dist/infrastructure/retry/RetryConfigPresets.d.ts.map +1 -0
  43. package/dist/infrastructure/retry/RetryConfigPresets.js +406 -0
  44. package/dist/infrastructure/retry/RetryConfigPresets.js.map +1 -0
  45. package/dist/infrastructure/retry/RetryPolicy.d.ts +148 -0
  46. package/dist/infrastructure/retry/RetryPolicy.d.ts.map +1 -0
  47. package/dist/infrastructure/retry/RetryPolicy.js +373 -0
  48. package/dist/infrastructure/retry/RetryPolicy.js.map +1 -0
  49. package/dist/infrastructure/retry/RetryableRepository.d.ts +75 -0
  50. package/dist/infrastructure/retry/RetryableRepository.d.ts.map +1 -0
  51. package/dist/infrastructure/retry/RetryableRepository.js +142 -0
  52. package/dist/infrastructure/retry/RetryableRepository.js.map +1 -0
  53. package/dist/infrastructure/retry/RetryableRequest.d.ts +132 -0
  54. package/dist/infrastructure/retry/RetryableRequest.d.ts.map +1 -0
  55. package/dist/infrastructure/retry/RetryableRequest.js +248 -0
  56. package/dist/infrastructure/retry/RetryableRequest.js.map +1 -0
  57. package/dist/infrastructure/retry/index.d.ts +35 -0
  58. package/dist/infrastructure/retry/index.d.ts.map +1 -0
  59. package/dist/infrastructure/retry/index.js +36 -0
  60. package/dist/infrastructure/retry/index.js.map +1 -0
  61. package/dist/services/GoveeControlService.d.ts +53 -0
  62. package/dist/services/GoveeControlService.d.ts.map +1 -1
  63. package/dist/services/GoveeControlService.js +138 -12
  64. package/dist/services/GoveeControlService.js.map +1 -1
  65. package/docs/EXAMPLES.md +799 -0
  66. package/docs/LLM_API_REFERENCE.md +425 -0
  67. package/docs/TYPE_DEFINITIONS.md +803 -0
  68. package/package.json +25 -16
package/README.md CHANGED
@@ -5,14 +5,16 @@
5
5
  [![CI](https://github.com/felixgeelhaar/govee-api-client/workflows/CI/badge.svg)](https://github.com/felixgeelhaar/govee-api-client/actions)
6
6
  [![codecov](https://codecov.io/gh/felixgeelhaar/govee-api-client/branch/main/graph/badge.svg)](https://codecov.io/gh/felixgeelhaar/govee-api-client)
7
7
 
8
- An enterprise-grade TypeScript client library for the Govee Developer REST API. Built with Domain-Driven Design (DDD) principles and comprehensive error handling.
8
+ An enterprise-grade TypeScript client library for the Govee Developer REST API. Built with Domain-Driven Design (DDD) principles, comprehensive error handling, and production-ready rate limiting and retry capabilities.
9
9
 
10
10
  ## Features
11
11
 
12
12
  - ๐ŸŽฏ **Type-Safe**: Full TypeScript support with comprehensive type definitions
13
13
  - ๐Ÿ—๏ธ **Domain-Driven Design**: Clean architecture following DDD principles
14
- - โšก **Rate Limiting**: Built-in rate limiting to prevent API throttling
14
+ - โšก **Rate Limiting**: High-performance sliding window rate limiter with burst capability
15
+ - ๐Ÿ”„ **Retry Logic**: Enterprise-grade retry with exponential backoff, jitter, and circuit breaker
15
16
  - ๐Ÿ›ก๏ธ **Error Handling**: Comprehensive error hierarchy with specific error types
17
+ - ๐Ÿ“Š **Observability**: Built-in metrics and monitoring for rate limiting and retries
16
18
  - ๐Ÿ“ **Logging**: Configurable logging with Pino integration
17
19
  - ๐Ÿงช **Well Tested**: >95% test coverage with unit and integration tests
18
20
  - ๐Ÿš€ **Production Ready**: Enterprise-grade reliability and performance
@@ -60,12 +62,15 @@ if (livingRoomLight) {
60
62
 
61
63
  ```typescript
62
64
  import pino from 'pino';
65
+ import { GoveeClient, RetryPolicy } from '@felixgeelhaar/govee-api-client';
63
66
 
64
67
  const client = new GoveeClient({
65
68
  apiKey: 'your-govee-api-key',
66
69
  timeout: 30000, // Request timeout in milliseconds (default: 30000)
67
- rateLimit: 100, // Requests per minute (default: 100)
70
+ rateLimit: 95, // Requests per minute (default: 95, with 5 buffer under Govee's limit)
68
71
  logger: pino({ level: 'info' }), // Optional logger (silent by default)
72
+ enableRetries: true, // Enable retry functionality (default: false)
73
+ retryPolicy: 'production', // Retry policy preset or custom RetryPolicy instance
69
74
  });
70
75
  ```
71
76
 
@@ -187,18 +192,166 @@ try {
187
192
  }
188
193
  ```
189
194
 
190
- ## Rate Limiting
195
+ ## Rate Limiting & Retry Features
191
196
 
192
- The client automatically handles rate limiting according to Govee's API limits (100 requests per minute by default). All requests are queued and throttled appropriately.
197
+ The client includes enterprise-grade rate limiting and retry capabilities designed for production environments.
198
+
199
+ ### Rate Limiting
200
+
201
+ Uses a high-performance sliding window rate limiter that allows bursts up to the limit while maintaining the average rate over time:
193
202
 
194
203
  ```typescript
195
- // Customize rate limiting
196
204
  const client = new GoveeClient({
197
205
  apiKey: 'your-api-key',
198
- rateLimit: 60, // 60 requests per minute
206
+ rateLimit: 95, // Default: 95 req/min (5 request buffer under Govee's 100/min limit)
199
207
  });
208
+
209
+ // Monitor rate limiter performance
210
+ const stats = client.getRateLimiterStats();
211
+ console.log(`Current utilization: ${stats.utilizationPercent}%`);
212
+ console.log(`Queue size: ${stats.queueSize}`);
213
+ console.log(`Can execute immediately: ${stats.canExecuteImmediately}`);
214
+ ```
215
+
216
+ ### Retry Logic
217
+
218
+ Comprehensive retry functionality with exponential backoff, jitter, and circuit breaker:
219
+
220
+ ```typescript
221
+ const client = new GoveeClient({
222
+ apiKey: 'your-api-key',
223
+ enableRetries: true,
224
+ retryPolicy: 'production', // 'development', 'testing', 'production'
225
+ });
226
+
227
+ // Monitor retry performance
228
+ const retryMetrics = client.getRetryMetrics();
229
+ if (retryMetrics) {
230
+ console.log(`Total retry attempts: ${retryMetrics.totalAttempts}`);
231
+ console.log(`Success rate: ${retryMetrics.successfulRetries}/${retryMetrics.totalAttempts}`);
232
+ console.log(`Circuit breaker state: ${retryMetrics.circuitBreakerState}`);
233
+ }
200
234
  ```
201
235
 
236
+ ### Custom Retry Policies
237
+
238
+ Create custom retry policies for specific requirements:
239
+
240
+ ```typescript
241
+ import {
242
+ GoveeClient,
243
+ RetryPolicy,
244
+ RateLimitError,
245
+ NetworkError,
246
+ GoveeApiError,
247
+ } from '@felixgeelhaar/govee-api-client';
248
+
249
+ const customRetryPolicy = new RetryPolicy({
250
+ backoff: {
251
+ type: 'exponential',
252
+ initialDelayMs: 1000,
253
+ maxDelayMs: 30000,
254
+ multiplier: 2.0,
255
+ },
256
+ jitter: {
257
+ type: 'equal',
258
+ factor: 0.1,
259
+ },
260
+ condition: {
261
+ maxAttempts: 3,
262
+ maxTotalTimeMs: 60000,
263
+ retryableStatusCodes: [408, 429, 502, 503, 504],
264
+ retryableErrorTypes: [RateLimitError, NetworkError, GoveeApiError],
265
+ },
266
+ circuitBreaker: {
267
+ enabled: true,
268
+ failureThreshold: 5,
269
+ recoveryTimeoutMs: 30000,
270
+ halfOpenSuccessThreshold: 2,
271
+ },
272
+ enableMetrics: true,
273
+ });
274
+
275
+ const client = new GoveeClient({
276
+ apiKey: 'your-api-key',
277
+ enableRetries: true,
278
+ retryPolicy: customRetryPolicy,
279
+ });
280
+ ```
281
+
282
+ ### Monitoring & Observability
283
+
284
+ Get comprehensive metrics for monitoring and debugging:
285
+
286
+ ```typescript
287
+ // Get complete service statistics
288
+ const serviceStats = client.getServiceStats();
289
+ console.log('Rate Limiter:', serviceStats.rateLimiter);
290
+ console.log('Retry Metrics:', serviceStats.retries);
291
+ console.log('Configuration:', serviceStats.configuration);
292
+
293
+ // Rate limiter specific stats
294
+ const rateLimiterStats = client.getRateLimiterStats();
295
+ console.log({
296
+ currentRequests: rateLimiterStats.currentRequests,
297
+ maxRequests: rateLimiterStats.maxRequests,
298
+ utilizationPercent: rateLimiterStats.utilizationPercent,
299
+ queueSize: rateLimiterStats.queueSize,
300
+ canExecuteImmediately: rateLimiterStats.canExecuteImmediately,
301
+ nextAvailableSlot: rateLimiterStats.nextAvailableSlot,
302
+ });
303
+
304
+ // Retry metrics (when retries are enabled)
305
+ const retryMetrics = client.getRetryMetrics();
306
+ if (retryMetrics) {
307
+ console.log({
308
+ totalAttempts: retryMetrics.totalAttempts,
309
+ successfulRetries: retryMetrics.successfulRetries,
310
+ failedRetries: retryMetrics.failedRetries,
311
+ totalRetryTimeMs: retryMetrics.totalRetryTimeMs,
312
+ averageRetryDelayMs: retryMetrics.averageRetryDelayMs,
313
+ circuitBreakerState: retryMetrics.circuitBreakerState,
314
+ lastError: retryMetrics.lastError?.message,
315
+ lastRetryTimestamp: retryMetrics.lastRetryTimestamp,
316
+ });
317
+ }
318
+
319
+ // Reset metrics for clean monitoring periods
320
+ client.resetRetryMetrics();
321
+ ```
322
+
323
+ ### Retry Policy Presets
324
+
325
+ The library includes three built-in retry policy presets optimized for different environments:
326
+
327
+ #### Production (Default)
328
+
329
+ - **Max attempts**: 3
330
+ - **Backoff**: Exponential with 1s initial delay, 30s max
331
+ - **Circuit breaker**: Enabled (5 failures to open, 30s recovery)
332
+ - **Jitter**: Equal jitter to prevent thundering herd
333
+
334
+ #### Development
335
+
336
+ - **Max attempts**: 5
337
+ - **Backoff**: Exponential with 500ms initial delay, 15s max
338
+ - **Circuit breaker**: Disabled for easier debugging
339
+ - **Jitter**: Full jitter for maximum randomization
340
+
341
+ #### Testing
342
+
343
+ - **Max attempts**: 2
344
+ - **Backoff**: Exponential with 2s initial delay, 60s max
345
+ - **Circuit breaker**: Enabled with conservative settings
346
+ - **Jitter**: Decorrelated jitter for sophisticated patterns
347
+
348
+ ### Performance Characteristics
349
+
350
+ - **Rate Limiter**: High-performance sliding window allows concurrent execution within limits
351
+ - **Memory Efficient**: Automatic cleanup of expired timestamps and bounded queue sizes
352
+ - **Production Ready**: Circuit breaker prevents cascade failures
353
+ - **Observable**: Comprehensive metrics for monitoring and alerting
354
+
202
355
  ## Domain-Driven Design
203
356
 
204
357
  The library follows DDD principles with clear separation of concerns:
@@ -3,11 +3,14 @@ import { GoveeDevice } from './domain/entities/GoveeDevice';
3
3
  import { DeviceState } from './domain/entities/DeviceState';
4
4
  import { Command } from './domain/entities/Command';
5
5
  import { ColorRgb, ColorTemperature, Brightness } from './domain/value-objects';
6
+ import { RetryPolicy } from './infrastructure/retry';
6
7
  export interface GoveeClientConfig {
7
8
  apiKey: string;
8
9
  timeout?: number;
9
10
  rateLimit?: number;
10
11
  logger?: Logger;
12
+ enableRetries?: boolean;
13
+ retryPolicy?: 'development' | 'testing' | 'production' | 'custom' | RetryPolicy;
11
14
  }
12
15
  export declare class GoveeClient {
13
16
  private readonly controlService;
@@ -31,5 +34,33 @@ export declare class GoveeClient {
31
34
  turnOnWithColorTemperature(deviceId: string, model: string, colorTemperature: ColorTemperature, brightness?: Brightness): Promise<void>;
32
35
  isDeviceOnline(deviceId: string, model: string): Promise<boolean>;
33
36
  isDevicePoweredOn(deviceId: string, model: string): Promise<boolean>;
37
+ getRateLimiterStats(): {
38
+ currentRequests: number;
39
+ maxRequests: number;
40
+ queueSize: number;
41
+ windowMs: number;
42
+ utilizationPercent: number;
43
+ canExecuteImmediately: boolean;
44
+ nextAvailableSlot: number;
45
+ };
46
+ getRetryMetrics(): Readonly<import("./infrastructure/retry").RetryMetrics> | null;
47
+ getServiceStats(): {
48
+ rateLimiter: {
49
+ currentRequests: number;
50
+ maxRequests: number;
51
+ queueSize: number;
52
+ windowMs: number;
53
+ utilizationPercent: number;
54
+ canExecuteImmediately: boolean;
55
+ nextAvailableSlot: number;
56
+ };
57
+ retries: Readonly<import("./infrastructure/retry").RetryMetrics> | null;
58
+ configuration: {
59
+ enableRetries: boolean;
60
+ rateLimit: number;
61
+ };
62
+ };
63
+ resetRetryMetrics(): void;
64
+ isRetryEnabled(): boolean;
34
65
  }
35
66
  //# sourceMappingURL=GoveeClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"GoveeClient.d.ts","sourceRoot":"","sources":["../src/GoveeClient.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEhF,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,iBAAiB;IAiCrC,OAAO,CAAC,cAAc;IAmBhB,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAIpC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIrE,sBAAsB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAIhD,qBAAqB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI/C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAItE,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKzD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7E,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrF,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzE,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,IAAI,CAAC;IAKV,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,IAAI,CAAC;IAIV,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,QAAQ,EACf,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,IAAI,CAAC;IAIV,0BAA0B,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,IAAI,CAAC;IASV,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAG3E"}
1
+ {"version":3,"file":"GoveeClient.d.ts","sourceRoot":"","sources":["../src/GoveeClient.ts"],"names":[],"mappings":"AAAA,OAAa,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,aAAa,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;CACjF;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,iBAAiB;IAyCrC,OAAO,CAAC,cAAc;IAiChB,UAAU,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAIpC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAIrE,sBAAsB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAIhD,qBAAqB,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAI/C,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAItE,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAKzD,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7E,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvD,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrF,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzE,mBAAmB,CACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,IAAI,CAAC;IAKV,oBAAoB,CACxB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,IAAI,CAAC;IAIV,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,QAAQ,EACf,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,IAAI,CAAC;IAIV,0BAA0B,CAC9B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,gBAAgB,EAClC,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,IAAI,CAAC;IASV,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIjE,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAK1E,mBAAmB;;;;;;;;;IAInB,eAAe;IAIf,eAAe;;;;;;;;;;;;;;;;IAIf,iBAAiB,IAAI,IAAI;IAIzB,cAAc,IAAI,OAAO;CAG1B"}
@@ -1,6 +1,7 @@
1
1
  import pino from 'pino';
2
2
  import { GoveeDeviceRepository } from './infrastructure/GoveeDeviceRepository';
3
3
  import { GoveeControlService } from './services/GoveeControlService';
4
+ import { RetryPolicy } from './infrastructure/retry';
4
5
  export class GoveeClient {
5
6
  constructor(config) {
6
7
  this.validateConfig(config);
@@ -23,6 +24,12 @@ export class GoveeClient {
23
24
  if (config.rateLimit !== undefined) {
24
25
  serviceConfig.rateLimit = config.rateLimit;
25
26
  }
27
+ if (config.enableRetries !== undefined) {
28
+ serviceConfig.enableRetries = config.enableRetries;
29
+ }
30
+ if (config.retryPolicy !== undefined) {
31
+ serviceConfig.retryPolicy = config.retryPolicy;
32
+ }
26
33
  this.controlService = new GoveeControlService(serviceConfig);
27
34
  this.logger.info('GoveeClient initialized successfully');
28
35
  }
@@ -38,6 +45,16 @@ export class GoveeClient {
38
45
  (!Number.isInteger(config.rateLimit) || config.rateLimit <= 0)) {
39
46
  throw new Error('Rate limit must be a positive integer');
40
47
  }
48
+ if (config.enableRetries !== undefined && typeof config.enableRetries !== 'boolean') {
49
+ throw new Error('enableRetries must be a boolean');
50
+ }
51
+ if (config.retryPolicy !== undefined) {
52
+ const validPolicies = ['development', 'testing', 'production', 'custom'];
53
+ if (!(config.retryPolicy instanceof RetryPolicy) &&
54
+ !validPolicies.includes(config.retryPolicy)) {
55
+ throw new Error('retryPolicy must be a RetryPolicy instance or one of: development, testing, production, custom');
56
+ }
57
+ }
41
58
  }
42
59
  // Device management methods
43
60
  async getDevices() {
@@ -93,5 +110,21 @@ export class GoveeClient {
93
110
  async isDevicePoweredOn(deviceId, model) {
94
111
  return this.controlService.isDevicePoweredOn(deviceId, model);
95
112
  }
113
+ // Monitoring and debugging methods
114
+ getRateLimiterStats() {
115
+ return this.controlService.getRateLimiterStats();
116
+ }
117
+ getRetryMetrics() {
118
+ return this.controlService.getRetryMetrics();
119
+ }
120
+ getServiceStats() {
121
+ return this.controlService.getServiceStats();
122
+ }
123
+ resetRetryMetrics() {
124
+ return this.controlService.resetRetryMetrics();
125
+ }
126
+ isRetryEnabled() {
127
+ return this.controlService.isRetryEnabled();
128
+ }
96
129
  }
97
130
  //# sourceMappingURL=GoveeClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GoveeClient.js","sourceRoot":"","sources":["../src/GoveeClient.ts"],"names":[],"mappings":"AAAA,OAAO,IAAgB,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAarE,MAAM,OAAO,WAAW;IAItB,YAAY,MAAyB;QACnC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAE5B,wCAAwC;QACxC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEzD,wBAAwB;QACxB,MAAM,gBAAgB,GAAQ;YAC5B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;QAEF,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,gBAAgB,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC5C,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;QAE/D,6BAA6B;QAC7B,MAAM,aAAa,GAAQ;YACzB,UAAU;YACV,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;QAEF,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,aAAa,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAC7C,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,IAAI,mBAAmB,CAAC,aAAa,CAAC,CAAC;QAE7D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;IAC3D,CAAC;IAEO,cAAc,CAAC,MAAyB;QAC9C,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7F,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QACD,IACE,MAAM,CAAC,OAAO,KAAK,SAAS;YAC5B,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,EAC1D,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,IACE,MAAM,CAAC,SAAS,KAAK,SAAS;YAC9B,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC,EAC9D,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,4BAA4B;IAC5B,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,KAAa;QAClD,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,sBAAsB;QAC1B,OAAO,IAAI,CAAC,cAAc,CAAC,sBAAsB,EAAE,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,OAAO,IAAI,CAAC,cAAc,CAAC,qBAAqB,EAAE,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,UAAkB;QACvC,OAAO,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAa;QACpC,OAAO,IAAI,CAAC,cAAc,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IAED,yBAAyB;IACzB,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,KAAa,EAAE,OAAgB;QACjE,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,KAAa;QAC1C,OAAO,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,KAAa;QAC3C,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,KAAa,EAAE,UAAsB;QACzE,OAAO,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACxE,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB,EAAE,KAAa,EAAE,KAAe;QAC7D,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK,CAAC,mBAAmB,CACvB,QAAgB,EAChB,KAAa,EACb,gBAAkC;QAElC,OAAO,IAAI,CAAC,cAAc,CAAC,mBAAmB,CAAC,QAAQ,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACpF,CAAC;IAED,sBAAsB;IACtB,KAAK,CAAC,oBAAoB,CACxB,QAAgB,EAChB,KAAa,EACb,UAAsB;QAEtB,OAAO,IAAI,CAAC,cAAc,CAAC,oBAAoB,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,QAAgB,EAChB,KAAa,EACb,KAAe,EACf,UAAuB;QAEvB,OAAO,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,0BAA0B,CAC9B,QAAgB,EAChB,KAAa,EACb,gBAAkC,EAClC,UAAuB;QAEvB,OAAO,IAAI,CAAC,cAAc,CAAC,0BAA0B,CACnD,QAAQ,EACR,KAAK,EACL,gBAAgB,EAChB,UAAU,CACX,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB,EAAE,KAAa;QAClD,OAAO,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7D,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,KAAa;QACrD,OAAO,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC;CACF"}
1
+ {"version":3,"file":"GoveeClient.js","sourceRoot":"","sources":["../src/GoveeClient.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ export declare class GoveeApiError extends GoveeApiClientError {
8
8
  static fromResponse(statusCode: number, responseBody: {
9
9
  code?: number;
10
10
  message?: string;
11
- } | string): GoveeApiError;
11
+ } | string | null | undefined): GoveeApiError;
12
12
  isDeviceOffline(): boolean;
13
13
  isUnsupportedCommand(): boolean;
14
14
  toObject(): {
@@ -1 +1 @@
1
- {"version":3,"file":"GoveeApiError.d.ts","sourceRoot":"","sources":["../../src/errors/GoveeApiError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,QAAQ,CAAC,IAAI,qBAAqB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAGtC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,KAAK;IAQf,MAAM,CAAC,YAAY,CACjB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,GACzD,aAAa;IAchB,eAAe,IAAI,OAAO;IAQ1B,oBAAoB,IAAI,OAAO;IAQ/B,QAAQ,IAAI;QACV,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CAgBF"}
1
+ {"version":3,"file":"GoveeApiError.d.ts","sourceRoot":"","sources":["../../src/errors/GoveeApiError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,qBAAa,aAAc,SAAQ,mBAAmB;IACpD,QAAQ,CAAC,IAAI,qBAAqB;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAGtC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,EACrB,UAAU,CAAC,EAAE,MAAM,EACnB,KAAK,CAAC,EAAE,KAAK;IAQf,MAAM,CAAC,YAAY,CACjB,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAC5E,aAAa;IAwBhB,eAAe,IAAI,OAAO;IAQ1B,oBAAoB,IAAI,OAAO;IAQ/B,QAAQ,IAAI;QACV,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB;CAgBF"}
@@ -8,12 +8,19 @@ export class GoveeApiError extends GoveeApiClientError {
8
8
  this.apiMessage = apiMessage;
9
9
  }
10
10
  static fromResponse(statusCode, responseBody) {
11
- if (typeof responseBody === 'string') {
11
+ // Handle string responses
12
+ if (typeof responseBody === 'string' && responseBody.trim().length > 0) {
12
13
  return new GoveeApiError(`Govee API error (HTTP ${statusCode}): ${responseBody}`, statusCode);
13
14
  }
15
+ // Handle null, undefined, or non-object responses
16
+ if (!responseBody || typeof responseBody !== 'object') {
17
+ return new GoveeApiError(`Govee API error (HTTP ${statusCode})`, statusCode);
18
+ }
19
+ // Handle object responses with potential undefined/null properties
14
20
  const apiErrorCode = responseBody.code;
15
21
  const apiMessage = responseBody.message;
16
- const message = apiMessage
22
+ // Construct meaningful error message, handling undefined/null apiMessage
23
+ const message = apiMessage && typeof apiMessage === 'string' && apiMessage.trim().length > 0
17
24
  ? `Govee API error (HTTP ${statusCode}): ${apiMessage}`
18
25
  : `Govee API error (HTTP ${statusCode})`;
19
26
  return new GoveeApiError(message, statusCode, apiErrorCode, apiMessage);
@@ -1 +1 @@
1
- {"version":3,"file":"GoveeApiError.js","sourceRoot":"","sources":["../../src/errors/GoveeApiError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,OAAO,aAAc,SAAQ,mBAAmB;IAMpD,YACE,OAAe,EACf,UAAkB,EAClB,YAAqB,EACrB,UAAmB,EACnB,KAAa;QAEb,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAZf,SAAI,GAAG,iBAAiB,CAAC;QAahC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,YAAY,CACjB,UAAkB,EAClB,YAA0D;QAE1D,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACrC,OAAO,IAAI,aAAa,CAAC,yBAAyB,UAAU,MAAM,YAAY,EAAE,EAAE,UAAU,CAAC,CAAC;QAChG,CAAC;QAED,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC;QACvC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC;QACxC,MAAM,OAAO,GAAG,UAAU;YACxB,CAAC,CAAC,yBAAyB,UAAU,MAAM,UAAU,EAAE;YACvD,CAAC,CAAC,yBAAyB,UAAU,GAAG,CAAC;QAE3C,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IAC1E,CAAC;IAED,eAAe;QACb,OAAO,CACL,IAAI,CAAC,UAAU,KAAK,GAAG;YACvB,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;gBAC5D,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,CAAC,CACvE,CAAC;IACJ,CAAC;IAED,oBAAoB;QAClB,OAAO,CACL,IAAI,CAAC,UAAU,KAAK,GAAG;YACvB,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;gBAChE,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,CAAC,CACrE,CAAC;IACJ,CAAC;IAED,QAAQ;QAWN,MAAM,GAAG,GAAG;YACV,GAAG,KAAK,CAAC,QAAQ,EAAE;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;QAEF,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACnC,GAAW,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAChD,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACjC,GAAW,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAC5C,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
1
+ {"version":3,"file":"GoveeApiError.js","sourceRoot":"","sources":["../../src/errors/GoveeApiError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,OAAO,aAAc,SAAQ,mBAAmB;IAMpD,YACE,OAAe,EACf,UAAkB,EAClB,YAAqB,EACrB,UAAmB,EACnB,KAAa;QAEb,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAZf,SAAI,GAAG,iBAAiB,CAAC;QAahC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,YAAY,CACjB,UAAkB,EAClB,YAA6E;QAE7E,0BAA0B;QAC1B,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvE,OAAO,IAAI,aAAa,CAAC,yBAAyB,UAAU,MAAM,YAAY,EAAE,EAAE,UAAU,CAAC,CAAC;QAChG,CAAC;QAED,kDAAkD;QAClD,IAAI,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACtD,OAAO,IAAI,aAAa,CAAC,yBAAyB,UAAU,GAAG,EAAE,UAAU,CAAC,CAAC;QAC/E,CAAC;QAED,mEAAmE;QACnE,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC;QACvC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC;QAExC,yEAAyE;QACzE,MAAM,OAAO,GACX,UAAU,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAC1E,CAAC,CAAC,yBAAyB,UAAU,MAAM,UAAU,EAAE;YACvD,CAAC,CAAC,yBAAyB,UAAU,GAAG,CAAC;QAE7C,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IAC1E,CAAC;IAED,eAAe;QACb,OAAO,CACL,IAAI,CAAC,UAAU,KAAK,GAAG;YACvB,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;gBAC5D,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,CAAC,CACvE,CAAC;IACJ,CAAC;IAED,oBAAoB;QAClB,OAAO,CACL,IAAI,CAAC,UAAU,KAAK,GAAG;YACvB,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC;gBAChE,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,CAAC,CACrE,CAAC;IACJ,CAAC;IAED,QAAQ;QAWN,MAAM,GAAG,GAAG;YACV,GAAG,KAAK,CAAC,QAAQ,EAAE;YACnB,UAAU,EAAE,IAAI,CAAC,UAAU;SAC5B,CAAC;QAEF,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACnC,GAAW,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAChD,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACjC,GAAW,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAC5C,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import { ZodError } from 'zod';
2
+ import { GoveeApiClientError } from './GoveeApiClientError';
3
+ /**
4
+ * Error thrown when API response validation fails using Zod schemas
5
+ */
6
+ export declare class ValidationError extends GoveeApiClientError {
7
+ readonly code = "VALIDATION_ERROR";
8
+ readonly zodError: ZodError;
9
+ readonly rawData: unknown;
10
+ constructor(message: string, zodError: ZodError, rawData: unknown);
11
+ /**
12
+ * Create a ValidationError from a Zod validation failure
13
+ */
14
+ static fromZodError(zodError: ZodError, rawData: unknown): ValidationError;
15
+ /**
16
+ * Get a detailed breakdown of validation errors
17
+ */
18
+ getValidationDetails(): Array<{
19
+ path: string;
20
+ message: string;
21
+ received: unknown;
22
+ }>;
23
+ /**
24
+ * Get a summary of validation errors for logging
25
+ */
26
+ getValidationSummary(): string;
27
+ }
28
+ //# sourceMappingURL=ValidationError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValidationError.d.ts","sourceRoot":"","sources":["../../src/errors/ValidationError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;GAEG;AACH,qBAAa,eAAgB,SAAQ,mBAAmB;IACtD,QAAQ,CAAC,IAAI,sBAAsB;IACnC,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IACnC,SAAgB,OAAO,EAAE,OAAO,CAAC;gBAErB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO;IAOjE;;OAEG;WACW,YAAY,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,eAAe;IAUjF;;OAEG;IACI,oBAAoB,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAQ1F;;OAEG;IACI,oBAAoB,IAAI,MAAM;CAQtC"}
@@ -0,0 +1,44 @@
1
+ import { GoveeApiClientError } from './GoveeApiClientError';
2
+ /**
3
+ * Error thrown when API response validation fails using Zod schemas
4
+ */
5
+ export class ValidationError extends GoveeApiClientError {
6
+ constructor(message, zodError, rawData) {
7
+ super(message);
8
+ this.code = 'VALIDATION_ERROR';
9
+ this.name = 'ValidationError';
10
+ this.zodError = zodError;
11
+ this.rawData = rawData;
12
+ }
13
+ /**
14
+ * Create a ValidationError from a Zod validation failure
15
+ */
16
+ static fromZodError(zodError, rawData) {
17
+ const errorMessages = zodError.issues.map(issue => {
18
+ const path = issue.path.length > 0 ? ` at path '${issue.path.join('.')}'` : '';
19
+ return `${issue.message}${path}`;
20
+ });
21
+ const message = `API response validation failed: ${errorMessages.join(', ')}`;
22
+ return new ValidationError(message, zodError, rawData);
23
+ }
24
+ /**
25
+ * Get a detailed breakdown of validation errors
26
+ */
27
+ getValidationDetails() {
28
+ return this.zodError.issues.map(issue => ({
29
+ path: issue.path.join('.'),
30
+ message: issue.message,
31
+ received: issue.path.reduce((obj, key) => obj?.[key], this.rawData),
32
+ }));
33
+ }
34
+ /**
35
+ * Get a summary of validation errors for logging
36
+ */
37
+ getValidationSummary() {
38
+ const details = this.getValidationDetails();
39
+ return details
40
+ .map(detail => `${detail.path}: ${detail.message} (received: ${JSON.stringify(detail.received)})`)
41
+ .join('; ');
42
+ }
43
+ }
44
+ //# sourceMappingURL=ValidationError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ValidationError.js","sourceRoot":"","sources":["../../src/errors/ValidationError.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,mBAAmB;IAKtD,YAAY,OAAe,EAAE,QAAkB,EAAE,OAAgB;QAC/D,KAAK,CAAC,OAAO,CAAC,CAAC;QALR,SAAI,GAAG,kBAAkB,CAAC;QAMjC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,YAAY,CAAC,QAAkB,EAAE,OAAgB;QAC7D,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YAChD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,OAAO,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,mCAAmC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9E,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACI,oBAAoB;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACxC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAQ,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;SACzE,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACI,oBAAoB;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC5C,OAAO,OAAO;aACX,GAAG,CACF,MAAM,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,eAAe,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAC7F;aACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;CACF"}
@@ -3,4 +3,5 @@ export { GoveeApiError } from './GoveeApiError';
3
3
  export { InvalidApiKeyError } from './InvalidApiKeyError';
4
4
  export { RateLimitError } from './RateLimitError';
5
5
  export { NetworkError } from './NetworkError';
6
+ export { ValidationError } from './ValidationError';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -3,4 +3,5 @@ export { GoveeApiError } from './GoveeApiError';
3
3
  export { InvalidApiKeyError } from './InvalidApiKeyError';
4
4
  export { RateLimitError } from './RateLimitError';
5
5
  export { NetworkError } from './NetworkError';
6
+ export { ValidationError } from './ValidationError';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/errors/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -5,4 +5,5 @@ export { GoveeApiClientError, GoveeApiError, InvalidApiKeyError, RateLimitError,
5
5
  export { GoveeControlService, type GoveeControlServiceConfig } from './services';
6
6
  export { GoveeDeviceRepository } from './infrastructure';
7
7
  export { type IGoveeDeviceRepository } from './domain/repositories';
8
+ export { RetryPolicy, type RetryPolicyConfig, type BackoffStrategy, type JitterConfig, type RetryCondition, type CircuitBreakerConfig, type RetryMetrics, } from './infrastructure/retry';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGpE,OAAO,EACL,WAAW,EACX,WAAW,EACX,OAAO,EACP,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,uBAAuB,EACvB,cAAc,EACd,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGhF,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,mBAAmB,EAAE,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGpE,OAAO,EACL,WAAW,EACX,WAAW,EACX,OAAO,EACP,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,uBAAuB,EACvB,cAAc,EACd,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,aAAa,GACnB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGhF,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAE,mBAAmB,EAAE,KAAK,yBAAyB,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAGpE,OAAO,EACL,WAAW,EACX,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,YAAY,GAClB,MAAM,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -9,4 +9,6 @@ export { GoveeApiClientError, GoveeApiError, InvalidApiKeyError, RateLimitError,
9
9
  // Services and repositories (for advanced usage)
10
10
  export { GoveeControlService } from './services';
11
11
  export { GoveeDeviceRepository } from './infrastructure';
12
+ // Retry infrastructure (for custom retry policies)
13
+ export { RetryPolicy, } from './infrastructure/retry';
12
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,OAAO,EAAE,WAAW,EAA0B,MAAM,eAAe,CAAC;AAEpE,kBAAkB;AAClB,OAAO,EACL,WAAW,EACX,WAAW,EACX,OAAO,EACP,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,uBAAuB,EACvB,cAAc,GAMf,MAAM,mBAAmB,CAAC;AAE3B,gBAAgB;AAChB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEhF,gBAAgB;AAChB,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,iDAAiD;AACjD,OAAO,EAAE,mBAAmB,EAAkC,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,OAAO,EAAE,WAAW,EAA0B,MAAM,eAAe,CAAC;AAEpE,kBAAkB;AAClB,OAAO,EACL,WAAW,EACX,WAAW,EACX,OAAO,EACP,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,uBAAuB,EACvB,cAAc,GAMf,MAAM,mBAAmB,CAAC;AAE3B,gBAAgB;AAChB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEhF,gBAAgB;AAChB,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,YAAY,GACb,MAAM,UAAU,CAAC;AAElB,iDAAiD;AACjD,OAAO,EAAE,mBAAmB,EAAkC,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAGzD,mDAAmD;AACnD,OAAO,EACL,WAAW,GAOZ,MAAM,wBAAwB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"GoveeDeviceRepository.d.ts","sourceRoot":"","sources":["../../src/infrastructure/GoveeDeviceRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EACL,WAAW,EAKZ,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAIrD,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8ED,qBAAa,qBAAsB,YAAW,sBAAsB;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAEnE,OAAO,CAAC,iBAAiB;gBAIb,MAAM,EAAE,cAAc;IAgBlC,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,iBAAiB;IAqCzB,OAAO,CAAC,eAAe;IAkCjB,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IA+FjC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA8C9D,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCjF,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,0BAA0B;IAsBlC,OAAO,CAAC,gCAAgC;CA4BzC"}
1
+ {"version":3,"file":"GoveeDeviceRepository.d.ts","sourceRoot":"","sources":["../../src/infrastructure/GoveeDeviceRepository.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,+CAA+C,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EACL,WAAW,EAKZ,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAIrD,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA8ED,qBAAa,qBAAsB,YAAW,sBAAsB;IAClE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAEnE,OAAO,CAAC,iBAAiB;gBAIb,MAAM,EAAE,cAAc;IAgBlC,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,iBAAiB;IAqCzB,OAAO,CAAC,eAAe;IAkCjB,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IA+FjC,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA8C9D,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCjF,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,0BAA0B;IA4ClC,OAAO,CAAC,gCAAgC;CA4BzC"}
@@ -5,7 +5,7 @@ import { ColorRgb, ColorTemperature, Brightness } from '../domain/value-objects'
5
5
  import { GoveeApiError, InvalidApiKeyError, RateLimitError, NetworkError } from '../errors';
6
6
  export class GoveeDeviceRepository {
7
7
  generateRequestId() {
8
- return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
8
+ return crypto.randomUUID();
9
9
  }
10
10
  constructor(config) {
11
11
  this.validateConfig(config);
@@ -201,10 +201,33 @@ export class GoveeDeviceRepository {
201
201
  color: 'devices.capabilities.color_setting',
202
202
  colorTem: 'devices.capabilities.color_setting',
203
203
  };
204
+ // Map instances correctly according to Govee API v1 specification
205
+ let instance;
206
+ let value;
207
+ if (cmdObj.name === 'turn') {
208
+ // Power commands use 'powerSwitch' instance and numeric values
209
+ instance = 'powerSwitch';
210
+ value = cmdObj.value === 'on' ? 1 : 0; // Convert string to number: on=1, off=0
211
+ }
212
+ else if (cmdObj.name === 'color') {
213
+ // Color commands use 'colorRgb' instance
214
+ instance = 'colorRgb';
215
+ value = cmdObj.value;
216
+ }
217
+ else if (cmdObj.name === 'colorTem') {
218
+ // Color temperature uses specific instance name
219
+ instance = 'colorTemperatureK';
220
+ value = cmdObj.value;
221
+ }
222
+ else {
223
+ // Other commands (brightness) use their name as instance
224
+ instance = cmdObj.name;
225
+ value = cmdObj.value;
226
+ }
204
227
  return {
205
228
  type: capabilityTypeMap[cmdObj.name] || `devices.capabilities.${cmdObj.name}`,
206
- instance: cmdObj.name === 'colorTem' ? 'colorTemperatureK' : cmdObj.name,
207
- value: cmdObj.value,
229
+ instance,
230
+ value,
208
231
  };
209
232
  }
210
233
  mapCapabilitiesToStateProperties(capabilities) {