Refactored to have include a direct link to the object in the return

main
Ailin Luca 2 years ago
parent 50c44354dd
commit fea6e3096a
  1. 16
      packages/solid/src/SolidLdoDataset.ts
  2. 11
      packages/solid/src/requester/requests/checkRootContainer.ts
  3. 9
      packages/solid/src/requester/requests/createDataResource.ts
  4. 9
      packages/solid/src/requester/requests/deleteResource.ts
  5. 37
      packages/solid/src/requester/requests/readResource.ts
  6. 10
      packages/solid/src/requester/requests/setAccessRules.ts
  7. 4
      packages/solid/src/requester/results/RequesterResult.ts
  8. 9
      packages/solid/src/requester/results/error/AccessControlError.ts
  9. 3
      packages/solid/src/requester/results/error/ErrorResult.ts
  10. 4
      packages/solid/src/requester/results/error/InvalidUriError.ts
  11. 15
      packages/solid/src/requester/results/success/AccessRule.ts
  12. 13
      packages/solid/src/requester/results/success/CheckRootContainerSuccess.ts
  13. 13
      packages/solid/src/requester/results/success/CreateSuccess.ts
  14. 13
      packages/solid/src/requester/results/success/DeleteSuccess.ts
  15. 65
      packages/solid/src/requester/results/success/ReadSuccess.ts
  16. 31
      packages/solid/src/requester/results/success/SuccessResult.ts
  17. 6
      packages/solid/src/requester/results/success/Unfetched.ts
  18. 6
      packages/solid/src/requester/results/success/UpdateSuccess.ts
  19. 145
      packages/solid/src/resource/Container.ts
  20. 88
      packages/solid/src/resource/Leaf.ts
  21. 59
      packages/solid/src/resource/Resource.ts
  22. 10
      packages/solid/src/resource/ResourceResult.ts
  23. 13
      packages/solid/src/resource/resourceResult/ResourceResult.ts
  24. 14
      packages/solid/src/resource/resourceResults/CreateResourceSuccess.ts
  25. 14
      packages/solid/src/resource/resourceResults/DeleteResourceSuccess.ts
  26. 12
      packages/solid/src/resource/resourceResults/GetRootContainerSuccess.ts
  27. 72
      packages/solid/src/resource/resourceResults/ReadResourceSuccess.ts
  28. 11
      packages/solid/src/resource/resourceResults/UpdateResourceSuccess.ts

@ -7,10 +7,11 @@ import type {
} from "./requester/requests/updateDataResource";
import { AggregateError } from "./requester/results/error/ErrorResult";
import { InvalidUriError } from "./requester/results/error/InvalidUriError";
import { AggregateSuccess } from "./requester/results/success/SuccessResult";
import type { AggregateSuccess } from "./requester/results/success/SuccessResult";
import type { UpdateSuccess } from "./requester/results/success/UpdateSuccess";
import type { Container } from "./resource/Container";
import type { Leaf } from "./resource/Leaf";
import type { ResourceResult } from "./resource/resourceResult/ResourceResult";
import type { ResourceGetterOptions } from "./ResourceStore";
import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext";
import { splitChangesByGraph } from "./util/splitChangesByGraph";
@ -39,7 +40,7 @@ export class SolidLdoDataset extends LdoDataset {
async commitChangesToPod(
changes: DatasetChanges<Quad>,
): Promise<
| AggregateSuccess<UpdateSuccess>
| AggregateSuccess<ResourceResult<UpdateSuccess, Leaf>>
| AggregateError<UpdateResultError | InvalidUriError>
> {
const changesByGraph = splitChangesByGraph(changes);
@ -84,12 +85,15 @@ export class SolidLdoDataset extends LdoDataset {
),
);
}
return new AggregateSuccess(
results
return {
isError: false,
type: "aggregateSuccess",
results: results
.map((result) => result[2])
.filter(
(result): result is UpdateSuccess => result.type === "updateSuccess",
(result): result is ResourceResult<UpdateSuccess, Leaf> =>
result.type === "updateSuccess",
),
);
};
}
}

@ -1,7 +1,7 @@
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 { CheckRootContainerSuccess } from "../results/success/CheckRootContainerSuccess";
import type {
HttpErrorResultType,
UnexpectedHttpError,
@ -28,10 +28,15 @@ export function checkHeadersForRootContainer(
}
const parsedLinkHeader = parseLinkHeader(linkHeader);
const types = parsedLinkHeader.get("rel", "type");
const isRoot = types.some(
const isRootContainer = types.some(
(type) => type.uri === "http://www.w3.org/ns/pim/space#Storage",
);
return new CheckRootContainerSuccess(uri, isRoot);
return {
uri,
isRootContainer,
type: "checkRootContainerSuccess",
isError: false,
};
}
export async function checkRootContainer(

@ -9,7 +9,7 @@ import { isContainerUri } from "../../util/uriTypes";
import { UnexpectedResourceError } from "../results/error/ErrorResult";
import type { HttpErrorResultType } from "../results/error/HttpErrorResult";
import { HttpErrorResult } from "../results/error/HttpErrorResult";
import { CreateSuccess } from "../results/success/CreateSuccess";
import type { CreateSuccess } from "../results/success/CreateSuccess";
import type { AbsentReadSuccess } from "../results/success/ReadSuccess";
import type { DeleteResultError } from "./deleteResource";
import { deleteResource } from "./deleteResource";
@ -134,7 +134,12 @@ export async function createDataResource(
if (options?.dataset) {
addResourceRdfToContainer(uri, options.dataset);
}
return new CreateSuccess(uri, !!overwrite);
return {
isError: false,
type: "createSuccess",
uri,
didOverwrite: !!overwrite,
};
} catch (err) {
return UnexpectedResourceError.fromThrown(uri, err);
}

@ -5,7 +5,7 @@ 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 { DeleteSuccess } from "../results/success/DeleteSuccess";
import type { DatasetRequestOptions } from "./requestOptions";
export type DeleteResult = DeleteSuccess | DeleteResultError;
@ -36,7 +36,12 @@ export async function deleteResource(
);
deleteResourceRdfFromContainer(uri, options.dataset);
}
return new DeleteSuccess(uri, response.status === 205);
return {
isError: false,
type: "deleteSuccess",
uri,
resourceExisted: response.status === 205,
};
}
return new UnexpectedHttpError(uri, response);
} catch (err) {

@ -10,12 +10,12 @@ import {
import type { DatasetRequestOptions } from "./requestOptions";
import type { ContainerUri, LeafUri } from "../../util/uriTypes";
import { isContainerUri } from "../../util/uriTypes";
import { BinaryReadSuccess } from "../results/success/ReadSuccess";
import {
import type { BinaryReadSuccess } from "../results/success/ReadSuccess";
import type {
ContainerReadSuccess,
DataReadSuccess,
} from "../results/success/ReadSuccess";
import { AbsentReadSuccess } from "../results/success/ReadSuccess";
import type { AbsentReadSuccess } from "../results/success/ReadSuccess";
import { NoncompliantPodError } from "../results/error/NoncompliantPodError";
import { guaranteeFetch } from "../../util/guaranteeFetch";
import { UnexpectedResourceError } from "../results/error/ErrorResult";
@ -57,7 +57,12 @@ export async function readResource(
// Fetch options to determine the document type
const response = await fetch(uri);
if (response.status === 404) {
return new AbsentReadSuccess(uri, false);
return {
isError: false,
type: "absentReadSuccess",
uri,
recalledFromMemory: false,
};
}
const httpErrorResult = HttpErrorResult.checkResponse(uri, response);
if (httpErrorResult) return httpErrorResult;
@ -89,13 +94,31 @@ export async function readResource(
if (isContainerUri(uri)) {
const result = checkHeadersForRootContainer(uri, response.headers);
if (result.isError) return result;
return new ContainerReadSuccess(uri, false, result.isRootContainer);
return {
isError: false,
type: "containerReadSuccess",
uri,
recalledFromMemory: false,
isRootContainer: result.isRootContainer,
};
}
return new DataReadSuccess(uri, false);
return {
isError: false,
type: "dataReadSuccess",
uri,
recalledFromMemory: false,
};
} else {
// Load Blob
const blob = await response.blob();
return new BinaryReadSuccess(uri, false, blob, contentType);
return {
isError: false,
type: "binaryReadSuccess",
uri,
recalledFromMemory: false,
blob,
mimeType: contentType,
};
}
} catch (err) {
return UnexpectedResourceError.fromThrown(uri, err);

@ -15,8 +15,8 @@ import {
import { guaranteeFetch } from "../../util/guaranteeFetch";
import { isContainerUri } from "../../util/uriTypes";
import type { AccessRule } from "../results/success/AccessRule";
import { SetAccessRuleSuccess } from "../results/success/AccessRule";
import { AccessRuleFetchError } from "../results/success/AccessRule";
import type { SetAccessRuleSuccess } from "../results/success/AccessRule";
import { AccessRuleFetchError } from "../results/error/AccessControlError";
import type { BasicRequestOptions } from "./requestOptions";
export type SetAccessRulesResult =
@ -78,5 +78,9 @@ export async function setAccessRules(
// Now save the ACL:
await saveAclFor(myDatasetWithAcl, updatedAcl, { fetch });
return new SetAccessRuleSuccess(uri);
return {
isError: false,
uri,
type: "setAccessRuleSuccess",
};
}

@ -1,8 +1,4 @@
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,9 @@
import { ResourceError } from "./ErrorResult";
export class AccessRuleFetchError extends ResourceError {
readonly type = "accessRuleFetchError" as const;
constructor(uri: string, message?: string) {
super(uri, message || `${uri} had trouble fetching access rules.`);
}
}

@ -1,11 +1,8 @@
import type { Container } from "../../../resource/Container";
import type { Leaf } from "../../../resource/Leaf";
import type { RequesterResult } from "../RequesterResult";
export abstract class ErrorResult extends Error implements RequesterResult {
abstract type: string;
readonly isError = true as const;
resource?: Leaf | Container;
constructor(message?: string) {
super(message || "An error unkown error was encountered.");

@ -2,4 +2,8 @@ import { ResourceError } from "./ErrorResult";
export class InvalidUriError extends ResourceError {
readonly type = "invalidUriError" as const;
constructor(uri: string, message?: string) {
super(uri, message || `${uri} is an invalid uri.`);
}
}

@ -1,20 +1,11 @@
import type { Access } from "@inrupt/solid-client";
import { ResourceError } from "../error/ErrorResult";
import { ResourceSuccess } from "./SuccessResult";
import type { 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}.`);
}
export interface SetAccessRuleSuccess extends ResourceSuccess {
type: "setAccessRuleSuccess";
}

@ -1,11 +1,6 @@
import { ResourceSuccess } from "./SuccessResult";
import type { 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;
}
export interface CheckRootContainerSuccess extends ResourceSuccess {
type: "checkRootContainerSuccess";
isRootContainer: boolean;
}

@ -1,11 +1,6 @@
import { ResourceSuccess } from "./SuccessResult";
import type { ResourceSuccess } from "./SuccessResult";
export class CreateSuccess extends ResourceSuccess {
readonly type = "createSuccess";
readonly didOverwrite: boolean;
constructor(uri: string, didOverwrite: boolean) {
super(uri);
this.didOverwrite = didOverwrite;
}
export interface CreateSuccess extends ResourceSuccess {
type: "createSuccess";
didOverwrite: boolean;
}

@ -1,11 +1,6 @@
import { ResourceSuccess } from "./SuccessResult";
import type { 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;
}
export interface DeleteSuccess extends ResourceSuccess {
type: "deleteSuccess";
resourceExisted: boolean;
}

@ -1,56 +1,33 @@
import { ResourceSuccess } from "./SuccessResult";
import type { ResourceSuccess, SuccessResult } from "./SuccessResult";
export abstract class ReadSuccess extends ResourceSuccess {
export interface 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 interface BinaryReadSuccess extends ReadSuccess {
type: "binaryReadSuccess";
blob: Blob;
mimeType: string;
}
export class DataReadSuccess extends ReadSuccess {
readonly type = "dataReadSuccess" as const;
constructor(uri: string, recalledFromMemory: boolean) {
super(uri, recalledFromMemory);
}
export interface DataReadSuccess extends ReadSuccess {
type: "dataReadSuccess";
}
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 interface ContainerReadSuccess extends ReadSuccess {
type: "containerReadSuccess";
isRootContainer: boolean;
}
export class AbsentReadSuccess extends ReadSuccess {
readonly type = "absentReadSuccess" as const;
export interface AbsentReadSuccess extends ReadSuccess {
type: "absentReadSuccess";
}
constructor(uri: string, recalledFromMemory: boolean) {
super(uri, recalledFromMemory);
}
export function isReadSuccess(result: SuccessResult): result is ReadSuccess {
return (
result.type === "binaryReadSuccess" ||
result.type === "dataReadSuccess" ||
result.type === "absentReadSuccess" ||
result.type === "containerReadSuccess"
);
}

@ -1,30 +1,15 @@
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 interface SuccessResult extends RequesterResult {
isError: false;
}
export abstract class ResourceSuccess extends SuccessResult {
readonly uri: string;
constructor(uri: string) {
super();
this.uri = uri;
}
export interface ResourceSuccess extends SuccessResult {
uri: string;
}
export class AggregateSuccess<
SuccessType extends SuccessResult,
> extends SuccessResult {
readonly type = "aggregateError" as const;
readonly results: SuccessType[];
constructor(results: SuccessType[]) {
super();
this.results = results;
}
export interface AggregateSuccess<SuccessType extends SuccessResult>
extends SuccessResult {
type: "aggregateSuccess";
results: SuccessType[];
}

@ -1,5 +1,5 @@
import { ResourceSuccess } from "./SuccessResult";
import type { ResourceSuccess } from "./SuccessResult";
export class Unfetched extends ResourceSuccess {
readonly type = "unfetched" as const;
export interface Unfetched extends ResourceSuccess {
type: "unfetched";
}

@ -1,5 +1,5 @@
import { ResourceSuccess } from "./SuccessResult";
import type { ResourceSuccess } from "./SuccessResult";
export class UpdateSuccess extends ResourceSuccess {
readonly type = "updateSuccess";
export interface UpdateSuccess extends ResourceSuccess {
type: "updateSuccess";
}

@ -21,19 +21,16 @@ import type {
import { AggregateError } from "../requester/results/error/ErrorResult";
import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
import type { DeleteSuccess } from "../requester/results/success/DeleteSuccess";
import {
AbsentReadSuccess,
ContainerReadSuccess,
} from "../requester/results/success/ReadSuccess";
import { AggregateSuccess } from "../requester/results/success/SuccessResult";
import { Unfetched } from "../requester/results/success/Unfetched";
import type { AbsentReadSuccess } from "../requester/results/success/ReadSuccess";
import type { ContainerReadSuccess } from "../requester/results/success/ReadSuccess";
import type { AggregateSuccess } from "../requester/results/success/SuccessResult";
import type { SolidLdoDatasetContext } from "../SolidLdoDatasetContext";
import { getParentUri, ldpContains } from "../util/rdfUtils";
import type { ContainerUri, LeafUri } from "../util/uriTypes";
import type { Leaf } from "./Leaf";
import type { SharedStatuses } from "./Resource";
import { Resource } from "./Resource";
import { GetRootContainerSuccess } from "./resourceResults/GetRootContainerSuccess";
import type { ResourceResult } from "./ResourceResult";
export class Container extends Resource {
readonly uri: ContainerUri;
@ -52,7 +49,7 @@ export class Container extends Resource {
super(context);
this.uri = uri;
this.requester = new ContainerRequester(uri, context);
this.status = new Unfetched(this.uri);
this.status = { isError: false, type: "unfetched", uri };
}
isRootContainer(): boolean | undefined {
@ -68,39 +65,58 @@ export class Container extends Resource {
}
}
async read(): Promise<ReadContainerResult> {
return (await super.read()) as ReadContainerResult;
async read(): Promise<ResourceResult<ReadContainerResult, Container>> {
const result = (await this.handleRead()) as ReadContainerResult;
if (result.isError) return result;
return { ...result, resource: this };
}
protected toReadResult(): ReadContainerResult {
protected toReadResult(): ResourceResult<ReadContainerResult, Container> {
if (this.isAbsent()) {
return new AbsentReadSuccess(this.uri, true);
return {
isError: false,
type: "absentReadSuccess",
uri: this.uri,
recalledFromMemory: true,
resource: this,
};
} else {
return new ContainerReadSuccess(this.uri, true, this.isRootContainer()!);
return {
isError: false,
type: "containerReadSuccess",
uri: this.uri,
recalledFromMemory: true,
isRootContainer: this.isRootContainer()!,
resource: this,
};
}
}
async readIfUnfetched(): Promise<ReadContainerResult> {
return super.readIfUnfetched() as Promise<ReadContainerResult>;
async readIfUnfetched(): Promise<
ResourceResult<ReadContainerResult, Container>
> {
return super.readIfUnfetched() as Promise<
ResourceResult<ReadContainerResult, Container>
>;
}
// Parent Container Methods
private async checkIfIsRootContainer(): Promise<CheckRootResult> {
private async checkIfIsRootContainer(): Promise<
ResourceResult<CheckRootResult, Container>
> {
const rootContainerResult = await this.requester.isRootContainer();
this.status = rootContainerResult;
if (rootContainerResult.isError) return rootContainerResult;
this.rootContainer = rootContainerResult.isRootContainer;
this.emit("update");
return rootContainerResult;
return { ...rootContainerResult, resource: this };
}
async getRootContainer(): Promise<
GetRootContainerSuccess | CheckRootResultError
> {
async getRootContainer(): Promise<Container | CheckRootResultError> {
const checkResult = await this.checkIfIsRootContainer();
if (checkResult.isError) return checkResult;
if (this.rootContainer) {
return new GetRootContainerSuccess(this);
return this;
}
const parentUri = getParentUri(this.uri);
if (!parentUri) {
@ -150,25 +166,51 @@ export class Container extends Resource {
// Child Creators
createChildAndOverwrite(
slug: ContainerUri,
): Promise<ContainerCreateAndOverwriteResult>;
createChildAndOverwrite(slug: LeafUri): Promise<LeafCreateAndOverwriteResult>;
): Promise<ResourceResult<ContainerCreateAndOverwriteResult, Container>>;
createChildAndOverwrite(
slug: LeafUri,
): Promise<ResourceResult<LeafCreateAndOverwriteResult, Leaf>>;
createChildAndOverwrite(
slug: string,
): Promise<ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult>;
): Promise<
ResourceResult<
ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult,
Leaf | Container
>
>;
createChildAndOverwrite(
slug: string,
): Promise<ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult> {
): Promise<
ResourceResult<
ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult,
Leaf | Container
>
> {
return this.child(slug).createAndOverwrite();
}
createChildIfAbsent(slug: ContainerUri): Promise<LeafCreateIfAbsentResult>;
createChildIfAbsent(slug: LeafUri): Promise<LeafCreateIfAbsentResult>;
createChildIfAbsent(
slug: ContainerUri,
): Promise<ResourceResult<ContainerCreateIfAbsentResult, Container>>;
createChildIfAbsent(
slug: LeafUri,
): Promise<ResourceResult<LeafCreateIfAbsentResult, Leaf>>;
createChildIfAbsent(
slug: string,
): Promise<ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult>;
): Promise<
ResourceResult<
ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult,
Leaf | Container
>
>;
createChildIfAbsent(
slug: string,
): Promise<ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult> {
): Promise<
ResourceResult<
ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult,
Leaf | Container
>
> {
return this.child(slug).createIfAbsent();
}
@ -176,7 +218,7 @@ export class Container extends Resource {
slug: LeafUri,
blob: Blob,
mimeType: string,
): Promise<LeafCreateAndOverwriteResult> {
): Promise<ResourceResult<LeafCreateAndOverwriteResult, Leaf>> {
return this.child(slug).uploadAndOverwrite(blob, mimeType);
}
@ -184,13 +226,16 @@ export class Container extends Resource {
slug: LeafUri,
blob: Blob,
mimeType: string,
): Promise<LeafCreateIfAbsentResult> {
): Promise<ResourceResult<LeafCreateIfAbsentResult, Leaf>> {
return this.child(slug).uploadIfAbsent(blob, mimeType);
}
async clear(): Promise<
| AggregateSuccess<DeleteSuccess>
| AggregateError<DeleteResultError | ReadResultError>
ResourceResult<
| AggregateSuccess<ResourceResult<DeleteSuccess, Container | Leaf>>
| AggregateError<DeleteResultError | ReadResultError>,
Container
>
> {
const readResult = await this.read();
if (readResult.isError) return new AggregateError([readResult]);
@ -211,14 +256,42 @@ export class Container extends Resource {
if (errors.length > 0) {
return new AggregateError(errors);
}
return new AggregateSuccess<DeleteSuccess>(results as DeleteSuccess[]);
return {
isError: false,
type: "aggregateSuccess",
results: results as ResourceResult<DeleteSuccess, Container | Leaf>[],
resource: this,
};
}
async delete(): Promise<
DeleteResult | AggregateError<DeleteResultError | ReadResultError>
ResourceResult<
DeleteResult | AggregateError<DeleteResultError | ReadResultError>,
Container
>
> {
const clearResult = await this.clear();
if (clearResult.isError) return clearResult;
return this.handleDelete();
const deleteResult = await this.handleDelete();
if (deleteResult.isError) return deleteResult;
return { ...deleteResult, resource: this };
}
async createAndOverwrite(): Promise<
ResourceResult<ContainerCreateAndOverwriteResult, Container>
> {
const createResult =
(await this.handleCreateAndOverwrite()) as ContainerCreateAndOverwriteResult;
if (createResult.isError) return createResult;
return { ...createResult, resource: this };
}
async createIfAbsent(): Promise<
ResourceResult<ContainerCreateIfAbsentResult, Container>
> {
const createResult =
(await this.handleCreateAndOverwrite()) as ContainerCreateIfAbsentResult;
if (createResult.isError) return createResult;
return { ...createResult, resource: this };
}
}

@ -10,20 +10,19 @@ import type { DeleteResult } from "../requester/requests/deleteResource";
import type { ReadLeafResult } from "../requester/requests/readResource";
import type { UpdateResult } from "../requester/requests/updateDataResource";
import type { DeleteSuccess } from "../requester/results/success/DeleteSuccess";
import {
import type { AbsentReadSuccess } from "../requester/results/success/ReadSuccess";
import type {
BinaryReadSuccess,
DataReadSuccess,
AbsentReadSuccess,
} from "../requester/results/success/ReadSuccess";
import type { ResourceSuccess } from "../requester/results/success/SuccessResult";
import { Unfetched } from "../requester/results/success/Unfetched";
import type { SolidLdoDatasetContext } from "../SolidLdoDatasetContext";
import { getParentUri } from "../util/rdfUtils";
import type { LeafUri } from "../util/uriTypes";
import type { Container } from "./Container";
import type { SharedStatuses } from "./Resource";
import { Resource } from "./Resource";
import type { GetRootContainerSuccess } from "./resourceResults/GetRootContainerSuccess";
import type { ResourceResult } from "./ResourceResult";
export class Leaf extends Resource {
readonly uri: LeafUri;
@ -43,7 +42,7 @@ export class Leaf extends Resource {
super(context);
this.uri = uri;
this.requester = new LeafRequester(uri, context);
this.status = new Unfetched(this.uri);
this.status = { isError: false, type: "unfetched", uri };
}
// Getters
@ -81,27 +80,46 @@ export class Leaf extends Resource {
}
}
async read(): Promise<ReadLeafResult> {
return (await super.read()) as ReadLeafResult;
async read(): Promise<ResourceResult<ReadLeafResult, Leaf>> {
const result = (await this.handleRead()) as ReadLeafResult;
if (result.isError) return result;
return { ...result, resource: this };
}
protected toReadResult(): ReadLeafResult {
protected toReadResult(): ResourceResult<ReadLeafResult, Leaf> {
if (this.isAbsent()) {
return new AbsentReadSuccess(this.uri, true);
return {
isError: false,
type: "absentReadSuccess",
uri: this.uri,
recalledFromMemory: true,
resource: this,
};
} else if (this.isBinary()) {
return new BinaryReadSuccess(
this.uri,
true,
this.binaryData!.blob,
this.binaryData!.mimeType,
);
return {
isError: false,
type: "binaryReadSuccess",
uri: this.uri,
recalledFromMemory: true,
blob: this.binaryData!.blob,
mimeType: this.binaryData!.mimeType,
resource: this,
};
} else {
return new DataReadSuccess(this.uri, true);
return {
isError: false,
type: "dataReadSuccess",
uri: this.uri,
recalledFromMemory: true,
resource: this,
};
}
}
async readIfUnfetched(): Promise<ReadLeafResult> {
return super.readIfUnfetched() as Promise<ReadLeafResult>;
async readIfUnfetched(): Promise<ResourceResult<ReadLeafResult, Leaf>> {
return super.readIfUnfetched() as Promise<
ResourceResult<ReadLeafResult, Leaf>
>;
}
// Parent Container Methods
@ -109,7 +127,7 @@ export class Leaf extends Resource {
const parentUri = getParentUri(this.uri)!;
return this.context.resourceStore.get(parentUri);
}
getRootContainer(): Promise<GetRootContainerSuccess | CheckRootResultError> {
getRootContainer(): Promise<Container | CheckRootResultError> {
const parentUri = getParentUri(this.uri)!;
const parent = this.context.resourceStore.get(parentUri);
return parent.getRootContainer();
@ -129,40 +147,60 @@ export class Leaf extends Resource {
async uploadAndOverwrite(
blob: Blob,
mimeType: string,
): Promise<LeafCreateAndOverwriteResult> {
): Promise<ResourceResult<LeafCreateAndOverwriteResult, Leaf>> {
const result = await this.requester.upload(blob, mimeType, true);
this.status = result;
if (result.isError) return result;
super.updateWithCreateSuccess(result);
this.binaryData = { blob, mimeType };
this.emitThisAndParent();
return result;
return { ...result, resource: this };
}
async uploadIfAbsent(
blob: Blob,
mimeType: string,
): Promise<LeafCreateIfAbsentResult> {
): Promise<ResourceResult<LeafCreateIfAbsentResult, Leaf>> {
const result = await this.requester.upload(blob, mimeType);
this.status = result;
if (result.isError) return result;
super.updateWithCreateSuccess(result);
this.binaryData = { blob, mimeType };
this.emitThisAndParent();
return result;
return { ...result, resource: this };
}
async update(changes: DatasetChanges<Quad>): Promise<UpdateResult> {
async update(
changes: DatasetChanges<Quad>,
): Promise<ResourceResult<UpdateResult, Leaf>> {
const result = await this.requester.updateDataResource(changes);
this.status = result;
if (result.isError) return result;
this.binaryData = undefined;
this.absent = false;
this.emitThisAndParent();
return result;
return { ...result, resource: this };
}
async delete(): Promise<DeleteResult> {
return this.handleDelete();
}
async createAndOverwrite(): Promise<
ResourceResult<LeafCreateAndOverwriteResult, Leaf>
> {
const createResult =
(await this.handleCreateAndOverwrite()) as LeafCreateAndOverwriteResult;
if (createResult.isError) return createResult;
return { ...createResult, resource: this };
}
async createIfAbsent(): Promise<
ResourceResult<LeafCreateIfAbsentResult, Leaf>
> {
const createResult =
(await this.handleCreateAndOverwrite()) as LeafCreateIfAbsentResult;
if (createResult.isError) return createResult;
return { ...createResult, resource: this };
}
}

@ -19,16 +19,15 @@ import EventEmitter from "events";
import { getParentUri } from "../util/rdfUtils";
import type { RequesterResult } from "../requester/results/RequesterResult";
import type { DeleteResult } from "../requester/requests/deleteResource";
import { ReadSuccess } from "../requester/results/success/ReadSuccess";
import type { ReadSuccess } from "../requester/results/success/ReadSuccess";
import { isReadSuccess } from "../requester/results/success/ReadSuccess";
import type { DeleteSuccess } from "../requester/results/success/DeleteSuccess";
import type { ResourceSuccess } from "../requester/results/success/SuccessResult";
import type { Unfetched } from "../requester/results/success/Unfetched";
import type { CreateSuccess } from "../requester/results/success/CreateSuccess";
import type { GetRootContainerSuccess } from "./resourceResults/GetRootContainerSuccess";
import type {
ReadResourceSuccessContainerTypes,
ReadResourceSuccessLeafTypes,
} from "./resourceResults/ReadResourceSuccess";
import type { ResourceResult } from "./resourceResult/ResourceResult";
import type { Container } from "./Container";
import type { Leaf } from "./Leaf";
export type SharedStatuses = Unfetched | DeleteResult | CreateSuccess;
@ -96,9 +95,7 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
this.didInitialFetch = true;
}
async read(): Promise<
ReadResourceSuccessContainerTypes | ReadResourceSuccessLeafTypes
> {
protected async handleRead(): Promise<ReadContainerResult | ReadLeafResult> {
const result = await this.requester.read();
this.status = result;
if (result.isError) return result;
@ -107,9 +104,18 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
return result;
}
protected abstract toReadResult(): ReadContainerResult | ReadLeafResult;
protected abstract toReadResult(): ResourceResult<
ReadLeafResult | ReadContainerResult,
Container | Leaf
>;
async readIfUnfetched(): Promise<ReadContainerResult | ReadLeafResult> {
abstract read(): Promise<
ResourceResult<ReadLeafResult | ReadContainerResult, Container | Leaf>
>;
async readIfUnfetched(): Promise<
ResourceResult<ReadLeafResult | ReadContainerResult, Container | Leaf>
> {
if (this.didInitialFetch) {
const readResult = this.toReadResult();
this.status = readResult;
@ -137,12 +143,19 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
protected updateWithCreateSuccess(result: ResourceSuccess) {
this.absent = false;
this.didInitialFetch = true;
if (result instanceof ReadSuccess) {
if (isReadSuccess(result)) {
this.updateWithReadSuccess(result);
}
}
async createAndOverwrite(): Promise<
abstract createAndOverwrite(): Promise<
ResourceResult<
ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult,
Leaf | Container
>
>;
protected async handleCreateAndOverwrite(): Promise<
ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult
> {
const result = await this.requester.createDataResource(true);
@ -153,7 +166,14 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
return result;
}
async createIfAbsent(): Promise<
abstract createIfAbsent(): Promise<
ResourceResult<
ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult,
Leaf | Container
>
>;
protected async handleCreateIfAbsent(): Promise<
ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult
> {
const result = await this.requester.createDataResource(true);
@ -165,20 +185,19 @@ export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
}
// Parent Container Methods -- Remember to change for Container
abstract getRootContainer(): Promise<
GetRootContainerSuccess | CheckRootResultError
>;
abstract getRootContainer(): Promise<Container | CheckRootResultError>;
// Access Rules Methods
// async getAccessRules(): Promise<AccessRuleResult | AccessRuleFetchError> {
// return getAccessRules({ uri: this.uri, fetch: this.context.fetch });
// }
async setAccessRules(
newAccessRules: AccessRule,
): Promise<SetAccessRulesResult> {
return setAccessRules(this.uri, newAccessRules, {
): Promise<ResourceResult<SetAccessRulesResult, Leaf | Container>> {
const result = await setAccessRules(this.uri, newAccessRules, {
fetch: this.context.fetch,
});
if (result.isError) return result;
return { ...result, resource: this as unknown as Leaf | Container };
}
}

@ -1,10 +0,0 @@
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,13 @@
import type { RequesterResult } from "../../requester/results/RequesterResult";
import type { Container } from "../Container";
import type { Leaf } from "../Leaf";
export type ResourceSuccess<
Result extends RequesterResult,
ResourceType extends Leaf | Container,
> = Result & { resource: ResourceType };
export type ResourceResult<
Result extends RequesterResult,
ResourceType extends Leaf | Container,
> = Result extends Error ? Result : ResourceSuccess<Result, ResourceType>;

@ -1,14 +0,0 @@
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;
}
}

@ -1,14 +0,0 @@
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;
}
}

@ -1,12 +0,0 @@
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;
}
}

@ -1,72 +0,0 @@
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;
}
}

@ -1,11 +0,0 @@
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;
}
}
Loading…
Cancel
Save