Skip to content

Commit 9075aa4

Browse files
feat(ref-imp): add array support for serviceEndpoint
1 parent df2a5bd commit 9075aa4

3 files changed

Lines changed: 64 additions & 17 deletions

File tree

lib/core/versions/latest/DocumentComposer.ts

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -345,22 +345,26 @@ export default class DocumentComposer {
345345
}
346346

347347
// `serviceEndpoint` validations.
348-
const serviceEndpoint = service.serviceEndpoint;
349-
if (typeof serviceEndpoint === 'string') {
350-
const uri = URI.parse(service.serviceEndpoint);
351-
if (uri.error !== undefined) {
352-
throw new SidetreeError(
353-
ErrorCode.DocumentComposerPatchServiceEndpointStringNotValidUri,
354-
`Service endpoint string '${serviceEndpoint}' is not a valid URI.`
355-
);
356-
}
357-
} else if (typeof serviceEndpoint === 'object') {
358-
// Allow `object` type only if it is not an array.
359-
if (Array.isArray(serviceEndpoint)) {
360-
throw new SidetreeError(ErrorCode.DocumentComposerPatchServiceEndpointCannotBeAnArray);
348+
// transform URI strings and JSON objects into array so that we can run validations more easily
349+
const serviceEndpointValueAsArray = Array.isArray(service.serviceEndpoint) ? service.serviceEndpoint : [service.serviceEndpoint];
350+
for (const serviceEndpoint of serviceEndpointValueAsArray) {
351+
// serviceEndpoint itself must be URI string or non-array object
352+
if (typeof serviceEndpoint === 'string') {
353+
const uri = URI.parse(serviceEndpoint);
354+
if (uri.error !== undefined) {
355+
throw new SidetreeError(
356+
ErrorCode.DocumentComposerPatchServiceEndpointStringNotValidUri,
357+
`Service endpoint string '${serviceEndpoint}' is not a valid URI.`
358+
);
359+
}
360+
} else if (typeof serviceEndpoint === 'object') {
361+
// Allow `object` type only if it is not an array.
362+
if (Array.isArray(serviceEndpoint)) {
363+
throw new SidetreeError(ErrorCode.DocumentComposerPatchServiceEndpointCannotBeAnArray);
364+
}
365+
} else {
366+
throw new SidetreeError(ErrorCode.DocumentComposerPatchServiceEndpointMustBeStringOrNonArrayObject);
361367
}
362-
} else {
363-
throw new SidetreeError(ErrorCode.DocumentComposerPatchServiceEndpointMustBeStringOrNonArrayObject);
364368
}
365369
}
366370
}

lib/core/versions/latest/models/ServiceModel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
export default interface ServiceModel {
55
id: string;
66
type: string;
7-
serviceEndpoint: string | object;
7+
serviceEndpoint: string | object | Array<string | object>;
88
}

tests/core/DocumentComposer.spec.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ describe('DocumentComposer', async () => {
469469
DocumentComposer['validateAddServicesPatch'](patch);
470470
});
471471

472-
it('should throw error if `serviceEndpoint` is an array.', () => {
472+
it('should allow an array as `serviceEndpoint`.', () => {
473473
const patch = {
474474
action: PatchAction.AddServices,
475475
services: [{
@@ -478,6 +478,20 @@ describe('DocumentComposer', async () => {
478478
serviceEndpoint: []
479479
}]
480480
};
481+
482+
// Expecting this call to succeed without errors.
483+
DocumentComposer['validateAddServicesPatch'](patch);
484+
});
485+
486+
it('should throw error if `serviceEndpoint` is an array that includes an array.', () => {
487+
const patch = {
488+
action: PatchAction.AddServices,
489+
services: [{
490+
id: 'someId',
491+
type: 'someType',
492+
serviceEndpoint: [[]] // array must contain URI strings or objects but not arrays
493+
}]
494+
};
481495
const expectedError = new SidetreeError(ErrorCode.DocumentComposerPatchServiceEndpointCannotBeAnArray);
482496
expect(() => { DocumentComposer['validateAddServicesPatch'](patch); }).toThrow(expectedError);
483497
});
@@ -495,6 +509,19 @@ describe('DocumentComposer', async () => {
495509
expect(() => { DocumentComposer['validateAddServicesPatch'](patch); }).toThrow(expectedError);
496510
});
497511

512+
it('should throw error if `serviceEndpoint` has an invalid type (inside an array).', () => {
513+
const patch = {
514+
action: PatchAction.AddServices,
515+
services: [{
516+
id: 'someId',
517+
type: 'someType',
518+
serviceEndpoint: [123] // Invalid serviceEndpoint type.
519+
}]
520+
};
521+
const expectedError = new SidetreeError(ErrorCode.DocumentComposerPatchServiceEndpointMustBeStringOrNonArrayObject);
522+
expect(() => { DocumentComposer['validateAddServicesPatch'](patch); }).toThrow(expectedError);
523+
});
524+
498525
it('Should throw if `serviceEndpoint` is not valid URI.', () => {
499526
const patch = {
500527
action: PatchAction.AddServices,
@@ -510,6 +537,22 @@ describe('DocumentComposer', async () => {
510537
ErrorCode.DocumentComposerPatchServiceEndpointStringNotValidUri
511538
);
512539
});
540+
541+
it('Should throw if `serviceEndpoint` is not valid URI (inside an array).', () => {
542+
const patch = {
543+
action: PatchAction.AddServices,
544+
services: [{
545+
id: 'someId',
546+
type: 'someType',
547+
serviceEndpoint: ['http://'] // Invalid URI.
548+
}]
549+
};
550+
551+
JasmineSidetreeErrorValidator.expectSidetreeErrorToBeThrown(
552+
() => DocumentComposer['validateAddServicesPatch'](patch),
553+
ErrorCode.DocumentComposerPatchServiceEndpointStringNotValidUri
554+
);
555+
});
513556
});
514557

515558
describe('validateDocumentPatches()', async () => {

0 commit comments

Comments
 (0)