@adobe/acc-js-sdk 1.1.14 → 1.1.16

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/compile.js CHANGED
@@ -31,6 +31,7 @@ var resources = [
31
31
  { name: "./transport.js" },
32
32
  { name: "./xtkCaster.js" },
33
33
  { name: "./domUtil.js" },
34
+ { name: "./xtkJob.js" },
34
35
  { name: "./cache.js" },
35
36
  { name: "./entityAccessor.js" },
36
37
  { name: "./xtkEntityCache.js" },
@@ -83,6 +83,8 @@
83
83
  link: methodLevelRepresentation.html
84
84
  - name: XTK Interfaces
85
85
  link: xtkInterface.html
86
+ - name: XTK Jobs
87
+ link: xtkJob.html
86
88
  - name: Handling timeouts
87
89
  link: timeouts.html
88
90
  - name: HTTP Headers
@@ -129,7 +129,7 @@ console.log(`About to call method '${methodName}' of scope '${scopeName}'`);
129
129
  returnedValue = undefined;
130
130
  }
131
131
  // If the API returns one parameter which is an object, the return it directly.
132
- // If not (return value is a litteral), then use a JSON with the return parameter name
132
+ // If not (return value is a literal), then use a JSON with the return parameter name
133
133
  else if (outNames.length == 1) {
134
134
  if (result && typeof result == "object")
135
135
  returnedValue = result;
@@ -2,6 +2,20 @@
2
2
  layout: page
3
3
  title: Change Log
4
4
  ---
5
+ <section class="changelog"><h1>Version 1.1.16</h1>
6
+ <h2>2022/11/29</h2>
7
+
8
+ <li>Added support for xtk:job interface and job-related methods. See <a href="https://opensource.adobe.com/acc-js-sdk/xtkJob.html">Jobs documentation</a> for more details</li>
9
+ </section>
10
+
11
+
12
+ <section class="changelog"><h1>Version 1.1.15</h1>
13
+ <h2>2022/11/28</h2>
14
+
15
+ <li>Fix an issue with SimpleJson serialization. See <a href="https://opensource.adobe.com/acc-js-sdk/simpleJson.html">SimpleJson documentation</a> for more details, and in particular the <b>Compatibility Notes</b> section</li>
16
+ <li>Fix credentials passing for fileUpload and getReportData methods. This is still a temporary fix until those APIs are made IMS compatible.</li>
17
+ </section>
18
+
5
19
  <section class="changelog"><h1>Version 1.1.14</h1>
6
20
  <h2>2022/11/25</h2>
7
21
 
@@ -202,7 +216,7 @@ For breaking changes see the [migration guide](MIGRATION.md)
202
216
  <li><b>getEntityIfMoreRecent</b> now takes an additional parameter which allows to specify and force a representation (xml, json...)
203
217
  <li>New helper function <b>DomUtil.isArray</b> to test if a JavaScript object is an array
204
218
  <li>New <b>EntityAccessor</b> object which allows to get attributes and child elements from xml or json objects, regardless of their representation
205
- <li>New <b>escapeXtk</b> function to escape litteral values in Xtk expression. Can be used as a function or as a tagged template litteral
219
+ <li>New <b>escapeXtk</b> function to escape literal values in Xtk expression. Can be used as a function or as a tagged template literal
206
220
  <li>New function <b>XtkCaster._variantStorageAttribute</b> which returns the name of a schema attribute used to store variant value types. The name of the attribute depends on the type: stringValue, longValue, etc.
207
221
  <li>Support for non static method that mutate the object on which they apply. For instance, the <b>xtk:queryDef#SelectAll</b>
208
222
  <li>Added samples in the samples/ folder
@@ -229,7 +243,7 @@ _Breaking changes in 1.0.0_
229
243
  <li>Changes in the <b>sdk.init</b>, <b>Client</b> constructor, and <b>logon</b> functions. Now using <b>ConnectionParameters</b> and <b>Credentials</b> objects to configure a Campaign connection
230
244
  <li>Client object members are now private: access to representation, etc. attributes is not allowed anymore except for <b>NLWS</b>, <b>XtkCaster</b>, and <b>DomUtil</b>
231
245
  <li>Access to the <b>sessionInfo</b> object after <b>logon</b> can be done via the new <b>getSessionInfo</b> call
232
- <li>Options cache internal strucutre change: option values in the cache are now object litterals containing the option value, type, and raw value (which may not be casted to the expected type yet)
246
+ <li>Options cache internal strucutre change: option values in the cache are now object literals containing the option value, type, and raw value (which may not be casted to the expected type yet)
233
247
  <li>Connecting to mid-sourcing (or other Campaign instances which are defined by an external account) is now done with the <b>ConnectionParameters.ofExternalAccount</b> function. As a consequence, <b>getSecretKeyCipher</b> is now private and deprecated
234
248
  <li>CampaignException object signature changed (but was not previously exposed)
235
249
  <li>The client-side bundle is now generated in the <b>dist/bundle.js</b> file instead of <b>bundle.js</b>
@@ -4,7 +4,7 @@ title: Escaping
4
4
  ---
5
5
 
6
6
 
7
- <p>It's common to use variables in query conditions. For instance, in the above example, you'll want to query an account by name instead of using the hardcoded <b>ffda</b> name. The <b>expr</b> attribute takes an XTK expression as a parameter, and <b>ffda</b> is a string litteral in an xtk expression.</p>
7
+ <p>It's common to use variables in query conditions. For instance, in the above example, you'll want to query an account by name instead of using the hardcoded <b>ffda</b> name. The <b>expr</b> attribute takes an XTK expression as a parameter, and <b>ffda</b> is a string literal in an xtk expression.</p>
8
8
 
9
9
  <p>To prevent xtk ingestions vulnerabilities, you should not concatenate strings and write code such as expr: "@name = '" + name + "'": if the value of the name
10
10
  parameter contains single quotes, your code will not work, but could also cause vulnerabilities.
@@ -13,19 +13,19 @@ title: Escaping
13
13
 
14
14
  <h1>sdk.escapeXtk</h1>
15
15
 
16
- <p>The <b>sdk.escapeXtk</b> can be used to properly escape string litterals in xtk expressions. The function will also surround the escaped value with single quotes.</p>
16
+ <p>The <b>sdk.escapeXtk</b> can be used to properly escape string literals in xtk expressions. The function will also surround the escaped value with single quotes.</p>
17
17
 
18
18
  <p>You can use string concatenation like this. Note the lack of single quotes around the value.</p>
19
19
  <pre class="code">
20
20
  { expr: "@name=" + sdk.escapeXtk(name) }
21
21
  </pre>
22
22
 
23
- <p>or a template litteral</p>
23
+ <p>or a template literal</p>
24
24
  <pre class="code">
25
25
  `{ expr: "@name=${sdk.escapeXtk(name)}" }`
26
26
  </pre>
27
27
 
28
- <p>The <b>escapeXtk</b> function can also be used to create tagged string litterals. This leads to a much shorter syntax. Note that with this syntax, only the parameter values of the template litteral are escaped</p>
28
+ <p>The <b>escapeXtk</b> function can also be used to create tagged string literals. This leads to a much shorter syntax. Note that with this syntax, only the parameter values of the template literal are escaped</p>
29
29
  <pre class="code">
30
30
  sdk.escapeXtk`{ expr: "@name=${name}" }`
31
31
  </pre>
@@ -4,7 +4,7 @@ title: SimpleJson format
4
4
  ---
5
5
 
6
6
  <p>The <b>SimpleJson</b> format is the format used by default by the SDK to conver between Campaign XML and JSON</p>
7
-
7
+ <p></p>
8
8
 
9
9
  <ul>
10
10
  <li>XML attributes are JSON properties (without the “@” sign)</li>
@@ -27,6 +27,7 @@ title: SimpleJson format
27
27
  </pre>
28
28
 
29
29
 
30
+ <h1>XML Root</h1>
30
31
  <p>The XML root element tag is automatically determined by the SDK as it's generating the XML, usually from the current schema name.</p>
31
32
 
32
33
  <pre class="code">
@@ -34,15 +35,21 @@ XML: &lt;root/>
34
35
  JSON: {}
35
36
  </pre>
36
37
 
37
- <p>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.
38
- Values in JSON attributes can be indifferently typed (ex: number, boolean), or strings (ex: "3" instead of just 3) depending if the conversion could determine the attribute type or not.
39
- API users should expect and handle both value and use the `XtkCaster` object to ensure proper conversion when using.</p>
38
+
39
+
40
+
41
+ <h1>XML Attributes</h1>
42
+ <p>XML attributes are mapped to JSON attributes with the same name, whose literal value can be a string, number, or boolean. There's no "@" sign in the JSON attribute name.
43
+ Values in JSON attributes can be either typed (ex: number, boolean), or strings (ex: "3" instead of just 3) depending if the conversion could determine the attribute type or not.
44
+ API users should expect and handle both value and use the <b>XtkCaster</b> object to ensure proper conversion.</p>
40
45
 
41
46
  <pre class="code">
42
47
  XML &lt;root hello="world" count="3" ok="true"/>
43
48
  JSON: { hello:"world", count:"3", ok:"true" }
44
49
  </pre>
45
50
 
51
+
52
+ <h1>XML Elements</h1>
46
53
  <p>XML elements are mapped to JSON objects</p>
47
54
 
48
55
  <pre class="code">
@@ -64,7 +71,9 @@ XML: &lt;root>&lt;item id=1/>&lt;item id=2/>&lt;/root>
64
71
  JSON: { item: [ { id:"1" }, { id:"2" } ] }
65
72
  </pre>
66
73
 
67
- <p>Text of XML element is handle with the <b>$</b> sign in the JSON attribute name, or with a child JSON object name <b>$</b></p>
74
+
75
+ <h1>Text nodes</h1>
76
+ <p>Text of XML element is handled with the <b>$</b> sign in the JSON attribute name, or with a child JSON object name <b>$</b></p>
68
77
 
69
78
  <p>Text of the root element</p>
70
79
  <pre class="code">
@@ -86,3 +95,67 @@ XML: &lt;root>&lt;item>Hello&lt;child id="1"/>
86
95
  &lt;/root>
87
96
  JSON: { item: { $: "Hello", child: { id:"1" } }
88
97
  </pre>
98
+
99
+ <p>Normally Campaign will not generate XML with elements containing multiple sibling text nodes. If this should happen, the SDK will consider them as a single text value, i.e. it will concatenate the contents of each text and CDATA node as if there was only one. However, whitespaces are processed independently for each text node.
100
+ </p>
101
+
102
+ <h1>Whitespaces</h1>
103
+ <p>In XML documents, whitespaces can be either significant or insignificant. The SDK uses the following rules to strip whitespaces, which correspond to how Campaign specifically uses XML</p>
104
+ <p> </p>
105
+ <ul>
106
+ <li>The characters " ", "\t", "\r" and "\n" are considered whitespaces</li>
107
+ <li>CDATA sections are kept unchanged, i.e. whitespaces are preserved exactly</li>
108
+ <li>For TEXT nodes directly under the root node are, whitespaces will be trimmed as explained below</li>
109
+ <li>For element nodes which only contain text and possibly attributes (for instance &lt;node&gt;value&lt;/node&gt;</li>, the text is kept unchanged, i.e. whitespaces are preserved exactly</li>
110
+ <li>For element nodes which have child elements, whitespaces will be trimmed as explained below</li>
111
+ <li>For the root element, whitespaces are always trimmed</li>
112
+ </ul>
113
+ <p> </p>
114
+ <p>
115
+ Whitespace trimming consists of removing all the leading and trailing whitespaces of each text node and concatenating all text node values. If the resulting value is empty, the text node is ignored. The rationale is to remove insignificant spaces created when formatting XML documents
116
+ </p>
117
+
118
+
119
+ <h1>Exceptions</h1>
120
+
121
+ <h2>When an attribute has the same name of an element</h2>
122
+
123
+ <p>If an element contains another element and an attribute which have the same name, the attribute name is prefixed with the "@" character</p>
124
+ <pre class="code">
125
+ XML: &lt;root timezone="Europe/Paris">
126
+ &lt;timezone>Europe/Paris&lt;/timezone>
127
+ &lt;/root>
128
+ JSON: { "@timezone": "Europe/Paris",
129
+ timezone: { "$": "Europe/Paris" } }
130
+ </pre>
131
+
132
+
133
+ <h1>Arrays of text elements</h1>
134
+ <p></p>
135
+ <pre class="code">
136
+ XML: &lt;root>
137
+ &lt;item>One&lt;/item>
138
+ &lt;item>Two&lt;/item>
139
+ &lt;/root>
140
+ JSON: { item: [
141
+ { $: "One" },
142
+ { $: "Two" }
143
+ ] }
144
+ </pre>
145
+
146
+
147
+
148
+ <h1>Compatibility notes</h1>
149
+
150
+ <p>
151
+ A few gaps were identified regarding SimpleJson format when converting from XML to JSON. They were fixed in release 1.1.15 and may introduce some behavior changes for cases which were ambiguous
152
+ </p>
153
+ <p> </p>
154
+ <ul>
155
+ <li>When XML element has both a text content and attributes or child elements</li>
156
+ <li>When root element has only text</li>
157
+ <li>When XML element has both an attribute and a child element with the same name</li>
158
+ <li>When array contains element which only have text</li>
159
+ <li>When XML is formatted (and therefore has insignificant whitespaces)</li>
160
+ <li>XML collections (i.e. when root node ends with “-collection”) would sometimes contain a JSON property “#text”</li>
161
+ </ul>
@@ -27,7 +27,7 @@ title: The Transport Protocol
27
27
 
28
28
  <p>If the request is successful, a promise is returned with the result payload, as a string.</p>
29
29
 
30
- <p>If the request fails, the promise is rejected with an error object with class <b>HttpError</b>, a litteral with the following attributes:</p>
30
+ <p>If the request fails, the promise is rejected with an error object with class <b>HttpError</b>, a literal with the following attributes:</p>
31
31
  <ul>
32
32
  <li><b>statusCode</b> is the HTTP status code, such as 404, 500, etc.</li>
33
33
  <li><b>statusText</b> is the HTTP status text coming with the error</li>
@@ -39,7 +39,7 @@ title: The Transport Protocol
39
39
  <p>The transport can be overriden by using the <b>client.setTransport</b> call and passing it a transport function, i.e. an async function which</p>
40
40
 
41
41
  <ul>
42
- <li>Takes a <b>Request</b> object litteral as a parameter</li>
42
+ <li>Takes a <b>Request</b> object literal as a parameter</li>
43
43
  <li>Returns a the request result in a promise</li>
44
44
  <li>Returns a rejected promise containing an <b>HttpError</b> in case of failure</li>
45
45
  </ul>
@@ -17,4 +17,4 @@ const delivery = client.NLWS.nmsDelivery.create({ label: "Hello" });
17
17
  await delivery.newInstance();
18
18
  </pre>
19
19
 
20
- <p>There are 2 common interfaces: <a href="{{ site.baseurl }}/xtkPersist.html">xtk:persist</a> and <a href="">xtk:jobInterface</a> which are documented below.</p>
20
+ <p>There are 2 common interfaces: <a href="{{ site.baseurl }}/xtkPersist.html">xtk:persist</a> and <a href="{{ site.baseurl }}/xtkJob.html">xtk:jobInterface</a> which are documented below.</p>
@@ -0,0 +1,131 @@
1
+ ---
2
+ layout: page
3
+ title: XTK Jobs (xkt:job, xkt:jobInterface)
4
+ ---
5
+ <p>This section describes how long running jobs are handled in ACC and ACC api. There are 2 schemas for jobs</p>
6
+ <ul>
7
+ <li>xtk:job which represents an acutal job, and which is implemented by several objects such as nms:delivery</li>
8
+ <li>xtk:jobInterface which contains methods to submit jobs and get their statuses. Other schemas do not actually implement the xtk:jobInterface interface</li>
9
+ </ul>
10
+
11
+ <p>In term of SOAP calls, running a job is simply executing a SOAP call synchronously or asynchronously in a separate thread or process. However, calls must be made on both the xtk:jobInterface and job entity schema. The SDK provides a helper interface to submit and handle jobs</p>
12
+
13
+ <h1>Simple Jobs</h1>
14
+
15
+ <p>
16
+ Simple jobs are non-static methods with no parameters, such as the nms:delivery#Prepare method which is used to prepare a delivery.
17
+ Such jobs can be executed synchronously (xtk:jobInterface#Execute) or asynchronously (xtk:jobInterface#Submit). Both methods return
18
+ a job id which can be used to retreive (poll) more about the job.
19
+ <p>
20
+
21
+ <p>
22
+ First, we need to retreive a delivery, which is the object upon which to run the Prepare method, but also implements xtk:job interface.
23
+ The Prepare method requires a complete delivery object, so we use SelectAll
24
+ </p>
25
+
26
+ <pre class="code">
27
+ const queryDef = {
28
+ schema: "nms:delivery",
29
+ operation: "get",
30
+ select: { node: [ { expr: "@id" } ] },
31
+ where: { condition: [ { expr:`@internalName='DM19'` } ] }
32
+ }
33
+ const query = NLWS.xtkQueryDef.create(queryDef);
34
+ await query.selectAll();
35
+ const delivery = await query.executeQuery();
36
+ </pre>
37
+
38
+ <p>
39
+ Now we can create a job for the Prepare method using the <b>client.jobInterface</b> function which returns a XtkJobInterface object.
40
+ We pass it a job specification containing the schema, method, and object
41
+ </p>
42
+
43
+ <pre class="code">
44
+ const job = await client.jobInterface({
45
+ xtkschema: 'nms:delivery',
46
+ method: 'Prepare',
47
+ object: delivery
48
+ });
49
+ </pre>
50
+
51
+ <p>
52
+ Finally we can submit the job and get it's status, progress, result, etc.
53
+ </p>
54
+
55
+ <pre class="code">
56
+ await job.submit();
57
+ var status = await job.getStatus();
58
+ </pre>
59
+
60
+
61
+ <h1>Soap calls</h1>
62
+ <p>
63
+ The <b>SubmitSoapCall</b> method allows to run more complex jobs with parameters. The principle is the same, for instance calling the <b>PrepareProof</b> method
64
+ which takes a boolean parameter
65
+ </p>
66
+
67
+ <pre class="code">
68
+ const job = await client.jobInterface({
69
+ xtkschema: 'nms:delivery',
70
+ method: 'PrepareProof',
71
+ object: delivery,
72
+ args: [ false ]
73
+ });
74
+ </pre>
75
+
76
+
77
+ <h1>Job Status</h1>
78
+ <p>
79
+ The status of a job is made of 3 pieces of information
80
+ </p>
81
+ <ul>
82
+ <li>The job status code</li>
83
+ <li>Job logs</li>
84
+ <li>Job properties which are arbitrary key value pairs and also contain progress information</li>
85
+ </ul>
86
+
87
+ <p>
88
+ For convenience, the SDK provides a <b>getStatus</b> function which will fetch and return the full job status object with strong
89
+ typing. When getStatus is called several time, each call will fetch the most recent status, and new logs since the previous call.
90
+ </p>
91
+
92
+ <table>
93
+ <thead>
94
+ <tr><th>Status code</th><th>Description</th></tr>
95
+ </thead>
96
+ <tbody>
97
+ <tr><td><b>0</b></td><td>Being edited</td></tr>
98
+ <tr><td><b>2</b></td><td>Running: execution is in progress</td></tr>
99
+ <tr><td><b>3</b></td><td>Canceling: a cancel request was submitted and the job will be canceld as soon as possible</td></tr>
100
+ <tr><td><b>4</b></td><td>Canceled</td></tr>
101
+ <tr><td><b>5</b></td><td>Finished: the job has finished successfully and getResult can be called</td></tr>
102
+ <tr><td><b>6</b></td><td>Error: the job failed. Details about the error can be found in the logs</td></tr>
103
+ <tr><td><b>7</b></td><td>Pause pending: a pause request was submitted and the job will be paused as soon as possible</td></tr>
104
+ <tr><td><b>8</b></td><td>Pause: the job is paused</td></tr>
105
+ <tr><td><b>9</b></td><td>Purge pending: a purge request was submitted and the job will be purged as soon as possible</td></tr>
106
+ </tbody>
107
+ </table>
108
+
109
+
110
+ <h1>Job Progress</h1>
111
+ <p>
112
+ The progress of a job is available as 2 integers: current and max which represent the current progression and max value for progression.
113
+ Both values are returned by the getStatus call as properties (i.e. <b>properties.progress.current</b> and <b>properties.progress.max</b>).
114
+ The SDK provides the <b>getProgress</b> function to retreive the progress as a percentage (and a valid number)
115
+ </p>
116
+
117
+ <pre class="code">
118
+ // Returns progress as a percentage in the [0..1] range
119
+ var progressPercent = job.getProgress();
120
+ </pre>
121
+
122
+
123
+ <h1>Job Result</h1>
124
+ <p>
125
+ Typically, a client would call the getStatus method every few seconds to get updates on the progress. When a job is finished and successfull,
126
+ one can get the result using the <b>getResult</b> function
127
+ </p>
128
+
129
+ <pre class="code">
130
+ var result = await job.getResult();
131
+ </pre>
@@ -74,7 +74,7 @@ const extAccount = await query.executeQuery();
74
74
 
75
75
 
76
76
  <h1>Escaping</h1>
77
- <p>It's common to use variables in query conditions. For instance, in the above example, you'll want to query an account by name instead of using the hardcoded <b>ffda</b> name. The <b>expr</b> attribute takes an XTK expression as a parameter, and <b>ffda</b> is a string litteral in an xtk expression.</p>
77
+ <p>It's common to use variables in query conditions. For instance, in the above example, you'll want to query an account by name instead of using the hardcoded <b>ffda</b> name. The <b>expr</b> attribute takes an XTK expression as a parameter, and <b>ffda</b> is a string literal in an xtk expression.</p>
78
78
 
79
79
  <p>To prevent xtk ingestions vulnerabilities, you should not concatenate strings and write code such as expr: "@name = '" + name + "'": if the value of the name
80
80
  parameter contains single quotes, your code will not work, but could also cause vulnerabilities.
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
4
4
  "description": "ACC Javascript SDK",
5
5
  "main": "src/index.js",
6
6
  "homepage": "https://github.com/adobe/acc-js-sdk#readme",
package/src/campaign.js CHANGED
@@ -28,7 +28,7 @@ const { Util } = require("./util.js");
28
28
  static INVALID_CREDENTIALS_TYPE(type, details) { return new CampaignException(undefined, 400, 16384, `SDK-000000 Invalid credentials type '${type}'`, details); }
29
29
  static CANNOT_GET_CREDENTIALS_USER(type) { return new CampaignException(undefined, 400, 16384, `SDK-000001 Cannot get user for Credentials of type '${type}'`); }
30
30
  static CANNOT_GET_CREDENTIALS_PASSWORD(type) { return new CampaignException(undefined, 400, 16384, `SDK-000002 Cannot get password for Credentials of type '${type}'`); }
31
- static INVALID_CONNECTION_OPTIONS(options) { return new CampaignException(undefined, 400, 16384, `SDK-000003 Invalid options parameter (type '${typeof options}'). An object litteral is expected`); }
31
+ static INVALID_CONNECTION_OPTIONS(options) { return new CampaignException(undefined, 400, 16384, `SDK-000003 Invalid options parameter (type '${typeof options}'). An object literal is expected`); }
32
32
  static INVALID_REPRESENTATION(representation, details) { return new CampaignException(undefined, 400, 16384, `SDK-000004 Invalid representation '${representation}'.`, details); }
33
33
  static CREDENTIALS_FOR_INVALID_EXT_ACCOUNT(name, type) { return new CampaignException(undefined, 400, 16384, `SDK-000005 Cannot created connection parameters for external account '${name}': account type ${type} not supported`); }
34
34
  static BAD_PARAMETER(name, value, details) { return new CampaignException(undefined, 400, 16384, `SDK-000006 Bad parameter '${name}' with value '${value}'`, details); }
package/src/client.js CHANGED
@@ -36,6 +36,7 @@ const request = require('./transport.js').request;
36
36
  const Application = require('./application.js').Application;
37
37
  const EntityAccessor = require('./entityAccessor.js').EntityAccessor;
38
38
  const { Util } = require('./util.js');
39
+ const { XtkJobInterface } = require('./xtkJob.js');
39
40
  const qsStringify = require('qs-stringify');
40
41
 
41
42
  /**
@@ -173,16 +174,7 @@ const clientHandler = (representation, headers, pushDownOptions) => {
173
174
  return callContext;
174
175
 
175
176
  // get Schema id from namespace (find first upper case letter)
176
- var schemaId = "";
177
- for (var i=0; i<namespace.length; i++) {
178
- const c = namespace[i];
179
- if (c >='A' && c<='Z') {
180
- schemaId = schemaId + ":" + c.toLowerCase() + namespace.substr(i+1);
181
- break;
182
- }
183
- schemaId = schemaId + c;
184
- }
185
- callContext.schemaId = schemaId;
177
+ callContext.schemaId = Util.schemaIdFromNamespace(namespace);
186
178
 
187
179
  const caller = function(thisArg, argumentsList) {
188
180
  const callContext = thisArg["."];
@@ -546,16 +538,14 @@ const fileUploader = (client) => {
546
538
  }
547
539
  const data = new FormData();
548
540
  data.append('file_noMd5', file);
549
- //TODO: Needs to be refactored after cookie issue get resolved.
550
541
  client._makeHttpCall({
551
542
  url: `${client._connectionParameters._endpoint}/nl/jsp/uploadFile.jsp`,
552
543
  processData: false,
553
- credentials: 'include',
554
544
  method: 'POST',
555
545
  data: data,
556
546
  headers: {
557
- 'x-security-token': client._securityToken,
558
- 'Cookie': '__sessiontoken=' + client._sessionToken,
547
+ 'X-Security-Token': client._securityToken,
548
+ 'X-Session-Token': client._sessionToken,
559
549
  }
560
550
  }).then((okay) => {
561
551
  if (!okay.startsWith('Ok')) {
@@ -1475,11 +1465,21 @@ class Client {
1475
1465
  const result = [];
1476
1466
  const schemaId = callContext.schemaId;
1477
1467
 
1478
- var schema = await that.getSchema(schemaId, "xml", true);
1468
+ var entitySchemaId = schemaId;
1469
+ if (schemaId === 'xtk:jobInterface')
1470
+ entitySchemaId = callContext.entitySchemaId;
1471
+
1472
+ // Get the schema which contains the method call. Methods of the xtk:jobInterface interface are handled specificaaly
1473
+ // because xtk:jobInterface is not actually a schema, but just an interface. In practice, it's used as an xtk template
1474
+ // rather that an xtk inheritance mechanism
1475
+ const methodSchemaId = schemaId === 'xtk:jobInterface' ? 'xtk:job' : schemaId;
1476
+ var schema = await that.getSchema(methodSchemaId, "xml", true);
1479
1477
  if (!schema)
1480
1478
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Schema '${schemaId}' not found`);
1481
1479
  var schemaName = schema.getAttribute("name");
1482
- var method = that._methodCache.get(schemaId, methodName);
1480
+
1481
+ // Lookup the method to call
1482
+ var method = that._methodCache.get(methodSchemaId, methodName);
1483
1483
  if (!method) {
1484
1484
  // first char of the method name may be lower case (ex: nms:seedMember.getAsModel) but the methodName
1485
1485
  // variable has been capitalized. Make an attempt to lookup method name without capitalisation
@@ -1489,13 +1489,16 @@ class Client {
1489
1489
  }
1490
1490
  if (!method) {
1491
1491
  this._methodCache.put(schema);
1492
- method = that._methodCache.get(schemaId, methodName);
1492
+ method = that._methodCache.get(methodSchemaId, methodName);
1493
1493
  }
1494
1494
  if (!method)
1495
1495
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Method '${methodName}' of schema '${schemaId}' not found`);
1496
- // console.log(method.toXMLString());
1497
1496
 
1498
- var urn = that._methodCache.getSoapUrn(schemaId, methodName);
1497
+ // Compute the SOAP URN. Again, specically handle xtk:jobInterface as it's not a real schema. The actual entity schema
1498
+ // would be available as the entitySchemaId property of the callContext
1499
+ var urn = schemaId !== 'xtk:jobInterface' ? that._methodCache.getSoapUrn(schemaId, methodName)
1500
+ : `xtk:jobInterface|${entitySchemaId}`;
1501
+
1499
1502
  var soapCall = that._prepareSoapCall(urn, methodName, false, callContext.headers, callContext.pushDownOptions);
1500
1503
 
1501
1504
  // If method is called with one parameter which is a function, then we assume it's a hook: the function will return
@@ -1512,13 +1515,13 @@ class Client {
1512
1515
  if (!object)
1513
1516
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Cannot call non-static method '${methodName}' of schema '${schemaId}' : no object was specified`);
1514
1517
 
1515
- const rootName = schemaId.substr(schemaId.indexOf(':') + 1);
1518
+ const rootName = entitySchemaId.substr(entitySchemaId.indexOf(':') + 1);
1516
1519
  object = that._fromRepresentation(rootName, object, callContext.representation);
1517
1520
  // The xtk:persist#NewInstance requires a xtkschema attribute which we can compute here
1518
1521
  // Actually, we're always adding it, for all non-static methods
1519
1522
  const xmlRoot = object.nodeType === 9 ? object.documentElement : object;
1520
1523
  if (!xmlRoot.hasAttribute("xtkschema"))
1521
- xmlRoot.setAttribute("xtkschema", schemaId);
1524
+ xmlRoot.setAttribute("xtkschema", entitySchemaId);
1522
1525
  soapCall.writeDocument("document", object);
1523
1526
  }
1524
1527
  const parametersIsArray = (typeof parameters == "object") && parameters.length;
@@ -1527,7 +1530,7 @@ class Client {
1527
1530
  var param = DomUtil.getFirstChildElement(params, "param");
1528
1531
  var paramIndex = 0;
1529
1532
  while (param) {
1530
- const inout = DomUtil.getAttributeAsString(param, "inout");
1533
+ const inout = DomUtil.getAttributeAsString(param, "inout");
1531
1534
  if (!inout || inout=="in") {
1532
1535
  const type = DomUtil.getAttributeAsString(param, "type");
1533
1536
  const paramName = DomUtil.getAttributeAsString(param, "name");
@@ -1570,9 +1573,9 @@ class Client {
1570
1573
  // Hack for workflow API. The C++ code checks that the name of the XML element is <variables>. When
1571
1574
  // using xml representation at the SDK level, it's ok since the SDK caller will set that. But this does
1572
1575
  // not work when using "BadgerFish" representation where we do not know the root element name.
1573
- if (schemaId == "xtk:workflow" && methodName == "StartWithParameters" && paramName == "parameters")
1576
+ if (entitySchemaId == "xtk:workflow" && methodName == "StartWithParameters" && paramName == "parameters")
1574
1577
  docName = "variables";
1575
- if (schemaId == "nms:rtEvent" && methodName == "PushEvent")
1578
+ if (entitySchemaId == "nms:rtEvent" && methodName == "PushEvent")
1576
1579
  docName = "rtEvent";
1577
1580
  // Try to guess the document name. This is usually available in the xtkschema attribute
1578
1581
  var xtkschema = EntityAccessor.getAttributeAsString(paramValue, "xtkschema");
@@ -1636,7 +1639,7 @@ class Client {
1636
1639
  else if (type == "DOMDocument") {
1637
1640
  returnValue = soapCall.getNextDocument();
1638
1641
  returnValue = that._toRepresentation(returnValue, callContext.representation);
1639
- if (schemaId === "xtk:queryDef" && methodName === "ExecuteQuery" && paramName === "output") {
1642
+ if (entitySchemaId === "xtk:queryDef" && methodName === "ExecuteQuery" && paramName === "output") {
1640
1643
  // https://github.com/adobe/acc-js-sdk/issues/3
1641
1644
  // Check if query operation is "getIfExists". The "object" variable at this point
1642
1645
  // is always an XML, regardless of the xml/json representation
@@ -1794,11 +1797,10 @@ class Client {
1794
1797
  url: `${this._connectionParameters._endpoint}/report/${callContext.reportName}?${encodeURI(`_noRender=true&_schema=${callContext.schema}&_context=${callContext.context}&_selection=${callContext.selection}`)}&_selectionCount=${selectionCount}`,
1795
1798
  headers: {
1796
1799
  'X-Security-Token': this._securityToken,
1797
- 'Cookie': '__sessiontoken=' + this._sessionToken,
1800
+ 'X-Session-Token': this._sessionToken,
1798
1801
  'Content-Type': 'application/x-www-form-urlencoded'
1799
1802
  },
1800
1803
  method: 'POST',
1801
- credentials: 'include',
1802
1804
  data : qsStringify(callContext.formData)
1803
1805
  };
1804
1806
 
@@ -1871,6 +1873,15 @@ class Client {
1871
1873
  const result = this._toRepresentation(doc);
1872
1874
  return result;
1873
1875
  }
1876
+
1877
+ /**
1878
+ * Creates a Job object which can be used to submit jobs, retrieve status, logs and progress, etc.
1879
+ * @param {Campaign.XtkSoapCallSpec} soapCallSpec the definition of the SOAP call
1880
+ * @returns {Campaign.XtkJobInterface} a job
1881
+ */
1882
+ jobInterface(soapCallSpec) {
1883
+ return new XtkJobInterface(this, soapCallSpec);
1884
+ }
1874
1885
  }
1875
1886
 
1876
1887