tsvesync 1.0.98 → 1.0.100

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.
@@ -117,7 +117,7 @@ export declare class Helpers {
117
117
  /**
118
118
  * Build request body for second authentication step (login with authorize code)
119
119
  */
120
- static reqBodyAuthStep2(authorizeCode: string, bizToken: string | null, appId: string, terminalId: string, userCountryCode?: string): Record<string, any>;
120
+ static reqBodyAuthStep2(authorizeCode: string, bizToken: string | null, appId: string, terminalId: string, userCountryCode?: string, regionChange?: string): Record<string, any>;
121
121
  /**
122
122
  * Builder for body of api requests
123
123
  */
@@ -194,7 +194,7 @@ class Helpers {
194
194
  /**
195
195
  * Build request body for second authentication step (login with authorize code)
196
196
  */
197
- static reqBodyAuthStep2(authorizeCode, bizToken, appId, terminalId, userCountryCode) {
197
+ static reqBodyAuthStep2(authorizeCode, bizToken, appId, terminalId, userCountryCode, regionChange) {
198
198
  const body = {
199
199
  'method': 'loginByAuthorizeCode4Vesync',
200
200
  'authorizeCode': authorizeCode,
@@ -214,6 +214,10 @@ class Helpers {
214
214
  if (bizToken) {
215
215
  body.bizToken = bizToken;
216
216
  }
217
+ // Only include regionChange if provided
218
+ if (regionChange) {
219
+ body.regionChange = regionChange;
220
+ }
217
221
  return body;
218
222
  }
219
223
  /**
@@ -438,15 +442,49 @@ class Helpers {
438
442
  const step2Body = this.reqBodyAuthStep2(authorizeCode, bizToken, appId, terminalId, userCountryCode);
439
443
  logger_1.logger.debug('Step 2: Logging in with authorization code...');
440
444
  const [loginResponse, loginStatus] = await this.callApi('/user/api/accountManage/v1/loginByAuthorizeCode4Vesync', 'post', step2Body, step1Headers, manager);
441
- setApiBaseUrl(originalUrl); // Restore original URL
442
445
  if (!loginResponse || loginStatus !== 200) {
443
446
  logger_1.logger.error('Step 2 failed:', loginResponse);
447
+ setApiBaseUrl(originalUrl); // Restore original URL on failure
444
448
  return [false, null, null, null];
445
449
  }
446
450
  if (loginResponse.code !== 0) {
451
+ // Handle cross-region error with retry (like pyvesync PR #340)
452
+ if (loginResponse.code === exports.CROSS_REGION_ERROR_CODE) {
453
+ logger_1.logger.debug('Cross-region error detected in Step 2, retrying with region change token...');
454
+ const { bizToken: regionChangeToken, countryCode: newCountryCode } = loginResponse.result || {};
455
+ if (regionChangeToken) {
456
+ // Retry Step 2 with region change token
457
+ const retryBody = {
458
+ ...step2Body,
459
+ bizToken: regionChangeToken,
460
+ regionChange: 'last_region',
461
+ userCountryCode: newCountryCode || userCountryCode
462
+ };
463
+ logger_1.logger.debug('Retrying Step 2 with region change token...', {
464
+ newCountryCode,
465
+ hasRegionChangeToken: true
466
+ });
467
+ const [retryResponse, retryStatus] = await this.callApi('/user/api/accountManage/v1/loginByAuthorizeCode4Vesync', 'post', retryBody, step1Headers, manager);
468
+ setApiBaseUrl(originalUrl); // Restore original URL after retry
469
+ if (retryResponse && retryResponse.code === 0) {
470
+ const { token, accountID, countryCode } = retryResponse.result || {};
471
+ if (token && accountID) {
472
+ logger_1.logger.debug('Step 2 retry successful with region change');
473
+ return [true, token, accountID, countryCode || newCountryCode];
474
+ }
475
+ }
476
+ logger_1.logger.error('Step 2 retry failed:', retryResponse);
477
+ return [false, null, null, null];
478
+ }
479
+ else {
480
+ logger_1.logger.error('No region change token in cross-region error response');
481
+ }
482
+ }
447
483
  logger_1.logger.error('Step 2 error code:', loginResponse.code, 'message:', loginResponse.msg);
484
+ setApiBaseUrl(originalUrl); // Restore original URL on error
448
485
  return [false, null, null, null];
449
486
  }
487
+ setApiBaseUrl(originalUrl); // Restore original URL on success
450
488
  const { token, accountID, countryCode } = loginResponse.result || {};
451
489
  if (!token || !accountID) {
452
490
  logger_1.logger.error('Missing required fields in step 2 response:', loginResponse.result);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsvesync",
3
- "version": "1.0.98",
3
+ "version": "1.0.100",
4
4
  "description": "A TypeScript library for interacting with VeSync smart home devices",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -264,7 +264,7 @@ export class Helpers {
264
264
  /**
265
265
  * Build request body for second authentication step (login with authorize code)
266
266
  */
267
- static reqBodyAuthStep2(authorizeCode: string, bizToken: string | null, appId: string, terminalId: string, userCountryCode?: string): Record<string, any> {
267
+ static reqBodyAuthStep2(authorizeCode: string, bizToken: string | null, appId: string, terminalId: string, userCountryCode?: string, regionChange?: string): Record<string, any> {
268
268
  const body: Record<string, any> = {
269
269
  'method': 'loginByAuthorizeCode4Vesync',
270
270
  'authorizeCode': authorizeCode,
@@ -285,6 +285,11 @@ export class Helpers {
285
285
  if (bizToken) {
286
286
  body.bizToken = bizToken;
287
287
  }
288
+
289
+ // Only include regionChange if provided
290
+ if (regionChange) {
291
+ body.regionChange = regionChange;
292
+ }
288
293
 
289
294
  return body;
290
295
  }
@@ -565,18 +570,65 @@ export class Helpers {
565
570
  manager
566
571
  );
567
572
 
568
- setApiBaseUrl(originalUrl); // Restore original URL
569
-
570
573
  if (!loginResponse || loginStatus !== 200) {
571
574
  logger.error('Step 2 failed:', loginResponse);
575
+ setApiBaseUrl(originalUrl); // Restore original URL on failure
572
576
  return [false, null, null, null];
573
577
  }
574
578
 
575
579
  if (loginResponse.code !== 0) {
580
+ // Handle cross-region error with retry (like pyvesync PR #340)
581
+ if (loginResponse.code === CROSS_REGION_ERROR_CODE) {
582
+ logger.debug('Cross-region error detected in Step 2, retrying with region change token...');
583
+
584
+ const { bizToken: regionChangeToken, countryCode: newCountryCode } = loginResponse.result || {};
585
+
586
+ if (regionChangeToken) {
587
+ // Retry Step 2 with region change token
588
+ const retryBody = {
589
+ ...step2Body,
590
+ bizToken: regionChangeToken,
591
+ regionChange: 'last_region',
592
+ userCountryCode: newCountryCode || userCountryCode
593
+ };
594
+
595
+ logger.debug('Retrying Step 2 with region change token...', {
596
+ newCountryCode,
597
+ hasRegionChangeToken: true
598
+ });
599
+
600
+ const [retryResponse, retryStatus] = await this.callApi(
601
+ '/user/api/accountManage/v1/loginByAuthorizeCode4Vesync',
602
+ 'post',
603
+ retryBody,
604
+ step1Headers,
605
+ manager
606
+ );
607
+
608
+ setApiBaseUrl(originalUrl); // Restore original URL after retry
609
+
610
+ if (retryResponse && retryResponse.code === 0) {
611
+ const { token, accountID, countryCode } = retryResponse.result || {};
612
+ if (token && accountID) {
613
+ logger.debug('Step 2 retry successful with region change');
614
+ return [true, token, accountID, countryCode || newCountryCode];
615
+ }
616
+ }
617
+
618
+ logger.error('Step 2 retry failed:', retryResponse);
619
+ return [false, null, null, null];
620
+ } else {
621
+ logger.error('No region change token in cross-region error response');
622
+ }
623
+ }
624
+
576
625
  logger.error('Step 2 error code:', loginResponse.code, 'message:', loginResponse.msg);
626
+ setApiBaseUrl(originalUrl); // Restore original URL on error
577
627
  return [false, null, null, null];
578
628
  }
579
629
 
630
+ setApiBaseUrl(originalUrl); // Restore original URL on success
631
+
580
632
  const { token, accountID, countryCode } = loginResponse.result || {};
581
633
 
582
634
  if (!token || !accountID) {