@etsoo/appscript 1.2.0 → 1.2.4

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.
@@ -102,7 +102,7 @@ class CoreAppTest extends CoreApp<IAppSettings, {}, NotificationCallProps> {
102
102
  },
103
103
  createClient(),
104
104
  container,
105
- new WindowStorage([], (_field, data, _index) => data),
105
+ new WindowStorage(),
106
106
  'SmartERP'
107
107
  );
108
108
  }
@@ -293,6 +293,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
293
293
  * @returns Result
294
294
  */
295
295
  orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
296
+ /**
297
+ * Persist settings to source when application exit
298
+ */
299
+ persist(): void;
296
300
  /**
297
301
  * Switch organization
298
302
  * @param id Organization id
@@ -427,6 +431,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
427
431
  */
428
432
  protected passphrase: string;
429
433
  private cachedRefreshToken?;
434
+ /**
435
+ * Get persisted fields
436
+ */
437
+ protected get persistedFields(): string[];
430
438
  /**
431
439
  * Protected constructor
432
440
  * @param settings Settings
@@ -436,6 +444,19 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
436
444
  * @param name Application name
437
445
  */
438
446
  protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, storage: IStorage, name: string);
447
+ private getDeviceId;
448
+ /**
449
+ * Restore settings from persisted source
450
+ */
451
+ protected restore(): boolean;
452
+ /**
453
+ * Persist settings to source when application exit
454
+ */
455
+ persist(): void;
456
+ /**
457
+ * Setup Api
458
+ * @param api Api
459
+ */
439
460
  protected setApi(api: IApi): void;
440
461
  /**
441
462
  * Api init call
@@ -723,6 +744,10 @@ export declare namespace CoreApp {
723
744
  * Device id field name
724
745
  */
725
746
  const deviceIdField = "SmartERPDeviceId";
747
+ /**
748
+ * Devices field name
749
+ */
750
+ const devicesField = "SmartERPDevices";
726
751
  /**
727
752
  * Device passphrase field name
728
753
  */
@@ -38,7 +38,7 @@ class CoreApp {
38
38
  /**
39
39
  * Passphrase for encryption
40
40
  */
41
- this.passphrase = '***';
41
+ this.passphrase = '';
42
42
  this.settings = settings;
43
43
  this.api = api;
44
44
  this.notifier = notifier;
@@ -46,6 +46,8 @@ class CoreApp {
46
46
  this.name = name;
47
47
  // Device id
48
48
  this._deviceId = storage.getData(CoreApp.deviceIdField, '');
49
+ // Restore
50
+ this.restore();
49
51
  this.setApi(api);
50
52
  const { currentCulture, currentRegion } = settings;
51
53
  this.changeCulture(currentCulture);
@@ -110,6 +112,69 @@ class CoreApp {
110
112
  set authorized(value) {
111
113
  this._authorized = value;
112
114
  }
115
+ /**
116
+ * Get persisted fields
117
+ */
118
+ get persistedFields() {
119
+ return [
120
+ CoreApp.deviceIdField,
121
+ CoreApp.serversideDeviceIdField,
122
+ CoreApp.headerTokenField
123
+ ];
124
+ }
125
+ getDeviceId() {
126
+ return this.deviceId.substring(0, 10);
127
+ }
128
+ /**
129
+ * Restore settings from persisted source
130
+ */
131
+ restore() {
132
+ // Current device id, '' means new, or reload (not included) or duplicate (included)
133
+ if (this.deviceId) {
134
+ // Devices
135
+ const devices = this.storage.getPersistedData(CoreApp.devicesField);
136
+ // Exists in the list?
137
+ if (!(devices === null || devices === void 0 ? void 0 : devices.includes(this.getDeviceId()))) {
138
+ const passphraseEncrypted = this.storage.getData(CoreApp.devicePassphraseField);
139
+ if (passphraseEncrypted) {
140
+ const passphraseDecrypted = this.decrypt(passphraseEncrypted, this.name);
141
+ if (passphraseDecrypted != null) {
142
+ this.passphrase = passphraseDecrypted;
143
+ return false;
144
+ }
145
+ }
146
+ }
147
+ else {
148
+ // Remove passphrase
149
+ this.storage.setData(CoreApp.devicePassphraseField, undefined);
150
+ this.passphrase = '';
151
+ }
152
+ }
153
+ // Restore
154
+ this.storage.copyFrom(this.persistedFields, true);
155
+ return true;
156
+ }
157
+ /**
158
+ * Persist settings to source when application exit
159
+ */
160
+ persist() {
161
+ // Devices
162
+ const devices = this.storage.getPersistedData(CoreApp.devicesField);
163
+ if (devices != null) {
164
+ const index = devices.indexOf(this.getDeviceId());
165
+ if (index !== -1) {
166
+ devices.splice(index, 1);
167
+ this.storage.setPersistedData(CoreApp.devicesField, devices);
168
+ }
169
+ }
170
+ if (!this.authorized)
171
+ return;
172
+ this.storage.copyTo(this.persistedFields);
173
+ }
174
+ /**
175
+ * Setup Api
176
+ * @param api Api
177
+ */
113
178
  setApi(api) {
114
179
  // onRequest, show loading or not, rewrite the property to override default action
115
180
  api.onRequest = (data) => {
@@ -156,16 +221,10 @@ class CoreApp {
156
221
  async initCall(callback) {
157
222
  var _a;
158
223
  // Passphrase exists?
159
- // Same session should avoid multiple init calls
160
- const passphraseEncrypted = this.storage.getData(CoreApp.devicePassphraseField);
161
- if (passphraseEncrypted) {
162
- const passphraseDecrypted = this.decrypt(passphraseEncrypted, this.name);
163
- if (passphraseDecrypted != null) {
164
- this.passphrase = passphraseDecrypted;
165
- if (callback)
166
- callback(true);
167
- return;
168
- }
224
+ if (this.passphrase) {
225
+ if (callback)
226
+ callback(true);
227
+ return;
169
228
  }
170
229
  // Serverside encrypted device id
171
230
  const identifier = this.storage.getData(CoreApp.serversideDeviceIdField);
@@ -175,7 +234,7 @@ class CoreApp {
175
234
  const data = {
176
235
  timestamp,
177
236
  identifier,
178
- deviceId: this.deviceId.length > 0 ? this.deviceId : undefined
237
+ deviceId: this.deviceId ? this.deviceId : undefined
179
238
  };
180
239
  const result = await this.apiInitCall(data);
181
240
  if (result == null) {
@@ -228,6 +287,10 @@ class CoreApp {
228
287
  // Update device id and cache it
229
288
  this._deviceId = data.deviceId;
230
289
  this.storage.setData(CoreApp.deviceIdField, this._deviceId);
290
+ // Devices
291
+ const devices = this.storage.getPersistedData(CoreApp.devicesField, []);
292
+ devices.push(this.getDeviceId());
293
+ this.storage.setPersistedData(CoreApp.devicesField, devices);
231
294
  // Current passphrase
232
295
  this.passphrase = passphrase;
233
296
  this.storage.setData(CoreApp.devicePassphraseField, this.encrypt(passphrase, this.name));
@@ -321,7 +384,7 @@ class CoreApp {
321
384
  if (regionItem == null || !this.settings.regions.includes(regionId))
322
385
  return;
323
386
  // Save the id to local storage
324
- this.storage.setData(shared_1.DomUtils.CountryField, regionId);
387
+ this.storage.setPersistedData(shared_1.DomUtils.CountryField, regionId);
325
388
  // Set the currency and culture
326
389
  this._currency = regionItem.currency;
327
390
  this._region = regionId;
@@ -339,7 +402,7 @@ class CoreApp {
339
402
  if (this._culture === name)
340
403
  return;
341
404
  // Save the cultrue to local storage
342
- this.storage.setData(shared_1.DomUtils.CultureField, name);
405
+ this.storage.setPersistedData(shared_1.DomUtils.CultureField, name);
343
406
  // Change the API's Content-Language header
344
407
  // .net 5 API, UseRequestLocalization, RequestCultureProviders, ContentLanguageHeaderRequestCultureProvider
345
408
  this.api.setContentLanguage(name);
@@ -358,17 +421,15 @@ class CoreApp {
358
421
  * Clear cache data
359
422
  */
360
423
  clearCacheData() {
361
- this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
362
- this.storage.setData(CoreApp.deviceIdField, undefined);
424
+ this.clearCacheToken();
363
425
  this.storage.setData(CoreApp.devicePassphraseField, undefined);
364
- this.storage.setData(CoreApp.headerTokenField, undefined);
365
426
  }
366
427
  /**
367
428
  * Clear cached token
368
429
  */
369
430
  clearCacheToken() {
370
431
  this.cachedRefreshToken = undefined;
371
- this.storage.setData(CoreApp.headerTokenField, undefined);
432
+ this.storage.setPersistedData(CoreApp.headerTokenField, undefined);
372
433
  }
373
434
  /**
374
435
  * Decrypt message
@@ -885,6 +946,10 @@ exports.CoreApp = CoreApp;
885
946
  * Device id field name
886
947
  */
887
948
  CoreApp.deviceIdField = 'SmartERPDeviceId';
949
+ /**
950
+ * Devices field name
951
+ */
952
+ CoreApp.devicesField = 'SmartERPDevices';
888
953
  /**
889
954
  * Device passphrase field name
890
955
  */
@@ -293,6 +293,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
293
293
  * @returns Result
294
294
  */
295
295
  orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
296
+ /**
297
+ * Persist settings to source when application exit
298
+ */
299
+ persist(): void;
296
300
  /**
297
301
  * Switch organization
298
302
  * @param id Organization id
@@ -427,6 +431,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
427
431
  */
428
432
  protected passphrase: string;
429
433
  private cachedRefreshToken?;
434
+ /**
435
+ * Get persisted fields
436
+ */
437
+ protected get persistedFields(): string[];
430
438
  /**
431
439
  * Protected constructor
432
440
  * @param settings Settings
@@ -436,6 +444,19 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
436
444
  * @param name Application name
437
445
  */
438
446
  protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, storage: IStorage, name: string);
447
+ private getDeviceId;
448
+ /**
449
+ * Restore settings from persisted source
450
+ */
451
+ protected restore(): boolean;
452
+ /**
453
+ * Persist settings to source when application exit
454
+ */
455
+ persist(): void;
456
+ /**
457
+ * Setup Api
458
+ * @param api Api
459
+ */
439
460
  protected setApi(api: IApi): void;
440
461
  /**
441
462
  * Api init call
@@ -723,6 +744,10 @@ export declare namespace CoreApp {
723
744
  * Device id field name
724
745
  */
725
746
  const deviceIdField = "SmartERPDeviceId";
747
+ /**
748
+ * Devices field name
749
+ */
750
+ const devicesField = "SmartERPDevices";
726
751
  /**
727
752
  * Device passphrase field name
728
753
  */
@@ -35,7 +35,7 @@ export class CoreApp {
35
35
  /**
36
36
  * Passphrase for encryption
37
37
  */
38
- this.passphrase = '***';
38
+ this.passphrase = '';
39
39
  this.settings = settings;
40
40
  this.api = api;
41
41
  this.notifier = notifier;
@@ -43,6 +43,8 @@ export class CoreApp {
43
43
  this.name = name;
44
44
  // Device id
45
45
  this._deviceId = storage.getData(CoreApp.deviceIdField, '');
46
+ // Restore
47
+ this.restore();
46
48
  this.setApi(api);
47
49
  const { currentCulture, currentRegion } = settings;
48
50
  this.changeCulture(currentCulture);
@@ -107,6 +109,69 @@ export class CoreApp {
107
109
  set authorized(value) {
108
110
  this._authorized = value;
109
111
  }
112
+ /**
113
+ * Get persisted fields
114
+ */
115
+ get persistedFields() {
116
+ return [
117
+ CoreApp.deviceIdField,
118
+ CoreApp.serversideDeviceIdField,
119
+ CoreApp.headerTokenField
120
+ ];
121
+ }
122
+ getDeviceId() {
123
+ return this.deviceId.substring(0, 10);
124
+ }
125
+ /**
126
+ * Restore settings from persisted source
127
+ */
128
+ restore() {
129
+ // Current device id, '' means new, or reload (not included) or duplicate (included)
130
+ if (this.deviceId) {
131
+ // Devices
132
+ const devices = this.storage.getPersistedData(CoreApp.devicesField);
133
+ // Exists in the list?
134
+ if (!(devices === null || devices === void 0 ? void 0 : devices.includes(this.getDeviceId()))) {
135
+ const passphraseEncrypted = this.storage.getData(CoreApp.devicePassphraseField);
136
+ if (passphraseEncrypted) {
137
+ const passphraseDecrypted = this.decrypt(passphraseEncrypted, this.name);
138
+ if (passphraseDecrypted != null) {
139
+ this.passphrase = passphraseDecrypted;
140
+ return false;
141
+ }
142
+ }
143
+ }
144
+ else {
145
+ // Remove passphrase
146
+ this.storage.setData(CoreApp.devicePassphraseField, undefined);
147
+ this.passphrase = '';
148
+ }
149
+ }
150
+ // Restore
151
+ this.storage.copyFrom(this.persistedFields, true);
152
+ return true;
153
+ }
154
+ /**
155
+ * Persist settings to source when application exit
156
+ */
157
+ persist() {
158
+ // Devices
159
+ const devices = this.storage.getPersistedData(CoreApp.devicesField);
160
+ if (devices != null) {
161
+ const index = devices.indexOf(this.getDeviceId());
162
+ if (index !== -1) {
163
+ devices.splice(index, 1);
164
+ this.storage.setPersistedData(CoreApp.devicesField, devices);
165
+ }
166
+ }
167
+ if (!this.authorized)
168
+ return;
169
+ this.storage.copyTo(this.persistedFields);
170
+ }
171
+ /**
172
+ * Setup Api
173
+ * @param api Api
174
+ */
110
175
  setApi(api) {
111
176
  // onRequest, show loading or not, rewrite the property to override default action
112
177
  api.onRequest = (data) => {
@@ -153,16 +218,10 @@ export class CoreApp {
153
218
  async initCall(callback) {
154
219
  var _a;
155
220
  // Passphrase exists?
156
- // Same session should avoid multiple init calls
157
- const passphraseEncrypted = this.storage.getData(CoreApp.devicePassphraseField);
158
- if (passphraseEncrypted) {
159
- const passphraseDecrypted = this.decrypt(passphraseEncrypted, this.name);
160
- if (passphraseDecrypted != null) {
161
- this.passphrase = passphraseDecrypted;
162
- if (callback)
163
- callback(true);
164
- return;
165
- }
221
+ if (this.passphrase) {
222
+ if (callback)
223
+ callback(true);
224
+ return;
166
225
  }
167
226
  // Serverside encrypted device id
168
227
  const identifier = this.storage.getData(CoreApp.serversideDeviceIdField);
@@ -172,7 +231,7 @@ export class CoreApp {
172
231
  const data = {
173
232
  timestamp,
174
233
  identifier,
175
- deviceId: this.deviceId.length > 0 ? this.deviceId : undefined
234
+ deviceId: this.deviceId ? this.deviceId : undefined
176
235
  };
177
236
  const result = await this.apiInitCall(data);
178
237
  if (result == null) {
@@ -225,6 +284,10 @@ export class CoreApp {
225
284
  // Update device id and cache it
226
285
  this._deviceId = data.deviceId;
227
286
  this.storage.setData(CoreApp.deviceIdField, this._deviceId);
287
+ // Devices
288
+ const devices = this.storage.getPersistedData(CoreApp.devicesField, []);
289
+ devices.push(this.getDeviceId());
290
+ this.storage.setPersistedData(CoreApp.devicesField, devices);
228
291
  // Current passphrase
229
292
  this.passphrase = passphrase;
230
293
  this.storage.setData(CoreApp.devicePassphraseField, this.encrypt(passphrase, this.name));
@@ -318,7 +381,7 @@ export class CoreApp {
318
381
  if (regionItem == null || !this.settings.regions.includes(regionId))
319
382
  return;
320
383
  // Save the id to local storage
321
- this.storage.setData(DomUtils.CountryField, regionId);
384
+ this.storage.setPersistedData(DomUtils.CountryField, regionId);
322
385
  // Set the currency and culture
323
386
  this._currency = regionItem.currency;
324
387
  this._region = regionId;
@@ -336,7 +399,7 @@ export class CoreApp {
336
399
  if (this._culture === name)
337
400
  return;
338
401
  // Save the cultrue to local storage
339
- this.storage.setData(DomUtils.CultureField, name);
402
+ this.storage.setPersistedData(DomUtils.CultureField, name);
340
403
  // Change the API's Content-Language header
341
404
  // .net 5 API, UseRequestLocalization, RequestCultureProviders, ContentLanguageHeaderRequestCultureProvider
342
405
  this.api.setContentLanguage(name);
@@ -355,17 +418,15 @@ export class CoreApp {
355
418
  * Clear cache data
356
419
  */
357
420
  clearCacheData() {
358
- this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
359
- this.storage.setData(CoreApp.deviceIdField, undefined);
421
+ this.clearCacheToken();
360
422
  this.storage.setData(CoreApp.devicePassphraseField, undefined);
361
- this.storage.setData(CoreApp.headerTokenField, undefined);
362
423
  }
363
424
  /**
364
425
  * Clear cached token
365
426
  */
366
427
  clearCacheToken() {
367
428
  this.cachedRefreshToken = undefined;
368
- this.storage.setData(CoreApp.headerTokenField, undefined);
429
+ this.storage.setPersistedData(CoreApp.headerTokenField, undefined);
369
430
  }
370
431
  /**
371
432
  * Decrypt message
@@ -881,6 +942,10 @@ export class CoreApp {
881
942
  * Device id field name
882
943
  */
883
944
  CoreApp.deviceIdField = 'SmartERPDeviceId';
945
+ /**
946
+ * Devices field name
947
+ */
948
+ CoreApp.devicesField = 'SmartERPDevices';
884
949
  /**
885
950
  * Device passphrase field name
886
951
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.2.0",
3
+ "version": "1.2.4",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -54,7 +54,7 @@
54
54
  "dependencies": {
55
55
  "@etsoo/notificationbase": "^1.0.95",
56
56
  "@etsoo/restclient": "^1.0.63",
57
- "@etsoo/shared": "^1.0.91",
57
+ "@etsoo/shared": "^1.0.94",
58
58
  "@types/crypto-js": "^4.0.2",
59
59
  "crypto-js": "^4.1.1"
60
60
  },
@@ -403,6 +403,11 @@ export interface ICoreApp<
403
403
  serviceId?: number
404
404
  ): Promise<IdLabelDto[] | undefined>;
405
405
 
406
+ /**
407
+ * Persist settings to source when application exit
408
+ */
409
+ persist(): void;
410
+
406
411
  /**
407
412
  * Switch organization
408
413
  * @param id Organization id
@@ -591,10 +596,21 @@ export abstract class CoreApp<
591
596
  /**
592
597
  * Passphrase for encryption
593
598
  */
594
- protected passphrase: string = '***';
599
+ protected passphrase: string = '';
595
600
 
596
601
  private cachedRefreshToken?: string;
597
602
 
603
+ /**
604
+ * Get persisted fields
605
+ */
606
+ protected get persistedFields() {
607
+ return [
608
+ CoreApp.deviceIdField,
609
+ CoreApp.serversideDeviceIdField,
610
+ CoreApp.headerTokenField
611
+ ];
612
+ }
613
+
598
614
  /**
599
615
  * Protected constructor
600
616
  * @param settings Settings
@@ -619,6 +635,9 @@ export abstract class CoreApp<
619
635
  // Device id
620
636
  this._deviceId = storage.getData(CoreApp.deviceIdField, '');
621
637
 
638
+ // Restore
639
+ this.restore();
640
+
622
641
  this.setApi(api);
623
642
 
624
643
  const { currentCulture, currentRegion } = settings;
@@ -630,6 +649,73 @@ export abstract class CoreApp<
630
649
  this.setup();
631
650
  }
632
651
 
652
+ private getDeviceId() {
653
+ return this.deviceId.substring(0, 10);
654
+ }
655
+
656
+ /**
657
+ * Restore settings from persisted source
658
+ */
659
+ protected restore() {
660
+ // Current device id, '' means new, or reload (not included) or duplicate (included)
661
+ if (this.deviceId) {
662
+ // Devices
663
+ const devices = this.storage.getPersistedData<string[]>(
664
+ CoreApp.devicesField
665
+ );
666
+
667
+ // Exists in the list?
668
+ if (!devices?.includes(this.getDeviceId())) {
669
+ const passphraseEncrypted = this.storage.getData<string>(
670
+ CoreApp.devicePassphraseField
671
+ );
672
+ if (passphraseEncrypted) {
673
+ const passphraseDecrypted = this.decrypt(
674
+ passphraseEncrypted,
675
+ this.name
676
+ );
677
+ if (passphraseDecrypted != null) {
678
+ this.passphrase = passphraseDecrypted;
679
+ return false;
680
+ }
681
+ }
682
+ } else {
683
+ // Remove passphrase
684
+ this.storage.setData(CoreApp.devicePassphraseField, undefined);
685
+ this.passphrase = '';
686
+ }
687
+ }
688
+
689
+ // Restore
690
+ this.storage.copyFrom(this.persistedFields, true);
691
+
692
+ return true;
693
+ }
694
+
695
+ /**
696
+ * Persist settings to source when application exit
697
+ */
698
+ persist() {
699
+ // Devices
700
+ const devices = this.storage.getPersistedData<string[]>(
701
+ CoreApp.devicesField
702
+ );
703
+ if (devices != null) {
704
+ const index = devices.indexOf(this.getDeviceId());
705
+ if (index !== -1) {
706
+ devices.splice(index, 1);
707
+ this.storage.setPersistedData(CoreApp.devicesField, devices);
708
+ }
709
+ }
710
+
711
+ if (!this.authorized) return;
712
+ this.storage.copyTo(this.persistedFields);
713
+ }
714
+
715
+ /**
716
+ * Setup Api
717
+ * @param api Api
718
+ */
633
719
  protected setApi(api: IApi) {
634
720
  // onRequest, show loading or not, rewrite the property to override default action
635
721
  api.onRequest = (data) => {
@@ -679,20 +765,9 @@ export abstract class CoreApp<
679
765
  */
680
766
  async initCall(callback?: (result: boolean) => void) {
681
767
  // Passphrase exists?
682
- // Same session should avoid multiple init calls
683
- const passphraseEncrypted = this.storage.getData<string>(
684
- CoreApp.devicePassphraseField
685
- );
686
- if (passphraseEncrypted) {
687
- const passphraseDecrypted = this.decrypt(
688
- passphraseEncrypted,
689
- this.name
690
- );
691
- if (passphraseDecrypted != null) {
692
- this.passphrase = passphraseDecrypted;
693
- if (callback) callback(true);
694
- return;
695
- }
768
+ if (this.passphrase) {
769
+ if (callback) callback(true);
770
+ return;
696
771
  }
697
772
 
698
773
  // Serverside encrypted device id
@@ -707,7 +782,7 @@ export abstract class CoreApp<
707
782
  const data: InitCallDto = {
708
783
  timestamp,
709
784
  identifier,
710
- deviceId: this.deviceId.length > 0 ? this.deviceId : undefined
785
+ deviceId: this.deviceId ? this.deviceId : undefined
711
786
  };
712
787
 
713
788
  const result = await this.apiInitCall(data);
@@ -770,6 +845,14 @@ export abstract class CoreApp<
770
845
  this._deviceId = data.deviceId;
771
846
  this.storage.setData(CoreApp.deviceIdField, this._deviceId);
772
847
 
848
+ // Devices
849
+ const devices = this.storage.getPersistedData<string[]>(
850
+ CoreApp.devicesField,
851
+ []
852
+ );
853
+ devices.push(this.getDeviceId());
854
+ this.storage.setPersistedData(CoreApp.devicesField, devices);
855
+
773
856
  // Current passphrase
774
857
  this.passphrase = passphrase;
775
858
  this.storage.setData(
@@ -884,7 +967,7 @@ export abstract class CoreApp<
884
967
  return;
885
968
 
886
969
  // Save the id to local storage
887
- this.storage.setData(DomUtils.CountryField, regionId);
970
+ this.storage.setPersistedData(DomUtils.CountryField, regionId);
888
971
 
889
972
  // Set the currency and culture
890
973
  this._currency = regionItem.currency;
@@ -906,7 +989,7 @@ export abstract class CoreApp<
906
989
  if (this._culture === name) return;
907
990
 
908
991
  // Save the cultrue to local storage
909
- this.storage.setData(DomUtils.CultureField, name);
992
+ this.storage.setPersistedData(DomUtils.CultureField, name);
910
993
 
911
994
  // Change the API's Content-Language header
912
995
  // .net 5 API, UseRequestLocalization, RequestCultureProviders, ContentLanguageHeaderRequestCultureProvider
@@ -933,12 +1016,8 @@ export abstract class CoreApp<
933
1016
  * Clear cache data
934
1017
  */
935
1018
  clearCacheData() {
936
- this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
937
-
938
- this.storage.setData(CoreApp.deviceIdField, undefined);
1019
+ this.clearCacheToken();
939
1020
  this.storage.setData(CoreApp.devicePassphraseField, undefined);
940
-
941
- this.storage.setData(CoreApp.headerTokenField, undefined);
942
1021
  }
943
1022
 
944
1023
  /**
@@ -946,7 +1025,7 @@ export abstract class CoreApp<
946
1025
  */
947
1026
  clearCacheToken() {
948
1027
  this.cachedRefreshToken = undefined;
949
- this.storage.setData(CoreApp.headerTokenField, undefined);
1028
+ this.storage.setPersistedData(CoreApp.headerTokenField, undefined);
950
1029
  }
951
1030
 
952
1031
  /**
@@ -1568,6 +1647,11 @@ export namespace CoreApp {
1568
1647
  */
1569
1648
  export const deviceIdField = 'SmartERPDeviceId';
1570
1649
 
1650
+ /**
1651
+ * Devices field name
1652
+ */
1653
+ export const devicesField = 'SmartERPDevices';
1654
+
1571
1655
  /**
1572
1656
  * Device passphrase field name
1573
1657
  */