trane-thermostat-api 1.0.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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -0
  3. package/dist/client/auth.d.ts +50 -0
  4. package/dist/client/auth.d.ts.map +1 -0
  5. package/dist/client/auth.js +236 -0
  6. package/dist/client/auth.js.map +1 -0
  7. package/dist/client/nexia-client.d.ts +48 -0
  8. package/dist/client/nexia-client.d.ts.map +1 -0
  9. package/dist/client/nexia-client.js +311 -0
  10. package/dist/client/nexia-client.js.map +1 -0
  11. package/dist/devices/nexia-automation.d.ts +15 -0
  12. package/dist/devices/nexia-automation.d.ts.map +1 -0
  13. package/dist/devices/nexia-automation.js +39 -0
  14. package/dist/devices/nexia-automation.js.map +1 -0
  15. package/dist/devices/nexia-sensor.d.ts +34 -0
  16. package/dist/devices/nexia-sensor.d.ts.map +1 -0
  17. package/dist/devices/nexia-sensor.js +152 -0
  18. package/dist/devices/nexia-sensor.js.map +1 -0
  19. package/dist/devices/nexia-thermostat.d.ts +73 -0
  20. package/dist/devices/nexia-thermostat.d.ts.map +1 -0
  21. package/dist/devices/nexia-thermostat.js +357 -0
  22. package/dist/devices/nexia-thermostat.js.map +1 -0
  23. package/dist/devices/nexia-zone.d.ts +61 -0
  24. package/dist/devices/nexia-zone.d.ts.map +1 -0
  25. package/dist/devices/nexia-zone.js +370 -0
  26. package/dist/devices/nexia-zone.js.map +1 -0
  27. package/dist/index.d.ts +15 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +41 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/types/api.d.ts +277 -0
  32. package/dist/types/api.d.ts.map +1 -0
  33. package/dist/types/api.js +3 -0
  34. package/dist/types/api.js.map +1 -0
  35. package/dist/types/constants.d.ts +137 -0
  36. package/dist/types/constants.d.ts.map +1 -0
  37. package/dist/types/constants.js +160 -0
  38. package/dist/types/constants.js.map +1 -0
  39. package/dist/types/interfaces.d.ts +211 -0
  40. package/dist/types/interfaces.d.ts.map +1 -0
  41. package/dist/types/interfaces.js +3 -0
  42. package/dist/types/interfaces.js.map +1 -0
  43. package/dist/utils/errors.d.ts +94 -0
  44. package/dist/utils/errors.d.ts.map +1 -0
  45. package/dist/utils/errors.js +231 -0
  46. package/dist/utils/errors.js.map +1 -0
  47. package/dist/utils/http-utils.d.ts +59 -0
  48. package/dist/utils/http-utils.d.ts.map +1 -0
  49. package/dist/utils/http-utils.js +273 -0
  50. package/dist/utils/http-utils.js.map +1 -0
  51. package/dist/utils/json-utils.d.ts +32 -0
  52. package/dist/utils/json-utils.d.ts.map +1 -0
  53. package/dist/utils/json-utils.js +389 -0
  54. package/dist/utils/json-utils.js.map +1 -0
  55. package/dist/utils/validation.d.ts +52 -0
  56. package/dist/utils/validation.d.ts.map +1 -0
  57. package/dist/utils/validation.js +272 -0
  58. package/dist/utils/validation.js.map +1 -0
  59. package/package.json +69 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Spencer S
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # Nexia Homebridge Library
2
+
3
+ A TypeScript/Node.js library for controlling Nexia/Trane/American Standard thermostats, specifically designed for Homebridge integration.
4
+
5
+ ## Overview
6
+
7
+ This library provides a complete rewrite of the Python Nexia library in TypeScript, offering:
8
+
9
+ - **Full TypeScript support** with comprehensive type definitions
10
+ - **Homebridge-optimized** architecture for seamless HomeKit integration
11
+ - **Modern async/await** patterns for all API interactions
12
+ - **Multi-zone support** with individual thermostat zone control
13
+ - **RoomIQ sensor integration** for enhanced temperature monitoring
14
+ - **Comprehensive error handling** with structured error hierarchy
15
+
16
+ ## Supported Devices
17
+
18
+ - **Nexia Thermostats**: XL950, XL1050, XL824, UX360
19
+ - **Trane Thermostats**: Compatible with Nexia API
20
+ - **American Standard**: Compatible with Nexia API
21
+
22
+ ## Features
23
+
24
+ ### Thermostat Control
25
+ - System mode control (Auto, Heat, Cool, Off)
26
+ - Temperature setpoint management with deadband validation
27
+ - Fan speed and mode control
28
+ - Emergency heat support
29
+ - Outdoor temperature monitoring
30
+ - Variable speed compressor monitoring
31
+
32
+ ### Zone Management
33
+ - Individual zone temperature control
34
+ - Zone-specific mode settings
35
+ - Hold/schedule management
36
+ - Preset mode support (Home, Away, Sleep)
37
+ - RoomIQ sensor selection and monitoring
38
+
39
+ ### Humidity & Air Quality
40
+ - Humidity monitoring and control
41
+ - Dehumidify/humidify setpoint management
42
+ - Air cleaner mode control (Auto, Quick, Allergy)
43
+
44
+ ### Advanced Features
45
+ - ETag-based caching for efficient API usage
46
+ - Automatic session management and re-authentication
47
+ - Rate-limited login attempts to prevent account lockout
48
+ - Brand-specific URL handling (Nexia, Trane, American Standard)
49
+ - Comprehensive device capability detection
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ npm install trane-thermostat-api
55
+ ```
56
+
57
+ ## Quick Start
58
+
59
+ ```typescript
60
+ import { NexiaClient, BrandType } from 'trane-thermostat-api';
61
+
62
+ const client = new NexiaClient({
63
+ username: 'your-email@example.com',
64
+ password: 'your-password',
65
+ brand: BrandType.NEXIA
66
+ });
67
+
68
+ // Authenticate and discover devices
69
+ await client.login();
70
+ const thermostats = await client.getThermostats();
71
+
72
+ // Control thermostat
73
+ const thermostat = thermostats[0];
74
+ await thermostat.setFanMode('auto');
75
+
76
+ // Control zones
77
+ const zone = thermostat.zones[0];
78
+ await zone.setTemperatures({
79
+ heatingSetpoint: 70,
80
+ coolingSetpoint: 75
81
+ });
82
+ ```
83
+
84
+ ## API Documentation
85
+
86
+ ### Core Classes
87
+
88
+ #### NexiaClient
89
+ Main HTTP client for API communication and device discovery.
90
+
91
+ #### NexiaThermostat
92
+ Represents a physical thermostat with full feature detection and control.
93
+
94
+ #### NexiaZone
95
+ Represents a zone/room within a thermostat with independent temperature control.
96
+
97
+ #### NexiaSensor
98
+ RoomIQ temperature and humidity sensor with battery monitoring.
99
+
100
+ ## Homebridge Integration
101
+
102
+ This library is designed specifically for Homebridge plugins. See the included platform implementation for complete HomeKit integration examples.
103
+
104
+ ## Development
105
+
106
+ ```bash
107
+ # Install dependencies
108
+ npm install
109
+
110
+ # Build the project
111
+ npm run build
112
+
113
+ # Run tests
114
+ npm test
115
+
116
+ # Run linting
117
+ npm run lint
118
+
119
+ # Watch mode for development
120
+ npm run dev
121
+ ```
122
+
123
+ ## Testing
124
+
125
+ The test suite includes:
126
+ - Unit tests for all core classes
127
+ - Mock HTTP responses for API testing
128
+ - Validation logic testing
129
+ - Error handling scenarios
130
+ - Integration tests with real API endpoints
131
+
132
+ ```bash
133
+ npm run test:coverage
134
+ ```
135
+
136
+ ## Contributing
137
+
138
+ 1. Fork the repository
139
+ 2. Create a feature branch
140
+ 3. Make your changes with tests
141
+ 4. Run the test suite
142
+ 5. Submit a pull request
143
+
144
+ ## License
145
+
146
+ MIT License - see LICENSE file for details.
147
+
148
+ ## Acknowledgments
149
+
150
+ Based on the original Python Nexia library architecture, rewritten for modern TypeScript/Node.js environments with Homebridge-specific optimizations.
@@ -0,0 +1,50 @@
1
+ import { BrandType } from '../types/constants';
2
+ import { AuthTokens } from '../types/api';
3
+ import { HttpClient } from '../utils/http-utils';
4
+ export interface AuthConfig {
5
+ username: string;
6
+ password: string;
7
+ deviceName?: string;
8
+ brand: BrandType;
9
+ stateFile?: string;
10
+ houseId?: number;
11
+ }
12
+ export interface AuthState {
13
+ deviceUuid: string;
14
+ apiKey?: string;
15
+ mobileId?: string;
16
+ loginAttempts: number;
17
+ lastLoginAttempt?: number;
18
+ sessionExpiry?: number;
19
+ }
20
+ export declare class AuthManager {
21
+ private readonly config;
22
+ private readonly httpClient;
23
+ private readonly stateFilePath;
24
+ private authState;
25
+ constructor(httpClient: HttpClient, config: AuthConfig);
26
+ initialize(): Promise<void>;
27
+ authenticate(): Promise<AuthTokens>;
28
+ isSessionValid(): boolean;
29
+ refreshSession(): Promise<void>;
30
+ getApiKey(): string | null;
31
+ getMobileId(): string | null;
32
+ getDeviceUuid(): string;
33
+ needsAuthentication(): boolean;
34
+ logout(): Promise<void>;
35
+ reset(): Promise<void>;
36
+ getSessionInfo(): Promise<{
37
+ houseId: number;
38
+ houseName: string;
39
+ }>;
40
+ private validateConfig;
41
+ private getStateFilePath;
42
+ private loadState;
43
+ private saveState;
44
+ private generateNewDeviceUuid;
45
+ private checkRateLimit;
46
+ private performLogin;
47
+ private handleLoginFailure;
48
+ handleSessionExpired(): void;
49
+ }
50
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/client/auth.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAgC,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAgD,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAUjD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,SAAS,CAAY;gBAEjB,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU;IAazC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,YAAY,IAAI,OAAO,CAAC,UAAU,CAAC;IA6CzC,cAAc,IAAI,OAAO;IAYnB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBrC,SAAS,IAAI,MAAM,GAAG,IAAI;IAO1B,WAAW,IAAI,MAAM,GAAG,IAAI;IAO5B,aAAa,IAAI,MAAM;IAOvB,mBAAmB,IAAI,OAAO;IAOxB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAYvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAatB,cAAc,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IA8C9E,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,gBAAgB;YAaV,SAAS;YA4BT,SAAS;YAiBT,qBAAqB;IAQnC,OAAO,CAAC,cAAc;YA8BR,YAAY;IAuB1B,OAAO,CAAC,kBAAkB;IAQnB,oBAAoB,IAAI,IAAI;CAMpC"}
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuthManager = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const uuid_1 = require("uuid");
7
+ const constants_1 = require("../types/constants");
8
+ const errors_1 = require("../utils/errors");
9
+ class AuthManager {
10
+ constructor(httpClient, config) {
11
+ this.httpClient = httpClient;
12
+ this.config = this.validateConfig(config);
13
+ this.stateFilePath = this.getStateFilePath();
14
+ this.authState = {
15
+ deviceUuid: (0, uuid_1.v4)(),
16
+ loginAttempts: 0
17
+ };
18
+ }
19
+ async initialize() {
20
+ try {
21
+ await this.loadState();
22
+ }
23
+ catch (error) {
24
+ console.warn('Failed to load auth state, starting fresh:', error);
25
+ await this.generateNewDeviceUuid();
26
+ }
27
+ }
28
+ async authenticate() {
29
+ this.checkRateLimit();
30
+ try {
31
+ const response = await this.performLogin();
32
+ if (response.success && response.api_key && response.mobile_id) {
33
+ this.authState.apiKey = response.api_key;
34
+ this.authState.mobileId = response.mobile_id;
35
+ this.authState.loginAttempts = 0;
36
+ this.authState.lastLoginAttempt = Date.now();
37
+ this.authState.sessionExpiry = Date.now() + (24 * 60 * 60 * 1000);
38
+ this.httpClient.setAuthHeaders(response.api_key, response.mobile_id, this.config.brand);
39
+ await this.saveState();
40
+ return {
41
+ apiKey: response.api_key,
42
+ mobileId: response.mobile_id,
43
+ success: true
44
+ };
45
+ }
46
+ else {
47
+ this.handleLoginFailure();
48
+ throw new errors_1.AuthenticationError('Login failed: Invalid credentials');
49
+ }
50
+ }
51
+ catch (error) {
52
+ this.handleLoginFailure();
53
+ if (error instanceof errors_1.AuthenticationError) {
54
+ throw error;
55
+ }
56
+ const nexiaError = errors_1.ErrorHandler.handle(error);
57
+ throw new errors_1.AuthenticationError(`Login failed: ${nexiaError.message}`);
58
+ }
59
+ }
60
+ isSessionValid() {
61
+ return !!(this.authState.apiKey &&
62
+ this.authState.mobileId &&
63
+ this.authState.sessionExpiry &&
64
+ this.authState.sessionExpiry > Date.now());
65
+ }
66
+ async refreshSession() {
67
+ this.authState.apiKey = undefined;
68
+ this.authState.mobileId = undefined;
69
+ this.authState.sessionExpiry = undefined;
70
+ this.httpClient.clearAuthHeaders();
71
+ await this.authenticate();
72
+ }
73
+ getApiKey() {
74
+ return this.authState.apiKey || null;
75
+ }
76
+ getMobileId() {
77
+ return this.authState.mobileId || null;
78
+ }
79
+ getDeviceUuid() {
80
+ return this.authState.deviceUuid;
81
+ }
82
+ needsAuthentication() {
83
+ return !this.isSessionValid();
84
+ }
85
+ async logout() {
86
+ this.authState.apiKey = undefined;
87
+ this.authState.mobileId = undefined;
88
+ this.authState.sessionExpiry = undefined;
89
+ this.httpClient.clearAuthHeaders();
90
+ await this.saveState();
91
+ }
92
+ async reset() {
93
+ this.authState = {
94
+ deviceUuid: (0, uuid_1.v4)(),
95
+ loginAttempts: 0
96
+ };
97
+ this.httpClient.clearAuthHeaders();
98
+ await this.saveState();
99
+ }
100
+ async getSessionInfo() {
101
+ if (!this.isSessionValid()) {
102
+ await this.authenticate();
103
+ }
104
+ try {
105
+ const response = await this.httpClient.post(constants_1.API_ENDPOINTS.SESSION, {});
106
+ if (response.data.success && response.data.result?.homes) {
107
+ const homes = response.data.result.homes;
108
+ if (homes.length === 0) {
109
+ throw new errors_1.AuthenticationError('No homes found in account');
110
+ }
111
+ const targetHouse = this.config.houseId
112
+ ? homes.find(h => h.house_id === this.config.houseId)
113
+ : homes[0];
114
+ if (!targetHouse) {
115
+ throw new errors_1.AuthenticationError(`House ID ${this.config.houseId} not found. Available houses: ${homes.map(h => h.house_id).join(', ')}`);
116
+ }
117
+ return {
118
+ houseId: targetHouse.house_id,
119
+ houseName: targetHouse.name
120
+ };
121
+ }
122
+ else {
123
+ throw new errors_1.AuthenticationError('Failed to retrieve session information');
124
+ }
125
+ }
126
+ catch (error) {
127
+ if (error instanceof errors_1.AuthenticationError) {
128
+ throw error;
129
+ }
130
+ const nexiaError = errors_1.ErrorHandler.handle(error);
131
+ throw new errors_1.AuthenticationError(`Session discovery failed: ${nexiaError.message}`);
132
+ }
133
+ }
134
+ validateConfig(config) {
135
+ if (!config.username || typeof config.username !== 'string') {
136
+ throw new errors_1.ConfigurationError('Username is required');
137
+ }
138
+ if (!config.password || typeof config.password !== 'string') {
139
+ throw new errors_1.ConfigurationError('Password is required');
140
+ }
141
+ if (!Object.values(constants_1.BrandType).includes(config.brand)) {
142
+ throw new errors_1.ConfigurationError(`Invalid brand: ${config.brand}. Must be one of: ${Object.values(constants_1.BrandType).join(', ')}`);
143
+ }
144
+ return {
145
+ ...config,
146
+ deviceName: config.deviceName || constants_1.API_CONSTANTS.DEFAULT_DEVICE_NAME
147
+ };
148
+ }
149
+ getStateFilePath() {
150
+ if (this.config.stateFile) {
151
+ return this.config.stateFile;
152
+ }
153
+ const homeDir = process.env['HOME'] || process.env['USERPROFILE'] || process.cwd();
154
+ return (0, path_1.join)(homeDir, '.nexia', 'auth-state.json');
155
+ }
156
+ async loadState() {
157
+ try {
158
+ const stateData = await fs_1.promises.readFile(this.stateFilePath, 'utf8');
159
+ const state = JSON.parse(stateData);
160
+ if (state.deviceUuid && typeof state.deviceUuid === 'string') {
161
+ this.authState = {
162
+ ...this.authState,
163
+ ...state
164
+ };
165
+ if (this.isSessionValid() && state.apiKey && state.mobileId) {
166
+ this.httpClient.setAuthHeaders(state.apiKey, state.mobileId, this.config.brand);
167
+ }
168
+ }
169
+ else {
170
+ throw new Error('Invalid state file format');
171
+ }
172
+ }
173
+ catch {
174
+ await this.generateNewDeviceUuid();
175
+ }
176
+ }
177
+ async saveState() {
178
+ try {
179
+ await fs_1.promises.mkdir((0, path_1.dirname)(this.stateFilePath), { recursive: true });
180
+ const stateData = JSON.stringify(this.authState, null, 2);
181
+ await fs_1.promises.writeFile(this.stateFilePath, stateData, 'utf8');
182
+ }
183
+ catch (error) {
184
+ console.warn('Failed to save auth state:', error);
185
+ }
186
+ }
187
+ async generateNewDeviceUuid() {
188
+ this.authState.deviceUuid = (0, uuid_1.v4)();
189
+ await this.saveState();
190
+ }
191
+ checkRateLimit() {
192
+ const now = Date.now();
193
+ const lastAttempt = this.authState.lastLoginAttempt || 0;
194
+ const timeSinceLastAttempt = now - lastAttempt;
195
+ if (timeSinceLastAttempt > 60 * 60 * 1000) {
196
+ this.authState.loginAttempts = 0;
197
+ }
198
+ if (this.authState.loginAttempts >= constants_1.API_CONSTANTS.MAX_LOGIN_ATTEMPTS) {
199
+ const waitTime = 60 * 60 * 1000;
200
+ const remainingWait = waitTime - timeSinceLastAttempt;
201
+ if (remainingWait > 0) {
202
+ throw new errors_1.RateLimitError(`Too many login attempts. Try again in ${Math.ceil(remainingWait / 60000)} minutes.`, Math.ceil(remainingWait / 1000));
203
+ }
204
+ else {
205
+ this.authState.loginAttempts = 0;
206
+ }
207
+ }
208
+ }
209
+ async performLogin() {
210
+ const loginData = {
211
+ login: this.config.username,
212
+ password: this.config.password,
213
+ device_uuid: this.authState.deviceUuid,
214
+ device_name: this.config.deviceName,
215
+ app_version: constants_1.API_CONSTANTS.APP_VERSION,
216
+ is_commercial: false
217
+ };
218
+ const response = await this.httpClient.post(constants_1.API_ENDPOINTS.SIGN_IN, loginData);
219
+ if (response.status === 302) {
220
+ throw new errors_1.AuthenticationError('Invalid credentials');
221
+ }
222
+ return response.data;
223
+ }
224
+ handleLoginFailure() {
225
+ this.authState.loginAttempts = (this.authState.loginAttempts || 0) + 1;
226
+ this.authState.lastLoginAttempt = Date.now();
227
+ }
228
+ handleSessionExpired() {
229
+ this.authState.apiKey = undefined;
230
+ this.authState.mobileId = undefined;
231
+ this.authState.sessionExpiry = undefined;
232
+ this.httpClient.clearAuthHeaders();
233
+ }
234
+ }
235
+ exports.AuthManager = AuthManager;
236
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/client/auth.ts"],"names":[],"mappings":";;;AAKA,2BAAoC;AACpC,+BAAqC;AACrC,+BAAoC;AACpC,kDAA6E;AAG7E,4CAOyB;AAoBzB,MAAa,WAAW;IAMtB,YAAY,UAAsB,EAAE,MAAkB;QACpD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC7C,IAAI,CAAC,SAAS,GAAG;YACf,UAAU,EAAE,IAAA,SAAM,GAAE;YACpB,aAAa,EAAE,CAAC;SACjB,CAAC;IACJ,CAAC;IAKM,KAAK,CAAC,UAAU;QACrB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,OAAO,CAAC,IAAI,CAAC,4CAA4C,EAAE,KAAK,CAAC,CAAC;YAClE,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACrC,CAAC;IACH,CAAC;IAKM,KAAK,CAAC,YAAY;QAEvB,IAAI,CAAC,cAAc,EAAE,CAAC;QAEtB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;YAE3C,IAAI,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBAE/D,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC;gBACzC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC;gBAC7C,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC;gBACjC,IAAI,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC7C,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;gBAGlE,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAGxF,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;gBAEvB,OAAO;oBACL,MAAM,EAAE,QAAQ,CAAC,OAAO;oBACxB,QAAQ,EAAE,QAAQ,CAAC,SAAS;oBAC5B,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC1B,MAAM,IAAI,4BAAmB,CAAC,mCAAmC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAE1B,IAAI,KAAK,YAAY,4BAAmB,EAAE,CAAC;gBACzC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,UAAU,GAAG,qBAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,IAAI,4BAAmB,CAAC,iBAAiB,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAKM,cAAc;QACnB,OAAO,CAAC,CAAC,CACP,IAAI,CAAC,SAAS,CAAC,MAAM;YACrB,IAAI,CAAC,SAAS,CAAC,QAAQ;YACvB,IAAI,CAAC,SAAS,CAAC,aAAa;YAC5B,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAC1C,CAAC;IACJ,CAAC;IAKM,KAAK,CAAC,cAAc;QAEzB,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC;QAGzC,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC;QAGnC,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;IAC5B,CAAC;IAKM,SAAS;QACd,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC;IACvC,CAAC;IAKM,WAAW;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,IAAI,IAAI,CAAC;IACzC,CAAC;IAKM,aAAa;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;IACnC,CAAC;IAKM,mBAAmB;QACxB,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;IAChC,CAAC;IAKM,KAAK,CAAC,MAAM;QACjB,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC;QAEzC,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC;QACnC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC;IAKM,KAAK,CAAC,KAAK;QAChB,IAAI,CAAC,SAAS,GAAG;YACf,UAAU,EAAE,IAAA,SAAM,GAAE;YACpB,aAAa,EAAE,CAAC;SACjB,CAAC;QAEF,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC;QACnC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC;IAKM,KAAK,CAAC,cAAc;QACzB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAkB,yBAAa,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAExF,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;gBACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;gBAEzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,MAAM,IAAI,4BAAmB,CAAC,2BAA2B,CAAC,CAAC;gBAC7D,CAAC;gBAGD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO;oBACrC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;oBACrD,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAEb,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,MAAM,IAAI,4BAAmB,CAC3B,YAAY,IAAI,CAAC,MAAM,CAAC,OAAO,iCAAiC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxG,CAAC;gBACJ,CAAC;gBAED,OAAO;oBACL,OAAO,EAAE,WAAW,CAAC,QAAQ;oBAC7B,SAAS,EAAE,WAAW,CAAC,IAAI;iBAC5B,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,4BAAmB,CAAC,wCAAwC,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,4BAAmB,EAAE,CAAC;gBACzC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,MAAM,UAAU,GAAG,qBAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,IAAI,4BAAmB,CAAC,6BAA6B,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAKO,cAAc,CAAC,MAAkB;QACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC5D,MAAM,IAAI,2BAAkB,CAAC,sBAAsB,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAC5D,MAAM,IAAI,2BAAkB,CAAC,sBAAsB,CAAC,CAAC;QACvD,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAS,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,2BAAkB,CAAC,kBAAkB,MAAM,CAAC,KAAK,qBAAqB,MAAM,CAAC,MAAM,CAAC,qBAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzH,CAAC;QAED,OAAO;YACL,GAAG,MAAM;YACT,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,yBAAa,CAAC,mBAAmB;SACnE,CAAC;IACJ,CAAC;IAKO,gBAAgB;QACtB,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAC/B,CAAC;QAGD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACnF,OAAO,IAAA,WAAI,EAAC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IACpD,CAAC;IAKO,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,aAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YAChE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAc,CAAC;YAGjD,IAAI,KAAK,CAAC,UAAU,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;gBAC7D,IAAI,CAAC,SAAS,GAAG;oBACf,GAAG,IAAI,CAAC,SAAS;oBACjB,GAAG,KAAK;iBACT,CAAC;gBAGF,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;oBAC5D,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAClF,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YAEP,MAAM,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACrC,CAAC;IACH,CAAC;IAKO,KAAK,CAAC,SAAS;QACrB,IAAI,CAAC;YAEH,MAAM,aAAE,CAAC,KAAK,CAAC,IAAA,cAAO,EAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAGjE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,aAAE,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC;QAEpD,CAAC;IACH,CAAC;IAKO,KAAK,CAAC,qBAAqB;QACjC,IAAI,CAAC,SAAS,CAAC,UAAU,GAAG,IAAA,SAAM,GAAE,CAAC;QACrC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;IACzB,CAAC;IAKO,cAAc;QACpB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,gBAAgB,IAAI,CAAC,CAAC;QACzD,MAAM,oBAAoB,GAAG,GAAG,GAAG,WAAW,CAAC;QAG/C,IAAI,oBAAoB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;YAC1C,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC;QACnC,CAAC;QAGD,IAAI,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,yBAAa,CAAC,kBAAkB,EAAE,CAAC;YACrE,MAAM,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;YAChC,MAAM,aAAa,GAAG,QAAQ,GAAG,oBAAoB,CAAC;YAEtD,IAAI,aAAa,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,uBAAc,CACtB,yCAAyC,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,WAAW,EACpF,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,CAChC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBAEN,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAKO,KAAK,CAAC,YAAY;QACxB,MAAM,SAAS,GAAiB;YAC9B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC3B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU;YACtC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,UAAW;YACpC,WAAW,EAAE,yBAAa,CAAC,WAAW;YACtC,aAAa,EAAE,KAAK;SACrB,CAAC;QAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAgB,yBAAa,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAG7F,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,4BAAmB,CAAC,qBAAqB,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAKO,kBAAkB;QACxB,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACvE,IAAI,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/C,CAAC;IAKM,oBAAoB;QACzB,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC;QACzC,IAAI,CAAC,UAAU,CAAC,gBAAgB,EAAE,CAAC;IACrC,CAAC;CACF;AAvWD,kCAuWC"}
@@ -0,0 +1,48 @@
1
+ import { BrandType } from '../types/constants';
2
+ import { NexiaClientConfig, UpdateOptions } from '../types/api';
3
+ import { INexiaClient, INexiaThermostat, INexiaAutomation } from '../types/interfaces';
4
+ export declare class NexiaClient implements INexiaClient {
5
+ private readonly httpClient;
6
+ private readonly authManager;
7
+ private readonly config;
8
+ private _houseId?;
9
+ private _houseName?;
10
+ private thermostats;
11
+ private automations;
12
+ private _lastUpdate;
13
+ private isInitialized;
14
+ constructor(config: NexiaClientConfig);
15
+ initialize(): Promise<void>;
16
+ login(): Promise<void>;
17
+ logout(): Promise<void>;
18
+ isAuthenticated(): boolean;
19
+ getThermostats(): Promise<INexiaThermostat[]>;
20
+ getAutomations(): Promise<INexiaAutomation[]>;
21
+ getThermostatById(id: string): INexiaThermostat | undefined;
22
+ getAutomationById(id: string): INexiaAutomation | undefined;
23
+ update(options?: UpdateOptions): Promise<void>;
24
+ get<T>(url: string, headers?: Record<string, string>): Promise<T>;
25
+ post<T>(url: string, data: unknown, headers?: Record<string, string>): Promise<T>;
26
+ put<T>(url: string, data: unknown, headers?: Record<string, string>): Promise<T>;
27
+ get brand(): BrandType;
28
+ get username(): string;
29
+ getHouseId(): number | undefined;
30
+ get lastUpdate(): Date | null;
31
+ getThermostatIds(): string[];
32
+ getAutomationIds(): string[];
33
+ clearCache(): void;
34
+ private validateConfig;
35
+ private ensureAuthenticated;
36
+ private processHouseData;
37
+ private processThermostat;
38
+ private processAutomation;
39
+ private clearDeviceCache;
40
+ private isSessionExpiredError;
41
+ private handleSessionExpiry;
42
+ delayedUpdate(delayMs?: number): Promise<void>;
43
+ getBaseUrl(): string;
44
+ getMobileUrl(): string;
45
+ getUpdateUrl(): string | null;
46
+ getHouseName(): string | undefined;
47
+ }
48
+ //# sourceMappingURL=nexia-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nexia-client.d.ts","sourceRoot":"","sources":["../../src/client/nexia-client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAA0C,MAAM,oBAAoB,CAAC;AACvF,OAAO,EAIL,iBAAiB,EACjB,aAAa,EACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAavF,qBAAa,WAAY,YAAW,YAAY;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAE3C,OAAO,CAAC,QAAQ,CAAC,CAAS;IAE1B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,WAAW,CAA4C;IAC/D,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,aAAa,CAAkB;gBAE3B,MAAM,EAAE,iBAAiB;IA8BxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAkB3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBtB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B,eAAe,IAAI,OAAO;IAOpB,cAAc,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAQ7C,cAAc,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAQnD,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAO3D,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS;IAOrD,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmClD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoBjE,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoBjF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAkB7F,IAAW,KAAK,IAAI,SAAS,CAE5B;IAED,IAAW,QAAQ,IAAI,MAAM,CAE5B;IAEM,UAAU,IAAI,MAAM,GAAG,SAAS;IAIvC,IAAW,UAAU,IAAI,IAAI,GAAG,IAAI,CAEnC;IAKM,gBAAgB,IAAI,MAAM,EAAE;IAO5B,gBAAgB,IAAI,MAAM,EAAE;IAO5B,UAAU,IAAI,IAAI;IAOzB,OAAO,CAAC,cAAc;YAwBR,mBAAmB;YAanB,gBAAgB;YAqDhB,iBAAiB;YAiBjB,iBAAiB;IAiB/B,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,qBAAqB;YAWf,mBAAmB;IAqBpB,aAAa,CAAC,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB1D,UAAU,IAAI,MAAM;IAOpB,YAAY,IAAI,MAAM;IAOtB,YAAY,IAAI,MAAM,GAAG,IAAI;IAO7B,YAAY,IAAI,MAAM,GAAG,SAAS;CAG1C"}