@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.
- package/README.md +160 -7
- package/dist/GoveeClient.d.ts +31 -0
- package/dist/GoveeClient.d.ts.map +1 -1
- package/dist/GoveeClient.js +33 -0
- package/dist/GoveeClient.js.map +1 -1
- package/dist/errors/GoveeApiError.d.ts +1 -1
- package/dist/errors/GoveeApiError.d.ts.map +1 -1
- package/dist/errors/GoveeApiError.js +9 -2
- package/dist/errors/GoveeApiError.js.map +1 -1
- package/dist/errors/ValidationError.d.ts +28 -0
- package/dist/errors/ValidationError.d.ts.map +1 -0
- package/dist/errors/ValidationError.js +44 -0
- package/dist/errors/ValidationError.js.map +1 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/index.js +1 -0
- package/dist/errors/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/GoveeDeviceRepository.d.ts.map +1 -1
- package/dist/infrastructure/GoveeDeviceRepository.js +26 -3
- package/dist/infrastructure/GoveeDeviceRepository.js.map +1 -1
- package/dist/infrastructure/SlidingWindowRateLimiter.d.ts +83 -0
- package/dist/infrastructure/SlidingWindowRateLimiter.d.ts.map +1 -0
- package/dist/infrastructure/SlidingWindowRateLimiter.js +218 -0
- package/dist/infrastructure/SlidingWindowRateLimiter.js.map +1 -0
- package/dist/infrastructure/index.d.ts +2 -0
- package/dist/infrastructure/index.d.ts.map +1 -1
- package/dist/infrastructure/index.js +2 -0
- package/dist/infrastructure/index.js.map +1 -1
- package/dist/infrastructure/response-schemas.d.ts +82 -0
- package/dist/infrastructure/response-schemas.d.ts.map +1 -0
- package/dist/infrastructure/response-schemas.js +59 -0
- package/dist/infrastructure/response-schemas.js.map +1 -0
- package/dist/infrastructure/retry/IntegrationGuide.d.ts +133 -0
- package/dist/infrastructure/retry/IntegrationGuide.d.ts.map +1 -0
- package/dist/infrastructure/retry/IntegrationGuide.js +295 -0
- package/dist/infrastructure/retry/IntegrationGuide.js.map +1 -0
- package/dist/infrastructure/retry/RetryConfigPresets.d.ts +114 -0
- package/dist/infrastructure/retry/RetryConfigPresets.d.ts.map +1 -0
- package/dist/infrastructure/retry/RetryConfigPresets.js +406 -0
- package/dist/infrastructure/retry/RetryConfigPresets.js.map +1 -0
- package/dist/infrastructure/retry/RetryPolicy.d.ts +148 -0
- package/dist/infrastructure/retry/RetryPolicy.d.ts.map +1 -0
- package/dist/infrastructure/retry/RetryPolicy.js +373 -0
- package/dist/infrastructure/retry/RetryPolicy.js.map +1 -0
- package/dist/infrastructure/retry/RetryableRepository.d.ts +75 -0
- package/dist/infrastructure/retry/RetryableRepository.d.ts.map +1 -0
- package/dist/infrastructure/retry/RetryableRepository.js +142 -0
- package/dist/infrastructure/retry/RetryableRepository.js.map +1 -0
- package/dist/infrastructure/retry/RetryableRequest.d.ts +132 -0
- package/dist/infrastructure/retry/RetryableRequest.d.ts.map +1 -0
- package/dist/infrastructure/retry/RetryableRequest.js +248 -0
- package/dist/infrastructure/retry/RetryableRequest.js.map +1 -0
- package/dist/infrastructure/retry/index.d.ts +35 -0
- package/dist/infrastructure/retry/index.d.ts.map +1 -0
- package/dist/infrastructure/retry/index.js +36 -0
- package/dist/infrastructure/retry/index.js.map +1 -0
- package/dist/services/GoveeControlService.d.ts +53 -0
- package/dist/services/GoveeControlService.d.ts.map +1 -1
- package/dist/services/GoveeControlService.js +138 -12
- package/dist/services/GoveeControlService.js.map +1 -1
- package/docs/EXAMPLES.md +799 -0
- package/docs/LLM_API_REFERENCE.md +425 -0
- package/docs/TYPE_DEFINITIONS.md +803 -0
- package/package.json +25 -16
package/README.md
CHANGED
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
[](https://github.com/felixgeelhaar/govee-api-client/actions)
|
|
6
6
|
[](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
|
|
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**:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
package/dist/GoveeClient.d.ts
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"GoveeClient.d.ts","sourceRoot":"","sources":["../src/GoveeClient.ts"],"names":[],"mappings":"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"}
|
package/dist/GoveeClient.js
CHANGED
|
@@ -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
|
package/dist/GoveeClient.js.map
CHANGED
|
@@ -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;
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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"}
|
package/dist/errors/index.d.ts
CHANGED
|
@@ -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"}
|
package/dist/errors/index.js
CHANGED
|
@@ -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
|
package/dist/errors/index.js.map
CHANGED
|
@@ -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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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
|
|
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
|
|
207
|
-
value
|
|
229
|
+
instance,
|
|
230
|
+
value,
|
|
208
231
|
};
|
|
209
232
|
}
|
|
210
233
|
mapCapabilitiesToStateProperties(capabilities) {
|