@actdim/dynstruct 1.1.7 → 1.1.8
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/dist/appDomain/appContracts.d.ts +31 -25
- package/dist/appDomain/appContracts.d.ts.map +1 -1
- package/dist/appDomain/appContracts.es.js +10 -9
- package/dist/appDomain/appContracts.es.js.map +1 -1
- package/dist/appDomain/security/securityContracts.d.ts +18 -18
- package/dist/appDomain/security/securityContracts.d.ts.map +1 -1
- package/dist/appDomain/security/securityContracts.es.js +10 -10
- package/dist/appDomain/security/securityContracts.es.js.map +1 -1
- package/dist/appDomain/security/securityProvider.d.ts +8 -8
- package/dist/appDomain/security/securityProvider.d.ts.map +1 -1
- package/dist/appDomain/security/securityProvider.es.js +55 -54
- package/dist/appDomain/security/securityProvider.es.js.map +1 -1
- package/dist/componentModel/adapters.d.ts +1 -1
- package/dist/componentModel/adapters.es.js.map +1 -1
- package/dist/net/client.d.ts.map +1 -1
- package/dist/net/client.es.js +14 -12
- package/dist/net/client.es.js.map +1 -1
- package/dist/services/StorageService.d.ts.map +1 -1
- package/dist/services/StorageService.es.js +11 -10
- package/dist/services/StorageService.es.js.map +1 -1
- package/dist/services/react/NavService.d.ts +3 -2
- package/dist/services/react/NavService.d.ts.map +1 -1
- package/dist/services/react/NavService.es.js +5 -5
- package/dist/services/react/NavService.es.js.map +1 -1
- package/dist/services/react/StorageService.d.ts +1 -1
- package/dist/services/react/StorageService.d.ts.map +1 -1
- package/dist/services/react/StorageService.es.js +3 -3
- package/dist/services/react/StorageService.es.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import { AccessLevel as
|
|
2
|
-
import { getValuePrefixer as
|
|
1
|
+
import { $CONTEXT_GET as m, $ACL_GET as T, $AUTH_SIGNIN as c, $AUTH_SIGNOUT as d, $AUTH_REFRESH as k, $AUTH_ENSURE as f, $CONFIG_GET as C, $AUTH_SIGNIN_REQUEST as E, AccessLevel as y } from "./securityContracts.es.js";
|
|
2
|
+
import { getValuePrefixer as w } from "@actdim/utico/typeCore";
|
|
3
3
|
import "jwt-decode";
|
|
4
|
-
import { getResponseResult as
|
|
5
|
-
import { ApiError as
|
|
6
|
-
|
|
4
|
+
import { getResponseResult as l } from "../../net/request.es.js";
|
|
5
|
+
import { ApiError as u } from "../../net/apiError.es.js";
|
|
6
|
+
import { $CONFIG_GET as p, $STORE_GET as i, $STORE_REMOVE as o, $STORE_SET as h } from "../appContracts.es.js";
|
|
7
|
+
const v = {
|
|
7
8
|
accessToken: "ACCESS_TOKEN",
|
|
8
9
|
refreshToken: "REFRESH_TOKEN",
|
|
9
10
|
acl: "ACL",
|
|
10
11
|
userCredentials: "USER_CREDENTIALS",
|
|
11
12
|
userInfo: "USER_INFO"
|
|
12
13
|
};
|
|
13
|
-
class
|
|
14
|
+
class $ {
|
|
14
15
|
// private isAuthenticated: boolean;
|
|
15
16
|
// private isExpired: boolean;
|
|
16
17
|
msgBus;
|
|
@@ -28,28 +29,28 @@ class E {
|
|
|
28
29
|
fetcher = window;
|
|
29
30
|
init;
|
|
30
31
|
constructor(s) {
|
|
31
|
-
this.msgBus = s, this.init = this.
|
|
32
|
-
channel:
|
|
32
|
+
this.msgBus = s, this.init = this.updateConfig(), this.msgBus.provide({
|
|
33
|
+
channel: m,
|
|
33
34
|
callback: (e) => this.getContext()
|
|
34
35
|
}), this.msgBus.provide({
|
|
35
|
-
channel:
|
|
36
|
+
channel: T,
|
|
36
37
|
callback: (e) => this.getAcl(e.payload)
|
|
37
38
|
}), this.msgBus.provide({
|
|
38
|
-
channel:
|
|
39
|
-
callback: (e) => this.
|
|
39
|
+
channel: c,
|
|
40
|
+
callback: (e) => this.signIn(e.payload)
|
|
40
41
|
}), this.msgBus.provide({
|
|
41
|
-
channel:
|
|
42
|
-
callback: (e) => this.
|
|
42
|
+
channel: d,
|
|
43
|
+
callback: (e) => this.signOut()
|
|
43
44
|
}), this.msgBus.provide({
|
|
44
|
-
channel:
|
|
45
|
-
callback: (e) => this.
|
|
45
|
+
channel: k,
|
|
46
|
+
callback: (e) => this.refreshAuth()
|
|
46
47
|
}), this.msgBus.provide({
|
|
47
|
-
channel:
|
|
48
|
-
callback: (e) => this.
|
|
48
|
+
channel: f,
|
|
49
|
+
callback: (e) => this.ensureAuth()
|
|
49
50
|
}), this.msgBus.provide({
|
|
50
|
-
channel:
|
|
51
|
+
channel: C,
|
|
51
52
|
callback: async (e) => (await this.msgBus.request({
|
|
52
|
-
channel:
|
|
53
|
+
channel: p
|
|
53
54
|
})).payload?.security
|
|
54
55
|
});
|
|
55
56
|
}
|
|
@@ -63,27 +64,27 @@ class E {
|
|
|
63
64
|
tokenExpiresAt: this.tokenExpiresAt
|
|
64
65
|
};
|
|
65
66
|
}
|
|
66
|
-
async
|
|
67
|
+
async updateConfig() {
|
|
67
68
|
const s = await this.msgBus.request({
|
|
68
|
-
channel:
|
|
69
|
+
channel: p
|
|
69
70
|
});
|
|
70
71
|
this.domainConfig = s.payload.security;
|
|
71
|
-
const e =
|
|
72
|
-
this.storageKeys = e(
|
|
72
|
+
const e = w(`${this.domainConfig.id}/`);
|
|
73
|
+
this.storageKeys = e(v), await this.restoreData();
|
|
73
74
|
}
|
|
74
|
-
async
|
|
75
|
+
async restoreData() {
|
|
75
76
|
this.accessToken = (await this.msgBus.request({
|
|
76
|
-
channel:
|
|
77
|
+
channel: i,
|
|
77
78
|
payload: {
|
|
78
79
|
key: this.storageKeys.accessToken
|
|
79
80
|
}
|
|
80
81
|
})).payload.data.value, this.refreshToken = (await this.msgBus.request({
|
|
81
|
-
channel:
|
|
82
|
+
channel: i,
|
|
82
83
|
payload: {
|
|
83
84
|
key: this.storageKeys.refreshToken
|
|
84
85
|
}
|
|
85
86
|
})).payload.data.value, this.userCredentials = (await this.msgBus.request({
|
|
86
|
-
channel:
|
|
87
|
+
channel: i,
|
|
87
88
|
payload: {
|
|
88
89
|
key: this.storageKeys.userCredentials
|
|
89
90
|
}
|
|
@@ -91,12 +92,12 @@ class E {
|
|
|
91
92
|
username: null,
|
|
92
93
|
password: null
|
|
93
94
|
}, this.acl = (await this.msgBus.request({
|
|
94
|
-
channel:
|
|
95
|
+
channel: i,
|
|
95
96
|
payload: {
|
|
96
97
|
key: this.storageKeys.acl
|
|
97
98
|
}
|
|
98
99
|
})).payload.data.value || null, this.accessToken && this.msgBus.request({
|
|
99
|
-
channel:
|
|
100
|
+
channel: c,
|
|
100
101
|
group: "out",
|
|
101
102
|
payload: this.getContext()
|
|
102
103
|
});
|
|
@@ -114,48 +115,48 @@ class E {
|
|
|
114
115
|
// }
|
|
115
116
|
// };
|
|
116
117
|
// removeSavedData
|
|
117
|
-
async
|
|
118
|
+
async clearSavedData() {
|
|
118
119
|
this.accessToken = null, await this.msgBus.request({
|
|
119
|
-
channel:
|
|
120
|
+
channel: o,
|
|
120
121
|
payload: {
|
|
121
122
|
key: this.storageKeys.accessToken
|
|
122
123
|
}
|
|
123
124
|
}), this.refreshToken = null, await this.msgBus.request({
|
|
124
|
-
channel:
|
|
125
|
+
channel: o,
|
|
125
126
|
payload: {
|
|
126
127
|
key: this.storageKeys.refreshToken
|
|
127
128
|
}
|
|
128
129
|
}), this.userCredentials = null, await this.msgBus.request({
|
|
129
|
-
channel:
|
|
130
|
+
channel: o,
|
|
130
131
|
payload: {
|
|
131
132
|
key: this.storageKeys.userCredentials
|
|
132
133
|
}
|
|
133
134
|
}), this.acl = null, await this.msgBus.request({
|
|
134
|
-
channel:
|
|
135
|
+
channel: o,
|
|
135
136
|
payload: {
|
|
136
137
|
key: this.storageKeys.acl
|
|
137
138
|
}
|
|
138
139
|
});
|
|
139
140
|
}
|
|
140
|
-
async
|
|
141
|
+
async ensureAuth() {
|
|
141
142
|
this.accessToken = null, this.acl = null;
|
|
142
143
|
const s = this.msgBus.once({
|
|
143
|
-
channel:
|
|
144
|
+
channel: c,
|
|
144
145
|
group: "out"
|
|
145
146
|
}), e = async () => {
|
|
146
147
|
throw await this.msgBus.once({
|
|
147
|
-
channel:
|
|
148
|
+
channel: d,
|
|
148
149
|
group: "out"
|
|
149
150
|
}), new Error("Auth failed: login aborted");
|
|
150
151
|
};
|
|
151
152
|
this.msgBus.send({
|
|
152
|
-
channel:
|
|
153
|
+
channel: E,
|
|
153
154
|
payload: {
|
|
154
155
|
callbackUrl: window.location.pathname + window.location.search
|
|
155
156
|
}
|
|
156
157
|
}), await Promise.race([s, e]);
|
|
157
158
|
}
|
|
158
|
-
async
|
|
159
|
+
async signIn(s) {
|
|
159
160
|
let e = this.domainConfig.routes?.authSignIn;
|
|
160
161
|
e = e.replace(/[?&]$/, "");
|
|
161
162
|
const n = JSON.stringify(s), t = {
|
|
@@ -170,38 +171,38 @@ class E {
|
|
|
170
171
|
...t,
|
|
171
172
|
status: "executing"
|
|
172
173
|
}, a = await this.fetcher.fetch(e, t);
|
|
173
|
-
await
|
|
174
|
-
let
|
|
175
|
-
return this.userCredentials = s, this.accessToken =
|
|
174
|
+
await l(a, r), u.assert(a, r);
|
|
175
|
+
let g = a.resolved.json;
|
|
176
|
+
return this.userCredentials = s, this.accessToken = g.accessToken, this.refreshToken = g.refreshToken, this.saveData(), this.getContext();
|
|
176
177
|
}
|
|
177
|
-
async
|
|
178
|
+
async saveData() {
|
|
178
179
|
await this.msgBus.request({
|
|
179
|
-
channel:
|
|
180
|
+
channel: h,
|
|
180
181
|
payload: {
|
|
181
182
|
key: this.storageKeys.accessToken,
|
|
182
183
|
value: this.accessToken || null
|
|
183
184
|
}
|
|
184
185
|
}), await this.msgBus.request({
|
|
185
|
-
channel:
|
|
186
|
+
channel: h,
|
|
186
187
|
payload: {
|
|
187
188
|
key: this.storageKeys.refreshToken,
|
|
188
189
|
value: this.refreshToken || null
|
|
189
190
|
}
|
|
190
191
|
}), await this.msgBus.request({
|
|
191
|
-
channel:
|
|
192
|
+
channel: h,
|
|
192
193
|
payload: {
|
|
193
194
|
key: this.storageKeys.userCredentials,
|
|
194
195
|
value: this.userCredentials ? this.userCredentials : null
|
|
195
196
|
}
|
|
196
197
|
}), await this.msgBus.request({
|
|
197
|
-
channel:
|
|
198
|
+
channel: h,
|
|
198
199
|
payload: {
|
|
199
200
|
key: this.storageKeys.acl,
|
|
200
201
|
value: this.acl ? this.acl : null
|
|
201
202
|
}
|
|
202
203
|
});
|
|
203
204
|
}
|
|
204
|
-
async
|
|
205
|
+
async signOut() {
|
|
205
206
|
let s = this.domainConfig.routes?.authSignOut;
|
|
206
207
|
s && (s = s.replace(/[?&]$/, ""));
|
|
207
208
|
const e = {
|
|
@@ -215,9 +216,9 @@ class E {
|
|
|
215
216
|
...e,
|
|
216
217
|
status: "executing"
|
|
217
218
|
}, t = await this.fetcher.fetch(s, e);
|
|
218
|
-
await
|
|
219
|
+
await l(t, n), u.assert(t, n), this.clearSavedData();
|
|
219
220
|
}
|
|
220
|
-
async
|
|
221
|
+
async refreshAuth() {
|
|
221
222
|
let s = this.domainConfig.routes?.authRefresh;
|
|
222
223
|
s && (s = s.replace(/[?&]$/, ""));
|
|
223
224
|
let e = {
|
|
@@ -236,19 +237,19 @@ class E {
|
|
|
236
237
|
...t,
|
|
237
238
|
status: "executing"
|
|
238
239
|
}, a = await this.fetcher.fetch(s, t);
|
|
239
|
-
return await
|
|
240
|
+
return await l(a, r), u.assert(a, r), e = a.resolved.json, this.accessToken = e.accessToken, this.refreshToken = e.refreshToken, this.saveData(), this.getContext();
|
|
240
241
|
}
|
|
241
242
|
async getAcl(s) {
|
|
242
243
|
return {
|
|
243
|
-
[
|
|
244
|
+
[y.Full]: ""
|
|
244
245
|
};
|
|
245
246
|
}
|
|
246
247
|
// authorize
|
|
247
|
-
async verifyAccess(s, e =
|
|
248
|
+
async verifyAccess(s, e = y.Full) {
|
|
248
249
|
return this.getAcl(s), !1;
|
|
249
250
|
}
|
|
250
251
|
}
|
|
251
252
|
export {
|
|
252
|
-
|
|
253
|
+
$ as SecurityProvider
|
|
253
254
|
};
|
|
254
255
|
//# sourceMappingURL=securityProvider.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"securityProvider.es.js","sources":["../../../src/appDomain/security/securityProvider.ts"],"sourcesContent":["import {\r\n AccessLevel,\r\n IAccessDescriptor,\r\n ISecurable,\r\n BaseSecurityDomainConfig,\r\n UserCredentials,\r\n SecurityTokens,\r\n SecurityContext\r\n} from \"./securityContracts\";\r\nimport { getValuePrefixer } from \"@actdim/utico/typeCore\";\r\nimport { jwtDecode } from \"jwt-decode\";\r\nimport { getResponseResult, IRequestParams, IRequestState, IResponseState } from \"@/net/request\";\r\nimport { ApiError } from \"@/net/apiError\";\r\nimport { MsgBus } from \"@actdim/msgmesh/contracts\";\r\nimport { BaseAppMsgStruct } from \"@/appDomain/appContracts\";\r\n\r\nconst userNameClaim = \"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\";\r\n\r\n// JwtTokenPayload\r\ntype TokenPayload = {\r\n [userNameClaim]: string;\r\n};\r\n\r\n// Access denied\r\n// Insufficient privileges to perform this operation\r\nconst defaultAccessDeniedReason = \"Insufficient privileges. Contact your system Administrator.\";\r\n\r\nconst storageKeys = {\r\n accessToken: \"ACCESS_TOKEN\",\r\n refreshToken: \"REFRESH_TOKEN\",\r\n acl: \"ACL\",\r\n userCredentials: \"USER_CREDENTIALS\",\r\n userInfo: \"USER_INFO\"\r\n};\r\n\r\nfunction decodeJWTToken<T extends TokenPayload>(token: string): T {\r\n if (!token) {\r\n return null;\r\n }\r\n try {\r\n return jwtDecode<T>(this.accessToken);\r\n } catch {\r\n // something wrong with the token\r\n return null;\r\n }\r\n}\r\n\r\nexport class SecurityProvider<TUserInfo = any> {\r\n // private isAuthenticated: boolean;\r\n\r\n // private isExpired: boolean;\r\n\r\n private msgBus: MsgBus<BaseAppMsgStruct>;\r\n\r\n private domainConfig: BaseSecurityDomainConfig;\r\n\r\n private storageKeys: typeof storageKeys;\r\n\r\n private accessToken: string;\r\n\r\n private refreshToken: string;\r\n\r\n private userCredentials: UserCredentials;\r\n\r\n private userInfo: TUserInfo;\r\n\r\n // private authority: string;\r\n private authProvider: string;\r\n\r\n private tokenExpiresAt: string;\r\n\r\n // RBAC vs ABAC vs PBAC: https://habr.com/ru/companies/otus/articles/698080/\r\n private acl: any;\r\n\r\n private fetcher: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> } = window;\r\n\r\n private init: Promise<any>;\r\n\r\n constructor(msgBus: MsgBus<BaseAppMsgStruct>) {\r\n this.msgBus = msgBus;\r\n\r\n this.init = this.updateConfigAsync();\r\n\r\n // TODO: support custom requests\r\n\r\n this.msgBus.provide({\r\n channel: \"APP-SECURITY-GET-CONTEXT\",\r\n callback: (msg) => {\r\n return this.getContext();\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: \"APP-SECURITY-GET-ACL\",\r\n callback: (msg) => {\r\n return this.getAcl(msg.payload);\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: \"APP-SECURITY-AUTH-SIGNIN\",\r\n callback: (msg) => {\r\n return this.signInAsync(msg.payload);\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: \"APP-SECURITY-AUTH-SIGNOUT\",\r\n callback: (msg) => {\r\n return this.signOutAsync();\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: \"APP-SECURITY-AUTH-REFRESH\",\r\n callback: (msg) => {\r\n return this.refreshAsync();\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: \"APP-SECURITY-REQUEST-AUTH\",\r\n callback: (msg) => {\r\n return this.requestAuthorize();\r\n }\r\n });\r\n\r\n // HELPER\r\n this.msgBus.provide({\r\n channel: \"APP-SECURITY-GET-CONFIG\",\r\n callback: async (msg) => {\r\n return (\r\n await this.msgBus.request({\r\n channel: \"APP-CONFIG-GET\"\r\n })\r\n ).payload?.security;\r\n }\r\n });\r\n }\r\n\r\n public getContext(): SecurityContext {\r\n return {\r\n accessToken: this.accessToken,\r\n refreshToken: this.refreshToken,\r\n userInfo: this.userInfo,\r\n authProvider: this.authProvider,\r\n domain: this.domain,\r\n tokenExpiresAt: this.tokenExpiresAt\r\n };\r\n }\r\n\r\n private async updateConfigAsync() {\r\n const msg = await this.msgBus.request({\r\n channel: \"APP-CONFIG-GET\"\r\n });\r\n this.domainConfig = msg.payload.security;\r\n const prefixer = getValuePrefixer<typeof storageKeys>(`${this.domainConfig.id}/`);\r\n this.storageKeys = prefixer(storageKeys);\r\n await this.restoreDataAsync();\r\n }\r\n\r\n async restoreDataAsync() {\r\n this.accessToken = (\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-GET\",\r\n payload: {\r\n key: this.storageKeys.accessToken\r\n }\r\n })\r\n ).payload.data.value;\r\n this.refreshToken = (\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-GET\",\r\n payload: {\r\n key: this.storageKeys.refreshToken\r\n }\r\n })\r\n ).payload.data.value;\r\n this.userCredentials = (\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-GET\",\r\n payload: {\r\n key: this.storageKeys.userCredentials\r\n }\r\n })\r\n ).payload.data.value || {\r\n username: null,\r\n password: null\r\n }; \r\n\r\n this.acl = (\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-GET\",\r\n payload: {\r\n key: this.storageKeys.acl\r\n }\r\n })\r\n ).payload.data.value || null;\r\n\r\n if (this.accessToken) {\r\n this.msgBus.request({\r\n channel: \"APP-SECURITY-AUTH-SIGNIN\",\r\n group: \"out\",\r\n payload: this.getContext()\r\n });\r\n }\r\n }\r\n\r\n public get domain(): string {\r\n return this.domainConfig.id;\r\n }\r\n\r\n // cleanUserAndActionsStorage = (): void => {\r\n // const obsoleteKeysRegexMatch = /^(user|actions)@.+$/;\r\n // for (let i = localStorage.length - 1; i >= 0; i--) {\r\n // const key = localStorage.key(i);\r\n // if (key && obsoleteKeysRegexMatch.test(key)) {\r\n // localStorage.removeItem(key);\r\n // }\r\n // }\r\n // };\r\n\r\n // removeSavedData\r\n async clearSavedDataAsync() {\r\n this.accessToken = null;\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-REMOVE\",\r\n payload: {\r\n key: this.storageKeys.accessToken\r\n }\r\n });\r\n this.refreshToken = null;\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-REMOVE\",\r\n payload: {\r\n key: this.storageKeys.refreshToken\r\n }\r\n });\r\n this.userCredentials = null;\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-REMOVE\",\r\n payload: {\r\n key: this.storageKeys.userCredentials\r\n }\r\n });\r\n this.acl = null;\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-REMOVE\",\r\n payload: {\r\n key: this.storageKeys.acl\r\n }\r\n });\r\n }\r\n\r\n async requestAuthorize() {\r\n this.accessToken = null;\r\n this.acl = null;\r\n\r\n const signIn = this.msgBus.once({\r\n channel: \"APP-SECURITY-AUTH-SIGNIN\",\r\n group: \"out\"\r\n });\r\n\r\n const signOut = async () => {\r\n await this.msgBus.once({\r\n channel: \"APP-SECURITY-AUTH-SIGNOUT\",\r\n group: \"out\"\r\n });\r\n throw new Error(\"Auth failed: login aborted\");\r\n };\r\n\r\n this.msgBus.send({\r\n channel: \"APP-SECURITY-REQUEST-AUTH-SIGNIN\",\r\n payload: {\r\n callbackUrl: window.location.pathname + window.location.search\r\n }\r\n });\r\n await Promise.race([signIn, signOut]);\r\n }\r\n\r\n async signInAsync(credentials: UserCredentials) {\r\n let url = this.domainConfig.routes?.authSignIn;\r\n\r\n url = url.replace(/[?&]$/, \"\");\r\n\r\n const content = JSON.stringify(credentials);\r\n\r\n // application/x-www-form-urlencoded?\r\n // username=&password=\r\n\r\n const requestParams: IRequestParams = {\r\n url: url,\r\n body: content,\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"text/plain\"\r\n }\r\n };\r\n\r\n const request: IRequestState = {\r\n ...requestParams,\r\n status: \"executing\"\r\n };\r\n\r\n const response: IResponseState = await this.fetcher.fetch(url, requestParams);\r\n await getResponseResult(response, request);\r\n ApiError.assert(response, request);\r\n\r\n let tokens = response.resolved.json as SecurityTokens;\r\n\r\n this.userCredentials = credentials;\r\n\r\n this.accessToken = tokens.accessToken;\r\n this.refreshToken = tokens.refreshToken;\r\n // this.acl = ...;\r\n\r\n this.saveDataAsync();\r\n\r\n return this.getContext();\r\n }\r\n\r\n async saveDataAsync() {\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-SET\",\r\n payload: {\r\n key: this.storageKeys.accessToken,\r\n value: this.accessToken || null\r\n }\r\n });\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-SET\",\r\n payload: {\r\n key: this.storageKeys.refreshToken,\r\n value: this.refreshToken || null\r\n }\r\n });\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-SET\",\r\n payload: {\r\n key: this.storageKeys.userCredentials,\r\n value: this.userCredentials ? this.userCredentials : null\r\n }\r\n });\r\n await this.msgBus.request({\r\n channel: \"APP-KV-STORE-SET\",\r\n payload: {\r\n key: this.storageKeys.acl,\r\n value: this.acl ? this.acl : null\r\n }\r\n });\r\n }\r\n\r\n async signOutAsync() {\r\n let url = this.domainConfig.routes?.authSignOut;\r\n if (url) {\r\n url = url.replace(/[?&]$/, \"\");\r\n }\r\n\r\n const requestParams: IRequestParams = {\r\n url: url,\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"text/plain\"\r\n }\r\n };\r\n\r\n const request: IRequestState = {\r\n ...requestParams,\r\n status: \"executing\"\r\n };\r\n\r\n const response: IResponseState = await this.fetcher.fetch(url, requestParams);\r\n await getResponseResult(response, request);\r\n ApiError.assert(response, request);\r\n\r\n // this.accessToken = null;\r\n // this.refreshToken = null;\r\n // this.userCredentials = null;\r\n // this.acl = null;\r\n // this.saveDataAsync();\r\n this.clearSavedDataAsync();\r\n }\r\n\r\n async refreshAsync() {\r\n let url = this.domainConfig.routes?.authRefresh;\r\n if (url) {\r\n url = url.replace(/[?&]$/, \"\");\r\n }\r\n\r\n let tokens: SecurityTokens = {\r\n refreshToken: this.refreshToken\r\n };\r\n\r\n const content = JSON.stringify(tokens);\r\n // const content = tokens;\r\n\r\n const requestParams: IRequestParams = {\r\n url: url,\r\n body: content,\r\n method: \"POST\",\r\n // useAuth: true,\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"text/plain\"\r\n }\r\n };\r\n\r\n const request: IRequestState = {\r\n ...requestParams,\r\n status: \"executing\"\r\n };\r\n\r\n const response: IResponseState = await this.fetcher.fetch(url, requestParams);\r\n await getResponseResult(response, request);\r\n ApiError.assert(response, request);\r\n\r\n tokens = response.resolved.json as SecurityTokens;\r\n\r\n this.accessToken = tokens.accessToken;\r\n this.refreshToken = tokens.refreshToken;\r\n // this.userInfo = ...; // TODO\r\n // this.acl = ...;\r\n\r\n this.saveDataAsync();\r\n\r\n return this.getContext();\r\n }\r\n\r\n async getAcl<T extends ISecurable>(obj: T) {\r\n // TODO: read from this.acl\r\n\r\n return {\r\n [AccessLevel.Full]: \"\"\r\n } as IAccessDescriptor;\r\n }\r\n\r\n // authorize\r\n async verifyAccess<T extends ISecurable>(obj: T, accessLevel = AccessLevel.Full) {\r\n const acl = this.getAcl(obj);\r\n\r\n // TODO: check accessDescriptors\r\n\r\n return false;\r\n }\r\n}\r\n"],"names":["storageKeys","SecurityProvider","msgBus","msg","prefixer","getValuePrefixer","signIn","signOut","credentials","url","content","requestParams","request","response","getResponseResult","ApiError","tokens","obj","AccessLevel","accessLevel"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"securityProvider.es.js","sources":["../../../src/appDomain/security/securityProvider.ts"],"sourcesContent":["import {\r\n AccessLevel,\r\n IAccessDescriptor,\r\n ISecurable,\r\n BaseSecurityDomainConfig,\r\n UserCredentials,\r\n SecurityTokens,\r\n SecurityContext,\r\n $AUTH_SIGNIN,\r\n $AUTH_SIGNOUT,\r\n $AUTH_SIGNIN_REQUEST,\r\n $CONTEXT_GET,\r\n $ACL_GET,\r\n $AUTH_REFRESH,\r\n $AUTH_ENSURE,\r\n $CONFIG_GET as $SECURITY_CONFIG_GET\r\n} from \"./securityContracts\";\r\nimport { getValuePrefixer } from \"@actdim/utico/typeCore\";\r\nimport { jwtDecode } from \"jwt-decode\";\r\nimport { getResponseResult, IRequestParams, IRequestState, IResponseState } from \"@/net/request\";\r\nimport { ApiError } from \"@/net/apiError\";\r\nimport { MsgBus } from \"@actdim/msgmesh/contracts\";\r\nimport { $CONFIG_GET, $STORE_GET, $STORE_REMOVE, $STORE_SET, BaseAppMsgStruct } from \"@/appDomain/appContracts\";\r\n\r\nconst userNameClaim = \"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name\";\r\n\r\n// JwtTokenPayload\r\ntype TokenPayload = {\r\n [userNameClaim]: string;\r\n};\r\n\r\n// Access denied\r\n// Insufficient privileges to perform this operation\r\nconst defaultAccessDeniedReason = \"Insufficient privileges. Contact your system Administrator.\";\r\n\r\nconst storageKeys = {\r\n accessToken: \"ACCESS_TOKEN\",\r\n refreshToken: \"REFRESH_TOKEN\",\r\n acl: \"ACL\",\r\n userCredentials: \"USER_CREDENTIALS\",\r\n userInfo: \"USER_INFO\"\r\n};\r\n\r\nfunction decodeJWTToken<T extends TokenPayload>(token: string): T {\r\n if (!token) {\r\n return null;\r\n }\r\n try {\r\n return jwtDecode<T>(this.accessToken);\r\n } catch {\r\n // something wrong with the token\r\n return null;\r\n }\r\n}\r\n\r\nexport class SecurityProvider<TUserInfo = any> {\r\n // private isAuthenticated: boolean;\r\n\r\n // private isExpired: boolean;\r\n\r\n private msgBus: MsgBus<BaseAppMsgStruct>;\r\n\r\n private domainConfig: BaseSecurityDomainConfig;\r\n\r\n private storageKeys: typeof storageKeys;\r\n\r\n private accessToken: string;\r\n\r\n private refreshToken: string;\r\n\r\n private userCredentials: UserCredentials;\r\n\r\n private userInfo: TUserInfo;\r\n\r\n // private authority: string;\r\n private authProvider: string;\r\n\r\n private tokenExpiresAt: string;\r\n\r\n // RBAC vs ABAC vs PBAC: https://habr.com/ru/companies/otus/articles/698080/\r\n private acl: any;\r\n\r\n private fetcher: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> } = window;\r\n\r\n private init: Promise<any>;\r\n\r\n constructor(msgBus: MsgBus<BaseAppMsgStruct>) {\r\n this.msgBus = msgBus;\r\n\r\n this.init = this.updateConfig();\r\n\r\n // TODO: support custom requests\r\n\r\n this.msgBus.provide({\r\n channel: $CONTEXT_GET,\r\n callback: (msg) => {\r\n return this.getContext();\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: $ACL_GET,\r\n callback: (msg) => {\r\n return this.getAcl(msg.payload);\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: $AUTH_SIGNIN,\r\n callback: (msg) => {\r\n return this.signIn(msg.payload);\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: $AUTH_SIGNOUT,\r\n callback: (msg) => {\r\n return this.signOut();\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: $AUTH_REFRESH,\r\n callback: (msg) => {\r\n return this.refreshAuth();\r\n }\r\n });\r\n\r\n this.msgBus.provide({\r\n channel: $AUTH_ENSURE,\r\n callback: (msg) => {\r\n return this.ensureAuth();\r\n }\r\n });\r\n\r\n // HELPER\r\n this.msgBus.provide({\r\n channel: $SECURITY_CONFIG_GET,\r\n callback: async (msg) => {\r\n return (\r\n await this.msgBus.request({\r\n channel: $CONFIG_GET\r\n })\r\n ).payload?.security;\r\n }\r\n });\r\n }\r\n\r\n public getContext(): SecurityContext {\r\n return {\r\n accessToken: this.accessToken,\r\n refreshToken: this.refreshToken,\r\n userInfo: this.userInfo,\r\n authProvider: this.authProvider,\r\n domain: this.domain,\r\n tokenExpiresAt: this.tokenExpiresAt\r\n };\r\n }\r\n\r\n private async updateConfig() {\r\n const msg = await this.msgBus.request({\r\n channel: $CONFIG_GET\r\n });\r\n this.domainConfig = msg.payload.security;\r\n const prefixer = getValuePrefixer<typeof storageKeys>(`${this.domainConfig.id}/`);\r\n this.storageKeys = prefixer(storageKeys);\r\n await this.restoreData();\r\n }\r\n\r\n async restoreData() {\r\n this.accessToken = (\r\n await this.msgBus.request({\r\n channel: $STORE_GET,\r\n payload: {\r\n key: this.storageKeys.accessToken\r\n }\r\n })\r\n ).payload.data.value;\r\n this.refreshToken = (\r\n await this.msgBus.request({\r\n channel: $STORE_GET,\r\n payload: {\r\n key: this.storageKeys.refreshToken\r\n }\r\n })\r\n ).payload.data.value;\r\n this.userCredentials = (\r\n await this.msgBus.request({\r\n channel: $STORE_GET,\r\n payload: {\r\n key: this.storageKeys.userCredentials\r\n }\r\n })\r\n ).payload.data.value || {\r\n username: null,\r\n password: null\r\n };\r\n\r\n this.acl = (\r\n await this.msgBus.request({\r\n channel: $STORE_GET,\r\n payload: {\r\n key: this.storageKeys.acl\r\n }\r\n })\r\n ).payload.data.value || null;\r\n\r\n if (this.accessToken) {\r\n this.msgBus.request({\r\n channel: $AUTH_SIGNIN,\r\n group: \"out\",\r\n payload: this.getContext()\r\n });\r\n }\r\n }\r\n\r\n public get domain(): string {\r\n return this.domainConfig.id;\r\n }\r\n\r\n // cleanUserAndActionsStorage = (): void => {\r\n // const obsoleteKeysRegexMatch = /^(user|actions)@.+$/;\r\n // for (let i = localStorage.length - 1; i >= 0; i--) {\r\n // const key = localStorage.key(i);\r\n // if (key && obsoleteKeysRegexMatch.test(key)) {\r\n // localStorage.removeItem(key);\r\n // }\r\n // }\r\n // };\r\n\r\n // removeSavedData\r\n async clearSavedData() {\r\n this.accessToken = null;\r\n await this.msgBus.request({\r\n channel: $STORE_REMOVE,\r\n payload: {\r\n key: this.storageKeys.accessToken\r\n }\r\n });\r\n this.refreshToken = null;\r\n await this.msgBus.request({\r\n channel: $STORE_REMOVE,\r\n payload: {\r\n key: this.storageKeys.refreshToken\r\n }\r\n });\r\n this.userCredentials = null;\r\n await this.msgBus.request({\r\n channel: $STORE_REMOVE,\r\n payload: {\r\n key: this.storageKeys.userCredentials\r\n }\r\n });\r\n this.acl = null;\r\n await this.msgBus.request({\r\n channel: $STORE_REMOVE,\r\n payload: {\r\n key: this.storageKeys.acl\r\n }\r\n });\r\n }\r\n\r\n async ensureAuth() {\r\n this.accessToken = null;\r\n this.acl = null;\r\n\r\n const signIn = this.msgBus.once({\r\n channel: $AUTH_SIGNIN,\r\n group: \"out\"\r\n });\r\n\r\n const signOut = async () => {\r\n await this.msgBus.once({\r\n channel: $AUTH_SIGNOUT,\r\n group: \"out\"\r\n });\r\n throw new Error(\"Auth failed: login aborted\");\r\n };\r\n\r\n this.msgBus.send({\r\n channel: $AUTH_SIGNIN_REQUEST,\r\n payload: {\r\n callbackUrl: window.location.pathname + window.location.search\r\n }\r\n });\r\n await Promise.race([signIn, signOut]);\r\n }\r\n\r\n async signIn(credentials: UserCredentials) {\r\n let url = this.domainConfig.routes?.authSignIn;\r\n\r\n url = url.replace(/[?&]$/, \"\");\r\n\r\n const content = JSON.stringify(credentials);\r\n\r\n // application/x-www-form-urlencoded?\r\n // username=&password=\r\n\r\n const requestParams: IRequestParams = {\r\n url: url,\r\n body: content,\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"text/plain\"\r\n }\r\n };\r\n\r\n const request: IRequestState = {\r\n ...requestParams,\r\n status: \"executing\"\r\n };\r\n\r\n const response: IResponseState = await this.fetcher.fetch(url, requestParams);\r\n await getResponseResult(response, request);\r\n ApiError.assert(response, request);\r\n\r\n let tokens = response.resolved.json as SecurityTokens;\r\n\r\n this.userCredentials = credentials;\r\n\r\n this.accessToken = tokens.accessToken;\r\n this.refreshToken = tokens.refreshToken;\r\n // this.acl = ...;\r\n\r\n this.saveData();\r\n\r\n return this.getContext();\r\n }\r\n\r\n async saveData() {\r\n await this.msgBus.request({\r\n channel: $STORE_SET,\r\n payload: {\r\n key: this.storageKeys.accessToken,\r\n value: this.accessToken || null\r\n }\r\n });\r\n await this.msgBus.request({\r\n channel: $STORE_SET,\r\n payload: {\r\n key: this.storageKeys.refreshToken,\r\n value: this.refreshToken || null\r\n }\r\n });\r\n await this.msgBus.request({\r\n channel: $STORE_SET,\r\n payload: {\r\n key: this.storageKeys.userCredentials,\r\n value: this.userCredentials ? this.userCredentials : null\r\n }\r\n });\r\n await this.msgBus.request({\r\n channel: $STORE_SET,\r\n payload: {\r\n key: this.storageKeys.acl,\r\n value: this.acl ? this.acl : null\r\n }\r\n });\r\n }\r\n\r\n async signOut() {\r\n let url = this.domainConfig.routes?.authSignOut;\r\n if (url) {\r\n url = url.replace(/[?&]$/, \"\");\r\n }\r\n\r\n const requestParams: IRequestParams = {\r\n url: url,\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"text/plain\"\r\n }\r\n };\r\n\r\n const request: IRequestState = {\r\n ...requestParams,\r\n status: \"executing\"\r\n };\r\n\r\n const response: IResponseState = await this.fetcher.fetch(url, requestParams);\r\n await getResponseResult(response, request);\r\n ApiError.assert(response, request);\r\n\r\n // this.accessToken = null;\r\n // this.refreshToken = null;\r\n // this.userCredentials = null;\r\n // this.acl = null;\r\n // this.saveData();\r\n this.clearSavedData();\r\n }\r\n\r\n async refreshAuth() {\r\n let url = this.domainConfig.routes?.authRefresh;\r\n if (url) {\r\n url = url.replace(/[?&]$/, \"\");\r\n }\r\n\r\n let tokens: SecurityTokens = {\r\n refreshToken: this.refreshToken\r\n };\r\n\r\n const content = JSON.stringify(tokens);\r\n // const content = tokens;\r\n\r\n const requestParams: IRequestParams = {\r\n url: url,\r\n body: content,\r\n method: \"POST\",\r\n // useAuth: true,\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n Accept: \"text/plain\"\r\n }\r\n };\r\n\r\n const request: IRequestState = {\r\n ...requestParams,\r\n status: \"executing\"\r\n };\r\n\r\n const response: IResponseState = await this.fetcher.fetch(url, requestParams);\r\n await getResponseResult(response, request);\r\n ApiError.assert(response, request);\r\n\r\n tokens = response.resolved.json as SecurityTokens;\r\n\r\n this.accessToken = tokens.accessToken;\r\n this.refreshToken = tokens.refreshToken;\r\n // this.userInfo = ...; // TODO\r\n // this.acl = ...;\r\n\r\n this.saveData();\r\n\r\n return this.getContext();\r\n }\r\n\r\n async getAcl<T extends ISecurable>(obj: T) {\r\n // TODO: read from this.acl\r\n\r\n return {\r\n [AccessLevel.Full]: \"\"\r\n } as IAccessDescriptor;\r\n }\r\n\r\n // authorize\r\n async verifyAccess<T extends ISecurable>(obj: T, accessLevel = AccessLevel.Full) {\r\n const acl = this.getAcl(obj);\r\n\r\n // TODO: check accessDescriptors\r\n\r\n return false;\r\n }\r\n}\r\n"],"names":["storageKeys","SecurityProvider","msgBus","$CONTEXT_GET","msg","$ACL_GET","$AUTH_SIGNIN","$AUTH_SIGNOUT","$AUTH_REFRESH","$AUTH_ENSURE","$SECURITY_CONFIG_GET","$CONFIG_GET","prefixer","getValuePrefixer","$STORE_GET","$STORE_REMOVE","signIn","signOut","$AUTH_SIGNIN_REQUEST","credentials","url","content","requestParams","request","response","getResponseResult","ApiError","tokens","$STORE_SET","obj","AccessLevel","accessLevel"],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ export type MsgProviderAdapter = {
|
|
|
6
6
|
};
|
|
7
7
|
export declare function registerAdapters(msgBus: MsgBus<any>, adapters: MsgProviderAdapter[], abortSignal?: AbortSignal): void;
|
|
8
8
|
export type BaseServiceSuffix = 'CLIENT' | 'API' | 'SERVICE' | 'FETCHER' | 'CONTROLLER' | 'LOADER' | 'REPOSITORY' | 'PROVIDER';
|
|
9
|
-
export type BaseWordSeparator = "
|
|
9
|
+
export type BaseWordSeparator = ".";
|
|
10
10
|
export type ToMsgChannelPrefix<TServiceName extends string, Prefix extends string, Suffix extends string = BaseServiceSuffix, WordSeparator extends string = BaseWordSeparator> = `${Prefix}${WordSeparator}${RemoveSuffix<Uppercase<TServiceName>, Suffix>}${WordSeparator}`;
|
|
11
11
|
type ToMsgStructSource<TService, TPrefix extends string, TSkip extends keyof TService = never> = Filter<ToUpper<AddPrefix<Skip<TService, TSkip>, TPrefix>>, Func>;
|
|
12
12
|
export type ToMsgStruct<TService, TPrefix extends string, TSkip extends keyof TService = never, TMsgStructSource = ToMsgStructSource<TService, TPrefix, TSkip>> = MsgStructFactory<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.es.js","sources":["../../src/componentModel/adapters.ts"],"sourcesContent":["import { ClientBase } from \"@/net/client\";\r\nimport { MsgBus, MsgStructFactory } from \"@actdim/msgmesh/contracts\";\r\nimport { AddPrefix, Filter, Func, RemoveSuffix, Skip, ToUpper } from \"@actdim/utico/typeCore\";\r\n\r\nconst getMethodNames = (client: any) => {\r\n // return new Set(...)\r\n return Object.getOwnPropertyNames(client).filter(\r\n (name) => name !== 'constructor' && typeof client[name] === 'function',\r\n );\r\n};\r\n\r\n// const baseMethodNames = getMethodNames(ClientBase.prototype);\r\n\r\n// ServiceMsgDispatcher\r\nexport type MsgProviderAdapter = {\r\n service: any;\r\n // channelResolver/channelMapper\r\n channelSelector: (service: any, methodName: string) => string;\r\n};\r\n\r\nexport function registerAdapters(msgBus: MsgBus<any>, adapters: MsgProviderAdapter[], abortSignal?: AbortSignal) {\r\n if (adapters) {\r\n for (const adapter of adapters) {\r\n const { service, channelSelector } = adapter;\r\n if (!service || !channelSelector) {\r\n throw new Error(\"Service and channelSelector are required for an adapter\")\r\n }\r\n for (const methodName of getMethodNames(Object.getPrototypeOf(service))) {\r\n const channel = channelSelector?.(service, methodName);\r\n if (channel) {\r\n msgBus.provide({\r\n channel: channel,\r\n topic: '/.*/',\r\n callback: (msg) => {\r\n return (service[methodName] as Func)(...((msg.payload || []) as any[]));\r\n },\r\n options: {\r\n abortSignal: abortSignal\r\n }\r\n });\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport type BaseServiceSuffix = 'CLIENT' | 'API' | 'SERVICE' | 'FETCHER' | 'CONTROLLER' | 'LOADER' | 'REPOSITORY' | 'PROVIDER';\r\nexport type BaseWordSeparator = \"
|
|
1
|
+
{"version":3,"file":"adapters.es.js","sources":["../../src/componentModel/adapters.ts"],"sourcesContent":["import { ClientBase } from \"@/net/client\";\r\nimport { MsgBus, MsgStructFactory } from \"@actdim/msgmesh/contracts\";\r\nimport { AddPrefix, Filter, Func, RemoveSuffix, Skip, ToUpper } from \"@actdim/utico/typeCore\";\r\n\r\nconst getMethodNames = (client: any) => {\r\n // return new Set(...)\r\n return Object.getOwnPropertyNames(client).filter(\r\n (name) => name !== 'constructor' && typeof client[name] === 'function',\r\n );\r\n};\r\n\r\n// const baseMethodNames = getMethodNames(ClientBase.prototype);\r\n\r\n// ServiceMsgDispatcher\r\nexport type MsgProviderAdapter = {\r\n service: any;\r\n // channelResolver/channelMapper\r\n channelSelector: (service: any, methodName: string) => string;\r\n};\r\n\r\nexport function registerAdapters(msgBus: MsgBus<any>, adapters: MsgProviderAdapter[], abortSignal?: AbortSignal) {\r\n if (adapters) {\r\n for (const adapter of adapters) {\r\n const { service, channelSelector } = adapter;\r\n if (!service || !channelSelector) {\r\n throw new Error(\"Service and channelSelector are required for an adapter\")\r\n }\r\n for (const methodName of getMethodNames(Object.getPrototypeOf(service))) {\r\n const channel = channelSelector?.(service, methodName);\r\n if (channel) {\r\n msgBus.provide({\r\n channel: channel,\r\n topic: '/.*/',\r\n callback: (msg) => {\r\n return (service[methodName] as Func)(...((msg.payload || []) as any[]));\r\n },\r\n options: {\r\n abortSignal: abortSignal\r\n }\r\n });\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nexport type BaseServiceSuffix = 'CLIENT' | 'API' | 'SERVICE' | 'FETCHER' | 'CONTROLLER' | 'LOADER' | 'REPOSITORY' | 'PROVIDER';\r\nexport type BaseWordSeparator = \".\"; // \"/\"\r\n\r\n// const suffixes = ['CLIENT', 'API', 'SERVICE'] satisfies Uppercase<BaseServiceSuffix>[];\r\n// runtime version: `${prefix}${removeSuffix(serviceName.toUpperCase(), suffixes)}.`\r\nexport type ToMsgChannelPrefix<\r\n TServiceName extends string,\r\n Prefix extends string,\r\n Suffix extends string = BaseServiceSuffix,\r\n WordSeparator extends string = BaseWordSeparator\r\n> = `${Prefix}${WordSeparator}${RemoveSuffix<Uppercase<TServiceName>, Suffix>}${WordSeparator}`;\r\n\r\ntype ToMsgStructSource<TService, TPrefix extends string, TSkip extends keyof TService = never> = Filter<\r\n ToUpper<AddPrefix<Skip<TService, TSkip>, TPrefix>>,\r\n Func\r\n>;\r\n\r\nexport type ToMsgStruct<TService, TPrefix extends string, TSkip extends keyof TService = never, TMsgStructSource = ToMsgStructSource<TService, TPrefix, TSkip>> = MsgStructFactory<{\r\n [K in keyof TMsgStructSource as TMsgStructSource[K] extends Func ? (Uppercase<K extends string ? K : never>) : never]: {\r\n in: TMsgStructSource[K] extends Func ? Parameters<TMsgStructSource[K]> : never;\r\n out: TMsgStructSource[K] extends Func ? ReturnType<TMsgStructSource[K]> : never;\r\n };\r\n}>;\r\n\r\nexport function getMsgChannelSelector<TTPrefix extends string>(\r\n services: Record<TTPrefix, any>,\r\n) {\r\n return (service: any, methodName: string) => {\r\n const entry = Object.entries(services).find((entry) => entry[1] === service);\r\n if (!entry) {\r\n return null;\r\n }\r\n return `${entry[0]}${methodName.toUpperCase()}`;\r\n };\r\n}"],"names":["getMethodNames","client","name","registerAdapters","msgBus","adapters","abortSignal","adapter","service","channelSelector","methodName","channel","msg","getMsgChannelSelector","services","entry"],"mappings":"AAIA,MAAMA,IAAiB,CAACC,MAEb,OAAO,oBAAoBA,CAAM,EAAE;AAAA,EACtC,CAACC,MAASA,MAAS,iBAAiB,OAAOD,EAAOC,CAAI,KAAM;AAAA;AAa7D,SAASC,EAAiBC,GAAqBC,GAAgCC,GAA2B;AAC7G,MAAID;AACA,eAAWE,KAAWF,GAAU;AAC5B,YAAM,EAAE,SAAAG,GAAS,iBAAAC,EAAA,IAAoBF;AACrC,UAAI,CAACC,KAAW,CAACC;AACb,cAAM,IAAI,MAAM,yDAAyD;AAE7E,iBAAWC,KAAcV,EAAe,OAAO,eAAeQ,CAAO,CAAC,GAAG;AACrE,cAAMG,IAAUF,IAAkBD,GAASE,CAAU;AACrD,QAAIC,KACAP,EAAO,QAAQ;AAAA,UACX,SAAAO;AAAA,UACA,OAAO;AAAA,UACP,UAAU,CAACC,MACCJ,EAAQE,CAAU,EAAW,GAAKE,EAAI,WAAW,CAAA,CAAa;AAAA,UAE1E,SAAS;AAAA,YACL,aAAAN;AAAA,UAAA;AAAA,QACJ,CACH;AAAA,MAET;AAAA,IACJ;AAER;AA0BO,SAASO,EACZC,GACF;AACE,SAAO,CAACN,GAAcE,MAAuB;AACzC,UAAMK,IAAQ,OAAO,QAAQD,CAAQ,EAAE,KAAK,CAACC,MAAUA,EAAM,CAAC,MAAMP,CAAO;AAC3E,WAAKO,IAGE,GAAGA,EAAM,CAAC,CAAC,GAAGL,EAAW,aAAa,KAFlC;AAAA,EAGf;AACJ;"}
|
package/dist/net/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/net/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,QAAQ,EAAqB,cAAc,EAAiB,MAAM,WAAW,CAAC;AAE1G,OAAO,EAAoB,cAAc,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/net/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,QAAQ,EAAqB,cAAc,EAAiB,MAAM,WAAW,CAAC;AAE1G,OAAO,EAAoB,cAAc,EAAe,MAAM,0BAA0B,CAAC;AAIzF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAa9E;AAID,qBAAa,UAAU;IACnB,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAE1B,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC;IAGvB,OAAO,CAAC,eAAe,CAA6B;IAEpD,OAAO,CAAC,OAAO,CAAW;IAE1B,OAAO,CAAC,MAAM,CAA2B;IAEzC,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,IAAI,CAAe;IAE3B,OAAO,CAAC,WAAW,CAAW;gBAElB,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,WAAW,WAAe;cAgBnE,eAAe;YAcjB,mBAAmB;YAUnB,qBAAqB;YAqBrB,2BAA2B;YAkD3B,mBAAmB;IA+CpB,UAAU,CAAC,CAAC,EAAE,aAAa,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;CA2CxE"}
|
package/dist/net/client.es.js
CHANGED
|
@@ -2,15 +2,17 @@ import { v4 as d } from "uuid";
|
|
|
2
2
|
import o from "http-status";
|
|
3
3
|
import { getResponseResult as u } from "./request.es.js";
|
|
4
4
|
import { ApiError as r } from "./apiError.es.js";
|
|
5
|
-
|
|
5
|
+
import { $CONFIG_GET as f } from "../appDomain/appContracts.es.js";
|
|
6
|
+
import { $AUTH_SIGNIN as p, $CONTEXT_GET as y, $AUTH_REFRESH as w, $AUTH_ENSURE as g } from "../appDomain/security/securityContracts.es.js";
|
|
7
|
+
function A(i, e) {
|
|
6
8
|
if (!i)
|
|
7
9
|
return i;
|
|
8
10
|
const t = e.map((c) => c.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"), s = new RegExp(`(_?(${t}))+?$`, "i");
|
|
9
11
|
let a = i.replace(s, "");
|
|
10
12
|
return a = a.trim(), a.length > 0 ? a : i;
|
|
11
13
|
}
|
|
12
|
-
const
|
|
13
|
-
class
|
|
14
|
+
const T = ["api", "controller", "client", "fetcher"];
|
|
15
|
+
class B {
|
|
14
16
|
baseUrl;
|
|
15
17
|
name;
|
|
16
18
|
// private requestStates
|
|
@@ -20,9 +22,9 @@ class g {
|
|
|
20
22
|
accessToken;
|
|
21
23
|
init;
|
|
22
24
|
apiSuffixes;
|
|
23
|
-
constructor(e, n, t =
|
|
25
|
+
constructor(e, n, t = T) {
|
|
24
26
|
this.apiSuffixes = t, this.fetcher = n || window, this.requestStateMap = /* @__PURE__ */ new Map(), this.msgBus = e.msgBus, this.msgBus.on({
|
|
25
|
-
channel:
|
|
27
|
+
channel: p,
|
|
26
28
|
group: "out",
|
|
27
29
|
callback: (s) => {
|
|
28
30
|
this.accessToken = s.payload.accessToken;
|
|
@@ -31,14 +33,14 @@ class g {
|
|
|
31
33
|
}
|
|
32
34
|
async getBaseUrlAsync() {
|
|
33
35
|
const n = (await this.msgBus.request({
|
|
34
|
-
channel:
|
|
35
|
-
})).payload, t =
|
|
36
|
+
channel: f
|
|
37
|
+
})).payload, t = A(this.name, this.apiSuffixes), s = Object.entries(n.apis).find((a) => a[0].toLowerCase() === t?.toLowerCase());
|
|
36
38
|
s || console.warn(`API "${t}" is not defined in the current configuration. Using default configuration.`), this.baseUrl = s?.[1].url || n.baseUrl;
|
|
37
39
|
}
|
|
38
40
|
async updateSecurityAsync() {
|
|
39
41
|
if (!this.accessToken) {
|
|
40
42
|
const e = await this.msgBus.request({
|
|
41
|
-
channel:
|
|
43
|
+
channel: y
|
|
42
44
|
});
|
|
43
45
|
this.accessToken = e.payload.accessToken;
|
|
44
46
|
}
|
|
@@ -102,9 +104,9 @@ class g {
|
|
|
102
104
|
throw t;
|
|
103
105
|
if (t.status === o.UNAUTHORIZED) {
|
|
104
106
|
t.response?.headers?.get("token-expired") ? await this.msgBus.request({
|
|
105
|
-
channel:
|
|
107
|
+
channel: w
|
|
106
108
|
}) : await this.msgBus.request({
|
|
107
|
-
channel:
|
|
109
|
+
channel: g
|
|
108
110
|
});
|
|
109
111
|
continue;
|
|
110
112
|
}
|
|
@@ -137,7 +139,7 @@ class g {
|
|
|
137
139
|
}
|
|
138
140
|
}
|
|
139
141
|
export {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
+
B as ClientBase,
|
|
143
|
+
A as extractApiName
|
|
142
144
|
};
|
|
143
145
|
//# sourceMappingURL=client.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.es.js","sources":["../../src/net/client.ts"],"sourcesContent":["import { v4 as uuid } from \"uuid\";\r\nimport httpStatus from \"http-status\";\r\nimport { getResponseResult, IFetcher, IRequestCallbacks, IRequestParams, IRequestState } from \"./request\";\r\nimport { ApiError } from \"./apiError\";\r\nimport { BaseAppMsgStruct, BaseAppContext } from \"@/appDomain/appContracts\";\r\nimport { MsgBus } from \"@actdim/msgmesh/contracts\";\r\n\r\n// MLWEB-2172\r\n\r\n// TODO: support request cancellation\r\n// https://stackoverflow.com/questions/31061838/how-do-i-cancel-an-http-fetch-request\r\n// https://mukeshprajapati0251.medium.com/cancel-rest-api-pending-request-1af65e70366d\r\n\r\nexport function extractApiName(name: string, suffixes: string[]): string | null {\r\n if (!name) {\r\n return name;\r\n // return null; // ?\r\n }\r\n const escaped = suffixes.map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\r\n const group = escaped.join(\"|\");\r\n const pattern = new RegExp(`(_?(${group}))+?$`, \"i\");\r\n\r\n let result = name.replace(pattern, \"\");\r\n\r\n result = result.trim();\r\n return result.length > 0 ? result : name;\r\n}\r\n\r\nconst API_SUFFIXES = [\"api\", \"controller\", \"client\", \"fetcher\"];\r\n// App(Api)ClientBase\r\nexport class ClientBase {\r\n protected baseUrl: string;\r\n\r\n protected name: string;\r\n\r\n // private requestStates\r\n private requestStateMap: Map<string, IRequestState>;\r\n\r\n private fetcher: IFetcher;\r\n\r\n private msgBus: MsgBus<BaseAppMsgStruct>;\r\n\r\n private accessToken: string;\r\n\r\n private init: Promise<any>;\r\n\r\n private apiSuffixes: string[];\r\n\r\n constructor(context: BaseAppContext, fetcher?: IFetcher, apiSuffixes = API_SUFFIXES) {\r\n this.apiSuffixes = apiSuffixes;\r\n this.fetcher = fetcher || window;\r\n this.requestStateMap = new Map<string, IRequestState>();\r\n this.msgBus = context.msgBus;\r\n // TODO: unsubscribe\r\n this.msgBus.on({\r\n channel: \"APP-SECURITY-AUTH-SIGNIN\",\r\n group: \"out\",\r\n callback: (msg) => {\r\n this.accessToken = msg.payload.accessToken;\r\n }\r\n });\r\n this.init = Promise.all([this.getBaseUrlAsync(), this.updateSecurityAsync()]);\r\n }\r\n\r\n protected async getBaseUrlAsync() {\r\n const msg = await this.msgBus.request({\r\n channel: \"APP-CONFIG-GET\"\r\n });\r\n const config = msg.payload;\r\n const apiName = extractApiName(this.name, this.apiSuffixes);\r\n const apiEntry = Object.entries(config.apis).find((entry) => entry[0].toLowerCase() === apiName?.toLowerCase());\r\n if (!apiEntry) {\r\n // console.debug\r\n console.warn(`API \"${apiName}\" is not defined in the current configuration. Using default configuration.`);\r\n }\r\n this.baseUrl = apiEntry?.[1].url || config.baseUrl;\r\n }\r\n\r\n private async updateSecurityAsync() {\r\n if (!this.accessToken) {\r\n const msg = await this.msgBus.request({\r\n channel: \"APP-SECURITY-GET-CONTEXT\"\r\n });\r\n this.accessToken = msg.payload.accessToken;\r\n }\r\n return this.accessToken;\r\n }\r\n\r\n private async addAuthorizationAsync(request: IRequestParams) {\r\n const accessToken = await this.updateSecurityAsync();\r\n if (!accessToken) {\r\n throw ApiError.create({\r\n status: httpStatus.UNAUTHORIZED\r\n });\r\n }\r\n const authorizationHeader = \"Authorization\";\r\n const headers = request.headers;\r\n const headerValue = `Bearer ${accessToken}`;\r\n if (headers instanceof Headers) {\r\n // if (headers.has(authorizationHeader)) {\r\n // headers.delete(authorizationHeader)\r\n // }\r\n // headers.append(authorizationHeader, headerValue);\r\n headers.set(authorizationHeader, headerValue);\r\n } else {\r\n throw new Error(\"Unsupported headers\"); // object type\r\n }\r\n }\r\n\r\n private async executeRequestInternalAsync(request: IRequestState) {\r\n try {\r\n let proceed = true;\r\n const onBeforeSendRequest = request.callbacks && request.callbacks.onBeforeSendRequest;\r\n if (onBeforeSendRequest) {\r\n const event = {\r\n request: request,\r\n cancel: false,\r\n handled: false\r\n } as Parameters<IRequestCallbacks[\"onBeforeSendRequest\"]>[0];\r\n await onBeforeSendRequest(event);\r\n if (event.cancel) {\r\n // interrupt\r\n proceed = false;\r\n request.status = \"canceled\";\r\n if (event.handled) {\r\n request.result = event.result;\r\n } else {\r\n // ApiError?\r\n throw new Error(\"The request was aborted\"); // has been? canceled?\r\n }\r\n }\r\n }\r\n if (proceed) {\r\n request.status = \"executing\";\r\n const response = await this.fetcher.fetch(request.url, request);\r\n ApiError.assert(response, request);\r\n let onResponseRead = request.callbacks && request.callbacks.onResponseRead;\r\n if (!onResponseRead) {\r\n onResponseRead = async (event) => {\r\n const result = await getResponseResult(response, request);\r\n event.result = result;\r\n };\r\n }\r\n const event = {\r\n response: response\r\n } as Parameters<IRequestCallbacks[\"onResponseRead\"]>[0];\r\n\r\n await onResponseRead(event);\r\n request.result = event.result;\r\n request.status = \"succeeded\";\r\n }\r\n } catch (err) {\r\n request.status = \"failed\";\r\n // throw ApiError.create(undefined, request);\r\n throw err;\r\n }\r\n return request;\r\n }\r\n\r\n private async executeRequestAsync(request: IRequestState): Promise<IRequestState> {\r\n let attempt = 0;\r\n do {\r\n try {\r\n if (request.useAuth) {\r\n await this.addAuthorizationAsync(request);\r\n }\r\n return await this.executeRequestInternalAsync(request);\r\n } catch (err) {\r\n if (err instanceof ApiError) {\r\n if (attempt > 0) {\r\n throw err;\r\n }\r\n if (err.status === httpStatus.UPGRADE_REQUIRED) {\r\n // await this.context.msgBus.request({\r\n // channel: \"APP_RELOAD\" // APP_REQUEST_UPDGRADE\r\n // });\r\n throw err;\r\n } else if (err.status === httpStatus.UNAUTHORIZED) {\r\n if (err.response?.headers?.get(\"token-expired\")) {\r\n // token expired or invalid\r\n await this.msgBus.request({\r\n channel: \"APP-SECURITY-AUTH-REFRESH\"\r\n });\r\n } else {\r\n await this.msgBus.request({\r\n channel: \"APP-SECURITY-REQUEST-AUTH\"\r\n });\r\n }\r\n // codes:\r\n // TOKEN_EXPIRED\r\n // TOKEN_INVALID\r\n // TOKEN_MISSING\r\n // AUTH_REQUIRED\r\n // header: WWW-Authenticate\r\n continue;\r\n }\r\n continue;\r\n }\r\n throw err;\r\n } finally {\r\n attempt++;\r\n }\r\n } while (true);\r\n }\r\n\r\n // T extends IApiResponse\r\n public async fetchAsync<T>(requestParams: IRequestParams): Promise<T> {\r\n await this.init;\r\n\r\n const defaultParams: Partial<IRequestParams> = {\r\n contentType: \"application/json\",\r\n method: \"POST\",\r\n body: null,\r\n headers: {},\r\n cache: \"default\",\r\n credentials: \"same-origin\",\r\n mode: \"cors\"\r\n };\r\n\r\n requestParams = { ...defaultParams, ...requestParams };\r\n if (!requestParams.id) {\r\n requestParams.id = uuid();\r\n }\r\n\r\n if (!(requestParams.headers instanceof Headers)) {\r\n requestParams.headers = new Headers(requestParams.headers);\r\n }\r\n\r\n requestParams.headers.append(\"Content-Type\", requestParams.contentType);\r\n // \"api-version\"\r\n\r\n if (requestParams.method === \"POST\") {\r\n if (!requestParams.body) {\r\n requestParams.body = \"\";\r\n }\r\n }\r\n\r\n let request = {\r\n ...requestParams,\r\n status: \"queued\",\r\n response: undefined,\r\n result: undefined\r\n } as IRequestState;\r\n\r\n this.requestStateMap.set(requestParams.id, request);\r\n\r\n await this.executeRequestAsync(request);\r\n return request.result;\r\n }\r\n}\r\n/* \r\nif (status === 404) {\r\n return response.text().then((_responseText) => {\r\n let result404: any = null;\r\n result404 = _responseText === \"\" ? null : JSON.parse(_responseText, this.jsonParseReviver) as __API__ProblemDetails;\r\n return throwException(\"Not Found\", status, _responseText, _headers, result404);\r\n });\r\n } else if (status !== 200 && status !== 204) {\r\n return response.text().then((_responseText) => {\r\n return throwException(\"An unexpected server error occurred.\", status, _responseText, _headers);\r\n });\r\n }\r\n\r\nBLOB\r\nlet reader = new FileReader();\r\n reader.onload = event => resolve((event.target as any).result);\r\n reader.readAsText(blob);\r\n*/\r\n"],"names":["extractApiName","name","suffixes","group","s","pattern","result","API_SUFFIXES","ClientBase","context","fetcher","apiSuffixes","msg","config","apiName","apiEntry","entry","request","accessToken","ApiError","httpStatus","authorizationHeader","headers","headerValue","proceed","onBeforeSendRequest","event","response","onResponseRead","getResponseResult","err","attempt","requestParams","uuid"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.es.js","sources":["../../src/net/client.ts"],"sourcesContent":["import { v4 as uuid } from \"uuid\";\r\nimport httpStatus from \"http-status\";\r\nimport { getResponseResult, IFetcher, IRequestCallbacks, IRequestParams, IRequestState } from \"./request\";\r\nimport { ApiError } from \"./apiError\";\r\nimport { BaseAppMsgStruct, BaseAppContext, $CONFIG_GET } from \"@/appDomain/appContracts\";\r\nimport { MsgBus } from \"@actdim/msgmesh/contracts\";\r\nimport { $AUTH_ENSURE, $AUTH_REFRESH, $AUTH_SIGNIN, $CONTEXT_GET } from \"@/appDomain/security/securityContracts\";\r\n\r\nexport function extractApiName(name: string, suffixes: string[]): string | null {\r\n if (!name) {\r\n return name;\r\n // return null; // ?\r\n }\r\n const escaped = suffixes.map((s) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"));\r\n const group = escaped.join(\"|\");\r\n const pattern = new RegExp(`(_?(${group}))+?$`, \"i\");\r\n\r\n let result = name.replace(pattern, \"\");\r\n\r\n result = result.trim();\r\n return result.length > 0 ? result : name;\r\n}\r\n\r\nconst API_SUFFIXES = [\"api\", \"controller\", \"client\", \"fetcher\"];\r\n// App(Api)ClientBase\r\nexport class ClientBase {\r\n protected baseUrl: string;\r\n\r\n protected name: string;\r\n\r\n // private requestStates\r\n private requestStateMap: Map<string, IRequestState>;\r\n\r\n private fetcher: IFetcher;\r\n\r\n private msgBus: MsgBus<BaseAppMsgStruct>;\r\n\r\n private accessToken: string;\r\n\r\n private init: Promise<any>;\r\n\r\n private apiSuffixes: string[];\r\n\r\n constructor(context: BaseAppContext, fetcher?: IFetcher, apiSuffixes = API_SUFFIXES) {\r\n this.apiSuffixes = apiSuffixes;\r\n this.fetcher = fetcher || window;\r\n this.requestStateMap = new Map<string, IRequestState>();\r\n this.msgBus = context.msgBus;\r\n // TODO: unsubscribe\r\n this.msgBus.on({\r\n channel: $AUTH_SIGNIN,\r\n group: \"out\",\r\n callback: (msg) => {\r\n this.accessToken = msg.payload.accessToken;\r\n }\r\n });\r\n this.init = Promise.all([this.getBaseUrlAsync(), this.updateSecurityAsync()]);\r\n }\r\n\r\n protected async getBaseUrlAsync() {\r\n const msg = await this.msgBus.request({\r\n channel: $CONFIG_GET\r\n });\r\n const config = msg.payload;\r\n const apiName = extractApiName(this.name, this.apiSuffixes);\r\n const apiEntry = Object.entries(config.apis).find((entry) => entry[0].toLowerCase() === apiName?.toLowerCase());\r\n if (!apiEntry) {\r\n // console.debug\r\n console.warn(`API \"${apiName}\" is not defined in the current configuration. Using default configuration.`);\r\n }\r\n this.baseUrl = apiEntry?.[1].url || config.baseUrl;\r\n }\r\n\r\n private async updateSecurityAsync() {\r\n if (!this.accessToken) {\r\n const msg = await this.msgBus.request({\r\n channel: $CONTEXT_GET\r\n });\r\n this.accessToken = msg.payload.accessToken;\r\n }\r\n return this.accessToken;\r\n }\r\n\r\n private async addAuthorizationAsync(request: IRequestParams) {\r\n const accessToken = await this.updateSecurityAsync();\r\n if (!accessToken) {\r\n throw ApiError.create({\r\n status: httpStatus.UNAUTHORIZED\r\n });\r\n }\r\n const authorizationHeader = \"Authorization\";\r\n const headers = request.headers;\r\n const headerValue = `Bearer ${accessToken}`;\r\n if (headers instanceof Headers) {\r\n // if (headers.has(authorizationHeader)) {\r\n // headers.delete(authorizationHeader)\r\n // }\r\n // headers.append(authorizationHeader, headerValue);\r\n headers.set(authorizationHeader, headerValue);\r\n } else {\r\n throw new Error(\"Unsupported headers\"); // object type\r\n }\r\n }\r\n\r\n private async executeRequestInternalAsync(request: IRequestState) {\r\n try {\r\n let proceed = true;\r\n const onBeforeSendRequest = request.callbacks && request.callbacks.onBeforeSendRequest;\r\n if (onBeforeSendRequest) {\r\n const event = {\r\n request: request,\r\n cancel: false,\r\n handled: false\r\n } as Parameters<IRequestCallbacks[\"onBeforeSendRequest\"]>[0];\r\n await onBeforeSendRequest(event);\r\n if (event.cancel) {\r\n // interrupt\r\n proceed = false;\r\n request.status = \"canceled\";\r\n if (event.handled) {\r\n request.result = event.result;\r\n } else {\r\n // ApiError?\r\n throw new Error(\"The request was aborted\"); // has been? canceled?\r\n }\r\n }\r\n }\r\n if (proceed) {\r\n request.status = \"executing\";\r\n const response = await this.fetcher.fetch(request.url, request);\r\n ApiError.assert(response, request);\r\n let onResponseRead = request.callbacks && request.callbacks.onResponseRead;\r\n if (!onResponseRead) {\r\n onResponseRead = async (event) => {\r\n const result = await getResponseResult(response, request);\r\n event.result = result;\r\n };\r\n }\r\n const event = {\r\n response: response\r\n } as Parameters<IRequestCallbacks[\"onResponseRead\"]>[0];\r\n\r\n await onResponseRead(event);\r\n request.result = event.result;\r\n request.status = \"succeeded\";\r\n }\r\n } catch (err) {\r\n request.status = \"failed\";\r\n // throw ApiError.create(undefined, request);\r\n throw err;\r\n }\r\n return request;\r\n }\r\n\r\n private async executeRequestAsync(request: IRequestState): Promise<IRequestState> {\r\n let attempt = 0;\r\n do {\r\n try {\r\n if (request.useAuth) {\r\n await this.addAuthorizationAsync(request);\r\n }\r\n return await this.executeRequestInternalAsync(request);\r\n } catch (err) {\r\n if (err instanceof ApiError) {\r\n if (attempt > 0) {\r\n throw err;\r\n }\r\n if (err.status === httpStatus.UPGRADE_REQUIRED) {\r\n // await this.context.msgBus.request({\r\n // channel: \"APP.RELOAD\"\r\n // });\r\n throw err;\r\n } else if (err.status === httpStatus.UNAUTHORIZED) {\r\n if (err.response?.headers?.get(\"token-expired\")) {\r\n // token expired or invalid\r\n await this.msgBus.request({\r\n channel: $AUTH_REFRESH\r\n });\r\n } else {\r\n await this.msgBus.request({\r\n channel: $AUTH_ENSURE\r\n });\r\n }\r\n // codes:\r\n // TOKEN_EXPIRED\r\n // TOKEN_INVALID\r\n // TOKEN_MISSING\r\n // AUTH_REQUIRED\r\n // header: WWW-Authenticate\r\n continue;\r\n }\r\n continue;\r\n }\r\n throw err;\r\n } finally {\r\n attempt++;\r\n }\r\n } while (true);\r\n }\r\n\r\n // T extends IApiResponse\r\n public async fetchAsync<T>(requestParams: IRequestParams): Promise<T> {\r\n await this.init;\r\n\r\n const defaultParams: Partial<IRequestParams> = {\r\n contentType: \"application/json\",\r\n method: \"POST\",\r\n body: null,\r\n headers: {},\r\n cache: \"default\",\r\n credentials: \"same-origin\",\r\n mode: \"cors\"\r\n };\r\n\r\n requestParams = { ...defaultParams, ...requestParams };\r\n if (!requestParams.id) {\r\n requestParams.id = uuid();\r\n }\r\n\r\n if (!(requestParams.headers instanceof Headers)) {\r\n requestParams.headers = new Headers(requestParams.headers);\r\n }\r\n\r\n requestParams.headers.append(\"Content-Type\", requestParams.contentType);\r\n // \"api-version\"\r\n\r\n if (requestParams.method === \"POST\") {\r\n if (!requestParams.body) {\r\n requestParams.body = \"\";\r\n }\r\n }\r\n\r\n let request = {\r\n ...requestParams,\r\n status: \"queued\",\r\n response: undefined,\r\n result: undefined\r\n } as IRequestState;\r\n\r\n this.requestStateMap.set(requestParams.id, request);\r\n\r\n await this.executeRequestAsync(request);\r\n return request.result;\r\n }\r\n}\r\n\r\n// TODO: check MLWEB-2172\r\n// TODO: support request cancellation\r\n// https://stackoverflow.com/questions/31061838/how-do-i-cancel-an-http-fetch-request\r\n// https://mukeshprajapati0251.medium.com/cancel-rest-api-pending-request-1af65e70366d\r\n\r\n/* \r\nif (status === 404) {\r\n return response.text().then((_responseText) => {\r\n let result404: any = null;\r\n result404 = _responseText === \"\" ? null : JSON.parse(_responseText, this.jsonParseReviver) as __API__ProblemDetails;\r\n return throwException(\"Not Found\", status, _responseText, _headers, result404);\r\n });\r\n } else if (status !== 200 && status !== 204) {\r\n return response.text().then((_responseText) => {\r\n return throwException(\"An unexpected server error occurred.\", status, _responseText, _headers);\r\n });\r\n }\r\n\r\nBLOB\r\nlet reader = new FileReader();\r\n reader.onload = event => resolve((event.target as any).result);\r\n reader.readAsText(blob);\r\n*/\r\n"],"names":["extractApiName","name","suffixes","group","s","pattern","result","API_SUFFIXES","ClientBase","context","fetcher","apiSuffixes","$AUTH_SIGNIN","msg","config","$CONFIG_GET","apiName","apiEntry","entry","$CONTEXT_GET","request","accessToken","ApiError","httpStatus","authorizationHeader","headers","headerValue","proceed","onBeforeSendRequest","event","response","onResponseRead","getResponseResult","err","attempt","$AUTH_REFRESH","$AUTH_ENSURE","requestParams","uuid"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageService.d.ts","sourceRoot":"","sources":["../../src/services/StorageService.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"StorageService.d.ts","sourceRoot":"","sources":["../../src/services/StorageService.ts"],"names":[],"mappings":"AACA,OAAO,EAAyC,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACnG,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEnD,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW;;;GAwDxH"}
|
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
import { PersistentStore as i } from "@actdim/utico/store/persistentStore";
|
|
2
|
-
|
|
2
|
+
import { $STORE_GET as p, $STORE_SET as s, $STORE_REMOVE as l } from "../appDomain/appContracts.es.js";
|
|
3
|
+
async function k(t, n, e) {
|
|
3
4
|
const c = new AbortController();
|
|
4
5
|
e && (e = AbortSignal.any([e, c.signal]));
|
|
5
|
-
const
|
|
6
|
+
const r = () => i.open(n);
|
|
6
7
|
return t.provide({
|
|
7
|
-
channel:
|
|
8
|
+
channel: p,
|
|
8
9
|
group: "in",
|
|
9
10
|
options: {
|
|
10
11
|
abortSignal: e
|
|
11
12
|
},
|
|
12
|
-
callback: async (o) => await (await
|
|
13
|
+
callback: async (o) => await (await r()).get(o.payload.key)
|
|
13
14
|
}), t.provide({
|
|
14
|
-
channel:
|
|
15
|
+
channel: s,
|
|
15
16
|
group: "in",
|
|
16
17
|
options: {
|
|
17
18
|
abortSignal: e
|
|
18
19
|
},
|
|
19
20
|
callback: async (o) => {
|
|
20
|
-
await (await
|
|
21
|
+
await (await r()).set(
|
|
21
22
|
{
|
|
22
23
|
key: o.payload.key
|
|
23
24
|
},
|
|
@@ -25,20 +26,20 @@ async function s(t, a, e) {
|
|
|
25
26
|
);
|
|
26
27
|
}
|
|
27
28
|
}), t.provide({
|
|
28
|
-
channel:
|
|
29
|
+
channel: l,
|
|
29
30
|
group: "in",
|
|
30
31
|
options: {
|
|
31
32
|
abortSignal: e
|
|
32
33
|
},
|
|
33
34
|
callback: async (o) => {
|
|
34
|
-
await (await
|
|
35
|
+
await (await r()).delete(o.payload.key);
|
|
35
36
|
}
|
|
36
37
|
}), {
|
|
37
|
-
storeName:
|
|
38
|
+
storeName: n,
|
|
38
39
|
abortSignal: e
|
|
39
40
|
};
|
|
40
41
|
}
|
|
41
42
|
export {
|
|
42
|
-
|
|
43
|
+
k as createStorageService
|
|
43
44
|
};
|
|
44
45
|
//# sourceMappingURL=StorageService.es.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageService.es.js","sources":["../../src/services/StorageService.ts"],"sourcesContent":["import { PersistentStore } from '@actdim/utico/store/persistentStore';\r\nimport { BaseAppMsgStruct } from '@/appDomain/appContracts';\r\nimport { MsgBus } from '@actdim/msgmesh/contracts';\r\n\r\nexport async function createStorageService(msgBus: MsgBus<BaseAppMsgStruct>, storeName: string, abortSignal?: AbortSignal) {\r\n\r\n const abortController = new AbortController();\r\n if (abortSignal) {\r\n abortSignal = AbortSignal.any([abortSignal, abortController.signal]);\r\n }\r\n\r\n const getStore = () => {\r\n return PersistentStore.open(storeName);\r\n }\r\n\r\n msgBus.provide({\r\n channel:
|
|
1
|
+
{"version":3,"file":"StorageService.es.js","sources":["../../src/services/StorageService.ts"],"sourcesContent":["import { PersistentStore } from '@actdim/utico/store/persistentStore';\r\nimport { $STORE_GET, $STORE_REMOVE, $STORE_SET, BaseAppMsgStruct } from '@/appDomain/appContracts';\r\nimport { MsgBus } from '@actdim/msgmesh/contracts';\r\n\r\nexport async function createStorageService(msgBus: MsgBus<BaseAppMsgStruct>, storeName: string, abortSignal?: AbortSignal) {\r\n\r\n const abortController = new AbortController();\r\n if (abortSignal) {\r\n abortSignal = AbortSignal.any([abortSignal, abortController.signal]);\r\n }\r\n\r\n const getStore = () => {\r\n return PersistentStore.open(storeName);\r\n }\r\n\r\n msgBus.provide({\r\n channel: $STORE_GET,\r\n group: \"in\",\r\n options: {\r\n abortSignal\r\n },\r\n callback: async (msg) => {\r\n const store = await getStore();\r\n return await store.get(msg.payload.key);\r\n }\r\n });\r\n\r\n msgBus.provide({\r\n channel: $STORE_SET,\r\n group: \"in\",\r\n options: {\r\n abortSignal\r\n },\r\n callback: async (msg) => {\r\n const store = await getStore();\r\n await store.set(\r\n {\r\n key: msg.payload.key,\r\n },\r\n msg.payload.value,\r\n );\r\n }\r\n });\r\n\r\n msgBus.provide({\r\n channel: $STORE_REMOVE,\r\n group: \"in\",\r\n options: {\r\n abortSignal\r\n },\r\n callback: async (msg) => {\r\n const store = await getStore();\r\n await store.delete(msg.payload.key);\r\n }\r\n });\r\n\r\n return {\r\n storeName,\r\n abortSignal\r\n }\r\n};"],"names":["createStorageService","msgBus","storeName","abortSignal","abortController","getStore","PersistentStore","$STORE_GET","msg","$STORE_SET","$STORE_REMOVE"],"mappings":";;AAIA,eAAsBA,EAAqBC,GAAkCC,GAAmBC,GAA2B;AAEvH,QAAMC,IAAkB,IAAI,gBAAA;AAC5B,EAAID,MACAA,IAAc,YAAY,IAAI,CAACA,GAAaC,EAAgB,MAAM,CAAC;AAGvE,QAAMC,IAAW,MACNC,EAAgB,KAAKJ,CAAS;AAGzC,SAAAD,EAAO,QAAQ;AAAA,IACX,SAASM;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,MACL,aAAAJ;AAAA,IAAA;AAAA,IAEJ,UAAU,OAAOK,MAEN,OADO,MAAMH,EAAA,GACD,IAAIG,EAAI,QAAQ,GAAG;AAAA,EAC1C,CACH,GAEDP,EAAO,QAAQ;AAAA,IACX,SAASQ;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,MACL,aAAAN;AAAA,IAAA;AAAA,IAEJ,UAAU,OAAOK,MAAQ;AAErB,aADc,MAAMH,EAAA,GACR;AAAA,QACR;AAAA,UACI,KAAKG,EAAI,QAAQ;AAAA,QAAA;AAAA,QAErBA,EAAI,QAAQ;AAAA,MAAA;AAAA,IAEpB;AAAA,EAAA,CACH,GAEDP,EAAO,QAAQ;AAAA,IACX,SAASS;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,MACL,aAAAP;AAAA,IAAA;AAAA,IAEJ,UAAU,OAAOK,MAAQ;AAErB,aADc,MAAMH,EAAA,GACR,OAAOG,EAAI,QAAQ,GAAG;AAAA,IACtC;AAAA,EAAA,CACH,GAEM;AAAA,IACH,WAAAN;AAAA,IACA,aAAAC;AAAA,EAAA;AAER;"}
|