@supersoniks/concorde 1.1.44 → 1.1.45

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.
@@ -4,6 +4,7 @@ export type APIConfiguration = {
4
4
  token: string | null;
5
5
  userName: string | null;
6
6
  password: string | null;
7
+ authToken: string | null;
7
8
  tokenProvider: string | null;
8
9
  addHTTPResponse?: boolean;
9
10
  credentials?: RequestCredentials;
@@ -12,6 +13,13 @@ export type ResultTypeInterface = CoreJSType & {
12
13
  _sonic_http_response_?: Response;
13
14
  text?: string;
14
15
  };
16
+ export type APICall = {
17
+ apiMethod: "get" | "send" | "submitFormData";
18
+ path: string;
19
+ additionalHeaders: HeadersInit | undefined;
20
+ method?: string | undefined;
21
+ data?: unknown;
22
+ };
15
23
  declare class API {
16
24
  /**
17
25
  * Ce tableau static permet de ne pas appeler plusieurs fois le même service lors d'appel concurrents en GET.
@@ -32,11 +40,17 @@ declare class API {
32
40
  /**
33
41
  * le bearer token a passer pour les appels REST
34
42
  */
35
- token: string | null | undefined;
43
+ private _token;
44
+ set token(token: string | null | undefined);
45
+ get token(): string | null | undefined;
36
46
  /**
37
47
  * Le endPoint pour obtenir le bearer token qui sera concaténé à l'url du service
38
48
  */
39
49
  tokenProvider: string | null;
50
+ /**
51
+ * le bearer token à passer pour un éventuel renouvellement de token automatique
52
+ */
53
+ authToken: string | null;
40
54
  /**
41
55
  * credentials
42
56
  */
@@ -45,13 +59,22 @@ declare class API {
45
59
  * Tableau static des tokens stokés en memoire vive (comportement à revoir à l'occasion)
46
60
  */
47
61
  static tokens: Map<string | null, string | null | undefined>;
62
+ /**
63
+ * Tableau stockant l'ensemble des tokens invalides
64
+ */
65
+ static invalidTokens: (string | null | undefined)[];
66
+ handleInvalidToken(token: string | null | undefined): void;
67
+ /**
68
+ * Tableau static des tentatives échouées de récupération auto du token
69
+ */
70
+ static failledTokenUpdates: Map<string | null, true>;
48
71
  /**
49
72
  * Le endPoint pour obtenir le bearer token qui sera concaténé à l'url du service
50
73
  */
51
74
  addHTTPResponse: boolean;
52
75
  lastResult?: Response;
53
76
  constructor(config: APIConfiguration);
54
- handleResult(fetchResult?: Response): Promise<ResultTypeInterface>;
77
+ handleResult(fetchResult: Response, lastCall: APICall): Promise<ResultTypeInterface>;
55
78
  /**
56
79
  * Basic auth
57
80
  */
@@ -65,7 +88,7 @@ declare class API {
65
88
  /**
66
89
  * Concatène le serviceURL et le endpoint donné en paramètre
67
90
  */
68
- computeURL(path: string): string;
91
+ computeURL(path: string, query?: Record<string, string>): string;
69
92
  send<T, SendType = CoreJSType>(path: string, data: SendType, method?: string, additionalHeaders?: HeadersInit): Promise<T & ResultTypeInterface>;
70
93
  /**
71
94
  * Agit comme une soumission de formulaire, mais attends un json en réponse
package/core/utils/api.js CHANGED
@@ -12,6 +12,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
12
12
  import HTML from "@supersoniks/concorde/core/utils/HTML";
13
13
  import Objects from "@supersoniks/concorde/core/utils/Objects";
14
14
  class API {
15
+ set token(token) {
16
+ this._token = token;
17
+ if (!token) {
18
+ API.tokens.delete(this.serviceURL);
19
+ return;
20
+ }
21
+ if (API.invalidTokens.includes(token))
22
+ return;
23
+ API.tokens.set(this.serviceURL, token);
24
+ }
25
+ get token() {
26
+ // si le token est marqué invalide, on utilise utilise la dernière version valide connue du token pour ce serviceURL
27
+ return API.invalidTokens.includes(this._token) ? API.tokens.get(this.serviceURL) : this._token;
28
+ }
29
+ handleInvalidToken(token) {
30
+ if (!token)
31
+ return;
32
+ if (API.invalidTokens.includes(token))
33
+ return;
34
+ API.invalidTokens.push(token);
35
+ this.token = null;
36
+ }
15
37
  constructor(config) {
16
38
  /**
17
39
  * Le endPoint pour obtenir le bearer token qui sera concaténé à l'url du service
@@ -22,24 +44,27 @@ class API {
22
44
  this.serviceURL = document.location.origin;
23
45
  this.userName = config.userName;
24
46
  this.password = config.password;
25
- this.token = config.token;
47
+ if (config.token)
48
+ this.token = config.token;
26
49
  this.tokenProvider = config.tokenProvider;
50
+ this.authToken = config.authToken;
27
51
  this.addHTTPResponse = config.addHTTPResponse || false;
28
52
  this.credentials = config.credentials;
29
53
  }
30
- handleResult(fetchResult) {
54
+ handleResult(fetchResult, lastCall) {
31
55
  var _a;
32
56
  return __awaiter(this, void 0, void 0, function* () {
33
57
  this.lastResult = fetchResult;
34
- const contentType = (_a = fetchResult === null || fetchResult === void 0 ? void 0 : fetchResult.headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.toLowerCase();
58
+ const contentType = (_a = fetchResult.headers.get("content-type")) === null || _a === void 0 ? void 0 : _a.toLowerCase();
59
+ const httpCode = fetchResult.status;
35
60
  let result = {};
36
- if (contentType && contentType.indexOf("text/") == 0) {
37
- const str = yield (fetchResult === null || fetchResult === void 0 ? void 0 : fetchResult.text());
61
+ if (!contentType || contentType.indexOf("text/") == 0) {
62
+ const str = yield fetchResult.text();
38
63
  result = { text: str };
39
64
  }
40
65
  else {
41
66
  try {
42
- result = yield (fetchResult === null || fetchResult === void 0 ? void 0 : fetchResult.json());
67
+ result = yield fetchResult.json();
43
68
  }
44
69
  catch (e) {
45
70
  result = {};
@@ -48,6 +73,15 @@ class API {
48
73
  if (this.addHTTPResponse && Objects.isObject(result)) {
49
74
  result._sonic_http_response_ = fetchResult;
50
75
  }
76
+ if (httpCode === 498 && !API.failledTokenUpdates.has(this.serviceURL)) {
77
+ this.handleInvalidToken(this.token);
78
+ if (lastCall.apiMethod === "get") {
79
+ result = yield this[lastCall.apiMethod](lastCall.path, lastCall.additionalHeaders);
80
+ }
81
+ else {
82
+ result = yield this[lastCall.apiMethod](lastCall.path, lastCall.data, lastCall.method, lastCall.additionalHeaders);
83
+ }
84
+ }
51
85
  return result;
52
86
  });
53
87
  }
@@ -62,39 +96,63 @@ class API {
62
96
  this.token = API.tokens.get(this.serviceURL);
63
97
  return;
64
98
  }
65
- if (!this.userName || !this.password || !this.tokenProvider)
99
+ if (!this.tokenProvider)
66
100
  return;
67
- const headers = {
68
- Authorization: "Basic " + window.btoa(unescape(encodeURIComponent(this.userName + ":" + this.password))),
69
- };
70
- const result = yield fetch(this.computeURL(this.tokenProvider), {
101
+ let headers = {};
102
+ if (this.userName && this.password) {
103
+ headers = {
104
+ Authorization: "Basic " + window.btoa(unescape(encodeURIComponent(this.userName + ":" + this.password))),
105
+ };
106
+ }
107
+ else if (this.authToken) {
108
+ headers = {
109
+ Authorization: "Bearer " + this.authToken,
110
+ };
111
+ }
112
+ const serviceURL = new URL(this.serviceURL);
113
+ const serviceHost = serviceURL.protocol + "//" + serviceURL.host;
114
+ const result = yield fetch(this.computeURL(this.tokenProvider, { serviceHost: serviceHost }), {
71
115
  headers: headers,
72
116
  credentials: this.credentials,
73
117
  });
74
118
  try {
75
119
  const json = yield result.json();
76
- this.token = json.token;
77
- API.tokens.set(this.serviceURL, this.token);
120
+ const newToken = json.token;
121
+ if (newToken) {
122
+ this.token = json.token;
123
+ }
124
+ else {
125
+ API.failledTokenUpdates.set(this.serviceURL, true);
126
+ }
78
127
  }
79
128
  catch (e) {
80
- console.log("Problème au moment du parsing du json au retour de l'authentification");
129
+ API.failledTokenUpdates.set(this.serviceURL, true);
81
130
  }
82
131
  });
83
132
  }
84
133
  get(path, additionalHeaders) {
85
134
  return __awaiter(this, void 0, void 0, function* () {
135
+ const lastCall = {
136
+ apiMethod: "get",
137
+ path: path,
138
+ additionalHeaders: additionalHeaders,
139
+ };
86
140
  const headers = yield this.createHeaders(additionalHeaders);
87
141
  const url = this.computeURL(path);
88
- if (!API.loadingGetPromises.has(url)) {
142
+ const mapKey = JSON.stringify({
143
+ url: url,
144
+ headers: headers,
145
+ });
146
+ if (!API.loadingGetPromises.has(mapKey)) {
89
147
  const promise = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
90
148
  const result = yield fetch(url, { headers: headers, credentials: this.credentials });
91
- const handledResult = yield this.handleResult(result);
149
+ const handledResult = yield this.handleResult(result, lastCall);
92
150
  resolve(handledResult);
93
151
  }));
94
- API.loadingGetPromises.set(url, promise);
152
+ API.loadingGetPromises.set(mapKey, promise);
95
153
  }
96
- const result = (yield API.loadingGetPromises.get(url));
97
- API.loadingGetPromises.delete(url);
154
+ const result = (yield API.loadingGetPromises.get(mapKey));
155
+ API.loadingGetPromises.delete(mapKey);
98
156
  return result;
99
157
  });
100
158
  }
@@ -118,14 +176,32 @@ class API {
118
176
  /**
119
177
  * Concatène le serviceURL et le endpoint donné en paramètre
120
178
  */
121
- computeURL(path) {
122
- return (this.serviceURL + "/" + path).replace(/([^(https?:)])\/{2,}/g, "$1/");
179
+ computeURL(path, query = {}) {
180
+ let url = "";
181
+ if (path.startsWith("http"))
182
+ url = path;
183
+ else
184
+ url = this.serviceURL + "/" + path;
185
+ if (!url.startsWith("http"))
186
+ url = window.location.origin + url;
187
+ const computedUrl = new URL(url);
188
+ for (const key in query) {
189
+ computedUrl.searchParams.set(key, query[key]);
190
+ }
191
+ return computedUrl.toString().replace(/([^(https?:)])\/{2,}/g, "$1/");
123
192
  }
124
193
  /*
125
194
  * Envoie des données au endPoint passé en paramètre. par défaut en POST
126
195
  */
127
196
  send(path, data, method = "POST", additionalHeaders) {
128
197
  return __awaiter(this, void 0, void 0, function* () {
198
+ const lastCall = {
199
+ apiMethod: "send",
200
+ path: path,
201
+ additionalHeaders: additionalHeaders,
202
+ method: method,
203
+ data: data,
204
+ };
129
205
  const headers = yield this.createHeaders(additionalHeaders);
130
206
  headers["Accept"] = "application/json";
131
207
  headers["Content-Type"] = "application/json";
@@ -135,7 +211,7 @@ class API {
135
211
  method: method,
136
212
  body: JSON.stringify(data),
137
213
  });
138
- return (yield this.handleResult(result));
214
+ return (yield this.handleResult(result, lastCall));
139
215
  });
140
216
  }
141
217
  /**
@@ -143,6 +219,13 @@ class API {
143
219
  */
144
220
  submitFormData(path, data, method = "POST", additionalHeaders) {
145
221
  return __awaiter(this, void 0, void 0, function* () {
222
+ const lastCall = {
223
+ apiMethod: "submitFormData",
224
+ path: path,
225
+ additionalHeaders: additionalHeaders,
226
+ method: method,
227
+ data: data,
228
+ };
146
229
  const headers = yield this.createHeaders(additionalHeaders);
147
230
  headers["Accept"] = "application/json";
148
231
  const formData = new FormData();
@@ -155,7 +238,7 @@ class API {
155
238
  method: method,
156
239
  body: formData,
157
240
  });
158
- return (yield this.handleResult(result));
241
+ return (yield this.handleResult(result, lastCall));
159
242
  });
160
243
  }
161
244
  /**
@@ -191,4 +274,12 @@ API.loadingGetPromises = new Map();
191
274
  * Tableau static des tokens stokés en memoire vive (comportement à revoir à l'occasion)
192
275
  */
193
276
  API.tokens = new Map();
277
+ /**
278
+ * Tableau stockant l'ensemble des tokens invalides
279
+ */
280
+ API.invalidTokens = [];
281
+ /**
282
+ * Tableau static des tentatives échouées de récupération auto du token
283
+ */
284
+ API.failledTokenUpdates = new Map();
194
285
  export default API;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supersoniks/concorde",
3
- "version": "1.1.44",
3
+ "version": "1.1.45",
4
4
  "customElements": "custom-elements.json",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -73,6 +73,8 @@
73
73
  "./functional/sdui/SDUIDescriptorTransformer": "./core/components/functional/sdui/SDUIDescriptorTransformer.js",
74
74
  "./core/components/functional/sdui/default-library.json": "./core/components/functional/sdui/default-library.json",
75
75
  "./functional/sdui/default-library.json": "./core/components/functional/sdui/default-library.json",
76
+ "./core/components/functional/sdui/example.json": "./core/components/functional/sdui/example.json",
77
+ "./functional/sdui/example.json": "./core/components/functional/sdui/example.json",
76
78
  "./core/components/functional/sdui/sdui-utils": "./core/components/functional/sdui/sdui-utils.js",
77
79
  "./functional/sdui/sdui-utils": "./core/components/functional/sdui/sdui-utils.js",
78
80
  "./core/components/functional/sdui/sdui": "./core/components/functional/sdui/sdui.js",
@@ -260,7 +262,6 @@
260
262
  "./docs/navigation/navigation": "./docs/navigation/navigation.js",
261
263
  "./docs/navigation": "./docs/navigation/navigation.js",
262
264
  "./docs/prism/index": "./docs/prism/index.js",
263
- "./docs/search/doc-search.json": "./docs/search/doc-search.json",
264
265
  "./docs/search/docs-search.json": "./docs/search/docs-search.json",
265
266
  "./docs/search/markdown-renderer": "./docs/search/markdown-renderer.js",
266
267
  "./docs/search/page": "./docs/search/page.js",