@etsoo/appscript 1.1.3 → 1.1.7

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 (43) hide show
  1. package/.github/workflows/main.yml +1 -1
  2. package/README.md +63 -13
  3. package/lib/cjs/address/AddressUtils.d.ts +1 -1
  4. package/lib/cjs/address/AddressUtils.js +7 -10
  5. package/lib/cjs/app/AppSettings.d.ts +1 -1
  6. package/lib/cjs/app/CoreApp.d.ts +21 -6
  7. package/lib/cjs/app/CoreApp.js +32 -6
  8. package/lib/cjs/app/ExternalSettings.d.ts +1 -1
  9. package/lib/cjs/business/BusinessTax.d.ts +66 -0
  10. package/lib/cjs/business/BusinessTax.js +61 -0
  11. package/lib/cjs/business/BusinessUtils.js +2 -3
  12. package/lib/cjs/dto/IdDto.d.ts +1 -1
  13. package/lib/cjs/dto/IdLabelDto.d.ts +1 -1
  14. package/lib/cjs/dto/UpdateDto.d.ts +1 -1
  15. package/lib/cjs/index.d.ts +1 -0
  16. package/lib/cjs/index.js +1 -0
  17. package/lib/mjs/address/AddressUtils.d.ts +1 -1
  18. package/lib/mjs/address/AddressUtils.js +8 -11
  19. package/lib/mjs/app/AppSettings.d.ts +1 -1
  20. package/lib/mjs/app/CoreApp.d.ts +21 -6
  21. package/lib/mjs/app/CoreApp.js +32 -6
  22. package/lib/mjs/app/ExternalSettings.d.ts +1 -1
  23. package/lib/mjs/business/BusinessTax.d.ts +66 -0
  24. package/lib/mjs/business/BusinessTax.js +57 -0
  25. package/lib/mjs/business/BusinessUtils.js +3 -4
  26. package/lib/mjs/dto/IdDto.d.ts +1 -1
  27. package/lib/mjs/dto/IdLabelDto.d.ts +1 -1
  28. package/lib/mjs/dto/UpdateDto.d.ts +1 -1
  29. package/lib/mjs/index.d.ts +1 -0
  30. package/lib/mjs/index.js +1 -0
  31. package/package.json +14 -14
  32. package/src/address/AddressUtils.ts +3 -3
  33. package/src/app/AppSettings.ts +1 -1
  34. package/src/app/CoreApp.ts +44 -7
  35. package/src/app/ExternalSettings.ts +1 -1
  36. package/src/business/BusinessTax.ts +86 -0
  37. package/src/business/BusinessUtils.ts +2 -2
  38. package/src/dto/IdDto.ts +1 -1
  39. package/src/dto/IdLabelDto.ts +1 -1
  40. package/src/dto/UpdateDto.ts +1 -1
  41. package/src/index.ts +1 -0
  42. package/tsconfig.cjs.json +1 -1
  43. package/tsconfig.json +1 -1
@@ -30,7 +30,7 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
30
30
  /**
31
31
  * Label delegate
32
32
  */
33
- readonly labelDelegate: <T extends DataTypes.SimpleType = string>(key: string) => T | undefined;
33
+ readonly labelDelegate: <T = string>(key: string) => T | undefined;
34
34
  /**
35
35
  * Culture, like zh-CN
36
36
  */
@@ -43,6 +43,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
43
43
  * Country or region, like CN
44
44
  */
45
45
  readonly region: string;
46
+ /**
47
+ * Is current authorized
48
+ */
49
+ readonly authorized: boolean;
46
50
  /**
47
51
  * IP data
48
52
  */
@@ -110,7 +114,7 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
110
114
  * @param key key
111
115
  * @returns Resource
112
116
  */
113
- get<T extends DataTypes.SimpleType = string>(key: string): T | undefined;
117
+ get<T = string>(key: string): T | undefined;
114
118
  /**
115
119
  * Get multiple culture labels
116
120
  * @param keys Keys
@@ -149,6 +153,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
149
153
  * @returns Transformed url
150
154
  */
151
155
  transformUrl(url: string): string;
156
+ /**
157
+ * Try login, returning false means is loading
158
+ */
159
+ tryLogin(): boolean;
152
160
  /**
153
161
  * User login
154
162
  * @param user User data
@@ -195,7 +203,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
195
203
  /**
196
204
  * Label delegate
197
205
  */
198
- get labelDelegate(): <T extends DataTypes.SimpleType = string>(key: string) => T | undefined;
206
+ get labelDelegate(): <T = string>(key: string) => T | undefined;
199
207
  /**
200
208
  * IP data
201
209
  */
@@ -213,6 +221,13 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
213
221
  * Search input element
214
222
  */
215
223
  searchInput?: HTMLInputElement;
224
+ private _authorized;
225
+ /**
226
+ * Is current authorized
227
+ */
228
+ get authorized(): boolean;
229
+ private set authorized(value);
230
+ private _isTryingLogin;
216
231
  /**
217
232
  * Protected constructor
218
233
  * @param settings Settings
@@ -282,7 +297,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
282
297
  * @param key key
283
298
  * @returns Resource
284
299
  */
285
- get<T extends DataTypes.SimpleType = string>(key: string): T | undefined;
300
+ get<T = string>(key: string): T | undefined;
286
301
  /**
287
302
  * Get multiple culture labels
288
303
  * @param keys Keys
@@ -326,9 +341,9 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
326
341
  */
327
342
  transformUrl(url: string): string;
328
343
  /**
329
- * Try login
344
+ * Try login, returning false means is loading
330
345
  */
331
- abstract tryLogin(): void;
346
+ tryLogin(): boolean;
332
347
  /**
333
348
  * User login
334
349
  * @param user User data
@@ -16,6 +16,8 @@ export class CoreApp {
16
16
  * Response token header field name
17
17
  */
18
18
  this.headerTokenField = 'SmartERPRefreshToken';
19
+ this._authorized = false;
20
+ this._isTryingLogin = false;
19
21
  // onRequest, show loading or not, rewrite the property to override default action
20
22
  api.onRequest = (data) => {
21
23
  if (data.showLoading == null || data.showLoading) {
@@ -76,6 +78,15 @@ export class CoreApp {
76
78
  get labelDelegate() {
77
79
  return this.get.bind(this);
78
80
  }
81
+ /**
82
+ * Is current authorized
83
+ */
84
+ get authorized() {
85
+ return this._authorized;
86
+ }
87
+ set authorized(value) {
88
+ this._authorized = value;
89
+ }
79
90
  /**
80
91
  * Alert action result
81
92
  * @param result Action result
@@ -90,10 +101,15 @@ export class CoreApp {
90
101
  * @param keep Keep in local storage or not
91
102
  */
92
103
  authorize(token, refreshToken, keep = false) {
104
+ // State, when token is null, means logout
105
+ this.authorized = token != null;
106
+ // Token
93
107
  this.api.authorize(this.settings.authScheme, token);
94
108
  // Cover the current value
95
109
  StorageUtils.setLocalData(this.headerTokenField, keep ? refreshToken : undefined);
96
110
  StorageUtils.setSessionData(this.headerTokenField, keep ? undefined : refreshToken);
111
+ // Reset tryLogin state
112
+ this._isTryingLogin = false;
97
113
  }
98
114
  /**
99
115
  * Change country or region
@@ -175,8 +191,7 @@ export class CoreApp {
175
191
  }
176
192
  // Detect IP callbacks
177
193
  detectIPCallbacks() {
178
- var _a;
179
- (_a = this.ipDetectCallbacks) === null || _a === void 0 ? void 0 : _a.forEach((f) => f());
194
+ this.ipDetectCallbacks?.forEach((f) => f());
180
195
  }
181
196
  /**
182
197
  * Format date to string
@@ -187,7 +202,7 @@ export class CoreApp {
187
202
  */
188
203
  formatDate(input, options, timeZone) {
189
204
  const { currentCulture, timeZone: defaultTimeZone } = this.settings;
190
- timeZone !== null && timeZone !== void 0 ? timeZone : (timeZone = defaultTimeZone);
205
+ timeZone ?? (timeZone = defaultTimeZone);
191
206
  return DateUtils.format(input, currentCulture.name, options, timeZone);
192
207
  }
193
208
  /**
@@ -226,6 +241,9 @@ export class CoreApp {
226
241
  const value = this.settings.currentCulture.resources[key];
227
242
  if (value == null)
228
243
  return undefined;
244
+ // No strict type convertion here
245
+ // Make sure the type is strictly match
246
+ // Otherwise even request number, may still return the source string type
229
247
  return value;
230
248
  }
231
249
  /**
@@ -234,7 +252,7 @@ export class CoreApp {
234
252
  */
235
253
  getLabels(...keys) {
236
254
  const init = {};
237
- return keys.reduce((a, v) => { var _a; return ({ ...a, [v]: (_a = this.get(v)) !== null && _a !== void 0 ? _a : '' }); }, init);
255
+ return keys.reduce((a, v) => ({ ...a, [v]: this.get(v) ?? '' }), init);
238
256
  }
239
257
  /**
240
258
  * Get cached token
@@ -275,9 +293,8 @@ export class CoreApp {
275
293
  * @returns Time zone
276
294
  */
277
295
  getTimeZone() {
278
- var _a, _b;
279
296
  // settings.timeZone = Utils.getTimeZone()
280
- return (_a = this.settings.timeZone) !== null && _a !== void 0 ? _a : (_b = this.ipData) === null || _b === void 0 ? void 0 : _b.timezone;
297
+ return this.settings.timeZone ?? this.ipData?.timezone;
281
298
  }
282
299
  /**
283
300
  * Callback where exit a page
@@ -309,6 +326,15 @@ export class CoreApp {
309
326
  // To /a/b/../ => /a
310
327
  return pathname.endsWith('/') ? pathname + url : pathname + '/' + url;
311
328
  }
329
+ /**
330
+ * Try login, returning false means is loading
331
+ */
332
+ tryLogin() {
333
+ if (this._isTryingLogin)
334
+ return false;
335
+ this._isTryingLogin = true;
336
+ return true;
337
+ }
312
338
  /**
313
339
  * User login
314
340
  * @param user User data
@@ -1,5 +1,5 @@
1
1
  /**
2
- * External settings
2
+ * External settings items
3
3
  */
4
4
  export interface IExternalSettings {
5
5
  /**
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Business tax interface
3
+ */
4
+ export interface IBusinessTax {
5
+ /**
6
+ * Id
7
+ */
8
+ readonly id: string;
9
+ /**
10
+ * Name
11
+ */
12
+ readonly name: string;
13
+ /**
14
+ * Mask
15
+ */
16
+ readonly mask: string;
17
+ /**
18
+ * Get label key
19
+ */
20
+ readonly labelKey: string;
21
+ }
22
+ /**
23
+ * Business tax
24
+ * https://imask.js.org/
25
+ */
26
+ export declare class BusinessTax implements IBusinessTax {
27
+ id: string;
28
+ name: string;
29
+ mask: string;
30
+ /**
31
+ * CN
32
+ * Unified Social Credit Code (USCC) / 统一信用代码
33
+ * https://zh.wikisource.org/wiki/GB_32100-2015_%E6%B3%95%E4%BA%BA%E5%92%8C%E5%85%B6%E4%BB%96%E7%BB%84%E7%BB%87%E7%BB%9F%E4%B8%80%E7%A4%BE%E4%BC%9A%E4%BF%A1%E7%94%A8%E4%BB%A3%E7%A0%81%E7%BC%96%E7%A0%81%E8%A7%84%E5%88%99
34
+ */
35
+ static CN: BusinessTax;
36
+ /**
37
+ * NZ, Inland Revenue (IRD)
38
+ */
39
+ static NZ: BusinessTax;
40
+ /**
41
+ * US, Employer Identification Number (EIN)
42
+ */
43
+ static US: BusinessTax;
44
+ /**
45
+ * CA, tax ID number (Business Number, BN)
46
+ */
47
+ static CA: BusinessTax;
48
+ /**
49
+ * HK, Business Registration Number (BRN)
50
+ */
51
+ static HK: BusinessTax;
52
+ /**
53
+ * All countries and regions
54
+ */
55
+ static all: BusinessTax[];
56
+ /**
57
+ * Get country or region by id
58
+ * @param id Country id
59
+ */
60
+ static getById(id: string): BusinessTax | undefined;
61
+ constructor(id: string, name: string, mask: string);
62
+ /**
63
+ * Get label key
64
+ */
65
+ get labelKey(): string;
66
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Business tax
3
+ * https://imask.js.org/
4
+ */
5
+ export class BusinessTax {
6
+ // Typescript constructor shorthand
7
+ constructor(id, name, mask) {
8
+ this.id = id;
9
+ this.name = name;
10
+ this.mask = mask;
11
+ }
12
+ /**
13
+ * Get country or region by id
14
+ * @param id Country id
15
+ */
16
+ static getById(id) {
17
+ return BusinessTax.all.find((c) => c.id === id);
18
+ }
19
+ /**
20
+ * Get label key
21
+ */
22
+ get labelKey() {
23
+ return 'tax' + this.id + this.name;
24
+ }
25
+ }
26
+ /**
27
+ * CN
28
+ * Unified Social Credit Code (USCC) / 统一信用代码
29
+ * https://zh.wikisource.org/wiki/GB_32100-2015_%E6%B3%95%E4%BA%BA%E5%92%8C%E5%85%B6%E4%BB%96%E7%BB%84%E7%BB%87%E7%BB%9F%E4%B8%80%E7%A4%BE%E4%BC%9A%E4%BF%A1%E7%94%A8%E4%BB%A3%E7%A0%81%E7%BC%96%E7%A0%81%E8%A7%84%E5%88%99
30
+ */
31
+ BusinessTax.CN = new BusinessTax('CN', 'USCC', '*0-000000-**********');
32
+ /**
33
+ * NZ, Inland Revenue (IRD)
34
+ */
35
+ BusinessTax.NZ = new BusinessTax('NZ', 'IRD', '00[0]-000-000');
36
+ /**
37
+ * US, Employer Identification Number (EIN)
38
+ */
39
+ BusinessTax.US = new BusinessTax('US', 'EIN', '00-0000000');
40
+ /**
41
+ * CA, tax ID number (Business Number, BN)
42
+ */
43
+ BusinessTax.CA = new BusinessTax('CA', 'BN', '000000000');
44
+ /**
45
+ * HK, Business Registration Number (BRN)
46
+ */
47
+ BusinessTax.HK = new BusinessTax('HK', 'BRN', '00000000');
48
+ /**
49
+ * All countries and regions
50
+ */
51
+ BusinessTax.all = [
52
+ BusinessTax.CN,
53
+ BusinessTax.NZ,
54
+ BusinessTax.US,
55
+ BusinessTax.CA,
56
+ BusinessTax.HK
57
+ ];
@@ -1,4 +1,4 @@
1
- import { Utils } from '@etsoo/shared';
1
+ import { DataTypes } from '@etsoo/shared';
2
2
  import { ProductUnit } from './ProductUnit';
3
3
  /**
4
4
  * Business utils
@@ -21,8 +21,7 @@ export var BusinessUtils;
21
21
  BusinessUtils.addIdLabelBlankItem = addIdLabelBlankItem;
22
22
  // Get unit label by key
23
23
  function getUnitLabelByKey(func, key) {
24
- var _a;
25
- return (_a = func('unit' + key)) !== null && _a !== void 0 ? _a : key;
24
+ return func('unit' + key) ?? key;
26
25
  }
27
26
  /**
28
27
  * Get product unit's label
@@ -42,7 +41,7 @@ export var BusinessUtils;
42
41
  * @returns Units
43
42
  */
44
43
  function getUnits(func) {
45
- return Utils.getEnumKeys(ProductUnit).map((key) => ({
44
+ return DataTypes.getEnumKeys(ProductUnit).map((key) => ({
46
45
  id: ProductUnit[key],
47
46
  label: getUnitLabelByKey(func, key)
48
47
  }));
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Id Dto
2
+ * Dto with id field
3
3
  */
4
4
  export declare type IdDto<T = number> = {
5
5
  /**
@@ -1,6 +1,6 @@
1
1
  import { DataTypes } from '@etsoo/shared';
2
2
  /**
3
- * Id & label data
3
+ * Dto with id and label field
4
4
  */
5
5
  export declare type IdLabelDto = {
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  import { IdDto } from './IdDto';
2
2
  /**
3
- * Update Dto
3
+ * Dto with id and changedFields
4
4
  */
5
5
  export declare type UpdateDto<T = number> = IdDto<T> & {
6
6
  /**
@@ -7,6 +7,7 @@ export * from './app/ExternalSettings';
7
7
  export * from './bridges/ElectronBridge';
8
8
  export * from './bridges/IAppData';
9
9
  export * from './bridges/IBridge';
10
+ export * from './business/BusinessTax';
10
11
  export * from './business/BusinessUtils';
11
12
  export * from './business/ProductUnit';
12
13
  export * from './dto/IdDto';
package/lib/mjs/index.js CHANGED
@@ -11,6 +11,7 @@ export * from './bridges/ElectronBridge';
11
11
  export * from './bridges/IAppData';
12
12
  export * from './bridges/IBridge';
13
13
  // business
14
+ export * from './business/BusinessTax';
14
15
  export * from './business/BusinessUtils';
15
16
  export * from './business/ProductUnit';
16
17
  // dto
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.1.3",
3
+ "version": "1.1.7",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -47,24 +47,24 @@
47
47
  },
48
48
  "homepage": "https://github.com/ETSOO/NotificationBase#readme",
49
49
  "dependencies": {
50
- "@etsoo/notificationbase": "^1.0.79",
51
- "@etsoo/restclient": "^1.0.51",
52
- "@etsoo/shared": "^1.0.46"
50
+ "@etsoo/notificationbase": "^1.0.82",
51
+ "@etsoo/restclient": "^1.0.52",
52
+ "@etsoo/shared": "^1.0.49"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@babel/cli": "^7.15.7",
56
- "@babel/core": "^7.15.5",
57
- "@babel/plugin-transform-runtime": "^7.15.0",
58
- "@babel/preset-env": "^7.15.6",
56
+ "@babel/core": "^7.15.8",
57
+ "@babel/plugin-transform-runtime": "^7.15.8",
58
+ "@babel/preset-env": "^7.15.8",
59
59
  "@babel/runtime-corejs3": "^7.15.4",
60
60
  "@types/jest": "^27.0.2",
61
- "@typescript-eslint/eslint-plugin": "^4.32.0",
62
- "@typescript-eslint/parser": "^4.32.0",
63
- "eslint": "^7.32.0",
61
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
62
+ "@typescript-eslint/parser": "^5.0.0",
63
+ "eslint": "^8.0.1",
64
64
  "eslint-config-airbnb-base": "^14.2.1",
65
- "eslint-plugin-import": "^2.24.2",
66
- "jest": "^27.2.4",
67
- "ts-jest": "^27.0.5",
68
- "typescript": "^4.4.3"
65
+ "eslint-plugin-import": "^2.25.2",
66
+ "jest": "^27.2.5",
67
+ "ts-jest": "^27.0.6",
68
+ "typescript": "^4.4.4"
69
69
  }
70
70
  }
@@ -1,4 +1,4 @@
1
- import { Utils } from '@etsoo/shared';
1
+ import { DataTypes } from '@etsoo/shared';
2
2
  import { AddressRegion } from '..';
3
3
  import { IdLabelDto } from '../dto/IdLabelDto';
4
4
  import { ICultureGet } from '../state/Culture';
@@ -18,7 +18,7 @@ export namespace AddressUtils {
18
18
  func: ICultureGet,
19
19
  isNumberKey: boolean = false
20
20
  ): IdLabelDto[] {
21
- return Utils.getEnumKeys(AddressContinent).map((key) => ({
21
+ return DataTypes.getEnumKeys(AddressContinent).map((key) => ({
22
22
  id: isNumberKey
23
23
  ? AddressContinent[key as keyof typeof AddressContinent]
24
24
  : key,
@@ -27,7 +27,7 @@ export namespace AddressUtils {
27
27
  }
28
28
 
29
29
  /**
30
- * Get region
30
+ * Get region from regions and detected region and language
31
31
  * @param regions Supported regions
32
32
  * @param detectedRegion Detected region
33
33
  * @param detectedLanguage Detected language
@@ -4,7 +4,7 @@ import { AddressRegion } from '../address/AddressRegion';
4
4
  import { IExternalSettings } from './ExternalSettings';
5
5
 
6
6
  /**
7
- * API settings interface
7
+ * App settings interface
8
8
  */
9
9
  export interface IAppSettings extends IExternalSettings {
10
10
  /**
@@ -46,9 +46,7 @@ export interface ICoreApp<
46
46
  /**
47
47
  * Label delegate
48
48
  */
49
- readonly labelDelegate: <T extends DataTypes.SimpleType = string>(
50
- key: string
51
- ) => T | undefined;
49
+ readonly labelDelegate: <T = string>(key: string) => T | undefined;
52
50
 
53
51
  /**
54
52
  * Culture, like zh-CN
@@ -65,6 +63,11 @@ export interface ICoreApp<
65
63
  */
66
64
  readonly region: string;
67
65
 
66
+ /**
67
+ * Is current authorized
68
+ */
69
+ readonly authorized: boolean;
70
+
68
71
  /**
69
72
  * IP data
70
73
  */
@@ -154,7 +157,7 @@ export interface ICoreApp<
154
157
  * @param key key
155
158
  * @returns Resource
156
159
  */
157
- get<T extends DataTypes.SimpleType = string>(key: string): T | undefined;
160
+ get<T = string>(key: string): T | undefined;
158
161
 
159
162
  /**
160
163
  * Get multiple culture labels
@@ -199,6 +202,11 @@ export interface ICoreApp<
199
202
  */
200
203
  transformUrl(url: string): string;
201
204
 
205
+ /**
206
+ * Try login, returning false means is loading
207
+ */
208
+ tryLogin(): boolean;
209
+
202
210
  /**
203
211
  * User login
204
212
  * @param user User data
@@ -291,6 +299,20 @@ export abstract class CoreApp<
291
299
  */
292
300
  searchInput?: HTMLInputElement;
293
301
 
302
+ private _authorized: boolean = false;
303
+ /**
304
+ * Is current authorized
305
+ */
306
+ get authorized() {
307
+ return this._authorized;
308
+ }
309
+
310
+ private set authorized(value: boolean) {
311
+ this._authorized = value;
312
+ }
313
+
314
+ private _isTryingLogin = false;
315
+
294
316
  /**
295
317
  * Protected constructor
296
318
  * @param settings Settings
@@ -355,6 +377,10 @@ export abstract class CoreApp<
355
377
  * @param keep Keep in local storage or not
356
378
  */
357
379
  authorize(token?: string, refreshToken?: string, keep: boolean = false) {
380
+ // State, when token is null, means logout
381
+ this.authorized = token != null;
382
+
383
+ // Token
358
384
  this.api.authorize(this.settings.authScheme, token);
359
385
 
360
386
  // Cover the current value
@@ -366,6 +392,9 @@ export abstract class CoreApp<
366
392
  this.headerTokenField,
367
393
  keep ? undefined : refreshToken
368
394
  );
395
+
396
+ // Reset tryLogin state
397
+ this._isTryingLogin = false;
369
398
  }
370
399
 
371
400
  /**
@@ -529,9 +558,13 @@ export abstract class CoreApp<
529
558
  * @param key key
530
559
  * @returns Resource
531
560
  */
532
- get<T extends DataTypes.SimpleType = string>(key: string): T | undefined {
561
+ get<T = string>(key: string): T | undefined {
533
562
  const value = this.settings.currentCulture.resources[key];
534
563
  if (value == null) return undefined;
564
+
565
+ // No strict type convertion here
566
+ // Make sure the type is strictly match
567
+ // Otherwise even request number, may still return the source string type
535
568
  return value as T;
536
569
  }
537
570
 
@@ -632,9 +665,13 @@ export abstract class CoreApp<
632
665
  }
633
666
 
634
667
  /**
635
- * Try login
668
+ * Try login, returning false means is loading
636
669
  */
637
- abstract tryLogin(): void;
670
+ tryLogin() {
671
+ if (this._isTryingLogin) return false;
672
+ this._isTryingLogin = true;
673
+ return true;
674
+ }
638
675
 
639
676
  /**
640
677
  * User login
@@ -1,5 +1,5 @@
1
1
  /**
2
- * External settings
2
+ * External settings items
3
3
  */
4
4
  export interface IExternalSettings {
5
5
  /**
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Business tax interface
3
+ */
4
+ export interface IBusinessTax {
5
+ /**
6
+ * Id
7
+ */
8
+ readonly id: string;
9
+
10
+ /**
11
+ * Name
12
+ */
13
+ readonly name: string;
14
+
15
+ /**
16
+ * Mask
17
+ */
18
+ readonly mask: string;
19
+
20
+ /**
21
+ * Get label key
22
+ */
23
+ readonly labelKey: string;
24
+ }
25
+
26
+ /**
27
+ * Business tax
28
+ * https://imask.js.org/
29
+ */
30
+ export class BusinessTax implements IBusinessTax {
31
+ /**
32
+ * CN
33
+ * Unified Social Credit Code (USCC) / 统一信用代码
34
+ * https://zh.wikisource.org/wiki/GB_32100-2015_%E6%B3%95%E4%BA%BA%E5%92%8C%E5%85%B6%E4%BB%96%E7%BB%84%E7%BB%87%E7%BB%9F%E4%B8%80%E7%A4%BE%E4%BC%9A%E4%BF%A1%E7%94%A8%E4%BB%A3%E7%A0%81%E7%BC%96%E7%A0%81%E8%A7%84%E5%88%99
35
+ */
36
+ static CN = new BusinessTax('CN', 'USCC', '*0-000000-**********');
37
+
38
+ /**
39
+ * NZ, Inland Revenue (IRD)
40
+ */
41
+ static NZ = new BusinessTax('NZ', 'IRD', '00[0]-000-000');
42
+
43
+ /**
44
+ * US, Employer Identification Number (EIN)
45
+ */
46
+ static US = new BusinessTax('US', 'EIN', '00-0000000');
47
+
48
+ /**
49
+ * CA, tax ID number (Business Number, BN)
50
+ */
51
+ static CA = new BusinessTax('CA', 'BN', '000000000');
52
+
53
+ /**
54
+ * HK, Business Registration Number (BRN)
55
+ */
56
+ static HK = new BusinessTax('HK', 'BRN', '00000000');
57
+
58
+ /**
59
+ * All countries and regions
60
+ */
61
+ static all = [
62
+ BusinessTax.CN,
63
+ BusinessTax.NZ,
64
+ BusinessTax.US,
65
+ BusinessTax.CA,
66
+ BusinessTax.HK
67
+ ];
68
+
69
+ /**
70
+ * Get country or region by id
71
+ * @param id Country id
72
+ */
73
+ static getById(id: string) {
74
+ return BusinessTax.all.find((c) => c.id === id);
75
+ }
76
+
77
+ // Typescript constructor shorthand
78
+ constructor(public id: string, public name: string, public mask: string) {}
79
+
80
+ /**
81
+ * Get label key
82
+ */
83
+ get labelKey() {
84
+ return 'tax' + this.id + this.name;
85
+ }
86
+ }