@adobe/acc-js-sdk 1.0.3 → 1.0.7

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/src/client.js CHANGED
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /*
3
2
  Copyright 2020 Adobe. All rights reserved.
4
3
  This file is licensed to you under the Apache License, Version 2.0 (the "License");
@@ -10,7 +9,9 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
10
9
  OF ANY KIND, either express or implied. See the License for the specific language
11
10
  governing permissions and limitations under the License.
12
11
  */
13
-
12
+ (function() {
13
+ "use strict";
14
+
14
15
 
15
16
  /**********************************************************************************
16
17
  *
@@ -86,7 +87,7 @@ const xtkObjectHandler = {
86
87
  });
87
88
 
88
89
  }
89
- }
90
+ };
90
91
 
91
92
  /**
92
93
  * Java Script Proxy handler for NLWS.
@@ -130,7 +131,7 @@ const clientHandler = {
130
131
  var promise = callContext.client._callMethod(methodName, callContext, argumentsList);
131
132
  return promise.then(function(optionAndValue) {
132
133
  const optionName = argumentsList[0];
133
- client._optionCache.cache(optionName, optionAndValue);
134
+ client._optionCache.put(optionName, optionAndValue);
134
135
  return optionAndValue;
135
136
  });
136
137
  }
@@ -143,7 +144,7 @@ const clientHandler = {
143
144
  return function(body) {
144
145
  callContext.object = body;
145
146
  return new Proxy(callContext, xtkObjectHandler);
146
- }
147
+ };
147
148
  }
148
149
 
149
150
  return new Proxy(caller, {
@@ -160,27 +161,32 @@ const clientHandler = {
160
161
  // Campaign credentials
161
162
  // ========================================================================================
162
163
 
163
- /**
164
- * Credentials to a Campaign instance. Encapsulates the various types of credentials.
165
- * Do not create directly, use one of the methods in ConnectionParameters
166
- *
164
+ /**
167
165
  * @class
168
166
  * @constructor
169
167
  * @private
170
- * @param {string} type the credentials type. Supported types are "UserPassword" and "ImsServiceToken" and "SessionToken" and "AnonymousUser"
171
- * @param {string} sessionToken the session token. It's exact form depends on the credentials type. For instance it can be "user/passord" for the "UserPassword" credentials type
172
- * @param {string} securityToken the security token. Will use an empty token if not specified
173
168
  * @memberof Campaign
174
169
  */
175
170
  class Credentials {
176
171
 
172
+ /**
173
+ * Credentials to a Campaign instance. Encapsulates the various types of credentials.
174
+ * Do not create directly, use one of the methods in ConnectionParameters
175
+ * @param {string} type the credentials type. Supported types are "UserPassword" and "ImsServiceToken" and "SessionToken" and "AnonymousUser"
176
+ * @param {string} sessionToken the session token. It's exact form depends on the credentials type. For instance it can be "user/passord" for the "UserPassword" credentials type
177
+ * @param {string} securityToken the security token. Will use an empty token if not specified
178
+ */
177
179
  constructor(type, sessionToken, securityToken) {
178
180
  if (type != "UserPassword" && type != "ImsServiceToken" && type != "SessionToken" &&
179
- type != "AnonymousUser" && type != "SecurityToken")
181
+ type != "AnonymousUser" && type != "SecurityToken" && type != "BearerToken")
180
182
  throw CampaignException.INVALID_CREDENTIALS_TYPE(type);
181
183
  this._type = type;
182
184
  this._sessionToken = sessionToken || "";
183
185
  this._securityToken = securityToken || "";
186
+ if (type == "BearerToken") {
187
+ this._bearerToken = sessionToken || "";
188
+ this._sessionToken = "";
189
+ }
184
190
  }
185
191
 
186
192
  /**
@@ -218,19 +224,39 @@ class Credentials {
218
224
  // ========================================================================================
219
225
 
220
226
  /**
221
- * Creates a connection parameters object which can be used to create a Client object
222
- * to connect to a Campaign instance
223
- *
227
+ * @typedef {Object} ConnectionOptions
228
+ * @property {string} representation - the representation to use, i.e. "SimpleJson" (the default), "BadgerFish", or "xml"
229
+ * @property {boolean} rememberMe - The Campaign `rememberMe` attribute which can be used to extend the lifetime of session tokens
230
+ * @property {number} entityCacheTTL - The TTL (in milliseconds) after which cached XTK entities expire. Defaults to 5 minutes
231
+ * @property {number} methodCacheTTL - The TTL (in milliseconds) after which cached XTK methods expire. Defaults to 5 minutes
232
+ * @property {number} optionCacheTTL - The TTL (in milliseconds) after which cached XTK options expire. Defaults to 5 minutes
233
+ * @property {boolean} traceAPICalls - Activates the tracing of all API calls
234
+ * @property {Utils.Transport} transport - Overrides the transport (i.e. HTTP layer)
235
+ * @property {boolean} noStorage - De-activate using of local storage. By default, and in addition to in-memory cache, entities, methods, and options are also persisted in local storage if there is one.
236
+ * @property {Storage} storage - Overrides the storage interface (i.e. LocalStorage)
237
+ * @memberOf Campaign
238
+ */
239
+
240
+
241
+ /**
224
242
  * @class
225
243
  * @constructor
226
- * @param {string} endpoint The campaign endpoint (URL)
227
- * @param {Credentials} credentials The credentials for the connection
228
- * @param {*} options connection options. Currently only contains a "representation" attribute which controls what type of entities (xml or json) the SDK handles
229
244
  * @memberof Campaign
230
245
  */
231
246
  class ConnectionParameters {
232
-
247
+
248
+ /**
249
+ * Creates a connection parameters object which can be used to create a Client object
250
+ * to connect to a Campaign instance
251
+ * @param {string} endpoint The campaign endpoint (URL)
252
+ * @param {Campaign.Credentials} credentials The credentials for the connection
253
+ * @param {Campaign.ConnectionOptions} options connection options
254
+ */
233
255
  constructor(endpoint, credentials, options) {
256
+ // this._options will be populated with the data from "options" and with
257
+ // default values. But the "options" parameter will not be modified
258
+ this._options = {};
259
+
234
260
  // Default value
235
261
  if (options === undefined || options === null)
236
262
  options = { };
@@ -240,18 +266,37 @@ class ConnectionParameters {
240
266
  if (typeof options != "object")
241
267
  throw CampaignException.INVALID_CONNECTION_OPTIONS(options);
242
268
 
243
- if (options.representation === undefined || options.representation === null)
244
- options.representation = "SimpleJson";
269
+ this._options.representation = options.representation;
270
+ if (this._options.representation === undefined || this._options.representation === null)
271
+ this._options.representation = "SimpleJson";
245
272
 
246
- if (options.representation != "xml" && options.representation != "BadgerFish" && options.representation != "SimpleJson")
247
- throw CampaignException.INVALID_REPRESENTATION(options.representation, "Cannot create Campaign client");
273
+ if (this._options.representation != "xml" && this._options.representation != "BadgerFish" && this._options.representation != "SimpleJson")
274
+ throw CampaignException.INVALID_REPRESENTATION(this._options.representation, "Cannot create Campaign client");
248
275
 
249
276
  // Defaults for rememberMe
250
- options.rememberMe = !!options.rememberMe;
277
+ this._options.rememberMe = !!options.rememberMe;
278
+
279
+ this._options.entityCacheTTL = options.entityCacheTTL || 1000*300; // 5 mins
280
+ this._options.methodCacheTTL = options.methodCacheTTL || 1000*300; // 5 mins
281
+ this._options.optionCacheTTL = options.optionCacheTTL || 1000*300; // 5 mins
282
+ this._options.traceAPICalls = options.traceAPICalls === null || options.traceAPICalls ? !!options.traceAPICalls : false;
283
+ this._options.transport = options.transport || request;
251
284
 
252
285
  this._endpoint = endpoint;
253
286
  this._credentials = credentials;
254
- this._options = options;
287
+
288
+ var storage;
289
+ if (!options.noStorage) {
290
+ storage = options.storage;
291
+ try {
292
+ if (!storage)
293
+ storage = localStorage;
294
+ } catch (ex) {
295
+ /* ignore error if localStorage not found */
296
+ }
297
+ }
298
+ this._options._storage = storage;
299
+ this._options.refreshClient = options.refreshClient;
255
300
  }
256
301
 
257
302
  /**
@@ -260,7 +305,7 @@ class ConnectionParameters {
260
305
  * @param {string} endpoint The campaign endpoint (URL)
261
306
  * @param {string} user The user name
262
307
  * @param {string} password The user password
263
- * @param {*} options connection options
308
+ * @param {Campaign.ConnectionOptions} options connection options
264
309
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
265
310
  */
266
311
  static ofUserAndPassword(endpoint, user, password, options) {
@@ -268,13 +313,25 @@ class ConnectionParameters {
268
313
  return new ConnectionParameters(endpoint, credentials, options);
269
314
  }
270
315
 
316
+ /**
317
+ * Creates connection parameters for a Campaign instance from bearer token
318
+ *
319
+ * @param {string} endpoint The campaign endpoint (URL)
320
+ * @param {string} bearerToken IMS bearer token
321
+ * @param {*} options connection options
322
+ * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
323
+ */
324
+ static ofBearerToken(endpoint, bearerToken, options) {
325
+ const credentials = new Credentials("BearerToken", bearerToken);
326
+ return new ConnectionParameters(endpoint, credentials, options);
327
+ }
271
328
  /**
272
329
  * Creates connection parameters for a Campaign instance, using an IMS service token and a user name (the user to impersonate)
273
330
  *
274
331
  * @param {string} endpoint The campaign endpoint (URL)
275
332
  * @param {string} user The user name
276
333
  * @param {string} serviceToken The IMS service token
277
- * @param {*} options connection options
334
+ * @param {Campaign.ConnectionOptions} options connection options
278
335
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
279
336
  */
280
337
  static ofUserAndServiceToken(endpoint, user, serviceToken, options) {
@@ -288,7 +345,7 @@ class ConnectionParameters {
288
345
  * @static
289
346
  * @param {string} endpoint The campaign endpoint (URL)
290
347
  * @param {string} sessionToken The session token
291
- * @param {*} options connection options
348
+ * @param {Campaign.ConnectionOptions} options connection options
292
349
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
293
350
  */
294
351
  static ofSessionToken(endpoint, sessionToken, options) {
@@ -305,7 +362,7 @@ class ConnectionParameters {
305
362
  * @static
306
363
  * @param {string} endpoint The campaign endpoint (URL)
307
364
  * @param {string} securityToken The session token
308
- * @param {*} options connection options
365
+ * @param {Campaign.ConnectionOptions} options connection options
309
366
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
310
367
  */
311
368
  static ofSecurityToken(endpoint, securityToken, options) {
@@ -317,7 +374,7 @@ class ConnectionParameters {
317
374
  * Creates connection parameters for a Campaign instance for an anonymous user
318
375
  *
319
376
  * @param {string} endpoint The campaign endpoint (URL)
320
- * @param {*} options connection options
377
+ * @param {Campaign.ConnectionOptions} options connection options
321
378
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
322
379
  */
323
380
  static ofAnonymousUser(endpoint, options) {
@@ -356,9 +413,9 @@ class ConnectionParameters {
356
413
  { "expr": "@type=3" }
357
414
  ]
358
415
  }
359
- }
416
+ };
360
417
  // Convert to current representation
361
- queryDef = client.convertToRepresentation(queryDef, "SimpleJson");
418
+ queryDef = client._convertToRepresentation(queryDef, "SimpleJson");
362
419
  const query = client.NLWS.xtkQueryDef.create(queryDef);
363
420
  const extAccount = await query.executeQuery();
364
421
 
@@ -381,18 +438,20 @@ class ConnectionParameters {
381
438
  // ========================================================================================
382
439
 
383
440
  /**
384
- * ACC API Client.
385
- * Do not create directly, use SDK.init instead
386
- *
387
441
  * @private
388
442
  * @class
389
443
  * @constructor
390
- * @param {Campaign.SDK} sdk is the global sdk object used to create the client
391
- * @param {Campaign.ConnectionParameters} user user name, for instance admin
392
444
  * @memberof Campaign
393
445
  */
394
446
  class Client {
395
-
447
+
448
+ /**
449
+ * ACC API Client.
450
+ * Do not create directly, use SDK.init instead
451
+ *
452
+ * @param {Campaign.SDK} sdk is the global sdk object used to create the client
453
+ * @param {Campaign.ConnectionParameters} user user name, for instance admin
454
+ */
396
455
  constructor(sdk, connectionParameters) {
397
456
  this.sdk = sdk;
398
457
  this._connectionParameters = connectionParameters; // ## TODO security concern (password kept in memory)
@@ -405,14 +464,22 @@ class Client {
405
464
 
406
465
  this._secretKeyCipher = undefined;
407
466
 
408
- this._entityCache = new XtkEntityCache();
409
- this._methodCache = new MethodCache();
410
- this._optionCache = new OptionCache();
467
+ this._storage = connectionParameters._options._storage;
468
+ // TODO late cache initiallzation because need XtkDatabaseId / instance name
469
+ var instanceKey = connectionParameters._endpoint || "";
470
+ if (instanceKey.startsWith("http://")) instanceKey = instanceKey.substr(7);
471
+ if (instanceKey.startsWith("https://")) instanceKey = instanceKey.substr(8);
472
+ const rootKey = `acc.js.sdk.${sdk.getSDKVersion().version}.${instanceKey}.cache`;
473
+
474
+ this._entityCache = new XtkEntityCache(this._storage, `${rootKey}.XtkEntityCache`, connectionParameters._options.entityCacheTTL);
475
+ this._methodCache = new MethodCache(this._storage, `${rootKey}.MethodCache`, connectionParameters._options.methodCacheTTL);
476
+ this._optionCache = new OptionCache(this._storage, `${rootKey}.OptionCache`, connectionParameters._options.optionCacheTTL);
411
477
  this.NLWS = new Proxy(this, clientHandler);
412
478
 
413
- this._transport = request;
414
- this._traceAPICalls = false;
479
+ this._transport = connectionParameters._options.transport;
480
+ this._traceAPICalls = connectionParameters._options.traceAPICalls;
415
481
  this._observers = [];
482
+ this._refreshClient = connectionParameters._options.refreshClient;
416
483
 
417
484
  // expose utilities
418
485
 
@@ -447,7 +514,7 @@ class Client {
447
514
  *
448
515
  * @returns {string} the user agent string
449
516
  */
450
- getUserAgentString() {
517
+ _getUserAgentString() {
451
518
  const version = this.sdk.getSDKVersion();
452
519
  return `${version.name}/${version.version} ${version.description}`;
453
520
  }
@@ -460,7 +527,7 @@ class Client {
460
527
  * @param {string} representation the expected representation ('xml', 'BadgerFish', or 'SimpleJson'). If not set, will use the current representation
461
528
  * @returns {XML.XtkObject} the object converted in the requested representation
462
529
  */
463
- toRepresentation(xml, representation) {
530
+ _toRepresentation(xml, representation) {
464
531
  representation = representation || this._representation;
465
532
  if (representation == "xml")
466
533
  return xml;
@@ -478,7 +545,7 @@ class Client {
478
545
  * @param {string} representation the expected representation ('xml', 'BadgerFish', or 'SimpleJson'). If not set, will use the current representation
479
546
  * @returns {DOMElement} the object converted to XML
480
547
  */
481
- fromRepresentation(rootName, entity, representation) {
548
+ _fromRepresentation(rootName, entity, representation) {
482
549
  representation = representation || this._representation;
483
550
  if (representation == "xml")
484
551
  return entity;
@@ -498,12 +565,12 @@ class Client {
498
565
  * @param {string} toRepresentation the target representation ('xml', 'BadgerFish', or 'SimpleJson'). If not set, will use the current representation
499
566
  * @returns {DOMElement} the converted object
500
567
  */
501
- convertToRepresentation(entity, fromRepresentation, toRepresentation) {
568
+ _convertToRepresentation(entity, fromRepresentation, toRepresentation) {
502
569
  toRepresentation = toRepresentation || this._representation;
503
- if (this.isSameRepresentation(fromRepresentation, toRepresentation))
570
+ if (this._isSameRepresentation(fromRepresentation, toRepresentation))
504
571
  return entity;
505
- var xml = this.fromRepresentation("root", entity, fromRepresentation);
506
- entity = this.toRepresentation(xml, toRepresentation);
572
+ var xml = this._fromRepresentation("root", entity, fromRepresentation);
573
+ entity = this._toRepresentation(xml, toRepresentation);
507
574
  return entity;
508
575
  }
509
576
 
@@ -515,7 +582,7 @@ class Client {
515
582
  * @param {string} rep2 the second representation ('xml', 'BadgerFish', or 'SimpleJson')
516
583
  * @returns a boolean indicating if the 2 representations are the same or not
517
584
  */
518
- isSameRepresentation(rep1, rep2) {
585
+ _isSameRepresentation(rep1, rep2) {
519
586
  if (!rep1 || !rep2) throw CampaignException.INVALID_REPRESENTATION(undefined, "Cannot compare to undefined representation");
520
587
  if (rep1 != "xml" && rep1 != "SimpleJson" && rep1 != "BadgerFish") throw CampaignException.INVALID_REPRESENTATION(rep1, "Cannot compare to invalid representation");
521
588
  if (rep2 != "xml" && rep2 != "SimpleJson" && rep2 != "BadgerFish") throw CampaignException.INVALID_REPRESENTATION(rep2, "Cannot compare to invalid representation");
@@ -575,6 +642,17 @@ class Client {
575
642
  if (credentialsType == "AnonymousUser")
576
643
  return true;
577
644
 
645
+ // When using bearer token authentication we are considered logged only after
646
+ // the bearer token has been converted into session token and security token
647
+ // by method xtk:session#BearerTokenLogon
648
+ if( credentialsType == "BearerToken")
649
+ return this._sessionToken != undefined &&
650
+ this._sessionToken != null &&
651
+ this._sessionToken != "" &&
652
+ this._securityToken != undefined &&
653
+ this._securityToken != null &&
654
+ this._securityToken != "";
655
+
578
656
  // with session token authentication, we do not expect a security token
579
657
  // with security token authentication, we do not expect a session token
580
658
  const needsSecurityToken = credentialsType != "SessionToken";
@@ -594,44 +672,80 @@ class Client {
594
672
  * @return {SOAP.SoapMethodCall} a SoapMethodCall which have been initialized with security tokens... and to which the method
595
673
  * parameters should be set
596
674
  */
597
- prepareSoapCall(urn, method, internal) {
598
- const soapCall = new SoapMethodCall(this._transport, urn, method, this._sessionToken, this._securityToken, this.getUserAgentString());
675
+ _prepareSoapCall(urn, method, internal) {
676
+ const soapCall = new SoapMethodCall(this._transport, urn, method, this._sessionToken, this._securityToken, this._getUserAgentString());
599
677
  soapCall.internal = !!internal;
600
678
  return soapCall;
601
679
  }
602
680
 
603
681
  /**
604
- * After a SOAP method call has been prepared with 'prepareSoapCall', and parameters have been added,
682
+ * Retry a a SOAP call
683
+ *
684
+ * @private
685
+ * @return {SOAP.SoapMethodCall} a SoapMethodCall to retry
686
+ * parameters should be set
687
+ */
688
+ async _retrySoapCall(soapCall) {
689
+ soapCall.retry = false;
690
+ var newClient = await this._refreshClient(this);
691
+ soapCall.finalize(newClient._soapEndPoint(), newClient);
692
+ if (this._traceAPICalls) {
693
+ const safeCallData = Util.trim(soapCall.request.data);
694
+ console.log(`RETRY SOAP//request ${safeCallData}`);
695
+ }
696
+ await soapCall.execute();
697
+ if (this._traceAPICalls) {
698
+ const safeCallResponse = Util.trim(soapCall.response);
699
+ console.log(`SOAP//response ${safeCallResponse}`);
700
+ }
701
+ return;
702
+ }
703
+
704
+ /**
705
+ * SOAP Endpoint
706
+ *
707
+ * @private
708
+ * @return {string} soap call End point
709
+ */
710
+ _soapEndPoint() {
711
+ return this._connectionParameters._endpoint + "/nl/jsp/soaprouter.jsp";
712
+ }
713
+ /**
714
+ * After a SOAP method call has been prepared with '_prepareSoapCall', and parameters have been added,
605
715
  * this function actually executes the SOAP call
606
716
  *
607
717
  * @private
608
718
  * @param {SOAP.SoapMethodCall} soapCall the SOAP method to call
609
719
  */
610
- makeSoapCall(soapCall) {
720
+ _makeSoapCall(soapCall) {
611
721
  const that = this;
612
722
  if (soapCall.requiresLogon() && !that.isLogged())
613
723
  throw CampaignException.NOT_LOGGED_IN(soapCall, `Cannot execute SOAP call ${soapCall.urn}#${soapCall.methodName}: you are not logged in. Use the Logon function first`);
614
- var soapEndpoint = that._connectionParameters._endpoint + "/nl/jsp/soaprouter.jsp";
615
- soapCall.finalize(soapEndpoint);
724
+ soapCall.finalize(this._soapEndPoint());
616
725
 
617
726
  const safeCallData = Util.trim(soapCall.request.data);
618
727
  if (that._traceAPICalls)
619
728
  console.log(`SOAP//request ${safeCallData}`);
620
- that._notifyObservers((observer) => { observer.onSOAPCall && observer.onSOAPCall(soapCall, safeCallData); });
729
+ that._notifyObservers((observer) => observer.onSOAPCall && observer.onSOAPCall(soapCall, safeCallData) );
621
730
 
622
731
  return soapCall.execute()
623
732
  .then(() => {
624
733
  const safeCallResponse = Util.trim(soapCall.response);
625
734
  if (that._traceAPICalls)
626
735
  console.log(`SOAP//response ${safeCallResponse}`);
627
- that._notifyObservers((observer) => { observer.onSOAPCallSuccess && observer.onSOAPCallSuccess(soapCall, safeCallResponse); });
736
+ that._notifyObservers((observer) => observer.onSOAPCallSuccess && observer.onSOAPCallSuccess(soapCall, safeCallResponse) );
628
737
  return Promise.resolve();
629
738
  })
630
739
  .catch((ex) => {
631
740
  if (that._traceAPICalls)
632
741
  console.log(`SOAP//failure ${ex.toString()}`);
633
- that._notifyObservers((observer) => { observer.onSOAPCallFailure && observer.onSOAPCallFailure(soapCall, ex); });
634
- return Promise.reject(ex);
742
+ that._notifyObservers((observer) => observer.onSOAPCallFailure && observer.onSOAPCallFailure(soapCall, ex) );
743
+ // Call session expiration callback in case of 401
744
+ if (ex.statusCode == 401 && that._refreshClient && soapCall.retry) {
745
+ return this._retrySoapCall(soapCall);
746
+ }
747
+ else
748
+ return Promise.reject(ex);
635
749
  });
636
750
  }
637
751
 
@@ -649,7 +763,7 @@ class Client {
649
763
 
650
764
  // Clear session token cookie to ensure we're not inheriting an expired cookie. See NEO-26589
651
765
  if (credentials._type != "SecurityToken" && typeof document != "undefined") {
652
- document.cookie = '__sessiontoken=;path=/;'
766
+ document.cookie = '__sessiontoken=;path=/;';
653
767
  }
654
768
  if (credentials._type == "SessionToken" || credentials._type == "AnonymousUser") {
655
769
  that._sessionInfo = undefined;
@@ -657,29 +771,37 @@ class Client {
657
771
  that._sessionToken = credentials._sessionToken;
658
772
  that._securityToken = "";
659
773
  that.application = new Application(that);
774
+ return Promise.resolve();
660
775
  }
661
- else if (credentials._type == "SecurityToken") {
662
- that._sessionInfo = undefined;
776
+ else if (credentials._type == "SecurityToken") {
777
+ that._sessionInfo = undefined;
663
778
  that._installedPackages = {};
664
779
  that._sessionToken = "";
665
780
  that._securityToken = credentials._securityToken;
666
781
  that.application = new Application(that);
782
+ return Promise.resolve();
667
783
  }
668
- else if (credentials._type == "UserPassword") {
669
- const user = credentials._getUser();
670
- const password = credentials._getPassword();
671
-
672
- const soapCall = this.prepareSoapCall("xtk:session", "Logon");
673
- soapCall.writeString("login", user);
674
- soapCall.writeString("password", password);
675
- var parameters = null;
676
- if (this._connectionParameters._options.rememberMe) {
677
- parameters = soapCall.createElement("parameters");
678
- parameters.setAttribute("rememberMe", "true");
784
+ else if (credentials._type == "UserPassword" || credentials._type == "BearerToken") {
785
+ const soapCall = that._prepareSoapCall("xtk:session", credentials._type === "UserPassword" ? "Logon" : "BearerTokenLogon");
786
+ // No retry for logon SOAP methods
787
+ soapCall.retry = false;
788
+ if (credentials._type == "UserPassword") {
789
+ const user = credentials._getUser();
790
+ const password = credentials._getPassword();
791
+ soapCall.writeString("login", user);
792
+ soapCall.writeString("password", password);
793
+ var parameters = null;
794
+ if (this._connectionParameters._options.rememberMe) {
795
+ parameters = soapCall.createElement("parameters");
796
+ parameters.setAttribute("rememberMe", "true");
797
+ }
798
+ soapCall.writeElement("parameters", parameters);
679
799
  }
680
- soapCall.writeElement("parameters", parameters);
681
-
682
- return this.makeSoapCall(soapCall).then(function() {
800
+ else {
801
+ const bearerToken = credentials._bearerToken;
802
+ soapCall.writeString("bearerToken", bearerToken);
803
+ }
804
+ return this._makeSoapCall(soapCall).then(function() {
683
805
  const sessionToken = soapCall.getNextString();
684
806
 
685
807
  that._sessionInfo = soapCall.getNextDocument();
@@ -722,7 +844,7 @@ class Client {
722
844
  */
723
845
  getSessionInfo(representation) {
724
846
  representation = representation || this._representation;
725
- return this.toRepresentation(this._sessionInfo, representation);
847
+ return this._toRepresentation(this._sessionInfo, representation);
726
848
  }
727
849
 
728
850
  /**
@@ -731,11 +853,10 @@ class Client {
731
853
  logoff() {
732
854
  var that = this;
733
855
  if (!that.isLogged()) return;
734
-
735
856
  const credentials = this._connectionParameters._credentials;
736
857
  if (credentials._type != "SessionToken" && credentials._type != "AnonymousUser") {
737
- var soapCall = that.prepareSoapCall("xtk:session", "Logoff");
738
- return this.makeSoapCall(soapCall).then(function() {
858
+ var soapCall = that._prepareSoapCall("xtk:session", "Logoff");
859
+ return this._makeSoapCall(soapCall).then(function() {
739
860
  that._sessionToken = "";
740
861
  that._securityToken = "";
741
862
  that.application = null;
@@ -757,13 +878,13 @@ class Client {
757
878
  * @return the option value, casted in the expected data type. If the option does not exist, it will return null.
758
879
  */
759
880
  async getOption(name, useCache = true) {
760
- var value = undefined;
881
+ var value;
761
882
  if (useCache)
762
883
  value = this._optionCache.get(name);
763
884
  if (value === undefined) {
764
885
  const option = await this.NLWS.xtkSession.getOption(name);
765
- value = this._optionCache.cache(name, option);
766
- this._optionCache.cache(name, option);
886
+ value = this._optionCache.put(name, option);
887
+ this._optionCache.put(name, option);
767
888
  }
768
889
  return value;
769
890
  }
@@ -797,7 +918,7 @@ class Client {
797
918
  doc[attName] = value;
798
919
  return this.NLWS.xtkSession.write(doc).then(() => {
799
920
  // Once set, cache the value
800
- this._optionCache.cache(name, [value, type]);
921
+ this._optionCache.put(name, [value, type]);
801
922
  });
802
923
  }
803
924
 
@@ -863,34 +984,38 @@ class Client {
863
984
  }
864
985
 
865
986
  /**
866
- * Fetches an entity (GetEntityIfMoreRecent)
987
+ * Gets an entity, such as a schema, a source schema, a form, a navtree, etc. Each Campaign entity has a MD5 which is used to determine
988
+ * if an entity has changed or not. The GetEntityIfMoreRecent SOAP call can use this MD5 to avoid returning entities that did not
989
+ * actually changed. Currently, the SDK, however is not able to use the MD5 and will perform a SOAP call every time the function is
990
+ * called and return the whole entity
867
991
  *
868
- * @private
869
992
  * @param {string} entityType is the type of entity requested, such as "xtk:schema", "xtk:srcSchema", "xtk:navtree", "xtk:form", etc.
870
993
  * @param {string} fullName is the fully qualified name of the entity (i.e. <namespace>:<name>)
871
994
  * @param {string} representation the expected representation, or undefined to set the default
872
- * @return A DOM representation of the entity, or null if the entity is not found
995
+ * @param {boolean} internal indicates an "internal" call, i.e. a call performed by the SDK itself rather than the user of the SDK. For instance, the SDK will dynamically load schemas to find method definitions
996
+ * @return {XML.XtkObject} A DOM or JSON representation of the entity, or null if the entity is not found
873
997
  */
874
998
  async getEntityIfMoreRecent(entityType, fullName, representation, internal) {
875
999
  const that = this;
876
- const soapCall = this.prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", internal);
1000
+ const soapCall = this._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", internal);
877
1001
  soapCall.writeString("pk", entityType + "|" + fullName);
878
1002
  soapCall.writeString("md5", "");
879
1003
  soapCall.writeBoolean("mustExist", false);
880
- return this.makeSoapCall(soapCall).then(function() {
1004
+ return this._makeSoapCall(soapCall).then(function() {
881
1005
  var doc = soapCall.getNextDocument();
882
1006
  soapCall.checkNoMoreArgs();
883
- doc = that.toRepresentation(doc, representation);
1007
+ doc = that._toRepresentation(doc, representation);
884
1008
  return doc;
885
1009
  });
886
1010
  }
887
1011
 
888
1012
  /**
889
- * Get a schema definition.
1013
+ * Get a compiled schema (not a source schema) definition as a DOM or JSON object depending on hte current representation
890
1014
  *
891
1015
  * @param {string} schemaId the schema id, such as "xtk:session", or "nms:recipient"
892
1016
  * @param {string} representation an optional representation of the schema: "BadgerFish", "SimpleJson" or "xml". If not set, we'll use the client default representation
893
- * @returns {*} the schema definition, as either a DOM document or a JSON object
1017
+ * @param {boolean} internal indicates an "internal" call, i.e. a call performed by the SDK itself rather than the user of the SDK. For instance, the SDK will dynamically load schemas to find method definitions
1018
+ * @returns {XML.XtkObject} the schema definition, as either a DOM document or a JSON object
894
1019
  */
895
1020
  async getSchema(schemaId, representation, internal) {
896
1021
  var that = this;
@@ -901,7 +1026,7 @@ class Client {
901
1026
  if (entity)
902
1027
  that._entityCache.put("xtk:schema", schemaId, entity);
903
1028
 
904
- entity = that.toRepresentation(entity, representation);
1029
+ entity = that._toRepresentation(entity, representation);
905
1030
  return entity;
906
1031
  }
907
1032
 
@@ -910,7 +1035,7 @@ class Client {
910
1035
  *
911
1036
  * @param {string} enumName
912
1037
  * @param {string} optionalStartSchemaOrSchemaName
913
- * @returns the enumeration definition in the current representation
1038
+ * @returns {XML.XtkObject} the enumeration definition in the current representation
914
1039
  */
915
1040
  async getSysEnum(enumName, optionalStartSchemaOrSchemaName) {
916
1041
 
@@ -967,7 +1092,7 @@ class Client {
967
1092
  var schemaName = schema.getAttribute("name");
968
1093
  var method = that._methodCache.get(schemaId, methodName);
969
1094
  if (!method) {
970
- this._methodCache.cache(schema);
1095
+ this._methodCache.put(schema);
971
1096
  method = that._methodCache.get(schemaId, methodName);
972
1097
  }
973
1098
  if (!method)
@@ -975,7 +1100,7 @@ class Client {
975
1100
  // console.log(method.toXMLString());
976
1101
 
977
1102
  var urn = that._methodCache.getSoapUrn(schemaId, methodName);
978
- var soapCall = that.prepareSoapCall(urn, methodName);
1103
+ var soapCall = that._prepareSoapCall(urn, methodName);
979
1104
 
980
1105
  const isStatic = DomUtil.getAttributeAsBoolean(method, "static");
981
1106
  var object = callContext.object;
@@ -984,7 +1109,7 @@ class Client {
984
1109
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Cannot call non-static method '${methodName}' of schema '${schemaId}' : no object was specified`);
985
1110
 
986
1111
  const rootName = schemaId.substr(schemaId.indexOf(':') + 1);
987
- object = that.fromRepresentation(rootName, object);
1112
+ object = that._fromRepresentation(rootName, object);
988
1113
  soapCall.writeDocument("document", object);
989
1114
  }
990
1115
 
@@ -994,7 +1119,7 @@ class Client {
994
1119
  var param = DomUtil.getFirstChildElement(params, "param");
995
1120
  var paramIndex = 0;
996
1121
  while (param) {
997
- const inout = DomUtil.getAttributeAsString(param, "inout");
1122
+ const inout = DomUtil.getAttributeAsString(param, "inout");
998
1123
  if (!inout || inout=="in") {
999
1124
  const type = DomUtil.getAttributeAsString(param, "type");
1000
1125
  const paramName = DomUtil.getAttributeAsString(param, "name");
@@ -1032,7 +1157,7 @@ class Client {
1032
1157
  const index = xtkschema.indexOf(":");
1033
1158
  docName = xtkschema.substr(index+1);
1034
1159
  }
1035
- var xmlValue = that.fromRepresentation(docName, paramValue);
1160
+ var xmlValue = that._fromRepresentation(docName, paramValue);
1036
1161
  if (type == "DOMDocument")
1037
1162
  soapCall.writeDocument(paramName, xmlValue);
1038
1163
  else
@@ -1045,13 +1170,13 @@ class Client {
1045
1170
  }
1046
1171
  }
1047
1172
 
1048
- return that.makeSoapCall(soapCall).then(function() {
1173
+ return that._makeSoapCall(soapCall).then(function() {
1049
1174
  if (!isStatic) {
1050
1175
  // Non static methods, such as xtk:query#SelectAll return a element named "entity" which is the object itself on which
1051
1176
  // the method is called. This is the new version of the object (in XML form)
1052
1177
  const entity = soapCall.getEntity();
1053
1178
  if (entity) {
1054
- callContext.object = that.toRepresentation(entity);
1179
+ callContext.object = that._toRepresentation(entity);
1055
1180
  }
1056
1181
  }
1057
1182
 
@@ -1082,7 +1207,7 @@ class Client {
1082
1207
  returnValue = soapCall.getNextDate();
1083
1208
  else if (type == "DOMDocument") {
1084
1209
  returnValue = soapCall.getNextDocument();
1085
- returnValue = that.toRepresentation(returnValue);
1210
+ returnValue = that._toRepresentation(returnValue);
1086
1211
  if (schemaId === "xtk:queryDef" && methodName === "ExecuteQuery" && paramName === "output") {
1087
1212
  // https://github.com/adobe/acc-js-sdk/issues/3
1088
1213
  // Check if query operation is "getIfExists". The "object" variable at this point
@@ -1102,32 +1227,27 @@ class Client {
1102
1227
  }
1103
1228
  else if (type == "DOMElement") {
1104
1229
  returnValue = soapCall.getNextElement();
1105
- returnValue = that.toRepresentation(returnValue);
1230
+ returnValue = that._toRepresentation(returnValue);
1106
1231
  }
1107
1232
  else {
1108
1233
  // type can reference a schema element. The naming convension is that the type name
1109
1234
  // is {schemaName}{elementNameCamelCase}. For instance, the type "sessionUserInfo"
1110
1235
  // matches the "userInfo" element of the "xtkSession" schema
1236
+ let element;
1111
1237
  if (type.substr(0, schemaName.length) == schemaName) {
1112
1238
  const shortTypeName = type.substr(schemaName.length, 1).toLowerCase() + type.substr(schemaName.length + 1);
1113
- var element = DomUtil.getFirstChildElement(schema, "element");
1239
+ element = DomUtil.getFirstChildElement(schema, "element");
1114
1240
  while (element) {
1115
1241
  if (element.getAttribute("name") == shortTypeName) {
1116
1242
  // Type found in schema: Process as a DOM element
1117
1243
  returnValue = soapCall.getNextElement();
1118
- returnValue = that.toRepresentation(returnValue);
1244
+ returnValue = that._toRepresentation(returnValue);
1119
1245
  break;
1120
1246
  }
1121
- element = DomUtil.getNextSiblingElement(element, "element")
1247
+ element = DomUtil.getNextSiblingElement(element, "element");
1122
1248
  }
1123
1249
 
1124
1250
  }
1125
- /* else if (type == "sessionUserInfo") {
1126
- returnValue = soapCall.getNextElement();
1127
- if (that._representation == "BadgerFish")
1128
- returnValue = DomUtil.toJSON(returnValue);
1129
- }
1130
- */
1131
1251
  if (!element)
1132
1252
  throw CampaignException.UNEXPECTED_SOAP_RESPONSE(soapCall, `Unsupported return type '${type}' for parameter '${paramName}' of method '${methodName}' of schema '${schemaId}'`);
1133
1253
  }
@@ -1147,23 +1267,23 @@ class Client {
1147
1267
  request.method = request.method || "GET";
1148
1268
  request.headers = request.headers || [];
1149
1269
  if (!request.headers['User-Agent'])
1150
- request.headers['User-Agent'] = this.getUserAgentString();
1270
+ request.headers['User-Agent'] = this._getUserAgentString();
1151
1271
  try {
1152
1272
  const safeCallData = Util.trim(request.data);
1153
1273
  if (this._traceAPICalls)
1154
1274
  console.log(`HTTP//request ${request.method} ${request.url}${safeCallData ? " " + safeCallData : ""}`);
1155
- this._notifyObservers((observer) => { observer.onHTTPCall && observer.onHTTPCall(request, safeCallData); });
1275
+ this._notifyObservers((observer) => observer.onHTTPCall && observer.onHTTPCall(request, safeCallData) );
1156
1276
  const body = await this._transport(request);
1157
1277
 
1158
1278
  const safeCallResponse = Util.trim(body);
1159
1279
  if (this._traceAPICalls)
1160
1280
  console.log(`HTTP//response${safeCallResponse ? " " + safeCallResponse : ""}`);
1161
- this._notifyObservers((observer) => { observer.onHTTPCallSuccess && observer.onHTTPCallSuccess(request, safeCallResponse); });
1281
+ this._notifyObservers((observer) => observer.onHTTPCallSuccess && observer.onHTTPCallSuccess(request, safeCallResponse) );
1162
1282
  return body;
1163
1283
  } catch(err) {
1164
1284
  if (this._traceAPICalls)
1165
1285
  console.log("HTTP//failure", err);
1166
- this._notifyObservers((observer) => { observer.onHTTPCallFailure && observer.onHTTPCallFailure(request, err); });
1286
+ this._notifyObservers((observer) => observer.onHTTPCallFailure && observer.onHTTPCallFailure(request, err) );
1167
1287
  throw makeCampaignException({ request:request, reqponse:err.response }, err);
1168
1288
  }
1169
1289
  }
@@ -1180,7 +1300,7 @@ class Client {
1180
1300
  };
1181
1301
  const body = await this._makeHttpCall(request);
1182
1302
  const xml = DomUtil.parse(body);
1183
- const result = this.toRepresentation(xml);
1303
+ const result = this._toRepresentation(xml);
1184
1304
  return result;
1185
1305
  }
1186
1306
 
@@ -1208,7 +1328,7 @@ class Client {
1208
1328
  const timestamp = lines[1].trim();
1209
1329
  if (timestamp != "") root.setAttribute("timestamp", timestamp);
1210
1330
  }
1211
- const result = this.toRepresentation(doc);
1331
+ const result = this._toRepresentation(doc);
1212
1332
  return result;
1213
1333
  }
1214
1334
 
@@ -1233,8 +1353,8 @@ class Client {
1233
1353
  var status = lines[0].trim();
1234
1354
  if (status != "") root.setAttribute("status", status);
1235
1355
 
1236
- var rtCount = undefined;
1237
- var threshold = undefined;
1356
+ var rtCount;
1357
+ var threshold;
1238
1358
  if (status == "Error") {
1239
1359
  const error = lines.length > 1 ? lines[1] : "";
1240
1360
  root.setAttribute("error", error);
@@ -1263,10 +1383,9 @@ class Client {
1263
1383
  }
1264
1384
  if (rtCount !== undefined && rtCount.trim() != "") root.setAttribute("eventQueueSize", rtCount);
1265
1385
  if (threshold !== undefined && rtCount.trim() != "") root.setAttribute("eventQueueMaxSize", threshold);
1266
- const result = this.toRepresentation(doc);
1386
+ const result = this._toRepresentation(doc);
1267
1387
  return result;
1268
1388
  }
1269
-
1270
1389
  }
1271
1390
 
1272
1391
 
@@ -1275,3 +1394,5 @@ Client.CampaignException = CampaignException;
1275
1394
  exports.Client = Client;
1276
1395
  exports.Credentials = Credentials;
1277
1396
  exports.ConnectionParameters = ConnectionParameters;
1397
+
1398
+ })();