@eluvio/elv-client-js 3.2.44 → 3.2.45

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.
@@ -1246,7 +1246,7 @@ var ElvWalletClient = /*#__PURE__*/function () {
1246
1246
  return this.client.ContentObjectMetadata({
1247
1247
  versionHash: marketplaceHash,
1248
1248
  metadataSubtree: "public/asset_metadata/info",
1249
- linkDepthLimit: 2,
1249
+ linkDepthLimit: 1,
1250
1250
  resolveLinks: true,
1251
1251
  resolveIgnoreErrors: true,
1252
1252
  resolveIncludeSource: true,
@@ -1432,7 +1432,11 @@ var ElvWalletClient = /*#__PURE__*/function () {
1432
1432
  start: start,
1433
1433
  limit: limit,
1434
1434
  sort_descending: sortDesc
1435
- };
1435
+ }; // Created isn't a valid sort mode for owned
1436
+
1437
+ if (mode === "owned" && sortBy === "created") {
1438
+ sortBy = "default";
1439
+ }
1436
1440
 
1437
1441
  if (mode !== "leaderboard") {
1438
1442
  params.sort_by = sortBy;
@@ -1443,33 +1447,33 @@ var ElvWalletClient = /*#__PURE__*/function () {
1443
1447
  }
1444
1448
 
1445
1449
  if (!marketplaceParams) {
1446
- _context16.next = 13;
1450
+ _context16.next = 14;
1447
1451
  break;
1448
1452
  }
1449
1453
 
1450
- _context16.next = 8;
1454
+ _context16.next = 9;
1451
1455
  return this.MarketplaceInfo({
1452
1456
  marketplaceParams: marketplaceParams
1453
1457
  });
1454
1458
 
1455
- case 8:
1459
+ case 9:
1456
1460
  marketplaceInfo = _context16.sent;
1457
1461
 
1458
1462
  if (!(collectionIndexes.length > 0)) {
1459
- _context16.next = 13;
1463
+ _context16.next = 14;
1460
1464
  break;
1461
1465
  }
1462
1466
 
1463
- _context16.next = 12;
1467
+ _context16.next = 13;
1464
1468
  return this.Marketplace({
1465
1469
  marketplaceParams: marketplaceParams
1466
1470
  });
1467
1471
 
1468
- case 12:
1472
+ case 13:
1469
1473
  marketplace = _context16.sent;
1470
1474
 
1471
- case 13:
1472
- _context16.prev = 13;
1475
+ case 14:
1476
+ _context16.prev = 14;
1473
1477
  filters = [];
1474
1478
 
1475
1479
  if (sellerAddress) {
@@ -1584,87 +1588,87 @@ var ElvWalletClient = /*#__PURE__*/function () {
1584
1588
  }
1585
1589
 
1586
1590
  _context16.t0 = mode;
1587
- _context16.next = _context16.t0 === "owned" ? 28 : _context16.t0 === "listings" ? 30 : _context16.t0 === "transfers" ? 32 : _context16.t0 === "sales" ? 36 : _context16.t0 === "listing-stats" ? 40 : _context16.t0 === "sales-stats" ? 42 : _context16.t0 === "leaderboard" ? 45 : 47;
1591
+ _context16.next = _context16.t0 === "owned" ? 29 : _context16.t0 === "listings" ? 31 : _context16.t0 === "transfers" ? 33 : _context16.t0 === "sales" ? 37 : _context16.t0 === "listing-stats" ? 41 : _context16.t0 === "sales-stats" ? 43 : _context16.t0 === "leaderboard" ? 46 : 48;
1588
1592
  break;
1589
1593
 
1590
- case 28:
1594
+ case 29:
1591
1595
  path = UrlJoin("as", "wlt", userAddress || this.UserAddress());
1592
- return _context16.abrupt("break", 47);
1596
+ return _context16.abrupt("break", 48);
1593
1597
 
1594
- case 30:
1598
+ case 31:
1595
1599
  path = UrlJoin("as", "mkt", "f");
1596
- return _context16.abrupt("break", 47);
1600
+ return _context16.abrupt("break", 48);
1597
1601
 
1598
- case 32:
1602
+ case 33:
1599
1603
  path = UrlJoin("as", "mkt", "hst", "f");
1600
1604
  filters.push("action:eq:TRANSFERRED");
1601
1605
  filters.push("action:eq:SOLD");
1602
- return _context16.abrupt("break", 47);
1606
+ return _context16.abrupt("break", 48);
1603
1607
 
1604
- case 36:
1608
+ case 37:
1605
1609
  path = UrlJoin("as", "mkt", "hst", "f");
1606
1610
  filters.push("action:eq:SOLD");
1607
1611
  filters.push("seller:co:0x");
1608
- return _context16.abrupt("break", 47);
1612
+ return _context16.abrupt("break", 48);
1609
1613
 
1610
- case 40:
1614
+ case 41:
1611
1615
  path = UrlJoin("as", "mkt", "stats", "listed");
1612
- return _context16.abrupt("break", 47);
1616
+ return _context16.abrupt("break", 48);
1613
1617
 
1614
- case 42:
1618
+ case 43:
1615
1619
  path = UrlJoin("as", "mkt", "stats", "sold");
1616
1620
  filters.push("seller:co:0x");
1617
- return _context16.abrupt("break", 47);
1621
+ return _context16.abrupt("break", 48);
1618
1622
 
1619
- case 45:
1623
+ case 46:
1620
1624
  path = UrlJoin("as", "wlt", "leaders");
1621
- return _context16.abrupt("break", 47);
1625
+ return _context16.abrupt("break", 48);
1622
1626
 
1623
- case 47:
1627
+ case 48:
1624
1628
  if (filters.length > 0) {
1625
1629
  params.filter = filters;
1626
1630
  }
1627
1631
 
1628
1632
  if (!mode.includes("stats")) {
1629
- _context16.next = 52;
1633
+ _context16.next = 53;
1630
1634
  break;
1631
1635
  }
1632
1636
 
1633
- _context16.next = 51;
1637
+ _context16.next = 52;
1634
1638
  return Utils.ResponseToJson(this.client.authClient.MakeAuthServiceRequest({
1635
1639
  path: path,
1636
1640
  method: "GET",
1637
1641
  queryParams: params
1638
1642
  }));
1639
1643
 
1640
- case 51:
1644
+ case 52:
1641
1645
  return _context16.abrupt("return", _context16.sent);
1642
1646
 
1643
- case 52:
1647
+ case 53:
1644
1648
  _context16.t2 = Utils;
1645
- _context16.next = 55;
1649
+ _context16.next = 56;
1646
1650
  return this.client.authClient.MakeAuthServiceRequest({
1647
1651
  path: path,
1648
1652
  method: "GET",
1649
1653
  queryParams: params
1650
1654
  });
1651
1655
 
1652
- case 55:
1656
+ case 56:
1653
1657
  _context16.t3 = _context16.sent;
1654
- _context16.next = 58;
1658
+ _context16.next = 59;
1655
1659
  return _context16.t2.ResponseToJson.call(_context16.t2, _context16.t3);
1656
1660
 
1657
- case 58:
1661
+ case 59:
1658
1662
  _context16.t1 = _context16.sent;
1659
1663
 
1660
1664
  if (_context16.t1) {
1661
- _context16.next = 61;
1665
+ _context16.next = 62;
1662
1666
  break;
1663
1667
  }
1664
1668
 
1665
1669
  _context16.t1 = [];
1666
1670
 
1667
- case 61:
1671
+ case 62:
1668
1672
  _ref16 = _context16.t1;
1669
1673
  contents = _ref16.contents;
1670
1674
  paging = _ref16.paging;
@@ -1680,12 +1684,12 @@ var ElvWalletClient = /*#__PURE__*/function () {
1680
1684
  })
1681
1685
  });
1682
1686
 
1683
- case 67:
1684
- _context16.prev = 67;
1685
- _context16.t4 = _context16["catch"](13);
1687
+ case 68:
1688
+ _context16.prev = 68;
1689
+ _context16.t4 = _context16["catch"](14);
1686
1690
 
1687
1691
  if (!(_context16.t4.status && _context16.t4.status.toString() === "404")) {
1688
- _context16.next = 71;
1692
+ _context16.next = 72;
1689
1693
  break;
1690
1694
  }
1691
1695
 
@@ -1699,15 +1703,15 @@ var ElvWalletClient = /*#__PURE__*/function () {
1699
1703
  results: []
1700
1704
  });
1701
1705
 
1702
- case 71:
1706
+ case 72:
1703
1707
  throw _context16.t4;
1704
1708
 
1705
- case 72:
1709
+ case 73:
1706
1710
  case "end":
1707
1711
  return _context16.stop();
1708
1712
  }
1709
1713
  }
1710
- }, _callee16, this, [[13, 67]]);
1714
+ }, _callee16, this, [[14, 68]]);
1711
1715
  }));
1712
1716
 
1713
1717
  function FilteredQuery() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eluvio/elv-client-js",
3
- "version": "3.2.44",
3
+ "version": "3.2.45",
4
4
  "description": "Javascript client for the Eluvio Content Fabric",
5
5
  "main": "src/index.js",
6
6
  "author": "Kevin Talmadge",
package/src/HttpClient.js CHANGED
@@ -22,8 +22,8 @@ class HttpClient {
22
22
  return Fetch(url, params);
23
23
  }
24
24
 
25
- RecordWriteToken(writeToken) {
26
- this.draftURIs[writeToken] = this.BaseURI();
25
+ RecordWriteToken(writeToken, nodeUrlStr) {
26
+ this.draftURIs[writeToken] = nodeUrlStr ? new URI(nodeUrlStr) : this.BaseURI();
27
27
  }
28
28
 
29
29
  RequestHeaders(bodyType, headers={}) {
@@ -54,7 +54,7 @@ class HttpClient {
54
54
  let baseURI = this.BaseURI();
55
55
 
56
56
  // If URL contains a write token, it must go to the correct server and can not fail over
57
- const writeTokenMatch = path.replace(/^\//, "").match(/(qlibs\/ilib[a-zA-Z0-9]+|q|qid)\/(tqw_[a-zA-Z0-9]+)/);
57
+ const writeTokenMatch = path.replace(/^\//, "").match(/(qlibs\/ilib[a-zA-Z0-9]+|q|qid)\/(tqw__[a-zA-Z0-9]+)/);
58
58
  const writeToken = writeTokenMatch ? writeTokenMatch[2] : undefined;
59
59
 
60
60
  if(writeToken) {
@@ -34,6 +34,8 @@ const {
34
34
  * @param {boolean=} encrypt=true - (Local or copied files only) - Unless `false` is passed in explicitly, any uploaded/copied files will be stored encrypted
35
35
  * @param {boolean=} copy=false - (S3) If specified, files will be copied from S3
36
36
  * @param {function=} callback - Progress callback for file upload (See UploadFiles/UploadFilesFromS3 method)
37
+ * @param {("warn"|"info"|"debug")=} respLogLevel=warn - The level of logging to return in http response
38
+ * @param {("none"|"error"|"warn"|"info"|"debug")=} structLogLevel=none - The level of logging to save to object metadata
37
39
  * @param {Array<Object>=} access=[] - Array of cloud credentials, along with path matching regex strings - Required if any files in the masters are cloud references (currently only AWS S3 is supported)
38
40
  * - If this parameter is non-empty, all items in fileInfo are assumed to be items in cloud storage
39
41
  * - Format: [
@@ -76,7 +78,9 @@ exports.CreateProductionMaster = async function({
76
78
  encrypt=true,
77
79
  access=[],
78
80
  copy=false,
79
- callback
81
+ callback,
82
+ respLogLevel = "warn",
83
+ structLogLevel="none"
80
84
  }) {
81
85
  ValidateLibrary(libraryId);
82
86
 
@@ -174,6 +178,10 @@ exports.CreateProductionMaster = async function({
174
178
  objectId: id,
175
179
  writeToken: write_token,
176
180
  method: UrlJoin("media", "production_master", "init"),
181
+ queryParams: {
182
+ response_log_level: respLogLevel,
183
+ struct_log_level: structLogLevel
184
+ },
177
185
  body: {
178
186
  access
179
187
  },
@@ -215,20 +223,25 @@ exports.CreateProductionMaster = async function({
215
223
  };
216
224
 
217
225
  /**
218
- * Create a mezzanine of the given master content object
226
+ * Create (or edit) a mezzanine offering based on the a given master content object version and variant key
219
227
  *
220
228
  * @methodGroup ABR Publishing
221
229
  * @namedParams
230
+ * @param {Object=} abrProfile - Custom ABR profile. If not specified, the profile of the mezzanine library will be used
231
+ * @param {Object=} addlOfferingSpecs - Specs for additional offerings to create by patching the offering being created/edited
232
+ * @param {string=} description - Description for mezzanine content object
233
+ * @param {boolean=} keepOtherStreams=false - If objectId is specified, whether to preserve existing streams with keys other than the ones specified in production master
222
234
  * @param {string} libraryId - ID of the mezzanine library
235
+ * @param {string} masterVersionHash - The version hash of the production master content object
236
+ * @param {Object=} metadata - Additional metadata for mezzanine content object
237
+ * @param {string} name - Name for mezzanine content object
223
238
  * @param {string=} objectId - ID of existing object (if not specified, new object will be created)
239
+ * @param {string=} offeringKey=default - The key of the offering to create
240
+ * @param {("warn"|"info"|"debug")=} respLogLevel=warn - The level of logging to return in http response
241
+ * @param {("none"|"error"|"warn"|"info"|"debug")=} structLogLevel=none - The level of logging to save to object metadata
242
+ * @param {Array<string>} streamKeys - List of stream keys from variant to include. If not supplied all streams will be included.
224
243
  * @param {string=} type - ID or version hash of the content type for the mezzanine
225
- * @param {string} name - Name for mezzanine content object
226
- * @param {string=} description - Description for mezzanine content object
227
- * @param {Object=} metadata - Additional metadata for mezzanine content object
228
- * @param {string} masterVersionHash - The version hash of the production master content object
229
244
  * @param {string=} variant=default - What variant of the master content object to use
230
- * @param {string=} offeringKey=default - The key of the offering to create
231
- * @param {Object=} abrProfile - Custom ABR profile. If not specified, the profile of the mezzanine library will be used
232
245
  *
233
246
  * @return {Object} - The finalize response for the object, as well as logs, warnings and errors from the mezzanine initialization
234
247
  */
@@ -241,8 +254,13 @@ exports.CreateABRMezzanine = async function({
241
254
  metadata,
242
255
  masterVersionHash,
243
256
  abrProfile,
257
+ addlOfferingSpecs,
244
258
  variant="default",
245
- offeringKey="default"
259
+ offeringKey="default",
260
+ keepOtherStreams= false,
261
+ respLogLevel = "warn",
262
+ structLogLevel="none",
263
+ streamKeys
246
264
  }) {
247
265
  ValidateLibrary(libraryId);
248
266
  ValidateVersion(masterVersionHash);
@@ -251,6 +269,14 @@ exports.CreateABRMezzanine = async function({
251
269
  throw Error("Master version hash not specified");
252
270
  }
253
271
 
272
+ if(!objectId && (keepOtherStreams)) {
273
+ throw Error("Existing mezzanine object ID required in order to use 'keepOtherStreams'");
274
+ }
275
+
276
+ if(addlOfferingSpecs && !abrProfile) {
277
+ throw Error("abrProfile required when using addlOfferingSpecs");
278
+ }
279
+
254
280
  const existingMez = !!objectId;
255
281
 
256
282
  let options = type ? { type } : {};
@@ -295,9 +321,12 @@ exports.CreateABRMezzanine = async function({
295
321
  };
296
322
 
297
323
  const body = {
324
+ additional_offering_specs: addlOfferingSpecs,
298
325
  offering_key: offeringKey,
299
- variant_key: variant,
300
- prod_master_hash: masterVersionHash
326
+ keep_other_streams: keepOtherStreams,
327
+ prod_master_hash: masterVersionHash,
328
+ stream_keys: streamKeys,
329
+ variant_key: variant
301
330
  };
302
331
 
303
332
  let storeClear = false;
@@ -327,6 +356,10 @@ exports.CreateABRMezzanine = async function({
327
356
  objectId: id,
328
357
  writeToken: write_token,
329
358
  method: UrlJoin("media", "abr_mezzanine", "init"),
359
+ queryParams: {
360
+ response_log_level: respLogLevel,
361
+ struct_log_level: structLogLevel
362
+ },
330
363
  headers,
331
364
  body,
332
365
  constant: false
@@ -551,26 +584,14 @@ exports.LROStatus = async function({libraryId, objectId, offeringKey="default"})
551
584
  }
552
585
  }
553
586
 
554
- let error, result;
555
- const fabricURIs = this.fabricURIs;
556
- try {
557
- this.SetNodes({fabricURIs: [lroDraft.node, ...fabricURIs]});
558
-
559
- result = await this.ContentObjectMetadata({
560
- libraryId,
561
- objectId,
562
- writeToken: lroDraft.write_token,
563
- metadataSubtree: "lro_status"
564
- });
565
- } catch(err) {
566
- error = err;
567
- } finally {
568
- this.SetNodes({fabricURIs});
569
- }
587
+ this.HttpClient.RecordWriteToken(lroDraft.write_token, lroDraft.node);
570
588
 
571
- if(error) { throw error; }
572
-
573
- return result;
589
+ return await this.ContentObjectMetadata({
590
+ libraryId,
591
+ objectId,
592
+ writeToken: lroDraft.write_token,
593
+ metadataSubtree: "lro_status"
594
+ });
574
595
  };
575
596
 
576
597
  /**
@@ -582,10 +603,12 @@ exports.LROStatus = async function({libraryId, objectId, offeringKey="default"})
582
603
  * @param {string} objectId - ID of the mezzanine object
583
604
  * @param {string} writeToken - Write token for the mezzanine object
584
605
  * @param {string=} offeringKey=default - The offering to process
606
+ * @param {function=} preFinalizeFn - A function to call before finalizing changes, to allow further modifications to offering. The function will be invoked with {elvClient, nodeUrl, writeToken} to allow access to the draft and MUST NOT finalize the draft.
607
+ * @param {boolean=} preFinalizeThrow - If set to `true` then any error thrown by preFinalizeFn will not be caught. Otherwise, any exception will be appended to the `warnings` array returned after finalization.
585
608
  *
586
609
  * @return {Promise<Object>} - The finalize response for the mezzanine object, as well as any logs, warnings and errors from the finalization
587
610
  */
588
- exports.FinalizeABRMezzanine = async function({libraryId, objectId, offeringKey="default"}) {
611
+ exports.FinalizeABRMezzanine = async function({libraryId, objectId, offeringKey="default", preFinalizeFn, preFinalizeThrow}) {
589
612
  ValidateParameters({libraryId, objectId});
590
613
 
591
614
  const lroDraft = await this.ContentObjectMetadata({
@@ -632,6 +655,22 @@ exports.FinalizeABRMezzanine = async function({libraryId, objectId, offeringKey=
632
655
  constant: false
633
656
  });
634
657
 
658
+ let preFinalizeWarnings = [];
659
+ if(preFinalizeFn) {
660
+ const params = {
661
+ elvClient: this,
662
+ nodeUrl: lroDraft.node,
663
+ writeToken: lroDraft.write_token
664
+ };
665
+ if(preFinalizeThrow){
666
+ await preFinalizeFn(params);
667
+ } else try {
668
+ await preFinalizeFn(params);
669
+ } catch(e) {
670
+ preFinalizeWarnings = `Error trying to set video stream codec descriptors: ${e}`;
671
+ }
672
+ }
673
+
635
674
  const finalizeResponse = await this.FinalizeContentObject({
636
675
  libraryId,
637
676
  objectId: objectId,
@@ -643,7 +682,7 @@ exports.FinalizeABRMezzanine = async function({libraryId, objectId, offeringKey=
643
682
  result = {
644
683
  data,
645
684
  logs: logs || [],
646
- warnings: warnings || [],
685
+ warnings: (warnings || []).concat(preFinalizeWarnings),
647
686
  errors: errors || [],
648
687
  ...finalizeResponse
649
688
  };
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  const UrlJoin = require("url-join");
8
+ const objectPath = require("object-path");
8
9
 
9
10
  const HttpClient = require("../HttpClient");
10
11
 
@@ -581,17 +582,18 @@ exports.ContentObjects = async function({libraryId, filterOptions={}}) {
581
582
  * @param {string=} libraryId - ID of the library
582
583
  * @param {string=} objectId - ID of the object
583
584
  * @param {string=} versionHash - Version hash of the object -- if not specified, latest version is returned
585
+ * @param {string=} writeToken - Write token for an object draft -- if supplied, versionHash will be ignored
584
586
  *
585
587
  * @returns {Promise<Object>} - Description of content object
586
588
  */
587
- exports.ContentObject = async function({libraryId, objectId, versionHash}) {
589
+ exports.ContentObject = async function({libraryId, objectId, versionHash, writeToken}) {
588
590
  ValidateParameters({libraryId, objectId, versionHash});
589
591
 
590
- this.Log(`Retrieving content object: ${libraryId || ""} ${objectId || versionHash}`);
592
+ this.Log(`Retrieving content object: ${libraryId || ""} ${writeToken || versionHash || objectId}`);
591
593
 
592
594
  if(versionHash) { objectId = this.utils.DecodeVersionHash(versionHash).objectId; }
593
595
 
594
- let path = UrlJoin("q", versionHash || objectId);
596
+ let path = UrlJoin("q", writeToken || versionHash || objectId);
595
597
 
596
598
  return await this.utils.ResponseToJson(
597
599
  this.HttpClient.Request({
@@ -925,8 +927,17 @@ exports.ContentObjectMetadata = async function({
925
927
  if(error.status !== 404) {
926
928
  throw error;
927
929
  }
928
-
929
- metadata = metadataSubtree === "/" ? {} : undefined;
930
+ // For a 404 error, check if error was due to write token not found
931
+ const errQwtoken = objectPath.get(error.body, "errors[0].cause.cause.cause.qwtoken");
932
+ if(errQwtoken) {
933
+ // if so, re-throw rather than suppress error
934
+ throw error;
935
+ } else {
936
+ // For all other 404 errors (not just 'subtree not found'), suppress error and
937
+ // return an empty value. (there are function call chains that depend on this behavior,
938
+ // e.g. CreateABRMezzanine -> CreateEncryptionConk -> ContentObjectMetadata)
939
+ metadata = metadataSubtree === "/" ? {} : undefined;
940
+ }
930
941
  }
931
942
 
932
943
  if(!produceLinkUrls) { return metadata; }
@@ -750,7 +750,7 @@ exports.CreateNonOwnerCap = async function({objectId, libraryId, publicKey, writ
750
750
  * meta: New metadata for the object - will be merged into existing metadata if specified
751
751
  * type: New type for the object - Object ID, version hash or name of type
752
752
  *
753
- * @returns {Promise<object>} - Response containing the object ID and write token of the draft
753
+ * @returns {Promise<object>} - Response containing the object ID and write token of the draft, as well as URL of node handling the draft
754
754
  */
755
755
  exports.EditContentObject = async function({libraryId, objectId, options={}}) {
756
756
  ValidateParameters({libraryId, objectId});
@@ -774,20 +774,27 @@ exports.EditContentObject = async function({libraryId, objectId, options={}}) {
774
774
 
775
775
  let path = UrlJoin("qid", objectId);
776
776
 
777
- let editResponse = await this.utils.ResponseToJson(
778
- this.HttpClient.Request({
779
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
780
- method: "POST",
781
- path: path,
782
- body: options
783
- })
784
- );
777
+ const rawEditResponse = await this.HttpClient.Request({
778
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
779
+ method: "POST",
780
+ path: path,
781
+ body: options
782
+ });
783
+
784
+ const actualUrl = new URL(rawEditResponse.url);
785
+ actualUrl.pathname = "";
786
+ actualUrl.search = "";
787
+ actualUrl.hash = "";
788
+ const nodeUrl = actualUrl.href;
789
+
790
+ let editResponse = await this.utils.ResponseToJson(rawEditResponse);
785
791
 
786
792
  // Record the node used in creating this write token
787
- this.HttpClient.RecordWriteToken(editResponse.write_token);
793
+ this.HttpClient.RecordWriteToken(editResponse.write_token, nodeUrl);
788
794
 
789
795
  editResponse.writeToken = editResponse.write_token;
790
796
  editResponse.objectId = editResponse.id;
797
+ editResponse.nodeUrl = nodeUrl;
791
798
 
792
799
  return editResponse;
793
800
  };