@felixgeelhaar/govee-api-client 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -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/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/GoveeDeviceRepository.d.ts.map +1 -1
- package/dist/infrastructure/GoveeDeviceRepository.js +48 -6
- package/dist/infrastructure/GoveeDeviceRepository.js.map +1 -1
- package/docs/EXAMPLES.md +980 -0
- package/docs/LLM_API_REFERENCE.md +425 -0
- package/docs/TYPE_DEFINITIONS.md +974 -0
- package/package.json +10 -4
|
@@ -0,0 +1,974 @@
|
|
|
1
|
+
# Govee API Client - Type Definitions
|
|
2
|
+
|
|
3
|
+
This document provides comprehensive type definitions for the Govee API Client library. All types are fully documented with TypeScript definitions.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Configuration Types](#configuration-types)
|
|
8
|
+
- [Domain Entity Types](#domain-entity-types)
|
|
9
|
+
- [Value Object Types](#value-object-types)
|
|
10
|
+
- [Command Types](#command-types)
|
|
11
|
+
- [State Types](#state-types)
|
|
12
|
+
- [Error Types](#error-types)
|
|
13
|
+
- [Validation Types](#validation-types)
|
|
14
|
+
- [Retry & Rate Limiting Types](#retry--rate-limiting-types)
|
|
15
|
+
- [Utility Types](#utility-types)
|
|
16
|
+
|
|
17
|
+
## Configuration Types
|
|
18
|
+
|
|
19
|
+
### GoveeClientConfig
|
|
20
|
+
|
|
21
|
+
Main configuration interface for initializing the GoveeClient.
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
interface GoveeClientConfig {
|
|
25
|
+
apiKey: string; // Required: Govee API key
|
|
26
|
+
timeout?: number; // Optional: Request timeout in milliseconds (default: 30000)
|
|
27
|
+
rateLimit?: number; // Optional: Max requests per minute (default: 95)
|
|
28
|
+
logger?: Logger; // Optional: Pino logger instance
|
|
29
|
+
enableRetries?: boolean; // Optional: Enable retry logic (default: false)
|
|
30
|
+
retryPolicy?: RetryPolicyType; // Optional: Retry policy configuration
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type RetryPolicyType = 'development' | 'testing' | 'production' | 'custom' | RetryPolicy;
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### GoveeControlServiceConfig
|
|
37
|
+
|
|
38
|
+
Configuration for the internal control service.
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
interface GoveeControlServiceConfig {
|
|
42
|
+
repository: IGoveeDeviceRepository;
|
|
43
|
+
logger?: Logger;
|
|
44
|
+
rateLimit?: number;
|
|
45
|
+
enableRetries?: boolean;
|
|
46
|
+
retryPolicy?: RetryPolicyType;
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### GoveeDeviceRepositoryConfig
|
|
51
|
+
|
|
52
|
+
Configuration for the device repository.
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
interface GoveeDeviceRepositoryConfig {
|
|
56
|
+
apiKey: string;
|
|
57
|
+
timeout?: number;
|
|
58
|
+
logger?: Logger;
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Domain Entity Types
|
|
63
|
+
|
|
64
|
+
### GoveeDevice
|
|
65
|
+
|
|
66
|
+
Represents a Govee smart device.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
class GoveeDevice {
|
|
70
|
+
readonly deviceId: string;
|
|
71
|
+
readonly model: string; // Alias for sku (backward compatibility)
|
|
72
|
+
readonly sku: string;
|
|
73
|
+
readonly deviceName: string;
|
|
74
|
+
readonly controllable: boolean;
|
|
75
|
+
readonly retrievable: boolean;
|
|
76
|
+
readonly supportedCmds: readonly string[];
|
|
77
|
+
readonly capabilities: readonly GoveeCapability[];
|
|
78
|
+
|
|
79
|
+
equals(other: GoveeDevice): boolean;
|
|
80
|
+
supportsCommand(command: string): boolean;
|
|
81
|
+
canControl(): boolean;
|
|
82
|
+
canRetrieve(): boolean;
|
|
83
|
+
toString(): string;
|
|
84
|
+
toObject(): DeviceObject;
|
|
85
|
+
static fromObject(obj: DeviceObject): GoveeDevice;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface DeviceObject {
|
|
89
|
+
deviceId: string;
|
|
90
|
+
model: string;
|
|
91
|
+
deviceName: string;
|
|
92
|
+
controllable: boolean;
|
|
93
|
+
retrievable: boolean;
|
|
94
|
+
supportedCmds: string[];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface GoveeCapability {
|
|
98
|
+
type: string;
|
|
99
|
+
instance: string;
|
|
100
|
+
parameters?: {
|
|
101
|
+
dataType: string;
|
|
102
|
+
options?: Array<{
|
|
103
|
+
name: string;
|
|
104
|
+
value: unknown;
|
|
105
|
+
}>;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### DeviceState
|
|
111
|
+
|
|
112
|
+
Represents the current state of a device.
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
class DeviceState {
|
|
116
|
+
readonly deviceId: string;
|
|
117
|
+
readonly model: string;
|
|
118
|
+
readonly properties: readonly StateProperty[];
|
|
119
|
+
|
|
120
|
+
getPowerState(): PowerState | undefined;
|
|
121
|
+
getBrightness(): number | undefined; // 0-100
|
|
122
|
+
getColor(): ColorState | undefined;
|
|
123
|
+
getColorTemperature(): number | undefined; // Kelvin
|
|
124
|
+
isOnline(): boolean;
|
|
125
|
+
hasProperty(type: string, instance: string): boolean;
|
|
126
|
+
getProperty(type: string, instance: string): StateProperty | undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
interface StateProperty {
|
|
130
|
+
type: string;
|
|
131
|
+
instance: string;
|
|
132
|
+
value: unknown;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
type PowerState = 'on' | 'off';
|
|
136
|
+
type ColorState = { r: number; g: number; b: number };
|
|
137
|
+
type ColorTemperatureState = number; // Kelvin
|
|
138
|
+
type BrightnessState = number; // 0-100
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Command Types
|
|
142
|
+
|
|
143
|
+
Base command class and specific command implementations.
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
abstract class Command {
|
|
147
|
+
abstract readonly name: string;
|
|
148
|
+
abstract readonly value: unknown;
|
|
149
|
+
abstract toApiFormat(): { name: string; value: unknown };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
class PowerOnCommand extends Command {
|
|
153
|
+
readonly name = 'turn';
|
|
154
|
+
readonly value = 1;
|
|
155
|
+
toApiFormat(): { name: string; value: number };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
class PowerOffCommand extends Command {
|
|
159
|
+
readonly name = 'turn';
|
|
160
|
+
readonly value = 0;
|
|
161
|
+
toApiFormat(): { name: string; value: number };
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
class BrightnessCommand extends Command {
|
|
165
|
+
readonly name = 'brightness';
|
|
166
|
+
readonly value: number;
|
|
167
|
+
constructor(brightness: Brightness);
|
|
168
|
+
toApiFormat(): { name: string; value: number };
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
class ColorCommand extends Command {
|
|
172
|
+
readonly name = 'color';
|
|
173
|
+
readonly value: { r: number; g: number; b: number };
|
|
174
|
+
constructor(color: ColorRgb);
|
|
175
|
+
toApiFormat(): { name: string; value: { r: number; g: number; b: number } };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
class ColorTemperatureCommand extends Command {
|
|
179
|
+
readonly name = 'colorTem';
|
|
180
|
+
readonly value: number;
|
|
181
|
+
constructor(colorTemperature: ColorTemperature);
|
|
182
|
+
toApiFormat(): { name: string; value: number };
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### CommandFactory
|
|
187
|
+
|
|
188
|
+
Static factory for creating commands.
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
class CommandFactory {
|
|
192
|
+
static powerOn(): PowerOnCommand;
|
|
193
|
+
static powerOff(): PowerOffCommand;
|
|
194
|
+
static brightness(brightness: Brightness): BrightnessCommand;
|
|
195
|
+
static color(color: ColorRgb): ColorCommand;
|
|
196
|
+
static colorTemperature(temp: ColorTemperature): ColorTemperatureCommand;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Value Object Types
|
|
201
|
+
|
|
202
|
+
### ColorRgb
|
|
203
|
+
|
|
204
|
+
Represents RGB color values (0-255 per component).
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
class ColorRgb {
|
|
208
|
+
readonly r: number; // 0-255
|
|
209
|
+
readonly g: number; // 0-255
|
|
210
|
+
readonly b: number; // 0-255
|
|
211
|
+
|
|
212
|
+
constructor(r: number, g: number, b: number);
|
|
213
|
+
equals(other: ColorRgb): boolean;
|
|
214
|
+
toString(): string; // "rgb(r, g, b)"
|
|
215
|
+
toHex(): string; // "#rrggbb"
|
|
216
|
+
toObject(): ColorRgbObject;
|
|
217
|
+
|
|
218
|
+
static fromHex(hex: string): ColorRgb;
|
|
219
|
+
static fromObject(obj: ColorRgbObject): ColorRgb;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
interface ColorRgbObject {
|
|
223
|
+
r: number;
|
|
224
|
+
g: number;
|
|
225
|
+
b: number;
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### ColorTemperature
|
|
230
|
+
|
|
231
|
+
Represents color temperature in Kelvin (2000-9000K).
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
class ColorTemperature {
|
|
235
|
+
readonly kelvin: number; // 2000-9000
|
|
236
|
+
|
|
237
|
+
constructor(kelvin: number);
|
|
238
|
+
equals(other: ColorTemperature): boolean;
|
|
239
|
+
toString(): string;
|
|
240
|
+
isWarm(): boolean; // < 4000K
|
|
241
|
+
isCool(): boolean; // > 5000K
|
|
242
|
+
toObject(): ColorTemperatureObject;
|
|
243
|
+
|
|
244
|
+
static warmWhite(): ColorTemperature; // 2700K
|
|
245
|
+
static coolWhite(): ColorTemperature; // 6500K
|
|
246
|
+
static daylight(): ColorTemperature; // 5600K
|
|
247
|
+
static fromObject(obj: ColorTemperatureObject): ColorTemperature;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
interface ColorTemperatureObject {
|
|
251
|
+
kelvin: number;
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Brightness
|
|
256
|
+
|
|
257
|
+
Represents brightness level (0-100).
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
class Brightness {
|
|
261
|
+
readonly level: number; // 0-100
|
|
262
|
+
|
|
263
|
+
constructor(level: number);
|
|
264
|
+
equals(other: Brightness): boolean;
|
|
265
|
+
toString(): string;
|
|
266
|
+
asPercent(): number; // 0.0-1.0
|
|
267
|
+
isDim(): boolean; // < 30
|
|
268
|
+
isBright(): boolean; // > 70
|
|
269
|
+
toObject(): BrightnessObject;
|
|
270
|
+
|
|
271
|
+
static dim(): Brightness; // 25
|
|
272
|
+
static medium(): Brightness; // 50
|
|
273
|
+
static bright(): Brightness; // 75
|
|
274
|
+
static fromObject(obj: BrightnessObject): Brightness;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
interface BrightnessObject {
|
|
278
|
+
level: number;
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## Error Types
|
|
283
|
+
|
|
284
|
+
### Error Hierarchy
|
|
285
|
+
|
|
286
|
+
Complete error class hierarchy with TypeScript types.
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
abstract class GoveeApiClientError extends Error {
|
|
290
|
+
abstract readonly errorType: string;
|
|
291
|
+
abstract isRetryable(): boolean;
|
|
292
|
+
|
|
293
|
+
constructor(message: string);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
class GoveeApiError extends GoveeApiClientError {
|
|
297
|
+
readonly errorType = 'GoveeApiError';
|
|
298
|
+
readonly statusCode?: number;
|
|
299
|
+
readonly response?: unknown;
|
|
300
|
+
|
|
301
|
+
constructor(message: string, statusCode?: number, response?: unknown);
|
|
302
|
+
isRetryable(): boolean;
|
|
303
|
+
isDeviceOffline(): boolean;
|
|
304
|
+
getRecommendation(): string;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
class InvalidApiKeyError extends GoveeApiClientError {
|
|
308
|
+
readonly errorType = 'InvalidApiKeyError';
|
|
309
|
+
|
|
310
|
+
constructor(message: string);
|
|
311
|
+
isRetryable(): false;
|
|
312
|
+
getRecommendation(): string;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
class RateLimitError extends GoveeApiClientError {
|
|
316
|
+
readonly errorType = 'RateLimitError';
|
|
317
|
+
readonly retryAfterMs?: number;
|
|
318
|
+
|
|
319
|
+
constructor(message: string, retryAfterMs?: number);
|
|
320
|
+
isRetryable(): true;
|
|
321
|
+
getRetryAfterMs(): number;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
class NetworkError extends GoveeApiClientError {
|
|
325
|
+
readonly errorType = 'NetworkError';
|
|
326
|
+
readonly cause?: Error;
|
|
327
|
+
|
|
328
|
+
constructor(message: string, cause?: Error);
|
|
329
|
+
isRetryable(): boolean;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
class ValidationError extends GoveeApiClientError {
|
|
333
|
+
readonly code = 'VALIDATION_ERROR';
|
|
334
|
+
readonly zodError: ZodError;
|
|
335
|
+
readonly rawData: unknown;
|
|
336
|
+
|
|
337
|
+
constructor(message: string, zodError: ZodError, rawData: unknown);
|
|
338
|
+
|
|
339
|
+
static fromZodError(zodError: ZodError, rawData: unknown): ValidationError;
|
|
340
|
+
getValidationDetails(): Array<{ path: string; message: string; received: unknown }>;
|
|
341
|
+
getValidationSummary(): string;
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Error Type Guards
|
|
346
|
+
|
|
347
|
+
TypeScript type guards for error handling.
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
function isGoveeApiError(error: unknown): error is GoveeApiError;
|
|
351
|
+
function isInvalidApiKeyError(error: unknown): error is InvalidApiKeyError;
|
|
352
|
+
function isRateLimitError(error: unknown): error is RateLimitError;
|
|
353
|
+
function isNetworkError(error: unknown): error is NetworkError;
|
|
354
|
+
function isValidationError(error: unknown): error is ValidationError;
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Validation Types
|
|
358
|
+
|
|
359
|
+
### Zod Schemas
|
|
360
|
+
|
|
361
|
+
Exported Zod schemas for runtime API response validation.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
import { z } from 'zod';
|
|
365
|
+
|
|
366
|
+
// Device capability schema
|
|
367
|
+
const GoveeCapabilitySchema: z.ZodType;
|
|
368
|
+
|
|
369
|
+
// Individual device response schema
|
|
370
|
+
const GoveeDeviceResponseSchema: z.ZodType;
|
|
371
|
+
|
|
372
|
+
// Full devices API response schema
|
|
373
|
+
const GoveeDevicesResponseSchema: z.ZodObject<{
|
|
374
|
+
code: z.ZodNumber;
|
|
375
|
+
message: z.ZodString;
|
|
376
|
+
data: z.ZodArray<typeof GoveeDeviceResponseSchema>;
|
|
377
|
+
}>;
|
|
378
|
+
|
|
379
|
+
// Device state capability schema
|
|
380
|
+
const GoveeStateCapabilitySchema: z.ZodObject<{
|
|
381
|
+
type: z.ZodString;
|
|
382
|
+
instance: z.ZodString;
|
|
383
|
+
state: z.ZodObject<{ value: z.ZodUnknown }>;
|
|
384
|
+
}>;
|
|
385
|
+
|
|
386
|
+
// Device state API response schema
|
|
387
|
+
const GoveeStateResponseSchema: z.ZodObject<{
|
|
388
|
+
code: z.ZodNumber;
|
|
389
|
+
message: z.ZodString;
|
|
390
|
+
data: z.ZodObject<{
|
|
391
|
+
device: z.ZodString;
|
|
392
|
+
sku: z.ZodString;
|
|
393
|
+
capabilities: z.ZodArray<typeof GoveeStateCapabilitySchema>;
|
|
394
|
+
}>;
|
|
395
|
+
}>;
|
|
396
|
+
|
|
397
|
+
// Command API response schema
|
|
398
|
+
const GoveeCommandResponseSchema: z.ZodObject<{
|
|
399
|
+
code: z.ZodNumber;
|
|
400
|
+
message: z.ZodString;
|
|
401
|
+
data: z.ZodOptional<z.ZodUnknown>;
|
|
402
|
+
}>;
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Response Types
|
|
406
|
+
|
|
407
|
+
TypeScript types inferred from Zod schemas.
|
|
408
|
+
|
|
409
|
+
```typescript
|
|
410
|
+
// Type inferred from GoveeDevicesResponseSchema
|
|
411
|
+
type GoveeDevicesResponse = {
|
|
412
|
+
code: number;
|
|
413
|
+
message: string;
|
|
414
|
+
data: Array<{
|
|
415
|
+
device?: string | null;
|
|
416
|
+
sku?: string | null;
|
|
417
|
+
deviceName?: string | null;
|
|
418
|
+
capabilities?: Array<{
|
|
419
|
+
type?: string | null;
|
|
420
|
+
instance?: string | null;
|
|
421
|
+
parameters?: {
|
|
422
|
+
dataType: string;
|
|
423
|
+
options?: Array<{
|
|
424
|
+
name: string;
|
|
425
|
+
value: unknown;
|
|
426
|
+
}>;
|
|
427
|
+
};
|
|
428
|
+
}> | null;
|
|
429
|
+
}>;
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
// Type inferred from GoveeStateResponseSchema
|
|
433
|
+
type GoveeStateResponse = {
|
|
434
|
+
code: number;
|
|
435
|
+
message: string;
|
|
436
|
+
data: {
|
|
437
|
+
device: string;
|
|
438
|
+
sku: string;
|
|
439
|
+
capabilities: Array<{
|
|
440
|
+
type: string;
|
|
441
|
+
instance: string;
|
|
442
|
+
state: {
|
|
443
|
+
value: unknown;
|
|
444
|
+
};
|
|
445
|
+
}>;
|
|
446
|
+
};
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
// Type inferred from GoveeCommandResponseSchema
|
|
450
|
+
type GoveeCommandResponse = {
|
|
451
|
+
code: number;
|
|
452
|
+
message: string;
|
|
453
|
+
data?: unknown;
|
|
454
|
+
};
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Using Validation Schemas
|
|
458
|
+
|
|
459
|
+
Examples of using exported schemas for custom validation:
|
|
460
|
+
|
|
461
|
+
```typescript
|
|
462
|
+
import {
|
|
463
|
+
GoveeDevicesResponseSchema,
|
|
464
|
+
GoveeStateResponseSchema,
|
|
465
|
+
type GoveeDevicesResponse,
|
|
466
|
+
} from '@felixgeelhaar/govee-api-client';
|
|
467
|
+
|
|
468
|
+
// Validate unknown data
|
|
469
|
+
function validateDevicesResponse(data: unknown): GoveeDevicesResponse {
|
|
470
|
+
return GoveeDevicesResponseSchema.parse(data); // Throws on invalid data
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Safe validation without throwing
|
|
474
|
+
function safeValidate(data: unknown) {
|
|
475
|
+
const result = GoveeDevicesResponseSchema.safeParse(data);
|
|
476
|
+
|
|
477
|
+
if (result.success) {
|
|
478
|
+
const validData: GoveeDevicesResponse = result.data;
|
|
479
|
+
return validData;
|
|
480
|
+
} else {
|
|
481
|
+
console.error('Validation failed:', result.error);
|
|
482
|
+
return null;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// Custom schema composition
|
|
487
|
+
import { z } from 'zod';
|
|
488
|
+
|
|
489
|
+
const ExtendedDeviceSchema = GoveeDevicesResponseSchema.extend({
|
|
490
|
+
metadata: z.object({
|
|
491
|
+
fetchedAt: z.date(),
|
|
492
|
+
cacheKey: z.string(),
|
|
493
|
+
}),
|
|
494
|
+
});
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
### ValidationError Details
|
|
498
|
+
|
|
499
|
+
Structure of validation error details returned by `getValidationDetails()`:
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
interface ValidationDetail {
|
|
503
|
+
path: string; // JSON path to the field that failed (e.g., "data.0.deviceName")
|
|
504
|
+
message: string; // Human-readable error message
|
|
505
|
+
received: unknown; // The actual value that failed validation
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Example usage
|
|
509
|
+
try {
|
|
510
|
+
await client.getDevices();
|
|
511
|
+
} catch (error) {
|
|
512
|
+
if (error instanceof ValidationError) {
|
|
513
|
+
const details: ValidationDetail[] = error.getValidationDetails();
|
|
514
|
+
|
|
515
|
+
details.forEach(({ path, message, received }) => {
|
|
516
|
+
console.log(`Field "${path}" is invalid`);
|
|
517
|
+
console.log(`Error: ${message}`);
|
|
518
|
+
console.log(`Got: ${JSON.stringify(received)}`);
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
## Retry & Rate Limiting Types
|
|
525
|
+
|
|
526
|
+
### RetryPolicy
|
|
527
|
+
|
|
528
|
+
Configuration for retry behavior.
|
|
529
|
+
|
|
530
|
+
```typescript
|
|
531
|
+
class RetryPolicy {
|
|
532
|
+
constructor(config: RetryPolicyConfig);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
interface RetryPolicyConfig {
|
|
536
|
+
backoff: BackoffStrategy;
|
|
537
|
+
jitter: JitterConfig;
|
|
538
|
+
condition: RetryCondition;
|
|
539
|
+
circuitBreaker: CircuitBreakerConfig;
|
|
540
|
+
enableMetrics: boolean;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
interface BackoffStrategy {
|
|
544
|
+
type: 'exponential' | 'linear' | 'constant';
|
|
545
|
+
initialDelayMs: number;
|
|
546
|
+
maxDelayMs: number;
|
|
547
|
+
multiplier?: number; // For exponential backoff
|
|
548
|
+
increment?: number; // For linear backoff
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
interface JitterConfig {
|
|
552
|
+
type: 'none' | 'full' | 'equal' | 'decorrelated';
|
|
553
|
+
factor?: number; // 0.0-1.0, randomization factor
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
interface RetryCondition {
|
|
557
|
+
maxAttempts: number;
|
|
558
|
+
maxTotalTimeMs: number;
|
|
559
|
+
retryableStatusCodes: number[];
|
|
560
|
+
retryableErrorTypes: (new (...args: any[]) => Error)[];
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
interface CircuitBreakerConfig {
|
|
564
|
+
enabled: boolean;
|
|
565
|
+
failureThreshold: number; // Failures before opening
|
|
566
|
+
recoveryTimeoutMs: number; // Time before trying half-open
|
|
567
|
+
halfOpenSuccessThreshold: number; // Successes needed to close
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### RetryMetrics
|
|
572
|
+
|
|
573
|
+
Metrics for monitoring retry behavior.
|
|
574
|
+
|
|
575
|
+
```typescript
|
|
576
|
+
interface RetryMetrics {
|
|
577
|
+
totalAttempts: number;
|
|
578
|
+
successfulRetries: number;
|
|
579
|
+
failedRetries: number;
|
|
580
|
+
totalRetryTimeMs: number;
|
|
581
|
+
averageRetryDelayMs: number;
|
|
582
|
+
circuitBreakerState: CircuitBreakerState;
|
|
583
|
+
lastError?: Error;
|
|
584
|
+
lastRetryTimestamp?: Date;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
type CircuitBreakerState = 'closed' | 'open' | 'half-open';
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### Rate Limiter Types
|
|
591
|
+
|
|
592
|
+
Types for rate limiting functionality.
|
|
593
|
+
|
|
594
|
+
```typescript
|
|
595
|
+
interface RateLimiterStats {
|
|
596
|
+
currentRequests: number;
|
|
597
|
+
maxRequests: number;
|
|
598
|
+
utilizationPercent: number;
|
|
599
|
+
queueSize: number;
|
|
600
|
+
canExecuteImmediately: boolean;
|
|
601
|
+
nextAvailableSlot: Date | null;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
interface ServiceStats {
|
|
605
|
+
rateLimiter: RateLimiterStats;
|
|
606
|
+
retries?: RetryMetrics;
|
|
607
|
+
configuration: ServiceConfiguration;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
interface ServiceConfiguration {
|
|
611
|
+
rateLimit: number;
|
|
612
|
+
timeout: number;
|
|
613
|
+
retriesEnabled: boolean;
|
|
614
|
+
retryPolicy?: string;
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
## Repository Types
|
|
619
|
+
|
|
620
|
+
### IGoveeDeviceRepository
|
|
621
|
+
|
|
622
|
+
Interface for device repository implementations.
|
|
623
|
+
|
|
624
|
+
```typescript
|
|
625
|
+
interface IGoveeDeviceRepository {
|
|
626
|
+
findAll(): Promise<GoveeDevice[]>;
|
|
627
|
+
findState(deviceId: string, model: string): Promise<DeviceState>;
|
|
628
|
+
sendCommand(deviceId: string, model: string, command: Command): Promise<void>;
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### API Response Types
|
|
633
|
+
|
|
634
|
+
Internal types for API responses (used by repository).
|
|
635
|
+
|
|
636
|
+
```typescript
|
|
637
|
+
interface DevicesResponse {
|
|
638
|
+
code: number;
|
|
639
|
+
message: string;
|
|
640
|
+
data: {
|
|
641
|
+
devices: DeviceData[];
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
interface DeviceData {
|
|
646
|
+
device: string; // deviceId
|
|
647
|
+
sku: string; // model
|
|
648
|
+
deviceName: string;
|
|
649
|
+
capabilities: GoveeCapability[];
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
interface StateResponse {
|
|
653
|
+
code: number;
|
|
654
|
+
message: string;
|
|
655
|
+
data: {
|
|
656
|
+
device: string;
|
|
657
|
+
sku: string;
|
|
658
|
+
capabilities: StateCapability[];
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
interface StateCapability {
|
|
663
|
+
type: string;
|
|
664
|
+
instance: string;
|
|
665
|
+
state: {
|
|
666
|
+
value: unknown;
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
interface CommandResponse {
|
|
671
|
+
code: number;
|
|
672
|
+
message: string;
|
|
673
|
+
data: Record<string, unknown>;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
interface ApiErrorResponse {
|
|
677
|
+
code: number;
|
|
678
|
+
message: string;
|
|
679
|
+
data?: unknown;
|
|
680
|
+
}
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
## Utility Types
|
|
684
|
+
|
|
685
|
+
### Generic Utility Types
|
|
686
|
+
|
|
687
|
+
Helpful TypeScript utility types.
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
// Extract device ID type
|
|
691
|
+
type DeviceId = GoveeDevice['deviceId'];
|
|
692
|
+
|
|
693
|
+
// Extract model type
|
|
694
|
+
type DeviceModel = GoveeDevice['model'];
|
|
695
|
+
|
|
696
|
+
// Extract supported command types
|
|
697
|
+
type SupportedCommand = GoveeDevice['supportedCmds'][number];
|
|
698
|
+
|
|
699
|
+
// Extract power state union
|
|
700
|
+
type PowerState = ReturnType<DeviceState['getPowerState']>;
|
|
701
|
+
|
|
702
|
+
// Extract color object type
|
|
703
|
+
type ColorObject = NonNullable<ReturnType<DeviceState['getColor']>>;
|
|
704
|
+
|
|
705
|
+
// Configuration with required API key
|
|
706
|
+
type RequiredApiKeyConfig = Required<Pick<GoveeClientConfig, 'apiKey'>> &
|
|
707
|
+
Partial<Omit<GoveeClientConfig, 'apiKey'>>;
|
|
708
|
+
|
|
709
|
+
// Partial device for updates
|
|
710
|
+
type PartialDevice = Partial<Pick<GoveeDevice, 'deviceName' | 'controllable' | 'retrievable'>>;
|
|
711
|
+
|
|
712
|
+
// Command name union type
|
|
713
|
+
type CommandName = Command['name'];
|
|
714
|
+
|
|
715
|
+
// Command value type
|
|
716
|
+
type CommandValue = Command['value'];
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### Async Return Types
|
|
720
|
+
|
|
721
|
+
Types for async method return values.
|
|
722
|
+
|
|
723
|
+
```typescript
|
|
724
|
+
// Device list operations
|
|
725
|
+
type DeviceListResult = Promise<GoveeDevice[]>;
|
|
726
|
+
type DeviceSearchResult = Promise<GoveeDevice | undefined>;
|
|
727
|
+
type DeviceFilterResult = Promise<GoveeDevice[]>;
|
|
728
|
+
|
|
729
|
+
// Device control operations
|
|
730
|
+
type ControlResult = Promise<void>;
|
|
731
|
+
type StateResult = Promise<DeviceState>;
|
|
732
|
+
type StatusResult = Promise<boolean>;
|
|
733
|
+
|
|
734
|
+
// Monitoring operations
|
|
735
|
+
type StatsResult = RateLimiterStats;
|
|
736
|
+
type MetricsResult = RetryMetrics | undefined;
|
|
737
|
+
type ServiceStatsResult = ServiceStats;
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
### Event Types
|
|
741
|
+
|
|
742
|
+
Types for potential event handling (future extension).
|
|
743
|
+
|
|
744
|
+
```typescript
|
|
745
|
+
interface DeviceEvent {
|
|
746
|
+
type: 'state-changed' | 'offline' | 'online' | 'error';
|
|
747
|
+
deviceId: string;
|
|
748
|
+
model: string;
|
|
749
|
+
timestamp: Date;
|
|
750
|
+
data?: unknown;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
interface RateLimitEvent {
|
|
754
|
+
type: 'limit-reached' | 'limit-warning' | 'queue-full';
|
|
755
|
+
timestamp: Date;
|
|
756
|
+
stats: RateLimiterStats;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
interface RetryEvent {
|
|
760
|
+
type: 'retry-attempt' | 'retry-success' | 'retry-failure' | 'circuit-breaker';
|
|
761
|
+
timestamp: Date;
|
|
762
|
+
attempt: number;
|
|
763
|
+
delay: number;
|
|
764
|
+
error?: Error;
|
|
765
|
+
}
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
### Type Predicates
|
|
769
|
+
|
|
770
|
+
Type guard functions for runtime type checking.
|
|
771
|
+
|
|
772
|
+
```typescript
|
|
773
|
+
// Device type guards
|
|
774
|
+
function isGoveeDevice(obj: unknown): obj is GoveeDevice;
|
|
775
|
+
function isDeviceState(obj: unknown): obj is DeviceState;
|
|
776
|
+
function isCommand(obj: unknown): obj is Command;
|
|
777
|
+
|
|
778
|
+
// Value object type guards
|
|
779
|
+
function isColorRgb(obj: unknown): obj is ColorRgb;
|
|
780
|
+
function isColorTemperature(obj: unknown): obj is ColorTemperature;
|
|
781
|
+
function isBrightness(obj: unknown): obj is Brightness;
|
|
782
|
+
|
|
783
|
+
// Configuration type guards
|
|
784
|
+
function isValidClientConfig(obj: unknown): obj is GoveeClientConfig;
|
|
785
|
+
function isValidRetryPolicy(obj: unknown): obj is RetryPolicy;
|
|
786
|
+
|
|
787
|
+
// State property type guards
|
|
788
|
+
function isPowerProperty(prop: StateProperty): prop is StateProperty & { value: 0 | 1 };
|
|
789
|
+
function isBrightnessProperty(prop: StateProperty): prop is StateProperty & { value: number };
|
|
790
|
+
function isColorProperty(prop: StateProperty): prop is StateProperty & { value: ColorState };
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
### Branded Types
|
|
794
|
+
|
|
795
|
+
Branded types for additional type safety.
|
|
796
|
+
|
|
797
|
+
```typescript
|
|
798
|
+
// Branded string types for IDs
|
|
799
|
+
type DeviceId = string & { readonly __brand: 'DeviceId' };
|
|
800
|
+
type ModelId = string & { readonly __brand: 'ModelId' };
|
|
801
|
+
type ApiKey = string & { readonly __brand: 'ApiKey' };
|
|
802
|
+
|
|
803
|
+
// Branded number types for values
|
|
804
|
+
type KelvinValue = number & { readonly __brand: 'Kelvin' };
|
|
805
|
+
type BrightnessValue = number & { readonly __brand: 'Brightness' };
|
|
806
|
+
type RgbValue = number & { readonly __brand: 'RgbComponent' };
|
|
807
|
+
|
|
808
|
+
// Type constructors
|
|
809
|
+
function createDeviceId(id: string): DeviceId;
|
|
810
|
+
function createModelId(model: string): ModelId;
|
|
811
|
+
function createApiKey(key: string): ApiKey;
|
|
812
|
+
function createKelvinValue(kelvin: number): KelvinValue;
|
|
813
|
+
function createBrightnessValue(brightness: number): BrightnessValue;
|
|
814
|
+
function createRgbValue(rgb: number): RgbValue;
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
### Template Literal Types
|
|
818
|
+
|
|
819
|
+
Template literal types for command names and property types.
|
|
820
|
+
|
|
821
|
+
```typescript
|
|
822
|
+
// Command name templates
|
|
823
|
+
type PowerCommand = `turn_${string}`;
|
|
824
|
+
type ColorCommand = `color_${string}`;
|
|
825
|
+
type BrightnessCommand = `brightness_${string}`;
|
|
826
|
+
|
|
827
|
+
// Property type templates
|
|
828
|
+
type OnOffProperty = `devices.capabilities.on_off.${string}`;
|
|
829
|
+
type RangeProperty = `devices.capabilities.range.${string}`;
|
|
830
|
+
type ColorProperty = `devices.capabilities.color_setting.${string}`;
|
|
831
|
+
|
|
832
|
+
// Instance name templates
|
|
833
|
+
type PowerInstance = 'powerSwitch';
|
|
834
|
+
type BrightnessInstance = 'brightness';
|
|
835
|
+
type ColorRgbInstance = 'colorRgb';
|
|
836
|
+
type ColorTemperatureInstance = 'colorTemperatureK';
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### Conditional Types
|
|
840
|
+
|
|
841
|
+
Conditional types for advanced type manipulation.
|
|
842
|
+
|
|
843
|
+
```typescript
|
|
844
|
+
// Extract command type based on name
|
|
845
|
+
type CommandByName<T extends string> = T extends 'turn'
|
|
846
|
+
? PowerOnCommand | PowerOffCommand
|
|
847
|
+
: T extends 'brightness'
|
|
848
|
+
? BrightnessCommand
|
|
849
|
+
: T extends 'color'
|
|
850
|
+
? ColorCommand
|
|
851
|
+
: T extends 'colorTem'
|
|
852
|
+
? ColorTemperatureCommand
|
|
853
|
+
: never;
|
|
854
|
+
|
|
855
|
+
// Extract value type based on command
|
|
856
|
+
type ValueByCommand<T extends Command> = T extends PowerOnCommand | PowerOffCommand
|
|
857
|
+
? number
|
|
858
|
+
: T extends BrightnessCommand
|
|
859
|
+
? number
|
|
860
|
+
: T extends ColorCommand
|
|
861
|
+
? ColorState
|
|
862
|
+
: T extends ColorTemperatureCommand
|
|
863
|
+
? number
|
|
864
|
+
: never;
|
|
865
|
+
|
|
866
|
+
// Device with specific capabilities
|
|
867
|
+
type DeviceWithCapability<T extends string> = GoveeDevice & {
|
|
868
|
+
supportedCmds: readonly T[];
|
|
869
|
+
};
|
|
870
|
+
|
|
871
|
+
// Controllable device
|
|
872
|
+
type ControllableDevice = DeviceWithCapability<'turn'>;
|
|
873
|
+
|
|
874
|
+
// Color-capable device
|
|
875
|
+
type ColorDevice = DeviceWithCapability<'color'>;
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
### Mapped Types
|
|
879
|
+
|
|
880
|
+
Mapped types for transforming interfaces.
|
|
881
|
+
|
|
882
|
+
```typescript
|
|
883
|
+
// Optional device properties
|
|
884
|
+
type OptionalDevice = {
|
|
885
|
+
[K in keyof GoveeDevice]?: GoveeDevice[K];
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
// Required configuration
|
|
889
|
+
type RequiredConfig = {
|
|
890
|
+
[K in keyof GoveeClientConfig]-?: GoveeClientConfig[K];
|
|
891
|
+
};
|
|
892
|
+
|
|
893
|
+
// Serializable versions (without methods)
|
|
894
|
+
type SerializableDevice = Pick<
|
|
895
|
+
GoveeDevice,
|
|
896
|
+
'deviceId' | 'model' | 'deviceName' | 'controllable' | 'retrievable' | 'supportedCmds'
|
|
897
|
+
>;
|
|
898
|
+
|
|
899
|
+
type SerializableState = Pick<DeviceState, 'deviceId' | 'model'> & {
|
|
900
|
+
properties: StateProperty[];
|
|
901
|
+
powerState?: PowerState;
|
|
902
|
+
brightness?: number;
|
|
903
|
+
color?: ColorState;
|
|
904
|
+
colorTemperature?: number;
|
|
905
|
+
online: boolean;
|
|
906
|
+
};
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
## Type Validation
|
|
910
|
+
|
|
911
|
+
### Runtime Type Validation with Zod
|
|
912
|
+
|
|
913
|
+
Schema definitions for runtime validation.
|
|
914
|
+
|
|
915
|
+
```typescript
|
|
916
|
+
import { z } from 'zod';
|
|
917
|
+
|
|
918
|
+
// Configuration schemas
|
|
919
|
+
const GoveeClientConfigSchema = z.object({
|
|
920
|
+
apiKey: z.string().min(1),
|
|
921
|
+
timeout: z.number().int().positive().optional(),
|
|
922
|
+
rateLimit: z.number().int().positive().optional(),
|
|
923
|
+
logger: z.any().optional(),
|
|
924
|
+
enableRetries: z.boolean().optional(),
|
|
925
|
+
retryPolicy: z
|
|
926
|
+
.union([
|
|
927
|
+
z.literal('development'),
|
|
928
|
+
z.literal('testing'),
|
|
929
|
+
z.literal('production'),
|
|
930
|
+
z.literal('custom'),
|
|
931
|
+
z.any(), // RetryPolicy instance
|
|
932
|
+
])
|
|
933
|
+
.optional(),
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
// Value object schemas
|
|
937
|
+
const ColorRgbSchema = z.object({
|
|
938
|
+
r: z.number().int().min(0).max(255),
|
|
939
|
+
g: z.number().int().min(0).max(255),
|
|
940
|
+
b: z.number().int().min(0).max(255),
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
const ColorTemperatureSchema = z.object({
|
|
944
|
+
kelvin: z.number().int().min(2000).max(9000),
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
const BrightnessSchema = z.object({
|
|
948
|
+
level: z.number().int().min(0).max(100),
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
// Device schemas
|
|
952
|
+
const GoveeDeviceSchema = z.object({
|
|
953
|
+
deviceId: z.string().min(1),
|
|
954
|
+
model: z.string().min(1),
|
|
955
|
+
deviceName: z.string().min(1),
|
|
956
|
+
controllable: z.boolean(),
|
|
957
|
+
retrievable: z.boolean(),
|
|
958
|
+
supportedCmds: z.array(z.string()),
|
|
959
|
+
});
|
|
960
|
+
|
|
961
|
+
// API response schemas
|
|
962
|
+
const ApiErrorSchema = z.object({
|
|
963
|
+
code: z.number(),
|
|
964
|
+
message: z.string(),
|
|
965
|
+
data: z.unknown().optional(),
|
|
966
|
+
});
|
|
967
|
+
|
|
968
|
+
// Type extraction from schemas
|
|
969
|
+
type ValidatedClientConfig = z.infer<typeof GoveeClientConfigSchema>;
|
|
970
|
+
type ValidatedColorRgb = z.infer<typeof ColorRgbSchema>;
|
|
971
|
+
type ValidatedDevice = z.infer<typeof GoveeDeviceSchema>;
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
This comprehensive type reference provides LLMs with complete type information for generating accurate, type-safe code when working with the Govee API Client library.
|