mysa-js-sdk 2.1.2 → 3.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.
package/dist/index.d.cts CHANGED
@@ -1,11 +1,20 @@
1
1
  /** Error thrown when attempting to access the Mysa API without proper authentication. */
2
2
  declare class UnauthenticatedError extends Error {
3
+ /**
4
+ * The underlying failure that prevented authentication.
5
+ *
6
+ * Callers need it to tell a credential rejection apart from a transport or service failure, since both surface as
7
+ * this error. Declared explicitly rather than passed to `super` so the SDK keeps compiling against its current lib,
8
+ * which predates the two-argument `Error` constructor.
9
+ */
10
+ readonly cause?: unknown;
3
11
  /**
4
12
  * Creates a new UnauthenticatedError instance.
5
13
  *
6
14
  * @param message - The error message
15
+ * @param cause - The underlying failure that prevented authentication, if any.
7
16
  */
8
- constructor(message: string);
17
+ constructor(message: string, cause?: unknown);
9
18
  }
10
19
  /** Error thrown when a Mysa API request fails. */
11
20
  declare class MysaApiError extends Error {
@@ -20,6 +29,16 @@ declare class MysaApiError extends Error {
20
29
  */
21
30
  constructor(apiResponse: Response);
22
31
  }
32
+ /** Error thrown when a device id does not match any device on the account. */
33
+ declare class UnknownDeviceError extends Error {
34
+ readonly deviceId: string;
35
+ /**
36
+ * Creates a new UnknownDeviceError instance.
37
+ *
38
+ * @param deviceId - The device id that could not be resolved
39
+ */
40
+ constructor(deviceId: string);
41
+ }
23
42
  /** Error thrown when an MQTT publish ultimately fails after retry attempts. */
24
43
  declare class MqttPublishError extends Error {
25
44
  attempts: number;
@@ -99,7 +118,7 @@ interface Status {
99
118
  setPoint: number;
100
119
  /** Optional electrical current draw measurement in amperes */
101
120
  current?: number;
102
- /** Optional heating element duty cycle as a percentage (0-100) */
121
+ /** Optional heating element duty cycle, as a fraction between 0.0 and 1.0 */
103
122
  dutyCycle?: number;
104
123
  }
105
124
 
@@ -123,20 +142,16 @@ declare class VoidLogger implements Logger {
123
142
  }
124
143
 
125
144
  /**
126
- * Interface representing an authenticated Mysa user session.
145
+ * Interface representing the credentials of a Mysa account.
127
146
  *
128
- * Contains the authentication tokens and user information required to make authorized API calls to the Mysa service.
129
- * These tokens are typically obtained through the login process and used for subsequent API requests.
147
+ * The client authenticates with these credentials on demand, and re-authenticates with them whenever its session can no
148
+ * longer be refreshed. They are held for the lifetime of the client.
130
149
  */
131
- interface MysaSession {
132
- /** The username/email address of the authenticated user */
150
+ interface MysaCredentials {
151
+ /** The email address of the Mysa account. */
133
152
  username: string;
134
- /** JWT identity token containing user identity information */
135
- idToken: string;
136
- /** JWT access token used for authorizing API requests */
137
- accessToken: string;
138
- /** JWT refresh token used to obtain new access tokens when they expire */
139
- refreshToken: string;
153
+ /** The password of the Mysa account. */
154
+ password: string;
140
155
  }
141
156
 
142
157
  /**
@@ -553,7 +568,7 @@ interface DeviceV2Status extends MsgPayload<OutMessageType.DEVICE_V2_STATUS> {
553
568
  body: {
554
569
  /** Ambient temperature reading from the device sensor */
555
570
  ambTemp: number;
556
- /** Current duty cycle percentage of the heating element */
571
+ /** Current duty cycle of the heating element, as a fraction between 0.0 and 1.0 */
557
572
  dtyCycle: number;
558
573
  /** Relative humidity percentage reading from the device sensor */
559
574
  hum: number;
@@ -682,14 +697,6 @@ type OutPayload = MsgTypeOutPayload | MsgOutPayload;
682
697
  * emission in the Mysa API client's event system.
683
698
  */
684
699
  type MysaApiClientEventTypes = {
685
- /**
686
- * Event emitted when the session changes.
687
- *
688
- * @remarks
689
- * You should subscribe to this event and persist the session object whenever it changes.
690
- * @param session - The new session object or undefined if session was cleared.
691
- */
692
- sessionChanged: [session: MysaSession | undefined];
693
700
  /**
694
701
  * Event emitted when a device's status information is updated.
695
702
  *
@@ -761,9 +768,9 @@ interface MqttPublishOptions {
761
768
  * @example
762
769
  *
763
770
  * ```typescript
764
- * const client = new MysaApiClient();
771
+ * const client = new MysaApiClient({ username: 'user@example.com', password: 'password' });
765
772
  *
766
- * await client.login('user@example.com', 'password');
773
+ * await client.login();
767
774
  * const devices = await client.getDevices();
768
775
  *
769
776
  * client.emitter.on('statusChanged', (status) => {
@@ -776,10 +783,14 @@ interface MqttPublishOptions {
776
783
  * ```
777
784
  */
778
785
  declare class MysaApiClient {
786
+ /** The credentials of the Mysa account this client authenticates as. */
787
+ private _credentials;
779
788
  /** The current session object, if any. */
780
789
  private _cognitoUserSession?;
781
790
  /** The current user object, if any. */
782
791
  private _cognitoUser?;
792
+ /** The in-flight session acquisition, if any, so that concurrent callers share a single refresh or login. */
793
+ private _freshSessionPromise?;
783
794
  /** The logger instance used by the client. */
784
795
  private _logger;
785
796
  /** The fetcher function used by the client. */
@@ -804,47 +815,41 @@ declare class MysaApiClient {
804
815
  * @see {@link MysaApiClientEventTypes} for the possible events and their payloads.
805
816
  */
806
817
  readonly emitter: EventEmitter<MysaApiClientEventTypes>;
807
- /**
808
- * Gets the persistable session object.
809
- *
810
- * @returns The current persistable session object, if any.
811
- */
812
- get session(): MysaSession | undefined;
813
- /**
814
- * Returns whether the client currently has an active session.
815
- *
816
- * @returns True if the client has an active session, false otherwise.
817
- */
818
- get isAuthenticated(): boolean;
819
818
  /**
820
819
  * Constructs a new instance of the MysaApiClient.
821
820
  *
822
- * @param session - The persistable session object, if any.
821
+ * @param credentials - The credentials of the Mysa account to authenticate as.
823
822
  * @param options - The options for the client.
824
823
  */
825
- constructor(session?: MysaSession, options?: MysaApiClientOptions);
824
+ constructor(credentials: MysaCredentials, options?: MysaApiClientOptions);
826
825
  /**
827
- * Logs in the user with the given email address and password.
826
+ * Ensures the client has a usable session, logging in with the credentials it was constructed with if needed.
828
827
  *
829
- * This method authenticates the user with Mysa's Cognito user pool and establishes a session that can be used for
830
- * subsequent API calls. Upon successful login, a 'sessionChanged' event is emitted.
828
+ * Calling this method is optional: the client authenticates on demand before its first API call, and re-authenticates
829
+ * on its own whenever its session can no longer be refreshed. Call it explicitly at startup to fail fast on invalid
830
+ * credentials instead of on the first API call. It is a no-op when the current session is still usable.
831
831
  *
832
832
  * @example
833
833
  *
834
834
  * ```typescript
835
835
  * try {
836
- * await client.login('user@example.com', 'password123');
836
+ * await client.login();
837
837
  * console.log('Login successful!');
838
838
  * } catch (error) {
839
839
  * console.error('Login failed:', error.message);
840
840
  * }
841
841
  * ```
842
842
  *
843
- * @param emailAddress - The email address of the user.
844
- * @param password - The password of the user.
843
+ * @throws {@link UnauthenticatedError} When authentication fails due to invalid credentials or network issues.
844
+ */
845
+ login(): Promise<void>;
846
+ /**
847
+ * Authenticates with Mysa's Cognito user pool and replaces the current session, if any.
848
+ *
849
+ * @returns A promise that resolves to the newly established session.
845
850
  * @throws {@link Error} When authentication fails due to invalid credentials or network issues.
846
851
  */
847
- login(emailAddress: string, password: string): Promise<void>;
852
+ private _login;
848
853
  /**
849
854
  * Retrieves the list of devices associated with the user.
850
855
  *
@@ -862,7 +867,7 @@ declare class MysaApiClient {
862
867
  *
863
868
  * @returns A promise that resolves to the list of devices.
864
869
  * @throws {@link MysaApiError} When the API request fails.
865
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
870
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
866
871
  */
867
872
  getDevices(): Promise<Devices>;
868
873
  /**
@@ -884,7 +889,7 @@ declare class MysaApiClient {
884
889
  *
885
890
  * @param deviceId - The ID of the device to get the serial number for.
886
891
  * @returns A promise that resolves to the serial number, or undefined if not found.
887
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
892
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
888
893
  */
889
894
  getDeviceSerialNumber(deviceId: string): Promise<string | undefined>;
890
895
  /**
@@ -892,7 +897,7 @@ declare class MysaApiClient {
892
897
  *
893
898
  * @returns A promise that resolves to the firmware information for all devices.
894
899
  * @throws {@link MysaApiError} When the API request fails.
895
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
900
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
896
901
  */
897
902
  getDeviceFirmwares(): Promise<Firmwares>;
898
903
  /**
@@ -900,7 +905,7 @@ declare class MysaApiClient {
900
905
  *
901
906
  * @returns A promise that resolves to the current state of all devices.
902
907
  * @throws {@link MysaApiError} When the API request fails.
903
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
908
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
904
909
  */
905
910
  getDeviceStates(): Promise<DeviceStates>;
906
911
  /**
@@ -908,7 +913,7 @@ declare class MysaApiClient {
908
913
  *
909
914
  * @returns A promise that resolves to the homes information.
910
915
  * @throws {@link MysaApiError} When the API request fails.
911
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
916
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
912
917
  */
913
918
  getHomes(): Promise<Homes>;
914
919
  /**
@@ -938,7 +943,8 @@ declare class MysaApiClient {
938
943
  * @param mode - The operating mode to set (one of MysaDeviceMode values, or undefined to leave unchanged).
939
944
  * @param fanSpeed - The fan speed mode to set ('low', 'medium', 'high', 'max', 'auto', or undefined to leave
940
945
  * unchanged).
941
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
946
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
947
+ * @throws {@link UnknownDeviceError} When the device id does not match any device on the account.
942
948
  * @throws {@link Error} When MQTT connection or command sending fails.
943
949
  */
944
950
  setDeviceState(deviceId: string, setPoint?: number, mode?: MysaDeviceMode, fanSpeed?: MysaFanSpeedMode): Promise<void>;
@@ -978,12 +984,23 @@ declare class MysaApiClient {
978
984
  * Ensures a valid, non-expired session is available.
979
985
  *
980
986
  * This method checks if the current session is valid and not expired. If the session is expired, it automatically
981
- * refreshes it using the refresh token.
987
+ * refreshes it using the refresh token. If there is no session yet, or if the refresh token has itself expired or
988
+ * been revoked, the client logs back in with its credentials.
989
+ *
990
+ * Concurrent callers share a single in-flight acquisition, so a burst of API calls never triggers more than one
991
+ * refresh or login.
982
992
  *
983
993
  * @returns A promise that resolves to a valid CognitoUserSession.
984
- * @throws {@link UnauthenticatedError} When no session exists or refresh fails.
994
+ * @throws {@link UnauthenticatedError} When neither refreshing nor logging back in succeeds.
985
995
  */
986
996
  private _getFreshSession;
997
+ /**
998
+ * Refreshes the current session, falling back to a full login when it cannot be refreshed.
999
+ *
1000
+ * @returns A promise that resolves to a valid CognitoUserSession.
1001
+ * @throws {@link UnauthenticatedError} When logging back in fails.
1002
+ */
1003
+ private _acquireFreshSession;
987
1004
  /**
988
1005
  * Establishes and returns an MQTT connection for real-time communication.
989
1006
  *
@@ -1158,4 +1175,4 @@ type MsgTypeInPayload = CheckDeviceSettings | StartPublishingDeviceStatus;
1158
1175
  */
1159
1176
  type InPayload = MsgTypeInPayload | MsgInPayload;
1160
1177
 
1161
- export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaDeviceMode, type MysaFanSpeedMode, type MysaSession, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, VoidLogger };
1178
+ export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaCredentials, type MysaDeviceMode, type MysaFanSpeedMode, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, UnknownDeviceError, VoidLogger };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,20 @@
1
1
  /** Error thrown when attempting to access the Mysa API without proper authentication. */
2
2
  declare class UnauthenticatedError extends Error {
3
+ /**
4
+ * The underlying failure that prevented authentication.
5
+ *
6
+ * Callers need it to tell a credential rejection apart from a transport or service failure, since both surface as
7
+ * this error. Declared explicitly rather than passed to `super` so the SDK keeps compiling against its current lib,
8
+ * which predates the two-argument `Error` constructor.
9
+ */
10
+ readonly cause?: unknown;
3
11
  /**
4
12
  * Creates a new UnauthenticatedError instance.
5
13
  *
6
14
  * @param message - The error message
15
+ * @param cause - The underlying failure that prevented authentication, if any.
7
16
  */
8
- constructor(message: string);
17
+ constructor(message: string, cause?: unknown);
9
18
  }
10
19
  /** Error thrown when a Mysa API request fails. */
11
20
  declare class MysaApiError extends Error {
@@ -20,6 +29,16 @@ declare class MysaApiError extends Error {
20
29
  */
21
30
  constructor(apiResponse: Response);
22
31
  }
32
+ /** Error thrown when a device id does not match any device on the account. */
33
+ declare class UnknownDeviceError extends Error {
34
+ readonly deviceId: string;
35
+ /**
36
+ * Creates a new UnknownDeviceError instance.
37
+ *
38
+ * @param deviceId - The device id that could not be resolved
39
+ */
40
+ constructor(deviceId: string);
41
+ }
23
42
  /** Error thrown when an MQTT publish ultimately fails after retry attempts. */
24
43
  declare class MqttPublishError extends Error {
25
44
  attempts: number;
@@ -99,7 +118,7 @@ interface Status {
99
118
  setPoint: number;
100
119
  /** Optional electrical current draw measurement in amperes */
101
120
  current?: number;
102
- /** Optional heating element duty cycle as a percentage (0-100) */
121
+ /** Optional heating element duty cycle, as a fraction between 0.0 and 1.0 */
103
122
  dutyCycle?: number;
104
123
  }
105
124
 
@@ -123,20 +142,16 @@ declare class VoidLogger implements Logger {
123
142
  }
124
143
 
125
144
  /**
126
- * Interface representing an authenticated Mysa user session.
145
+ * Interface representing the credentials of a Mysa account.
127
146
  *
128
- * Contains the authentication tokens and user information required to make authorized API calls to the Mysa service.
129
- * These tokens are typically obtained through the login process and used for subsequent API requests.
147
+ * The client authenticates with these credentials on demand, and re-authenticates with them whenever its session can no
148
+ * longer be refreshed. They are held for the lifetime of the client.
130
149
  */
131
- interface MysaSession {
132
- /** The username/email address of the authenticated user */
150
+ interface MysaCredentials {
151
+ /** The email address of the Mysa account. */
133
152
  username: string;
134
- /** JWT identity token containing user identity information */
135
- idToken: string;
136
- /** JWT access token used for authorizing API requests */
137
- accessToken: string;
138
- /** JWT refresh token used to obtain new access tokens when they expire */
139
- refreshToken: string;
153
+ /** The password of the Mysa account. */
154
+ password: string;
140
155
  }
141
156
 
142
157
  /**
@@ -553,7 +568,7 @@ interface DeviceV2Status extends MsgPayload<OutMessageType.DEVICE_V2_STATUS> {
553
568
  body: {
554
569
  /** Ambient temperature reading from the device sensor */
555
570
  ambTemp: number;
556
- /** Current duty cycle percentage of the heating element */
571
+ /** Current duty cycle of the heating element, as a fraction between 0.0 and 1.0 */
557
572
  dtyCycle: number;
558
573
  /** Relative humidity percentage reading from the device sensor */
559
574
  hum: number;
@@ -682,14 +697,6 @@ type OutPayload = MsgTypeOutPayload | MsgOutPayload;
682
697
  * emission in the Mysa API client's event system.
683
698
  */
684
699
  type MysaApiClientEventTypes = {
685
- /**
686
- * Event emitted when the session changes.
687
- *
688
- * @remarks
689
- * You should subscribe to this event and persist the session object whenever it changes.
690
- * @param session - The new session object or undefined if session was cleared.
691
- */
692
- sessionChanged: [session: MysaSession | undefined];
693
700
  /**
694
701
  * Event emitted when a device's status information is updated.
695
702
  *
@@ -761,9 +768,9 @@ interface MqttPublishOptions {
761
768
  * @example
762
769
  *
763
770
  * ```typescript
764
- * const client = new MysaApiClient();
771
+ * const client = new MysaApiClient({ username: 'user@example.com', password: 'password' });
765
772
  *
766
- * await client.login('user@example.com', 'password');
773
+ * await client.login();
767
774
  * const devices = await client.getDevices();
768
775
  *
769
776
  * client.emitter.on('statusChanged', (status) => {
@@ -776,10 +783,14 @@ interface MqttPublishOptions {
776
783
  * ```
777
784
  */
778
785
  declare class MysaApiClient {
786
+ /** The credentials of the Mysa account this client authenticates as. */
787
+ private _credentials;
779
788
  /** The current session object, if any. */
780
789
  private _cognitoUserSession?;
781
790
  /** The current user object, if any. */
782
791
  private _cognitoUser?;
792
+ /** The in-flight session acquisition, if any, so that concurrent callers share a single refresh or login. */
793
+ private _freshSessionPromise?;
783
794
  /** The logger instance used by the client. */
784
795
  private _logger;
785
796
  /** The fetcher function used by the client. */
@@ -804,47 +815,41 @@ declare class MysaApiClient {
804
815
  * @see {@link MysaApiClientEventTypes} for the possible events and their payloads.
805
816
  */
806
817
  readonly emitter: EventEmitter<MysaApiClientEventTypes>;
807
- /**
808
- * Gets the persistable session object.
809
- *
810
- * @returns The current persistable session object, if any.
811
- */
812
- get session(): MysaSession | undefined;
813
- /**
814
- * Returns whether the client currently has an active session.
815
- *
816
- * @returns True if the client has an active session, false otherwise.
817
- */
818
- get isAuthenticated(): boolean;
819
818
  /**
820
819
  * Constructs a new instance of the MysaApiClient.
821
820
  *
822
- * @param session - The persistable session object, if any.
821
+ * @param credentials - The credentials of the Mysa account to authenticate as.
823
822
  * @param options - The options for the client.
824
823
  */
825
- constructor(session?: MysaSession, options?: MysaApiClientOptions);
824
+ constructor(credentials: MysaCredentials, options?: MysaApiClientOptions);
826
825
  /**
827
- * Logs in the user with the given email address and password.
826
+ * Ensures the client has a usable session, logging in with the credentials it was constructed with if needed.
828
827
  *
829
- * This method authenticates the user with Mysa's Cognito user pool and establishes a session that can be used for
830
- * subsequent API calls. Upon successful login, a 'sessionChanged' event is emitted.
828
+ * Calling this method is optional: the client authenticates on demand before its first API call, and re-authenticates
829
+ * on its own whenever its session can no longer be refreshed. Call it explicitly at startup to fail fast on invalid
830
+ * credentials instead of on the first API call. It is a no-op when the current session is still usable.
831
831
  *
832
832
  * @example
833
833
  *
834
834
  * ```typescript
835
835
  * try {
836
- * await client.login('user@example.com', 'password123');
836
+ * await client.login();
837
837
  * console.log('Login successful!');
838
838
  * } catch (error) {
839
839
  * console.error('Login failed:', error.message);
840
840
  * }
841
841
  * ```
842
842
  *
843
- * @param emailAddress - The email address of the user.
844
- * @param password - The password of the user.
843
+ * @throws {@link UnauthenticatedError} When authentication fails due to invalid credentials or network issues.
844
+ */
845
+ login(): Promise<void>;
846
+ /**
847
+ * Authenticates with Mysa's Cognito user pool and replaces the current session, if any.
848
+ *
849
+ * @returns A promise that resolves to the newly established session.
845
850
  * @throws {@link Error} When authentication fails due to invalid credentials or network issues.
846
851
  */
847
- login(emailAddress: string, password: string): Promise<void>;
852
+ private _login;
848
853
  /**
849
854
  * Retrieves the list of devices associated with the user.
850
855
  *
@@ -862,7 +867,7 @@ declare class MysaApiClient {
862
867
  *
863
868
  * @returns A promise that resolves to the list of devices.
864
869
  * @throws {@link MysaApiError} When the API request fails.
865
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
870
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
866
871
  */
867
872
  getDevices(): Promise<Devices>;
868
873
  /**
@@ -884,7 +889,7 @@ declare class MysaApiClient {
884
889
  *
885
890
  * @param deviceId - The ID of the device to get the serial number for.
886
891
  * @returns A promise that resolves to the serial number, or undefined if not found.
887
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
892
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
888
893
  */
889
894
  getDeviceSerialNumber(deviceId: string): Promise<string | undefined>;
890
895
  /**
@@ -892,7 +897,7 @@ declare class MysaApiClient {
892
897
  *
893
898
  * @returns A promise that resolves to the firmware information for all devices.
894
899
  * @throws {@link MysaApiError} When the API request fails.
895
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
900
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
896
901
  */
897
902
  getDeviceFirmwares(): Promise<Firmwares>;
898
903
  /**
@@ -900,7 +905,7 @@ declare class MysaApiClient {
900
905
  *
901
906
  * @returns A promise that resolves to the current state of all devices.
902
907
  * @throws {@link MysaApiError} When the API request fails.
903
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
908
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
904
909
  */
905
910
  getDeviceStates(): Promise<DeviceStates>;
906
911
  /**
@@ -908,7 +913,7 @@ declare class MysaApiClient {
908
913
  *
909
914
  * @returns A promise that resolves to the homes information.
910
915
  * @throws {@link MysaApiError} When the API request fails.
911
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
916
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
912
917
  */
913
918
  getHomes(): Promise<Homes>;
914
919
  /**
@@ -938,7 +943,8 @@ declare class MysaApiClient {
938
943
  * @param mode - The operating mode to set (one of MysaDeviceMode values, or undefined to leave unchanged).
939
944
  * @param fanSpeed - The fan speed mode to set ('low', 'medium', 'high', 'max', 'auto', or undefined to leave
940
945
  * unchanged).
941
- * @throws {@link UnauthenticatedError} When the user is not authenticated.
946
+ * @throws {@link UnauthenticatedError} When the client cannot authenticate with its credentials.
947
+ * @throws {@link UnknownDeviceError} When the device id does not match any device on the account.
942
948
  * @throws {@link Error} When MQTT connection or command sending fails.
943
949
  */
944
950
  setDeviceState(deviceId: string, setPoint?: number, mode?: MysaDeviceMode, fanSpeed?: MysaFanSpeedMode): Promise<void>;
@@ -978,12 +984,23 @@ declare class MysaApiClient {
978
984
  * Ensures a valid, non-expired session is available.
979
985
  *
980
986
  * This method checks if the current session is valid and not expired. If the session is expired, it automatically
981
- * refreshes it using the refresh token.
987
+ * refreshes it using the refresh token. If there is no session yet, or if the refresh token has itself expired or
988
+ * been revoked, the client logs back in with its credentials.
989
+ *
990
+ * Concurrent callers share a single in-flight acquisition, so a burst of API calls never triggers more than one
991
+ * refresh or login.
982
992
  *
983
993
  * @returns A promise that resolves to a valid CognitoUserSession.
984
- * @throws {@link UnauthenticatedError} When no session exists or refresh fails.
994
+ * @throws {@link UnauthenticatedError} When neither refreshing nor logging back in succeeds.
985
995
  */
986
996
  private _getFreshSession;
997
+ /**
998
+ * Refreshes the current session, falling back to a full login when it cannot be refreshed.
999
+ *
1000
+ * @returns A promise that resolves to a valid CognitoUserSession.
1001
+ * @throws {@link UnauthenticatedError} When logging back in fails.
1002
+ */
1003
+ private _acquireFreshSession;
987
1004
  /**
988
1005
  * Establishes and returns an MQTT connection for real-time communication.
989
1006
  *
@@ -1158,4 +1175,4 @@ type MsgTypeInPayload = CheckDeviceSettings | StartPublishingDeviceStatus;
1158
1175
  */
1159
1176
  type InPayload = MsgTypeInPayload | MsgInPayload;
1160
1177
 
1161
- export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaDeviceMode, type MysaFanSpeedMode, type MysaSession, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, VoidLogger };
1178
+ export { type BrandInfo, type ChangeDeviceState, type CheckDeviceSettings, type DeviceAcStatus, type DeviceBase, type DeviceLog, type DevicePostBoot, type DeviceSetpointChange, type DeviceState, type DeviceStateChange, type DeviceStates, type DeviceStatesObj, type DeviceV1Status, type DeviceV2Status, type Devices, type DevicesObj, type FirmwareDevice, type Firmwares, type HomeBase, type Homes, InMessageType, type InPayload, type Logger, type ModeObj, MqttPublishError, type MqttPublishOptions, type MsgBasePayload, type MsgInPayload, type MsgOutPayload, type MsgPayload, type MsgTypeBasePayload, type MsgTypeInPayload, type MsgTypeOutPayload, type MsgTypePayload, MysaApiClient, type MysaApiClientEventTypes, type MysaApiClientOptions, MysaApiError, type MysaCredentials, type MysaDeviceMode, type MysaFanSpeedMode, OutMessageType, type OutPayload, type SetPointChange, type StartPublishingDeviceStatus, type StateChange, type Status, type SupportedCaps, type TimestampedValue, UnauthenticatedError, UnknownDeviceError, VoidLogger };