@eluvio/elv-client-js 4.0.89 → 4.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Utils.js CHANGED
@@ -545,18 +545,40 @@ const Utils = {
545
545
  });
546
546
  },
547
547
 
548
- ResponseToJson: async (response) => {
549
- return Utils.ResponseToFormat("json", response);
548
+ /**
549
+ * Interprets an http response body obtained from an http call as JSON and returns result of parsing it.
550
+ *
551
+ * @param {Promise} response - An http response from node-fetch
552
+ * @param {boolean=} debug - Whether or not to log the body
553
+ * @param {Function} logFn - Log function to use if debug is truthy
554
+ * @return {*} - Result of parsing response body as JSON
555
+ */
556
+ ResponseToJson: async (response, debug = false, logFn) => {
557
+ return await Utils.ResponseToFormat("json", response, debug, logFn);
550
558
  },
551
559
 
552
- ResponseToFormat: async (format, response) => {
560
+ /**
561
+ * Interprets an http response body obtained from an http call as a requested format and returns result of converting/formatting.
562
+ *
563
+ * @param {string} format - The format to use when interpreting response body (e.g. "json", "text" et. al.)
564
+ * @param {Promise} response - An http response from node-fetch
565
+ * @param {boolean=} debug - Whether or not to log a debug statement containing the body (ignored for formats other than "json" and "text")
566
+ * @param {Function} logFn - Log function to use if debug is truthy
567
+ * @return {*} - Result of converting response body into the requested format
568
+ */
569
+ ResponseToFormat: async (format, response, debug = false, logFn) => {
553
570
  response = await response;
571
+ let formattedBody;
554
572
 
555
573
  switch(format.toLowerCase()) {
556
574
  case "json":
557
- return await response.json();
575
+ formattedBody = await response.json();
576
+ if(debug) logFn(`response body: ${JSON.stringify(formattedBody, null, 2)}`);
577
+ return formattedBody;
558
578
  case "text":
559
- return await response.text();
579
+ formattedBody = await response.text();
580
+ if(debug) logFn(`response body: ${formattedBody}`);
581
+ return formattedBody;
560
582
  case "blob":
561
583
  return await response.blob();
562
584
  case "arraybuffer":
@@ -390,13 +390,11 @@ exports.ContentLibrary = async function({libraryId}) {
390
390
 
391
391
  const path = UrlJoin("qlibs", libraryId);
392
392
 
393
- const library = await this.utils.ResponseToJson(
394
- this.HttpClient.Request({
395
- headers: await this.authClient.AuthorizationHeader({libraryId}),
396
- method: "GET",
397
- path: path
398
- })
399
- );
393
+ const library = await this.HttpClient.RequestJsonBody({
394
+ headers: await this.authClient.AuthorizationHeader({libraryId}),
395
+ method: "GET",
396
+ path: path
397
+ });
400
398
 
401
399
  return {
402
400
  ...library,
@@ -566,14 +564,12 @@ exports.ContentObjects = async function({libraryId, filterOptions={}}) {
566
564
  this.Log("Filter options:");
567
565
  this.Log(filterOptions);
568
566
 
569
- return await this.utils.ResponseToJson(
570
- this.HttpClient.Request({
571
- headers: await this.authClient.AuthorizationHeader({libraryId}),
572
- method: "GET",
573
- path: path,
574
- queryParams
575
- })
576
- );
567
+ return await this.HttpClient.RequestJsonBody({
568
+ headers: await this.authClient.AuthorizationHeader({libraryId}),
569
+ method: "GET",
570
+ path: path,
571
+ queryParams
572
+ });
577
573
  };
578
574
 
579
575
  /**
@@ -597,13 +593,11 @@ exports.ContentObject = async function({libraryId, objectId, versionHash, writeT
597
593
 
598
594
  let path = UrlJoin("q", writeToken || versionHash || objectId);
599
595
 
600
- return await this.utils.ResponseToJson(
601
- this.HttpClient.Request({
602
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
603
- method: "GET",
604
- path: path
605
- })
606
- );
596
+ return await this.HttpClient.RequestJsonBody({
597
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
598
+ method: "GET",
599
+ path: path
600
+ });
607
601
  };
608
602
 
609
603
  /**
@@ -919,22 +913,20 @@ exports.ContentObjectMetadata = async function({
919
913
 
920
914
  let metadata;
921
915
  try {
922
- metadata = await this.utils.ResponseToJson(
923
- this.HttpClient.Request({
924
- headers: { "Authorization": authTokens.map(token => `Bearer ${token}`) },
925
- queryParams: {
926
- ...queryParams,
927
- select,
928
- remove,
929
- link_depth: linkDepthLimit,
930
- resolve: resolveLinks,
931
- resolve_include_source: resolveIncludeSource,
932
- resolve_ignore_errors: resolveIgnoreErrors,
933
- },
934
- method: "GET",
935
- path: path
936
- })
937
- );
916
+ metadata = await this.HttpClient.RequestJsonBody({
917
+ headers: { "Authorization": authTokens.map(token => `Bearer ${token}`) },
918
+ queryParams: {
919
+ ...queryParams,
920
+ select,
921
+ remove,
922
+ link_depth: linkDepthLimit,
923
+ resolve: resolveLinks,
924
+ resolve_include_source: resolveIncludeSource,
925
+ resolve_ignore_errors: resolveIgnoreErrors,
926
+ },
927
+ method: "GET",
928
+ path: path
929
+ });
938
930
  } catch(error) {
939
931
  if(error.status !== 404) {
940
932
  throw error;
@@ -1066,13 +1058,11 @@ exports.ContentObjectVersions = async function({libraryId, objectId}) {
1066
1058
 
1067
1059
  let path = UrlJoin("qid", objectId);
1068
1060
 
1069
- return this.utils.ResponseToJson(
1070
- this.HttpClient.Request({
1071
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId}),
1072
- method: "GET",
1073
- path: path
1074
- })
1075
- );
1061
+ return this.HttpClient.RequestJsonBody({
1062
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId}),
1063
+ method: "GET",
1064
+ path: path
1065
+ });
1076
1066
  };
1077
1067
 
1078
1068
  /**
@@ -1143,13 +1133,11 @@ exports.LatestVersionHashV2 = async function({objectId, versionHash}) {
1143
1133
  try {
1144
1134
  let path = UrlJoin("q", objectId);
1145
1135
 
1146
- let q = await this.utils.ResponseToJson(
1147
- this.HttpClient.Request({
1148
- headers: await this.authClient.AuthorizationHeader({objectId}),
1149
- method: "GET",
1150
- path: path
1151
- })
1152
- );
1136
+ let q = await this.HttpClient.RequestJsonBody({
1137
+ headers: await this.authClient.AuthorizationHeader({objectId}),
1138
+ method: "GET",
1139
+ path: path
1140
+ });
1153
1141
  latestHash = q.hash;
1154
1142
 
1155
1143
  } catch(error) {
@@ -1379,15 +1367,13 @@ exports.AvailableOfferings = async function({
1379
1367
  .flat()
1380
1368
  .filter(token => token);
1381
1369
 
1382
- return await this.utils.ResponseToJson(
1383
- this.HttpClient.Request({
1384
- path: path,
1385
- method: "GET",
1386
- headers: {
1387
- Authorization: `Bearer ${authorization.join(",")}`
1388
- }
1389
- })
1390
- );
1370
+ return await this.HttpClient.RequestJsonBody({
1371
+ path: path,
1372
+ method: "GET",
1373
+ headers: {
1374
+ Authorization: `Bearer ${authorization.join(",")}`
1375
+ }
1376
+ });
1391
1377
  } catch(error) {
1392
1378
  if(error.status && parseInt(error.status) === 500) {
1393
1379
  return {};
@@ -1526,13 +1512,11 @@ exports.PlayoutOptions = async function({
1526
1512
  };
1527
1513
 
1528
1514
  const playoutOptions = Object.values(
1529
- await this.utils.ResponseToJson(
1530
- this.HttpClient.Request({
1531
- path,
1532
- method: "GET",
1533
- queryParams
1534
- })
1535
- )
1515
+ await this.HttpClient.RequestJsonBody({
1516
+ path,
1517
+ method: "GET",
1518
+ queryParams
1519
+ })
1536
1520
  );
1537
1521
 
1538
1522
  if(!signedLink && linkTarget.versionHash) {
@@ -1638,17 +1622,14 @@ exports.PlayoutOptions = async function({
1638
1622
  playoutMap.multiview = true;
1639
1623
 
1640
1624
  playoutMap.AvailableViews = async () => {
1641
- return await this.utils.ResponseToFormat(
1642
- "json",
1643
- await this.HttpClient.Request({
1644
- path: UrlJoin("q", linkTarget.versionHash || versionHash, "rep", handler, offering, "views.json"),
1645
- method: "GET",
1646
- queryParams: {
1647
- sid: sessionId,
1648
- authorization
1649
- }
1650
- })
1651
- );
1625
+ return await this.HttpClient.RequestJsonBody({
1626
+ path: UrlJoin("q", linkTarget.versionHash || versionHash, "rep", handler, offering, "views.json"),
1627
+ method: "GET",
1628
+ queryParams: {
1629
+ sid: sessionId,
1630
+ authorization
1631
+ }
1632
+ });
1652
1633
  };
1653
1634
 
1654
1635
  playoutMap.SwitchView = async (view) => {
@@ -1882,7 +1863,9 @@ exports.CallBitcodeMethod = async function({
1882
1863
  path,
1883
1864
  queryParams,
1884
1865
  allowFailover: false
1885
- })
1866
+ }),
1867
+ this.HttpClient.debug,
1868
+ this.HttpClient.Log.bind(this.HttpClient)
1886
1869
  );
1887
1870
  };
1888
1871
 
@@ -183,8 +183,13 @@ exports.CreateContentType = async function({name, metadata={}, bitcode}) {
183
183
  path: path
184
184
  });
185
185
  // extract the url for the node that handled the request
186
+ // TODO: remove/simplify after we start using /nodes API call to get node URLs for write tokens
186
187
  const nodeUrl = (new URL(rawCreateResponse.url)).origin;
187
- const createResponse = await this.utils.ResponseToJson(rawCreateResponse);
188
+ const createResponse = await this.utils.ResponseToJson(
189
+ rawCreateResponse,
190
+ this.HttpClient.debug,
191
+ this.HttpClient.Log.bind(this.HttpClient)
192
+ );
188
193
 
189
194
  // Record the node used in creating this write token
190
195
  this.RecordWriteToken({writeToken: createResponse.write_token, fabricNodeUrl: nodeUrl});
@@ -602,8 +607,14 @@ exports.CreateContentObject = async function({libraryId, objectId, options={}})
602
607
  path: path,
603
608
  body: options
604
609
  });
610
+ // extract the url for the node that handled the request
611
+ // TODO: remove/simplify after we start using /nodes API call to get node URLs for write tokens
605
612
  const nodeUrl = (new URL(rawCreateResponse.url)).origin;
606
- const createResponse = await this.utils.ResponseToJson(rawCreateResponse);
613
+ const createResponse = await this.utils.ResponseToJson(
614
+ rawCreateResponse,
615
+ this.HttpClient.debug,
616
+ this.HttpClient.Log.bind(this.HttpClient)
617
+ );
607
618
 
608
619
  // Record the node used in creating this write token
609
620
  this.RecordWriteToken({writeToken: createResponse.write_token, fabricNodeUrl: nodeUrl});
@@ -773,8 +784,13 @@ exports.EditContentObject = async function({libraryId, objectId, options={}}) {
773
784
  body: options
774
785
  });
775
786
  // extract the url for the node that handled the request
787
+ // TODO: remove/simplify after we start using /nodes API call to get node URLs for write tokens
776
788
  const nodeUrl = (new URL(rawEditResponse.url)).origin;
777
- const editResponse = await this.utils.ResponseToJson(rawEditResponse);
789
+ const editResponse = await this.utils.ResponseToJson(
790
+ rawEditResponse,
791
+ this.HttpClient.debug,
792
+ this.HttpClient.Log.bind(this.HttpClient)
793
+ );
778
794
 
779
795
  // Record the node used in creating this write token
780
796
  this.RecordWriteToken({writeToken: editResponse.write_token, fabricNodeUrl: nodeUrl});
@@ -957,14 +973,12 @@ exports.FinalizeContentObject = async function({
957
973
 
958
974
  let path = UrlJoin("q", writeToken);
959
975
 
960
- const finalizeResponse = await this.utils.ResponseToJson(
961
- this.HttpClient.Request({
962
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
963
- method: "POST",
964
- path: path,
965
- allowFailover: false
966
- })
967
- );
976
+ const finalizeResponse = await this.HttpClient.RequestJsonBody({
977
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
978
+ method: "POST",
979
+ path: path,
980
+ allowFailover: false
981
+ });
968
982
 
969
983
  this.Log(`Finalized: ${finalizeResponse.hash}`);
970
984
 
@@ -1006,7 +1020,8 @@ exports.PublishContentVersion = async function({objectId, versionHash, awaitComm
1006
1020
  });
1007
1021
 
1008
1022
  const abi = await this.ContractAbi({id: objectId});
1009
- const fromBlock = commit.blockNumber + 1;
1023
+ const fromBlock = commit.blockNumber - 30; // due to block re-org
1024
+
1010
1025
  const objectHash = await this.ExtractValueFromEvent({
1011
1026
  abi,
1012
1027
  event: commit,
@@ -1035,6 +1050,7 @@ exports.PublishContentVersion = async function({objectId, versionHash, awaitComm
1035
1050
  contractAddress: this.utils.HashToAddress(objectId),
1036
1051
  abi,
1037
1052
  fromBlock,
1053
+ topics: [ Ethers.utils.id("VersionConfirm(address,address,string)") ],
1038
1054
  count: 1000
1039
1055
  });
1040
1056
 
@@ -1077,7 +1093,6 @@ exports.PublishContentVersion = async function({objectId, versionHash, awaitComm
1077
1093
  }
1078
1094
  }
1079
1095
  }
1080
-
1081
1096
  };
1082
1097
 
1083
1098
  /**
@@ -45,13 +45,11 @@ exports.ListFiles = async function({libraryId, objectId, path = "", versionHash,
45
45
 
46
46
  let urlPath = UrlJoin("q", writeToken || versionHash || objectId, "files_list", path);
47
47
 
48
- return this.utils.ResponseToJson(
49
- this.HttpClient.Request({
50
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
51
- method: "GET",
52
- path: urlPath,
53
- })
54
- );
48
+ return this.HttpClient.RequestJsonBody({
49
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
50
+ method: "GET",
51
+ path: urlPath,
52
+ });
55
53
  };
56
54
 
57
55
  /**
@@ -121,7 +119,11 @@ exports.UploadFilesFromS3 = async function({
121
119
  }
122
120
  }
123
121
 
124
- this.Log(`Uploading files from S3: ${libraryId} ${objectId} ${writeToken}`);
122
+ if(copy) {
123
+ this.Log(`Copying files from S3: ${libraryId} ${objectId} ${writeToken}`);
124
+ } else {
125
+ this.Log(`Adding links to files in S3: ${libraryId} ${objectId} ${writeToken}`);
126
+ }
125
127
 
126
128
  let encryption_key;
127
129
  if(encryption === "cgck") {
@@ -485,15 +487,13 @@ exports.CreateFileUploadJob = async function({libraryId, objectId, writeToken, o
485
487
 
486
488
  const path = UrlJoin("q", writeToken, "file_jobs");
487
489
 
488
- return this.utils.ResponseToJson(
489
- this.HttpClient.Request({
490
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true, encryption}),
491
- method: "POST",
492
- path: path,
493
- body,
494
- allowFailover: false
495
- })
496
- );
490
+ return this.HttpClient.RequestJsonBody({
491
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true, encryption}),
492
+ method: "POST",
493
+ path: path,
494
+ body,
495
+ allowFailover: false
496
+ });
497
497
  };
498
498
 
499
499
  exports.UploadStatus = async function({libraryId, objectId, writeToken, uploadId}) {
@@ -815,13 +815,11 @@ exports.ContentParts = async function({libraryId, objectId, versionHash}) {
815
815
 
816
816
  const path = UrlJoin("q", versionHash || objectId, "parts");
817
817
 
818
- const response = await this.utils.ResponseToJson(
819
- this.HttpClient.Request({
820
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
821
- method: "GET",
822
- path: path
823
- })
824
- );
818
+ const response = await this.HttpClient.RequestJsonBody({
819
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
820
+ method: "GET",
821
+ path: path
822
+ });
825
823
 
826
824
  return response.parts;
827
825
  };
@@ -849,13 +847,11 @@ exports.ContentPart = async function({libraryId, objectId, versionHash, partHash
849
847
 
850
848
  let path = UrlJoin("q", versionHash || objectId, "parts", partHash);
851
849
 
852
- return await this.utils.ResponseToJson(
853
- this.HttpClient.Request({
854
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
855
- method: "GET",
856
- path: path
857
- })
858
- );
850
+ return await this.HttpClient.RequestJsonBody({
851
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, versionHash}),
852
+ method: "GET",
853
+ path: path
854
+ });
859
855
  };
860
856
 
861
857
  /**
@@ -1079,16 +1075,14 @@ exports.CreatePart = async function({libraryId, objectId, writeToken, encryption
1079
1075
 
1080
1076
  const path = UrlJoin("q", writeToken, "parts");
1081
1077
 
1082
- const openResponse = await this.utils.ResponseToJson(
1083
- this.HttpClient.Request({
1084
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true, encryption}),
1085
- method: "POST",
1086
- path,
1087
- bodyType: "BINARY",
1088
- body: "",
1089
- allowFailover: false
1090
- })
1091
- );
1078
+ const openResponse = await this.HttpClient.RequestJsonBody({
1079
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true, encryption}),
1080
+ method: "POST",
1081
+ path,
1082
+ bodyType: "BINARY",
1083
+ body: "",
1084
+ allowFailover: false
1085
+ });
1092
1086
 
1093
1087
  return openResponse.part.write_token;
1094
1088
  };
@@ -1149,16 +1143,14 @@ exports.FinalizePart = async function({libraryId, objectId, writeToken, partWrit
1149
1143
  ValidateWriteToken(writeToken);
1150
1144
 
1151
1145
  const path = UrlJoin("q", writeToken, "parts");
1152
- return await this.utils.ResponseToJson(
1153
- await this.HttpClient.Request({
1154
- headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true, encryption}),
1155
- method: "POST",
1156
- path: UrlJoin(path, partWriteToken),
1157
- bodyType: "BINARY",
1158
- body: "",
1159
- allowFailover: false
1160
- })
1161
- );
1146
+ return await this.HttpClient.RequestJsonBody({
1147
+ headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true, encryption}),
1148
+ method: "POST",
1149
+ path: UrlJoin(path, partWriteToken),
1150
+ bodyType: "BINARY",
1151
+ body: "",
1152
+ allowFailover: false
1153
+ });
1162
1154
  };
1163
1155
 
1164
1156
  /**
@@ -1350,7 +1350,11 @@ exports.StreamConfig = async function({name, customSettings={}, probeMetadata})
1350
1350
  status.user_config = userConfig;
1351
1351
 
1352
1352
  // Get node URI from user config
1353
- const hostName = userConfig.url.replace("udp://", "").replace("rtmp://", "").replace("srt://", "").split(":")[0];
1353
+ const parsedName = userConfig.url
1354
+ .replace("udp://", "https://")
1355
+ .replace("rtmp://", "https://")
1356
+ .replace("srt://", "https://");
1357
+ const hostName = new URL(parsedName).hostname;
1354
1358
  const streamUrl = new URL(userConfig.url);
1355
1359
 
1356
1360
  console.log("Retrieving nodes - matching", hostName);
@@ -0,0 +1,93 @@
1
+ /* eslint-disable no-console */
2
+
3
+ const { ElvClient } = require("../src/ElvClient");
4
+
5
+ const configUrl = "https://test.net955205.contentfabric.io/config";
6
+ const libraryId = "ilibE6vhm2YCR6vZCtW9mope6Dbo2Tn"; // to create and edit content
7
+
8
+ const Tool = async () => {
9
+
10
+ const client = await ElvClient.FromConfigurationUrl({configUrl});
11
+
12
+ let wallet = client.GenerateWallet();
13
+ let signer = wallet.AddAccount({
14
+ privateKey: process.env.PRIVATE_KEY
15
+ });
16
+
17
+ client.SetSigner({signer});
18
+ client.ToggleLogging(true);
19
+
20
+
21
+ try {
22
+ let start = new Date().getTime();
23
+ const {objectId, writeToken} = await client.CreateContentObject({
24
+ libraryId: libraryId,
25
+ options: {
26
+ meta: {commit: "Create Content-" + start.toString()}
27
+ }
28
+ });
29
+ let end = new Date().getTime();
30
+ let timeDifference = end - start;
31
+ console.log("content object completed after: ", timeDifference, "ms");
32
+
33
+ start = new Date().getTime();
34
+ const {hash} = await client.FinalizeContentObject({
35
+ libraryId,
36
+ objectId,
37
+ writeToken
38
+ });
39
+ end = new Date();
40
+ timeDifference = end - start;
41
+ console.log("finalize object completed after: ", timeDifference, "ms");
42
+
43
+ start = new Date().getTime();
44
+ const editResponse = await client.EditContentObject({
45
+ libraryId,
46
+ objectId,
47
+ });
48
+ end = new Date().getTime();
49
+ timeDifference = end - start;
50
+ console.log("edit object completed after: ", timeDifference, "ms");
51
+
52
+ const metadata = {
53
+ description: "edit content",
54
+ };
55
+
56
+ start = new Date().getTime();
57
+ await client.ReplaceMetadata({
58
+ libraryId,
59
+ objectId,
60
+ writeToken: editResponse.write_token,
61
+ metadata
62
+ });
63
+ end = new Date().getTime();
64
+ timeDifference = end - start;
65
+ console.log("replace metadata completed after: ", timeDifference, "ms");
66
+
67
+
68
+ start = new Date().getTime();
69
+ await client.FinalizeContentObject({
70
+ libraryId,
71
+ objectId,
72
+ writeToken: editResponse.write_token,
73
+ });
74
+ end = new Date().getTime();
75
+ timeDifference = end - start;
76
+ console.log("finalize object completed after: ", timeDifference, "ms");
77
+
78
+ console.log(`\nSuccessfully created new content version: ${hash}`);
79
+ } catch(error) {
80
+ console.error("Error creating content object:");
81
+ console.error(error);
82
+ }
83
+ };
84
+
85
+ const privateKey = process.env.PRIVATE_KEY;
86
+ if(!privateKey) {
87
+ console.error("PRIVATE_KEY environment variable must be specified");
88
+ return;
89
+ }
90
+
91
+ Tool();
92
+
93
+