@etsoo/appscript 1.5.21 → 1.5.23

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.
@@ -135,6 +135,8 @@ class CoreAppTest extends CoreApp<
135
135
  new WindowStorage(),
136
136
  'SmartERP'
137
137
  );
138
+
139
+ this.deviceId = 'abcd1234';
138
140
  }
139
141
 
140
142
  freshCountdownUI(callback?: () => PromiseLike<unknown>): void {
@@ -90,6 +90,7 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
90
90
  * Device id, randome string from ServiceBase.InitCallAsync
91
91
  */
92
92
  get deviceId(): string;
93
+ protected set deviceId(value: string);
93
94
  /**
94
95
  * Label delegate
95
96
  */
@@ -123,6 +124,11 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
123
124
  */
124
125
  get isReady(): boolean;
125
126
  private set isReady(value);
127
+ /**
128
+ * Current cached URL
129
+ */
130
+ get cachedUrl(): string | undefined | null;
131
+ set cachedUrl(value: string | undefined | null);
126
132
  private _isTryingLogin;
127
133
  /**
128
134
  * Last called with token refresh
@@ -246,6 +252,11 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
246
252
  * @returns Result
247
253
  */
248
254
  initCall(callback?: (result: boolean) => void, resetKeys?: boolean): Promise<void>;
255
+ /**
256
+ * Update passphrase
257
+ * @param passphrase Secret passphrase
258
+ */
259
+ protected updatePassphrase(passphrase: string): void;
249
260
  /**
250
261
  * Init call update
251
262
  * @param data Result data
@@ -39,8 +39,14 @@ class CoreApp {
39
39
  * Device id, randome string from ServiceBase.InitCallAsync
40
40
  */
41
41
  get deviceId() {
42
+ if (this._deviceId === '') {
43
+ throw new Error('Device id is empty');
44
+ }
42
45
  return this._deviceId;
43
46
  }
47
+ set deviceId(value) {
48
+ this._deviceId = value;
49
+ }
44
50
  /**
45
51
  * Label delegate
46
52
  */
@@ -83,6 +89,15 @@ class CoreApp {
83
89
  set isReady(value) {
84
90
  this._isReady = value;
85
91
  }
92
+ /**
93
+ * Current cached URL
94
+ */
95
+ get cachedUrl() {
96
+ return this.storage.getData(this.fields.cachedUrl);
97
+ }
98
+ set cachedUrl(value) {
99
+ this.storage.setData(this.fields.cachedUrl, value);
100
+ }
86
101
  /**
87
102
  * Get persisted fields
88
103
  */
@@ -520,33 +535,16 @@ class CoreApp {
520
535
  callback(updateResult);
521
536
  }
522
537
  /**
523
- * Init call update
524
- * @param data Result data
525
- * @param timestamp Timestamp
538
+ * Update passphrase
539
+ * @param passphrase Secret passphrase
526
540
  */
527
- async initCallUpdate(data, timestamp) {
528
- // Data check
529
- if (data.deviceId == null || data.passphrase == null)
530
- return false;
531
- // Decrypt
532
- // Should be done within 120 seconds after returning from the backend
533
- const passphrase = this.decrypt(data.passphrase, timestamp.toString());
534
- if (passphrase == null)
535
- return false;
536
- // Update device id and cache it
537
- this._deviceId = data.deviceId;
538
- this.storage.setData(this.fields.deviceId, this._deviceId);
539
- // Devices
540
- const devices = this.storage.getPersistedData(this.fields.devices, []);
541
- devices.push(this.getDeviceId());
542
- this.storage.setPersistedData(this.fields.devices, devices);
543
- // Current passphrase
541
+ updatePassphrase(passphrase) {
542
+ // Previous passphrase
543
+ const prev = this.passphrase;
544
+ // Update
544
545
  this.passphrase = passphrase;
545
546
  this.storage.setData(this.fields.devicePassphrase, this.encrypt(passphrase, this.name));
546
- // Previous passphrase
547
- if (data.previousPassphrase) {
548
- const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
549
- // Update
547
+ if (prev) {
550
548
  const fields = this.initCallEncryptedUpdateFields();
551
549
  for (const field of fields) {
552
550
  const currentValue = this.storage.getData(field);
@@ -576,6 +574,35 @@ class CoreApp {
576
574
  this.storage.setData(field, newValue);
577
575
  }
578
576
  }
577
+ }
578
+ /**
579
+ * Init call update
580
+ * @param data Result data
581
+ * @param timestamp Timestamp
582
+ */
583
+ async initCallUpdate(data, timestamp) {
584
+ // Data check
585
+ if (data.deviceId == null || data.passphrase == null)
586
+ return false;
587
+ // Decrypt
588
+ // Should be done within 120 seconds after returning from the backend
589
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
590
+ if (passphrase == null)
591
+ return false;
592
+ // Update device id and cache it
593
+ this._deviceId = data.deviceId;
594
+ this.storage.setData(this.fields.deviceId, this._deviceId);
595
+ // Devices
596
+ const devices = this.storage.getPersistedData(this.fields.devices, []);
597
+ devices.push(this.getDeviceId());
598
+ this.storage.setPersistedData(this.fields.devices, devices);
599
+ // Previous passphrase
600
+ if (data.previousPassphrase) {
601
+ const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
602
+ this.passphrase = prev ?? '';
603
+ }
604
+ // Update passphrase
605
+ this.updatePassphrase(passphrase);
579
606
  return true;
580
607
  }
581
608
  /**
@@ -1525,8 +1552,9 @@ class CoreApp {
1525
1552
  * @param removeUrl Remove current URL for reuse
1526
1553
  */
1527
1554
  toLoginPage(tryLogin, removeUrl) {
1528
- const url = `/?tryLogin=${tryLogin ?? false}` +
1529
- (removeUrl ? '' : '&url=' + encodeURIComponent(location.href));
1555
+ // Save the current URL
1556
+ this.cachedUrl = removeUrl ? undefined : globalThis.location.href;
1557
+ const url = `/?tryLogin=${tryLogin ?? false}`;
1530
1558
  this.navigate(url);
1531
1559
  }
1532
1560
  /**
@@ -55,7 +55,7 @@ export interface RefreshTokenProps {
55
55
  /**
56
56
  * App fields
57
57
  */
58
- export declare const appFields: readonly ["headerToken", "serversideDeviceId", "deviceId", "devices", "devicePassphrase"];
58
+ export declare const appFields: readonly ["headerToken", "serversideDeviceId", "deviceId", "devices", "devicePassphrase", "cachedUrl"];
59
59
  /**
60
60
  * Basic type template
61
61
  */
@@ -130,6 +130,10 @@ export interface IApp {
130
130
  * Is debug mode
131
131
  */
132
132
  readonly debug: boolean;
133
+ /**
134
+ * Cached URL
135
+ */
136
+ cachedUrl: string | undefined | null;
133
137
  /**
134
138
  * IP data
135
139
  */
@@ -9,5 +9,6 @@ exports.appFields = [
9
9
  'serversideDeviceId',
10
10
  'deviceId',
11
11
  'devices',
12
- 'devicePassphrase'
12
+ 'devicePassphrase',
13
+ 'cachedUrl'
13
14
  ];
@@ -90,6 +90,7 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
90
90
  * Device id, randome string from ServiceBase.InitCallAsync
91
91
  */
92
92
  get deviceId(): string;
93
+ protected set deviceId(value: string);
93
94
  /**
94
95
  * Label delegate
95
96
  */
@@ -123,6 +124,11 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
123
124
  */
124
125
  get isReady(): boolean;
125
126
  private set isReady(value);
127
+ /**
128
+ * Current cached URL
129
+ */
130
+ get cachedUrl(): string | undefined | null;
131
+ set cachedUrl(value: string | undefined | null);
126
132
  private _isTryingLogin;
127
133
  /**
128
134
  * Last called with token refresh
@@ -246,6 +252,11 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
246
252
  * @returns Result
247
253
  */
248
254
  initCall(callback?: (result: boolean) => void, resetKeys?: boolean): Promise<void>;
255
+ /**
256
+ * Update passphrase
257
+ * @param passphrase Secret passphrase
258
+ */
259
+ protected updatePassphrase(passphrase: string): void;
249
260
  /**
250
261
  * Init call update
251
262
  * @param data Result data
@@ -36,8 +36,14 @@ export class CoreApp {
36
36
  * Device id, randome string from ServiceBase.InitCallAsync
37
37
  */
38
38
  get deviceId() {
39
+ if (this._deviceId === '') {
40
+ throw new Error('Device id is empty');
41
+ }
39
42
  return this._deviceId;
40
43
  }
44
+ set deviceId(value) {
45
+ this._deviceId = value;
46
+ }
41
47
  /**
42
48
  * Label delegate
43
49
  */
@@ -80,6 +86,15 @@ export class CoreApp {
80
86
  set isReady(value) {
81
87
  this._isReady = value;
82
88
  }
89
+ /**
90
+ * Current cached URL
91
+ */
92
+ get cachedUrl() {
93
+ return this.storage.getData(this.fields.cachedUrl);
94
+ }
95
+ set cachedUrl(value) {
96
+ this.storage.setData(this.fields.cachedUrl, value);
97
+ }
83
98
  /**
84
99
  * Get persisted fields
85
100
  */
@@ -517,33 +532,16 @@ export class CoreApp {
517
532
  callback(updateResult);
518
533
  }
519
534
  /**
520
- * Init call update
521
- * @param data Result data
522
- * @param timestamp Timestamp
535
+ * Update passphrase
536
+ * @param passphrase Secret passphrase
523
537
  */
524
- async initCallUpdate(data, timestamp) {
525
- // Data check
526
- if (data.deviceId == null || data.passphrase == null)
527
- return false;
528
- // Decrypt
529
- // Should be done within 120 seconds after returning from the backend
530
- const passphrase = this.decrypt(data.passphrase, timestamp.toString());
531
- if (passphrase == null)
532
- return false;
533
- // Update device id and cache it
534
- this._deviceId = data.deviceId;
535
- this.storage.setData(this.fields.deviceId, this._deviceId);
536
- // Devices
537
- const devices = this.storage.getPersistedData(this.fields.devices, []);
538
- devices.push(this.getDeviceId());
539
- this.storage.setPersistedData(this.fields.devices, devices);
540
- // Current passphrase
538
+ updatePassphrase(passphrase) {
539
+ // Previous passphrase
540
+ const prev = this.passphrase;
541
+ // Update
541
542
  this.passphrase = passphrase;
542
543
  this.storage.setData(this.fields.devicePassphrase, this.encrypt(passphrase, this.name));
543
- // Previous passphrase
544
- if (data.previousPassphrase) {
545
- const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
546
- // Update
544
+ if (prev) {
547
545
  const fields = this.initCallEncryptedUpdateFields();
548
546
  for (const field of fields) {
549
547
  const currentValue = this.storage.getData(field);
@@ -573,6 +571,35 @@ export class CoreApp {
573
571
  this.storage.setData(field, newValue);
574
572
  }
575
573
  }
574
+ }
575
+ /**
576
+ * Init call update
577
+ * @param data Result data
578
+ * @param timestamp Timestamp
579
+ */
580
+ async initCallUpdate(data, timestamp) {
581
+ // Data check
582
+ if (data.deviceId == null || data.passphrase == null)
583
+ return false;
584
+ // Decrypt
585
+ // Should be done within 120 seconds after returning from the backend
586
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
587
+ if (passphrase == null)
588
+ return false;
589
+ // Update device id and cache it
590
+ this._deviceId = data.deviceId;
591
+ this.storage.setData(this.fields.deviceId, this._deviceId);
592
+ // Devices
593
+ const devices = this.storage.getPersistedData(this.fields.devices, []);
594
+ devices.push(this.getDeviceId());
595
+ this.storage.setPersistedData(this.fields.devices, devices);
596
+ // Previous passphrase
597
+ if (data.previousPassphrase) {
598
+ const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
599
+ this.passphrase = prev ?? '';
600
+ }
601
+ // Update passphrase
602
+ this.updatePassphrase(passphrase);
576
603
  return true;
577
604
  }
578
605
  /**
@@ -1522,8 +1549,9 @@ export class CoreApp {
1522
1549
  * @param removeUrl Remove current URL for reuse
1523
1550
  */
1524
1551
  toLoginPage(tryLogin, removeUrl) {
1525
- const url = `/?tryLogin=${tryLogin ?? false}` +
1526
- (removeUrl ? '' : '&url=' + encodeURIComponent(location.href));
1552
+ // Save the current URL
1553
+ this.cachedUrl = removeUrl ? undefined : globalThis.location.href;
1554
+ const url = `/?tryLogin=${tryLogin ?? false}`;
1527
1555
  this.navigate(url);
1528
1556
  }
1529
1557
  /**
@@ -55,7 +55,7 @@ export interface RefreshTokenProps {
55
55
  /**
56
56
  * App fields
57
57
  */
58
- export declare const appFields: readonly ["headerToken", "serversideDeviceId", "deviceId", "devices", "devicePassphrase"];
58
+ export declare const appFields: readonly ["headerToken", "serversideDeviceId", "deviceId", "devices", "devicePassphrase", "cachedUrl"];
59
59
  /**
60
60
  * Basic type template
61
61
  */
@@ -130,6 +130,10 @@ export interface IApp {
130
130
  * Is debug mode
131
131
  */
132
132
  readonly debug: boolean;
133
+ /**
134
+ * Cached URL
135
+ */
136
+ cachedUrl: string | undefined | null;
133
137
  /**
134
138
  * IP data
135
139
  */
@@ -6,5 +6,6 @@ export const appFields = [
6
6
  'serversideDeviceId',
7
7
  'deviceId',
8
8
  'devices',
9
- 'devicePassphrase'
9
+ 'devicePassphrase',
10
+ 'cachedUrl'
10
11
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.5.21",
3
+ "version": "1.5.23",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -170,8 +170,14 @@ export abstract class CoreApp<
170
170
  * Device id, randome string from ServiceBase.InitCallAsync
171
171
  */
172
172
  get deviceId() {
173
+ if (this._deviceId === '') {
174
+ throw new Error('Device id is empty');
175
+ }
173
176
  return this._deviceId;
174
177
  }
178
+ protected set deviceId(value: string) {
179
+ this._deviceId = value;
180
+ }
175
181
 
176
182
  /**
177
183
  * Label delegate
@@ -234,6 +240,16 @@ export abstract class CoreApp<
234
240
  this._isReady = value;
235
241
  }
236
242
 
243
+ /**
244
+ * Current cached URL
245
+ */
246
+ get cachedUrl() {
247
+ return this.storage.getData(this.fields.cachedUrl);
248
+ }
249
+ set cachedUrl(value: string | undefined | null) {
250
+ this.storage.setData(this.fields.cachedUrl, value);
251
+ }
252
+
237
253
  private _isTryingLogin = false;
238
254
 
239
255
  /**
@@ -827,49 +843,21 @@ export abstract class CoreApp<
827
843
  }
828
844
 
829
845
  /**
830
- * Init call update
831
- * @param data Result data
832
- * @param timestamp Timestamp
846
+ * Update passphrase
847
+ * @param passphrase Secret passphrase
833
848
  */
834
- protected async initCallUpdate(
835
- data: InitCallResultData,
836
- timestamp: number
837
- ): Promise<boolean> {
838
- // Data check
839
- if (data.deviceId == null || data.passphrase == null) return false;
840
-
841
- // Decrypt
842
- // Should be done within 120 seconds after returning from the backend
843
- const passphrase = this.decrypt(data.passphrase, timestamp.toString());
844
- if (passphrase == null) return false;
845
-
846
- // Update device id and cache it
847
- this._deviceId = data.deviceId;
848
- this.storage.setData(this.fields.deviceId, this._deviceId);
849
-
850
- // Devices
851
- const devices = this.storage.getPersistedData<string[]>(
852
- this.fields.devices,
853
- []
854
- );
855
- devices.push(this.getDeviceId());
856
- this.storage.setPersistedData(this.fields.devices, devices);
849
+ protected updatePassphrase(passphrase: string) {
850
+ // Previous passphrase
851
+ const prev = this.passphrase;
857
852
 
858
- // Current passphrase
853
+ // Update
859
854
  this.passphrase = passphrase;
860
855
  this.storage.setData(
861
856
  this.fields.devicePassphrase,
862
857
  this.encrypt(passphrase, this.name)
863
858
  );
864
859
 
865
- // Previous passphrase
866
- if (data.previousPassphrase) {
867
- const prev = this.decrypt(
868
- data.previousPassphrase,
869
- timestamp.toString()
870
- );
871
-
872
- // Update
860
+ if (prev) {
873
861
  const fields = this.initCallEncryptedUpdateFields();
874
862
  for (const field of fields) {
875
863
  const currentValue = this.storage.getData<string>(field);
@@ -907,6 +895,48 @@ export abstract class CoreApp<
907
895
  this.storage.setData(field, newValue);
908
896
  }
909
897
  }
898
+ }
899
+
900
+ /**
901
+ * Init call update
902
+ * @param data Result data
903
+ * @param timestamp Timestamp
904
+ */
905
+ protected async initCallUpdate(
906
+ data: InitCallResultData,
907
+ timestamp: number
908
+ ): Promise<boolean> {
909
+ // Data check
910
+ if (data.deviceId == null || data.passphrase == null) return false;
911
+
912
+ // Decrypt
913
+ // Should be done within 120 seconds after returning from the backend
914
+ const passphrase = this.decrypt(data.passphrase, timestamp.toString());
915
+ if (passphrase == null) return false;
916
+
917
+ // Update device id and cache it
918
+ this._deviceId = data.deviceId;
919
+ this.storage.setData(this.fields.deviceId, this._deviceId);
920
+
921
+ // Devices
922
+ const devices = this.storage.getPersistedData<string[]>(
923
+ this.fields.devices,
924
+ []
925
+ );
926
+ devices.push(this.getDeviceId());
927
+ this.storage.setPersistedData(this.fields.devices, devices);
928
+
929
+ // Previous passphrase
930
+ if (data.previousPassphrase) {
931
+ const prev = this.decrypt(
932
+ data.previousPassphrase,
933
+ timestamp.toString()
934
+ );
935
+ this.passphrase = prev ?? '';
936
+ }
937
+
938
+ // Update passphrase
939
+ this.updatePassphrase(passphrase);
910
940
 
911
941
  return true;
912
942
  }
@@ -2102,9 +2132,10 @@ export abstract class CoreApp<
2102
2132
  * @param removeUrl Remove current URL for reuse
2103
2133
  */
2104
2134
  toLoginPage(tryLogin?: boolean, removeUrl?: boolean) {
2105
- const url =
2106
- `/?tryLogin=${tryLogin ?? false}` +
2107
- (removeUrl ? '' : '&url=' + encodeURIComponent(location.href));
2135
+ // Save the current URL
2136
+ this.cachedUrl = removeUrl ? undefined : globalThis.location.href;
2137
+
2138
+ const url = `/?tryLogin=${tryLogin ?? false}`;
2108
2139
 
2109
2140
  this.navigate(url);
2110
2141
  }
package/src/app/IApp.ts CHANGED
@@ -89,7 +89,8 @@ export const appFields = [
89
89
  'serversideDeviceId',
90
90
  'deviceId',
91
91
  'devices',
92
- 'devicePassphrase'
92
+ 'devicePassphrase',
93
+ 'cachedUrl'
93
94
  ] as const;
94
95
 
95
96
  /**
@@ -181,6 +182,11 @@ export interface IApp {
181
182
  */
182
183
  readonly debug: boolean;
183
184
 
185
+ /**
186
+ * Cached URL
187
+ */
188
+ cachedUrl: string | undefined | null;
189
+
184
190
  /**
185
191
  * IP data
186
192
  */