@docbrasil/api-systemmanager 1.1.83 → 1.1.84

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/api/dispatch.js CHANGED
@@ -199,18 +199,73 @@ class Dispatch {
199
199
  return this._client;
200
200
  }
201
201
 
202
+ /**
203
+ * @description Decode the payload of a JWT token (base64url → JSON).
204
+ * Does NOT verify the signature — used only to extract claims for header building.
205
+ * @param {string} token JWT token string
206
+ * @return {object|null} Decoded payload or null on failure
207
+ * @private
208
+ */
209
+ _decodeJwtPayload(token) {
210
+ try {
211
+ const parts = token.split('.');
212
+ if (parts.length !== 3) return null;
213
+ const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');
214
+ const json = decodeURIComponent(
215
+ atob(base64).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')
216
+ );
217
+ return JSON.parse(json);
218
+ } catch (e) {
219
+ return null;
220
+ }
221
+ }
222
+
202
223
  /**
203
224
  * @description Create a dedicated Axios client for Akamai routes.
225
+ * In DEV there is no NGiNX to translate the Authorization JWT into the
226
+ * x-api-key / x-user-id / x-organization-id headers that Akamai expects.
227
+ * When an apiKey is supplied the client adds a request interceptor that
228
+ * decodes the JWT and sets those headers automatically.
204
229
  * @param {string} url The Akamai base URL (e.g., http://localhost:9008 in DEV).
230
+ * @param {object} [options] Optional configuration
231
+ * @param {string} [options.apiKey] API key for Akamai authentication.
232
+ * When provided, the client will transform the Authorization JWT into
233
+ * x-api-key, x-user-id and x-organization-id headers on every request.
205
234
  * @public
206
235
  */
207
- setAkamaiBaseUrl(url) {
236
+ setAkamaiBaseUrl(url, options = {}) {
208
237
  Joi.assert(url, Joi.string().required());
209
238
 
210
- this._akamaiClient = Axios.create({
239
+ const self = this;
240
+
241
+ self._akamaiClient = Axios.create({
211
242
  baseURL: url,
212
243
  withCredentials: true
213
244
  });
245
+
246
+ // When an API key is provided, add interceptor to build Akamai headers from the JWT
247
+ if (options.apiKey) {
248
+ const apiKey = options.apiKey;
249
+
250
+ self._akamaiClient.interceptors.request.use((config) => {
251
+ const auth = config.headers && (config.headers.Authorization || config.headers.authorization);
252
+ if (auth) {
253
+ const payload = self._decodeJwtPayload(auth);
254
+ if (payload) {
255
+ config.headers['x-api-key'] = apiKey;
256
+ config.headers['x-user-id'] = payload._id || payload.userId;
257
+ config.headers['x-organization-id'] = payload.orgId || payload.organizationId;
258
+ if (payload.language) {
259
+ config.headers['x-country'] = payload.language;
260
+ }
261
+ // Remove the Authorization header — Akamai doesn't use it
262
+ delete config.headers.Authorization;
263
+ delete config.headers.authorization;
264
+ }
265
+ }
266
+ return config;
267
+ });
268
+ }
214
269
  }
215
270
 
216
271
  /**
package/dist/bundle.cjs CHANGED
@@ -211,18 +211,73 @@ class Dispatch {
211
211
  return this._client;
212
212
  }
213
213
 
214
+ /**
215
+ * @description Decode the payload of a JWT token (base64url → JSON).
216
+ * Does NOT verify the signature — used only to extract claims for header building.
217
+ * @param {string} token JWT token string
218
+ * @return {object|null} Decoded payload or null on failure
219
+ * @private
220
+ */
221
+ _decodeJwtPayload(token) {
222
+ try {
223
+ const parts = token.split('.');
224
+ if (parts.length !== 3) return null;
225
+ const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');
226
+ const json = decodeURIComponent(
227
+ atob(base64).split('').map(c => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)).join('')
228
+ );
229
+ return JSON.parse(json);
230
+ } catch (e) {
231
+ return null;
232
+ }
233
+ }
234
+
214
235
  /**
215
236
  * @description Create a dedicated Axios client for Akamai routes.
237
+ * In DEV there is no NGiNX to translate the Authorization JWT into the
238
+ * x-api-key / x-user-id / x-organization-id headers that Akamai expects.
239
+ * When an apiKey is supplied the client adds a request interceptor that
240
+ * decodes the JWT and sets those headers automatically.
216
241
  * @param {string} url The Akamai base URL (e.g., http://localhost:9008 in DEV).
242
+ * @param {object} [options] Optional configuration
243
+ * @param {string} [options.apiKey] API key for Akamai authentication.
244
+ * When provided, the client will transform the Authorization JWT into
245
+ * x-api-key, x-user-id and x-organization-id headers on every request.
217
246
  * @public
218
247
  */
219
- setAkamaiBaseUrl(url) {
248
+ setAkamaiBaseUrl(url, options = {}) {
220
249
  Joi__default["default"].assert(url, Joi__default["default"].string().required());
221
250
 
222
- this._akamaiClient = Axios__default["default"].create({
251
+ const self = this;
252
+
253
+ self._akamaiClient = Axios__default["default"].create({
223
254
  baseURL: url,
224
255
  withCredentials: true
225
256
  });
257
+
258
+ // When an API key is provided, add interceptor to build Akamai headers from the JWT
259
+ if (options.apiKey) {
260
+ const apiKey = options.apiKey;
261
+
262
+ self._akamaiClient.interceptors.request.use((config) => {
263
+ const auth = config.headers && (config.headers.Authorization || config.headers.authorization);
264
+ if (auth) {
265
+ const payload = self._decodeJwtPayload(auth);
266
+ if (payload) {
267
+ config.headers['x-api-key'] = apiKey;
268
+ config.headers['x-user-id'] = payload._id || payload.userId;
269
+ config.headers['x-organization-id'] = payload.orgId || payload.organizationId;
270
+ if (payload.language) {
271
+ config.headers['x-country'] = payload.language;
272
+ }
273
+ // Remove the Authorization header — Akamai doesn't use it
274
+ delete config.headers.Authorization;
275
+ delete config.headers.authorization;
276
+ }
277
+ }
278
+ return config;
279
+ });
280
+ }
226
281
  }
227
282
 
228
283
  /**
@@ -16557,17 +16612,20 @@ class API {
16557
16612
 
16558
16613
  // If akamaiUri was provided in options, configure the Akamai client
16559
16614
  if (self.options.akamaiUri) {
16560
- self.dispatch.setAkamaiBaseUrl(self.options.akamaiUri);
16615
+ self.dispatch.setAkamaiBaseUrl(self.options.akamaiUri, { apiKey: self.options.akamaiApiKey });
16561
16616
  }
16562
16617
  }
16563
16618
 
16564
16619
  /**
16565
16620
  * @description Set the Akamai base URL for agent/AI routes.
16566
16621
  * @param {string} url The Akamai base URL.
16622
+ * @param {object} [options] Optional configuration
16623
+ * @param {string} [options.apiKey] API key for Akamai authentication (required in DEV,
16624
+ * where there is no NGiNX to translate Authorization JWT into x-* headers).
16567
16625
  * @public
16568
16626
  */
16569
- setAkamaiBaseUrl(url) {
16570
- this.dispatch.setAkamaiBaseUrl(url);
16627
+ setAkamaiBaseUrl(url, options = {}) {
16628
+ this.dispatch.setAkamaiBaseUrl(url, options);
16571
16629
  }
16572
16630
  }
16573
16631