diff --git a/CHANGELOG.md b/CHANGELOG.md index ed2c0efc2..8456d3f5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ The following changes are pending, and will be applied on the next major release - Node 22 is now supported +### Bugfixes + +- The `/resources` module function have their signature now aligned with the underlying `@inrupt/solid-client` functions. + Namely, the `options` parameter for `saveSolidDatasetAt` and `getSolidDataset` support additional entries that were + already available in `@inrupt/solid-client`. + ## [3.0.5](https://github.com/inrupt/solid-client-access-grants-js/releases/tag/v3.0.5) - 2024-07-31 ### Bugfixes diff --git a/src/common/verify/isValidAccessGrant.test.ts b/src/common/verify/isValidAccessGrant.test.ts index d71186d4e..4fd13a7bc 100644 --- a/src/common/verify/isValidAccessGrant.test.ts +++ b/src/common/verify/isValidAccessGrant.test.ts @@ -23,18 +23,24 @@ import { jest, describe, it, expect, beforeAll } from "@jest/globals"; import { isVerifiableCredential, getVerifiableCredentialApiConfiguration, + verifiableCredentialToDataset, } from "@inrupt/solid-client-vc"; - +import type * as SolidClient from "@inrupt/solid-client"; import type * as VcLibrary from "@inrupt/solid-client-vc"; import { isValidAccessGrant } from "./isValidAccessGrant"; jest.mock("@inrupt/solid-client", () => { - const solidClientModule = jest.requireActual("@inrupt/solid-client") as any; + const solidClientModule = jest.requireActual( + "@inrupt/solid-client", + ) as typeof SolidClient; solidClientModule.getSolidDataset = jest.fn( solidClientModule.getSolidDataset, ); - solidClientModule.getWellKnownSolid = jest.fn(); - return solidClientModule; + return { + ...solidClientModule, + getWellKnownSolid: jest.fn<(typeof SolidClient)["getWellKnownSolid"]>(), + getSolidDataset: jest.fn<(typeof SolidClient)["getSolidDataset"]>(), + }; }); jest.mock("@inrupt/solid-client-vc", () => { @@ -150,9 +156,12 @@ describe("isValidAccessGrant", () => { }), ); - await isValidAccessGrant(MOCK_ACCESS_GRANT_BASE as any, { - fetch: mockedFetch, - }); + await isValidAccessGrant( + await verifiableCredentialToDataset(MOCK_ACCESS_GRANT_BASE), + { + fetch: mockedFetch, + }, + ); expect(mockedFetch).toHaveBeenCalledWith( expect.anything(), @@ -290,10 +299,13 @@ describe("isValidAccessGrant", () => { status: 200, }), ); - await isValidAccessGrant(MOCK_ACCESS_GRANT_BASE as any, { - fetch: mockedFetch, - verificationEndpoint: "https://some.verification.api", - }); + await isValidAccessGrant( + await verifiableCredentialToDataset(MOCK_ACCESS_GRANT_BASE), + { + fetch: mockedFetch, + verificationEndpoint: "https://some.verification.api", + }, + ); expect(mockedFetch).toHaveBeenCalledWith( "https://some.verification.api", expect.anything(), @@ -352,9 +364,12 @@ describe("isValidAccessGrant", () => { }), ); - await isValidAccessGrant(MOCK_ACCESS_GRANT_BASE as any, { - fetch: mockedFetch, - }); + await isValidAccessGrant( + await verifiableCredentialToDataset(MOCK_ACCESS_GRANT_BASE), + { + fetch: mockedFetch, + }, + ); expect(mockedDiscovery).toHaveBeenCalledWith(MOCK_ACCESS_GRANT.issuer); }); diff --git a/src/gConsent/discover/getAccessManagementUi.test.ts b/src/gConsent/discover/getAccessManagementUi.test.ts index 482a45d64..6c10a3740 100644 --- a/src/gConsent/discover/getAccessManagementUi.test.ts +++ b/src/gConsent/discover/getAccessManagementUi.test.ts @@ -20,8 +20,8 @@ // import { jest, describe, it, expect } from "@jest/globals"; -import type { getWellKnownSolid, getSolidDataset } from "@inrupt/solid-client"; -import { mockSolidDatasetFrom } from "@inrupt/solid-client"; +import { getSolidDataset, mockSolidDatasetFrom } from "@inrupt/solid-client"; +import type * as SolidClient from "@inrupt/solid-client"; import { getAccessManagementUi } from "./getAccessManagementUi"; @@ -32,39 +32,36 @@ import { } from "../request/request.mock"; jest.mock("@inrupt/solid-client", () => { - const solidClientModule = jest.requireActual("@inrupt/solid-client") as any; - solidClientModule.getSolidDataset = jest.fn( - solidClientModule.getSolidDataset, - ); - solidClientModule.getWellKnownSolid = jest.fn(); - return solidClientModule; + const solidClientModule = jest.requireActual( + "@inrupt/solid-client", + ) as typeof SolidClient; + return { + ...solidClientModule, + getSolidDataset: jest.fn(), + getWellKnownSolid: jest.fn(), + }; }); describe("getAccessManagementUi", () => { it("uses the provided fetch if any", async () => { - const spiedGetDataset = jest - .spyOn( - jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - }, - "getSolidDataset", - ) - .mockResolvedValueOnce(mockWebIdWithUi("https://some.webid")); + const { getSolidDataset: mockedGetDataset } = jest.requireMock( + "@inrupt/solid-client", + ) as jest.Mocked; + + mockedGetDataset.mockResolvedValueOnce( + mockWebIdWithUi("https://some.webid"), + ); const mockedFetch = jest.fn(); await getAccessManagementUi("https://some.webid", { fetch: mockedFetch }); - expect(spiedGetDataset).toHaveBeenCalledWith("https://some.webid", { + expect(mockedGetDataset).toHaveBeenCalledWith("https://some.webid", { fetch: mockedFetch, }); }); it("throws if the WebID document cannot be dereferenced", async () => { - const solidClient = jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - getWellKnownSolid: typeof getWellKnownSolid; - }; - jest.spyOn(solidClient, "getSolidDataset").mockRejectedValue("Some error"); + jest.mocked(getSolidDataset).mockRejectedValue("Some error"); await expect(getAccessManagementUi("https://some.webid")).rejects.toThrow( /some.webid.*Some error/, @@ -72,12 +69,8 @@ describe("getAccessManagementUi", () => { }); it("throws if the WebID document does not contain the WebID", async () => { - const solidClient = jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - getWellKnownSolid: typeof getWellKnownSolid; - }; jest - .spyOn(solidClient, "getSolidDataset") + .mocked(getSolidDataset) .mockResolvedValue(mockSolidDatasetFrom("https://some.webid")); await expect(getAccessManagementUi("https://some.webid")).rejects.toThrow( @@ -86,48 +79,45 @@ describe("getAccessManagementUi", () => { }); it("returns the IRI advertized by the user's profile when present", async () => { - const solidClient = jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - getWellKnownSolid: typeof getWellKnownSolid; - }; - jest - .spyOn(solidClient, "getSolidDataset") - .mockResolvedValueOnce(mockWebIdWithUi("https://some.webid")); - const spiedGetWellKnown = jest.spyOn(solidClient, "getWellKnownSolid"); + const { + getSolidDataset: mockedGetSolidDataset, + getWellKnownSolid: mockedGetWellKnownSolid, + } = jest.requireMock("@inrupt/solid-client") as jest.Mocked< + typeof SolidClient + >; + mockedGetSolidDataset.mockResolvedValueOnce( + mockWebIdWithUi("https://some.webid"), + ); await expect(getAccessManagementUi("https://some.webid")).resolves.toBe( MOCKED_ACCESS_UI_IRI, ); // If the profile contains a preferred UI, the .well-known document should not be looked up. - expect(spiedGetWellKnown).not.toHaveBeenCalled(); + expect(mockedGetWellKnownSolid).not.toHaveBeenCalled(); }); it("falls back to the IRI advertized by the user's Pod provider when present", async () => { - const solidClient = jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - getWellKnownSolid: typeof getWellKnownSolid; - }; - jest - .spyOn(solidClient, "getSolidDataset") - .mockResolvedValueOnce(mockWebIdWithUi("https://some.webid", false)); - const spiedGetWellKnown = jest - .spyOn(solidClient, "getWellKnownSolid") - .mockResolvedValueOnce(mockWellKnownWithAccess()); + const { + getSolidDataset: mockedGetSolidDataset, + getWellKnownSolid: mockedGetWellKnownSolid, + } = jest.requireMock("@inrupt/solid-client") as jest.Mocked< + typeof SolidClient + >; + mockedGetSolidDataset.mockResolvedValueOnce( + mockWebIdWithUi("https://some.webid", false), + ); + mockedGetWellKnownSolid.mockResolvedValueOnce(mockWellKnownWithAccess()); await expect(getAccessManagementUi("https://some.webid")).resolves.toBe( MOCKED_ACCESS_UI_IRI, ); - expect(spiedGetWellKnown).toHaveBeenCalled(); + expect(mockedGetWellKnownSolid).toHaveBeenCalled(); }); it("returns undefined if the user's WebID does not link to a storage", async () => { - const solidClient = jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - getWellKnownSolid: typeof getWellKnownSolid; - }; jest - .spyOn(solidClient, "getSolidDataset") + .mocked(getSolidDataset) .mockResolvedValueOnce( mockWebIdWithUi("https://some.webid", false, false), ); @@ -138,42 +128,44 @@ describe("getAccessManagementUi", () => { }); it("returns undefined if the host's well-known does not link to a recommended access management UI", async () => { - const solidClient = jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - getWellKnownSolid: typeof getWellKnownSolid; - }; - jest - .spyOn(solidClient, "getSolidDataset") - .mockResolvedValueOnce(mockWebIdWithUi("https://some.webid", false)); - const spiedGetWellKnown = jest - .spyOn(solidClient, "getWellKnownSolid") - .mockResolvedValueOnce(mockWellKnownWithAccess(false)); + const { + getSolidDataset: mockedGetSolidDataset, + getWellKnownSolid: mockedGetWellKnownSolid, + } = jest.requireMock("@inrupt/solid-client") as jest.Mocked< + typeof SolidClient + >; + mockedGetSolidDataset.mockResolvedValueOnce( + mockWebIdWithUi("https://some.webid", false), + ); + mockedGetWellKnownSolid.mockResolvedValueOnce( + mockWellKnownWithAccess(false), + ); await expect( getAccessManagementUi("https://some.webid"), ).resolves.toBeUndefined(); - expect(spiedGetWellKnown).toHaveBeenCalled(); + expect(mockedGetWellKnownSolid).toHaveBeenCalled(); }); it("returns undefined if the host's well-known is empty", async () => { - const solidClient = jest.requireMock("@inrupt/solid-client") as { - getSolidDataset: typeof getSolidDataset; - getWellKnownSolid: typeof getWellKnownSolid; - }; - jest - .spyOn(solidClient, "getSolidDataset") - .mockResolvedValueOnce(mockWebIdWithUi("https://some.webid", false)); - const spiedGetWellKnown = jest - .spyOn(solidClient, "getWellKnownSolid") - .mockResolvedValueOnce( - mockSolidDatasetFrom("https://some.server/.well-known/solid"), - ); + const { + getSolidDataset: mockedGetSolidDataset, + getWellKnownSolid: mockedGetWellKnownSolid, + } = jest.requireMock("@inrupt/solid-client") as jest.Mocked< + typeof SolidClient + >; + mockedGetSolidDataset.mockResolvedValueOnce( + mockWebIdWithUi("https://some.webid", false), + ); + mockedGetWellKnownSolid.mockResolvedValueOnce( + mockSolidDatasetFrom("https://some.server/.well-known/solid"), + ); await expect( getAccessManagementUi("https://some.webid"), ).resolves.toBeUndefined(); - expect(spiedGetWellKnown).toHaveBeenCalled(); + expect(mockedGetWellKnownSolid).toHaveBeenCalled(); }); }); diff --git a/src/gConsent/manage/denyAccessRequest.test.ts b/src/gConsent/manage/denyAccessRequest.test.ts index ce5cee628..2eb796500 100644 --- a/src/gConsent/manage/denyAccessRequest.test.ts +++ b/src/gConsent/manage/denyAccessRequest.test.ts @@ -145,7 +145,7 @@ describe("denyAccessRequest", () => { const denail = await denyAccessRequest(accessRequestVc, { accessEndpoint: "https://some.access-endpoint.override/", - fetch: jest.fn() as typeof fetch, + fetch: jest.fn(), returnLegacyJsonld, }); @@ -178,7 +178,7 @@ describe("denyAccessRequest", () => { JSON.parse(JSON.stringify(accessRequestVc)), { accessEndpoint: "https://some.access-endpoint.override/", - fetch: jest.fn() as typeof fetch, + fetch: jest.fn(), returnLegacyJsonld, }, ); @@ -208,7 +208,7 @@ describe("denyAccessRequest", () => { const legacyDenial = await denyAccessRequest(accessRequestVc, { accessEndpoint: "https://some.access-endpoint.override/", - fetch: jest.fn() as typeof fetch, + fetch: jest.fn(), returnLegacyJsonld: true, }); @@ -223,7 +223,7 @@ describe("denyAccessRequest", () => { const denial = await denyAccessRequest(accessRequestVc, { accessEndpoint: "https://some.access-endpoint.override/", - fetch: jest.fn() as typeof fetch, + fetch: jest.fn(), returnLegacyJsonld: false, }); @@ -285,7 +285,7 @@ describe("denyAccessRequest", () => { purpose: ["https://example.org/some-purpose"], }); await denyAccessRequest(accessRequestWithPurpose, { - fetch: jest.fn() as typeof fetch, + fetch: jest.fn(), returnLegacyJsonld, }); @@ -325,12 +325,12 @@ describe("denyAccessRequest", () => { .spyOn(mockedVcModule, "issueVerifiableCredential") .mockResolvedValueOnce(await mockAccessGrantVc()); const mockedFetch = jest - .fn(global.fetch) + .fn() .mockResolvedValueOnce( new Response(JSON.stringify(await mockAccessRequestVc())), ); await denyAccessRequest("https://some.credential", { - fetch: mockedFetch as typeof fetch, + fetch: mockedFetch, returnLegacyJsonld, }); @@ -365,12 +365,12 @@ describe("denyAccessRequest", () => { .mockResolvedValueOnce(await mockAccessGrantVc()); const mockedFetch = jest - .fn(global.fetch) + .fn() .mockResolvedValueOnce( new Response(JSON.stringify(await mockAccessRequestVc())), ); await denyAccessRequest(new URL("https://some.credential"), { - fetch: mockedFetch as typeof fetch, + fetch: mockedFetch, returnLegacyJsonld, }); diff --git a/src/index.ts b/src/index.ts index 41f0cf2aa..5ba520862 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,7 +39,6 @@ export type { AccessGrantAny } from "./type/AccessGrant"; export type { AccessModes } from "./type/AccessModes"; export type { FetchOptions } from "./type/FetchOptions"; export type { RedirectOptions } from "./type/RedirectOptions"; -export type { SaveInContainerOptions } from "./type/SaveInContainerOptions"; export { CredentialIsAccessGrantAny } from "./type/AccessGrant"; diff --git a/src/resource/createContainerInContainer.test.ts b/src/resource/createContainerInContainer.test.ts index e9e5053d1..3ce321050 100644 --- a/src/resource/createContainerInContainer.test.ts +++ b/src/resource/createContainerInContainer.test.ts @@ -56,16 +56,17 @@ describe("createContainerInContainer", () => { MOCKED_DATASET, ); const mockedFetch = jest.fn(); + const options = { fetch: mockedFetch, slugSuggestion: "NewChildContainer" }; const resultDataset = await createContainerInContainer( TEST_CONTAINER_URL, mockAccessRequest, - { fetch: mockedFetch, slugSuggestion: "NewChildContainer" }, + options, ); expect(fetchWithVc).toHaveBeenCalledWith( TEST_CONTAINER_URL, mockAccessRequest, - { fetch: mockedFetch }, + options, ); expect(solidClientModule.createContainerInContainer).toHaveBeenCalledWith( diff --git a/src/resource/createContainerInContainer.ts b/src/resource/createContainerInContainer.ts index fca0bbc31..8ed24c771 100644 --- a/src/resource/createContainerInContainer.ts +++ b/src/resource/createContainerInContainer.ts @@ -20,14 +20,12 @@ // import type { UrlString } from "@inrupt/solid-client"; -import { createContainerInContainer as coreCreateContainerInContainer } from "@inrupt/solid-client"; +import { createContainerInContainer as solidClientCreateContainerInContainer } from "@inrupt/solid-client"; import type { DatasetWithId, VerifiableCredential, } from "@inrupt/solid-client-vc"; import { fetchWithVc } from "../fetch"; -import type { FetchOptions } from "../type/FetchOptions"; -import type { SaveInContainerOptions } from "../type/SaveInContainerOptions"; /** * Create an empty Container inside the Container at the given URL. @@ -62,21 +60,15 @@ import type { SaveInContainerOptions } from "../type/SaveInContainerOptions"; export async function createContainerInContainer( containerUrl: UrlString, accessGrant: VerifiableCredential | DatasetWithId, - options?: SaveInContainerOptions, + options?: Parameters[1], ) { - const fetchOptions: FetchOptions = {}; - - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - const authenticatedFetch = await fetchWithVc( containerUrl, accessGrant, - fetchOptions, + options, ); - return await coreCreateContainerInContainer(containerUrl, { + return await solidClientCreateContainerInContainer(containerUrl, { ...options, fetch: authenticatedFetch, }); diff --git a/src/resource/deleteFile.ts b/src/resource/deleteFile.ts index f5cc1caef..e6aae28a9 100644 --- a/src/resource/deleteFile.ts +++ b/src/resource/deleteFile.ts @@ -26,7 +26,6 @@ import type { VerifiableCredential, } from "@inrupt/solid-client-vc"; import { fetchWithVc } from "../fetch"; -import type { FetchOptions } from "../type/FetchOptions"; /** * Delete a File from a Solid Pod using an Access Grant to prove the caller @@ -45,18 +44,9 @@ import type { FetchOptions } from "../type/FetchOptions"; export async function deleteFile( fileUrl: UrlString, accessGrant: VerifiableCredential | DatasetWithId, - options?: FetchOptions, + options?: Parameters[1], ) { - const fetchOptions: FetchOptions = {}; - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - - const authenticatedFetch = await fetchWithVc( - fileUrl, - accessGrant, - fetchOptions, - ); + const authenticatedFetch = await fetchWithVc(fileUrl, accessGrant, options); return await coreDeleteFile(fileUrl, { ...options, diff --git a/src/resource/deleteSolidDataset.ts b/src/resource/deleteSolidDataset.ts index 759daf13e..f9660c692 100644 --- a/src/resource/deleteSolidDataset.ts +++ b/src/resource/deleteSolidDataset.ts @@ -26,7 +26,6 @@ import type { VerifiableCredential, } from "@inrupt/solid-client-vc"; import { fetchWithVc } from "../fetch"; -import type { FetchOptions } from "../type/FetchOptions"; /** * Delete a Dataset from a Solid Pod using an Access Grant to prove the caller @@ -45,17 +44,12 @@ import type { FetchOptions } from "../type/FetchOptions"; export async function deleteSolidDataset( datasetUrl: UrlString, accessGrant: VerifiableCredential | DatasetWithId, - options?: FetchOptions, + options?: Parameters[1], ) { - const fetchOptions: FetchOptions = {}; - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - const authenticatedFetch = await fetchWithVc( datasetUrl, accessGrant, - fetchOptions, + options, ); return await coreDeleteSolidDataset(datasetUrl, { diff --git a/src/resource/file.test.ts b/src/resource/file.test.ts index cacd9161a..bdc7cafa3 100644 --- a/src/resource/file.test.ts +++ b/src/resource/file.test.ts @@ -104,17 +104,19 @@ describe("overwriteFile", () => { const fileUrl = "https://some.resource.test/file.txt"; const mockedAccessGrant = await mockAccessRequestVc(); - + const options = { fetch: mockedFetch, contentType: "text/plain" }; const resultFile = await overwriteFile( fileUrl, mockedFile, mockedAccessGrant, - { fetch: mockedFetch, contentType: "text/plain" }, + options, ); - expect(fetchWithVc).toHaveBeenCalledWith(fileUrl, mockedAccessGrant, { - fetch: mockedFetch, - }); + expect(fetchWithVc).toHaveBeenCalledWith( + fileUrl, + mockedAccessGrant, + options, + ); expect(solidClientModule.overwriteFile).toHaveBeenCalledWith( fileUrl, @@ -134,21 +136,24 @@ describe("saveFileInContainer", () => { const containerUrl = "https://some.resource.test/"; const fileNameSuggestion = "test-file.txt"; const mockedAccessGrant = await mockAccessRequestVc(); + const options = { + fetch: mockedFetch, + slug: fileNameSuggestion, + contentType: "text/plain", + }; const resultFile = await saveFileInContainer( containerUrl, mockedFile, mockedAccessGrant, - { - fetch: mockedFetch, - slug: fileNameSuggestion, - contentType: "text/plain", - }, + options, ); - expect(fetchWithVc).toHaveBeenCalledWith(containerUrl, mockedAccessGrant, { - fetch: mockedFetch, - }); + expect(fetchWithVc).toHaveBeenCalledWith( + containerUrl, + mockedAccessGrant, + options, + ); expect(solidClientModule.saveFileInContainer).toHaveBeenCalledWith( containerUrl, diff --git a/src/resource/file.ts b/src/resource/file.ts index dcaac25a5..1e51d985b 100644 --- a/src/resource/file.ts +++ b/src/resource/file.ts @@ -31,7 +31,6 @@ import type { VerifiableCredential, } from "@inrupt/solid-client-vc"; import { fetchWithVc } from "../fetch"; -import type { FetchOptions } from "../type/FetchOptions"; /** * Retrieve a File from a Solid Pod using an Access Grant to prove the caller is @@ -50,20 +49,16 @@ import type { FetchOptions } from "../type/FetchOptions"; export async function getFile( resourceUrl: UrlString, accessGrant: VerifiableCredential | DatasetWithId, - options?: FetchOptions, + options?: Parameters[1], ) { - const fetchOptions: FetchOptions = {}; - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - const authenticatedFetch = await fetchWithVc( resourceUrl, accessGrant, - fetchOptions, + options, ); return await coreGetFile(resourceUrl, { + ...options, fetch: authenticatedFetch, }); } @@ -94,26 +89,16 @@ export async function overwriteFile( resourceUrl: UrlString, file: T, accessGrant: VerifiableCredential | DatasetWithId, - options?: FetchOptions & { contentType?: string }, + options?: Parameters[2], ): Promise { - const fetchOptions: FetchOptions = {}; - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - const authenticatedFetch = await fetchWithVc( resourceUrl, accessGrant, - fetchOptions, + options, ); - const overwriteFileOptions: { contentType?: string } = {}; - if (options && options.contentType) { - overwriteFileOptions.contentType = options.contentType; - } - return await coreOverwriteFile(resourceUrl, file, { - ...overwriteFileOptions, + ...options, fetch: authenticatedFetch, }); } @@ -137,29 +122,15 @@ export async function saveFileInContainer( containerUrl: UrlString, file: T, accessGrant: VerifiableCredential | DatasetWithId, - options?: FetchOptions & { contentType?: string; slug?: string }, + options?: Parameters[2], ): Promise { - const fetchOptions: FetchOptions = {}; - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - const authenticatedFetch = await fetchWithVc( containerUrl, accessGrant, - fetchOptions, + options, ); - - const fileOptions: { contentType?: string; slug?: string } = {}; - if (options && options.contentType) { - fileOptions.contentType = options.contentType; - } - if (options && options.slug) { - fileOptions.slug = options.slug; - } - return await coreSaveFileInContainer(containerUrl, file, { - ...fileOptions, + ...options, fetch: authenticatedFetch, }); } diff --git a/src/resource/getSolidDataset.test.ts b/src/resource/getSolidDataset.test.ts index ae02005ca..eda8f2d32 100644 --- a/src/resource/getSolidDataset.test.ts +++ b/src/resource/getSolidDataset.test.ts @@ -43,7 +43,7 @@ describe("getSolidDataset", () => { const solidClientModule = jest.requireMock("@inrupt/solid-client") as any; const mockedDataset = mockSolidDatasetFrom("https://some.url"); solidClientModule.getSolidDataset.mockResolvedValueOnce(mockedDataset); - const mockedFetch = jest.fn() as typeof fetch; + const mockedFetch = jest.fn(); // TODO: change to mockAccessGrantVc when rebasing const resultDataset = await getSolidDataset( "https://some.dataset.url", diff --git a/src/resource/getSolidDataset.ts b/src/resource/getSolidDataset.ts index 54a7b6e4c..508d3c5fd 100644 --- a/src/resource/getSolidDataset.ts +++ b/src/resource/getSolidDataset.ts @@ -26,7 +26,6 @@ import type { VerifiableCredential, } from "@inrupt/solid-client-vc"; import { fetchWithVc } from "../fetch"; -import type { FetchOptions } from "../type/FetchOptions"; /** * Retrieve a Dataset from a Solid Pod using an Access Grant to prove the caller @@ -45,17 +44,12 @@ import type { FetchOptions } from "../type/FetchOptions"; export async function getSolidDataset( datasetUrl: UrlString, accessGrant: VerifiableCredential | DatasetWithId, - options?: FetchOptions, + options?: Parameters[1], ) { - const fetchOptions: FetchOptions = {}; - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - const authenticatedFetch = await fetchWithVc( datasetUrl, accessGrant, - fetchOptions, + options, ); return await coreGetSolidDataset(datasetUrl, { diff --git a/src/resource/saveSolidDatasetAt.test.ts b/src/resource/saveSolidDatasetAt.test.ts index 1434b1d68..5c9ddf4db 100644 --- a/src/resource/saveSolidDatasetAt.test.ts +++ b/src/resource/saveSolidDatasetAt.test.ts @@ -45,7 +45,7 @@ describe("saveSolidDatasetAt", () => { const solidClientModule = jest.requireMock("@inrupt/solid-client") as any; const mockedDataset = mockSolidDatasetFrom("https://some.url"); solidClientModule.saveSolidDatasetAt.mockResolvedValueOnce(mockedDataset); - const mockedFetch = jest.fn() as typeof fetch; + const mockedFetch = jest.fn(); // TODO: change to mockAccessGrantVc when rebasing const resultDataset = await saveSolidDatasetAt( "https://some.dataset.url", diff --git a/src/resource/saveSolidDatasetAt.ts b/src/resource/saveSolidDatasetAt.ts index 5fd74c869..d9038bdca 100644 --- a/src/resource/saveSolidDatasetAt.ts +++ b/src/resource/saveSolidDatasetAt.ts @@ -19,20 +19,26 @@ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // -import type { UrlString, SolidDataset } from "@inrupt/solid-client"; -import { saveSolidDatasetAt as coreSaveSolidDatasetAt } from "@inrupt/solid-client"; +import { + saveSolidDatasetAt as solidClientSaveSolidDatasetAt, + type SolidDataset, + type UrlString, +} from "@inrupt/solid-client"; import type { DatasetWithId, VerifiableCredential, } from "@inrupt/solid-client-vc"; import { fetchWithVc } from "../fetch"; -import type { FetchOptions } from "../type/FetchOptions"; + +export type solidClientSaveSolidDatasetAtType = + typeof solidClientSaveSolidDatasetAt; /** * Saves a Dataset in a Solid Pod using an Access Grant to prove the caller is * authorized to write or append to the dataset at the given dataset URL. * - * ```{note} This function does not support saving a dataset if the + * ```{note} + * This function does not support saving a dataset if the * dataset does not yet exist, unlike its `@inrupt/solid-client` * counterpart. * ``` @@ -51,20 +57,15 @@ export async function saveSolidDatasetAt( datasetUrl: UrlString, solidDataset: Dataset, accessGrant: VerifiableCredential | DatasetWithId, - options?: FetchOptions, -) { - const fetchOptions: FetchOptions = {}; - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - + options?: Parameters[2], +): ReturnType { const authenticatedFetch = await fetchWithVc( datasetUrl, accessGrant, - fetchOptions, + options, ); - return await coreSaveSolidDatasetAt(datasetUrl, solidDataset, { + return await solidClientSaveSolidDatasetAt(datasetUrl, solidDataset, { ...options, fetch: authenticatedFetch, }); diff --git a/src/resource/saveSolidDatasetInContainer.test.ts b/src/resource/saveSolidDatasetInContainer.test.ts index e6bfb73d7..2b2ffa9c1 100644 --- a/src/resource/saveSolidDatasetInContainer.test.ts +++ b/src/resource/saveSolidDatasetInContainer.test.ts @@ -20,7 +20,7 @@ // import { it, jest, describe, expect, beforeAll } from "@jest/globals"; -import type { UrlString } from "@inrupt/solid-client"; +import type * as SolidClient from "@inrupt/solid-client"; import { mockSolidDatasetFrom } from "@inrupt/solid-client"; import { mockAccessRequestVc } from "../gConsent/util/access.mock"; import { saveSolidDatasetInContainer } from "./saveSolidDatasetInContainer"; @@ -28,13 +28,18 @@ import { fetchWithVc } from "../fetch"; jest.mock("../fetch"); jest.mock("@inrupt/solid-client", () => { - const solidClientModule = jest.requireActual("@inrupt/solid-client") as any; - solidClientModule.saveSolidDatasetInContainer = jest.fn(); - return solidClientModule; + const solidClientModule = jest.requireActual( + "@inrupt/solid-client", + ) as typeof SolidClient; + return { + ...solidClientModule, + saveSolidDatasetInContainer: + jest.fn<(typeof SolidClient)["saveFileInContainer"]>(), + }; }); const MOCKED_DATASET = mockSolidDatasetFrom("https://some.url"); -const TEST_CONTAINER_URL: UrlString = "https://example.com/testContainerUrl"; +const TEST_CONTAINER_URL = "https://example.com/testContainerUrl"; describe("saveSolidDatasetInContainer", () => { let accessRequestVc: Awaited>; @@ -44,25 +49,27 @@ describe("saveSolidDatasetInContainer", () => { }); it("authenticates using the provided VC with a slugSuggestion", async () => { - const solidClientModule = jest.requireMock("@inrupt/solid-client") as any; + const solidClientModule = jest.requireMock( + "@inrupt/solid-client", + ) as jest.Mocked; const mockedDataset = mockSolidDatasetFrom("https://some.url"); solidClientModule.saveSolidDatasetInContainer.mockResolvedValueOnce( mockedDataset, ); - const mockedFetch = jest.fn() as typeof fetch; + const mockedFetch = jest.fn(); - // TODO: change to mockAccessGrantVc when rebasing + const options = { fetch: mockedFetch, slugSuggestion: "test" }; const resultDataset = await saveSolidDatasetInContainer( TEST_CONTAINER_URL, MOCKED_DATASET, accessRequestVc, - { fetch: mockedFetch, slugSuggestion: "test" }, + options, ); expect(fetchWithVc).toHaveBeenCalledWith( TEST_CONTAINER_URL, accessRequestVc, - { fetch: mockedFetch }, + options, ); expect(solidClientModule.saveSolidDatasetInContainer).toHaveBeenCalledWith( diff --git a/src/resource/saveSolidDatasetInContainer.ts b/src/resource/saveSolidDatasetInContainer.ts index f3f282ef3..2e3ed7e1a 100644 --- a/src/resource/saveSolidDatasetInContainer.ts +++ b/src/resource/saveSolidDatasetInContainer.ts @@ -26,8 +26,6 @@ import type { VerifiableCredential, } from "@inrupt/solid-client-vc"; import { fetchWithVc } from "../fetch"; -import type { FetchOptions } from "../type/FetchOptions"; -import type { SaveInContainerOptions } from "../type/SaveInContainerOptions"; /** * Given a SolidDataset, store it in a Solid Pod as a new Resource inside a Container. @@ -64,28 +62,16 @@ export async function saveSolidDatasetInContainer( containerUrl: UrlString, solidDataset: SolidDataset, accessGrant: VerifiableCredential | DatasetWithId, - options: SaveInContainerOptions, + options: Parameters[2], ) { - const fetchOptions: FetchOptions = {}; - - if (options && options.fetch) { - fetchOptions.fetch = options.fetch; - } - const authenticatedFetch = await fetchWithVc( containerUrl, accessGrant, - fetchOptions, + options, ); - const containerOptions: { slugSuggestion?: string } = {}; - - if (options && options.slugSuggestion) { - containerOptions.slugSuggestion = options.slugSuggestion; - } - return await coreSaveSolidDatasetInContainer(containerUrl, solidDataset, { - ...containerOptions, + ...options, fetch: authenticatedFetch, }); } diff --git a/src/type/SaveInContainerOptions.ts b/src/type/SaveInContainerOptions.ts deleted file mode 100644 index d809f830f..000000000 --- a/src/type/SaveInContainerOptions.ts +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright Inrupt Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the -// Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -import type { FetchOptions } from "./FetchOptions"; -/** - * @module interfaces - */ - -/** - * Additional options for saving a dataset/resource in a container. Extends - * FetchOptions and includes: - * - `slugSuggestion`: A user suggested resource/container name. If a container - * does not already have a resource/container in it with that name, it will - * use the slug suggestion as the name. - * - * @since 2.1.0 - */ -// TODO: This should come from @inrupt/solid-client -export interface SaveInContainerOptions extends FetchOptions { - slugSuggestion?: string; -}