diff --git a/src/common/common.ts b/src/common/common.ts index cc3662cf..3fb8b1ee 100644 --- a/src/common/common.ts +++ b/src/common/common.ts @@ -305,39 +305,35 @@ export const defaultContext = ["https://www.w3.org/2018/credentials/v1"]; export const defaultCredentialTypes = ["VerifiableCredential"]; +type LegacyEndpoints = Partial<{ + derivationService: UrlString; + issuerService: UrlString; + statusService: UrlString; + verifierService: UrlString; + queryService: UrlString; +}>; + /** * A Verifiable Credential API configuration details. */ -export type VerifiableCredentialApiConfiguration = - // Legacy endpoints - Partial<{ +export type VerifiableCredentialApiConfiguration = LegacyEndpoints & { + // Spec-compliant endpoints, available in the `specCompliant` object + specCompliant: Partial<{ derivationService: UrlString; issuerService: UrlString; + issuerCredentialAll: UrlString; + holderPresentationAll: UrlString; statusService: UrlString; - verifierService: UrlString; - }> & { - // Spec-compliant endpoints, available in the `specCompliant` object - specCompliant: Partial<{ - derivationService: UrlString; - issuerService: UrlString; - issuerCredentialAll: UrlString; - holderPresentationAll: UrlString; - statusService: UrlString; - credentialVerifierService: UrlString; - presentationVerifierService: UrlString; - queryService: UrlString; - exchangeService: UrlString; - proveService: UrlString; - }>; - } & { - // Legacy endpoints, available in the `legacy` object too to ease transition - legacy: Partial<{ - derivationService: UrlString; - issuerService: UrlString; - statusService: UrlString; - verifierService: UrlString; - }>; - }; + credentialVerifierService: UrlString; + presentationVerifierService: UrlString; + queryService: UrlString; + exchangeService: UrlString; + proveService: UrlString; + }>; +} & { + // Legacy endpoints, available in the `legacy` object too to ease transition + legacy: LegacyEndpoints; +}; // Solid VC URIs const SOLID_VC_NS = "http://www.w3.org/ns/solid/vc#"; @@ -345,6 +341,7 @@ const SOLID_VC_DERIVATION_SERVICE = SOLID_VC_NS.concat("derivationService"); const SOLID_VC_ISSUER_SERVICE = SOLID_VC_NS.concat("issuerService"); const SOLID_VC_STATUS_SERVICE = SOLID_VC_NS.concat("statusService"); const SOLID_VC_VERIFIER_SERVICE = SOLID_VC_NS.concat("verifierService"); +const SOLID_VC_QUERY_SERVICE = SOLID_VC_NS.concat("queryService"); async function discoverLegacyEndpoints( vcServiceUrl: UrlString, @@ -368,6 +365,8 @@ async function discoverLegacyEndpoints( undefined, issuerService: getIri(wellKnownRootBlankNode, SOLID_VC_ISSUER_SERVICE) ?? undefined, + queryService: + getIri(wellKnownRootBlankNode, SOLID_VC_QUERY_SERVICE) ?? undefined, statusService: getIri(wellKnownRootBlankNode, SOLID_VC_STATUS_SERVICE) ?? undefined, verifierService: diff --git a/src/common/configuration.test.ts b/src/common/configuration.test.ts index 7d25c943..4d676850 100644 --- a/src/common/configuration.test.ts +++ b/src/common/configuration.test.ts @@ -47,6 +47,7 @@ const mockVcWellKnown = (options: { statusPresent?: boolean; verifierPresent?: boolean; derivationPresent?: boolean; + queryPresent?: boolean; }): SolidClient.SolidDataset & SolidClient.WithServerResourceInfo => { const wellKnown = buildThing(); if (options.issuerPresent) { @@ -73,6 +74,12 @@ const mockVcWellKnown = (options: { `${MOCKED_VC_SERVICE}/derive`, ); } + if (options.queryPresent) { + wellKnown.addIri( + "http://www.w3.org/ns/solid/vc#queryService", + `${MOCKED_VC_SERVICE}/query`, + ); + } return setThing( mockSolidDatasetFrom("https://vc-service.iri/.well-known/solid"), wellKnown.build(), @@ -169,6 +176,23 @@ describe("getVerifiableCredentialApiConfiguration", () => { ); }); + it("returns the IRI of the query service if present", async () => { + const clientModule = jest.requireMock( + "@inrupt/solid-client", + ) as jest.Mocked; + clientModule.getSolidDataset.mockResolvedValueOnce( + mockVcWellKnown({ queryPresent: true }), + ); + const result = await getVerifiableCredentialApiConfiguration( + "https://some.example.wellknown.iri", + ); + expect(result).toEqual( + expect.objectContaining({ + queryService: `${MOCKED_VC_SERVICE}/query`, + }), + ); + }); + it("returns the IRI of multiple services if present", async () => { const clientModule = jest.requireMock( "@inrupt/solid-client", @@ -200,6 +224,7 @@ describe("getVerifiableCredentialApiConfiguration", () => { expect(result.issuerService).toBeUndefined(); expect(result.statusService).toBeUndefined(); expect(result.verifierService).toBeUndefined(); + expect(result.queryService).toBeUndefined(); }); it("makes the legacy endpoints available on the legacy object", async () => { @@ -207,7 +232,11 @@ describe("getVerifiableCredentialApiConfiguration", () => { "@inrupt/solid-client", ) as jest.Mocked; clientModule.getSolidDataset.mockResolvedValueOnce( - mockVcWellKnown({ derivationPresent: true, issuerPresent: true }), + mockVcWellKnown({ + derivationPresent: true, + issuerPresent: true, + queryPresent: true, + }), ); const result = await getVerifiableCredentialApiConfiguration( "https://some.example.wellknown.iri", @@ -216,6 +245,7 @@ describe("getVerifiableCredentialApiConfiguration", () => { expect(result.derivationService).toStrictEqual( result.legacy.derivationService, ); + expect(result.queryService).toStrictEqual(result.legacy.queryService); }); });