Skip to content

Commit fd4503b

Browse files
Add transfer capability to the SDK (#60)
* Add transfer capability to the SDK * minor version bump Co-authored-by: KK, Amith <amith.kk@unisys.com>
1 parent bfdb0c9 commit fd4503b

4 files changed

Lines changed: 107 additions & 3 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@dbom/sdk",
3-
"version": "1.1.2",
3+
"version": "1.2.0",
44
"description": "Node SDK for DBoM",
55
"main": "src/dbom-node.js",
66
"scripts": {

src/dbom-node.js

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ const {
3434
ParentAssetOrChannelNotFound,
3535
ChildAssetOrChannelNotFound,
3636
SigningServiceError,
37+
SourceAssetOrChannelNotFound,
38+
DestinationAssetAlreadyExists,
3739
} = require('./errors');
3840

3941
/** Class representing a DBoM Node. */
@@ -71,7 +73,7 @@ class DbomNode {
7173

7274
/**
7375
* Constructs baseURL from initialized DBoM Node
74-
* @returns
76+
* @returns
7577
*/
7678
_constructBaseURL() {
7779
return `http://${this.gatewayURI}/api/v1`;
@@ -394,7 +396,7 @@ class DbomNode {
394396
async queryAssets(repoID, channelID, queryParams) {
395397
const requestURI = `${this._constructAssetURL(repoID, channelID)}/_query`;
396398
try {
397-
return (await this.axios.post(requestURI,
399+
return (await this.axios.post(requestURI,
398400
this.constructor._applyQueryParamDefaults(queryParams))).data;
399401
} catch (e) {
400402
const status = this._getErrorStatus(e);
@@ -445,6 +447,43 @@ class DbomNode {
445447
}
446448
}
447449
}
450+
451+
/**
452+
* Attaches a child asset to the provided parent asset
453+
* @param {string} sourceRepoID - Repository ID of the repository where the source asset
454+
* is stored
455+
* @param {string} sourceChannelID - Channel ID of the channel where the source asset is stored
456+
* @param {string} sourceAssetID - Asset ID of the source asset
457+
* @param {string} destinationRepoID - Repository ID of the destination repository
458+
* @param {string} destinationChannelID - Channel ID of the destination channel
459+
* @param {string} destinationAssetID - Asset ID that must be given to the asset on
460+
* the destination channel
461+
* @param {string} transferDescription - The reason to be associated with the transfer
462+
* @returns {*} - Gateway Response
463+
*/
464+
async transferAsset(sourceRepoID, sourceChannelID, sourceAssetID,
465+
destinationRepoID, destinationChannelID, destinationAssetID,
466+
transferDescription) {
467+
const requestURI = `${this._constructAssetURL(sourceRepoID, sourceChannelID, sourceAssetID)}/transfer`;
468+
const body = {
469+
transferDescription,
470+
repoID: destinationRepoID,
471+
channelID: destinationChannelID,
472+
assetID: destinationAssetID,
473+
};
474+
try {
475+
return (await this.axios.post(requestURI, body)).data;
476+
} catch (e) {
477+
const status = this._getErrorStatus(e);
478+
if (status === 404) {
479+
throw new SourceAssetOrChannelNotFound();
480+
} else if (status === 409 && e.response.data.status === 'Already Exists') {
481+
throw new DestinationAssetAlreadyExists();
482+
} else {
483+
throw new GatewayError(status, e.response.data);
484+
}
485+
}
486+
}
448487
}
449488

450489
module.exports = DbomNode;

src/errors.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,15 @@ class ParentAssetOrChannelNotFound extends AssetOrChannelNotFound {
5050
}
5151
}
5252

53+
class SourceAssetOrChannelNotFound extends AssetOrChannelNotFound {
54+
constructor() {
55+
super();
56+
this.name = this.constructor.name;
57+
this.message = 'Source asset or channel was not found';
58+
this.status = 404;
59+
}
60+
}
61+
5362
class ChildAssetOrChannelNotFound extends AssetOrChannelNotFound {
5463
constructor() {
5564
super();
@@ -68,6 +77,15 @@ class AssetAlreadyExists extends DbomError {
6877
}
6978
}
7079

80+
class DestinationAssetAlreadyExists extends AssetAlreadyExists {
81+
constructor() {
82+
super();
83+
this.name = this.constructor.name;
84+
this.message = 'Destination asset-id already exists';
85+
this.status = 409;
86+
}
87+
}
88+
7189
class AssetAlreadyAttached extends DbomError {
7290
constructor() {
7391
super();
@@ -105,6 +123,7 @@ class SigningServiceError extends DbomError {
105123
}
106124
}
107125

126+
108127
module.exports = {
109128
DbomError,
110129
AssetInvalid,
@@ -116,4 +135,6 @@ module.exports = {
116135
AssetNotAttached,
117136
AssetAlreadyAttached,
118137
GatewayError,
138+
SourceAssetOrChannelNotFound,
139+
DestinationAssetAlreadyExists,
119140
};

src/test/dbom-node.test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ const {
3535
AssetAlreadyExists,
3636
AssetAlreadyAttached,
3737
ParentAssetOrChannelNotFound,
38+
SourceAssetOrChannelNotFound,
3839
ChildAssetOrChannelNotFound,
3940
SigningServiceError,
41+
DestinationAssetAlreadyExists,
4042
} = require('../errors');
4143

4244
describe('dbom node', () => {
@@ -655,4 +657,46 @@ describe('dbom node', () => {
655657
.rejectedWith(GatewayError);
656658
});
657659
});
660+
661+
context('transferAsset', () => {
662+
it('should transfer asset', (done) => {
663+
axiosMock(200, 'stubResponse', done);
664+
dbom.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
665+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID').then((resolve) => {
666+
expect(resolve).to.equal('stubResponse');
667+
});
668+
dbom1.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
669+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID').then((resolve) => {
670+
expect(resolve).to.equal('stubResponse');
671+
});
672+
});
673+
674+
it('should return source asset not found error', (done) => {
675+
axiosMock(404, 'stubResponse', done);
676+
expect(dbom.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
677+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID')).to.be.rejectedWith(SourceAssetOrChannelNotFound);
678+
expect(dbom1.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
679+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID')).to.be.rejectedWith(SourceAssetOrChannelNotFound);
680+
});
681+
682+
it('should report if destination asset already exists', (done) => {
683+
axiosMock(409, {
684+
success: false,
685+
status: 'Already Exists',
686+
error: 'Destination asset already exists',
687+
}, done);
688+
expect(dbom.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
689+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID')).to.be.rejectedWith(DestinationAssetAlreadyExists);
690+
expect(dbom1.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
691+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID')).to.be.rejectedWith(DestinationAssetAlreadyExists);
692+
});
693+
694+
it('should return gateway error', (done) => {
695+
axiosMock(500, 'stubResponse', done);
696+
expect(dbom.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
697+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID')).to.be.rejectedWith(GatewayError);
698+
expect(dbom1.transferAsset('sourceRepoID', 'sourceChannelID', 'sourceAssetID',
699+
'destinationRepoID', 'destinationChannelID', 'destinationAssetID')).to.be.rejectedWith(GatewayError);
700+
});
701+
});
658702
});

0 commit comments

Comments
 (0)