@etsoo/appscript 1.5.98 → 1.6.0
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.
- package/README.md +0 -1
- package/__tests__/app/CoreApp.ts +53 -2
- package/__tests__/app/TestApp.ts +19 -4
- package/lib/cjs/app/CoreApp.d.ts +6 -0
- package/lib/cjs/app/CoreApp.js +22 -5
- package/lib/cjs/app/ExternalSettings.d.ts +30 -4
- package/lib/cjs/app/ExternalSettings.js +48 -27
- package/lib/mjs/app/CoreApp.d.ts +6 -0
- package/lib/mjs/app/CoreApp.js +22 -5
- package/lib/mjs/app/ExternalSettings.d.ts +30 -4
- package/lib/mjs/app/ExternalSettings.js +48 -27
- package/package.json +2 -2
- package/src/app/CoreApp.ts +31 -6
- package/src/app/ExternalSettings.ts +80 -31
package/README.md
CHANGED
package/__tests__/app/CoreApp.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { ApiDataError, ApiMethod } from "@etsoo/restclient";
|
|
2
2
|
import { DataTypes, IActionResult } from "@etsoo/shared";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
EntityStatus,
|
|
5
|
+
ExternalEndpoint,
|
|
6
|
+
ExternalSettings,
|
|
7
|
+
UserRole
|
|
8
|
+
} from "../../src";
|
|
4
9
|
import { TestApp } from "./TestApp";
|
|
5
10
|
|
|
6
11
|
// Arrange
|
|
@@ -16,7 +21,7 @@ const app = new appClass();
|
|
|
16
21
|
|
|
17
22
|
await app.changeCulture(app.settings.cultures[0]);
|
|
18
23
|
|
|
19
|
-
test("Test for domain
|
|
24
|
+
test("Test for domain substitution", () => {
|
|
20
25
|
expect(app.settings.endpoint).toBe("http://localhost:9000/api/");
|
|
21
26
|
|
|
22
27
|
expect(app.settings.endpoints?.core.endpoint).toBe(
|
|
@@ -24,6 +29,52 @@ test("Test for domain replacement", () => {
|
|
|
24
29
|
);
|
|
25
30
|
});
|
|
26
31
|
|
|
32
|
+
test("Test for formatApp", () => {
|
|
33
|
+
expect(
|
|
34
|
+
ExternalSettings.formatApp(
|
|
35
|
+
"admin.app.local",
|
|
36
|
+
"core",
|
|
37
|
+
"https://{hostname}/api/"
|
|
38
|
+
)
|
|
39
|
+
).toBe("https://core.app.local/api/");
|
|
40
|
+
|
|
41
|
+
expect(
|
|
42
|
+
ExternalSettings.formatApp("localhost", "admin", "https://{hostname}/api/")
|
|
43
|
+
).toBe("https://localhost/api/");
|
|
44
|
+
|
|
45
|
+
// Custom sub domain match
|
|
46
|
+
ExternalSettings.subDomainMatch = /app(?=\.)/i;
|
|
47
|
+
|
|
48
|
+
expect(
|
|
49
|
+
ExternalSettings.formatApp(
|
|
50
|
+
"admin.app.local",
|
|
51
|
+
"core",
|
|
52
|
+
"https://{hostname}/api/"
|
|
53
|
+
)
|
|
54
|
+
).toBe("https://admin.core.local/api/");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("Test for formatHost with endpoints", () => {
|
|
58
|
+
// Reset sub domain match
|
|
59
|
+
ExternalSettings.subDomainMatch = /(?<=\/\/)[0-9a-z]+(?=\.)/i;
|
|
60
|
+
|
|
61
|
+
const endpoints: Record<string, ExternalEndpoint> = {
|
|
62
|
+
core: {
|
|
63
|
+
endpoint: "https://{hostname}/api/",
|
|
64
|
+
webUrl: "https://{hostname}/"
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const result = ExternalSettings.formatHost(endpoints, "admin.app.local");
|
|
69
|
+
|
|
70
|
+
expect(result).toStrictEqual({
|
|
71
|
+
core: {
|
|
72
|
+
endpoint: "https://core.app.local/api/",
|
|
73
|
+
webUrl: "https://core.app.local/"
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
27
78
|
test("Test for properties", () => {
|
|
28
79
|
expect(app.settings.currentRegion.label).toBe("中国大陆");
|
|
29
80
|
});
|
package/__tests__/app/TestApp.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
InitCallResultData,
|
|
17
17
|
IUser
|
|
18
18
|
} from "../../src";
|
|
19
|
-
import { DataTypes, DomUtils,
|
|
19
|
+
import { DataTypes, DomUtils, WindowStorage } from "@etsoo/shared";
|
|
20
20
|
|
|
21
21
|
// Detected country or region
|
|
22
22
|
const { detectedCountry } = DomUtils;
|
|
@@ -72,7 +72,9 @@ export class TestApp extends CoreApp<
|
|
|
72
72
|
*/
|
|
73
73
|
constructor() {
|
|
74
74
|
super(
|
|
75
|
-
|
|
75
|
+
{
|
|
76
|
+
appId: 0,
|
|
77
|
+
|
|
76
78
|
/**
|
|
77
79
|
* Endpoint of the API service
|
|
78
80
|
*/
|
|
@@ -115,8 +117,8 @@ export class TestApp extends CoreApp<
|
|
|
115
117
|
currentCulture: DomUtils.getCulture(
|
|
116
118
|
supportedCultures,
|
|
117
119
|
detectedCulture
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
+
)[0]
|
|
121
|
+
},
|
|
120
122
|
createClient(),
|
|
121
123
|
container,
|
|
122
124
|
new WindowStorage(),
|
|
@@ -124,6 +126,19 @@ export class TestApp extends CoreApp<
|
|
|
124
126
|
);
|
|
125
127
|
}
|
|
126
128
|
|
|
129
|
+
// Example of local format settings
|
|
130
|
+
protected override formatSettings(settings: IAppSettings): IAppSettings {
|
|
131
|
+
const { endpoint, endpoints, ...rest } = settings;
|
|
132
|
+
return {
|
|
133
|
+
...rest,
|
|
134
|
+
endpoint: ExternalSettings.formatHost(endpoint, "localhost"),
|
|
135
|
+
endpoints:
|
|
136
|
+
endpoints == null
|
|
137
|
+
? undefined
|
|
138
|
+
: ExternalSettings.formatHost(endpoints, "localhost")
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
127
142
|
freshCountdownUI(callback?: () => PromiseLike<unknown>): void {
|
|
128
143
|
throw new Error("Method not implemented.");
|
|
129
144
|
}
|
package/lib/cjs/app/CoreApp.d.ts
CHANGED
|
@@ -176,6 +176,12 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
|
|
|
176
176
|
* @param debug Debug mode
|
|
177
177
|
*/
|
|
178
178
|
protected constructor(settings: S, api: IApi | undefined | null, notifier: INotifier<N, C>, storage: IStorage, name: string, debug?: boolean);
|
|
179
|
+
/**
|
|
180
|
+
* Format settings
|
|
181
|
+
* @param settings Original settings
|
|
182
|
+
* @returns Result
|
|
183
|
+
*/
|
|
184
|
+
protected formatSettings(settings: S): S;
|
|
179
185
|
private getDeviceId;
|
|
180
186
|
private resetKeys;
|
|
181
187
|
/**
|
package/lib/cjs/app/CoreApp.js
CHANGED
|
@@ -11,6 +11,7 @@ const EntityStatus_1 = require("../business/EntityStatus");
|
|
|
11
11
|
const ActionResultError_1 = require("../result/ActionResultError");
|
|
12
12
|
const IApp_1 = require("./IApp");
|
|
13
13
|
const UserRole_1 = require("./UserRole");
|
|
14
|
+
const ExternalSettings_1 = require("./ExternalSettings");
|
|
14
15
|
const AuthApi_1 = require("../api/AuthApi");
|
|
15
16
|
let CJ;
|
|
16
17
|
const loadCrypto = () => import("crypto-js");
|
|
@@ -164,11 +165,10 @@ class CoreApp {
|
|
|
164
165
|
this.passphrase = "";
|
|
165
166
|
this.apis = {};
|
|
166
167
|
this.tasks = [];
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const region = AddressRegion_1.AddressRegion.getById(settings.regions[0]);
|
|
168
|
+
// Format settings
|
|
169
|
+
this.settings = this.formatSettings(settings);
|
|
170
|
+
// Current region
|
|
171
|
+
const region = AddressRegion_1.AddressRegion.getById(this.settings.regions[0]);
|
|
172
172
|
if (region == null) {
|
|
173
173
|
throw new Error("No default region defined");
|
|
174
174
|
}
|
|
@@ -232,6 +232,23 @@ class CoreApp {
|
|
|
232
232
|
this.setup();
|
|
233
233
|
});
|
|
234
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Format settings
|
|
237
|
+
* @param settings Original settings
|
|
238
|
+
* @returns Result
|
|
239
|
+
*/
|
|
240
|
+
formatSettings(settings) {
|
|
241
|
+
const { endpoint, webUrl, endpoints, hostname = globalThis.location.hostname, ...rest } = settings;
|
|
242
|
+
return {
|
|
243
|
+
...rest,
|
|
244
|
+
hostname,
|
|
245
|
+
endpoint: ExternalSettings_1.ExternalSettings.formatHost(endpoint, hostname),
|
|
246
|
+
webUrl: ExternalSettings_1.ExternalSettings.formatHost(webUrl, hostname),
|
|
247
|
+
endpoints: endpoints == null
|
|
248
|
+
? undefined
|
|
249
|
+
: ExternalSettings_1.ExternalSettings.formatHost(endpoints, hostname)
|
|
250
|
+
};
|
|
251
|
+
}
|
|
235
252
|
getDeviceId() {
|
|
236
253
|
return this.deviceId.substring(0, 15);
|
|
237
254
|
}
|
|
@@ -28,18 +28,44 @@ export interface IExternalSettings extends ExternalEndpoint {
|
|
|
28
28
|
* 程序编号
|
|
29
29
|
*/
|
|
30
30
|
readonly appId: number;
|
|
31
|
+
/**
|
|
32
|
+
* Default hostname for substitution
|
|
33
|
+
* 用于替换的默认主机名
|
|
34
|
+
*/
|
|
35
|
+
hostname?: string;
|
|
31
36
|
/**
|
|
32
37
|
* Endpoints to other services
|
|
33
38
|
*/
|
|
34
|
-
readonly endpoints?: Record<"core" | "
|
|
39
|
+
readonly endpoints?: Record<"core" | "admin" | "finance" | "crm" | "oa" | "agile" | string, ExternalEndpoint>;
|
|
35
40
|
}
|
|
36
41
|
/**
|
|
37
42
|
* External settings namespace
|
|
38
43
|
*/
|
|
39
44
|
export declare namespace ExternalSettings {
|
|
40
45
|
/**
|
|
41
|
-
*
|
|
46
|
+
* Sub domain match regular expression
|
|
47
|
+
*/
|
|
48
|
+
let subDomainMatch: RegExp;
|
|
49
|
+
/**
|
|
50
|
+
* Create settings instance
|
|
51
|
+
* @param settings Settings
|
|
52
|
+
* @returns Result
|
|
53
|
+
*/
|
|
54
|
+
function create<T extends IExternalSettings = IExternalSettings>(settings?: unknown, hostname?: string): T;
|
|
55
|
+
/**
|
|
56
|
+
* Format the app
|
|
57
|
+
* @param hostname Hostname
|
|
58
|
+
* @param app App key
|
|
59
|
+
* @param endpoint Endpoint
|
|
60
|
+
* @returns Result
|
|
61
|
+
*/
|
|
62
|
+
function formatApp(hostname: string, app: string, endpoint: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Format the host
|
|
65
|
+
* @param setting Setting
|
|
66
|
+
* @param hostname Hostname
|
|
67
|
+
* @returns Result
|
|
42
68
|
*/
|
|
43
|
-
function
|
|
44
|
-
function
|
|
69
|
+
function formatHost(setting: string, hostname: string): string;
|
|
70
|
+
function formatHost(setting: Record<string, ExternalEndpoint>, hostname?: string | null): Record<string, ExternalEndpoint>;
|
|
45
71
|
}
|
|
@@ -7,39 +7,60 @@ exports.ExternalSettings = void 0;
|
|
|
7
7
|
var ExternalSettings;
|
|
8
8
|
(function (ExternalSettings) {
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Sub domain match regular expression
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
ExternalSettings.subDomainMatch = /(?<=\/\/)[0-9a-z]+(?=\.)/i;
|
|
13
|
+
/**
|
|
14
|
+
* Create settings instance
|
|
15
|
+
* @param settings Settings
|
|
16
|
+
* @returns Result
|
|
17
|
+
*/
|
|
18
|
+
function create(settings, hostname) {
|
|
19
|
+
// Default settings reading from globalThis
|
|
20
|
+
settings ?? (settings = Reflect.get(globalThis, "settings"));
|
|
21
|
+
if (settings) {
|
|
22
|
+
if (typeof settings === "string") {
|
|
23
|
+
settings = JSON.parse(settings);
|
|
24
|
+
}
|
|
25
|
+
if (settings != null &&
|
|
26
|
+
typeof settings === "object" &&
|
|
27
|
+
"appId" in settings &&
|
|
28
|
+
"endpoint" in settings) {
|
|
29
|
+
const s = settings;
|
|
30
|
+
if (hostname)
|
|
31
|
+
s.hostname = hostname;
|
|
32
|
+
return s;
|
|
23
33
|
}
|
|
24
34
|
}
|
|
25
|
-
|
|
35
|
+
throw new Error("No external settings found");
|
|
26
36
|
}
|
|
27
37
|
ExternalSettings.create = create;
|
|
28
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Format the app
|
|
40
|
+
* @param hostname Hostname
|
|
41
|
+
* @param app App key
|
|
42
|
+
* @param endpoint Endpoint
|
|
43
|
+
* @returns Result
|
|
44
|
+
*/
|
|
45
|
+
function formatApp(hostname, app, endpoint) {
|
|
46
|
+
return formatHost(endpoint, hostname).replace(ExternalSettings.subDomainMatch, app);
|
|
47
|
+
}
|
|
48
|
+
ExternalSettings.formatApp = formatApp;
|
|
49
|
+
function formatHost(setting, hostname) {
|
|
29
50
|
// Default hostname
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
hostname ?? (hostname = globalThis.location.hostname);
|
|
52
|
+
if (typeof setting === "string") {
|
|
53
|
+
return setting.replace("{hostname}", hostname);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return Object.fromEntries(Object.entries(setting).map(([key, value]) => [
|
|
57
|
+
key,
|
|
58
|
+
{
|
|
59
|
+
endpoint: formatApp(hostname, key, value.endpoint),
|
|
60
|
+
webUrl: formatApp(hostname, key, value.webUrl)
|
|
61
|
+
}
|
|
62
|
+
]));
|
|
41
63
|
}
|
|
42
|
-
return settings;
|
|
43
64
|
}
|
|
44
|
-
ExternalSettings.
|
|
65
|
+
ExternalSettings.formatHost = formatHost;
|
|
45
66
|
})(ExternalSettings || (exports.ExternalSettings = ExternalSettings = {}));
|
package/lib/mjs/app/CoreApp.d.ts
CHANGED
|
@@ -176,6 +176,12 @@ export declare abstract class CoreApp<U extends IUser, S extends IAppSettings, N
|
|
|
176
176
|
* @param debug Debug mode
|
|
177
177
|
*/
|
|
178
178
|
protected constructor(settings: S, api: IApi | undefined | null, notifier: INotifier<N, C>, storage: IStorage, name: string, debug?: boolean);
|
|
179
|
+
/**
|
|
180
|
+
* Format settings
|
|
181
|
+
* @param settings Original settings
|
|
182
|
+
* @returns Result
|
|
183
|
+
*/
|
|
184
|
+
protected formatSettings(settings: S): S;
|
|
179
185
|
private getDeviceId;
|
|
180
186
|
private resetKeys;
|
|
181
187
|
/**
|
package/lib/mjs/app/CoreApp.js
CHANGED
|
@@ -8,6 +8,7 @@ import { EntityStatus } from "../business/EntityStatus";
|
|
|
8
8
|
import { ActionResultError } from "../result/ActionResultError";
|
|
9
9
|
import { appFields } from "./IApp";
|
|
10
10
|
import { UserRole } from "./UserRole";
|
|
11
|
+
import { ExternalSettings } from "./ExternalSettings";
|
|
11
12
|
import { AuthApi } from "../api/AuthApi";
|
|
12
13
|
let CJ;
|
|
13
14
|
const loadCrypto = () => import("crypto-js");
|
|
@@ -161,11 +162,10 @@ export class CoreApp {
|
|
|
161
162
|
this.passphrase = "";
|
|
162
163
|
this.apis = {};
|
|
163
164
|
this.tasks = [];
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const region = AddressRegion.getById(settings.regions[0]);
|
|
165
|
+
// Format settings
|
|
166
|
+
this.settings = this.formatSettings(settings);
|
|
167
|
+
// Current region
|
|
168
|
+
const region = AddressRegion.getById(this.settings.regions[0]);
|
|
169
169
|
if (region == null) {
|
|
170
170
|
throw new Error("No default region defined");
|
|
171
171
|
}
|
|
@@ -229,6 +229,23 @@ export class CoreApp {
|
|
|
229
229
|
this.setup();
|
|
230
230
|
});
|
|
231
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Format settings
|
|
234
|
+
* @param settings Original settings
|
|
235
|
+
* @returns Result
|
|
236
|
+
*/
|
|
237
|
+
formatSettings(settings) {
|
|
238
|
+
const { endpoint, webUrl, endpoints, hostname = globalThis.location.hostname, ...rest } = settings;
|
|
239
|
+
return {
|
|
240
|
+
...rest,
|
|
241
|
+
hostname,
|
|
242
|
+
endpoint: ExternalSettings.formatHost(endpoint, hostname),
|
|
243
|
+
webUrl: ExternalSettings.formatHost(webUrl, hostname),
|
|
244
|
+
endpoints: endpoints == null
|
|
245
|
+
? undefined
|
|
246
|
+
: ExternalSettings.formatHost(endpoints, hostname)
|
|
247
|
+
};
|
|
248
|
+
}
|
|
232
249
|
getDeviceId() {
|
|
233
250
|
return this.deviceId.substring(0, 15);
|
|
234
251
|
}
|
|
@@ -28,18 +28,44 @@ export interface IExternalSettings extends ExternalEndpoint {
|
|
|
28
28
|
* 程序编号
|
|
29
29
|
*/
|
|
30
30
|
readonly appId: number;
|
|
31
|
+
/**
|
|
32
|
+
* Default hostname for substitution
|
|
33
|
+
* 用于替换的默认主机名
|
|
34
|
+
*/
|
|
35
|
+
hostname?: string;
|
|
31
36
|
/**
|
|
32
37
|
* Endpoints to other services
|
|
33
38
|
*/
|
|
34
|
-
readonly endpoints?: Record<"core" | "
|
|
39
|
+
readonly endpoints?: Record<"core" | "admin" | "finance" | "crm" | "oa" | "agile" | string, ExternalEndpoint>;
|
|
35
40
|
}
|
|
36
41
|
/**
|
|
37
42
|
* External settings namespace
|
|
38
43
|
*/
|
|
39
44
|
export declare namespace ExternalSettings {
|
|
40
45
|
/**
|
|
41
|
-
*
|
|
46
|
+
* Sub domain match regular expression
|
|
47
|
+
*/
|
|
48
|
+
let subDomainMatch: RegExp;
|
|
49
|
+
/**
|
|
50
|
+
* Create settings instance
|
|
51
|
+
* @param settings Settings
|
|
52
|
+
* @returns Result
|
|
53
|
+
*/
|
|
54
|
+
function create<T extends IExternalSettings = IExternalSettings>(settings?: unknown, hostname?: string): T;
|
|
55
|
+
/**
|
|
56
|
+
* Format the app
|
|
57
|
+
* @param hostname Hostname
|
|
58
|
+
* @param app App key
|
|
59
|
+
* @param endpoint Endpoint
|
|
60
|
+
* @returns Result
|
|
61
|
+
*/
|
|
62
|
+
function formatApp(hostname: string, app: string, endpoint: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Format the host
|
|
65
|
+
* @param setting Setting
|
|
66
|
+
* @param hostname Hostname
|
|
67
|
+
* @returns Result
|
|
42
68
|
*/
|
|
43
|
-
function
|
|
44
|
-
function
|
|
69
|
+
function formatHost(setting: string, hostname: string): string;
|
|
70
|
+
function formatHost(setting: Record<string, ExternalEndpoint>, hostname?: string | null): Record<string, ExternalEndpoint>;
|
|
45
71
|
}
|
|
@@ -4,39 +4,60 @@
|
|
|
4
4
|
export var ExternalSettings;
|
|
5
5
|
(function (ExternalSettings) {
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Sub domain match regular expression
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
ExternalSettings.subDomainMatch = /(?<=\/\/)[0-9a-z]+(?=\.)/i;
|
|
10
|
+
/**
|
|
11
|
+
* Create settings instance
|
|
12
|
+
* @param settings Settings
|
|
13
|
+
* @returns Result
|
|
14
|
+
*/
|
|
15
|
+
function create(settings, hostname) {
|
|
16
|
+
// Default settings reading from globalThis
|
|
17
|
+
settings ?? (settings = Reflect.get(globalThis, "settings"));
|
|
18
|
+
if (settings) {
|
|
19
|
+
if (typeof settings === "string") {
|
|
20
|
+
settings = JSON.parse(settings);
|
|
21
|
+
}
|
|
22
|
+
if (settings != null &&
|
|
23
|
+
typeof settings === "object" &&
|
|
24
|
+
"appId" in settings &&
|
|
25
|
+
"endpoint" in settings) {
|
|
26
|
+
const s = settings;
|
|
27
|
+
if (hostname)
|
|
28
|
+
s.hostname = hostname;
|
|
29
|
+
return s;
|
|
20
30
|
}
|
|
21
31
|
}
|
|
22
|
-
|
|
32
|
+
throw new Error("No external settings found");
|
|
23
33
|
}
|
|
24
34
|
ExternalSettings.create = create;
|
|
25
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Format the app
|
|
37
|
+
* @param hostname Hostname
|
|
38
|
+
* @param app App key
|
|
39
|
+
* @param endpoint Endpoint
|
|
40
|
+
* @returns Result
|
|
41
|
+
*/
|
|
42
|
+
function formatApp(hostname, app, endpoint) {
|
|
43
|
+
return formatHost(endpoint, hostname).replace(ExternalSettings.subDomainMatch, app);
|
|
44
|
+
}
|
|
45
|
+
ExternalSettings.formatApp = formatApp;
|
|
46
|
+
function formatHost(setting, hostname) {
|
|
26
47
|
// Default hostname
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
hostname ?? (hostname = globalThis.location.hostname);
|
|
49
|
+
if (typeof setting === "string") {
|
|
50
|
+
return setting.replace("{hostname}", hostname);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return Object.fromEntries(Object.entries(setting).map(([key, value]) => [
|
|
54
|
+
key,
|
|
55
|
+
{
|
|
56
|
+
endpoint: formatApp(hostname, key, value.endpoint),
|
|
57
|
+
webUrl: formatApp(hostname, key, value.webUrl)
|
|
58
|
+
}
|
|
59
|
+
]));
|
|
38
60
|
}
|
|
39
|
-
return settings;
|
|
40
61
|
}
|
|
41
|
-
ExternalSettings.
|
|
62
|
+
ExternalSettings.formatHost = formatHost;
|
|
42
63
|
})(ExternalSettings || (ExternalSettings = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/appscript",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Applications shared TypeScript framework",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@etsoo/notificationbase": "^1.1.58",
|
|
39
39
|
"@etsoo/restclient": "^1.1.23",
|
|
40
|
-
"@etsoo/shared": "^1.2.
|
|
40
|
+
"@etsoo/shared": "^1.2.61",
|
|
41
41
|
"crypto-js": "^4.2.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
package/src/app/CoreApp.ts
CHANGED
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
import { UserRole } from "./UserRole";
|
|
46
46
|
import type CryptoJS from "crypto-js";
|
|
47
47
|
import { Currency } from "../business/Currency";
|
|
48
|
-
import { ExternalEndpoint } from "./ExternalSettings";
|
|
48
|
+
import { ExternalEndpoint, ExternalSettings } from "./ExternalSettings";
|
|
49
49
|
import { ApiRefreshTokenDto } from "../api/dto/ApiRefreshTokenDto";
|
|
50
50
|
import { ApiRefreshTokenRQ } from "../api/rq/ApiRefreshTokenRQ";
|
|
51
51
|
import { AuthApi } from "../api/AuthApi";
|
|
@@ -336,15 +336,15 @@ export abstract class CoreApp<
|
|
|
336
336
|
name: string,
|
|
337
337
|
debug: boolean = false
|
|
338
338
|
) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
this.settings = settings;
|
|
339
|
+
// Format settings
|
|
340
|
+
this.settings = this.formatSettings(settings);
|
|
343
341
|
|
|
344
|
-
|
|
342
|
+
// Current region
|
|
343
|
+
const region = AddressRegion.getById(this.settings.regions[0]);
|
|
345
344
|
if (region == null) {
|
|
346
345
|
throw new Error("No default region defined");
|
|
347
346
|
}
|
|
347
|
+
|
|
348
348
|
this.defaultRegion = region;
|
|
349
349
|
|
|
350
350
|
// Current system refresh token
|
|
@@ -433,6 +433,31 @@ export abstract class CoreApp<
|
|
|
433
433
|
);
|
|
434
434
|
}
|
|
435
435
|
|
|
436
|
+
/**
|
|
437
|
+
* Format settings
|
|
438
|
+
* @param settings Original settings
|
|
439
|
+
* @returns Result
|
|
440
|
+
*/
|
|
441
|
+
protected formatSettings(settings: S): S {
|
|
442
|
+
const {
|
|
443
|
+
endpoint,
|
|
444
|
+
webUrl,
|
|
445
|
+
endpoints,
|
|
446
|
+
hostname = globalThis.location.hostname,
|
|
447
|
+
...rest
|
|
448
|
+
} = settings;
|
|
449
|
+
return {
|
|
450
|
+
...rest,
|
|
451
|
+
hostname,
|
|
452
|
+
endpoint: ExternalSettings.formatHost(endpoint, hostname),
|
|
453
|
+
webUrl: ExternalSettings.formatHost(webUrl, hostname),
|
|
454
|
+
endpoints:
|
|
455
|
+
endpoints == null
|
|
456
|
+
? undefined
|
|
457
|
+
: ExternalSettings.formatHost(endpoints, hostname)
|
|
458
|
+
} as S;
|
|
459
|
+
}
|
|
460
|
+
|
|
436
461
|
private getDeviceId() {
|
|
437
462
|
return this.deviceId.substring(0, 15);
|
|
438
463
|
}
|
|
@@ -33,11 +33,17 @@ export interface IExternalSettings extends ExternalEndpoint {
|
|
|
33
33
|
*/
|
|
34
34
|
readonly appId: number;
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Default hostname for substitution
|
|
38
|
+
* 用于替换的默认主机名
|
|
39
|
+
*/
|
|
40
|
+
hostname?: string;
|
|
41
|
+
|
|
36
42
|
/**
|
|
37
43
|
* Endpoints to other services
|
|
38
44
|
*/
|
|
39
45
|
readonly endpoints?: Record<
|
|
40
|
-
"core" | "
|
|
46
|
+
"core" | "admin" | "finance" | "crm" | "oa" | "agile" | string,
|
|
41
47
|
ExternalEndpoint
|
|
42
48
|
>;
|
|
43
49
|
}
|
|
@@ -47,42 +53,85 @@ export interface IExternalSettings extends ExternalEndpoint {
|
|
|
47
53
|
*/
|
|
48
54
|
export namespace ExternalSettings {
|
|
49
55
|
/**
|
|
50
|
-
*
|
|
56
|
+
* Sub domain match regular expression
|
|
57
|
+
*/
|
|
58
|
+
export let subDomainMatch: RegExp = /(?<=\/\/)[0-9a-z]+(?=\.)/i;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Create settings instance
|
|
62
|
+
* @param settings Settings
|
|
63
|
+
* @returns Result
|
|
51
64
|
*/
|
|
52
|
-
export function create<T extends IExternalSettings = IExternalSettings>(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
export function create<T extends IExternalSettings = IExternalSettings>(
|
|
66
|
+
settings?: unknown,
|
|
67
|
+
hostname?: string
|
|
68
|
+
): T {
|
|
69
|
+
// Default settings reading from globalThis
|
|
70
|
+
settings ??= Reflect.get(globalThis, "settings");
|
|
71
|
+
|
|
72
|
+
if (settings) {
|
|
73
|
+
if (typeof settings === "string") {
|
|
74
|
+
settings = JSON.parse(settings);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (
|
|
78
|
+
settings != null &&
|
|
79
|
+
typeof settings === "object" &&
|
|
80
|
+
"appId" in settings &&
|
|
81
|
+
"endpoint" in settings
|
|
82
|
+
) {
|
|
83
|
+
const s = settings as T;
|
|
84
|
+
if (hostname) s.hostname = hostname;
|
|
85
|
+
return s;
|
|
67
86
|
}
|
|
68
87
|
}
|
|
69
|
-
|
|
88
|
+
|
|
89
|
+
throw new Error("No external settings found");
|
|
70
90
|
}
|
|
71
91
|
|
|
72
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Format the app
|
|
94
|
+
* @param hostname Hostname
|
|
95
|
+
* @param app App key
|
|
96
|
+
* @param endpoint Endpoint
|
|
97
|
+
* @returns Result
|
|
98
|
+
*/
|
|
99
|
+
export function formatApp(hostname: string, app: string, endpoint: string) {
|
|
100
|
+
return formatHost(endpoint, hostname).replace(subDomainMatch, app);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Format the host
|
|
105
|
+
* @param setting Setting
|
|
106
|
+
* @param hostname Hostname
|
|
107
|
+
* @returns Result
|
|
108
|
+
*/
|
|
109
|
+
export function formatHost(setting: string, hostname: string): string;
|
|
110
|
+
|
|
111
|
+
export function formatHost(
|
|
112
|
+
setting: Record<string, ExternalEndpoint>,
|
|
113
|
+
hostname?: string | null
|
|
114
|
+
): Record<string, ExternalEndpoint>;
|
|
115
|
+
|
|
116
|
+
export function formatHost(
|
|
117
|
+
setting: string | Record<string, ExternalEndpoint>,
|
|
118
|
+
hostname?: string | null
|
|
119
|
+
): string | Record<string, ExternalEndpoint> {
|
|
73
120
|
// Default hostname
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// replace {hostname}
|
|
77
|
-
for (const key in settings) {
|
|
78
|
-
const value = settings[key];
|
|
79
|
-
if (typeof value === "string") {
|
|
80
|
-
settings[key] = value.replace("{hostname}", hostname);
|
|
81
|
-
} else if (typeof value === "object") {
|
|
82
|
-
format(value, hostname);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
121
|
+
hostname ??= globalThis.location.hostname;
|
|
85
122
|
|
|
86
|
-
|
|
123
|
+
if (typeof setting === "string") {
|
|
124
|
+
return setting.replace("{hostname}", hostname);
|
|
125
|
+
} else {
|
|
126
|
+
return Object.fromEntries(
|
|
127
|
+
Object.entries(setting).map(([key, value]) => [
|
|
128
|
+
key,
|
|
129
|
+
{
|
|
130
|
+
endpoint: formatApp(hostname, key, value.endpoint),
|
|
131
|
+
webUrl: formatApp(hostname, key, value.webUrl)
|
|
132
|
+
}
|
|
133
|
+
])
|
|
134
|
+
);
|
|
135
|
+
}
|
|
87
136
|
}
|
|
88
137
|
}
|