@adobe/acc-js-sdk 1.1.1 → 1.1.2

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,11 @@ 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.2
9
+ _2022/03/22_
10
+
11
+ * Add support for choosing the representation (XML or JSON) at the method level using NLWS.xml or NLWS.json.
12
+
8
13
  ## Version 1.1.1
9
14
  _2022/03/10_
10
15
 
package/README.md CHANGED
@@ -304,6 +304,15 @@ const queryDef = {
304
304
  };
305
305
  ```
306
306
 
307
+ ## Method-level representation
308
+
309
+ The client object is created with a default representation which is used for all API calls in the context of this client. Since version 1.1.2, it is also possible to set the representation at the method level, i.e. use a particular representation for a particular API call.
310
+
311
+ * `client.NLWS`: use the default representation set at the client level
312
+ * `client.NLWS.xml`: use the XML reresentation
313
+ * `client.NLWS.json`: use the SimpleJson representation
314
+
315
+
307
316
  ## SimpleJson format
308
317
  The Simple JSON format works like this:
309
318
 
@@ -324,7 +333,7 @@ XML elements are mapped to JSON objects
324
333
  * XML: `<root><item id=1/></root>`
325
334
  * JSON: `{ item: { id:1 } }`
326
335
 
327
- If the parent element tag ends with `-collecion` children are always an array, even if there are no children, or if there is just one child. The rationale is that XML/JSON conversion is ambigous : XML can have multiple elements with the same tag and when there's only one such element, it's not possible to determine if it should be represented as a JSON object or JSON array unless we have additional metadata.
336
+ If the parent element tag ends with `-collection` children are always an array, even if there are no children, or if there is just one child. The rationale is that XML/JSON conversion is ambigous : XML can have multiple elements with the same tag and when there's only one such element, it's not possible to determine if it should be represented as a JSON object or JSON array unless we have additional metadata.
328
337
 
329
338
  * XML: `<root-collection><item id=1/></root>`
330
339
  * JSON: `{ item: [ { id:1 } ] }`
package/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@adobe/acc-js-sdk",
9
- "version": "1.1.0",
9
+ "version": "1.1.2",
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.1",
3
+ "version": "1.1.2",
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/client.js CHANGED
@@ -96,65 +96,77 @@ const xtkObjectHandler = {
96
96
  * <code>
97
97
  * result = await client.NLWS.xtkSession.getServerTime();
98
98
  * </code>
99
+ *
100
+ * To get a handler, call the `clientHandler` function and optionally pass a representation.
101
+ * If no representation is passed (undefined), the representation set at the client level
102
+ * will be used, which is the default behavior.
103
+ * To get a proxy with a specific representation, use NLWS.xml or NMWS.json
99
104
  *
100
105
  * @private
101
106
  * @memberof Campaign
102
107
  */
103
- const clientHandler = {
104
- get: function(client, namespace) {
105
- return new Proxy({ client:client, namespace:namespace}, {
106
- get: function(callContext, methodName) {
107
- if (methodName == ".") return callContext;
108
-
109
- // get Schema id from namespace (find first upper case letter)
110
- var schemaId = "";
111
- for (var i=0; i<namespace.length; i++) {
112
- const c = namespace[i];
113
- if (c >='A' && c<='Z') {
114
- schemaId = schemaId + ":" + c.toLowerCase() + namespace.substr(i+1);
115
- break;
116
- }
117
- schemaId = schemaId + c;
118
- }
119
- callContext.schemaId = schemaId;
120
-
121
- const caller = function(thisArg, argumentsList) {
122
- const callContext = thisArg["."];
123
- const namespace = callContext.namespace;
124
- const methodNameLC = methodName.toLowerCase();
125
- methodName = methodName.substr(0, 1).toUpperCase() + methodName.substr(1);
126
- if (namespace == "xtkSession" && methodNameLC == "logon")
127
- return callContext.client.logon(argumentsList[0]);
128
- else if (namespace == "xtkSession" && methodNameLC == "logoff")
129
- return callContext.client.logoff();
130
- else if (namespace == "xtkSession" && methodNameLC == "getoption") {
131
- var promise = callContext.client._callMethod(methodName, callContext, argumentsList);
132
- return promise.then(function(optionAndValue) {
133
- const optionName = argumentsList[0];
134
- client._optionCache.put(optionName, optionAndValue);
135
- return optionAndValue;
136
- });
108
+ const clientHandler = (representation) => {
109
+ return {
110
+ get: function(client, namespace) {
111
+ // Force XML or JSON representation (NLWS.xml or NLWS.json)
112
+ if (namespace == "xml") return new Proxy(client, clientHandler("xml"));
113
+ if (namespace == "json") return new Proxy(client, clientHandler("SimpleJson"));
114
+
115
+ return new Proxy({ client:client, namespace:namespace}, {
116
+ get: function(callContext, methodName) {
117
+ callContext.representation = representation;
118
+ if (methodName == ".") return callContext;
119
+
120
+ // get Schema id from namespace (find first upper case letter)
121
+ var schemaId = "";
122
+ for (var i=0; i<namespace.length; i++) {
123
+ const c = namespace[i];
124
+ if (c >='A' && c<='Z') {
125
+ schemaId = schemaId + ":" + c.toLowerCase() + namespace.substr(i+1);
126
+ break;
127
+ }
128
+ schemaId = schemaId + c;
137
129
  }
138
- // static method
139
- var result = callContext.client._callMethod(methodName, callContext, argumentsList);
140
- return result;
141
- };
142
-
143
- if (methodName == "create") {
144
- return function(body) {
145
- callContext.object = body;
146
- return new Proxy(callContext, xtkObjectHandler);
130
+ callContext.schemaId = schemaId;
131
+
132
+ const caller = function(thisArg, argumentsList) {
133
+ const callContext = thisArg["."];
134
+ const namespace = callContext.namespace;
135
+ const methodNameLC = methodName.toLowerCase();
136
+ methodName = methodName.substr(0, 1).toUpperCase() + methodName.substr(1);
137
+ if (namespace == "xtkSession" && methodNameLC == "logon")
138
+ return callContext.client.logon(argumentsList[0]);
139
+ else if (namespace == "xtkSession" && methodNameLC == "logoff")
140
+ return callContext.client.logoff();
141
+ else if (namespace == "xtkSession" && methodNameLC == "getoption") {
142
+ var promise = callContext.client._callMethod(methodName, callContext, argumentsList);
143
+ return promise.then(function(optionAndValue) {
144
+ const optionName = argumentsList[0];
145
+ client._optionCache.put(optionName, optionAndValue);
146
+ return optionAndValue;
147
+ });
148
+ }
149
+ // static method
150
+ var result = callContext.client._callMethod(methodName, callContext, argumentsList);
151
+ return result;
147
152
  };
148
- }
149
153
 
150
- return new Proxy(caller, {
151
- apply: function(target, thisArg, argumentsList) {
152
- return target(thisArg, argumentsList);
153
- }
154
- });
155
- }
156
- });
157
- }
154
+ if (methodName == "create") {
155
+ return function(body) {
156
+ callContext.object = body;
157
+ return new Proxy(callContext, xtkObjectHandler);
158
+ };
159
+ }
160
+
161
+ return new Proxy(caller, {
162
+ apply: function(target, thisArg, argumentsList) {
163
+ return target(thisArg, argumentsList);
164
+ }
165
+ });
166
+ }
167
+ });
168
+ }
169
+ };
158
170
  };
159
171
 
160
172
  // ========================================================================================
@@ -477,7 +489,7 @@ class Client {
477
489
  this._entityCache = new XtkEntityCache(this._storage, `${rootKey}.XtkEntityCache`, connectionParameters._options.entityCacheTTL);
478
490
  this._methodCache = new MethodCache(this._storage, `${rootKey}.MethodCache`, connectionParameters._options.methodCacheTTL);
479
491
  this._optionCache = new OptionCache(this._storage, `${rootKey}.OptionCache`, connectionParameters._options.optionCacheTTL);
480
- this.NLWS = new Proxy(this, clientHandler);
492
+ this.NLWS = new Proxy(this, clientHandler());
481
493
 
482
494
  this._transport = connectionParameters._options.transport;
483
495
  this._traceAPICalls = connectionParameters._options.traceAPICalls;
@@ -1122,7 +1134,7 @@ class Client {
1122
1134
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Cannot call non-static method '${methodName}' of schema '${schemaId}' : no object was specified`);
1123
1135
 
1124
1136
  const rootName = schemaId.substr(schemaId.indexOf(':') + 1);
1125
- object = that._fromRepresentation(rootName, object);
1137
+ object = that._fromRepresentation(rootName, object, callContext.representation);
1126
1138
  soapCall.writeDocument("document", object);
1127
1139
  }
1128
1140
 
@@ -1170,7 +1182,7 @@ class Client {
1170
1182
  const index = xtkschema.indexOf(":");
1171
1183
  docName = xtkschema.substr(index+1);
1172
1184
  }
1173
- var xmlValue = that._fromRepresentation(docName, paramValue);
1185
+ var xmlValue = that._fromRepresentation(docName, paramValue, callContext.representation);
1174
1186
  if (type == "DOMDocument")
1175
1187
  soapCall.writeDocument(paramName, xmlValue);
1176
1188
  else
@@ -1189,7 +1201,7 @@ class Client {
1189
1201
  // the method is called. This is the new version of the object (in XML form)
1190
1202
  const entity = soapCall.getEntity();
1191
1203
  if (entity) {
1192
- callContext.object = that._toRepresentation(entity);
1204
+ callContext.object = that._toRepresentation(entity, callContext.representation);
1193
1205
  }
1194
1206
  }
1195
1207
 
@@ -1220,7 +1232,7 @@ class Client {
1220
1232
  returnValue = soapCall.getNextDate();
1221
1233
  else if (type == "DOMDocument") {
1222
1234
  returnValue = soapCall.getNextDocument();
1223
- returnValue = that._toRepresentation(returnValue);
1235
+ returnValue = that._toRepresentation(returnValue, callContext.representation);
1224
1236
  if (schemaId === "xtk:queryDef" && methodName === "ExecuteQuery" && paramName === "output") {
1225
1237
  // https://github.com/adobe/acc-js-sdk/issues/3
1226
1238
  // Check if query operation is "getIfExists". The "object" variable at this point
@@ -1240,7 +1252,7 @@ class Client {
1240
1252
  }
1241
1253
  else if (type == "DOMElement") {
1242
1254
  returnValue = soapCall.getNextElement();
1243
- returnValue = that._toRepresentation(returnValue);
1255
+ returnValue = that._toRepresentation(returnValue, callContext.representation);
1244
1256
  }
1245
1257
  else {
1246
1258
  // type can reference a schema element. The naming convension is that the type name
@@ -1254,7 +1266,7 @@ class Client {
1254
1266
  if (element.getAttribute("name") == shortTypeName) {
1255
1267
  // Type found in schema: Process as a DOM element
1256
1268
  returnValue = soapCall.getNextElement();
1257
- returnValue = that._toRepresentation(returnValue);
1269
+ returnValue = that._toRepresentation(returnValue, callContext.representation);
1258
1270
  break;
1259
1271
  }
1260
1272
  element = DomUtil.getNextSiblingElement(element, "element");
@@ -2283,15 +2283,15 @@ describe('ACC Client', function () {
2283
2283
  it("Should ignore protocol for local storage root key", async () => {
2284
2284
  var connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("http://acc-sdk:8080", "admin", "admin", {});
2285
2285
  var client = await sdk.init(connectionParameters);
2286
- expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.1.acc-sdk:8080.cache.OptionCache$");
2286
+ expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.2.acc-sdk:8080.cache.OptionCache$");
2287
2287
 
2288
2288
  connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("https://acc-sdk:8080", "admin", "admin", {});
2289
2289
  client = await sdk.init(connectionParameters);
2290
- expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.1.acc-sdk:8080.cache.OptionCache$");
2290
+ expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.2.acc-sdk:8080.cache.OptionCache$");
2291
2291
 
2292
2292
  connectionParameters = sdk.ConnectionParameters.ofUserAndPassword("acc-sdk:8080", "admin", "admin", {});
2293
2293
  client = await sdk.init(connectionParameters);
2294
- expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.1.acc-sdk:8080.cache.OptionCache$");
2294
+ expect(client._optionCache._storage._rootKey).toBe("acc.js.sdk.1.1.2.acc-sdk:8080.cache.OptionCache$");
2295
2295
  })
2296
2296
 
2297
2297
  it("Should support no storage", async () => {
@@ -2422,4 +2422,56 @@ describe('ACC Client', function () {
2422
2422
  expect(paramsFn.mock.calls[0][1]).toMatchObject({ schemaId: "xtk:session", namespace: "xtkSession" });
2423
2423
  });
2424
2424
  });
2425
+
2426
+ describe("Method-level representation", () => {
2427
+ it("Should force an xml representation", async () => {
2428
+ const client = await Mock.makeClient();
2429
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2430
+ await client.NLWS.xtkSession.logon();
2431
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
2432
+ client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
2433
+ const queryDef = DomUtil.parse(`
2434
+ <queryDef schema="nms:extAccount" operation="select">
2435
+ <select>
2436
+ <node expr="@id"/>
2437
+ <node expr="@name"/>
2438
+ </select>
2439
+ </queryDef>
2440
+ `);
2441
+ const query = client.NLWS.xml.xtkQueryDef.create(queryDef);
2442
+ const result = await query.executeQuery();
2443
+ const xml = DomUtil.toXMLString(result);
2444
+ expect(xml).toBe(`<extAccount-collection xmlns="urn:xtk:queryDef">
2445
+ <extAccount id="1816" name="defaultPopAccount"/>
2446
+ <extAccount id="1818" name="defaultOther"/>
2447
+ <extAccount id="1849" name="billingReport"/>
2448
+ <extAccount id="12070" name="TST_EXT_ACCOUNT_POSTGRESQL"/>
2449
+ <extAccount id="1817" name="defaultEmailBulk"/>
2450
+ <extAccount id="2087" name="ffda"/>
2451
+ <extAccount id="2088" name="defaultEmailMid"/>
2452
+ </extAccount-collection>`);
2453
+ });
2454
+
2455
+ it("Should force an json representation", async () => {
2456
+ const client = await Mock.makeClient();
2457
+ client._transport.mockReturnValueOnce(Mock.LOGON_RESPONSE);
2458
+ await client.NLWS.xtkSession.logon();
2459
+ client._transport.mockReturnValueOnce(Mock.GET_XTK_QUERY_SCHEMA_RESPONSE);
2460
+ client._transport.mockReturnValueOnce(Mock.GET_QUERY_EXECUTE_RESPONSE);
2461
+ const queryDef = {
2462
+ "schema": "nms:extAccount",
2463
+ "operation": "select",
2464
+ "select": {
2465
+ "node": [
2466
+ { "expr": "@id" },
2467
+ { "expr": "@name" }
2468
+ ]
2469
+ }
2470
+ };
2471
+ const query = client.NLWS.json.xtkQueryDef.create(queryDef);
2472
+ const result = await query.executeQuery();
2473
+ const json = JSON.stringify(result);
2474
+ expect(json).toBe('{"#text":[],"extAccount":[{"id":"1816","name":"defaultPopAccount"},{"id":"1818","name":"defaultOther"},{"id":"1849","name":"billingReport"},{"id":"12070","name":"TST_EXT_ACCOUNT_POSTGRESQL"},{"id":"1817","name":"defaultEmailBulk"},{"id":"2087","name":"ffda"},{"id":"2088","name":"defaultEmailMid"}]}');
2475
+ });
2476
+ });
2425
2477
  });