@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
@@ -0,0 +1,373 @@
1
+ import { RateLimitError, NetworkError, GoveeApiError, InvalidApiKeyError, } from '../../errors';
2
+ /**
3
+ * Circuit breaker state management
4
+ */
5
+ class CircuitBreaker {
6
+ constructor(config, logger) {
7
+ this.config = config;
8
+ this.logger = logger;
9
+ this.state = 'closed';
10
+ this.failureCount = 0;
11
+ this.lastFailureTime = 0;
12
+ this.successCount = 0;
13
+ }
14
+ canExecute() {
15
+ const now = Date.now();
16
+ switch (this.state) {
17
+ case 'closed':
18
+ return true;
19
+ case 'open':
20
+ if (now - this.lastFailureTime >= this.config.recoveryTimeoutMs) {
21
+ this.logger?.info('Circuit breaker transitioning to half-open state');
22
+ this.state = 'half-open';
23
+ this.successCount = 0;
24
+ return true;
25
+ }
26
+ return false;
27
+ case 'half-open':
28
+ return true;
29
+ default:
30
+ return false;
31
+ }
32
+ }
33
+ recordSuccess() {
34
+ this.failureCount = 0;
35
+ if (this.state === 'half-open') {
36
+ this.successCount++;
37
+ if (this.successCount >= this.config.halfOpenSuccessThreshold) {
38
+ this.logger?.info('Circuit breaker transitioning to closed state');
39
+ this.state = 'closed';
40
+ }
41
+ }
42
+ }
43
+ recordFailure() {
44
+ this.failureCount++;
45
+ this.lastFailureTime = Date.now();
46
+ if (this.state === 'closed' && this.failureCount >= this.config.failureThreshold) {
47
+ this.logger?.warn('Circuit breaker transitioning to open state');
48
+ this.state = 'open';
49
+ }
50
+ else if (this.state === 'half-open') {
51
+ this.logger?.warn('Circuit breaker returning to open state');
52
+ this.state = 'open';
53
+ this.successCount = 0;
54
+ }
55
+ }
56
+ getState() {
57
+ return this.state;
58
+ }
59
+ reset() {
60
+ this.state = 'closed';
61
+ this.failureCount = 0;
62
+ this.lastFailureTime = 0;
63
+ this.successCount = 0;
64
+ this.logger?.info('Circuit breaker reset to closed state');
65
+ }
66
+ }
67
+ /**
68
+ * Enterprise-grade retry policy with exponential backoff, jitter, and circuit breaker
69
+ */
70
+ export class RetryPolicy {
71
+ constructor(config) {
72
+ this.config = config;
73
+ this.logger = config.logger;
74
+ this.validateConfig();
75
+ if (config.circuitBreaker?.enabled) {
76
+ this.circuitBreaker = new CircuitBreaker(config.circuitBreaker, this.logger);
77
+ }
78
+ this.metrics = {
79
+ totalAttempts: 0,
80
+ successfulRetries: 0,
81
+ failedRetries: 0,
82
+ totalRetryTimeMs: 0,
83
+ averageRetryDelayMs: 0,
84
+ circuitBreakerState: this.circuitBreaker?.getState() || 'closed',
85
+ };
86
+ }
87
+ validateConfig() {
88
+ const { backoff, condition, jitter } = this.config;
89
+ if (backoff.initialDelayMs <= 0 || backoff.maxDelayMs <= 0) {
90
+ throw new Error('Retry delays must be positive');
91
+ }
92
+ if (backoff.initialDelayMs > backoff.maxDelayMs) {
93
+ throw new Error('Initial delay cannot exceed maximum delay');
94
+ }
95
+ if (condition.maxAttempts <= 0 || condition.maxTotalTimeMs <= 0) {
96
+ throw new Error('Retry limits must be positive');
97
+ }
98
+ if (jitter.factor !== undefined && (jitter.factor < 0 || jitter.factor > 1)) {
99
+ throw new Error('Jitter factor must be between 0 and 1');
100
+ }
101
+ if (backoff.type === 'exponential' && (backoff.multiplier || 2) <= 1) {
102
+ throw new Error('Exponential backoff multiplier must be greater than 1');
103
+ }
104
+ }
105
+ /**
106
+ * Determines if an error should trigger a retry attempt
107
+ */
108
+ shouldRetry(error, attempt, elapsedTimeMs) {
109
+ const { condition } = this.config;
110
+ // Check circuit breaker
111
+ if (this.circuitBreaker && !this.circuitBreaker.canExecute()) {
112
+ this.logger?.debug('Retry blocked by circuit breaker');
113
+ return false;
114
+ }
115
+ // Check attempt limit
116
+ if (attempt >= condition.maxAttempts) {
117
+ this.logger?.debug(`Maximum attempts reached: ${attempt}/${condition.maxAttempts}`);
118
+ return false;
119
+ }
120
+ // Check time limit
121
+ if (elapsedTimeMs >= condition.maxTotalTimeMs) {
122
+ this.logger?.debug(`Maximum retry time exceeded: ${elapsedTimeMs}ms/${condition.maxTotalTimeMs}ms`);
123
+ return false;
124
+ }
125
+ // Custom retry decision
126
+ if (condition.shouldRetry) {
127
+ return condition.shouldRetry(error, attempt, elapsedTimeMs);
128
+ }
129
+ // Check if error type is retryable
130
+ const isRetryableType = condition.retryableErrorTypes.some(ErrorType => error instanceof ErrorType);
131
+ if (!isRetryableType) {
132
+ this.logger?.debug(`Error type not retryable: ${error.constructor.name}`);
133
+ return false;
134
+ }
135
+ // Specific retry logic based on error type
136
+ if (error instanceof RateLimitError) {
137
+ return error.canRetry();
138
+ }
139
+ if (error instanceof NetworkError) {
140
+ return error.isRetryable();
141
+ }
142
+ if (error instanceof GoveeApiError) {
143
+ // Retry on server errors (5xx) and some client errors
144
+ const retryableStatusCodes = [
145
+ 408,
146
+ 429,
147
+ 500,
148
+ 502,
149
+ 503,
150
+ 504,
151
+ ...condition.retryableStatusCodes,
152
+ ];
153
+ return retryableStatusCodes.includes(error.statusCode);
154
+ }
155
+ if (error instanceof InvalidApiKeyError) {
156
+ // Never retry authentication errors
157
+ return false;
158
+ }
159
+ return false;
160
+ }
161
+ /**
162
+ * Calculates the delay before the next retry attempt
163
+ */
164
+ calculateDelay(attempt, error) {
165
+ const { backoff, jitter } = this.config;
166
+ // Handle rate limit errors with specific retry-after values
167
+ if (error instanceof RateLimitError && error.canRetry()) {
168
+ const rateLimitDelay = error.getRetryAfterMs();
169
+ return this.applyJitter(rateLimitDelay, attempt);
170
+ }
171
+ let baseDelay;
172
+ switch (backoff.type) {
173
+ case 'fixed':
174
+ baseDelay = backoff.initialDelayMs;
175
+ break;
176
+ case 'linear':
177
+ baseDelay = backoff.initialDelayMs * attempt;
178
+ break;
179
+ case 'exponential':
180
+ const multiplier = backoff.multiplier || 2;
181
+ baseDelay = backoff.initialDelayMs * Math.pow(multiplier, attempt - 1);
182
+ break;
183
+ case 'custom':
184
+ if (!backoff.customBackoff) {
185
+ throw new Error('Custom backoff function not provided');
186
+ }
187
+ baseDelay = backoff.customBackoff(attempt, error);
188
+ break;
189
+ default:
190
+ throw new Error(`Unknown backoff type: ${backoff.type}`);
191
+ }
192
+ // Ensure delay doesn't exceed maximum
193
+ baseDelay = Math.min(baseDelay, backoff.maxDelayMs);
194
+ return this.applyJitter(baseDelay, attempt);
195
+ }
196
+ /**
197
+ * Applies jitter to prevent thundering herd problems
198
+ */
199
+ applyJitter(baseDelay, attempt) {
200
+ const { jitter } = this.config;
201
+ const factor = jitter.factor || 0.1;
202
+ switch (jitter.type) {
203
+ case 'none':
204
+ return baseDelay;
205
+ case 'full':
206
+ // Random value between 0 and baseDelay
207
+ return Math.random() * baseDelay;
208
+ case 'equal':
209
+ // baseDelay/2 + random(0, baseDelay/2)
210
+ return baseDelay / 2 + Math.random() * (baseDelay / 2);
211
+ case 'decorrelated':
212
+ // More sophisticated jitter that considers previous delays
213
+ const minDelay = this.config.backoff.initialDelayMs;
214
+ const maxJitter = baseDelay * factor;
215
+ return Math.min(this.config.backoff.maxDelayMs, Math.random() * (baseDelay * 3 - minDelay) + minDelay);
216
+ default:
217
+ throw new Error(`Unknown jitter type: ${jitter.type}`);
218
+ }
219
+ }
220
+ /**
221
+ * Records a successful operation
222
+ */
223
+ recordSuccess() {
224
+ this.circuitBreaker?.recordSuccess();
225
+ this.updateMetrics(true);
226
+ }
227
+ /**
228
+ * Records a failed operation
229
+ */
230
+ recordFailure(error) {
231
+ this.circuitBreaker?.recordFailure();
232
+ this.updateMetrics(false, error);
233
+ }
234
+ /**
235
+ * Updates retry metrics
236
+ */
237
+ updateMetrics(success, error) {
238
+ if (!this.config.enableMetrics)
239
+ return;
240
+ this.metrics.totalAttempts++;
241
+ this.metrics.circuitBreakerState = this.circuitBreaker?.getState() || 'closed';
242
+ this.metrics.lastRetryTimestamp = new Date();
243
+ if (success) {
244
+ this.metrics.successfulRetries++;
245
+ }
246
+ else {
247
+ this.metrics.failedRetries++;
248
+ this.metrics.lastError = error;
249
+ }
250
+ // Update average delay (simplified calculation)
251
+ if (this.metrics.totalAttempts > 1) {
252
+ this.metrics.averageRetryDelayMs =
253
+ this.metrics.totalRetryTimeMs / (this.metrics.totalAttempts - 1);
254
+ }
255
+ }
256
+ /**
257
+ * Gets current retry metrics
258
+ */
259
+ getMetrics() {
260
+ return { ...this.metrics };
261
+ }
262
+ /**
263
+ * Resets retry metrics and circuit breaker
264
+ */
265
+ reset() {
266
+ this.circuitBreaker?.reset();
267
+ Object.assign(this.metrics, {
268
+ totalAttempts: 0,
269
+ successfulRetries: 0,
270
+ failedRetries: 0,
271
+ totalRetryTimeMs: 0,
272
+ averageRetryDelayMs: 0,
273
+ circuitBreakerState: this.circuitBreaker?.getState() || 'closed',
274
+ lastError: undefined,
275
+ lastRetryTimestamp: undefined,
276
+ });
277
+ this.logger?.info('Retry policy metrics and circuit breaker reset');
278
+ }
279
+ /**
280
+ * Creates a default retry policy optimized for Govee API
281
+ */
282
+ static createGoveeOptimized(logger) {
283
+ return new RetryPolicy({
284
+ backoff: {
285
+ type: 'exponential',
286
+ initialDelayMs: 1000, // Start with 1 second
287
+ maxDelayMs: 30000, // Cap at 30 seconds
288
+ multiplier: 2.0,
289
+ },
290
+ jitter: {
291
+ type: 'equal',
292
+ factor: 0.1,
293
+ },
294
+ condition: {
295
+ maxAttempts: 3,
296
+ maxTotalTimeMs: 60000, // 1 minute total
297
+ retryableStatusCodes: [408, 502, 503, 504],
298
+ retryableErrorTypes: [RateLimitError, NetworkError, GoveeApiError],
299
+ },
300
+ circuitBreaker: {
301
+ enabled: true,
302
+ failureThreshold: 5,
303
+ recoveryTimeoutMs: 30000,
304
+ halfOpenSuccessThreshold: 2,
305
+ },
306
+ logger,
307
+ enableMetrics: true,
308
+ });
309
+ }
310
+ /**
311
+ * Creates a conservative retry policy for production environments
312
+ */
313
+ static createConservative(logger) {
314
+ return new RetryPolicy({
315
+ backoff: {
316
+ type: 'exponential',
317
+ initialDelayMs: 2000,
318
+ maxDelayMs: 60000,
319
+ multiplier: 1.5,
320
+ },
321
+ jitter: {
322
+ type: 'decorrelated',
323
+ factor: 0.2,
324
+ },
325
+ condition: {
326
+ maxAttempts: 2,
327
+ maxTotalTimeMs: 120000,
328
+ retryableStatusCodes: [429, 502, 503, 504],
329
+ retryableErrorTypes: [RateLimitError, NetworkError],
330
+ },
331
+ circuitBreaker: {
332
+ enabled: true,
333
+ failureThreshold: 3,
334
+ recoveryTimeoutMs: 60000,
335
+ halfOpenSuccessThreshold: 3,
336
+ },
337
+ logger,
338
+ enableMetrics: true,
339
+ });
340
+ }
341
+ /**
342
+ * Creates an aggressive retry policy for development/testing
343
+ */
344
+ static createAggressive(logger) {
345
+ return new RetryPolicy({
346
+ backoff: {
347
+ type: 'exponential',
348
+ initialDelayMs: 500,
349
+ maxDelayMs: 15000,
350
+ multiplier: 2.5,
351
+ },
352
+ jitter: {
353
+ type: 'full',
354
+ factor: 0.3,
355
+ },
356
+ condition: {
357
+ maxAttempts: 5,
358
+ maxTotalTimeMs: 45000,
359
+ retryableStatusCodes: [400, 408, 429, 500, 502, 503, 504],
360
+ retryableErrorTypes: [RateLimitError, NetworkError, GoveeApiError],
361
+ },
362
+ circuitBreaker: {
363
+ enabled: false,
364
+ failureThreshold: 10,
365
+ recoveryTimeoutMs: 15000,
366
+ halfOpenSuccessThreshold: 1,
367
+ },
368
+ logger,
369
+ enableMetrics: true,
370
+ });
371
+ }
372
+ }
373
+ //# sourceMappingURL=RetryPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RetryPolicy.js","sourceRoot":"","sources":["../../../src/infrastructure/retry/RetryPolicy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import { Logger } from 'pino';
2
+ import { IGoveeDeviceRepository } from '../../domain/repositories/IGoveeDeviceRepository';
3
+ import { GoveeDevice } from '../../domain/entities/GoveeDevice';
4
+ import { DeviceState } from '../../domain/entities/DeviceState';
5
+ import { Command } from '../../domain/entities/Command';
6
+ import { RetryExecutor, RetryResult } from './RetryableRequest';
7
+ /**
8
+ * Configuration for RetryableRepository
9
+ */
10
+ export interface RetryableRepositoryConfig {
11
+ /** The underlying repository to wrap */
12
+ repository: IGoveeDeviceRepository;
13
+ /** Retry executor to use */
14
+ retryExecutor?: RetryExecutor;
15
+ /** Logger for retry operations */
16
+ logger?: Logger;
17
+ /** Enable request ID generation */
18
+ enableRequestIds?: boolean;
19
+ }
20
+ /**
21
+ * Repository wrapper that adds retry functionality to any IGoveeDeviceRepository implementation
22
+ */
23
+ export declare class RetryableRepository implements IGoveeDeviceRepository {
24
+ private readonly repository;
25
+ private readonly retryExecutor;
26
+ private readonly logger?;
27
+ private readonly enableRequestIds;
28
+ private requestIdCounter;
29
+ constructor(config: RetryableRepositoryConfig);
30
+ /**
31
+ * Generates a unique request ID
32
+ */
33
+ private generateRequestId;
34
+ /**
35
+ * Finds all devices with retry logic
36
+ */
37
+ findAll(): Promise<GoveeDevice[]>;
38
+ /**
39
+ * Finds device state with retry logic
40
+ */
41
+ findState(deviceId: string, sku: string): Promise<DeviceState>;
42
+ /**
43
+ * Sends command with retry logic
44
+ */
45
+ sendCommand(deviceId: string, sku: string, command: Command): Promise<void>;
46
+ /**
47
+ * Gets detailed retry result for findAll operation
48
+ */
49
+ findAllWithRetryResult(): Promise<RetryResult<GoveeDevice[]>>;
50
+ /**
51
+ * Gets detailed retry result for findState operation
52
+ */
53
+ findStateWithRetryResult(deviceId: string, sku: string): Promise<RetryResult<DeviceState>>;
54
+ /**
55
+ * Gets detailed retry result for sendCommand operation
56
+ */
57
+ sendCommandWithRetryResult(deviceId: string, sku: string, command: Command): Promise<RetryResult<void>>;
58
+ /**
59
+ * Gets current retry metrics
60
+ */
61
+ getRetryMetrics(): Readonly<import("./RetryPolicy").RetryMetrics>;
62
+ /**
63
+ * Resets retry metrics
64
+ */
65
+ resetRetryMetrics(): void;
66
+ /**
67
+ * Gets the underlying repository (for direct access when needed)
68
+ */
69
+ getUnderlyingRepository(): IGoveeDeviceRepository;
70
+ }
71
+ /**
72
+ * Import the RetryResult type for convenience
73
+ */
74
+ export { RetryResult, RetryAttempt } from './RetryableRequest';
75
+ //# sourceMappingURL=RetryableRepository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RetryableRepository.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/retry/RetryableRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kDAAkD,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EACL,aAAa,EAGb,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAG5B;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,wCAAwC;IACxC,UAAU,EAAE,sBAAsB,CAAC;IACnC,4BAA4B;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,kCAAkC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mCAAmC;IACnC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,mBAAoB,YAAW,sBAAsB;IAChE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAC3C,OAAO,CAAC,gBAAgB,CAAK;gBAEjB,MAAM,EAAE,yBAAyB;IAQ7C;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAQzB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAcvC;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAgBpE;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBjF;;OAEG;IACG,sBAAsB,IAAI,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;IAcnE;;OAEG;IACG,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;IAgBhG;;OAEG;IACG,0BAA0B,CAC9B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAiB7B;;OAEG;IACH,eAAe;IAIf;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAIzB;;OAEG;IACH,uBAAuB,IAAI,sBAAsB;CAGlD;AAED;;GAEG;AACH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,142 @@
1
+ import { RetryExecutorFactory, } from './RetryableRequest';
2
+ /**
3
+ * Repository wrapper that adds retry functionality to any IGoveeDeviceRepository implementation
4
+ */
5
+ export class RetryableRepository {
6
+ constructor(config) {
7
+ this.requestIdCounter = 0;
8
+ this.repository = config.repository;
9
+ this.retryExecutor =
10
+ config.retryExecutor || RetryExecutorFactory.createForGoveeApi(config.logger);
11
+ this.logger = config.logger;
12
+ this.enableRequestIds = config.enableRequestIds ?? true;
13
+ }
14
+ /**
15
+ * Generates a unique request ID
16
+ */
17
+ generateRequestId(operation) {
18
+ if (!this.enableRequestIds) {
19
+ return `${operation}-${Date.now()}`;
20
+ }
21
+ return `${operation}-${++this.requestIdCounter}-${Date.now()}`;
22
+ }
23
+ /**
24
+ * Finds all devices with retry logic
25
+ */
26
+ async findAll() {
27
+ const request = {
28
+ id: this.generateRequestId('findAll'),
29
+ description: 'Fetch all Govee devices',
30
+ execute: () => this.repository.findAll(),
31
+ context: {
32
+ operation: 'findAll',
33
+ timestamp: new Date().toISOString(),
34
+ },
35
+ };
36
+ return this.retryExecutor.execute(request);
37
+ }
38
+ /**
39
+ * Finds device state with retry logic
40
+ */
41
+ async findState(deviceId, sku) {
42
+ const request = {
43
+ id: this.generateRequestId('findState'),
44
+ description: `Fetch state for device ${deviceId} (${sku})`,
45
+ execute: () => this.repository.findState(deviceId, sku),
46
+ context: {
47
+ operation: 'findState',
48
+ deviceId,
49
+ sku,
50
+ timestamp: new Date().toISOString(),
51
+ },
52
+ };
53
+ return this.retryExecutor.execute(request);
54
+ }
55
+ /**
56
+ * Sends command with retry logic
57
+ */
58
+ async sendCommand(deviceId, sku, command) {
59
+ const request = {
60
+ id: this.generateRequestId('sendCommand'),
61
+ description: `Send ${command.toObject().name} command to device ${deviceId} (${sku})`,
62
+ execute: () => this.repository.sendCommand(deviceId, sku, command),
63
+ context: {
64
+ operation: 'sendCommand',
65
+ deviceId,
66
+ sku,
67
+ command: command.toObject(),
68
+ timestamp: new Date().toISOString(),
69
+ },
70
+ };
71
+ return this.retryExecutor.execute(request);
72
+ }
73
+ /**
74
+ * Gets detailed retry result for findAll operation
75
+ */
76
+ async findAllWithRetryResult() {
77
+ const request = {
78
+ id: this.generateRequestId('findAll'),
79
+ description: 'Fetch all Govee devices (with retry details)',
80
+ execute: () => this.repository.findAll(),
81
+ context: {
82
+ operation: 'findAll',
83
+ timestamp: new Date().toISOString(),
84
+ },
85
+ };
86
+ return this.retryExecutor.executeWithResult(request);
87
+ }
88
+ /**
89
+ * Gets detailed retry result for findState operation
90
+ */
91
+ async findStateWithRetryResult(deviceId, sku) {
92
+ const request = {
93
+ id: this.generateRequestId('findState'),
94
+ description: `Fetch state for device ${deviceId} (${sku}) with retry details`,
95
+ execute: () => this.repository.findState(deviceId, sku),
96
+ context: {
97
+ operation: 'findState',
98
+ deviceId,
99
+ sku,
100
+ timestamp: new Date().toISOString(),
101
+ },
102
+ };
103
+ return this.retryExecutor.executeWithResult(request);
104
+ }
105
+ /**
106
+ * Gets detailed retry result for sendCommand operation
107
+ */
108
+ async sendCommandWithRetryResult(deviceId, sku, command) {
109
+ const request = {
110
+ id: this.generateRequestId('sendCommand'),
111
+ description: `Send ${command.toObject().name} command to device ${deviceId} (${sku}) with retry details`,
112
+ execute: () => this.repository.sendCommand(deviceId, sku, command),
113
+ context: {
114
+ operation: 'sendCommand',
115
+ deviceId,
116
+ sku,
117
+ command: command.toObject(),
118
+ timestamp: new Date().toISOString(),
119
+ },
120
+ };
121
+ return this.retryExecutor.executeWithResult(request);
122
+ }
123
+ /**
124
+ * Gets current retry metrics
125
+ */
126
+ getRetryMetrics() {
127
+ return this.retryExecutor.getMetrics();
128
+ }
129
+ /**
130
+ * Resets retry metrics
131
+ */
132
+ resetRetryMetrics() {
133
+ this.retryExecutor.resetMetrics();
134
+ }
135
+ /**
136
+ * Gets the underlying repository (for direct access when needed)
137
+ */
138
+ getUnderlyingRepository() {
139
+ return this.repository;
140
+ }
141
+ }
142
+ //# sourceMappingURL=RetryableRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RetryableRepository.js","sourceRoot":"","sources":["../../../src/infrastructure/retry/RetryableRepository.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,oBAAoB,GAErB,MAAM,oBAAoB,CAAC;AAiB5B;;GAEG;AACH,MAAM,OAAO,mBAAmB;IAO9B,YAAY,MAAiC;QAFrC,qBAAgB,GAAG,CAAC,CAAC;QAG3B,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,aAAa;YAChB,MAAM,CAAC,aAAa,IAAI,oBAAoB,CAAC,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAChF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAC1D,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,SAAiB;QACzC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACtC,CAAC;QAED,OAAO,GAAG,SAAS,IAAI,EAAE,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACjE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,OAAO,GAAoC;YAC/C,EAAE,EAAE,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC;YACrC,WAAW,EAAE,yBAAyB;YACtC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;YACxC,OAAO,EAAE;gBACP,SAAS,EAAE,SAAS;gBACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,GAAW;QAC3C,MAAM,OAAO,GAAkC;YAC7C,EAAE,EAAE,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC;YACvC,WAAW,EAAE,0BAA0B,QAAQ,KAAK,GAAG,GAAG;YAC1D,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC;YACvD,OAAO,EAAE;gBACP,SAAS,EAAE,WAAW;gBACtB,QAAQ;gBACR,GAAG;gBACH,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CAAC,QAAgB,EAAE,GAAW,EAAE,OAAgB;QAC/D,MAAM,OAAO,GAA2B;YACtC,EAAE,EAAE,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC;YACzC,WAAW,EAAE,QAAQ,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,sBAAsB,QAAQ,KAAK,GAAG,GAAG;YACrF,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC;YAClE,OAAO,EAAE;gBACP,SAAS,EAAE,aAAa;gBACxB,QAAQ;gBACR,GAAG;gBACH,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE;gBAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,sBAAsB;QAC1B,MAAM,OAAO,GAAoC;YAC/C,EAAE,EAAE,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC;YACrC,WAAW,EAAE,8CAA8C;YAC3D,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE;YACxC,OAAO,EAAE;gBACP,SAAS,EAAE,SAAS;gBACpB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,wBAAwB,CAAC,QAAgB,EAAE,GAAW;QAC1D,MAAM,OAAO,GAAkC;YAC7C,EAAE,EAAE,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC;YACvC,WAAW,EAAE,0BAA0B,QAAQ,KAAK,GAAG,sBAAsB;YAC7E,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC;YACvD,OAAO,EAAE;gBACP,SAAS,EAAE,WAAW;gBACtB,QAAQ;gBACR,GAAG;gBACH,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,0BAA0B,CAC9B,QAAgB,EAChB,GAAW,EACX,OAAgB;QAEhB,MAAM,OAAO,GAA2B;YACtC,EAAE,EAAE,IAAI,CAAC,iBAAiB,CAAC,aAAa,CAAC;YACzC,WAAW,EAAE,QAAQ,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,sBAAsB,QAAQ,KAAK,GAAG,sBAAsB;YACxG,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC;YAClE,OAAO,EAAE;gBACP,SAAS,EAAE,aAAa;gBACxB,QAAQ;gBACR,GAAG;gBACH,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE;gBAC3B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC;SACF,CAAC;QAEF,OAAO,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACvD,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,iBAAiB;QACf,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,uBAAuB;QACrB,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF"}