@adobe/acc-js-sdk 1.1.3 → 1.1.4

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/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ This is a node.js SDK for Campaign API. It exposes the Campaign API exactly like
5
5
 
6
6
  # Changelog
7
7
 
8
+ ## Version 1.1.4
9
+ _2022/06/xx_
10
+
11
+ * Added `application.version` which returns the server version in the format major.minor.servicePack (ex: 8.2.10)
12
+ * Added the ability to push down parameters to the SOAP and transport layers. See the pushDown section of the readme file.
13
+ * The pushDown mechanism can be used to simply overwrite the request timeout, either globally or at the method level
14
+ * Publicly export the HttpError class so that custom transports can be written more safely. A failure during transport should return an HttpError object
15
+ * By default, the SOAP method name is now added in the URLs for better troubleshooting
16
+
8
17
  ## Version 1.1.3
9
18
  _2022/05/30_
10
19
 
@@ -15,6 +24,10 @@ _2022/05/30_
15
24
  * Document how to set the password of an external account
16
25
  * By default, SDK will send additional HTTP headers to help troubleshooting and usage tracking
17
26
  * Add the ability to pass extra HTTP headers to API calls, either globally (to all HTTP headers), or locally, i.e. for a specific method
27
+ * Remove .vscode folder from the sources
28
+ * Example for xtkBuilder.installPackage API
29
+ * For APIs which have parameters of type DOMElement and which are called using XML, support passing either a DOMElement or a DOMDocument
30
+
18
31
 
19
32
  ## Version 1.1.2
20
33
  _2022/03/22_
package/README.md CHANGED
@@ -133,6 +133,8 @@ charset|UTF-8|The charset encoding used for http requests. In version 1.1.1 and
133
133
  extraHttpHeaders|[string]:string|An optional dictionary (key/value pairs) of extra HTTP headers to pass to all API calls.
134
134
  clientApp|string|An optional string describing the name and version of the SDK client application. It will be passed to the server in the ACC-SDK-Client-App HTTP header
135
135
  noSDKHeaders|boolean|Can be set to disable passing ACC-SDK-* HTTP headers to the server
136
+ noMethodInURL|boolean|Can be set to true to remove the method name from the URL
137
+ timeout|number|Can be used to set the APIs call timeout (in ms)
136
138
  ```js
137
139
  const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(
138
140
  "https://myInstance.campaign.adobe.com",
@@ -189,8 +191,8 @@ If you want to use the SDK client-side in a web page returned by Campaign, you c
189
191
  For this scenario, the `ofSecurityToken` function can be used. Pass it a security token (usually available as document.__securitytoken), and the SDK will let the browser handle the session token (cookie) for you.
190
192
 
191
193
  ```html
192
- <script src="acc-sdk.js"></script>
193
- <script>
194
+ <script src="acc-sdk.js"></script>
195
+ <script>
194
196
  (async () => {
195
197
  try {
196
198
  const sdk = document.accSDK;
@@ -204,8 +206,8 @@ For this scenario, the `ofSecurityToken` function can be used. Pass it a securit
204
206
  console.error(ex);
205
207
  }
206
208
  })();
207
- </script>
208
- </body>
209
+ </script>
210
+ </body>
209
211
  </html>
210
212
  ```
211
213
 
@@ -320,7 +322,8 @@ The Simple JSON format works like this:
320
322
 
321
323
  The XML root element tag is determined by the SDK as it's generating the XML, usually from the current schema name.
322
324
 
323
- * XML: `<root/>`
325
+ * XML: `<root/>
326
+ `
324
327
  * JSON: `{}`
325
328
 
326
329
  XML attributes are mapped to JSON attributes with the same name, whose litteral value can be a string, number, or boolean. There's no "@" sign in the JSON attribute name.
@@ -357,7 +360,9 @@ Text of a child element
357
360
  * Alternative JSON: `{ item: { $: "Hello" } }`
358
361
 
359
362
  If an element contains both text, and children, you need to use the alternative `$` syntax
360
- * XML: `<root><item>Hello<child id="1"/></item></root>`
363
+ * XML: `<root><item>Hello<child id="1"/>
364
+ </item>
365
+ </root>`
361
366
  * JSON: `{ item: { $: "Hello", child: { id:1 } }`
362
367
 
363
368
 
@@ -510,8 +515,8 @@ const DomUtil = client.DomUtil;
510
515
  Create DOM from XML string:
511
516
  ```js
512
517
  const doc = DomUtil.parse(`<root>
513
- <one/>
514
- </root>`);
518
+ <one/>
519
+ </root>`);
515
520
  ```
516
521
 
517
522
  Writes a DOM document or element as a string:
@@ -582,12 +587,12 @@ const json = DomUtil.toJSON(documentOrElement, "BadgerFish");
582
587
  Many Campaign APIs take arguments which are DOM documents or DOM elements. For example, the nms:delivery#DeployTriggerMessages first argument is a DOMElement which is supposed to be a `<where>` clause used as a condition to select Message Center deliveries to publish.
583
588
 
584
589
  ```xml
585
- <method name="DeployTriggerMessages" static="true">
586
- <parameters>
587
- <param inout="in" name="deliveries" type="DOMElement"/>
588
- <param inout="in" name="localPublish" type="boolean"/>
589
- </parameters>
590
- </method>
590
+ <method name="DeployTriggerMessages" static="true">
591
+ <parameters>
592
+ <param inout="in" name="deliveries" type="DOMElement"/>
593
+ <param inout="in" name="localPublish" type="boolean"/>
594
+ </parameters>
595
+ </method>
591
596
  ```
592
597
 
593
598
  For example, one would want to use the following condition to republish a particular delivery
@@ -603,7 +608,7 @@ For example, one would want to use the following condition to republish a partic
603
608
  The JSON object corresponds to the following XML
604
609
  ```xml
605
610
  <where>
606
- <condition expr="@internalName='DM23'"/>
611
+ <condition expr="@internalName='DM23'"/>
607
612
  </where>
608
613
  ```
609
614
 
@@ -757,6 +762,49 @@ const query = client.NLWS
757
762
  await query.executeQuery();
758
763
  ```
759
764
 
765
+ ## Timeouts
766
+
767
+ By default, the SDK has a timeout of 5s when running in a node.js environment, and uses the browser defaults when run inside a browser (using the fetch API).
768
+
769
+ It is possible to overwrite the transport layer (see `The Transport Protocol` and use your own code to make and configure HTTP requests) to tune the timeout value. It is a bit cumbersome though.
770
+
771
+ Instead, you can use the `timeout` parameter, and set it either globally, as a connection parameter, or even at the API call level but using the `PushDown` mechanism described below.
772
+
773
+ Sets a timeout of 10s gloally
774
+ ```js
775
+ const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(
776
+ "https://myInstance.campaign.adobe.com",
777
+ "admin", "admin",
778
+ { timeout: 10000 });
779
+ ```
780
+
781
+ Override the timeout to 1 min for a particular API call
782
+ ```js
783
+ NLWS.xml.pushDown({ timeout: 60000 }).xtkBuilder.installPackage(dom);
784
+ ```
785
+
786
+ ## Pushdown mechanism
787
+ The Pushdown mechanism can be used to push down variables to the transport layer. A common use case it to pass a custom timeout value down to the transport layer.
788
+
789
+ The pushed down parameters are passed as a second parameter to the transport function. This parameter will contain all the connection parameters as well as any parameter that you can push down at the API call level. API call pushdowns can override default pushdowns.
790
+
791
+ Any key/value pairs can be pushed down. This example pushes down the timeout and foo variables to the transport layer.
792
+ ```js
793
+ NLWS.xml.pushDown({ timeout: 60000, foo: 'bar' }).xtkBuilder.installPackage(dom);
794
+ ```
795
+
796
+ ## Troubleshooting
797
+ In the version 1.1.4 of the SDK, we are automatically adding the SOAP method name in the URL in order to simplify troubleshooting. Normally, all SOAP method calls are make to the soaprouter.jsp endpoint, which makes it difficult to understand which actual API call is being made.
798
+ In fact the SOAP call name is available via the SOAPAction HTTP header, but it's usually not immediatelly visible.
799
+
800
+ The SOAP calls URLs are now formed like this: `http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef#ExecuteQuery` where the SOAP method name is added as a query parameter. Campaign server ignores this parameter.
801
+
802
+ This can be disabled using the `noMethodInURL` connection parameter
803
+
804
+ const connectionParameters = sdk.ConnectionParameters.ofUserAndPassword(
805
+ "https://myInstance.campaign.adobe.com",
806
+ "admin", "admin",
807
+ { noMethodInURL: true });
760
808
 
761
809
 
762
810
  # Samples
@@ -982,12 +1030,16 @@ The transport protocol defines
982
1030
  - What is the corresponding response
983
1031
  - How errors are handled
984
1032
 
985
- The transport protocol exports a single asynchronous function `request` which takes a `Request` literal object with the following attributes. Note that it matches axios requests.
1033
+ The transport protocol exports a single asynchronous function `request` which takes two parameters.
1034
+
1035
+ The first parameter is the request object with the following attributes. Note that it matches axios requests.
986
1036
  * `method` is the HTTP verb
987
1037
  * `url` is the URL to call
988
1038
  * `headers` is an object containing key value pairs with http headers and their values
989
1039
  * `data` is the request payload
990
1040
 
1041
+ The second parameter is an set of additional parameters that have been pushed down to the transport layer (see the `Pushdown` paragraph for more details). In particular, the `timeout` parameter should be honored by the transport layer.
1042
+
991
1043
  If the request is successful, a promise is returned with the result payload, as a string.
992
1044
 
993
1045
  If the request fails, the promise is rejected with an error object with class `HttpError`, a litteral with the following attributes:
@@ -995,7 +1047,7 @@ If the request fails, the promise is rejected with an error object with class `H
995
1047
  * `statusText` is the HTTP status text coming with the error
996
1048
  * `data` is the response data, if any
997
1049
 
998
- For proper error handling by the ACC SDK, it's important that the actual class of returned objects is names "HttpError"
1050
+ For proper error handling by the ACC SDK, it's important that the actual class of returned objects is named "HttpError"
999
1051
 
1000
1052
  The transport can be overriden by using the `client.setTransport` call and passing it a transport function, i.e. an async function which
1001
1053
  * Takes a `Request` object litteral as a parameter
@@ -1052,14 +1104,14 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
1052
1104
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
1053
1105
  xmlns:ns="http://xml.apache.org/xml-soap">
1054
1106
  <SOAP-ENV:Header>
1055
- <Cookie>__sessiontoken=***</Cookie>
1056
- <X-Security-Token>***</X-Security-Token>
1107
+ <Cookie>__sessiontoken=***</Cookie>
1108
+ <X-Security-Token>***</X-Security-Token>
1057
1109
  </SOAP-ENV:Header>
1058
1110
  <SOAP-ENV:Body>
1059
- <m:GetOption xmlns:m="urn:xtk:session" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
1060
- <sessiontoken xsi:type="xsd:string">***</sessiontoken>
1061
- <name xsi:type="xsd:string">XtkDatabaseId</name>
1062
- </m:GetOption>
1111
+ <m:GetOption xmlns:m="urn:xtk:session" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
1112
+ <sessiontoken xsi:type="xsd:string">***</sessiontoken>
1113
+ <name xsi:type="xsd:string">XtkDatabaseId</name>
1114
+ </m:GetOption>
1063
1115
  </SOAP-ENV:Body>
1064
1116
  </SOAP-ENV:Envelope>
1065
1117
 
@@ -1069,10 +1121,10 @@ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
1069
1121
  xmlns:ns='urn:xtk:session'
1070
1122
  xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
1071
1123
  <SOAP-ENV:Body>
1072
- <GetOptionResponse xmlns='urn:xtk:session' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1073
- <pstrValue xsi:type='xsd:string'>uFE80000000000000F1FA913DD7CC7C4804BA419F</pstrValue>
1074
- <pbtType xsi:type='xsd:byte'>6</pbtType>
1075
- </GetOptionResponse>
1124
+ <GetOptionResponse xmlns='urn:xtk:session' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
1125
+ <pstrValue xsi:type='xsd:string'>uFE80000000000000F1FA913DD7CC7C4804BA419F</pstrValue>
1126
+ <pbtType xsi:type='xsd:byte'>6</pbtType>
1127
+ </GetOptionResponse>
1076
1128
  </SOAP-ENV:Body>
1077
1129
  </SOAP-ENV:Envelope>
1078
1130
  `````
@@ -1461,6 +1513,7 @@ The `application` object can be obtained from a client, and will mimmic the Camp
1461
1513
  | Attribute/Method | Description |
1462
1514
  |---|---|
1463
1515
  | **buildNumber** | The server build number
1516
+ | **version** | In SDK version 1.1.4 and above, returns the server version formatted as major.minor.servicePack (ex: 8.2.10)
1464
1517
  | **instanceName** | The name of the Campaign instance
1465
1518
  | **operator** | Information about the current operator (i.e. logged user), of class `CurrentLogin`
1466
1519
  | **packages** | List of installed packages, as an array of strings
package/compile.js CHANGED
@@ -38,8 +38,8 @@ var resources = [
38
38
  { name: "./optionCache.js" },
39
39
  { name: "./soap.js" },
40
40
  { name: "./crypto.js" },
41
- { name: "./testUtil.js" },
42
41
  { name: "./application.js" },
42
+ { name: "./testUtil.js" },
43
43
  { name: "./client.js" },
44
44
  { name: "./index.js" },
45
45
  ];
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@adobe/acc-js-sdk",
9
- "version": "1.1.3",
9
+ "version": "1.1.4",
10
10
  "license": "ISC",
11
11
  "dependencies": {
12
12
  "axios": "^0.25.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "ACC Javascript SDK",
5
5
  "main": "src/index.js",
6
6
  "homepage": "https://github.com/adobe/acc-js-sdk#readme",
@@ -0,0 +1,60 @@
1
+ /*
2
+ Copyright 2020 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+ const { DomUtil } = require('../src/domUtil.js');
13
+ const sdk = require('../src/index.js');
14
+ const utils = require("./utils.js");
15
+
16
+
17
+ /**
18
+ * This sample illustrates how to generate and import packages
19
+ */
20
+
21
+ ( async () => {
22
+
23
+ await utils.sample({
24
+ title: "Testing generating and importing packages",
25
+ labels: [ "Basics", "Packages", "xtk:builder", "InstallPackage" ],
26
+ description: `The xtkBuilder.installPackage() can be used to import packages`,
27
+ code: async() => {
28
+ return await utils.logon(async (client, NLWS) => {
29
+ console.log(`Generating package with an option named AccJsSdk`);
30
+ const doc = sdk.DomUtil.newDocument('pkgDesc');
31
+ const package = doc.createElement('package');
32
+ doc.documentElement.appendChild(package);
33
+ package.setAttribute('namespace', 'cus');
34
+ package.setAttribute('name', 'sdk');
35
+ package.setAttribute('buildNumber', '*');
36
+ package.setAttribute('buildVersion', '*');
37
+ package.setAttribute('label', 'Test package for ACC JS SDK');
38
+ package.setAttribute('vendor', 'acc-js-sdk');
39
+
40
+ const entities = doc.createElement('entities');
41
+ package.appendChild(entities);
42
+ entities.setAttribute('schema', 'xtk:option');
43
+
44
+ const option = doc.createElement('option');
45
+ option.setAttribute('name', 'AccJsSdk');
46
+ option.setAttribute('dataType', '6');
47
+ const version = client.application.version;
48
+ option.setAttribute('stringValue', JSON.stringify(version));
49
+ entities.appendChild(option);
50
+
51
+ // Install package. The package is in XML format and we set the timeout to 5 mins to prevent any issues
52
+ console.log(`Installing package`, DomUtil.toXMLString(doc));
53
+ await NLWS.xml.pushDown({ timeout: 5*60*1000 }).xtkBuilder.installPackage(doc);
54
+ console.log(`Package installed`);
55
+ });
56
+ }
57
+ });
58
+
59
+ })();
60
+
@@ -1207,23 +1207,30 @@ class Application {
1207
1207
  * The server build number
1208
1208
  * @type {string}
1209
1209
  */
1210
- this.buildNumber = EntityAccessor.getAttributeAsString(serverInfo, "buildNumber");
1210
+ this.buildNumber = EntityAccessor.getAttributeAsString(serverInfo, "buildNumber");
1211
+ /**
1212
+ * The server version, formatted as major.minor.servicePack (ex: 8.2.10)
1213
+ * @type {string}
1214
+ */
1215
+ this.version = EntityAccessor.getAttributeAsString(serverInfo, "majNumber") + "." +
1216
+ EntityAccessor.getAttributeAsString(serverInfo, "minNumber") + "." +
1217
+ EntityAccessor.getAttributeAsString(serverInfo, "servicePack");
1211
1218
  /**
1212
1219
  * The Campaign instance name
1213
1220
  * @type {string}
1214
1221
  */
1215
- this.instanceName = EntityAccessor.getAttributeAsString(serverInfo, "instanceName");
1222
+ this.instanceName = EntityAccessor.getAttributeAsString(serverInfo, "instanceName");
1216
1223
  const userInfo = EntityAccessor.getElement(info, "userInfo");
1217
1224
  /**
1218
1225
  * The logged operator
1219
1226
  * @type {Campaign.CurrentLogin}
1220
1227
  */
1221
- this.operator = new CurrentLogin(userInfo);
1228
+ this.operator = new CurrentLogin(userInfo);
1222
1229
  /**
1223
1230
  * The list of installed packages
1224
1231
  * @type {string[]}
1225
1232
  */
1226
- this.packages = [];
1233
+ this.packages = [];
1227
1234
  for (var p of EntityAccessor.getChildElements(userInfo, "installed-package")) {
1228
1235
  this.packages.push(`${EntityAccessor.getAttributeAsString(p, "namespace")}:${EntityAccessor.getAttributeAsString(p, "name")}`);
1229
1236
  }
package/src/client.js CHANGED
@@ -105,13 +105,13 @@ const xtkObjectHandler = {
105
105
  * @private
106
106
  * @memberof Campaign
107
107
  */
108
- const clientHandler = (representation, headers) => {
108
+ const clientHandler = (representation, headers, pushDownOptions) => {
109
109
  return {
110
110
  get: function(client, namespace) {
111
111
 
112
112
  // Force XML or JSON representation (NLWS.xml or NLWS.json)
113
- if (namespace == "xml") return new Proxy(client, clientHandler("xml", headers));
114
- if (namespace == "json") return new Proxy(client, clientHandler("SimpleJson", headers));
113
+ if (namespace == "xml") return new Proxy(client, clientHandler("xml", headers, pushDownOptions));
114
+ if (namespace == "json") return new Proxy(client, clientHandler("SimpleJson", headers, pushDownOptions));
115
115
 
116
116
  // Override HTTP headers (NLWS.headers({...}))
117
117
  // Unlike NLWS.xml or NLWS.json, NLWS.headers returns a function. This function takes key/value
@@ -123,16 +123,30 @@ const clientHandler = (representation, headers) => {
123
123
  const newHeaders = {};
124
124
  if (headers) for (let h in headers) newHeaders[h] = headers[h];
125
125
  if (methodHeaders) for (let h in methodHeaders) newHeaders[h] = methodHeaders[h];
126
- return new Proxy(client, clientHandler(representation, newHeaders));
126
+ return new Proxy(client, clientHandler(representation, newHeaders, pushDownOptions));
127
+ };
128
+
129
+ // Pushes down addition options to the SOAP and transport layers
130
+ if (namespace == "pushDown") return (methodPushDownOptions) => {
131
+ // Build of copy of the pushDownOptions in order to accomodate
132
+ // chained calls, such as NLWS.pushDown(...).pushDown(...)
133
+ const newPushDownOptions = {};
134
+ if (pushDownOptions) for (let h in pushDownOptions) newPushDownOptions[h] = pushDownOptions[h];
135
+ if (methodPushDownOptions) for (let h in methodPushDownOptions) newPushDownOptions[h] = methodPushDownOptions[h];
136
+ return new Proxy(client, clientHandler(representation, headers, newPushDownOptions));
127
137
  };
128
138
 
129
139
  return new Proxy({ client:client, namespace:namespace}, {
130
140
  get: function(callContext, methodName) {
131
141
  callContext.representation = representation;
132
142
  callContext.headers = callContext.headers || client._connectionParameters._options.extraHttpHeaders;
143
+ callContext.pushDownOptions = {};
133
144
  if (headers) {
134
145
  for (let h in headers) callContext.headers[h] = headers[h];
135
146
  }
147
+ if (pushDownOptions) {
148
+ for (let h in pushDownOptions) callContext.pushDownOptions[h] = pushDownOptions[h];
149
+ }
136
150
 
137
151
  if (methodName == ".") return callContext;
138
152
 
@@ -270,6 +284,8 @@ class Credentials {
270
284
  * @property {{ name:string, value:string}} extraHttpHeaders - optional key/value pair of HTTP header (will override any other headers)
271
285
  * @property {string} clientApp - optional name/version of the application client of the SDK. This will be passed in HTTP headers for troubleshooting
272
286
  * @property {boolean} noSDKHeaders - set to disable "ACC-SDK" HTTP headers
287
+ * @property {boolean} noMethodInURL - Can be set to true to remove the method name from the URL
288
+ * @property {number} timeout - Can be set to change the HTTP call timeout. Value is passed in ms.
273
289
  * @memberOf Campaign
274
290
  */
275
291
 
@@ -291,7 +307,7 @@ class ConnectionParameters {
291
307
  constructor(endpoint, credentials, options) {
292
308
  // this._options will be populated with the data from "options" and with
293
309
  // default values. But the "options" parameter will not be modified
294
- this._options = {};
310
+ this._options = Object.assign({}, options);
295
311
 
296
312
  // Default value
297
313
  if (options === undefined || options === null)
@@ -340,6 +356,7 @@ class ConnectionParameters {
340
356
  }
341
357
  this._options.clientApp = options.clientApp;
342
358
  this._options.noSDKHeaders = !!options.noSDKHeaders;
359
+ this._options.noMethodInURL = !!options.noMethodInURL;
343
360
  }
344
361
 
345
362
  /**
@@ -716,10 +733,11 @@ class Client {
716
733
  * @return {SOAP.SoapMethodCall} a SoapMethodCall which have been initialized with security tokens... and to which the method
717
734
  * parameters should be set
718
735
  */
719
- _prepareSoapCall(urn, method, internal, extraHttpHeaders) {
736
+ _prepareSoapCall(urn, method, internal, extraHttpHeaders, pushDownOptions) {
720
737
  const soapCall = new SoapMethodCall(this._transport, urn, method,
721
738
  this._sessionToken, this._securityToken,
722
- this._getUserAgentString(), this._connectionParameters._options.charset,
739
+ this._getUserAgentString(),
740
+ Object.assign({}, this._connectionParameters._options, pushDownOptions),
723
741
  extraHttpHeaders);
724
742
  soapCall.internal = !!internal;
725
743
  return soapCall;
@@ -1162,7 +1180,7 @@ class Client {
1162
1180
  // console.log(method.toXMLString());
1163
1181
 
1164
1182
  var urn = that._methodCache.getSoapUrn(schemaId, methodName);
1165
- var soapCall = that._prepareSoapCall(urn, methodName, false, callContext.headers);
1183
+ var soapCall = that._prepareSoapCall(urn, methodName, false, callContext.headers, callContext.pushDownOptions);
1166
1184
 
1167
1185
  // If method is called with one parameter which is a function, then we assume it's a hook: the function will return
1168
1186
  // the actual list of parameters
@@ -1234,7 +1252,7 @@ class Client {
1234
1252
  if (type == "DOMDocument")
1235
1253
  soapCall.writeDocument(paramName, xmlValue);
1236
1254
  else
1237
- soapCall.writeElement(paramName, xmlValue.documentElement);
1255
+ soapCall.writeElement(paramName, xmlValue);
1238
1256
  }
1239
1257
  else
1240
1258
  throw CampaignException.BAD_SOAP_PARAMETER(soapCall, paramName, paramValue, `Unsupported parameter type '${type}' for parameter '${paramName}' of method '${methodName}' of schema '${schemaId}`);
package/src/index.js CHANGED
@@ -23,7 +23,8 @@ const DomUtil = require('./domUtil.js').DomUtil;
23
23
  const XtkCaster = require('./xtkCaster.js').XtkCaster;
24
24
  const { Client, Credentials, ConnectionParameters } = require('./client.js');
25
25
  const request = require('./transport.js').request;
26
- const { TestUtil } = require('./testUtil');
26
+ const { TestUtil } = require('./testUtil.js');
27
+ const { HttpError } = require('./transport.js');
27
28
 
28
29
  /**
29
30
  * Get/Set the transport function (defaults to Axios). This function is used for testing / mocking the transport layer.
@@ -210,6 +211,7 @@ sdk.XtkCaster = XtkCaster;
210
211
  sdk.Credentials = Credentials;
211
212
  sdk.DomUtil = DomUtil;
212
213
  sdk.ConnectionParameters = ConnectionParameters;
214
+ sdk.HttpError = HttpError;
213
215
 
214
216
  // Public exports
215
217
  module.exports = sdk;
package/src/soap.js CHANGED
@@ -78,14 +78,15 @@ const NS_XSD = "http://www.w3.org/2001/XMLSchema";
78
78
  * @param {string} sessionToken Campaign session token
79
79
  * @param {string} securityToken Campaign security token
80
80
  * @param {string} userAgentString The user agent string to use for HTTP requests
81
- * @param {string} charset The charset encoding used for http requests, usually UTF-8
81
+ * @param {string} pushDownOptions Options to push down to the request (comes from connectionParameters._options)
82
82
  * @param {{ name:string, value:string}} extraHttpHeaders key/value pair of HTTP header (will override any other headers)
83
83
  * @memberof SOAP
84
84
  */
85
85
  class SoapMethodCall {
86
86
 
87
- constructor(transport, urn, methodName, sessionToken, securityToken, userAgentString, charset, extraHttpHeaders) {
87
+ constructor(transport, urn, methodName, sessionToken, securityToken, userAgentString, pushDownOptions, extraHttpHeaders) {
88
88
  this.request = undefined; // The HTTP request (object litteral passed to the transport layer)
89
+ this.requestOptions = undefined;
89
90
  this.response = undefined; // The HTTP response object (in case of success)
90
91
 
91
92
  // Current URN and method (for error reporting)
@@ -102,7 +103,8 @@ class SoapMethodCall {
102
103
  this._sessionToken = sessionToken || "";
103
104
  this._securityToken = securityToken || "";
104
105
  this._userAgentString = userAgentString;
105
- this._charset = charset || "";
106
+ this._pushDownOptions = pushDownOptions || {};
107
+ this._charset = this._pushDownOptions.charset || '';
106
108
  this._extraHttpHeaders = extraHttpHeaders || {};
107
109
 
108
110
  // THe SOAP call being built
@@ -289,6 +291,7 @@ class SoapMethodCall {
289
291
  writeElement(tag, element) {
290
292
  const node = this._addNode(tag, "ns:Element", null, SOAP_ENCODING_XML);
291
293
  if (element !== null && element !== undefined) {
294
+ if (element.nodeType === 9) element = element.documentElement;
292
295
  const child = this._doc.importNode(element, true);
293
296
  node.appendChild(child);
294
297
  }
@@ -517,7 +520,7 @@ class SoapMethodCall {
517
520
  * @param {string} url is the Campaign SOAP endpoint (soaprouter.jsp)
518
521
  * @returns {Object} an options object describing the HTTP request, with cookies, headers and body
519
522
  */
520
- _createHTTPRequest(url) {
523
+ _createHTTPRequest(url, requestOptions) {
521
524
 
522
525
  const headers = {
523
526
  'Content-type': `application/soap+xml${this._charset ? ";charset=" + this._charset : ""}`,
@@ -533,23 +536,24 @@ class SoapMethodCall {
533
536
  if (this.internal) headers["ACC-SDK-Call-Internal"] = "1";
534
537
  }
535
538
 
536
- const options = {
539
+ const request = {
537
540
  url: url,
538
541
  method: 'POST',
539
542
  headers: headers,
540
543
  data: DomUtil.toXMLString(this._doc)
541
544
  };
542
545
  if (this._sessionToken)
543
- options.headers.Cookie = '__sessiontoken=' + this._sessionToken;
546
+ request.headers.Cookie = '__sessiontoken=' + this._sessionToken;
544
547
  if (this._userAgentString)
545
- options.headers['User-Agent'] = this._userAgentString;
548
+ request.headers['User-Agent'] = this._userAgentString;
546
549
 
547
550
  // Override http headers with custom headers
548
551
  for (let h in this._extraHttpHeaders) {
549
- options.headers[h] = this._extraHttpHeaders[h];
552
+ request.headers[h] = this._extraHttpHeaders[h];
550
553
  }
551
554
 
552
- return options;
555
+ const extraOptions = Object.assign({}, this._pushDownOptions, requestOptions);
556
+ return [ request, extraOptions ];
553
557
  }
554
558
 
555
559
  /**
@@ -595,9 +599,11 @@ class SoapMethodCall {
595
599
  sessionTokenElem.textContent = this._sessionToken;
596
600
  this._method.prepend(sessionTokenElem);
597
601
  }
598
- const options = this._createHTTPRequest(url);
602
+ const noMethodInURL = !!this._pushDownOptions.noMethodInURL;
603
+ const actualUrl = noMethodInURL ? url : `${url}?${this.urn}#${this.methodName}`;
604
+
599
605
  // Prepare request and empty response objects
600
- this.request = options;
606
+ [this.request, this.requestOptions] = this._createHTTPRequest(actualUrl);
601
607
  this.response = undefined;
602
608
  }
603
609
 
@@ -610,7 +616,7 @@ class SoapMethodCall {
610
616
  */
611
617
  async execute() {
612
618
  const that = this;
613
- const promise = this._transport(this.request);
619
+ const promise = this._transport(this.request, this.requestOptions);
614
620
  return promise.then(function(body) {
615
621
  if (body.indexOf(`XSV-350008`) != -1)
616
622
  throw CampaignException.SESSION_EXPIRED();
package/src/testUtil.js CHANGED
@@ -1,4 +1,4 @@
1
- const { DomUtil } = require("./domUtil");
1
+ const { DomUtil } = require("./domUtil.js");
2
2
 
3
3
  /*
4
4
  Copyright 2022 Adobe. All rights reserved.
@@ -14,7 +14,7 @@ governing permissions and limitations under the License.
14
14
  (function() {
15
15
  "use strict";
16
16
 
17
- const { newSchema } = require("./application");
17
+ const { newSchema } = require("./application.js");
18
18
 
19
19
  /**********************************************************************************
20
20
  *
package/src/transport.js CHANGED
@@ -14,13 +14,27 @@ governing permissions and limitations under the License.
14
14
 
15
15
  const { Util } = require('./util.js');
16
16
 
17
+ /**
18
+ * @memberof Utils
19
+ * @class
20
+ * @constructor
21
+ */
17
22
  class HttpError {
23
+ /* Encapsulates an error from an HTTP call
24
+ * @param {string|number} statusCode - The Http status code
25
+ * @param {string?} statusText - The Http status text corresponding to the error code
26
+ * @param {any?} data - The payload of the HTTP response, which usually contains details about the error
27
+ */
18
28
  constructor(statusCode, statusText, data) {
19
29
  this.statusCode = statusCode;
20
30
  this.statusText = statusText || "";
21
31
  this.data = data;
22
32
  }
23
33
 
34
+ /**
35
+ * Returns a short description of the error
36
+ * @returns {string} a short descrption of the error
37
+ */
24
38
  toString() {
25
39
  return `${this.statusCode}${this.statusText ? " " + this.statusText : ""}`;
26
40
  }
@@ -52,13 +66,14 @@ if (!Util.isBrowser()) {
52
66
  * - request
53
67
  */
54
68
 
55
- const request = (options) => {
69
+ const request = (options, requestOptions) => {
70
+ requestOptions = requestOptions || {};
56
71
  const request = {
57
72
  method: options.method || "GET",
58
73
  url: options.url,
59
74
  headers: options.headers,
60
75
  data: options.data,
61
- timeout: 5000,
76
+ timeout: requestOptions.timeout || 5000,
62
77
  };
63
78
  return axios(request)
64
79
  .then((response) => {
@@ -2108,6 +2108,7 @@ describe('Application', () => {
2108
2108
  const application = client.application;
2109
2109
  expect(application).not.toBeNull();
2110
2110
  expect(application.buildNumber).toBeUndefined();
2111
+ expect(application.version).toBeUndefined();
2111
2112
  expect(application.instanceName).toBeUndefined();
2112
2113
  expect(application.operator).toBeUndefined();
2113
2114
  expect(application.package).toBeUndefined();
@@ -2145,4 +2146,14 @@ describe('Application', () => {
2145
2146
  expect(schema2).toBeNull();
2146
2147
  });
2147
2148
  });
2149
+
2150
+ describe("Version", () => {
2151
+ it("Should get proper version information", async () => {
2152
+ const client = await Mock.makeClient();
2153
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2154
+ await client.NLWS.xtkSession.logon();
2155
+ expect(client.application.buildNumber).toBe('9219');
2156
+ expect(client.application.version).toBe('6.7.0');
2157
+ })
2158
+ })
2148
2159
  });
@@ -25,7 +25,6 @@ const { HttpError } = require('../src/transport.js');
25
25
  const { Cipher } = require('../src/crypto.js');
26
26
  const { EntityAccessor } = require('../src/entityAccessor.js');
27
27
 
28
-
29
28
  describe('ACC Client', function () {
30
29
 
31
30
  describe('Init', function () {
@@ -2281,17 +2280,19 @@ describe('ACC Client', function () {
2281
2280
  });
2282
2281
 
2283
2282
  it("Should ignore protocol for local storage root key", async () => {
2283
+ const version = sdk.getSDKVersion().version; // "${version}" or similar
2284
+
2284
2285
  var connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", {});
2285
2286
  var client = await sdk.init(connectionParameters);
2286
- expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.3.acc-sdk:8080.cache.OptionCache$");
2287
+ expect(client._optionCache._storage._rootKey).toBe(`acc.js.sdk.${version}.acc-sdk:8080.cache.OptionCache$`);
2287
2288
 
2288
2289
  connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("https://acc-sdk:8080", "admin", "admin", {});
2289
2290
  client = await sdk.init(connectionParameters);
2290
- expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.3.acc-sdk:8080.cache.OptionCache$");
2291
+ expect(client._optionCache._storage._rootKey).toBe(`acc.js.sdk.${version}.acc-sdk:8080.cache.OptionCache$`);
2291
2292
 
2292
2293
  connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("acc-sdk:8080", "admin", "admin", {});
2293
2294
  client = await sdk.init(connectionParameters);
2294
- expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.3.acc-sdk:8080.cache.OptionCache$");
2295
+ expect(client._optionCache._storage._rootKey).toBe(`acc.js.sdk.${version}.acc-sdk:8080.cache.OptionCache$`);
2295
2296
  })
2296
2297
 
2297
2298
  it("Should support no storage", async () => {
@@ -2803,4 +2804,85 @@ describe('ACC Client', function () {
2803
2804
  });
2804
2805
  });
2805
2806
  });
2807
+
2808
+ describe("Pushdown parameters", () => {
2809
+ it("Should push down custom parameters", async () => {
2810
+ const client = await Mock.makeClient();
2811
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2812
+ await client.NLWS.xtkSession.logon();
2813
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
2814
+ client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
2815
+ const queryDef = {
2816
+ "schema": "nms:extAccount",
2817
+ "operation": "select",
2818
+ "select": {
2819
+ "node": [
2820
+ { "expr": "@id" },
2821
+ { "expr": "@name" }
2822
+ ]
2823
+ }
2824
+ };
2825
+ // Pushing down the foo=bar attributes
2826
+ const query = client.NLWS.pushDown({'foo': 'bar'}).xtkQueryDef.create(queryDef);
2827
+ await query.executeQuery();
2828
+ const lastCall = client._transport.mock.calls[client._transport.mock.calls.length-1];
2829
+ expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef#ExecuteQuery");
2830
+ expect(lastCall[1].charset).toBe("UTF-8");
2831
+ expect(lastCall[1].foo).toBe("bar");
2832
+ });
2833
+
2834
+ it("Should push down custom parameters defined at the connection level", async () => {
2835
+ const client = await Mock.makeClient({ 'cnxDefault': 3, 'foo': 'foo' });
2836
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2837
+ await client.NLWS.xtkSession.logon();
2838
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
2839
+ client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
2840
+ const queryDef = {
2841
+ "schema": "nms:extAccount",
2842
+ "operation": "select",
2843
+ "select": {
2844
+ "node": [
2845
+ { "expr": "@id" },
2846
+ { "expr": "@name" }
2847
+ ]
2848
+ }
2849
+ };
2850
+ // Pushing down the foo=bar attributes (should overload the "foo" set in connecion parameters)
2851
+ const query = client.NLWS.pushDown({'foo': 'bar'}).xtkQueryDef.create(queryDef);
2852
+ await query.executeQuery();
2853
+ const lastCall = client._transport.mock.calls[client._transport.mock.calls.length-1];
2854
+ expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef#ExecuteQuery");
2855
+ expect(lastCall[1].charset).toBe("UTF-8");
2856
+ expect(lastCall[1].foo).toBe("bar");
2857
+ expect(lastCall[1].cnxDefault).toBe(3);
2858
+ });
2859
+
2860
+ it("Should chain push options", async () => {
2861
+ const client = await Mock.makeClient({ 'cnxDefault': 3, 'foo': 'foo' });
2862
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2863
+ await client.NLWS.xtkSession.logon();
2864
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
2865
+ client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
2866
+ const queryDef = {
2867
+ "schema": "nms:extAccount",
2868
+ "operation": "select",
2869
+ "select": {
2870
+ "node": [
2871
+ { "expr": "@id" },
2872
+ { "expr": "@name" }
2873
+ ]
2874
+ }
2875
+ };
2876
+ // Supports multiple calls to pushDown. each one overrides the previous in case of duplicate key
2877
+ // Also supports undefined
2878
+ const query = client.NLWS.pushDown({'foo': 'bar'}).pushDown().pushDown({'foo': 'fu', x: 2 }).xtkQueryDef.create(queryDef);
2879
+ await query.executeQuery();
2880
+ const lastCall = client._transport.mock.calls[client._transport.mock.calls.length-1];
2881
+ expect(lastCall[0].url).toBe("http://acc-sdk:8080/nl/jsp/soaprouter.jsp?xtk:queryDef#ExecuteQuery");
2882
+ expect(lastCall[1].charset).toBe("UTF-8");
2883
+ expect(lastCall[1].foo).toBe("fu");
2884
+ expect(lastCall[1].cnxDefault).toBe(3);
2885
+ expect(lastCall[1].x).toBe(2);
2886
+ });
2887
+ });
2806
2888
  });
package/test/soap.test.js CHANGED
@@ -25,8 +25,8 @@ const sdk = require('../src/index.js');
25
25
 
26
26
  const URL = "https://soap-test/nl/jsp/soaprouter.jsp";
27
27
 
28
- function makeSoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString, optionalCharset, charset, extraHttpHeaders) {
29
- const call = new SoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString, optionalCharset, charset, extraHttpHeaders);
28
+ function makeSoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString, pushDownOptions, extraHttpHeaders) {
29
+ const call = new SoapMethodCall(transport, urn, methodName, sessionToken, securityToken, userAgentString, pushDownOptions, extraHttpHeaders);
30
30
  return call;
31
31
  }
32
32
 
@@ -145,7 +145,7 @@ describe('SOAP', function() {
145
145
 
146
146
  it('Should build an mostly empty SOAP call', function() {
147
147
  const call = makeSoapMethodCall(undefined, "xtk:session", "Empty"); // no auth
148
- const request = call._createHTTPRequest(URL);
148
+ const [ request ] = call._createHTTPRequest(URL);
149
149
  assert.equal(request.url, URL);
150
150
  assert.equal(request.method, "POST");
151
151
  assert.equal(request.headers["Content-type"], "application/soap+xml");
@@ -161,7 +161,7 @@ describe('SOAP', function() {
161
161
 
162
162
  it('Should have set authentication tokens', function() {
163
163
  const call = makeSoapMethodCall(undefined, "xtk:session", "Empty", "$session$", "$security$");
164
- const request = call._createHTTPRequest(URL);
164
+ const [ request ] = call._createHTTPRequest(URL);
165
165
  assert.equal(request.headers["X-Security-Token"], "$security$", "Security token matches");
166
166
  assert.equal(request.headers["Cookie"], "__sessiontoken=$session$", "Session token matches");
167
167
  const env = DomUtil.parse(request.data).documentElement;
@@ -176,7 +176,7 @@ describe('SOAP', function() {
176
176
  const expected = [ "false", "false", "false", "true", "true", "true", "false", "true", "false"];
177
177
  for (var i=0; i<values.length; i++)
178
178
  call.writeBoolean(`p${i}`, values[i]);
179
- const request = call._createHTTPRequest(URL);
179
+ const [ request ] = call._createHTTPRequest(URL);
180
180
  const env = DomUtil.parse(request.data).documentElement;
181
181
  const body = hasChildElement(env, "SOAP-ENV:Body");
182
182
  const method = hasChildElement(body, "m:Boolean");
@@ -191,7 +191,7 @@ describe('SOAP', function() {
191
191
  const expected = [ "0", "0", "0", "1", "2", "-3", "1", "0", "0", "7", "127", "12", "100", "5", "6", "-5", "-6"];
192
192
  for (var i=0; i<values.length; i++)
193
193
  call.writeByte(`p${i}`, values[i]);
194
- const request = call._createHTTPRequest(URL);
194
+ const [ request ] = call._createHTTPRequest(URL);
195
195
  const env = DomUtil.parse(request.data).documentElement;
196
196
  const body = hasChildElement(env, "SOAP-ENV:Body");
197
197
  const method = hasChildElement(body, "m:Byte");
@@ -206,7 +206,7 @@ describe('SOAP', function() {
206
206
  const expected = [ "0", "0", "0", "1", "2", "-3", "1", "0", "0", "7", "500", "12", "100", "5", "6", "-5", "-6"];
207
207
  for (var i=0; i<values.length; i++)
208
208
  call.writeShort(`p${i}`, values[i]);
209
- const request = call._createHTTPRequest(URL);
209
+ const [ request ] = call._createHTTPRequest(URL);
210
210
  const env = DomUtil.parse(request.data).documentElement;
211
211
  const body = hasChildElement(env, "SOAP-ENV:Body");
212
212
  const method = hasChildElement(body, "m:Short");
@@ -221,7 +221,7 @@ describe('SOAP', function() {
221
221
  const expected = [ "0", "0", "0", "1", "2", "-3", "1", "0", "0", "7", "500", "12", "100", "5", "6", "-5", "-6"];
222
222
  for (var i=0; i<values.length; i++)
223
223
  call.writeLong(`p${i}`, values[i]);
224
- const request = call._createHTTPRequest(URL);
224
+ const [ request ] = call._createHTTPRequest(URL);
225
225
  const env = DomUtil.parse(request.data).documentElement;
226
226
  const body = hasChildElement(env, "SOAP-ENV:Body");
227
227
  const method = hasChildElement(body, "m:Long");
@@ -236,7 +236,7 @@ describe('SOAP', function() {
236
236
  const expected = [ "0", "0", "0", "1", "2", "-3", "1", "0", "0", "7", "500", "12"];
237
237
  for (var i=0; i<values.length; i++)
238
238
  call.writeInt64(`p${i}`, values[i]);
239
- const request = call._createHTTPRequest(URL);
239
+ const [ request ] = call._createHTTPRequest(URL);
240
240
  const env = DomUtil.parse(request.data).documentElement;
241
241
  const body = hasChildElement(env, "SOAP-ENV:Body");
242
242
  const method = hasChildElement(body, "m:Int64");
@@ -251,7 +251,7 @@ describe('SOAP', function() {
251
251
  const expected = [ "0", "0", "0", "1", "2", "-3", "1", "0", "0", "7", "500", "12", "100", "5.1", "5.9", "-5.1", "-5.9"];
252
252
  for (var i=0; i<values.length; i++)
253
253
  call.writeFloat(`p${i}`, values[i]);
254
- const request = call._createHTTPRequest(URL);
254
+ const [ request ] = call._createHTTPRequest(URL);
255
255
  const env = DomUtil.parse(request.data).documentElement;
256
256
  const body = hasChildElement(env, "SOAP-ENV:Body");
257
257
  const method = hasChildElement(body, "m:Float");
@@ -266,7 +266,7 @@ describe('SOAP', function() {
266
266
  const expected = [ "0", "0", "0", "1", "2", "-3", "1", "0", "0", "7", "500", "12", "100", "5.1", "5.9", "-5.1", "-5.9"];
267
267
  for (var i=0; i<values.length; i++)
268
268
  call.writeDouble(`p${i}`, values[i]);
269
- const request = call._createHTTPRequest(URL);
269
+ const [ request ] = call._createHTTPRequest(URL);
270
270
  const env = DomUtil.parse(request.data).documentElement;
271
271
  const body = hasChildElement(env, "SOAP-ENV:Body");
272
272
  const method = hasChildElement(body, "m:Double");
@@ -281,7 +281,7 @@ describe('SOAP', function() {
281
281
  const expected = [ "", "", "0", "1", "2", "-3", "true", "false", "", "7", "500", "12", "1.e2", "5.1", "5.9", "-5.1", "-5.9", "Hello", "<>\""];
282
282
  for (var i=0; i<values.length; i++)
283
283
  call.writeString(`p${i}`, values[i]);
284
- const request = call._createHTTPRequest(URL);
284
+ const [ request ] = call._createHTTPRequest(URL);
285
285
  const env = DomUtil.parse(request.data).documentElement;
286
286
  const body = hasChildElement(env, "SOAP-ENV:Body");
287
287
  const method = hasChildElement(body, "m:String");
@@ -299,7 +299,7 @@ describe('SOAP', function() {
299
299
  const expected = [ "", "", "2020-12-31T12:34:56.789Z", "2020-12-31T12:34:56.789Z", "2020-12-31T00:00:00.000Z"];
300
300
  for (var i=0; i<values.length; i++)
301
301
  call.writeTimestamp(`p${i}`, values[i]);
302
- const request = call._createHTTPRequest(URL);
302
+ const [ request ] = call._createHTTPRequest(URL);
303
303
  const env = DomUtil.parse(request.data).documentElement;
304
304
  const body = hasChildElement(env, "SOAP-ENV:Body");
305
305
  const method = hasChildElement(body, "m:Timestamp");
@@ -317,7 +317,7 @@ describe('SOAP', function() {
317
317
  const expected = [ "", "", "2020-12-31T00:00:00.000Z", "2020-12-31T00:00:00.000Z", "2020-12-31T00:00:00.000Z"];
318
318
  for (var i=0; i<values.length; i++)
319
319
  call.writeDate(`p${i}`, values[i]);
320
- const request = call._createHTTPRequest(URL);
320
+ const [ request ] = call._createHTTPRequest(URL);
321
321
  const env = DomUtil.parse(request.data).documentElement;
322
322
  const body = hasChildElement(env, "SOAP-ENV:Body");
323
323
  const method = hasChildElement(body, "m:Date");
@@ -332,7 +332,7 @@ describe('SOAP', function() {
332
332
 
333
333
  const call = makeSoapMethodCall(undefined, "xtk:session", "Element", "$session$", "$security$");
334
334
  call.writeElement("p", element);
335
- const request = call._createHTTPRequest(URL);
335
+ const [ request ] = call._createHTTPRequest(URL);
336
336
  const env = DomUtil.parse(request.data).documentElement;
337
337
  const body = hasChildElement(env, "SOAP-ENV:Body");
338
338
  const method = hasChildElement(body, "m:Element");
@@ -348,7 +348,7 @@ describe('SOAP', function() {
348
348
  const element = call.createElement("root");
349
349
  element.setAttribute("att", "Hello");
350
350
  call.writeElement("p", element);
351
- const request = call._createHTTPRequest(URL);
351
+ const [ request ] = call._createHTTPRequest(URL);
352
352
  const env = DomUtil.parse(request.data).documentElement;
353
353
  const body = hasChildElement(env, "SOAP-ENV:Body");
354
354
  const method = hasChildElement(body, "m:Element");
@@ -362,7 +362,7 @@ describe('SOAP', function() {
362
362
  const call = makeSoapMethodCall(undefined, "xtk:session", "Element", "$session$", "$security$");
363
363
  call.writeElement("p", null);
364
364
  call.writeElement("q", undefined);
365
- const request = call._createHTTPRequest(URL);
365
+ const [ request ] = call._createHTTPRequest(URL);
366
366
  const env = DomUtil.parse(request.data).documentElement;
367
367
  const body = hasChildElement(env, "SOAP-ENV:Body");
368
368
  const method = hasChildElement(body, "m:Element");
@@ -378,7 +378,7 @@ describe('SOAP', function() {
378
378
 
379
379
  const call = makeSoapMethodCall(undefined, "xtk:session", "Document", "$session$", "$security$");
380
380
  call.writeDocument("p", doc);
381
- const request = call._createHTTPRequest(URL);
381
+ const [ request ] = call._createHTTPRequest(URL);
382
382
  const env = DomUtil.parse(request.data).documentElement;
383
383
  const body = hasChildElement(env, "SOAP-ENV:Body");
384
384
  const method = hasChildElement(body, "m:Document");
@@ -394,7 +394,7 @@ describe('SOAP', function() {
394
394
 
395
395
  const call = makeSoapMethodCall(undefined, "xtk:session", "Document", "$session$", "$security$");
396
396
  call.writeDocument("p", doc.documentElement);
397
- const request = call._createHTTPRequest(URL);
397
+ const [ request ] = call._createHTTPRequest(URL);
398
398
  const env = DomUtil.parse(request.data).documentElement;
399
399
  const body = hasChildElement(env, "SOAP-ENV:Body");
400
400
  const method = hasChildElement(body, "m:Document");
@@ -408,7 +408,7 @@ describe('SOAP', function() {
408
408
  const call = makeSoapMethodCall(undefined, "xtk:session", "Document", "$session$", "$security$");
409
409
  call.writeDocument("p", null);
410
410
  call.writeDocument("q", undefined);
411
- const request = call._createHTTPRequest(URL);
411
+ const [ request ] = call._createHTTPRequest(URL);
412
412
  const env = DomUtil.parse(request.data).documentElement;
413
413
  const body = hasChildElement(env, "SOAP-ENV:Body");
414
414
  const method = hasChildElement(body, "m:Document");
@@ -704,14 +704,14 @@ describe('SOAP', function() {
704
704
 
705
705
  it("Should support no encoding", function() {
706
706
  const call = makeSoapMethodCall(undefined, "xtk:session", "Empty");
707
- const request = call._createHTTPRequest(URL);
707
+ const [ request ] = call._createHTTPRequest(URL);
708
708
  assert.equal(request.url, URL);
709
709
  assert.equal(request.headers["Content-type"], "application/soap+xml");
710
710
  });
711
711
 
712
712
  it("Should support UTF-8 encoding", function() {
713
- const call = makeSoapMethodCall(undefined, "xtk:session", "Empty", undefined, undefined, undefined, "UTF-8");
714
- const request = call._createHTTPRequest(URL);
713
+ const call = makeSoapMethodCall(undefined, "xtk:session", "Empty", undefined, undefined, undefined, { charset: "UTF-8" });
714
+ const [ request ] = call._createHTTPRequest(URL);
715
715
  assert.equal(request.url, URL);
716
716
  assert.equal(request.headers["Content-type"], "application/soap+xml;charset=UTF-8");
717
717
  });
@@ -723,7 +723,7 @@ describe('SOAP', function() {
723
723
  expect(client._connectionParameters._options.charset).toBe('UTF-8');
724
724
  const soapCall = client._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", true);
725
725
  expect (soapCall._charset).toBe('UTF-8');
726
- const request = soapCall._createHTTPRequest(URL);
726
+ const [ request ] = soapCall._createHTTPRequest(URL);
727
727
  assert.equal(request.headers["Content-type"], "application/soap+xml;charset=UTF-8");
728
728
  })
729
729
 
@@ -734,7 +734,7 @@ describe('SOAP', function() {
734
734
  expect(client._connectionParameters._options.charset).toBe('');
735
735
  const soapCall = client._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", true);
736
736
  expect (soapCall._charset).toBe('');
737
- const request = soapCall._createHTTPRequest(URL);
737
+ const [ request ] = soapCall._createHTTPRequest(URL);
738
738
  assert.equal(request.headers["Content-type"], "application/soap+xml");
739
739
  })
740
740
 
@@ -745,7 +745,7 @@ describe('SOAP', function() {
745
745
  expect(client._connectionParameters._options.charset).toBe('ISO-8859-1');
746
746
  const soapCall = client._prepareSoapCall("xtk:persist", "GetEntityIfMoreRecent", true);
747
747
  expect (soapCall._charset).toBe('ISO-8859-1');
748
- const request = soapCall._createHTTPRequest(URL);
748
+ const [ request ] = soapCall._createHTTPRequest(URL);
749
749
  assert.equal(request.headers["Content-type"], "application/soap+xml;charset=ISO-8859-1");
750
750
  })
751
751
  });
@@ -833,7 +833,7 @@ describe("Campaign exception", () => {
833
833
 
834
834
  it("Should have HTTP request", () => {
835
835
  const call = makeSoapMethodCall(undefined, "xtk:session", "Date", "$session$", "$security$");
836
- const request = call._createHTTPRequest(URL);
836
+ const [ request ] = call._createHTTPRequest(URL);
837
837
  assert.equal(request.url, URL);
838
838
  })
839
839
 
@@ -842,13 +842,13 @@ describe("Campaign exception", () => {
842
842
  describe("User agent", () => {
843
843
  it("Should set user agent", () => {
844
844
  const call = makeSoapMethodCall(undefined, "xtk:session", "Date", "$session$", "$security$", "My User Agent");
845
- const request = call._createHTTPRequest(URL);
845
+ const [ request ] = call._createHTTPRequest(URL);
846
846
  expect(request.headers['User-Agent']).toBe("My User Agent");
847
847
  })
848
848
 
849
849
  it("Should support no user agent", () => {
850
850
  const call = makeSoapMethodCall(undefined, "xtk:session", "Date", "$session$", "$security$", undefined);
851
- const request = call._createHTTPRequest(URL);
851
+ const [ request ] = call._createHTTPRequest(URL);
852
852
  expect(request.headers['User-Agent']).toBeUndefined();
853
853
  })
854
854
  })
@@ -869,7 +869,7 @@ describe("Campaign exception", () => {
869
869
  describe('Extra Http headers', () => {
870
870
  it("Should take additional headers", () => {
871
871
  const call = makeSoapMethodCall(undefined, "xtk:session", "Date", "$session$", "$security$", "My User Agent", undefined, { 'X-ACC-UI-Version': '1.0' });
872
- const request = call._createHTTPRequest(URL);
872
+ const [ request ] = call._createHTTPRequest(URL);
873
873
  expect(request.headers['User-Agent']).toBe("My User Agent");
874
874
  expect(request.headers['X-ACC-UI-Version']).toBe("1.0");
875
875
  expect(request.headers['SoapAction']).toBe("xtk:session#Date");
@@ -877,12 +877,26 @@ describe("Campaign exception", () => {
877
877
 
878
878
  it("Should override default headers headers", () => {
879
879
  const call = makeSoapMethodCall(undefined, "xtk:session", "Date", "$session$", "$security$", "My User Agent", undefined, { 'X-ACC-UI-Version': '1.0', 'SoapAction': 'My soap action' });
880
- const request = call._createHTTPRequest(URL);
880
+ const [ request ] = call._createHTTPRequest(URL);
881
881
  expect(request.headers['User-Agent']).toBe("My User Agent");
882
882
  expect(request.headers['X-ACC-UI-Version']).toBe("1.0");
883
883
  expect(request.headers['SoapAction']).toBe("My soap action");
884
884
  });
885
885
  });
886
886
 
887
+ describe('Adding method name in the URL', () => {
888
+ it("Should add the method name by default in the URL", () => {
889
+ const call = makeSoapMethodCall(undefined, "xtk:session", "Empty", "$session$", "$security$");
890
+ call.finalize(URL);
891
+ expect(call.request.url).toBe("https://soap-test/nl/jsp/soaprouter.jsp?xtk:session#Empty");
892
+ });
893
+
894
+ it("Should be able to disable adding the method name by default in the URL", () => {
895
+ const call = makeSoapMethodCall(undefined, "xtk:session", "Empty", "$session$", "$security$", undefined, { noMethodInURL: true });
896
+ call.finalize(URL);
897
+ expect(call.request.url).toBe("https://soap-test/nl/jsp/soaprouter.jsp");
898
+ });
899
+ });
900
+
887
901
  });
888
902
 
@@ -1,22 +0,0 @@
1
- {
2
- // Use IntelliSense to learn about possible attributes.
3
- // Hover to view descriptions of existing attributes.
4
- // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
- "version": "0.2.0",
6
- "configurations": [
7
- {
8
- "type": "node",
9
- "request": "launch",
10
- "name": "Jest Current File",
11
- "program": "${workspaceFolder}/node_modules/.bin/jest",
12
- "args": ["${relativeFile}"],
13
- "console": "integratedTerminal",
14
- "internalConsoleOptions": "neverOpen",
15
- "windows": {
16
- "program": "${workspaceFolder}/node_modules/jest/bin/jest",
17
- }
18
- }
19
-
20
-
21
- ]
22
- }