@etsoo/appscript 1.3.99 → 1.4.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 (44) hide show
  1. package/__tests__/app/CoreApp.ts +6 -6
  2. package/lib/cjs/app/CoreApp.d.ts +10 -9
  3. package/lib/cjs/app/CoreApp.js +89 -49
  4. package/lib/cjs/app/IApp.d.ts +9 -8
  5. package/lib/cjs/erp/AuthApi.js +3 -3
  6. package/lib/cjs/i18n/en.d.ts +2 -2
  7. package/lib/cjs/i18n/en.js +3 -10
  8. package/lib/cjs/i18n/i18nResources.d.ts +3 -0
  9. package/lib/cjs/i18n/i18nResources.js +43 -0
  10. package/lib/cjs/i18n/zhHans.d.ts +2 -2
  11. package/lib/cjs/i18n/zhHans.js +3 -10
  12. package/lib/cjs/i18n/zhHant.d.ts +2 -2
  13. package/lib/cjs/i18n/zhHant.js +3 -10
  14. package/lib/cjs/index.d.ts +1 -1
  15. package/lib/cjs/index.js +2 -1
  16. package/lib/mjs/app/CoreApp.d.ts +10 -9
  17. package/lib/mjs/app/CoreApp.js +45 -28
  18. package/lib/mjs/app/IApp.d.ts +9 -8
  19. package/lib/mjs/erp/AuthApi.js +3 -3
  20. package/lib/mjs/i18n/en.d.ts +2 -2
  21. package/lib/mjs/i18n/en.js +3 -7
  22. package/lib/mjs/i18n/i18nResources.d.ts +3 -0
  23. package/lib/mjs/i18n/i18nResources.js +16 -0
  24. package/lib/mjs/i18n/zhHans.d.ts +2 -2
  25. package/lib/mjs/i18n/zhHans.js +3 -7
  26. package/lib/mjs/i18n/zhHant.d.ts +2 -2
  27. package/lib/mjs/i18n/zhHant.js +3 -7
  28. package/lib/mjs/index.d.ts +1 -1
  29. package/lib/mjs/index.js +1 -1
  30. package/package.json +5 -5
  31. package/src/app/CoreApp.ts +64 -40
  32. package/src/app/IApp.ts +19 -8
  33. package/src/erp/AuthApi.ts +3 -3
  34. package/src/i18n/en.ts +4 -8
  35. package/src/i18n/i18nResources.ts +19 -0
  36. package/src/i18n/zhHans.ts +4 -8
  37. package/src/i18n/zhHant.ts +4 -10
  38. package/src/index.ts +2 -1
  39. package/lib/cjs/i18n/en.json +0 -227
  40. package/lib/cjs/i18n/zh-Hans.json +0 -227
  41. package/lib/cjs/i18n/zh-Hant.json +0 -226
  42. package/lib/mjs/i18n/en.json +0 -227
  43. package/lib/mjs/i18n/zh-Hans.json +0 -227
  44. package/lib/mjs/i18n/zh-Hant.json +0 -226
@@ -18,17 +18,6 @@ import {
18
18
  NumberUtils,
19
19
  Utils
20
20
  } from '@etsoo/shared';
21
- import {
22
- AES,
23
- algo,
24
- enc,
25
- HmacSHA512,
26
- lib,
27
- mode,
28
- pad,
29
- PBKDF2,
30
- SHA3
31
- } from 'crypto-js';
32
21
  import { AddressRegion } from '../address/AddressRegion';
33
22
  import { BridgeUtils } from '../bridges/BridgeUtils';
34
23
  import { DataPrivacy } from '../business/DataPrivacy';
@@ -283,12 +272,9 @@ export abstract class CoreApp<
283
272
  this.setApi(api);
284
273
 
285
274
  const { currentCulture, currentRegion } = settings;
286
- this.changeCulture(currentCulture);
275
+ this.changeCulture(currentCulture, () => this.setup());
287
276
 
288
277
  this.changeRegion(currentRegion);
289
-
290
- // Setup callback
291
- this.setup();
292
278
  }
293
279
 
294
280
  private getDeviceId() {
@@ -337,7 +323,7 @@ export abstract class CoreApp<
337
323
  /**
338
324
  * Restore settings from persisted source
339
325
  */
340
- protected restore() {
326
+ protected async restore() {
341
327
  // Devices
342
328
  const devices = this.storage.getPersistedData<string[]>(
343
329
  this.fields.devices,
@@ -369,7 +355,7 @@ export abstract class CoreApp<
369
355
  );
370
356
  if (passphraseEncrypted) {
371
357
  // this.name to identifier different app's secret
372
- const passphraseDecrypted = this.decrypt(
358
+ const passphraseDecrypted = await this.decrypt(
373
359
  passphraseEncrypted,
374
360
  this.name
375
361
  );
@@ -560,7 +546,10 @@ export abstract class CoreApp<
560
546
  return;
561
547
  }
562
548
 
563
- const updateResult = this.initCallUpdate(result.data, data.timestamp);
549
+ const updateResult = await this.initCallUpdate(
550
+ result.data,
551
+ data.timestamp
552
+ );
564
553
  if (!updateResult) {
565
554
  this.notifier.alert(this.get<string>('noData')! + '(Update)');
566
555
  }
@@ -573,16 +562,19 @@ export abstract class CoreApp<
573
562
  * @param data Result data
574
563
  * @param timestamp Timestamp
575
564
  */
576
- protected initCallUpdate(
565
+ protected async initCallUpdate(
577
566
  data: InitCallResultData,
578
567
  timestamp: number
579
- ): boolean {
568
+ ): Promise<boolean> {
580
569
  // Data check
581
570
  if (data.deviceId == null || data.passphrase == null) return false;
582
571
 
583
572
  // Decrypt
584
573
  // Should be done within 120 seconds after returning from the backend
585
- const passphrase = this.decrypt(data.passphrase, timestamp.toString());
574
+ const passphrase = await this.decrypt(
575
+ data.passphrase,
576
+ timestamp.toString()
577
+ );
586
578
  if (passphrase == null) return false;
587
579
 
588
580
  // Update device id and cache it
@@ -606,7 +598,7 @@ export abstract class CoreApp<
606
598
 
607
599
  // Previous passphrase
608
600
  if (data.previousPassphrase) {
609
- const prev = this.decrypt(
601
+ const prev = await this.decrypt(
610
602
  data.previousPassphrase,
611
603
  timestamp.toString()
612
604
  );
@@ -627,13 +619,13 @@ export abstract class CoreApp<
627
619
  let newValueSource: string | undefined;
628
620
 
629
621
  if (enhanced) {
630
- newValueSource = this.decryptEnhanced(
622
+ newValueSource = await this.decryptEnhanced(
631
623
  currentValue,
632
624
  prev,
633
625
  12
634
626
  );
635
627
  } else {
636
- newValueSource = this.decrypt(currentValue, prev);
628
+ newValueSource = await this.decrypt(currentValue, prev);
637
629
  }
638
630
 
639
631
  if (newValueSource == null || newValueSource === '') {
@@ -643,8 +635,8 @@ export abstract class CoreApp<
643
635
  }
644
636
 
645
637
  const newValue = enhanced
646
- ? this.encryptEnhanced(newValueSource)
647
- : this.encrypt(newValueSource);
638
+ ? await this.encryptEnhanced(newValueSource)
639
+ : await this.encrypt(newValueSource);
648
640
 
649
641
  this.storage.setData(field, newValue);
650
642
  }
@@ -687,9 +679,12 @@ export abstract class CoreApp<
687
679
  // Token
688
680
  this.api.authorize(this.settings.authScheme, token);
689
681
 
690
- // Cover the current value
682
+ // Overwrite the current value
691
683
  if (refreshToken !== '') {
692
- if (refreshToken != null) refreshToken = this.encrypt(refreshToken);
684
+ if (refreshToken != null)
685
+ this.encrypt(refreshToken).then((result) =>
686
+ this.storage.setData(this.fields.headerToken, result)
687
+ );
693
688
  this.storage.setData(this.fields.headerToken, refreshToken);
694
689
  }
695
690
 
@@ -745,8 +740,9 @@ export abstract class CoreApp<
745
740
  /**
746
741
  * Change culture
747
742
  * @param culture New culture definition
743
+ * @param onReady On ready callback
748
744
  */
749
- changeCulture(culture: DataTypes.CultureDefinition) {
745
+ changeCulture(culture: DataTypes.CultureDefinition, onReady?: () => void) {
750
746
  // Name
751
747
  const { name } = culture;
752
748
 
@@ -766,7 +762,16 @@ export abstract class CoreApp<
766
762
  // Hold the current resources
767
763
  this.settings.currentCulture = culture;
768
764
 
769
- this.updateRegionLabel();
765
+ if (typeof culture.resources !== 'object') {
766
+ culture.resources().then((result) => {
767
+ culture.resources = result;
768
+ this.updateRegionLabel();
769
+ if (onReady) onReady();
770
+ });
771
+ } else {
772
+ this.updateRegionLabel();
773
+ if (onReady) onReady();
774
+ }
770
775
  }
771
776
 
772
777
  /**
@@ -818,11 +823,13 @@ export abstract class CoreApp<
818
823
  * @param passphrase Secret passphrase
819
824
  * @returns Pure text
820
825
  */
821
- decrypt(messageEncrypted: string, passphrase?: string) {
826
+ async decrypt(messageEncrypted: string, passphrase?: string) {
822
827
  // Iterations
823
828
  const iterations = parseInt(messageEncrypted.substring(0, 2), 10);
824
829
  if (isNaN(iterations)) return undefined;
825
830
 
831
+ const { PBKDF2, algo, enc, AES, pad, mode } = await import('crypto-js');
832
+
826
833
  try {
827
834
  const salt = enc.Hex.parse(messageEncrypted.substring(2, 34));
828
835
  const iv = enc.Hex.parse(messageEncrypted.substring(34, 66));
@@ -852,7 +859,7 @@ export abstract class CoreApp<
852
859
  * @param durationSeconds Duration seconds, <= 12 will be considered as month
853
860
  * @returns Pure text
854
861
  */
855
- decryptEnhanced(
862
+ async decryptEnhanced(
856
863
  messageEncrypted: string,
857
864
  passphrase?: string,
858
865
  durationSeconds?: number
@@ -885,7 +892,7 @@ export abstract class CoreApp<
885
892
  timestamp
886
893
  );
887
894
 
888
- return this.decrypt(message, passphrase);
895
+ return await this.decrypt(message, passphrase);
889
896
  } catch (e) {
890
897
  console.log('decryptEnhanced', e);
891
898
  return undefined;
@@ -939,10 +946,14 @@ export abstract class CoreApp<
939
946
  * @param iterations Iterations, 1000 times, 1 - 99
940
947
  * @returns Result
941
948
  */
942
- encrypt(message: string, passphrase?: string, iterations?: number) {
949
+ async encrypt(message: string, passphrase?: string, iterations?: number) {
943
950
  // Default 1 * 1000
944
951
  iterations ??= 1;
945
952
 
953
+ const { lib, PBKDF2, algo, enc, AES, pad, mode } = await import(
954
+ 'crypto-js'
955
+ );
956
+
946
957
  const bits = 16; // 128 / 8
947
958
  const salt = lib.WordArray.random(bits);
948
959
  const key = PBKDF2(passphrase ?? this.passphrase, salt, {
@@ -971,7 +982,11 @@ export abstract class CoreApp<
971
982
  * @param iterations Iterations, 1000 times, 1 - 99
972
983
  * @returns Result
973
984
  */
974
- encryptEnhanced(message: string, passphrase?: string, iterations?: number) {
985
+ async encryptEnhanced(
986
+ message: string,
987
+ passphrase?: string,
988
+ iterations?: number
989
+ ) {
975
990
  // Timestamp
976
991
  const timestamp = Utils.numberToChars(new Date().getTime());
977
992
 
@@ -980,7 +995,9 @@ export abstract class CoreApp<
980
995
  timestamp
981
996
  );
982
997
 
983
- return timestamp + '!' + this.encrypt(message, passphrase, iterations);
998
+ const result = await this.encrypt(message, passphrase, iterations);
999
+
1000
+ return timestamp + '!' + result;
984
1001
  }
985
1002
 
986
1003
  /**
@@ -1176,7 +1193,10 @@ export abstract class CoreApp<
1176
1193
  * @returns Resource
1177
1194
  */
1178
1195
  get<T = string>(key: string): T | undefined {
1179
- const value = this.settings.currentCulture.resources[key];
1196
+ // Make sure the resource files are loaded first
1197
+ const resources = this.settings.currentCulture.resources;
1198
+ const value =
1199
+ typeof resources === 'object' ? resources[key] : undefined;
1180
1200
  if (value == null) return undefined;
1181
1201
 
1182
1202
  // No strict type convertion here
@@ -1376,7 +1396,8 @@ export abstract class CoreApp<
1376
1396
  * @param message Message
1377
1397
  * @param passphrase Secret passphrase
1378
1398
  */
1379
- hash(message: string, passphrase?: string) {
1399
+ async hash(message: string, passphrase?: string) {
1400
+ const { SHA3, enc, HmacSHA512 } = await import('crypto-js');
1380
1401
  if (passphrase == null)
1381
1402
  return SHA3(message, { outputLength: 512 }).toString(enc.Base64);
1382
1403
  else return HmacSHA512(message, passphrase).toString(enc.Base64);
@@ -1388,7 +1409,8 @@ export abstract class CoreApp<
1388
1409
  * @param message Message
1389
1410
  * @param passphrase Secret passphrase
1390
1411
  */
1391
- hashHex(message: string, passphrase?: string) {
1412
+ async hashHex(message: string, passphrase?: string) {
1413
+ const { SHA3, enc, HmacSHA512 } = await import('crypto-js');
1392
1414
  if (passphrase == null)
1393
1415
  return SHA3(message, { outputLength: 512 }).toString(enc.Hex);
1394
1416
  else return HmacSHA512(message, passphrase).toString(enc.Hex);
@@ -1585,7 +1607,9 @@ export abstract class CoreApp<
1585
1607
  if (keep) {
1586
1608
  this.authorize(user.token, refreshToken);
1587
1609
  } else {
1588
- this.cachedRefreshToken = this.encrypt(refreshToken);
1610
+ this.encrypt(refreshToken).then(
1611
+ (result) => (this.cachedRefreshToken = result)
1612
+ );
1589
1613
  this.authorize(user.token, undefined);
1590
1614
  }
1591
1615
  }
package/src/app/IApp.ts CHANGED
@@ -85,7 +85,7 @@ export const appFields = [
85
85
  /**
86
86
  * Basic type template
87
87
  */
88
- export type IAppFields = { [key in typeof appFields[number]]: string };
88
+ export type IAppFields = { [key in (typeof appFields)[number]]: string };
89
89
 
90
90
  /**
91
91
  * Application interface, for generic version, see ICoreApp
@@ -214,8 +214,12 @@ export interface IApp {
214
214
  /**
215
215
  * Change culture
216
216
  * @param culture New culture definition
217
+ * @param onReady On ready callback
217
218
  */
218
- changeCulture(culture: DataTypes.CultureDefinition): void;
219
+ changeCulture(
220
+ culture: DataTypes.CultureDefinition,
221
+ onReady?: () => void
222
+ ): void;
219
223
 
220
224
  /**
221
225
  * Check the action result is about device invalid
@@ -247,7 +251,10 @@ export interface IApp {
247
251
  * @param passphrase Secret passphrase
248
252
  * @returns Pure text
249
253
  */
250
- decrypt(messageEncrypted: string, passphrase?: string): string | undefined;
254
+ decrypt(
255
+ messageEncrypted: string,
256
+ passphrase?: string
257
+ ): Promise<string | undefined>;
251
258
 
252
259
  /**
253
260
  * Enhanced decrypt message
@@ -260,7 +267,7 @@ export interface IApp {
260
267
  messageEncrypted: string,
261
268
  passphrase?: string,
262
269
  durationSeconds?: number
263
- ): string | undefined;
270
+ ): Promise<string | undefined>;
264
271
 
265
272
  /**
266
273
  * Detect IP data, call only one time
@@ -275,7 +282,11 @@ export interface IApp {
275
282
  * @param iterations Iterations, 1000 times, 1 - 99
276
283
  * @returns Result
277
284
  */
278
- encrypt(message: string, passphrase?: string, iterations?: number): string;
285
+ encrypt(
286
+ message: string,
287
+ passphrase?: string,
288
+ iterations?: number
289
+ ): Promise<string>;
279
290
 
280
291
  /**
281
292
  * Enhanced encrypt message
@@ -288,7 +299,7 @@ export interface IApp {
288
299
  message: string,
289
300
  passphrase?: string,
290
301
  iterations?: number
291
- ): string;
302
+ ): Promise<string>;
292
303
 
293
304
  /**
294
305
  * Format date to string
@@ -493,7 +504,7 @@ export interface IApp {
493
504
  * @param message Message
494
505
  * @param passphrase Secret passphrase
495
506
  */
496
- hash(message: string, passphrase?: string): string;
507
+ hash(message: string, passphrase?: string): Promise<string>;
497
508
 
498
509
  /**
499
510
  * Hash message Hex, SHA3 or HmacSHA512, 512 as Base64
@@ -501,7 +512,7 @@ export interface IApp {
501
512
  * @param message Message
502
513
  * @param passphrase Secret passphrase
503
514
  */
504
- hashHex(message: string, passphrase?: string): string;
515
+ hashHex(message: string, passphrase?: string): Promise<string>;
505
516
 
506
517
  /**
507
518
  * Check use has the specific role permission or not
@@ -35,15 +35,15 @@ export class AuthApi extends BaseApi {
35
35
  * @param payload Payload
36
36
  * @returns Result
37
37
  */
38
- loginId(id: string, payload?: ResultPayload) {
38
+ async loginId(id: string, payload?: ResultPayload) {
39
39
  const { deviceId, region } = this.app;
40
- id = this.app.encrypt(id);
40
+ id = await this.app.encrypt(id);
41
41
  const rq: LoginIdRQ = {
42
42
  id,
43
43
  deviceId,
44
44
  region
45
45
  };
46
- return this.api.get('Auth/LoginId', rq, payload);
46
+ return await this.api.get('Auth/LoginId', rq, payload);
47
47
  }
48
48
 
49
49
  /**
package/src/i18n/en.ts CHANGED
@@ -1,14 +1,10 @@
1
- import { DataTypes } from '@etsoo/shared';
2
- import enResources from './en.json';
1
+ import { DomUtils } from '@etsoo/shared';
2
+ import { i18nResource, i18nResourceCreator } from './i18nResources';
3
3
 
4
4
  /**
5
5
  * Get en neutral culture
6
6
  * @param localResources Local resources
7
7
  * @returns Full culture
8
8
  */
9
- export const en = (localResources: object): DataTypes.CultureDefinition => ({
10
- name: 'en',
11
- label: 'English',
12
- resources: { ...enResources, ...localResources },
13
- compatibleNames: []
14
- });
9
+ export const en = (resources: i18nResource) =>
10
+ DomUtils.en(i18nResourceCreator('./en.json', resources));
@@ -0,0 +1,19 @@
1
+ import { DataTypes } from '@etsoo/shared';
2
+
3
+ export type i18nResource = object | (() => Promise<object>);
4
+
5
+ export function i18nResourceCreator(file: string, resources: i18nResource) {
6
+ return async () => {
7
+ const [r1, r2] = await Promise.all([
8
+ import(file),
9
+ new Promise<object>((resolve) => {
10
+ if (typeof resources === 'object') {
11
+ resolve(resources);
12
+ } else {
13
+ resources().then((result) => resolve(result));
14
+ }
15
+ })
16
+ ]);
17
+ return { ...r1, ...r2 } as DataTypes.StringRecord;
18
+ };
19
+ }
@@ -1,14 +1,10 @@
1
- import { DataTypes } from '@etsoo/shared';
2
- import zhHansResources from './zh-Hans.json';
1
+ import { DomUtils } from '@etsoo/shared';
2
+ import { i18nResource, i18nResourceCreator } from './i18nResources';
3
3
 
4
4
  /**
5
5
  * Get zh-Hans neutral cultrue
6
6
  * @param localResources Local resources
7
7
  * @returns Full culture
8
8
  */
9
- export const zhHans = (localResources: {}): DataTypes.CultureDefinition => ({
10
- name: 'zh-Hans',
11
- label: '简体中文',
12
- resources: { ...zhHansResources, ...localResources },
13
- compatibleNames: ['zh-CN', 'zh-SG']
14
- });
9
+ export const zhHans = (resources: i18nResource) =>
10
+ DomUtils.en(i18nResourceCreator('./zh-Hans.json', resources));
@@ -1,16 +1,10 @@
1
- import { DataTypes } from '@etsoo/shared';
2
- import zhHantResources from './zh-Hant.json';
1
+ import { DomUtils } from '@etsoo/shared';
2
+ import { i18nResource, i18nResourceCreator } from './i18nResources';
3
3
 
4
4
  /**
5
5
  * Get zh-Hant neutral cultrue
6
6
  * @param localResources Local resources
7
7
  * @returns Full culture
8
8
  */
9
- export const zhHant = (
10
- localResources: object
11
- ): DataTypes.CultureDefinition => ({
12
- name: 'zh-Hant',
13
- label: '繁體中文',
14
- resources: { ...zhHantResources, ...localResources },
15
- compatibleNames: ['zh-HK', 'zh-TW', 'zh-MO']
16
- });
9
+ export const zhHant = (resources: i18nResource) =>
10
+ DomUtils.en(i18nResourceCreator('./zh-Hant.json', resources));
package/src/index.ts CHANGED
@@ -86,7 +86,8 @@ export {
86
86
  ApiAuthorizationScheme,
87
87
  ApiMethod,
88
88
  ApiResponseType,
89
- createClient
89
+ createClient,
90
+ createClientAsync
90
91
  } from '@etsoo/restclient';
91
92
  export type { IApi, IApiPayload } from '@etsoo/restclient';
92
93