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 { |
import type { BasicRequestOptions } from "./requestOptions"; |
||||||
UnexpectedHttpError, |
|
||||||
type HttpErrorResultType, |
|
||||||
} from "../requestResults/HttpErrorResult"; |
|
||||||
import { UnexpectedError } from "../requestResults/ErrorResult"; |
|
||||||
import type { SimpleRequestParams } from "./requestParams"; |
|
||||||
import { parse as parseLinkHeader } from "http-link-header"; |
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 function checkHeadersForRootContainer( |
||||||
export type CheckRootResultError = HttpErrorResultType | UnexpectedError; |
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({ |
export async function checkRootContainer( |
||||||
uri, |
uri: ContainerUri, |
||||||
fetch, |
options?: BasicRequestOptions, |
||||||
}: SimpleRequestParams): Promise<CheckRootResult> { |
): Promise<CheckRootResult> { |
||||||
try { |
try { |
||||||
|
const fetch = guaranteeFetch(options?.fetch); |
||||||
// Fetch options to determine the document type
|
// Fetch options to determine the document type
|
||||||
const response = await fetch(uri, { method: "HEAD" }); |
const response = await fetch(uri, { method: "HEAD" }); |
||||||
const linkHeader = response.headers.get("link"); |
const httpErrorResult = HttpErrorResult.checkResponse(uri, response); |
||||||
if (!linkHeader) { |
if (httpErrorResult) return httpErrorResult; |
||||||
return new UnexpectedHttpError( |
|
||||||
uri, |
return checkHeadersForRootContainer(uri, response.headers); |
||||||
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", |
|
||||||
); |
|
||||||
} catch (err) { |
} catch (err) { |
||||||
return UnexpectedError.fromThrown(uri, err); |
return UnexpectedResourceError.fromThrown(uri, err); |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,39 +1,45 @@ |
|||||||
import { namedNode } from "@rdfjs/data-model"; |
import { namedNode } from "@rdfjs/data-model"; |
||||||
import { AbsentResult } from "../requestResults/AbsentResult"; |
import { guaranteeFetch } from "../../util/guaranteeFetch"; |
||||||
import { UnexpectedError } from "../requestResults/ErrorResult"; |
|
||||||
import type { HttpErrorResultType } from "../requestResults/HttpErrorResult"; |
|
||||||
import { UnexpectedHttpError } from "../requestResults/HttpErrorResult"; |
|
||||||
import type { RequestParams } from "./requestParams"; |
|
||||||
import { deleteResourceRdfFromContainer } from "../../util/rdfUtils"; |
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 DeleteResult = DeleteSuccess | DeleteResultError; |
||||||
export type DeleteResultError = HttpErrorResultType | UnexpectedError; |
export type DeleteResultError = HttpErrorResultType | UnexpectedResourceError; |
||||||
|
|
||||||
export async function deleteResource({ |
export async function deleteResource( |
||||||
uri, |
uri: string, |
||||||
fetch, |
options?: DatasetRequestOptions, |
||||||
transaction, |
): Promise<DeleteResult> { |
||||||
}: RequestParams): Promise<DeleteResult> { |
|
||||||
try { |
try { |
||||||
|
const fetch = guaranteeFetch(options?.fetch); |
||||||
const response = await fetch(uri, { |
const response = await fetch(uri, { |
||||||
method: "delete", |
method: "delete", |
||||||
}); |
}); |
||||||
|
const errorResult = HttpErrorResult.checkResponse(uri, response); |
||||||
|
if (errorResult) return errorResult; |
||||||
|
|
||||||
// Specifically check for a 205. Annoyingly, the server will return 200 even
|
// 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
|
// if it hasn't been deleted when you're unauthenticated. 404 happens when
|
||||||
// the document never existed
|
// the document never existed
|
||||||
if (response.status === 205 || response.status === 404) { |
if (response.status === 205 || response.status === 404) { |
||||||
transaction.deleteMatches( |
if (options?.dataset) { |
||||||
undefined, |
options.dataset.deleteMatches( |
||||||
undefined, |
undefined, |
||||||
undefined, |
undefined, |
||||||
namedNode(uri), |
undefined, |
||||||
); |
namedNode(uri), |
||||||
deleteResourceRdfFromContainer(uri, transaction); |
); |
||||||
return new AbsentResult(uri); |
deleteResourceRdfFromContainer(uri, options.dataset); |
||||||
|
} |
||||||
|
return new DeleteSuccess(uri, response.status === 205); |
||||||
} |
} |
||||||
return new UnexpectedHttpError(uri, response); |
return new UnexpectedHttpError(uri, response); |
||||||
} catch (err) { |
} catch (err) { |
||||||
return UnexpectedError.fromThrown(uri, err); |
return UnexpectedResourceError.fromThrown(uri, err); |
||||||
} |
} |
||||||
} |
} |
||||||
|
@ -1,64 +1,103 @@ |
|||||||
import { DataResult } from "../requestResults/DataResult"; |
import type { UnexpectedHttpError } from "../results/error/HttpErrorResult"; |
||||||
import type { TurtleFormattingError } from "../requestResults/DataResult"; |
|
||||||
import { |
import { |
||||||
HttpErrorResult, |
HttpErrorResult, |
||||||
ServerHttpError, |
|
||||||
type HttpErrorResultType, |
type HttpErrorResultType, |
||||||
} from "../requestResults/HttpErrorResult"; |
} from "../results/error/HttpErrorResult"; |
||||||
import { UnexpectedError } from "../requestResults/ErrorResult"; |
|
||||||
import { AbsentResult } from "../requestResults/AbsentResult"; |
|
||||||
import { BinaryResult } from "../requestResults/BinaryResult"; |
|
||||||
import { |
import { |
||||||
addRawTurtleToDataset, |
addRawTurtleToDataset, |
||||||
addResourceRdfToContainer, |
addResourceRdfToContainer, |
||||||
} from "../../util/rdfUtils"; |
} 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 = |
export type ReadLeafResult = |
||||||
| AbsentResult |
| BinaryReadSuccess |
||||||
| DataResult |
| DataReadSuccess |
||||||
| BinaryResult |
| AbsentReadSuccess |
||||||
|
| ReadResultError; |
||||||
|
export type ReadContainerResult = |
||||||
|
| ContainerReadSuccess |
||||||
|
| AbsentReadSuccess |
||||||
| ReadResultError; |
| ReadResultError; |
||||||
export type ReadResultError = |
export type ReadResultError = |
||||||
| HttpErrorResultType |
| HttpErrorResultType |
||||||
| TurtleFormattingError |
| NoncompliantPodError |
||||||
| UnexpectedError; |
| UnexpectedHttpError |
||||||
|
| UnexpectedResourceError; |
||||||
|
|
||||||
export async function readResource({ |
export async function readResource( |
||||||
uri, |
uri: LeafUri, |
||||||
fetch, |
options?: DatasetRequestOptions, |
||||||
transaction, |
): Promise<ReadLeafResult>; |
||||||
}: RequestParams): Promise<ReadResult> { |
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 { |
try { |
||||||
|
const fetch = guaranteeFetch(options?.fetch); |
||||||
// Fetch options to determine the document type
|
// Fetch options to determine the document type
|
||||||
const response = await fetch(uri); |
const response = await fetch(uri); |
||||||
if (AbsentResult.is(response)) { |
if (response.status === 404) { |
||||||
return new AbsentResult(uri); |
return new AbsentReadSuccess(uri, false); |
||||||
} |
} |
||||||
const httpErrorResult = HttpErrorResult.checkResponse(uri, response); |
const httpErrorResult = HttpErrorResult.checkResponse(uri, response); |
||||||
if (httpErrorResult) return httpErrorResult; |
if (httpErrorResult) return httpErrorResult; |
||||||
|
|
||||||
// Add this resource to the container
|
// 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
|
// Parse Turtle
|
||||||
const rawTurtle = await response.text(); |
const rawTurtle = await response.text(); |
||||||
return addRawTurtleToDataset(rawTurtle, transaction, uri); |
if (options?.dataset) { |
||||||
} else { |
const result = await addRawTurtleToDataset( |
||||||
// Load Blob
|
rawTurtle, |
||||||
const contentType = response.headers.get("content-type"); |
options.dataset, |
||||||
if (!contentType) { |
|
||||||
return new ServerHttpError( |
|
||||||
uri, |
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(); |
const blob = await response.blob(); |
||||||
return new BinaryResult(uri, blob, contentType); |
return new BinaryReadSuccess(uri, false, blob, contentType); |
||||||
} |
} |
||||||
} catch (err) { |
} 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