parent
8eceab9f3d
commit
50c44354dd
@ -1,9 +0,0 @@ |
||||
import { RequesterResult } from "./RequesterResult"; |
||||
|
||||
export class AbsentResult extends RequesterResult { |
||||
type = "absent" as const; |
||||
|
||||
static is(response: Response): boolean { |
||||
return response.status === 404; |
||||
} |
||||
} |
@ -1,51 +0,0 @@ |
||||
import type { Access } from "@inrupt/solid-client"; |
||||
import { ErrorResult } from "./ErrorResult"; |
||||
import { RequesterResult } from "./RequesterResult"; |
||||
|
||||
export interface AccessRule { |
||||
public?: Access; |
||||
agent?: Record<string, Access>; |
||||
} |
||||
|
||||
export class AccessRuleChangeResult |
||||
extends RequesterResult |
||||
implements AccessRule |
||||
{ |
||||
type = "accessRuleChange" as const; |
||||
readonly public?: Access; |
||||
readonly agent?: Record<string, Access>; |
||||
|
||||
constructor( |
||||
uri: string, |
||||
publicRules?: Access, |
||||
agentRules?: Record<string, Access>, |
||||
) { |
||||
super(uri); |
||||
this.public = publicRules; |
||||
this.agent = agentRules; |
||||
} |
||||
} |
||||
|
||||
export class AccessRuleResult extends RequesterResult implements AccessRule { |
||||
type = "accessRule" as const; |
||||
readonly public: Access; |
||||
readonly agent: Record<string, Access>; |
||||
|
||||
constructor( |
||||
uri: string, |
||||
publicRules: Access, |
||||
agentRules: Record<string, Access>, |
||||
) { |
||||
super(uri); |
||||
this.public = publicRules; |
||||
this.agent = agentRules; |
||||
} |
||||
} |
||||
|
||||
export class AccessRuleFetchError extends ErrorResult { |
||||
readonly errorType = "accessRuleFetch" as const; |
||||
|
||||
constructor(uri: string, message?: string) { |
||||
super(uri, message || `Cannot get access rules for ${uri}.`); |
||||
} |
||||
} |
@ -1,18 +0,0 @@ |
||||
import { RequesterResult } from "./RequesterResult"; |
||||
|
||||
export class BinaryResult extends RequesterResult { |
||||
type = "binary" as const; |
||||
readonly blob: Blob; |
||||
readonly mimeType: string; |
||||
|
||||
constructor(uri: string, blob: Blob, mimeType: string) { |
||||
super(uri); |
||||
this.blob = blob; |
||||
this.mimeType = mimeType; |
||||
} |
||||
|
||||
static is(response: Response): boolean { |
||||
const contentType = response.headers.get("content-type"); |
||||
return !contentType || contentType !== "text/turtle"; |
||||
} |
||||
} |
@ -1,12 +0,0 @@ |
||||
import type { Container } from "../../resource/Container"; |
||||
import type { Leaf } from "../../resource/Leaf"; |
||||
import { RequesterResult } from "./RequesterResult"; |
||||
|
||||
export class CommitChangesSuccess extends RequesterResult { |
||||
readonly type = "commitChangesSuccess" as const; |
||||
readonly affectedResources: (Leaf | Container)[]; |
||||
constructor(uri: string, affectedResources: (Leaf | Container)[]) { |
||||
super(uri); |
||||
this.affectedResources = affectedResources; |
||||
} |
||||
} |
@ -1,27 +0,0 @@ |
||||
import { ErrorResult } from "./ErrorResult"; |
||||
import { RequesterResult } from "./RequesterResult"; |
||||
|
||||
export class DataResult extends RequesterResult { |
||||
type = "data" as const; |
||||
|
||||
static is(response: Response): boolean { |
||||
const contentType = response.headers.get("content-type"); |
||||
return !!contentType && contentType === "text/turtle"; |
||||
} |
||||
} |
||||
|
||||
export class TurtleFormattingError extends ErrorResult { |
||||
errorType = "turtleFormatting" as const; |
||||
|
||||
constructor(uri: string, message?: string) { |
||||
super(uri, message || `Problem parsing turtle for ${uri}`); |
||||
} |
||||
} |
||||
|
||||
export class InvalidUriError extends ErrorResult { |
||||
errorType = "invalidUri" as const; |
||||
|
||||
constructor(uri: string, message?: string) { |
||||
super(uri, message || `${uri} is not a valid uri.`); |
||||
} |
||||
} |
@ -1,7 +0,0 @@ |
||||
export abstract class RequesterResult { |
||||
readonly uri: string; |
||||
abstract readonly type: string; |
||||
constructor(uri: string) { |
||||
this.uri = uri; |
||||
} |
||||
} |
@ -1,35 +1,52 @@ |
||||
import { |
||||
UnexpectedHttpError, |
||||
type HttpErrorResultType, |
||||
} from "../requestResults/HttpErrorResult"; |
||||
import { UnexpectedError } from "../requestResults/ErrorResult"; |
||||
import type { SimpleRequestParams } from "./requestParams"; |
||||
import type { BasicRequestOptions } from "./requestOptions"; |
||||
import { parse as parseLinkHeader } from "http-link-header"; |
||||
import { NoncompliantPodError } from "../results/error/NoncompliantPodError"; |
||||
import { CheckRootContainerSuccess } from "../results/success/CheckRootContainerSuccess"; |
||||
import type { |
||||
HttpErrorResultType, |
||||
UnexpectedHttpError, |
||||
} from "../results/error/HttpErrorResult"; |
||||
import { HttpErrorResult } from "../results/error/HttpErrorResult"; |
||||
import { UnexpectedResourceError } from "../results/error/ErrorResult"; |
||||
import { guaranteeFetch } from "../../util/guaranteeFetch"; |
||||
import type { ContainerUri } from "../../util/uriTypes"; |
||||
|
||||
export type CheckRootResult = CheckRootContainerSuccess | CheckRootResultError; |
||||
export type CheckRootResultError = |
||||
| HttpErrorResultType |
||||
| NoncompliantPodError |
||||
| UnexpectedHttpError |
||||
| UnexpectedResourceError; |
||||
|
||||
export type CheckRootResult = boolean | CheckRootResultError; |
||||
export type CheckRootResultError = HttpErrorResultType | UnexpectedError; |
||||
export function checkHeadersForRootContainer( |
||||
uri: ContainerUri, |
||||
headers: Headers, |
||||
): CheckRootContainerSuccess | NoncompliantPodError { |
||||
const linkHeader = headers.get("link"); |
||||
if (!linkHeader) { |
||||
return new NoncompliantPodError(uri, "No link header present in request."); |
||||
} |
||||
const parsedLinkHeader = parseLinkHeader(linkHeader); |
||||
const types = parsedLinkHeader.get("rel", "type"); |
||||
const isRoot = types.some( |
||||
(type) => type.uri === "http://www.w3.org/ns/pim/space#Storage", |
||||
); |
||||
return new CheckRootContainerSuccess(uri, isRoot); |
||||
} |
||||
|
||||
export async function checkRootContainer({ |
||||
uri, |
||||
fetch, |
||||
}: SimpleRequestParams): Promise<CheckRootResult> { |
||||
export async function checkRootContainer( |
||||
uri: ContainerUri, |
||||
options?: BasicRequestOptions, |
||||
): Promise<CheckRootResult> { |
||||
try { |
||||
const fetch = guaranteeFetch(options?.fetch); |
||||
// Fetch options to determine the document type
|
||||
const response = await fetch(uri, { method: "HEAD" }); |
||||
const linkHeader = response.headers.get("link"); |
||||
if (!linkHeader) { |
||||
return new UnexpectedHttpError( |
||||
uri, |
||||
response, |
||||
"No link header present in request.", |
||||
); |
||||
} |
||||
const parsedLinkHeader = parseLinkHeader(linkHeader); |
||||
const types = parsedLinkHeader.get("rel", "type"); |
||||
return types.some( |
||||
(type) => type.uri === "http://www.w3.org/ns/pim/space#Storage", |
||||
); |
||||
const httpErrorResult = HttpErrorResult.checkResponse(uri, response); |
||||
if (httpErrorResult) return httpErrorResult; |
||||
|
||||
return checkHeadersForRootContainer(uri, response.headers); |
||||
} catch (err) { |
||||
return UnexpectedError.fromThrown(uri, err); |
||||
return UnexpectedResourceError.fromThrown(uri, err); |
||||
} |
||||
} |
||||
|
@ -1,39 +1,45 @@ |
||||
import { namedNode } from "@rdfjs/data-model"; |
||||
import { AbsentResult } from "../requestResults/AbsentResult"; |
||||
import { UnexpectedError } from "../requestResults/ErrorResult"; |
||||
import type { HttpErrorResultType } from "../requestResults/HttpErrorResult"; |
||||
import { UnexpectedHttpError } from "../requestResults/HttpErrorResult"; |
||||
import type { RequestParams } from "./requestParams"; |
||||
import { guaranteeFetch } from "../../util/guaranteeFetch"; |
||||
import { deleteResourceRdfFromContainer } from "../../util/rdfUtils"; |
||||
import { UnexpectedResourceError } from "../results/error/ErrorResult"; |
||||
import type { HttpErrorResultType } from "../results/error/HttpErrorResult"; |
||||
import { UnexpectedHttpError } from "../results/error/HttpErrorResult"; |
||||
import { HttpErrorResult } from "../results/error/HttpErrorResult"; |
||||
import { DeleteSuccess } from "../results/success/DeleteSuccess"; |
||||
import type { DatasetRequestOptions } from "./requestOptions"; |
||||
|
||||
export type DeleteResult = AbsentResult | DeleteResultError; |
||||
export type DeleteResultError = HttpErrorResultType | UnexpectedError; |
||||
export type DeleteResult = DeleteSuccess | DeleteResultError; |
||||
export type DeleteResultError = HttpErrorResultType | UnexpectedResourceError; |
||||
|
||||
export async function deleteResource({ |
||||
uri, |
||||
fetch, |
||||
transaction, |
||||
}: RequestParams): Promise<DeleteResult> { |
||||
export async function deleteResource( |
||||
uri: string, |
||||
options?: DatasetRequestOptions, |
||||
): Promise<DeleteResult> { |
||||
try { |
||||
const fetch = guaranteeFetch(options?.fetch); |
||||
const response = await fetch(uri, { |
||||
method: "delete", |
||||
}); |
||||
const errorResult = HttpErrorResult.checkResponse(uri, response); |
||||
if (errorResult) return errorResult; |
||||
|
||||
// Specifically check for a 205. Annoyingly, the server will return 200 even
|
||||
// if it hasn't been deleted when you're unauthenticated. 404 happens when
|
||||
// the document never existed
|
||||
if (response.status === 205 || response.status === 404) { |
||||
transaction.deleteMatches( |
||||
undefined, |
||||
undefined, |
||||
undefined, |
||||
namedNode(uri), |
||||
); |
||||
deleteResourceRdfFromContainer(uri, transaction); |
||||
return new AbsentResult(uri); |
||||
if (options?.dataset) { |
||||
options.dataset.deleteMatches( |
||||
undefined, |
||||
undefined, |
||||
undefined, |
||||
namedNode(uri), |
||||
); |
||||
deleteResourceRdfFromContainer(uri, options.dataset); |
||||
} |
||||
return new DeleteSuccess(uri, response.status === 205); |
||||
} |
||||
return new UnexpectedHttpError(uri, response); |
||||
} catch (err) { |
||||
return UnexpectedError.fromThrown(uri, err); |
||||
return UnexpectedResourceError.fromThrown(uri, err); |
||||
} |
||||
} |
||||
|
@ -1,64 +1,103 @@ |
||||
import { DataResult } from "../requestResults/DataResult"; |
||||
import type { TurtleFormattingError } from "../requestResults/DataResult"; |
||||
import type { UnexpectedHttpError } from "../results/error/HttpErrorResult"; |
||||
import { |
||||
HttpErrorResult, |
||||
ServerHttpError, |
||||
type HttpErrorResultType, |
||||
} from "../requestResults/HttpErrorResult"; |
||||
import { UnexpectedError } from "../requestResults/ErrorResult"; |
||||
import { AbsentResult } from "../requestResults/AbsentResult"; |
||||
import { BinaryResult } from "../requestResults/BinaryResult"; |
||||
} from "../results/error/HttpErrorResult"; |
||||
import { |
||||
addRawTurtleToDataset, |
||||
addResourceRdfToContainer, |
||||
} from "../../util/rdfUtils"; |
||||
import type { RequestParams } from "./requestParams"; |
||||
import type { DatasetRequestOptions } from "./requestOptions"; |
||||
import type { ContainerUri, LeafUri } from "../../util/uriTypes"; |
||||
import { isContainerUri } from "../../util/uriTypes"; |
||||
import { BinaryReadSuccess } from "../results/success/ReadSuccess"; |
||||
import { |
||||
ContainerReadSuccess, |
||||
DataReadSuccess, |
||||
} from "../results/success/ReadSuccess"; |
||||
import { AbsentReadSuccess } from "../results/success/ReadSuccess"; |
||||
import { NoncompliantPodError } from "../results/error/NoncompliantPodError"; |
||||
import { guaranteeFetch } from "../../util/guaranteeFetch"; |
||||
import { UnexpectedResourceError } from "../results/error/ErrorResult"; |
||||
import { checkHeadersForRootContainer } from "./checkRootContainer"; |
||||
|
||||
export type ReadResult = |
||||
| AbsentResult |
||||
| DataResult |
||||
| BinaryResult |
||||
export type ReadLeafResult = |
||||
| BinaryReadSuccess |
||||
| DataReadSuccess |
||||
| AbsentReadSuccess |
||||
| ReadResultError; |
||||
export type ReadContainerResult = |
||||
| ContainerReadSuccess |
||||
| AbsentReadSuccess |
||||
| ReadResultError; |
||||
export type ReadResultError = |
||||
| HttpErrorResultType |
||||
| TurtleFormattingError |
||||
| UnexpectedError; |
||||
| NoncompliantPodError |
||||
| UnexpectedHttpError |
||||
| UnexpectedResourceError; |
||||
|
||||
export async function readResource({ |
||||
uri, |
||||
fetch, |
||||
transaction, |
||||
}: RequestParams): Promise<ReadResult> { |
||||
export async function readResource( |
||||
uri: LeafUri, |
||||
options?: DatasetRequestOptions, |
||||
): Promise<ReadLeafResult>; |
||||
export async function readResource( |
||||
uri: ContainerUri, |
||||
options?: DatasetRequestOptions, |
||||
): Promise<ReadContainerResult>; |
||||
export async function readResource( |
||||
uri: string, |
||||
options?: DatasetRequestOptions, |
||||
): Promise<ReadLeafResult | ReadContainerResult>; |
||||
export async function readResource( |
||||
uri: string, |
||||
options?: DatasetRequestOptions, |
||||
): Promise<ReadLeafResult | ReadContainerResult> { |
||||
try { |
||||
const fetch = guaranteeFetch(options?.fetch); |
||||
// Fetch options to determine the document type
|
||||
const response = await fetch(uri); |
||||
if (AbsentResult.is(response)) { |
||||
return new AbsentResult(uri); |
||||
if (response.status === 404) { |
||||
return new AbsentReadSuccess(uri, false); |
||||
} |
||||
const httpErrorResult = HttpErrorResult.checkResponse(uri, response); |
||||
if (httpErrorResult) return httpErrorResult; |
||||
|
||||
// Add this resource to the container
|
||||
addResourceRdfToContainer(uri, transaction); |
||||
if (options?.dataset) { |
||||
addResourceRdfToContainer(uri, options.dataset); |
||||
} |
||||
|
||||
const contentType = response.headers.get("content-type"); |
||||
if (!contentType) { |
||||
return new NoncompliantPodError( |
||||
uri, |
||||
"Resource requests must return a content-type header.", |
||||
); |
||||
} |
||||
|
||||
if (DataResult.is(response)) { |
||||
if (contentType === "text/turtle") { |
||||
// Parse Turtle
|
||||
const rawTurtle = await response.text(); |
||||
return addRawTurtleToDataset(rawTurtle, transaction, uri); |
||||
} else { |
||||
// Load Blob
|
||||
const contentType = response.headers.get("content-type"); |
||||
if (!contentType) { |
||||
return new ServerHttpError( |
||||
if (options?.dataset) { |
||||
const result = await addRawTurtleToDataset( |
||||
rawTurtle, |
||||
options.dataset, |
||||
uri, |
||||
response, |
||||
"Server provided no content-type", |
||||
); |
||||
if (result) return result; |
||||
} |
||||
if (isContainerUri(uri)) { |
||||
const result = checkHeadersForRootContainer(uri, response.headers); |
||||
if (result.isError) return result; |
||||
return new ContainerReadSuccess(uri, false, result.isRootContainer); |
||||
} |
||||
return new DataReadSuccess(uri, false); |
||||
} else { |
||||
// Load Blob
|
||||
const blob = await response.blob(); |
||||
return new BinaryResult(uri, blob, contentType); |
||||
return new BinaryReadSuccess(uri, false, blob, contentType); |
||||
} |
||||
} catch (err) { |
||||
return UnexpectedError.fromThrown(uri, err); |
||||
return UnexpectedResourceError.fromThrown(uri, err); |
||||
} |
||||
} |
||||
|
@ -0,0 +1,9 @@ |
||||
import type { Dataset, Quad } from "@rdfjs/types"; |
||||
|
||||
export interface BasicRequestOptions { |
||||
fetch?: typeof fetch; |
||||
} |
||||
|
||||
export interface DatasetRequestOptions extends BasicRequestOptions { |
||||
dataset?: Dataset<Quad>; |
||||
} |
@ -1,10 +0,0 @@ |
||||
import type { TransactionalDataset } from "@ldo/subscribable-dataset"; |
||||
import type { Quad } from "@rdfjs/types"; |
||||
|
||||
export interface RequestParams { |
||||
uri: string; |
||||
fetch: typeof fetch; |
||||
transaction: TransactionalDataset<Quad>; |
||||
} |
||||
|
||||
export type SimpleRequestParams = Omit<RequestParams, "transaction">; |
@ -0,0 +1,8 @@ |
||||
import type { Container } from "../../resource/Container"; |
||||
import type { Leaf } from "../../resource/Leaf"; |
||||
|
||||
export interface RequesterResult { |
||||
type: string; |
||||
isError: boolean; |
||||
resource?: Leaf | Container; |
||||
} |
@ -0,0 +1,5 @@ |
||||
import { ResourceError } from "./ErrorResult"; |
||||
|
||||
export class InvalidUriError extends ResourceError { |
||||
readonly type = "invalidUriError" as const; |
||||
} |
@ -0,0 +1,11 @@ |
||||
import { ResourceError } from "./ErrorResult"; |
||||
|
||||
export class NoncompliantPodError extends ResourceError { |
||||
readonly type = "noncompliantPodError" as const; |
||||
constructor(uri: string, message?: string) { |
||||
super( |
||||
uri, |
||||
`Response from ${uri} is not compliant with the Solid Specification: ${message}`, |
||||
); |
||||
} |
||||
} |
@ -0,0 +1,20 @@ |
||||
import type { Access } from "@inrupt/solid-client"; |
||||
import { ResourceError } from "../error/ErrorResult"; |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export interface AccessRule { |
||||
public?: Access; |
||||
agent?: Record<string, Access>; |
||||
} |
||||
|
||||
export class SetAccessRuleSuccess extends ResourceSuccess { |
||||
type = "setAccessRuleSuccess" as const; |
||||
} |
||||
|
||||
export class AccessRuleFetchError extends ResourceError { |
||||
readonly type = "accessRuleFetchError" as const; |
||||
|
||||
constructor(uri: string, message?: string) { |
||||
super(uri, message || `Cannot get access rules for ${uri}.`); |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export class CheckRootContainerSuccess extends ResourceSuccess { |
||||
readonly type = "checkRootContainerSuccess" as const; |
||||
readonly isRootContainer: boolean; |
||||
|
||||
constructor(uri: string, isRootContainer: boolean) { |
||||
super(uri); |
||||
this.isRootContainer = isRootContainer; |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export class CreateSuccess extends ResourceSuccess { |
||||
readonly type = "createSuccess"; |
||||
readonly didOverwrite: boolean; |
||||
|
||||
constructor(uri: string, didOverwrite: boolean) { |
||||
super(uri); |
||||
this.didOverwrite = didOverwrite; |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export class DeleteSuccess extends ResourceSuccess { |
||||
readonly type = "deleteSuccess" as const; |
||||
readonly resourceExisted: boolean; |
||||
|
||||
constructor(uri: string, resourceExisted: boolean) { |
||||
super(uri); |
||||
this.resourceExisted = resourceExisted; |
||||
} |
||||
} |
@ -0,0 +1,56 @@ |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export abstract class ReadSuccess extends ResourceSuccess { |
||||
recalledFromMemory: boolean; |
||||
constructor(uri: string, recalledFromMemory: boolean) { |
||||
super(uri); |
||||
this.recalledFromMemory = recalledFromMemory; |
||||
} |
||||
} |
||||
|
||||
export class BinaryReadSuccess extends ReadSuccess { |
||||
readonly type = "binaryReadSuccess" as const; |
||||
readonly blob: Blob; |
||||
readonly mimeType: string; |
||||
|
||||
constructor( |
||||
uri: string, |
||||
recalledFromMemory: boolean, |
||||
blob: Blob, |
||||
mimeType: string, |
||||
) { |
||||
super(uri, recalledFromMemory); |
||||
this.blob = blob; |
||||
this.mimeType = mimeType; |
||||
} |
||||
} |
||||
|
||||
export class DataReadSuccess extends ReadSuccess { |
||||
readonly type = "dataReadSuccess" as const; |
||||
|
||||
constructor(uri: string, recalledFromMemory: boolean) { |
||||
super(uri, recalledFromMemory); |
||||
} |
||||
} |
||||
|
||||
export class ContainerReadSuccess extends ReadSuccess { |
||||
readonly type = "containerReadSuccess" as const; |
||||
readonly isRootContainer: boolean; |
||||
|
||||
constructor( |
||||
uri: string, |
||||
recalledFromMemory: boolean, |
||||
isRootContainer: boolean, |
||||
) { |
||||
super(uri, recalledFromMemory); |
||||
this.isRootContainer = isRootContainer; |
||||
} |
||||
} |
||||
|
||||
export class AbsentReadSuccess extends ReadSuccess { |
||||
readonly type = "absentReadSuccess" as const; |
||||
|
||||
constructor(uri: string, recalledFromMemory: boolean) { |
||||
super(uri, recalledFromMemory); |
||||
} |
||||
} |
@ -0,0 +1,30 @@ |
||||
import type { Container } from "../../../resource/Container"; |
||||
import type { Leaf } from "../../../resource/Leaf"; |
||||
import type { RequesterResult } from "../RequesterResult"; |
||||
|
||||
export abstract class SuccessResult implements RequesterResult { |
||||
readonly isError = false as const; |
||||
abstract readonly type: string; |
||||
resource?: Leaf | Container; |
||||
} |
||||
|
||||
export abstract class ResourceSuccess extends SuccessResult { |
||||
readonly uri: string; |
||||
|
||||
constructor(uri: string) { |
||||
super(); |
||||
this.uri = uri; |
||||
} |
||||
} |
||||
|
||||
export class AggregateSuccess< |
||||
SuccessType extends SuccessResult, |
||||
> extends SuccessResult { |
||||
readonly type = "aggregateError" as const; |
||||
readonly results: SuccessType[]; |
||||
|
||||
constructor(results: SuccessType[]) { |
||||
super(); |
||||
this.results = results; |
||||
} |
||||
} |
@ -0,0 +1,5 @@ |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export class Unfetched extends ResourceSuccess { |
||||
readonly type = "unfetched" as const; |
||||
} |
@ -0,0 +1,5 @@ |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
export class UpdateSuccess extends ResourceSuccess { |
||||
readonly type = "updateSuccess"; |
||||
} |
@ -0,0 +1,10 @@ |
||||
import type { LeafCreateAndOverwriteResult } from "../requester/requests/createDataResource"; |
||||
import { createDataResource } from "../requester/requests/createDataResource"; |
||||
import type { RequesterResult } from "../requester/results/RequesterResult"; |
||||
import type { Container } from "./Container"; |
||||
import type { Leaf } from "./Leaf"; |
||||
|
||||
export type ResourceResult< |
||||
Result extends RequesterResult, |
||||
ResourceType extends Leaf | Container, |
||||
> = Result & { resource: ResourceType }; |
@ -0,0 +1,14 @@ |
||||
import { CreateSuccess } from "../../requester/results/success/CreateSuccess"; |
||||
import type { Container } from "../Container"; |
||||
import type { Leaf } from "../Leaf"; |
||||
|
||||
export class CreateResourceSuccess< |
||||
ResourceType extends Leaf | Container, |
||||
> extends CreateSuccess { |
||||
readonly createdResource: ResourceType; |
||||
|
||||
constructor(uri: string, didOverwrite: boolean, resource: ResourceType) { |
||||
super(uri, didOverwrite); |
||||
this.createdResource = resource; |
||||
} |
||||
} |
@ -0,0 +1,14 @@ |
||||
import { DeleteSuccess } from "../../requester/results/success/DeleteSuccess"; |
||||
import type { Container } from "../Container"; |
||||
import type { Leaf } from "../Leaf"; |
||||
|
||||
export class DeleteResourceSuccess< |
||||
ResourceType extends Leaf | Container, |
||||
> extends DeleteSuccess { |
||||
readonly deletedResource: ResourceType; |
||||
|
||||
constructor(uri: string, resourceExisted: boolean, resource: ResourceType) { |
||||
super(uri, resourceExisted); |
||||
this.deletedResource = resource; |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
import { SuccessResult } from "../../requester/results/success/SuccessResult"; |
||||
import type { Container } from "../Container"; |
||||
|
||||
export class GetRootContainerSuccess extends SuccessResult { |
||||
readonly type = "getRootContainerSuccess" as const; |
||||
readonly rootContainer: Container; |
||||
|
||||
constructor(rootContainer: Container) { |
||||
super(); |
||||
this.rootContainer = rootContainer; |
||||
} |
||||
} |
@ -0,0 +1,72 @@ |
||||
import type { ReadResultError } from "../../requester/requests/readResource"; |
||||
import { |
||||
AbsentReadSuccess, |
||||
BinaryReadSuccess, |
||||
ContainerReadSuccess, |
||||
DataReadSuccess, |
||||
} from "../../requester/results/success/ReadSuccess"; |
||||
import type { Container } from "../Container"; |
||||
import type { Leaf } from "../Leaf"; |
||||
|
||||
export type ReadResourceSuccessContainerTypes = |
||||
| ContainerResourceReadSuccess |
||||
| AbsentResourceReadSuccess<Container> |
||||
| ReadResultError; |
||||
export type ReadResourceSuccessLeafTypes = |
||||
| DataResourceReadSuccess |
||||
| BinaryResourceReadSuccess |
||||
| AbsentResourceReadSuccess<Leaf> |
||||
| ReadResultError; |
||||
|
||||
export class DataResourceReadSuccess extends DataReadSuccess { |
||||
readonly readResource: Leaf; |
||||
|
||||
constructor(uri: string, recalledFromMemory: boolean, resource: Leaf) { |
||||
super(uri, recalledFromMemory); |
||||
this.readResource = resource; |
||||
} |
||||
} |
||||
|
||||
export class BinaryResourceReadSuccess extends BinaryReadSuccess { |
||||
readonly readResource: Leaf; |
||||
|
||||
constructor( |
||||
uri: string, |
||||
recalledFromMemory: boolean, |
||||
blob: Blob, |
||||
mimeType: string, |
||||
resource: Leaf, |
||||
) { |
||||
super(uri, recalledFromMemory, blob, mimeType); |
||||
this.readResource = resource; |
||||
} |
||||
} |
||||
|
||||
export class ContainerResourceReadSuccess extends ContainerReadSuccess { |
||||
readonly readResource: Container; |
||||
|
||||
constructor( |
||||
uri: string, |
||||
recalledFromMemory: boolean, |
||||
isRootContainer: boolean, |
||||
resource: Container, |
||||
) { |
||||
super(uri, recalledFromMemory, isRootContainer); |
||||
this.readResource = resource; |
||||
} |
||||
} |
||||
|
||||
export class AbsentResourceReadSuccess< |
||||
ResourceType extends Leaf | Container, |
||||
> extends AbsentReadSuccess { |
||||
readonly readResource: ResourceType; |
||||
|
||||
constructor( |
||||
uri: string, |
||||
recalledFromMemory: boolean, |
||||
resource: ResourceType, |
||||
) { |
||||
super(uri, recalledFromMemory); |
||||
this.readResource = resource; |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
import { UpdateSuccess } from "../../requester/results/success/UpdateSuccess"; |
||||
import type { Leaf } from "../Leaf"; |
||||
|
||||
export class UpdateResourceSuccess extends UpdateSuccess { |
||||
readonly updatedResource: Leaf; |
||||
|
||||
constructor(uri: string, resource: Leaf) { |
||||
super(uri); |
||||
this.updatedResource = resource; |
||||
} |
||||
} |
@ -0,0 +1,5 @@ |
||||
import crossFetch from "cross-fetch"; |
||||
|
||||
export function guaranteeFetch(fetchInput?: typeof fetch): typeof fetch { |
||||
return fetchInput || crossFetch; |
||||
} |
Loading…
Reference in new issue