@actdim/dynstruct 1.1.7 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/appDomain/appContracts.d.ts +31 -25
  2. package/dist/appDomain/appContracts.d.ts.map +1 -1
  3. package/dist/appDomain/appContracts.es.js +10 -9
  4. package/dist/appDomain/appContracts.es.js.map +1 -1
  5. package/dist/appDomain/security/securityContracts.d.ts +18 -18
  6. package/dist/appDomain/security/securityContracts.d.ts.map +1 -1
  7. package/dist/appDomain/security/securityContracts.es.js +10 -10
  8. package/dist/appDomain/security/securityContracts.es.js.map +1 -1
  9. package/dist/appDomain/security/securityProvider.d.ts +8 -8
  10. package/dist/appDomain/security/securityProvider.d.ts.map +1 -1
  11. package/dist/appDomain/security/securityProvider.es.js +55 -54
  12. package/dist/appDomain/security/securityProvider.es.js.map +1 -1
  13. package/dist/componentModel/adapters.d.ts +1 -1
  14. package/dist/componentModel/adapters.es.js.map +1 -1
  15. package/dist/componentModel/react.d.ts +2 -2
  16. package/dist/componentModel/react.d.ts.map +1 -1
  17. package/dist/componentModel/react.es.js +37 -37
  18. package/dist/componentModel/react.es.js.map +1 -1
  19. package/dist/net/client.d.ts.map +1 -1
  20. package/dist/net/client.es.js +14 -12
  21. package/dist/net/client.es.js.map +1 -1
  22. package/dist/services/StorageService.d.ts.map +1 -1
  23. package/dist/services/StorageService.es.js +11 -10
  24. package/dist/services/StorageService.es.js.map +1 -1
  25. package/dist/services/react/NavService.d.ts +4 -3
  26. package/dist/services/react/NavService.d.ts.map +1 -1
  27. package/dist/services/react/NavService.es.js +5 -5
  28. package/dist/services/react/NavService.es.js.map +1 -1
  29. package/dist/services/react/StorageService.d.ts +2 -2
  30. package/dist/services/react/StorageService.d.ts.map +1 -1
  31. package/dist/services/react/StorageService.es.js +3 -3
  32. package/dist/services/react/StorageService.es.js.map +1 -1
  33. package/package.json +2 -2
@@ -1,16 +1,17 @@
1
- import { AccessLevel as h } from "./securityContracts.es.js";
2
- import { getValuePrefixer as l } from "@actdim/utico/typeCore";
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 i } from "../../net/request.es.js";
5
- import { ApiError as o } from "../../net/apiError.es.js";
6
- const u = {
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 E {
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.updateConfigAsync(), this.msgBus.provide({
32
- channel: "APP-SECURITY-GET-CONTEXT",
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: "APP-SECURITY-GET-ACL",
36
+ channel: T,
36
37
  callback: (e) => this.getAcl(e.payload)
37
38
  }), this.msgBus.provide({
38
- channel: "APP-SECURITY-AUTH-SIGNIN",
39
- callback: (e) => this.signInAsync(e.payload)
39
+ channel: c,
40
+ callback: (e) => this.signIn(e.payload)
40
41
  }), this.msgBus.provide({
41
- channel: "APP-SECURITY-AUTH-SIGNOUT",
42
- callback: (e) => this.signOutAsync()
42
+ channel: d,
43
+ callback: (e) => this.signOut()
43
44
  }), this.msgBus.provide({
44
- channel: "APP-SECURITY-AUTH-REFRESH",
45
- callback: (e) => this.refreshAsync()
45
+ channel: k,
46
+ callback: (e) => this.refreshAuth()
46
47
  }), this.msgBus.provide({
47
- channel: "APP-SECURITY-REQUEST-AUTH",
48
- callback: (e) => this.requestAuthorize()
48
+ channel: f,
49
+ callback: (e) => this.ensureAuth()
49
50
  }), this.msgBus.provide({
50
- channel: "APP-SECURITY-GET-CONFIG",
51
+ channel: C,
51
52
  callback: async (e) => (await this.msgBus.request({
52
- channel: "APP-CONFIG-GET"
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 updateConfigAsync() {
67
+ async updateConfig() {
67
68
  const s = await this.msgBus.request({
68
- channel: "APP-CONFIG-GET"
69
+ channel: p
69
70
  });
70
71
  this.domainConfig = s.payload.security;
71
- const e = l(`${this.domainConfig.id}/`);
72
- this.storageKeys = e(u), await this.restoreDataAsync();
72
+ const e = w(`${this.domainConfig.id}/`);
73
+ this.storageKeys = e(v), await this.restoreData();
73
74
  }
74
- async restoreDataAsync() {
75
+ async restoreData() {
75
76
  this.accessToken = (await this.msgBus.request({
76
- channel: "APP-KV-STORE-GET",
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: "APP-KV-STORE-GET",
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: "APP-KV-STORE-GET",
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: "APP-KV-STORE-GET",
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: "APP-SECURITY-AUTH-SIGNIN",
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 clearSavedDataAsync() {
118
+ async clearSavedData() {
118
119
  this.accessToken = null, await this.msgBus.request({
119
- channel: "APP-KV-STORE-REMOVE",
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: "APP-KV-STORE-REMOVE",
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: "APP-KV-STORE-REMOVE",
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: "APP-KV-STORE-REMOVE",
135
+ channel: o,
135
136
  payload: {
136
137
  key: this.storageKeys.acl
137
138
  }
138
139
  });
139
140
  }
140
- async requestAuthorize() {
141
+ async ensureAuth() {
141
142
  this.accessToken = null, this.acl = null;
142
143
  const s = this.msgBus.once({
143
- channel: "APP-SECURITY-AUTH-SIGNIN",
144
+ channel: c,
144
145
  group: "out"
145
146
  }), e = async () => {
146
147
  throw await this.msgBus.once({
147
- channel: "APP-SECURITY-AUTH-SIGNOUT",
148
+ channel: d,
148
149
  group: "out"
149
150
  }), new Error("Auth failed: login aborted");
150
151
  };
151
152
  this.msgBus.send({
152
- channel: "APP-SECURITY-REQUEST-AUTH-SIGNIN",
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 signInAsync(s) {
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 i(a, r), o.assert(a, r);
174
- let c = a.resolved.json;
175
- return this.userCredentials = s, this.accessToken = c.accessToken, this.refreshToken = c.refreshToken, this.saveDataAsync(), this.getContext();
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 saveDataAsync() {
178
+ async saveData() {
178
179
  await this.msgBus.request({
179
- channel: "APP-KV-STORE-SET",
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: "APP-KV-STORE-SET",
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: "APP-KV-STORE-SET",
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: "APP-KV-STORE-SET",
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 signOutAsync() {
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 i(t, n), o.assert(t, n), this.clearSavedDataAsync();
219
+ await l(t, n), u.assert(t, n), this.clearSavedData();
219
220
  }
220
- async refreshAsync() {
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 i(a, r), o.assert(a, r), e = a.resolved.json, this.accessToken = e.accessToken, this.refreshToken = e.refreshToken, this.saveDataAsync(), this.getContext();
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
- [h.Full]: ""
244
+ [y.Full]: ""
244
245
  };
245
246
  }
246
247
  // authorize
247
- async verifyAccess(s, e = h.Full) {
248
+ async verifyAccess(s, e = y.Full) {
248
249
  return this.getAcl(s), !1;
249
250
  }
250
251
  }
251
252
  export {
252
- E as SecurityProvider
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 = \"-\"; // \".\"\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;"}
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;"}
@@ -1,5 +1,5 @@
1
- import { FC } from 'react';
1
+ import { default as React } from 'react';
2
2
  import { Component, ComponentDef, ComponentMsgHeaders, ComponentParams, ComponentStruct } from './contracts';
3
3
  export declare function useComponent<TStruct extends ComponentStruct = ComponentStruct, TMsgHeaders extends ComponentMsgHeaders = ComponentMsgHeaders>(componentDef: ComponentDef<TStruct, TMsgHeaders>, params: ComponentParams<TStruct>): any;
4
- export declare function getFC<TStruct extends ComponentStruct>(factory: (params: ComponentParams<TStruct>) => Component<TStruct>): FC<ComponentParams<TStruct>>;
4
+ export declare function getFC<TStruct extends ComponentStruct>(factory: (params: ComponentParams<TStruct>) => Component<TStruct>): React.FC<ComponentParams<TStruct>>;
5
5
  //# sourceMappingURL=react.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/componentModel/react.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAiD,EAAE,EAAW,MAAM,OAAO,CAAC;AAO1F,OAAO,EAEH,SAAS,EAET,YAAY,EAEZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EAOlB,MAAM,aAAa,CAAC;AAmWrB,wBAAgB,YAAY,CACxB,OAAO,SAAS,eAAe,GAAG,eAAe,EACjD,WAAW,SAAS,mBAAmB,GAAG,mBAAmB,EAC/D,YAAY,EAAE,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,OAQnF;AAGD,wBAAgB,KAAK,CAAC,OAAO,SAAS,eAAe,EACjD,OAAO,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,OAAO,CAAC,GAClE,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAQ9B"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/componentModel/react.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsD,MAAM,OAAO,CAAC;AAO3E,OAAO,EAEH,SAAS,EAET,YAAY,EAEZ,mBAAmB,EACnB,eAAe,EAEf,eAAe,EAOlB,MAAM,aAAa,CAAC;AAkWrB,wBAAgB,YAAY,CACxB,OAAO,SAAS,eAAe,GAAG,eAAe,EACjD,WAAW,SAAS,mBAAmB,GAAG,mBAAmB,EAC/D,YAAY,EAAE,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,OASnF;AAGD,wBAAgB,KAAK,CAAC,OAAO,SAAS,eAAe,EACjD,OAAO,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,SAAS,CAAC,OAAO,CAAC,GAClE,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,CAQpC"}
@@ -1,10 +1,10 @@
1
- import d, { useLayoutEffect as w, useEffect as M, useMemo as G } from "react";
2
- import { observer as S } from "mobx-react-lite";
1
+ import y, { useLayoutEffect as H, useEffect as G, useMemo as S } from "react";
2
+ import { observer as F } from "mobx-react-lite";
3
3
  import { observable as P } from "mobx";
4
- import { useLazyRef as F } from "../reactHooks.es.js";
4
+ import { useLazyRef as L } from "../reactHooks.es.js";
5
5
  import { getGlobalFlags as h } from "../globals.es.js";
6
- import { useComponentContext as H, ReactComponentContext as L } from "./componentContext.es.js";
7
- import { $ON_CHANGE as z, $ON_CHANGING as A, $ON_GET as T } from "./contracts.es.js";
6
+ import { useComponentContext as w, ReactComponentContext as z } from "./componentContext.es.js";
7
+ import { $ON_CHANGE as x, $ON_CHANGING as A, $ON_GET as T } from "./contracts.es.js";
8
8
  import { lazy as U } from "@actdim/utico/utils";
9
9
  import { getComponentSourceByCaller as _, getComponentMsgBus as J, toHtmlId as V, registerMsgBroker as q, isBinding as K, createRecursiveProxy as Q, createEffect as W } from "./core.es.js";
10
10
  function C(e) {
@@ -13,11 +13,11 @@ function C(e) {
13
13
  function X(e) {
14
14
  return e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^\/]+/, "");
15
15
  }
16
- function Y(e, i) {
16
+ function Y(e, u, i) {
17
17
  let t, l;
18
18
  e || (e = {});
19
- let u = e.regType;
20
- u || (u = _(6), u = X(u)), i || (i = {});
19
+ let d = e.regType;
20
+ d || (d = _(6), d = X(d)), i || (i = {});
21
21
  const $ = e.view;
22
22
  let v = e.msgBus;
23
23
  const b = /* @__PURE__ */ new Map(), B = U(() => J(v, (r) => {
@@ -27,19 +27,19 @@ function Y(e, i) {
27
27
  ...e.msgBroker
28
28
  };
29
29
  a.abortController || (a.abortController = new AbortController());
30
- const y = H(), N = S((r) => {
31
- const n = H(), g = n.currentId;
30
+ const N = F((r) => {
31
+ const n = w(), g = n.currentId;
32
32
  if (t.parentId = g, v || (v = n.msgBus), !t.id) {
33
33
  let o = i.$id;
34
34
  if (!o) {
35
35
  const f = i.$key;
36
- f ? o = `${V(u)}#${f}` : o = n.getNextId(u);
36
+ f ? o = `${V(d)}#${f}` : o = n.getNextId(d);
37
37
  }
38
38
  t.id = o;
39
39
  }
40
- w(() => {
40
+ H(() => {
41
41
  try {
42
- if (n.register(t.id, u, g), h().debug) {
42
+ if (n.register(t.id, d, g), h().debug) {
43
43
  const o = t.getHierarchyId();
44
44
  console.debug(`${o}>layout`);
45
45
  }
@@ -54,7 +54,7 @@ function Y(e, i) {
54
54
  }
55
55
  n.unregister(t.id), a.abortController?.abort(), e.events?.onLayoutDestroy?.(t), i.onLayoutDestroy?.(t);
56
56
  };
57
- }, [e, i, n]), M(() => {
57
+ }, [e, i, n]), G(() => {
58
58
  try {
59
59
  if (h().debug) {
60
60
  const o = t.getHierarchyId();
@@ -78,23 +78,23 @@ function Y(e, i) {
78
78
  const o = t.getHierarchyId();
79
79
  console.debug(`${o}>view`);
80
80
  }
81
- typeof $ == "function" ? s = $(r, t) : s = /* @__PURE__ */ d.createElement(d.Fragment, null, r.children);
81
+ typeof $ == "function" ? s = $(r, t) : s = /* @__PURE__ */ y.createElement(y.Fragment, null, r.children);
82
82
  } catch (o) {
83
83
  const f = JSON.stringify(o);
84
- s = /* @__PURE__ */ d.createElement(d.Fragment, null, f);
84
+ s = /* @__PURE__ */ y.createElement(y.Fragment, null, f);
85
85
  }
86
- const c = G(
86
+ const c = S(
87
87
  () => ({ ...n, currentId: t.id }),
88
88
  [e, i, n]
89
89
  );
90
- return /* @__PURE__ */ d.createElement(L.Provider, { value: c }, s);
90
+ return /* @__PURE__ */ y.createElement(z.Provider, { value: c }, s);
91
91
  }), I = {};
92
92
  if (l = {}, e.props && Object.assign(l, e.props), e.actions && Object.assign(l, e.actions), e.children)
93
93
  for (const [r, n] of Object.entries(e.children))
94
94
  if (typeof n == "function") {
95
95
  const g = n, s = (c) => {
96
96
  const o = g(c);
97
- return /* @__PURE__ */ d.createElement(o.View, null);
97
+ return /* @__PURE__ */ y.createElement(o.View, null);
98
98
  };
99
99
  Reflect.set(I, C(r), s);
100
100
  } else
@@ -114,15 +114,15 @@ function Y(e, i) {
114
114
  const n = `${T}${C(r)}`;
115
115
  return i[n] || e.events?.[n];
116
116
  }
117
- function x(r) {
117
+ function j(r) {
118
118
  const n = `${A}${C(r)}`;
119
119
  return ((g, s) => {
120
120
  let c = !0, o = i[n];
121
121
  return o && (c = o(g, s)), c && (o = e.events?.[n], o && (c = o(g, s))), c;
122
122
  });
123
123
  }
124
- function j(r) {
125
- const n = `${z}${C(r)}`;
124
+ function M(r) {
125
+ const n = `${x}${C(r)}`;
126
126
  return ((g) => {
127
127
  i[n]?.(g), e.events?.[n]?.(g);
128
128
  });
@@ -132,8 +132,8 @@ function Y(e, i) {
132
132
  for (const r of Object.keys(e.props))
133
133
  E[r] = {
134
134
  onGet: R(r),
135
- onChanging: x(r),
136
- onChange: j(r)
135
+ onChanging: j(r),
136
+ onChange: M(r)
137
137
  };
138
138
  for (const r of Object.keys(e.props))
139
139
  k[r] = P.deep;
@@ -148,14 +148,14 @@ function Y(e, i) {
148
148
  if (t = {
149
149
  id: i.$id,
150
150
  key: i.$key,
151
- regType: u,
151
+ regType: d,
152
152
  parentId: void 0,
153
- getHierarchyId: () => y.getHierarchyPath(t.id),
154
- getChainDown: () => y.getChainDown(t.id),
155
- getChainUp: () => y.getChainUp(t.id),
156
- getChildren: () => y.getChildren(t.id),
157
- getParent: () => y.getParent(t.id),
158
- getNodeMap: () => y.getNodeMap(),
153
+ getHierarchyId: () => u.getHierarchyPath(t.id),
154
+ getChainDown: () => u.getChainDown(t.id),
155
+ getChainUp: () => u.getChainUp(t.id),
156
+ getChildren: () => u.getChildren(t.id),
157
+ getParent: () => u.getParent(t.id),
158
+ getNodeMap: () => u.getNodeMap(),
159
159
  bindings: b,
160
160
  get msgBus() {
161
161
  return B();
@@ -175,16 +175,16 @@ function Y(e, i) {
175
175
  );
176
176
  return e.events?.onInit && e.events.onInit(t), i.onInit && i.onInit(t), t;
177
177
  }
178
- function oe(e, i) {
179
- const t = F(() => Y(e, i));
180
- return w(() => () => {
178
+ function oe(e, u) {
179
+ const i = w(), t = L(() => Y(e, i, u));
180
+ return H(() => () => {
181
181
  t.current = null;
182
182
  }, []), t.current;
183
183
  }
184
184
  function se(e) {
185
- return (t) => {
186
- const l = e(t);
187
- return /* @__PURE__ */ d.createElement(l.View, { ...t });
185
+ return (i) => {
186
+ const t = e(i);
187
+ return /* @__PURE__ */ y.createElement(t.View, { ...i });
188
188
  };
189
189
  }
190
190
  export {