/* eslint-disable @typescript-eslint/no-explicit-any */ import { guaranteeFetch } from "../../util/guaranteeFetch"; import type { AbsentReadSuccess, Resource } from "@ldo/connected"; import { UnexpectedResourceError } from "@ldo/connected"; import type { HttpErrorResultType } from "../results/error/HttpErrorResult"; import { HttpErrorResult } from "../results/error/HttpErrorResult"; import { CreateSuccess } from "../results/success/CreateSuccess"; import type { DeleteResultError } from "./deleteResource"; import { deleteResource } from "./deleteResource"; import type { ReadContainerResult, ReadLeafResult, ReadResultError, } from "./readResource"; import { readResource } from "./readResource"; import type { DatasetRequestOptions } from "./requestOptions"; import type { SolidLeaf } from "../../resources/SolidLeaf"; import type { SolidContainer } from "../../resources/SolidContainer"; import { addResourceRdfToContainer, getParentUri, getSlug, } from "../../util/rdfUtils"; /** * All possible return values when creating and overwriting a container */ export type ContainerCreateAndOverwriteResult = | CreateSuccess | CreateAndOverwriteResultErrors; /** * All possible return values when creating and overwriting a leaf */ export type LeafCreateAndOverwriteResult = | CreateSuccess | CreateAndOverwriteResultErrors; /** * All possible return values when creating a container if absent */ export type ContainerCreateIfAbsentResult = | CreateSuccess | Exclude> | CreateIfAbsentResultErrors; /** * All possible return values when creating a leaf if absent */ export type LeafCreateIfAbsentResult = | CreateSuccess | Exclude> | CreateIfAbsentResultErrors; /** * All possible errors returned by creating and overwriting a resource */ export type CreateAndOverwriteResultErrors = | DeleteResultError | CreateErrors; /** * All possible errors returned by creating a resource if absent */ export type CreateIfAbsentResultErrors = | ReadResultError | CreateErrors; /** * All possible errors returned by creating a resource */ export type CreateErrors = | HttpErrorResultType | UnexpectedResourceError; /** * @internal * Creates a data resource (RDF resource) at the provided URI. This resource * could also be a container. * * @param resource - The resource * @param overwrite - If true, the request will overwrite any previous resource * at this URI. * @param options - Options to provide a fetch function and a local dataset to * update. * @returns One of many create results depending on the input */ export function createDataResource( resource: SolidLeaf, overwrite: true, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resouce: SolidLeaf, overwrite: true, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resouce: SolidContainer, overwrite?: false, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resouce: SolidLeaf, overwrite?: false, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resouce: SolidContainer, overwrite?: boolean, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resouce: SolidLeaf, overwrite?: boolean, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resource: SolidContainer | SolidLeaf, overwrite: true, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resource: SolidContainer | SolidLeaf, overwrite?: false, options?: DatasetRequestOptions, ): Promise; export function createDataResource( resource: SolidContainer | SolidLeaf, overwrite?: boolean, options?: DatasetRequestOptions, ): Promise< | ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult | ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult >; export async function createDataResource( resource: SolidContainer | SolidLeaf, overwrite?: boolean, options?: DatasetRequestOptions, ): Promise< | ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult | ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult > { try { const fetch = guaranteeFetch(options?.fetch); let didOverwrite = false; if (overwrite) { const deleteResult = await deleteResource(resource, options); // Return if it wasn't deleted if (deleteResult.isError) return deleteResult as | DeleteResultError | DeleteResultError; didOverwrite = deleteResult.resourceExisted; } else { // Perform a read to check if it exists const readResult = await readResource(resource, options); // If it does exist stop and return. if (readResult.type !== "absentReadSuccess") { return readResult; } } // Create the document const parentUri = getParentUri(resource.uri)!; const headers: HeadersInit = { "content-type": "text/turtle", slug: getSlug(resource.uri), }; if (resource.type === "SolidContainer") { headers.link = '; rel="type"'; } const response = await fetch(parentUri, { method: "post", headers, }); const httpError = HttpErrorResult.checkResponse(resource, response); if (httpError) return httpError as | HttpErrorResultType | HttpErrorResultType; if (options?.dataset) { addResourceRdfToContainer(resource.uri, options.dataset); } return new CreateSuccess(resource, didOverwrite) as | CreateSuccess | CreateSuccess; } catch (err) { return UnexpectedResourceError.fromThrown(resource, err) as | UnexpectedResourceError | UnexpectedResourceError; } }