@eluvio/elv-client-js 4.0.78 → 4.0.79
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/dist/ElvClient-min.js +5 -5
- package/dist/ElvClient-node-min.js +9 -9
- package/dist/ElvFrameClient-min.js +2 -2
- package/dist/ElvWalletClient-min.js +7 -7
- package/dist/ElvWalletClient-node-min.js +9 -9
- package/dist/src/FrameClient.js +1 -1
- package/dist/src/HttpClient.js +15 -7
- package/dist/src/UserProfileClient.js +36 -71
- package/dist/src/client/AccessGroups.js +39 -35
- package/dist/src/client/ContentAccess.js +1 -1
- package/dist/src/client/ContentManagement.js +100 -40
- package/dist/src/client/Contracts.js +268 -4
- package/dist/src/client/LiveStream.js +239 -210
- package/package.json +1 -1
- package/src/FrameClient.js +2 -1
- package/src/HttpClient.js +6 -0
- package/src/UserProfileClient.js +9 -38
- package/src/client/AccessGroups.js +19 -24
- package/src/client/ContentAccess.js +1 -1
- package/src/client/ContentManagement.js +44 -22
- package/src/client/Contracts.js +157 -2
- package/src/client/LiveStream.js +146 -128
- package/testScripts/TestAddTenantContractId.js +87 -0
package/src/client/LiveStream.js
CHANGED
|
@@ -767,8 +767,7 @@ exports.StreamStartOrStopOrReset = async function({name, op}) {
|
|
|
767
767
|
};
|
|
768
768
|
|
|
769
769
|
/**
|
|
770
|
-
*
|
|
771
|
-
* Not implemented fully
|
|
770
|
+
* Close the edge write token and make the stream object inactive.
|
|
772
771
|
*
|
|
773
772
|
* @methodGroup Live Stream
|
|
774
773
|
* @namedParams
|
|
@@ -778,8 +777,7 @@ exports.StreamStartOrStopOrReset = async function({name, op}) {
|
|
|
778
777
|
*/
|
|
779
778
|
exports.StreamStopSession = async function({name}) {
|
|
780
779
|
try {
|
|
781
|
-
|
|
782
|
-
|
|
780
|
+
this.Log(`Terminating stream session for: ${name}`);
|
|
783
781
|
let conf = await this.LoadConf({name});
|
|
784
782
|
|
|
785
783
|
let {objectId} = conf;
|
|
@@ -799,86 +797,81 @@ exports.StreamStopSession = async function({name}) {
|
|
|
799
797
|
|
|
800
798
|
this.SetNodes({fabricURIs: [fabURI]});
|
|
801
799
|
|
|
802
|
-
|
|
800
|
+
const metaEdgeWriteToken = mainMeta.live_recording.fabric_config.edge_write_token;
|
|
803
801
|
|
|
804
|
-
if(
|
|
802
|
+
if(!metaEdgeWriteToken) {
|
|
805
803
|
return {
|
|
806
804
|
state: "inactive",
|
|
807
|
-
error: "
|
|
805
|
+
error: "The stream is not active"
|
|
808
806
|
};
|
|
809
807
|
}
|
|
810
|
-
let edgeMeta = await this.ContentObjectMetadata({
|
|
811
|
-
libraryId,
|
|
812
|
-
objectId,
|
|
813
|
-
writeToken: edgeWriteToken
|
|
814
|
-
});
|
|
815
808
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
libraryId: status.library_id,
|
|
823
|
-
objectId: status.object_id,
|
|
824
|
-
writeToken: status.edge_write_token,
|
|
825
|
-
method: "/live/stop/" + status.tlro,
|
|
826
|
-
constant: false
|
|
827
|
-
});
|
|
828
|
-
} catch(error) {
|
|
829
|
-
// The /call/lro/stop API returns empty response
|
|
830
|
-
// console.log("LRO Stop (failed): ", error);
|
|
831
|
-
}
|
|
809
|
+
try {
|
|
810
|
+
const streamMetadata = await this.ContentObjectMetadata({
|
|
811
|
+
libraryId,
|
|
812
|
+
objectId,
|
|
813
|
+
writeToken: metaEdgeWriteToken
|
|
814
|
+
});
|
|
832
815
|
|
|
833
|
-
|
|
834
|
-
let tries = 10;
|
|
835
|
-
while(status.state != "stopped" && tries-- > 0) {
|
|
836
|
-
console.log("Wait to terminate - ", status.state);
|
|
837
|
-
await Sleep(1000);
|
|
838
|
-
status = await this.StreamStatus({name});
|
|
839
|
-
}
|
|
840
|
-
console.log("Status after stop - ", status.state);
|
|
816
|
+
const status = await this.StreamStatus({name});
|
|
841
817
|
|
|
842
|
-
if(
|
|
843
|
-
|
|
844
|
-
|
|
818
|
+
if(status.state !== "stopped") {
|
|
819
|
+
return {
|
|
820
|
+
state: status.state,
|
|
821
|
+
error: "The stream must be stopped before terminating"
|
|
822
|
+
}
|
|
845
823
|
}
|
|
824
|
+
|
|
825
|
+
await this.DeleteWriteToken({
|
|
826
|
+
libraryId,
|
|
827
|
+
writeToken: metaEdgeWriteToken
|
|
828
|
+
});
|
|
829
|
+
} catch(error) {
|
|
830
|
+
this.Log(`Unable to retrieve metadata for edge write token ${edgeWriteToken}`);
|
|
846
831
|
}
|
|
847
832
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
833
|
+
const {writeToken} = await this.EditContentObject({
|
|
834
|
+
libraryId: libraryId,
|
|
835
|
+
objectId: objectId
|
|
836
|
+
});
|
|
852
837
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
};
|
|
838
|
+
// Set stop time and inactive state
|
|
839
|
+
const newState = "inactive";
|
|
840
|
+
const stopTime = Math.floor(new Date().getTime() / 1000);
|
|
857
841
|
|
|
858
|
-
|
|
842
|
+
const finalizeMetadata = {
|
|
843
|
+
live_recording: {
|
|
844
|
+
status: {
|
|
845
|
+
edge_write_token: "",
|
|
846
|
+
state: newState,
|
|
847
|
+
recording_stop_time: stopTime
|
|
848
|
+
},
|
|
849
|
+
fabric_config: {
|
|
850
|
+
edge_write_token: ""
|
|
851
|
+
}
|
|
852
|
+
},
|
|
853
|
+
recording_stop_time: stopTime
|
|
854
|
+
};
|
|
859
855
|
|
|
860
|
-
await this.
|
|
856
|
+
await this.MergeMetadata({
|
|
861
857
|
libraryId,
|
|
862
858
|
objectId,
|
|
863
|
-
writeToken
|
|
864
|
-
metadata:
|
|
859
|
+
writeToken,
|
|
860
|
+
metadata: finalizeMetadata
|
|
865
861
|
});
|
|
866
862
|
|
|
867
863
|
let fin = await this.FinalizeContentObject({
|
|
868
864
|
libraryId,
|
|
869
865
|
objectId,
|
|
870
|
-
writeToken
|
|
871
|
-
commitMessage:
|
|
872
|
-
publish: false // Don't publish this version because it is not currently useful
|
|
866
|
+
writeToken,
|
|
867
|
+
commitMessage: `Deactivate live stream - stop time ${stopTime}`
|
|
873
868
|
});
|
|
874
869
|
|
|
875
870
|
return {
|
|
876
871
|
fin,
|
|
877
872
|
name,
|
|
878
|
-
|
|
879
|
-
state: "terminated"
|
|
873
|
+
state: newState
|
|
880
874
|
};
|
|
881
|
-
|
|
882
875
|
} catch(error) {
|
|
883
876
|
console.error(error);
|
|
884
877
|
}
|
|
@@ -1419,97 +1412,122 @@ exports.StreamConfig = async function({name, customSettings={}}) {
|
|
|
1419
1412
|
};
|
|
1420
1413
|
|
|
1421
1414
|
/**
|
|
1422
|
-
*
|
|
1415
|
+
* List the pre-allocated URLs for a site
|
|
1423
1416
|
*
|
|
1424
1417
|
* @methodGroup Live Stream
|
|
1425
1418
|
* @namedParams
|
|
1426
|
-
* @param {string}
|
|
1419
|
+
* @param {string=} - ID of the live stream site object
|
|
1427
1420
|
*
|
|
1428
|
-
* @return {Promise<Object>} - The
|
|
1421
|
+
* @return {Promise<Object>} - The list of stream URLs
|
|
1429
1422
|
*/
|
|
1430
|
-
exports.
|
|
1423
|
+
exports.StreamListUrls = async function({siteId}={}) {
|
|
1431
1424
|
try {
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
}
|
|
1441
|
-
let status = await this.StreamStatus({name});
|
|
1425
|
+
const STATUS_MAP = {
|
|
1426
|
+
UNCONFIGURED: "unconfigured",
|
|
1427
|
+
UNINITIALIZED: "uninitialized",
|
|
1428
|
+
INACTIVE: "inactive",
|
|
1429
|
+
STOPPED: "stopped",
|
|
1430
|
+
STARTING: "starting",
|
|
1431
|
+
RUNNING: "running",
|
|
1432
|
+
STALLED: "stalled",
|
|
1433
|
+
};
|
|
1442
1434
|
|
|
1443
|
-
if(!
|
|
1444
|
-
|
|
1445
|
-
state: status.state,
|
|
1446
|
-
error: "Stream must be configured before deactivating"
|
|
1447
|
-
};
|
|
1448
|
-
}
|
|
1435
|
+
if(!siteId) {
|
|
1436
|
+
const tenantContractId = await this.userProfileClient.TenantContractId();
|
|
1449
1437
|
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
state: status.state,
|
|
1454
|
-
error: "Stream must be stopped before deactivating"
|
|
1455
|
-
};
|
|
1456
|
-
}
|
|
1438
|
+
if(!tenantContractId) {
|
|
1439
|
+
throw Error("No tenant contract ID configured");
|
|
1440
|
+
}
|
|
1457
1441
|
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1442
|
+
siteId = await this.ContentObjectMetadata({
|
|
1443
|
+
libraryId: tenantContractId.replace("iten", "ilib"),
|
|
1444
|
+
objectId: tenantContractId.replace("iten", "iq__"),
|
|
1445
|
+
metadataSubtree: "public/sites/live_streams",
|
|
1446
|
+
});
|
|
1463
1447
|
}
|
|
1464
1448
|
|
|
1465
|
-
this.
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
state: "inactive",
|
|
1472
|
-
error: "stream is already inactive"
|
|
1473
|
-
};
|
|
1474
|
-
}
|
|
1475
|
-
let edgeMeta = await this.ContentObjectMetadata({
|
|
1476
|
-
libraryId,
|
|
1477
|
-
objectId,
|
|
1478
|
-
writeToken: edgeWriteToken
|
|
1449
|
+
const streamMetadata = await this.ContentObjectMetadata({
|
|
1450
|
+
libraryId: await this.ContentObjectLibraryId({objectId: siteId}),
|
|
1451
|
+
objectId: siteId,
|
|
1452
|
+
metadataSubtree: "public/asset_metadata/live_streams",
|
|
1453
|
+
resolveLinks: true,
|
|
1454
|
+
resolveIgnoreErrors: true
|
|
1479
1455
|
});
|
|
1480
1456
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1457
|
+
const activeUrlMap = {};
|
|
1458
|
+
await this.utils.LimitedMap(
|
|
1459
|
+
10,
|
|
1460
|
+
Object.keys(streamMetadata || {}),
|
|
1461
|
+
async slug => {
|
|
1462
|
+
const stream = streamMetadata[slug];
|
|
1463
|
+
let versionHash;
|
|
1464
|
+
|
|
1465
|
+
if(
|
|
1466
|
+
stream &&
|
|
1467
|
+
stream.sources &&
|
|
1468
|
+
stream.sources.default &&
|
|
1469
|
+
stream.sources.default["."] &&
|
|
1470
|
+
stream.sources.default["."].container ||
|
|
1471
|
+
((stream["/"] || "").match(/^\/?qfab\/([\w]+)\/?.+/) || [])[1]
|
|
1472
|
+
) {
|
|
1473
|
+
versionHash = (
|
|
1474
|
+
stream.sources.default["."].container ||
|
|
1475
|
+
((stream["/"] || "").match(/^\/?qfab\/([\w]+)\/?.+/) || [])[1]
|
|
1476
|
+
);
|
|
1477
|
+
}
|
|
1484
1478
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1479
|
+
if(versionHash) {
|
|
1480
|
+
const objectId = this.utils.DecodeVersionHash(versionHash).objectId;
|
|
1481
|
+
const libraryId = await this.ContentObjectLibraryId({objectId});
|
|
1482
|
+
|
|
1483
|
+
const status = await this.StreamStatus({
|
|
1484
|
+
name: objectId
|
|
1485
|
+
});
|
|
1486
|
+
|
|
1487
|
+
const streamMeta = await this.ContentObjectMetadata({
|
|
1488
|
+
objectId,
|
|
1489
|
+
libraryId,
|
|
1490
|
+
select: [
|
|
1491
|
+
"live_recording_config/reference_url",
|
|
1492
|
+
// live_recording_config/url is the old path
|
|
1493
|
+
"live_recording_config/url"
|
|
1494
|
+
]
|
|
1495
|
+
});
|
|
1496
|
+
|
|
1497
|
+
const url = streamMeta.live_recording_config.reference_url || streamMeta.live_recording_config.url;
|
|
1498
|
+
const isActive = [STATUS_MAP.STARTING, STATUS_MAP.RUNNING, STATUS_MAP.STALLED, STATUS_MAP.STOPPED].includes(status.state);
|
|
1499
|
+
|
|
1500
|
+
if(url && isActive) {
|
|
1501
|
+
activeUrlMap[url] = true;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
);
|
|
1489
1506
|
|
|
1490
|
-
|
|
1507
|
+
const streamUrlStatus = {};
|
|
1491
1508
|
|
|
1492
|
-
await this.
|
|
1493
|
-
libraryId,
|
|
1494
|
-
objectId,
|
|
1495
|
-
|
|
1496
|
-
|
|
1509
|
+
const streamUrls = await this.ContentObjectMetadata({
|
|
1510
|
+
libraryId: await this.ContentObjectLibraryId({objectId: siteId}),
|
|
1511
|
+
objectId: siteId,
|
|
1512
|
+
metadataSubtree: "/live_stream_urls",
|
|
1513
|
+
resolveLinks: true,
|
|
1514
|
+
resolveIgnoreErrors: true
|
|
1497
1515
|
});
|
|
1498
1516
|
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1517
|
+
if(!streamUrls) {
|
|
1518
|
+
throw Error("No pre-allocated URLs configured");
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
Object.keys(streamUrls || {}).forEach(protocol => {
|
|
1522
|
+
streamUrlStatus[protocol] = streamUrls[protocol].map(url => {
|
|
1523
|
+
return {
|
|
1524
|
+
url,
|
|
1525
|
+
active: activeUrlMap[url] || false
|
|
1526
|
+
};
|
|
1527
|
+
})
|
|
1504
1528
|
});
|
|
1505
1529
|
|
|
1506
|
-
return
|
|
1507
|
-
reference_url: status.reference_url,
|
|
1508
|
-
fin,
|
|
1509
|
-
name,
|
|
1510
|
-
edge_write_token: edgeWriteToken,
|
|
1511
|
-
state: newState
|
|
1512
|
-
};
|
|
1530
|
+
return streamUrlStatus;
|
|
1513
1531
|
} catch(error) {
|
|
1514
1532
|
console.error(error);
|
|
1515
1533
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
const {ElvClient} = require("../src/ElvClient");
|
|
3
|
+
|
|
4
|
+
const yargs = require("yargs");
|
|
5
|
+
const argv = yargs
|
|
6
|
+
.option("configUrl", {
|
|
7
|
+
description: "Fabric configuration URL (e.g. https://main.net955210.contentfabric.io/config)"
|
|
8
|
+
})
|
|
9
|
+
.option("tenantContractId", {
|
|
10
|
+
description: "tenant Contract Id to set for the user"
|
|
11
|
+
})
|
|
12
|
+
.demandOption(
|
|
13
|
+
["configUrl", "tenantContractId"],
|
|
14
|
+
"\nUsage: PRIVATE_KEY=<private-key> node CreateUserWithTenantId --configUrl <config-url> --tenantContractId <tenant_id>\n"
|
|
15
|
+
)
|
|
16
|
+
.argv;
|
|
17
|
+
|
|
18
|
+
const TestAddTenantContractId = async ({configUrl, tenantContractId}) => {
|
|
19
|
+
try {
|
|
20
|
+
if(!process.env.PRIVATE_KEY) {
|
|
21
|
+
console.log("ERROR: 'PRIVATE_KEY' environment variable must be set");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log(`\nAdd tenant to User, tenant contract : ${tenantContractId}\n`);
|
|
25
|
+
|
|
26
|
+
// create user wallet
|
|
27
|
+
const client = await ElvClient.FromConfigurationUrl({configUrl});
|
|
28
|
+
const wallet = client.GenerateWallet();
|
|
29
|
+
const signer = wallet.AddAccount({privateKey: process.env.PRIVATE_KEY});
|
|
30
|
+
client.SetSigner({signer});
|
|
31
|
+
|
|
32
|
+
// set tenant contract ID for user
|
|
33
|
+
await client.userProfileClient.SetTenantContractId({tenantContractId});
|
|
34
|
+
console.log(`tenant contract ${await client.userProfileClient.TenantContractId()} set for user ${client.signer.address}`);
|
|
35
|
+
// console.log(await client.userProfileClient.UserMetadata());
|
|
36
|
+
|
|
37
|
+
// tenant contract ID set during creation of library
|
|
38
|
+
libraryId = await client.CreateContentLibrary({name: "library_with_tenant_contract_id"});
|
|
39
|
+
libraryAddress = client.utils.HashToAddress(libraryId);
|
|
40
|
+
console.log(`library created: ${libraryId}`);
|
|
41
|
+
let actualTenantContractId = await client.TenantContractId({contractAddress:libraryAddress});
|
|
42
|
+
if(tenantContractId !== actualTenantContractId){
|
|
43
|
+
throw Error(`tenant mismatch, actual: ${actualTenantContractId}, expected: ${tenantContractId}`);
|
|
44
|
+
}
|
|
45
|
+
// console.log(await client.ContentObjectMetadata({libraryId, objectId: client.utils.AddressToObjectId(libraryAddress)}));
|
|
46
|
+
|
|
47
|
+
// tenant contract ID set during creation of content type
|
|
48
|
+
const typeMetadata = {
|
|
49
|
+
bitcode_flags: "abrmaster",
|
|
50
|
+
bitcode_format: "builtin",
|
|
51
|
+
public: {
|
|
52
|
+
"eluv.displayApp": "default",
|
|
53
|
+
"eluv.manageApp": "default",
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const contentTypeId = await client.CreateContentType({
|
|
58
|
+
name: `${tenantContractId} - Title`,
|
|
59
|
+
metadata: {...typeMetadata}
|
|
60
|
+
});
|
|
61
|
+
contentTypeAddress = client.utils.HashToAddress(contentTypeId);
|
|
62
|
+
console.log(`content type - title created: ${contentTypeId}`);
|
|
63
|
+
actualTenantContractId = await client.TenantContractId({contractAddress:contentTypeAddress});
|
|
64
|
+
if(tenantContractId !== actualTenantContractId){
|
|
65
|
+
throw Error(`tenant mismatch, actual: ${actualTenantContractId}, expected: ${tenantContractId}`);
|
|
66
|
+
}
|
|
67
|
+
// console.log(await client.ContentObjectMetadata({
|
|
68
|
+
// libraryId: client.contentSpaceLibraryId,
|
|
69
|
+
// objectId: client.utils.AddressToObjectId(contentTypeAddress)}));
|
|
70
|
+
|
|
71
|
+
// tenant contract ID set during creation of access group
|
|
72
|
+
const groupAddress = await client.CreateAccessGroup({name: "Test Group"});
|
|
73
|
+
console.log(`group created: ${groupAddress}`);
|
|
74
|
+
actualTenantContractId = await client.TenantContractId({contractAddress:groupAddress});
|
|
75
|
+
if(tenantContractId !== actualTenantContractId){
|
|
76
|
+
throw Error(`tenant mismatch, actual: ${actualTenantContractId}, expected: ${tenantContractId}`);
|
|
77
|
+
}
|
|
78
|
+
// console.log(await client.ContentObjectMetadata({
|
|
79
|
+
// libraryId: client.contentSpaceLibraryId,
|
|
80
|
+
// objectId: client.utils.AddressToObjectId(groupAddress)}));
|
|
81
|
+
|
|
82
|
+
} catch(e){
|
|
83
|
+
console.error(e);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
TestAddTenantContractId(argv);
|