homebridge-carrier-infinity 1.8.1 → 1.9.0-beta.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 (73) hide show
  1. package/.devcontainer/.uix-hb-service-homebridge-startup.json.example +5 -0
  2. package/.devcontainer/config.json.example +2 -1
  3. package/.devcontainer/setup-homebridge.sh +6 -0
  4. package/CLAUDE.md +28 -21
  5. package/dist/accessory_base.d.ts +2 -2
  6. package/dist/accessory_base.d.ts.map +1 -1
  7. package/dist/accessory_base.js.map +1 -1
  8. package/dist/api/graphql_client.d.ts +71 -0
  9. package/dist/api/graphql_client.d.ts.map +1 -0
  10. package/dist/api/graphql_client.js +261 -0
  11. package/dist/api/graphql_client.js.map +1 -0
  12. package/dist/api/graphql_operations.d.ts +56 -0
  13. package/dist/api/graphql_operations.d.ts.map +1 -0
  14. package/dist/api/graphql_operations.js +325 -0
  15. package/dist/api/graphql_operations.js.map +1 -0
  16. package/dist/api/interface_graphql_mutations.d.ts +149 -0
  17. package/dist/api/interface_graphql_mutations.d.ts.map +1 -0
  18. package/dist/api/interface_graphql_mutations.js +8 -0
  19. package/dist/api/interface_graphql_mutations.js.map +1 -0
  20. package/dist/api/interface_graphql_system.d.ts +287 -0
  21. package/dist/api/interface_graphql_system.d.ts.map +1 -0
  22. package/dist/api/interface_graphql_system.js +9 -0
  23. package/dist/api/interface_graphql_system.js.map +1 -0
  24. package/dist/api/models_graphql.d.ts +167 -0
  25. package/dist/api/models_graphql.d.ts.map +1 -0
  26. package/dist/api/models_graphql.js +590 -0
  27. package/dist/api/models_graphql.js.map +1 -0
  28. package/dist/api/oauth2.d.ts +45 -0
  29. package/dist/api/oauth2.d.ts.map +1 -0
  30. package/dist/api/oauth2.js +35 -0
  31. package/dist/api/oauth2.js.map +1 -0
  32. package/dist/characteristics_base.d.ts +2 -2
  33. package/dist/characteristics_base.d.ts.map +1 -1
  34. package/dist/characteristics_base.js.map +1 -1
  35. package/dist/platform.d.ts +4 -4
  36. package/dist/platform.d.ts.map +1 -1
  37. package/dist/platform.js +7 -12
  38. package/dist/platform.js.map +1 -1
  39. package/dist/settings.d.ts +6 -3
  40. package/dist/settings.d.ts.map +1 -1
  41. package/dist/settings.js +7 -4
  42. package/dist/settings.js.map +1 -1
  43. package/eslint.config.mjs +93 -2
  44. package/package.json +3 -6
  45. package/dist/api/comodo-aaa-root.pem +0 -25
  46. package/dist/api/interface_config.d.ts +0 -185
  47. package/dist/api/interface_config.d.ts.map +0 -1
  48. package/dist/api/interface_config.js +0 -5
  49. package/dist/api/interface_config.js.map +0 -1
  50. package/dist/api/interface_locations.d.ts +0 -45
  51. package/dist/api/interface_locations.d.ts.map +0 -1
  52. package/dist/api/interface_locations.js +0 -5
  53. package/dist/api/interface_locations.js.map +0 -1
  54. package/dist/api/interface_profile.d.ts +0 -80
  55. package/dist/api/interface_profile.d.ts.map +0 -1
  56. package/dist/api/interface_profile.js +0 -5
  57. package/dist/api/interface_profile.js.map +0 -1
  58. package/dist/api/interface_status.d.ts +0 -90
  59. package/dist/api/interface_status.d.ts.map +0 -1
  60. package/dist/api/interface_status.js +0 -5
  61. package/dist/api/interface_status.js.map +0 -1
  62. package/dist/api/models.d.ts +0 -111
  63. package/dist/api/models.d.ts.map +0 -1
  64. package/dist/api/models.js +0 -572
  65. package/dist/api/models.js.map +0 -1
  66. package/dist/api/oauth.d.ts +0 -6
  67. package/dist/api/oauth.d.ts.map +0 -1
  68. package/dist/api/oauth.js +0 -49
  69. package/dist/api/oauth.js.map +0 -1
  70. package/dist/api/rest_client.d.ts +0 -15
  71. package/dist/api/rest_client.d.ts.map +0 -1
  72. package/dist/api/rest_client.js +0 -135
  73. package/dist/api/rest_client.js.map +0 -1
@@ -0,0 +1,5 @@
1
+ {
2
+ "debugMode": true,
3
+ "insecureMode": true,
4
+ "env": {}
5
+ }
@@ -10,7 +10,8 @@
10
10
  {
11
11
  "name": "Config",
12
12
  "port": 8581,
13
- "platform": "config"
13
+ "platform": "config",
14
+ "tempUnits": "f"
14
15
  },
15
16
  {
16
17
  "platform": "CarrierInfinity",
@@ -17,6 +17,12 @@ if [ ! -f ~/.homebridge/config.json ]; then
17
17
  cp .devcontainer/config.json.example ~/.homebridge/config.json
18
18
  fi
19
19
 
20
+ # Create debug mode config if it doesn't exist
21
+ if [ ! -f ~/.homebridge/.uix-hb-service-homebridge-startup.json ]; then
22
+ echo "Creating Homebridge service config from example..."
23
+ cp .devcontainer/.uix-hb-service-homebridge-startup.json.example ~/.homebridge/.uix-hb-service-homebridge-startup.json
24
+ fi
25
+
20
26
  # Install project dependencies
21
27
  echo "Installing project dependencies..."
22
28
  npm install
package/CLAUDE.md CHANGED
@@ -37,7 +37,8 @@ This repository includes a complete devcontainer configuration that automaticall
37
37
  When the codespace is created, the setup script (`.devcontainer/setup-homebridge.sh`) automatically:
38
38
  - Installs Homebridge, Homebridge Config UI X, and pm2 globally
39
39
  - Creates `~/.homebridge/` directory structure
40
- - Copies `.devcontainer/config.json.example` to `~/.homebridge/config.json`
40
+ - Copies `.devcontainer/config.json.example` to `~/.homebridge/config.json` (Fahrenheit display)
41
+ - Copies `.devcontainer/.uix-hb-service-homebridge-startup.json.example` (debug mode enabled)
41
42
  - Installs project dependencies
42
43
  - Builds the plugin
43
44
  - Symlinks the plugin to `~/.homebridge/node_modules/`
@@ -75,29 +76,33 @@ The plugin registers itself in [src/index.ts](src/index.ts) and implements the H
75
76
 
76
77
  #### 1. Platform ([src/platform.ts](src/platform.ts))
77
78
  - Entry point that discovers systems and zones after Homebridge launches
78
- - Maintains `infinity_client` (REST API client) and `systems` (indexed by serial number)
79
- - Periodically activates the API every 30 minutes to maintain connection
79
+ - Maintains `infinity_client` (GraphQL API client) and `systems` (indexed by serial number)
80
80
  - Creates accessories based on config options (outdoor temp sensor, humidity sensors, etc.)
81
81
 
82
82
  #### 2. API Layer ([src/api/](src/api/))
83
- - **InfinityRestClient** ([src/api/rest_client.ts](src/api/rest_client.ts)): OAuth-authenticated Axios client
84
- - Handles authentication with username/password
85
- - Automatic OAuth header injection via interceptor
86
- - Token refresh with 24hr memoization
87
- - Activation endpoint called every minute (with memoization)
88
-
89
- - **Models** ([src/api/models.ts](src/api/models.ts)): BaseModel and specific models (LocationsModel, SystemModel, etc.)
83
+ - **InfinityGraphQLClient** ([src/api/graphql_client.ts](src/api/graphql_client.ts)): OAuth 2.0 authenticated GraphQL client
84
+ - Handles authentication via Okta with username/password
85
+ - Automatic Bearer token injection via interceptor
86
+ - Token refresh with 24hr memoization (via Okta or assistedLogin mutation)
87
+ - No activation endpoint needed (simplified from old REST API)
88
+
89
+ - **GraphQL Operations** ([src/api/graphql_operations.ts](src/api/graphql_operations.ts)): GraphQL queries and mutations
90
+ - `GET_INFINITY_SYSTEMS`: Single query fetches profile, status, and config together (replaces 3 REST calls)
91
+ - `UPDATE_INFINITY_CONFIG`: System-level configuration mutations
92
+ - `UPDATE_INFINITY_ZONE_ACTIVITY`: Zone activity and setpoint mutations
93
+ - `UPDATE_INFINITY_ZONE_CONFIG`: Zone hold and schedule mutations
94
+
95
+ - **Models** ([src/api/models_graphql.ts](src/api/models_graphql.ts)): GraphQL-based models with facade pattern
96
+ - `UnifiedSystemModel` fetches all data (profile + status + config) via single GraphQL query
97
+ - `SystemProfileModel`, `SystemStatusModel`, `SystemConfigModel` are facades that maintain backward compatibility
90
98
  - `BaseModel` provides fetch/push pattern with mutex locking to prevent race conditions
91
99
  - Hash-based change detection (only pushes if data actually changed)
92
100
  - 10-second memoization on fetch operations
93
- - XML parsing via xml2js
94
- - Models include: `LocationsModel`, `SystemModel` with nested `ConfigModel`, `ProfileModel`, `StatusModel`
101
+ - JSON parsing (native JavaScript objects)
95
102
 
96
- - **Interface Files**: TypeScript interfaces auto-generated from XML samples in `testdata/` using the `xml2ts` script
97
- - [src/api/interface_config.ts](src/api/interface_config.ts)
98
- - [src/api/interface_profile.ts](src/api/interface_profile.ts)
99
- - [src/api/interface_status.ts](src/api/interface_status.ts)
100
- - [src/api/interface_locations.ts](src/api/interface_locations.ts)
103
+ - **Interface Files**: TypeScript interfaces for GraphQL API responses
104
+ - [src/api/interface_graphql_system.ts](src/api/interface_graphql_system.ts): System, profile, status, and config types
105
+ - [src/api/interface_graphql_mutations.ts](src/api/interface_graphql_mutations.ts): Mutation input and response types
101
106
 
102
107
  #### 3. Accessories ([src/accessory_*.ts](src/))
103
108
  All accessories extend `BaseAccessory` ([src/accessory_base.ts](src/accessory_base.ts)):
@@ -127,7 +132,7 @@ The plugin uses a wrapper pattern to bind HomeKit characteristics to API data:
127
132
  ### Key Patterns
128
133
 
129
134
  #### OAuth Authentication
130
- The API uses OAuth 1.0 with custom headers. See [src/api/oauth.ts](src/api/oauth.ts) for signature generation and [src/settings.ts](src/settings.ts) for consumer key/secret.
135
+ The API uses OAuth 2.0 via Okta with Bearer tokens. See [src/api/oauth2.ts](src/api/oauth2.ts) for token injection and [src/settings.ts](src/settings.ts) for OAuth endpoints and client ID. Authentication is handled via the `assistedLogin` GraphQL mutation or Okta token refresh endpoint.
131
136
 
132
137
  #### Memoization & Retry Decorators
133
138
  - `@MemoizeExpiring(milliseconds)`: Caches method results for specified duration
@@ -143,10 +148,12 @@ await tryAcquire(this.write_lock).runExclusive(async () => {
143
148
  ```
144
149
 
145
150
  #### Data Flow
146
- 1. **Read**: Characteristic getter → Model.fetch() → API GETXML parse → return value
147
- 2. **Write**: Characteristic setter → batch changes → Model.push() → XML buildAPI PUT
151
+ 1. **Read**: Characteristic getter → Model.fetch() → GraphQL queryJSON parse → return value
152
+ 2. **Write**: Characteristic setter → batch changes → Model.push() → GraphQL mutationJSON input
148
153
  3. **Updates**: Periodic polling + hash comparison triggers characteristic updates via subscription pattern
149
154
 
155
+ **Note**: The GraphQL API combines profile, status, and config data in a single query, reducing network overhead by 66% compared to the old REST API (1 query vs 3 separate calls).
156
+
150
157
  #### Hold Behavior
151
158
  The plugin supports multiple thermostat hold modes (forever, until next activity, for X hours, until time X) configured via `holdBehavior` and `holdArgument` in config.
152
159
 
@@ -173,7 +180,7 @@ The plugin supports multiple thermostat hold modes (forever, until next activity
173
180
 
174
181
  ## Important Notes
175
182
 
176
- - The API expects `activate()` calls regularly (~1 min), though more frequent doesn't help
177
183
  - Changes from HomeKit can take 1-2 minutes to reach the physical thermostat due to polling architecture
178
184
  - Node version requirement: >= 18
179
185
  - Homebridge version: >= 1.2 or ^2.0.0-beta.0
186
+ - The plugin uses the new GraphQL API (OAuth 2.0, JSON) which replaced the old REST API (OAuth 1.0, XML)
@@ -1,11 +1,11 @@
1
1
  import { Logger, PlatformAccessory, Service, WithUUID } from 'homebridge';
2
- import { SystemModel } from './api/models';
2
+ import { SystemModelGraphQL } from './api/models_graphql';
3
3
  import { CarrierInfinityHomebridgePlatform } from './platform';
4
4
  export declare abstract class BaseAccessory {
5
5
  protected readonly platform: CarrierInfinityHomebridgePlatform;
6
6
  protected readonly context: Record<string, string>;
7
7
  readonly accessory: PlatformAccessory;
8
- protected readonly system: SystemModel;
8
+ protected readonly system: SystemModelGraphQL;
9
9
  protected readonly log: Logger;
10
10
  constructor(platform: CarrierInfinityHomebridgePlatform, context: Record<string, string>);
11
11
  protected abstract ID(context: Record<string, string>): string;
@@ -1 +1 @@
1
- {"version":3,"file":"accessory_base.d.ts","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,iCAAiC,EAAE,MAAM,YAAY,CAAC;AAG/D,8BAAsB,aAAa;IAM/B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,iCAAiC;IAC9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IANpD,SAAgB,SAAS,EAAE,iBAAiB,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAoD;IAC1F,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAwD;gBAGjE,QAAQ,EAAE,iCAAiC,EAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkBpD,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM;IAE9D,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;CAW9F"}
1
+ {"version":3,"file":"accessory_base.d.ts","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,iCAAiC,EAAE,MAAM,YAAY,CAAC;AAG/D,8BAAsB,aAAa;IAM/B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,iCAAiC;IAC9D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IANpD,SAAgB,SAAS,EAAE,iBAAiB,CAAC;IAC7C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAoD;IACjG,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAwD;gBAGjE,QAAQ,EAAE,iCAAiC,EAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAkBpD,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM;IAE9D,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,OAAO,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;CAW9F"}
@@ -1 +1 @@
1
- {"version":3,"file":"accessory_base.js","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":";;;AACA,qDAAgD;AAGhD,yCAAwD;AAExD,MAAsB,aAAa;IAKjC,YACqB,QAA2C,EAC3C,OAA+B;QAD/B,aAAQ,GAAR,QAAQ,CAAmC;QAC3C,YAAO,GAAP,OAAO,CAAwB;QALjC,WAAM,GAAgB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACvE,QAAG,GAAW,IAAI,6BAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAMpF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QACnE,IAAI,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,SAAS,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,2BAA2B,CAAC,sBAAW,EAAE,wBAAa,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACzC,CAAC;IAIS,UAAU,CAAC,IAA8B,EAAE,IAAY,EAAE,QAAgB;QACjF,+BAA+B;QAC/B,IAAI,OAA4B,CAAC;QACjC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,2BAA2B;QAC3B,OAAO,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpE,CAAC;CACF;AAtCD,sCAsCC"}
1
+ {"version":3,"file":"accessory_base.js","sourceRoot":"","sources":["../src/accessory_base.ts"],"names":[],"mappings":";;;AACA,qDAAgD;AAGhD,yCAAwD;AAExD,MAAsB,aAAa;IAKjC,YACqB,QAA2C,EAC3C,OAA+B;QAD/B,aAAQ,GAAR,QAAQ,CAAmC;QAC3C,YAAO,GAAP,OAAO,CAAwB;QALjC,WAAM,GAAuB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC9E,QAAG,GAAW,IAAI,6BAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAMpF,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QACnE,IAAI,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,SAAS,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACxE,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,2BAA2B,CAAC,sBAAW,EAAE,wBAAa,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,SAAS,CAAC,OAAO,GAAG,OAAO,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACzC,CAAC;IAIS,UAAU,CAAC,IAA8B,EAAE,IAAY,EAAE,QAAgB;QACjF,+BAA+B;QAC/B,IAAI,OAA4B,CAAC;QACjC,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC;QACD,2BAA2B;QAC3B,OAAO,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IACpE,CAAC;CACF;AAtCD,sCAsCC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * GraphQL Client for Carrier Infinity API
3
+ *
4
+ * This replaces the InfinityRestClient with a GraphQL-based implementation
5
+ * using OAuth 2.0 Bearer token authentication instead of OAuth 1.0 HMAC signatures.
6
+ */
7
+ import { AxiosInstance } from 'axios';
8
+ import { Logger } from 'homebridge';
9
+ /**
10
+ * GraphQL Client for Carrier Infinity API
11
+ *
12
+ * Handles OAuth 2.0 authentication and GraphQL query/mutation execution.
13
+ * Much simpler than the old REST client - no XML parsing, no OAuth signatures,
14
+ * no custom certificates, no activation endpoint.
15
+ */
16
+ export declare class InfinityGraphQLClient {
17
+ username: string;
18
+ private password;
19
+ readonly log: Logger;
20
+ private access_token;
21
+ private refresh_token;
22
+ private token_type;
23
+ private token_expires_in;
24
+ private token_acquired_at;
25
+ axios: AxiosInstance;
26
+ private axiosNoAuth;
27
+ constructor(username: string, password: string, log: Logger);
28
+ /**
29
+ * Refresh OAuth 2.0 token with memoization (24 hours)
30
+ *
31
+ * This is called before every API request to ensure we have a valid token.
32
+ * The memoization ensures we only refresh once per day unless the token expires.
33
+ */
34
+ refreshToken(): Promise<void>;
35
+ /**
36
+ * Force refresh OAuth 2.0 token with retry logic
37
+ *
38
+ * If we have a refresh token, use the Okta token endpoint.
39
+ * Otherwise, use the assistedLogin mutation to get a new token.
40
+ */
41
+ forceRefreshToken(): Promise<void>;
42
+ /**
43
+ * Refresh token via Okta OAuth2 endpoint
44
+ */
45
+ private refreshTokenViaOkta;
46
+ /**
47
+ * Login via assistedLogin GraphQL mutation
48
+ */
49
+ private loginViaAssistedLogin;
50
+ /**
51
+ * Execute a GraphQL query
52
+ *
53
+ * @param query - GraphQL query string
54
+ * @param variables - Query variables
55
+ * @returns GraphQL response data
56
+ */
57
+ query<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
58
+ /**
59
+ * Execute a GraphQL mutation
60
+ *
61
+ * @param mutation - GraphQL mutation string
62
+ * @param variables - Mutation variables
63
+ * @returns GraphQL response data
64
+ */
65
+ mutate<T>(mutation: string, variables?: Record<string, unknown>): Promise<T>;
66
+ /**
67
+ * Helper to check if GraphQL response has errors
68
+ */
69
+ private hasGraphQLErrors;
70
+ }
71
+ //# sourceMappingURL=graphql_client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql_client.d.ts","sourceRoot":"","sources":["../../src/api/graphql_client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiBH,OAAc,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAIpC;;;;;;GAMG;AACH,qBAAa,qBAAqB;IAWvB,QAAQ,EAAE,MAAM;IACvB,OAAO,CAAC,QAAQ;aACA,GAAG,EAAE,MAAM;IAZ7B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,iBAAiB,CAAK;IAEvB,KAAK,EAAE,aAAa,CAAC;IAC5B,OAAO,CAAC,WAAW,CAAgB;gBAG1B,QAAQ,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EACR,GAAG,EAAE,MAAM;IAkE7B;;;;;OAKG;IAEG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;;;;OAKG;IAOG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBxC;;OAEG;YACW,mBAAmB;IAiCjC;;OAEG;YACW,qBAAqB;IAuCnC;;;;;;OAMG;IACG,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsB9E;;;;;;OAMG;IACG,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsBlF;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAGzB"}
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ /**
3
+ * GraphQL Client for Carrier Infinity API
4
+ *
5
+ * This replaces the InfinityRestClient with a GraphQL-based implementation
6
+ * using OAuth 2.0 Bearer token authentication instead of OAuth 1.0 HMAC signatures.
7
+ */
8
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
9
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
10
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
11
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
12
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
13
+ };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.InfinityGraphQLClient = void 0;
19
+ const settings_1 = require("../settings");
20
+ const oauth2_1 = require("./oauth2");
21
+ const graphql_operations_1 = require("./graphql_operations");
22
+ const axios_1 = __importDefault(require("axios"));
23
+ const typescript_memoize_1 = require("typescript-memoize");
24
+ const typescript_retry_decorator_1 = require("typescript-retry-decorator");
25
+ /**
26
+ * GraphQL Client for Carrier Infinity API
27
+ *
28
+ * Handles OAuth 2.0 authentication and GraphQL query/mutation execution.
29
+ * Much simpler than the old REST client - no XML parsing, no OAuth signatures,
30
+ * no custom certificates, no activation endpoint.
31
+ */
32
+ class InfinityGraphQLClient {
33
+ constructor(username, password, log) {
34
+ this.username = username;
35
+ this.password = password;
36
+ this.log = log;
37
+ this.access_token = '';
38
+ this.refresh_token = '';
39
+ this.token_type = 'Bearer';
40
+ this.token_expires_in = 0;
41
+ this.token_acquired_at = 0;
42
+ // Create authenticated Axios instance (for GraphQL queries after login)
43
+ this.axios = axios_1.default.create({
44
+ baseURL: settings_1.INFINITY_GRAPHQL_ENDPOINT,
45
+ headers: {
46
+ 'Content-Type': 'application/json',
47
+ Accept: 'application/json',
48
+ },
49
+ });
50
+ // Create no-auth Axios instance (for login mutation)
51
+ this.axiosNoAuth = axios_1.default.create({
52
+ baseURL: settings_1.INFINITY_GRAPHQL_NO_AUTH_ENDPOINT,
53
+ headers: {
54
+ 'Content-Type': 'application/json',
55
+ Accept: 'application/json',
56
+ },
57
+ });
58
+ // Response interceptor for debug logging
59
+ this.axios.interceptors.response.use(response => {
60
+ var _a, _b;
61
+ this.log.debug(`[GraphQL] ${(_a = response.request) === null || _a === void 0 ? void 0 : _a.method} ${response.request.host}${(_b = response.request) === null || _b === void 0 ? void 0 : _b.path}`, `${response.status} ${response.statusText}`);
62
+ return response;
63
+ }, error => {
64
+ var _a, _b, _c, _d, _e;
65
+ if (axios_1.default.isAxiosError(error)) {
66
+ this.log.debug(`[GraphQL] ${(_a = error.request) === null || _a === void 0 ? void 0 : _a.method} ${(_b = error.request) === null || _b === void 0 ? void 0 : _b.host}${(_c = error.request) === null || _c === void 0 ? void 0 : _c.path}`, `${(_d = error.response) === null || _d === void 0 ? void 0 : _d.status} ${(_e = error.response) === null || _e === void 0 ? void 0 : _e.statusText}`);
67
+ }
68
+ return Promise.reject(error);
69
+ });
70
+ // Same for no-auth instance
71
+ this.axiosNoAuth.interceptors.response.use(response => {
72
+ var _a, _b;
73
+ this.log.debug(`[GraphQL-NoAuth] ${(_a = response.request) === null || _a === void 0 ? void 0 : _a.method} ${response.request.host}${(_b = response.request) === null || _b === void 0 ? void 0 : _b.path}`, `${response.status} ${response.statusText}`);
74
+ return response;
75
+ }, error => {
76
+ var _a, _b, _c, _d, _e;
77
+ if (axios_1.default.isAxiosError(error)) {
78
+ this.log.debug(`[GraphQL-NoAuth] ${(_a = error.request) === null || _a === void 0 ? void 0 : _a.method} ${(_b = error.request) === null || _b === void 0 ? void 0 : _b.host}${(_c = error.request) === null || _c === void 0 ? void 0 : _c.path}`, `${(_d = error.response) === null || _d === void 0 ? void 0 : _d.status} ${(_e = error.response) === null || _e === void 0 ? void 0 : _e.statusText}`);
79
+ }
80
+ return Promise.reject(error);
81
+ });
82
+ // OAuth 2.0 Bearer token injection for authenticated instance
83
+ this.axios.interceptors.request.use(config => {
84
+ return oauth2_1.OAuth2Headers.intercept(config, this.access_token, this.token_type);
85
+ });
86
+ }
87
+ /**
88
+ * Refresh OAuth 2.0 token with memoization (24 hours)
89
+ *
90
+ * This is called before every API request to ensure we have a valid token.
91
+ * The memoization ensures we only refresh once per day unless the token expires.
92
+ */
93
+ async refreshToken() {
94
+ try {
95
+ await this.forceRefreshToken();
96
+ this.log.info('Completed login / token refresh successfully.');
97
+ }
98
+ catch (error) {
99
+ this.log.error('[API] Could not refresh access token: ', axios_1.default.isAxiosError(error) ? error.message : error);
100
+ throw error;
101
+ }
102
+ }
103
+ /**
104
+ * Force refresh OAuth 2.0 token with retry logic
105
+ *
106
+ * If we have a refresh token, use the Okta token endpoint.
107
+ * Otherwise, use the assistedLogin mutation to get a new token.
108
+ */
109
+ async forceRefreshToken() {
110
+ this.log.info('Attempting login / token refresh.');
111
+ // Check if we can use refresh token
112
+ const now = Date.now() / 1000;
113
+ const tokenAge = now - this.token_acquired_at;
114
+ const tokenExpired = tokenAge >= this.token_expires_in;
115
+ if (this.refresh_token && !tokenExpired) {
116
+ // Use Okta refresh token endpoint
117
+ try {
118
+ await this.refreshTokenViaOkta();
119
+ return;
120
+ }
121
+ catch (error) {
122
+ this.log.warn('Okta token refresh failed, falling back to assistedLogin:', error);
123
+ // Fall through to assistedLogin
124
+ }
125
+ }
126
+ // Use assistedLogin mutation
127
+ await this.loginViaAssistedLogin();
128
+ }
129
+ /**
130
+ * Refresh token via Okta OAuth2 endpoint
131
+ */
132
+ async refreshTokenViaOkta() {
133
+ const response = await axios_1.default.post(settings_1.INFINITY_OAUTH_TOKEN_ENDPOINT, {
134
+ client_id: settings_1.INFINITY_OAUTH_CLIENT_ID,
135
+ grant_type: 'refresh_token',
136
+ refresh_token: this.refresh_token,
137
+ scope: 'offline_access',
138
+ }, {
139
+ headers: {
140
+ 'Content-Type': 'application/json',
141
+ },
142
+ });
143
+ if (response.data.access_token) {
144
+ this.access_token = response.data.access_token;
145
+ this.token_type = response.data.token_type;
146
+ this.token_expires_in = response.data.expires_in;
147
+ this.token_acquired_at = Date.now() / 1000;
148
+ // Okta may return a new refresh token
149
+ if (response.data.refresh_token) {
150
+ this.refresh_token = response.data.refresh_token;
151
+ }
152
+ this.log.debug('Token refreshed via Okta endpoint.');
153
+ }
154
+ else {
155
+ throw new Error('Okta token refresh did not return access_token.');
156
+ }
157
+ }
158
+ /**
159
+ * Login via assistedLogin GraphQL mutation
160
+ */
161
+ async loginViaAssistedLogin() {
162
+ var _a;
163
+ const input = {
164
+ username: this.username,
165
+ password: this.password,
166
+ };
167
+ const response = await this.axiosNoAuth.post('', {
168
+ query: graphql_operations_1.ASSISTED_LOGIN,
169
+ variables: { input },
170
+ });
171
+ // Check for GraphQL errors
172
+ if (response.data.errors && response.data.errors.length > 0) {
173
+ const errorMessages = response.data.errors.map(e => e.message).join(', ');
174
+ throw new Error(`GraphQL errors during login: ${errorMessages}`);
175
+ }
176
+ // Check for mutation-level errors
177
+ const result = (_a = response.data.data) === null || _a === void 0 ? void 0 : _a.assistedLogin;
178
+ if (!result || !result.success) {
179
+ const errorMessage = (result === null || result === void 0 ? void 0 : result.errorMessage) || 'Unknown error';
180
+ throw new Error(`assistedLogin failed: ${errorMessage}`);
181
+ }
182
+ // Extract tokens
183
+ const tokenData = result.data;
184
+ if (!tokenData.access_token) {
185
+ throw new Error('assistedLogin did not return access_token.');
186
+ }
187
+ this.access_token = tokenData.access_token;
188
+ this.refresh_token = tokenData.refresh_token;
189
+ this.token_type = tokenData.token_type;
190
+ this.token_expires_in = tokenData.expires_in;
191
+ this.token_acquired_at = Date.now() / 1000;
192
+ this.log.debug('Token acquired via assistedLogin mutation.');
193
+ }
194
+ /**
195
+ * Execute a GraphQL query
196
+ *
197
+ * @param query - GraphQL query string
198
+ * @param variables - Query variables
199
+ * @returns GraphQL response data
200
+ */
201
+ async query(query, variables) {
202
+ // Ensure we have a valid token
203
+ await this.refreshToken();
204
+ const response = await this.axios.post('', {
205
+ query,
206
+ variables,
207
+ });
208
+ // Check for GraphQL errors
209
+ if (response.data.errors && response.data.errors.length > 0) {
210
+ const errorMessages = response.data.errors.map(e => e.message).join(', ');
211
+ throw new Error(`GraphQL query errors: ${errorMessages}`);
212
+ }
213
+ if (!response.data.data) {
214
+ throw new Error('GraphQL query returned no data.');
215
+ }
216
+ return response.data.data;
217
+ }
218
+ /**
219
+ * Execute a GraphQL mutation
220
+ *
221
+ * @param mutation - GraphQL mutation string
222
+ * @param variables - Mutation variables
223
+ * @returns GraphQL response data
224
+ */
225
+ async mutate(mutation, variables) {
226
+ // Ensure we have a valid token
227
+ await this.refreshToken();
228
+ const response = await this.axios.post('', {
229
+ query: mutation,
230
+ variables,
231
+ });
232
+ // Check for GraphQL errors
233
+ if (response.data.errors && response.data.errors.length > 0) {
234
+ const errorMessages = response.data.errors.map(e => e.message).join(', ');
235
+ throw new Error(`GraphQL mutation errors: ${errorMessages}`);
236
+ }
237
+ if (!response.data.data) {
238
+ throw new Error('GraphQL mutation returned no data.');
239
+ }
240
+ return response.data.data;
241
+ }
242
+ /**
243
+ * Helper to check if GraphQL response has errors
244
+ */
245
+ hasGraphQLErrors(errors) {
246
+ return !!(errors && errors.length > 0);
247
+ }
248
+ }
249
+ exports.InfinityGraphQLClient = InfinityGraphQLClient;
250
+ __decorate([
251
+ (0, typescript_memoize_1.MemoizeExpiring)(24 * 60 * 60 * 1000) // every 24 hrs
252
+ ], InfinityGraphQLClient.prototype, "refreshToken", null);
253
+ __decorate([
254
+ (0, typescript_retry_decorator_1.Retryable)({
255
+ maxAttempts: 5,
256
+ backOffPolicy: typescript_retry_decorator_1.BackOffPolicy.ExponentialBackOffPolicy,
257
+ backOff: 1000,
258
+ exponentialOption: { maxInterval: 5 * 60 * 1000, multiplier: 5 },
259
+ })
260
+ ], InfinityGraphQLClient.prototype, "forceRefreshToken", null);
261
+ //# sourceMappingURL=graphql_client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql_client.js","sourceRoot":"","sources":["../../src/api/graphql_client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * GraphQL Operations for Carrier Infinity API
3
+ *
4
+ * This file contains all GraphQL queries and mutations used to interact with
5
+ * the Carrier Infinity GraphQL API at dataservice.infinity.iot.carrier.com
6
+ */
7
+ /**
8
+ * Authentication mutation - used to obtain OAuth tokens
9
+ * Endpoint: https://dataservice.infinity.iot.carrier.com/graphql-no-auth
10
+ * No authentication required (this IS the authentication)
11
+ */
12
+ export declare const ASSISTED_LOGIN = "\n mutation assistedLogin($input: AssistedLoginInput!) {\n assistedLogin(input: $input) {\n success\n status\n errorMessage\n data {\n token_type\n expires_in\n access_token\n scope\n refresh_token\n }\n }\n }\n";
13
+ /**
14
+ * User information query - fetches user profile and location data
15
+ * Used to discover systems associated with a user account
16
+ */
17
+ export declare const GET_USER = "\n query getUser($userName: String!, $appVersion: String, $brand: String, $os: String, $osVersion: String) {\n user(\n userName: $userName\n appVersion: $appVersion\n brand: $brand\n os: $os\n osVersion: $osVersion\n ) {\n username\n identityId\n first\n last\n email\n emailVerified\n postal\n locations {\n locationId\n name\n systems {\n config {\n zones {\n id\n enabled\n }\n }\n profile {\n serial\n name\n }\n status {\n isDisconnected\n }\n }\n devices {\n deviceId\n type\n thingName\n name\n connectionStatus\n }\n }\n }\n }\n";
18
+ /**
19
+ * Infinity Systems query - fetches complete system data (profile + status + config)
20
+ * This single query replaces the old REST API's separate profile, status, and config endpoints
21
+ */
22
+ export declare const GET_INFINITY_SYSTEMS = "\n query getInfinitySystems($userName: String!) {\n infinitySystems(userName: $userName) {\n profile {\n serial\n name\n firmware\n model\n brand\n indoorModel\n indoorSerial\n idutype\n idusource\n outdoorModel\n outdoorSerial\n odutype\n }\n status {\n localTime\n localTimeOffset\n utcTime\n wcTime\n isDisconnected\n cfgem\n mode\n vacatrunning\n oat\n odu {\n type\n opstat\n }\n filtrlvl\n idu {\n type\n opstat\n cfm\n statpress\n blwrpm\n }\n vent\n ventlvl\n humid\n humlvl\n uvlvl\n zones {\n id\n rt\n rh\n fan\n htsp\n clsp\n hold\n enabled\n currentActivity\n zoneconditioning\n }\n }\n config {\n etag\n mode\n cfgem\n cfgdead\n cfgvent\n cfghumid\n cfguv\n cfgfan\n heatsource\n vacat\n vacstart\n vacend\n vacmint\n vacmaxt\n vacfan\n fueltype\n gasunit\n filtertype\n filterinterval\n humidityVacation {\n rclgovercool\n ventspdclg\n ventclg\n rhtg\n humidifier\n humid\n venthtg\n rclg\n ventspdhtg\n }\n zones {\n id\n name\n enabled\n hold\n holdActivity\n otmr\n occEnabled\n program {\n id\n day {\n id\n zoneId\n period {\n id\n zoneId\n dayId\n activity\n time\n enabled\n }\n }\n }\n activities {\n id\n zoneId\n type\n fan\n htsp\n clsp\n }\n }\n humidityAway {\n humid\n humidifier\n rhtg\n rclg\n rclgovercool\n }\n humidityHome {\n humid\n humidifier\n rhtg\n rclg\n rclgovercool\n }\n }\n }\n }\n";
23
+ /**
24
+ * Energy data query - fetches energy usage and efficiency data
25
+ * This is new functionality not available in the old REST API
26
+ */
27
+ export declare const GET_INFINITY_ENERGY = "\n query getInfinityEnergy($serial: String!) {\n infinityEnergy(serial: $serial) {\n energyConfig {\n cooling {\n display\n enabled\n }\n eheat {\n display\n enabled\n }\n fan {\n display\n enabled\n }\n fangas {\n display\n enabled\n }\n gas {\n display\n enabled\n }\n hpheat {\n display\n enabled\n }\n looppump {\n display\n enabled\n }\n reheat {\n display\n enabled\n }\n hspf\n seer\n }\n energyPeriods {\n energyPeriodType\n eHeatKwh\n coolingKwh\n fanGasKwh\n fanKwh\n hPHeatKwh\n loopPumpKwh\n gasKwh\n reheatKwh\n }\n }\n }\n";
28
+ /**
29
+ * Update system configuration mutation
30
+ * Used for system-level settings like mode, humidity, heat source, etc.
31
+ *
32
+ * Example inputs:
33
+ * - Set mode: { serial, mode: "cool" }
34
+ * - Set humidity: { serial, humidityHome: { humidifier: "on", rhtg: 8 } }
35
+ * - Set heat source: { serial, heatsource: "system" }
36
+ */
37
+ export declare const UPDATE_INFINITY_CONFIG = "\n mutation updateInfinityConfig($input: InfinityConfigInput!) {\n updateInfinityConfig(input: $input) {\n etag\n }\n }\n";
38
+ /**
39
+ * Update zone activity mutation
40
+ * Used for changing zone activity type, setpoints, and fan mode
41
+ *
42
+ * Example inputs:
43
+ * - Set manual activity: { serial, zoneId, activityType: "manual", clsp: "75", htsp: "68", fan: "med" }
44
+ * - Update fan: { serial, zoneId, activityType: "manual", fan: "high" }
45
+ */
46
+ export declare const UPDATE_INFINITY_ZONE_ACTIVITY = "\n mutation updateInfinityZoneActivity($input: InfinityZoneActivityInput!) {\n updateInfinityZoneActivity(input: $input) {\n etag\n }\n }\n";
47
+ /**
48
+ * Update zone configuration mutation
49
+ * Used for zone-level settings like hold status, schedule, etc.
50
+ *
51
+ * Example inputs:
52
+ * - Set hold: { serial, zoneId, hold: "on", holdActivity: "manual", otmr: "2024-01-30T18:00:00" }
53
+ * - Cancel hold: { serial, zoneId, hold: "off", holdActivity: null, otmr: null }
54
+ */
55
+ export declare const UPDATE_INFINITY_ZONE_CONFIG = "\n mutation updateInfinityZoneConfig($input: InfinityZoneConfigInput!) {\n updateInfinityZoneConfig(input: $input) {\n etag\n }\n }\n";
56
+ //# sourceMappingURL=graphql_operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql_operations.d.ts","sourceRoot":"","sources":["../../src/api/graphql_operations.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc,4RAe1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,40BA4CpB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,q5EAyIhC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,s4BAoD/B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,2IAMlC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,6JAMzC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,uJAMvC,CAAC"}