@adobe/acc-js-sdk 1.0.2 → 1.0.6

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,26 +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
- if (type != "UserPassword" && type != "ImsServiceToken" && type != "SessionToken" && type != "AnonymousUser")
180
+ if (type != "UserPassword" && type != "ImsServiceToken" && type != "SessionToken" &&
181
+ type != "AnonymousUser" && type != "SecurityToken" && type != "BearerToken")
179
182
  throw CampaignException.INVALID_CREDENTIALS_TYPE(type);
180
183
  this._type = type;
181
184
  this._sessionToken = sessionToken || "";
182
185
  this._securityToken = securityToken || "";
186
+ if (type == "BearerToken") {
187
+ this._bearerToken = sessionToken || "";
188
+ this._sessionToken = "";
189
+ }
183
190
  }
184
191
 
185
192
  /**
@@ -217,19 +224,39 @@ class Credentials {
217
224
  // ========================================================================================
218
225
 
219
226
  /**
220
- * Creates a connection parameters object which can be used to create a Client object
221
- * to connect to a Campaign instance
222
- *
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
+ /**
223
242
  * @class
224
243
  * @constructor
225
- * @param {string} endpoint The campaign endpoint (URL)
226
- * @param {Credentials} credentials The credentials for the connection
227
- * @param {*} options connection options. Currently only contains a "representation" attribute which controls what type of entities (xml or json) the SDK handles
228
244
  * @memberof Campaign
229
245
  */
230
246
  class ConnectionParameters {
231
-
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
+ */
232
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
+
233
260
  // Default value
234
261
  if (options === undefined || options === null)
235
262
  options = { };
@@ -239,18 +266,36 @@ class ConnectionParameters {
239
266
  if (typeof options != "object")
240
267
  throw CampaignException.INVALID_CONNECTION_OPTIONS(options);
241
268
 
242
- if (options.representation === undefined || options.representation === null)
243
- options.representation = "SimpleJson";
269
+ this._options.representation = options.representation;
270
+ if (this._options.representation === undefined || this._options.representation === null)
271
+ this._options.representation = "SimpleJson";
244
272
 
245
- if (options.representation != "xml" && options.representation != "BadgerFish" && options.representation != "SimpleJson")
246
- 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");
247
275
 
248
276
  // Defaults for rememberMe
249
- 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;
250
284
 
251
285
  this._endpoint = endpoint;
252
286
  this._credentials = credentials;
253
- 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;
254
299
  }
255
300
 
256
301
  /**
@@ -259,7 +304,7 @@ class ConnectionParameters {
259
304
  * @param {string} endpoint The campaign endpoint (URL)
260
305
  * @param {string} user The user name
261
306
  * @param {string} password The user password
262
- * @param {*} options connection options
307
+ * @param {Campaign.ConnectionOptions} options connection options
263
308
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
264
309
  */
265
310
  static ofUserAndPassword(endpoint, user, password, options) {
@@ -267,13 +312,25 @@ class ConnectionParameters {
267
312
  return new ConnectionParameters(endpoint, credentials, options);
268
313
  }
269
314
 
315
+ /**
316
+ * Creates connection parameters for a Campaign instance from bearer token
317
+ *
318
+ * @param {string} endpoint The campaign endpoint (URL)
319
+ * @param {string} bearerToken IMS bearer token
320
+ * @param {*} options connection options
321
+ * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
322
+ */
323
+ static ofBearerToken(endpoint, bearerToken, options) {
324
+ const credentials = new Credentials("BearerToken", bearerToken);
325
+ return new ConnectionParameters(endpoint, credentials, options);
326
+ }
270
327
  /**
271
328
  * Creates connection parameters for a Campaign instance, using an IMS service token and a user name (the user to impersonate)
272
329
  *
273
330
  * @param {string} endpoint The campaign endpoint (URL)
274
331
  * @param {string} user The user name
275
332
  * @param {string} serviceToken The IMS service token
276
- * @param {*} options connection options
333
+ * @param {Campaign.ConnectionOptions} options connection options
277
334
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
278
335
  */
279
336
  static ofUserAndServiceToken(endpoint, user, serviceToken, options) {
@@ -287,7 +344,7 @@ class ConnectionParameters {
287
344
  * @static
288
345
  * @param {string} endpoint The campaign endpoint (URL)
289
346
  * @param {string} sessionToken The session token
290
- * @param {*} options connection options
347
+ * @param {Campaign.ConnectionOptions} options connection options
291
348
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
292
349
  */
293
350
  static ofSessionToken(endpoint, sessionToken, options) {
@@ -295,11 +352,28 @@ class ConnectionParameters {
295
352
  return new ConnectionParameters(endpoint, credentials, options);
296
353
  }
297
354
 
355
+ /**
356
+ * Creates connection parameters for a Campaign instance, using a security token.
357
+ * Typically, called when embedding the SDK in Campaign: the session token will be
358
+ * passed automatically as a cookie, so only the security token is actually needed
359
+ * to logon
360
+ *
361
+ * @static
362
+ * @param {string} endpoint The campaign endpoint (URL)
363
+ * @param {string} securityToken The session token
364
+ * @param {Campaign.ConnectionOptions} options connection options
365
+ * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
366
+ */
367
+ static ofSecurityToken(endpoint, securityToken, options) {
368
+ const credentials = new Credentials("SecurityToken", "", securityToken);
369
+ return new ConnectionParameters(endpoint, credentials, options);
370
+ }
371
+
298
372
  /**
299
373
  * Creates connection parameters for a Campaign instance for an anonymous user
300
374
  *
301
375
  * @param {string} endpoint The campaign endpoint (URL)
302
- * @param {*} options connection options
376
+ * @param {Campaign.ConnectionOptions} options connection options
303
377
  * @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
304
378
  */
305
379
  static ofAnonymousUser(endpoint, options) {
@@ -338,9 +412,9 @@ class ConnectionParameters {
338
412
  { "expr": "@type=3" }
339
413
  ]
340
414
  }
341
- }
415
+ };
342
416
  // Convert to current representation
343
- queryDef = client.convertToRepresentation(queryDef, "SimpleJson");
417
+ queryDef = client._convertToRepresentation(queryDef, "SimpleJson");
344
418
  const query = client.NLWS.xtkQueryDef.create(queryDef);
345
419
  const extAccount = await query.executeQuery();
346
420
 
@@ -363,18 +437,20 @@ class ConnectionParameters {
363
437
  // ========================================================================================
364
438
 
365
439
  /**
366
- * ACC API Client.
367
- * Do not create directly, use SDK.init instead
368
- *
369
440
  * @private
370
441
  * @class
371
442
  * @constructor
372
- * @param {Campaign.SDK} sdk is the global sdk object used to create the client
373
- * @param {Campaign.ConnectionParameters} user user name, for instance admin
374
443
  * @memberof Campaign
375
444
  */
376
445
  class Client {
377
-
446
+
447
+ /**
448
+ * ACC API Client.
449
+ * Do not create directly, use SDK.init instead
450
+ *
451
+ * @param {Campaign.SDK} sdk is the global sdk object used to create the client
452
+ * @param {Campaign.ConnectionParameters} user user name, for instance admin
453
+ */
378
454
  constructor(sdk, connectionParameters) {
379
455
  this.sdk = sdk;
380
456
  this._connectionParameters = connectionParameters; // ## TODO security concern (password kept in memory)
@@ -387,13 +463,20 @@ class Client {
387
463
 
388
464
  this._secretKeyCipher = undefined;
389
465
 
390
- this._entityCache = new XtkEntityCache();
391
- this._methodCache = new MethodCache();
392
- this._optionCache = new OptionCache();
466
+ this._storage = connectionParameters._options._storage;
467
+ // TODO late cache initiallzation because need XtkDatabaseId / instance name
468
+ var instanceKey = connectionParameters._endpoint || "";
469
+ if (instanceKey.startsWith("http://")) instanceKey = instanceKey.substr(7);
470
+ if (instanceKey.startsWith("https://")) instanceKey = instanceKey.substr(8);
471
+ const rootKey = `acc.js.sdk.${sdk.getSDKVersion().version}.${instanceKey}.cache`;
472
+
473
+ this._entityCache = new XtkEntityCache(this._storage, `${rootKey}.XtkEntityCache`, connectionParameters._options.entityCacheTTL);
474
+ this._methodCache = new MethodCache(this._storage, `${rootKey}.MethodCache`, connectionParameters._options.methodCacheTTL);
475
+ this._optionCache = new OptionCache(this._storage, `${rootKey}.OptionCache`, connectionParameters._options.optionCacheTTL);
393
476
  this.NLWS = new Proxy(this, clientHandler);
394
477
 
395
- this._transport = request;
396
- this._traceAPICalls = false;
478
+ this._transport = connectionParameters._options.transport;
479
+ this._traceAPICalls = connectionParameters._options.traceAPICalls;
397
480
  this._observers = [];
398
481
 
399
482
  // expose utilities
@@ -429,7 +512,7 @@ class Client {
429
512
  *
430
513
  * @returns {string} the user agent string
431
514
  */
432
- getUserAgentString() {
515
+ _getUserAgentString() {
433
516
  const version = this.sdk.getSDKVersion();
434
517
  return `${version.name}/${version.version} ${version.description}`;
435
518
  }
@@ -442,7 +525,7 @@ class Client {
442
525
  * @param {string} representation the expected representation ('xml', 'BadgerFish', or 'SimpleJson'). If not set, will use the current representation
443
526
  * @returns {XML.XtkObject} the object converted in the requested representation
444
527
  */
445
- toRepresentation(xml, representation) {
528
+ _toRepresentation(xml, representation) {
446
529
  representation = representation || this._representation;
447
530
  if (representation == "xml")
448
531
  return xml;
@@ -460,7 +543,7 @@ class Client {
460
543
  * @param {string} representation the expected representation ('xml', 'BadgerFish', or 'SimpleJson'). If not set, will use the current representation
461
544
  * @returns {DOMElement} the object converted to XML
462
545
  */
463
- fromRepresentation(rootName, entity, representation) {
546
+ _fromRepresentation(rootName, entity, representation) {
464
547
  representation = representation || this._representation;
465
548
  if (representation == "xml")
466
549
  return entity;
@@ -480,12 +563,12 @@ class Client {
480
563
  * @param {string} toRepresentation the target representation ('xml', 'BadgerFish', or 'SimpleJson'). If not set, will use the current representation
481
564
  * @returns {DOMElement} the converted object
482
565
  */
483
- convertToRepresentation(entity, fromRepresentation, toRepresentation) {
566
+ _convertToRepresentation(entity, fromRepresentation, toRepresentation) {
484
567
  toRepresentation = toRepresentation || this._representation;
485
- if (this.isSameRepresentation(fromRepresentation, toRepresentation))
568
+ if (this._isSameRepresentation(fromRepresentation, toRepresentation))
486
569
  return entity;
487
- var xml = this.fromRepresentation("root", entity, fromRepresentation);
488
- entity = this.toRepresentation(xml, toRepresentation);
570
+ var xml = this._fromRepresentation("root", entity, fromRepresentation);
571
+ entity = this._toRepresentation(xml, toRepresentation);
489
572
  return entity;
490
573
  }
491
574
 
@@ -497,7 +580,7 @@ class Client {
497
580
  * @param {string} rep2 the second representation ('xml', 'BadgerFish', or 'SimpleJson')
498
581
  * @returns a boolean indicating if the 2 representations are the same or not
499
582
  */
500
- isSameRepresentation(rep1, rep2) {
583
+ _isSameRepresentation(rep1, rep2) {
501
584
  if (!rep1 || !rep2) throw CampaignException.INVALID_REPRESENTATION(undefined, "Cannot compare to undefined representation");
502
585
  if (rep1 != "xml" && rep1 != "SimpleJson" && rep1 != "BadgerFish") throw CampaignException.INVALID_REPRESENTATION(rep1, "Cannot compare to invalid representation");
503
586
  if (rep2 != "xml" && rep2 != "SimpleJson" && rep2 != "BadgerFish") throw CampaignException.INVALID_REPRESENTATION(rep2, "Cannot compare to invalid representation");
@@ -557,16 +640,25 @@ class Client {
557
640
  if (credentialsType == "AnonymousUser")
558
641
  return true;
559
642
 
643
+ // When using bearer token authentication we are considered logged only after
644
+ // the bearer token has been converted into session token and security token
645
+ // by method xtk:session#BearerTokenLogon
646
+ if( credentialsType == "BearerToken")
647
+ return this._sessionToken != undefined &&
648
+ this._sessionToken != null &&
649
+ this._sessionToken != "" &&
650
+ this._securityToken != undefined &&
651
+ this._securityToken != null &&
652
+ this._securityToken != "";
653
+
560
654
  // with session token authentication, we do not expect a security token
561
- const isSessionTokenAuth = credentialsType == "SessionToken";
562
-
563
- return this._sessionToken !== null &&
564
- this._sessionToken !== undefined &&
565
- this._sessionToken !== "" &&
566
- (isSessionTokenAuth || (
567
- this._securityToken !== null &&
568
- this._securityToken !== undefined &&
569
- this._securityToken !== ""));
655
+ // with security token authentication, we do not expect a session token
656
+ const needsSecurityToken = credentialsType != "SessionToken";
657
+ const hasSecurityToken = this._securityToken !== null && this._securityToken !== undefined && this._securityToken !== "";
658
+ const needsSessionToken = credentialsType != "SecurityToken";
659
+ const hasSessionToken = this._sessionToken !== null && this._sessionToken !== undefined && this._sessionToken !== "";
660
+
661
+ return (!needsSecurityToken || hasSecurityToken) && (!needsSessionToken || hasSessionToken);
570
662
  }
571
663
 
572
664
  /**
@@ -578,20 +670,20 @@ class Client {
578
670
  * @return {SOAP.SoapMethodCall} a SoapMethodCall which have been initialized with security tokens... and to which the method
579
671
  * parameters should be set
580
672
  */
581
- prepareSoapCall(urn, method, internal) {
582
- const soapCall = new SoapMethodCall(this._transport, urn, method, this._sessionToken, this._securityToken, this.getUserAgentString());
673
+ _prepareSoapCall(urn, method, internal) {
674
+ const soapCall = new SoapMethodCall(this._transport, urn, method, this._sessionToken, this._securityToken, this._getUserAgentString());
583
675
  soapCall.internal = !!internal;
584
676
  return soapCall;
585
677
  }
586
678
 
587
679
  /**
588
- * After a SOAP method call has been prepared with 'prepareSoapCall', and parameters have been added,
680
+ * After a SOAP method call has been prepared with '_prepareSoapCall', and parameters have been added,
589
681
  * this function actually executes the SOAP call
590
682
  *
591
683
  * @private
592
684
  * @param {SOAP.SoapMethodCall} soapCall the SOAP method to call
593
685
  */
594
- makeSoapCall(soapCall) {
686
+ _makeSoapCall(soapCall) {
595
687
  const that = this;
596
688
  if (soapCall.requiresLogon() && !that.isLogged())
597
689
  throw CampaignException.NOT_LOGGED_IN(soapCall, `Cannot execute SOAP call ${soapCall.urn}#${soapCall.methodName}: you are not logged in. Use the Logon function first`);
@@ -601,20 +693,20 @@ class Client {
601
693
  const safeCallData = Util.trim(soapCall.request.data);
602
694
  if (that._traceAPICalls)
603
695
  console.log(`SOAP//request ${safeCallData}`);
604
- that._notifyObservers((observer) => { observer.onSOAPCall && observer.onSOAPCall(soapCall, safeCallData); });
696
+ that._notifyObservers((observer) => observer.onSOAPCall && observer.onSOAPCall(soapCall, safeCallData) );
605
697
 
606
698
  return soapCall.execute()
607
699
  .then(() => {
608
700
  const safeCallResponse = Util.trim(soapCall.response);
609
701
  if (that._traceAPICalls)
610
702
  console.log(`SOAP//response ${safeCallResponse}`);
611
- that._notifyObservers((observer) => { observer.onSOAPCallSuccess && observer.onSOAPCallSuccess(soapCall, safeCallResponse); });
703
+ that._notifyObservers((observer) => observer.onSOAPCallSuccess && observer.onSOAPCallSuccess(soapCall, safeCallResponse) );
612
704
  return Promise.resolve();
613
705
  })
614
706
  .catch((ex) => {
615
707
  if (that._traceAPICalls)
616
708
  console.log(`SOAP//failure ${ex.toString()}`);
617
- that._notifyObservers((observer) => { observer.onSOAPCallFailure && observer.onSOAPCallFailure(soapCall, ex); });
709
+ that._notifyObservers((observer) => observer.onSOAPCallFailure && observer.onSOAPCallFailure(soapCall, ex) );
618
710
  return Promise.reject(ex);
619
711
  });
620
712
  }
@@ -629,35 +721,47 @@ class Client {
629
721
  this.application = null;
630
722
  this._sessionToken = "";
631
723
  this._securityToken = "";
724
+ const credentials = this._connectionParameters._credentials;
632
725
 
633
726
  // Clear session token cookie to ensure we're not inheriting an expired cookie. See NEO-26589
634
- if (typeof document != "undefined") {
635
- document.cookie = '__sessiontoken=;path=/;'
727
+ if (credentials._type != "SecurityToken" && typeof document != "undefined") {
728
+ document.cookie = '__sessiontoken=;path=/;';
636
729
  }
637
-
638
- const credentials = this._connectionParameters._credentials;
639
730
  if (credentials._type == "SessionToken" || credentials._type == "AnonymousUser") {
640
731
  that._sessionInfo = undefined;
641
732
  that._installedPackages = {};
642
733
  that._sessionToken = credentials._sessionToken;
643
734
  that._securityToken = "";
644
735
  that.application = new Application(that);
736
+ return Promise.resolve();
645
737
  }
646
- else if (credentials._type == "UserPassword") {
647
- const user = credentials._getUser();
648
- const password = credentials._getPassword();
649
-
650
- const soapCall = this.prepareSoapCall("xtk:session", "Logon");
651
- soapCall.writeString("login", user);
652
- soapCall.writeString("password", password);
653
- var parameters = null;
654
- if (this._connectionParameters._options.rememberMe) {
655
- parameters = soapCall.createElement("parameters");
656
- parameters.setAttribute("rememberMe", "true");
738
+ else if (credentials._type == "SecurityToken") {
739
+ that._sessionInfo = undefined;
740
+ that._installedPackages = {};
741
+ that._sessionToken = "";
742
+ that._securityToken = credentials._securityToken;
743
+ that.application = new Application(that);
744
+ return Promise.resolve();
745
+ }
746
+ else if (credentials._type == "UserPassword" || credentials._type == "BearerToken") {
747
+ const soapCall = that._prepareSoapCall("xtk:session", credentials._type === "UserPassword" ? "Logon" : "BearerTokenLogon");
748
+ if (credentials._type == "UserPassword") {
749
+ const user = credentials._getUser();
750
+ const password = credentials._getPassword();
751
+ soapCall.writeString("login", user);
752
+ soapCall.writeString("password", password);
753
+ var parameters = null;
754
+ if (this._connectionParameters._options.rememberMe) {
755
+ parameters = soapCall.createElement("parameters");
756
+ parameters.setAttribute("rememberMe", "true");
757
+ }
758
+ soapCall.writeElement("parameters", parameters);
657
759
  }
658
- soapCall.writeElement("parameters", parameters);
659
-
660
- return this.makeSoapCall(soapCall).then(function() {
760
+ else {
761
+ const bearerToken = credentials._bearerToken;
762
+ soapCall.writeString("bearerToken", bearerToken);
763
+ }
764
+ return this._makeSoapCall(soapCall).then(function() {
661
765
  const sessionToken = soapCall.getNextString();
662
766
 
663
767
  that._sessionInfo = soapCall.getNextDocument();
@@ -700,7 +804,7 @@ class Client {
700
804
  */
701
805
  getSessionInfo(representation) {
702
806
  representation = representation || this._representation;
703
- return this.toRepresentation(this._sessionInfo, representation);
807
+ return this._toRepresentation(this._sessionInfo, representation);
704
808
  }
705
809
 
706
810
  /**
@@ -712,8 +816,8 @@ class Client {
712
816
 
713
817
  const credentials = this._connectionParameters._credentials;
714
818
  if (credentials._type != "SessionToken" && credentials._type != "AnonymousUser") {
715
- var soapCall = that.prepareSoapCall("xtk:session", "Logoff");
716
- return this.makeSoapCall(soapCall).then(function() {
819
+ var soapCall = that._prepareSoapCall("xtk:session", "Logoff");
820
+ return this._makeSoapCall(soapCall).then(function() {
717
821
  that._sessionToken = "";
718
822
  that._securityToken = "";
719
823
  that.application = null;
@@ -735,13 +839,13 @@ class Client {
735
839
  * @return the option value, casted in the expected data type. If the option does not exist, it will return null.
736
840
  */
737
841
  async getOption(name, useCache = true) {
738
- var value = undefined;
842
+ var value;
739
843
  if (useCache)
740
844
  value = this._optionCache.get(name);
741
845
  if (value === undefined) {
742
846
  const option = await this.NLWS.xtkSession.getOption(name);
743
- value = this._optionCache.cache(name, option);
744
- this._optionCache.cache(name, option);
847
+ value = this._optionCache.put(name, option);
848
+ this._optionCache.put(name, option);
745
849
  }
746
850
  return value;
747
851
  }
@@ -775,7 +879,7 @@ class Client {
775
879
  doc[attName] = value;
776
880
  return this.NLWS.xtkSession.write(doc).then(() => {
777
881
  // Once set, cache the value
778
- this._optionCache.cache(name, [value, type]);
882
+ this._optionCache.put(name, [value, type]);
779
883
  });
780
884
  }
781
885
 
@@ -841,34 +945,38 @@ class Client {
841
945
  }
842
946
 
843
947
  /**
844
- * Fetches an entity (GetEntityIfMoreRecent)
948
+ * 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
949
+ * if an entity has changed or not. The GetEntityIfMoreRecent SOAP call can use this MD5 to avoid returning entities that did not
950
+ * actually changed. Currently, the SDK, however is not able to use the MD5 and will perform a SOAP call every time the function is
951
+ * called and return the whole entity
845
952
  *
846
- * @private
847
953
  * @param {string} entityType is the type of entity requested, such as "xtk:schema", "xtk:srcSchema", "xtk:navtree", "xtk:form", etc.
848
954
  * @param {string} fullName is the fully qualified name of the entity (i.e. <namespace>:<name>)
849
955
  * @param {string} representation the expected representation, or undefined to set the default
850
- * @return A DOM representation of the entity, or null if the entity is not found
956
+ * @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
957
+ * @return {XML.XtkObject} A DOM or JSON representation of the entity, or null if the entity is not found
851
958
  */
852
959
  async getEntityIfMoreRecent(entityType, fullName, representation, internal) {
853
960
  const that = this;
854
- const soapCall = this.prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", internal);
961
+ const soapCall = this._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", internal);
855
962
  soapCall.writeString("pk", entityType + "|" + fullName);
856
963
  soapCall.writeString("md5", "");
857
964
  soapCall.writeBoolean("mustExist", false);
858
- return this.makeSoapCall(soapCall).then(function() {
965
+ return this._makeSoapCall(soapCall).then(function() {
859
966
  var doc = soapCall.getNextDocument();
860
967
  soapCall.checkNoMoreArgs();
861
- doc = that.toRepresentation(doc, representation);
968
+ doc = that._toRepresentation(doc, representation);
862
969
  return doc;
863
970
  });
864
971
  }
865
972
 
866
973
  /**
867
- * Get a schema definition.
974
+ * Get a compiled schema (not a source schema) definition as a DOM or JSON object depending on hte current representation
868
975
  *
869
976
  * @param {string} schemaId the schema id, such as "xtk:session", or "nms:recipient"
870
977
  * @param {string} representation an optional representation of the schema: "BadgerFish", "SimpleJson" or "xml". If not set, we'll use the client default representation
871
- * @returns {*} the schema definition, as either a DOM document or a JSON object
978
+ * @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
979
+ * @returns {XML.XtkObject} the schema definition, as either a DOM document or a JSON object
872
980
  */
873
981
  async getSchema(schemaId, representation, internal) {
874
982
  var that = this;
@@ -879,7 +987,7 @@ class Client {
879
987
  if (entity)
880
988
  that._entityCache.put("xtk:schema", schemaId, entity);
881
989
 
882
- entity = that.toRepresentation(entity, representation);
990
+ entity = that._toRepresentation(entity, representation);
883
991
  return entity;
884
992
  }
885
993
 
@@ -888,7 +996,7 @@ class Client {
888
996
  *
889
997
  * @param {string} enumName
890
998
  * @param {string} optionalStartSchemaOrSchemaName
891
- * @returns the enumeration definition in the current representation
999
+ * @returns {XML.XtkObject} the enumeration definition in the current representation
892
1000
  */
893
1001
  async getSysEnum(enumName, optionalStartSchemaOrSchemaName) {
894
1002
 
@@ -945,7 +1053,7 @@ class Client {
945
1053
  var schemaName = schema.getAttribute("name");
946
1054
  var method = that._methodCache.get(schemaId, methodName);
947
1055
  if (!method) {
948
- this._methodCache.cache(schema);
1056
+ this._methodCache.put(schema);
949
1057
  method = that._methodCache.get(schemaId, methodName);
950
1058
  }
951
1059
  if (!method)
@@ -953,7 +1061,7 @@ class Client {
953
1061
  // console.log(method.toXMLString());
954
1062
 
955
1063
  var urn = that._methodCache.getSoapUrn(schemaId, methodName);
956
- var soapCall = that.prepareSoapCall(urn, methodName);
1064
+ var soapCall = that._prepareSoapCall(urn, methodName);
957
1065
 
958
1066
  const isStatic = DomUtil.getAttributeAsBoolean(method, "static");
959
1067
  var object = callContext.object;
@@ -962,7 +1070,7 @@ class Client {
962
1070
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Cannot call non-static method '${methodName}' of schema '${schemaId}' : no object was specified`);
963
1071
 
964
1072
  const rootName = schemaId.substr(schemaId.indexOf(':') + 1);
965
- object = that.fromRepresentation(rootName, object);
1073
+ object = that._fromRepresentation(rootName, object);
966
1074
  soapCall.writeDocument("document", object);
967
1075
  }
968
1076
 
@@ -972,7 +1080,7 @@ class Client {
972
1080
  var param = DomUtil.getFirstChildElement(params, "param");
973
1081
  var paramIndex = 0;
974
1082
  while (param) {
975
- const inout = DomUtil.getAttributeAsString(param, "inout");
1083
+ const inout = DomUtil.getAttributeAsString(param, "inout");
976
1084
  if (!inout || inout=="in") {
977
1085
  const type = DomUtil.getAttributeAsString(param, "type");
978
1086
  const paramName = DomUtil.getAttributeAsString(param, "name");
@@ -1010,7 +1118,7 @@ class Client {
1010
1118
  const index = xtkschema.indexOf(":");
1011
1119
  docName = xtkschema.substr(index+1);
1012
1120
  }
1013
- var xmlValue = that.fromRepresentation(docName, paramValue);
1121
+ var xmlValue = that._fromRepresentation(docName, paramValue);
1014
1122
  if (type == "DOMDocument")
1015
1123
  soapCall.writeDocument(paramName, xmlValue);
1016
1124
  else
@@ -1023,13 +1131,13 @@ class Client {
1023
1131
  }
1024
1132
  }
1025
1133
 
1026
- return that.makeSoapCall(soapCall).then(function() {
1134
+ return that._makeSoapCall(soapCall).then(function() {
1027
1135
  if (!isStatic) {
1028
1136
  // Non static methods, such as xtk:query#SelectAll return a element named "entity" which is the object itself on which
1029
1137
  // the method is called. This is the new version of the object (in XML form)
1030
1138
  const entity = soapCall.getEntity();
1031
1139
  if (entity) {
1032
- callContext.object = that.toRepresentation(entity);
1140
+ callContext.object = that._toRepresentation(entity);
1033
1141
  }
1034
1142
  }
1035
1143
 
@@ -1060,7 +1168,7 @@ class Client {
1060
1168
  returnValue = soapCall.getNextDate();
1061
1169
  else if (type == "DOMDocument") {
1062
1170
  returnValue = soapCall.getNextDocument();
1063
- returnValue = that.toRepresentation(returnValue);
1171
+ returnValue = that._toRepresentation(returnValue);
1064
1172
  if (schemaId === "xtk:queryDef" && methodName === "ExecuteQuery" && paramName === "output") {
1065
1173
  // https://github.com/adobe/acc-js-sdk/issues/3
1066
1174
  // Check if query operation is "getIfExists". The "object" variable at this point
@@ -1080,32 +1188,27 @@ class Client {
1080
1188
  }
1081
1189
  else if (type == "DOMElement") {
1082
1190
  returnValue = soapCall.getNextElement();
1083
- returnValue = that.toRepresentation(returnValue);
1191
+ returnValue = that._toRepresentation(returnValue);
1084
1192
  }
1085
1193
  else {
1086
1194
  // type can reference a schema element. The naming convension is that the type name
1087
1195
  // is {schemaName}{elementNameCamelCase}. For instance, the type "sessionUserInfo"
1088
1196
  // matches the "userInfo" element of the "xtkSession" schema
1197
+ let element;
1089
1198
  if (type.substr(0, schemaName.length) == schemaName) {
1090
1199
  const shortTypeName = type.substr(schemaName.length, 1).toLowerCase() + type.substr(schemaName.length + 1);
1091
- var element = DomUtil.getFirstChildElement(schema, "element");
1200
+ element = DomUtil.getFirstChildElement(schema, "element");
1092
1201
  while (element) {
1093
1202
  if (element.getAttribute("name") == shortTypeName) {
1094
1203
  // Type found in schema: Process as a DOM element
1095
1204
  returnValue = soapCall.getNextElement();
1096
- returnValue = that.toRepresentation(returnValue);
1205
+ returnValue = that._toRepresentation(returnValue);
1097
1206
  break;
1098
1207
  }
1099
- element = DomUtil.getNextSiblingElement(element, "element")
1208
+ element = DomUtil.getNextSiblingElement(element, "element");
1100
1209
  }
1101
1210
 
1102
1211
  }
1103
- /* else if (type == "sessionUserInfo") {
1104
- returnValue = soapCall.getNextElement();
1105
- if (that._representation == "BadgerFish")
1106
- returnValue = DomUtil.toJSON(returnValue);
1107
- }
1108
- */
1109
1212
  if (!element)
1110
1213
  throw CampaignException.UNEXPECTED_SOAP_RESPONSE(soapCall, `Unsupported return type '${type}' for parameter '${paramName}' of method '${methodName}' of schema '${schemaId}'`);
1111
1214
  }
@@ -1125,23 +1228,23 @@ class Client {
1125
1228
  request.method = request.method || "GET";
1126
1229
  request.headers = request.headers || [];
1127
1230
  if (!request.headers['User-Agent'])
1128
- request.headers['User-Agent'] = this.getUserAgentString();
1231
+ request.headers['User-Agent'] = this._getUserAgentString();
1129
1232
  try {
1130
1233
  const safeCallData = Util.trim(request.data);
1131
1234
  if (this._traceAPICalls)
1132
1235
  console.log(`HTTP//request ${request.method} ${request.url}${safeCallData ? " " + safeCallData : ""}`);
1133
- this._notifyObservers((observer) => { observer.onHTTPCall && observer.onHTTPCall(request, safeCallData); });
1236
+ this._notifyObservers((observer) => observer.onHTTPCall && observer.onHTTPCall(request, safeCallData) );
1134
1237
  const body = await this._transport(request);
1135
1238
 
1136
1239
  const safeCallResponse = Util.trim(body);
1137
1240
  if (this._traceAPICalls)
1138
1241
  console.log(`HTTP//response${safeCallResponse ? " " + safeCallResponse : ""}`);
1139
- this._notifyObservers((observer) => { observer.onHTTPCallSuccess && observer.onHTTPCallSuccess(request, safeCallResponse); });
1242
+ this._notifyObservers((observer) => observer.onHTTPCallSuccess && observer.onHTTPCallSuccess(request, safeCallResponse) );
1140
1243
  return body;
1141
1244
  } catch(err) {
1142
1245
  if (this._traceAPICalls)
1143
1246
  console.log("HTTP//failure", err);
1144
- this._notifyObservers((observer) => { observer.onHTTPCallFailure && observer.onHTTPCallFailure(request, err); });
1247
+ this._notifyObservers((observer) => observer.onHTTPCallFailure && observer.onHTTPCallFailure(request, err) );
1145
1248
  throw makeCampaignException({ request:request, reqponse:err.response }, err);
1146
1249
  }
1147
1250
  }
@@ -1158,7 +1261,7 @@ class Client {
1158
1261
  };
1159
1262
  const body = await this._makeHttpCall(request);
1160
1263
  const xml = DomUtil.parse(body);
1161
- const result = this.toRepresentation(xml);
1264
+ const result = this._toRepresentation(xml);
1162
1265
  return result;
1163
1266
  }
1164
1267
 
@@ -1186,7 +1289,7 @@ class Client {
1186
1289
  const timestamp = lines[1].trim();
1187
1290
  if (timestamp != "") root.setAttribute("timestamp", timestamp);
1188
1291
  }
1189
- const result = this.toRepresentation(doc);
1292
+ const result = this._toRepresentation(doc);
1190
1293
  return result;
1191
1294
  }
1192
1295
 
@@ -1211,8 +1314,8 @@ class Client {
1211
1314
  var status = lines[0].trim();
1212
1315
  if (status != "") root.setAttribute("status", status);
1213
1316
 
1214
- var rtCount = undefined;
1215
- var threshold = undefined;
1317
+ var rtCount;
1318
+ var threshold;
1216
1319
  if (status == "Error") {
1217
1320
  const error = lines.length > 1 ? lines[1] : "";
1218
1321
  root.setAttribute("error", error);
@@ -1241,10 +1344,9 @@ class Client {
1241
1344
  }
1242
1345
  if (rtCount !== undefined && rtCount.trim() != "") root.setAttribute("eventQueueSize", rtCount);
1243
1346
  if (threshold !== undefined && rtCount.trim() != "") root.setAttribute("eventQueueMaxSize", threshold);
1244
- const result = this.toRepresentation(doc);
1347
+ const result = this._toRepresentation(doc);
1245
1348
  return result;
1246
1349
  }
1247
-
1248
1350
  }
1249
1351
 
1250
1352
 
@@ -1253,3 +1355,5 @@ Client.CampaignException = CampaignException;
1253
1355
  exports.Client = Client;
1254
1356
  exports.Credentials = Credentials;
1255
1357
  exports.ConnectionParameters = ConnectionParameters;
1358
+
1359
+ })();