Refactored fetch methods out

main
jaxoncreed 2 years ago
parent 33c2c5cf9f
commit 0f68b88989
  1. 56500
      package-lock.json
  2. 0
      packages/demo-react/src/dashboard/BuildRootContainer.ts
  3. 30
      packages/solid/src/index.ts
  4. 3
      packages/solid/src/requester/ContainerRequester.ts
  5. 269
      packages/solid/src/requester/LeafRequester.ts
  6. 0
      packages/solid/src/requester/requestResults/AbsentResult.ts
  7. 0
      packages/solid/src/requester/requestResults/BinaryResult.ts
  8. 0
      packages/solid/src/requester/requestResults/DataResult.ts
  9. 0
      packages/solid/src/requester/requestResults/ErrorResult.ts
  10. 18
      packages/solid/src/requester/requestResults/HttpErrorResult.ts
  11. 0
      packages/solid/src/requester/requestResults/RequesterResult.ts
  12. 72
      packages/solid/src/requester/requests/createDataResource.ts
  13. 38
      packages/solid/src/requester/requests/deleteResource.ts
  14. 53
      packages/solid/src/requester/requests/readResource.ts
  15. 8
      packages/solid/src/requester/requests/requestParams.ts
  16. 14
      packages/solid/src/requester/requests/updateDataResource.ts
  17. 85
      packages/solid/src/requester/requests/uploadResource.ts
  18. 8
      packages/solid/src/resource/Container.ts
  19. 140
      packages/solid/src/resource/Leaf.ts
  20. 13
      packages/solid/src/util/rdfUtils.ts
  21. 18
      packages/solid/test/LeafRequester.test.ts

56500
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,30 +1,6 @@
// document
export * from "./document/FetchableDocument";
export * from "./document/DocumentStore";
// document/errors
export * from "./document/errors/DocumentError";
// document/accessRules
export * from "./document/accessRules/AccessRules";
export * from "./document/accessRules/AccessRulesStore";
// document/resource
export * from "./document/resource/Resource";
// document/resource/binaryResource
export * from "./document/resource/binaryResource/BinaryResource";
export * from "./document/resource/binaryResource/BinaryResourceStore";
// document/resource/dataResource
export * from "./document/resource/dataResource/DataResource";
export * from "./document/resource/dataResource/DataResourceStore";
// document/resource/containerResource
export * from "./document/resource/dataResource/containerResource/ContainerResource";
export * from "./document/resource/dataResource/containerResource/ContainerResourceStore";
// /
export * from "./createSolidLdoDataset";
export * from "./SolidLdoDataset";
export * from "./SolidLdoDatasetContext";
export * from "./resource/Leaf";
export * from "./resource/Container";

@ -0,0 +1,3 @@
export class ContainerRequester {
}

@ -1,55 +1,22 @@
import type { LeafUri } from "../util/uriTypes";
import { RequestBatcher } from "../util/RequestBatcher";
import type { SolidLdoDatasetContext } from "../SolidLdoDatasetContext";
import { AbsentResult } from "./requesterResults/AbsentResult";
import type { TurtleFormattingError } from "./requesterResults/DataResult";
import { DataResult } from "./requesterResults/DataResult";
import { BinaryResult } from "./requesterResults/BinaryResult";
import {
HttpErrorResult,
ServerHttpError,
UnauthenticatedHttpError,
UnexpectedHttpError,
} from "./requesterResults/HttpErrorResult";
import { UnexpectedError } from "./requesterResults/ErrorResult";
import type { LdoDataset } from "@ldo/ldo";
import { parseRdf } from "@ldo/ldo";
import { namedNode, quad as createQuad } from "@rdfjs/data-model";
import {
addRawTurtleToDataset,
addResourceRdfToContainer,
deleteResourceRdfFromContainer,
getParentUri,
getSlug,
} from "../util/rdfUtils";
import type { TransactionalDataset } from "@ldo/subscribable-dataset";
import type { Quad } from "@rdfjs/types";
export type ReadResult =
| AbsentResult
| DataResult
| BinaryResult
| ServerHttpError
| UnauthenticatedHttpError
| UnexpectedHttpError
| UnexpectedError
| TurtleFormattingError;
export type CreateResult =
| DataResult
| BinaryResult
| ServerHttpError
| UnauthenticatedHttpError
| UnexpectedError
| UnexpectedHttpError;
export type CreateResultWithoutOverwrite = CreateResult | TurtleFormattingError;
export type DeleteResult =
| AbsentResult
| ServerHttpError
| UnauthenticatedHttpError
| UnexpectedError
| UnexpectedHttpError;
import type { DatasetChanges } from "@ldo/rdf-utils";
import type {
CreateResult,
CreateResultWithoutOverwrite,
} from "./requests/createDataResource";
import { createDataResource } from "./requests/createDataResource";
import type { ReadResult } from "./requests/readResource";
import { readResource } from "./requests/readResource";
import type {
UploadResult,
UploadResultWithoutOverwrite,
} from "./requests/uploadResource";
import { uploadResource } from "./requests/uploadResource";
import type { DeleteResult } from "./requests/deleteResource";
import { deleteResource } from "./requests/deleteResource";
import type { UpdateResult } from "./requests/updateDataResource";
export class LeafRequester {
private requestBatcher = new RequestBatcher();
@ -71,9 +38,8 @@ export class LeafRequester {
const transaction = this.context.solidLdoDataset.startTransaction();
const result = await this.requestBatcher.queueProcess({
name: READ_KEY,
args: [transaction],
perform: (transaction: TransactionalDataset<Quad>) =>
this.performRead(transaction),
args: [{ uri: this.uri, transaction, fetch: this.context.fetch }],
perform: readResource,
modifyQueue: (queue, isLoading) => {
if (queue.length === 0) {
return isLoading[READ_KEY];
@ -88,45 +54,6 @@ export class LeafRequester {
return result;
}
/**
* Helper method to perform the read action
*/
private async performRead(
transaction: TransactionalDataset<Quad>,
): Promise<ReadResult> {
try {
// Fetch options to determine the document type
const response = await this.context.fetch(this.uri);
if (AbsentResult.is(response)) {
return new AbsentResult(this.uri);
}
if (ServerHttpError.is(response)) {
return new ServerHttpError(this.uri, response);
}
if (UnauthenticatedHttpError.is(response)) {
return new UnauthenticatedHttpError(this.uri, response);
}
if (HttpErrorResult.isnt(response)) {
return new UnexpectedHttpError(this.uri, response);
}
// Add this resource to the container
addResourceRdfToContainer(this.uri, transaction);
if (DataResult.is(response)) {
// Parse Turtle
const rawTurtle = await response.text();
return addRawTurtleToDataset(rawTurtle, transaction, this.uri);
} else {
// Load Blob
const blob = await response.blob();
return new BinaryResult(this.uri, blob);
}
} catch (err) {
return UnexpectedError.fromThrown(this.uri, err);
}
}
/**
* Creates a Resource
* @param overwrite: If true, this will orverwrite the resource if it already
@ -146,9 +73,11 @@ export class LeafRequester {
const transaction = this.context.solidLdoDataset.startTransaction();
const result = await this.requestBatcher.queueProcess({
name: CREATE_KEY,
args: [transaction, overwrite],
perform: (transaction: TransactionalDataset<Quad>, overwrite?: boolean) =>
this.performCreateDataResource(transaction, overwrite),
args: [
{ uri: this.uri, transaction, fetch: this.context.fetch },
overwrite,
],
perform: createDataResource,
modifyQueue: (queue, isLoading, args) => {
const lastElementInQueue = queue[queue.length - 1];
return (
@ -165,75 +94,64 @@ export class LeafRequester {
}
/**
* Helper Method to perform the createDataResourceAction
* @param overwrite
* Upload a binary
* @param blob
* @param mimeType
* @param overwrite: If true, will overwrite an existing file
*/
private async performCreateDataResource(
transaction: TransactionalDataset<Quad>,
async upload(
blob: Blob,
mimeType: string,
overwrite?: false,
): Promise<CreateResultWithoutOverwrite>;
private async performCreateDataResource(
transaction: TransactionalDataset<Quad>,
): Promise<UploadResultWithoutOverwrite>;
async upload(
blob: Blob,
mimeType: string,
overwrite: true,
): Promise<CreateResult>;
private async performCreateDataResource(
transaction: TransactionalDataset<Quad>,
): Promise<UploadResult>;
async upload(
blob: Blob,
mimeType: string,
overwrite?: boolean,
): Promise<CreateResultWithoutOverwrite | CreateResult>;
private async performCreateDataResource(
transaction: TransactionalDataset<Quad>,
): Promise<UploadResultWithoutOverwrite | UploadResult>;
async upload(
blob: Blob,
mimeType: string,
overwrite?: boolean,
): Promise<CreateResultWithoutOverwrite> {
try {
if (overwrite) {
const deleteResult = await this.performDelete(transaction);
// Return if it wasn't deleted
if (deleteResult.type !== "absent") {
return deleteResult;
}
} else {
// Perform a read to check if it exists
const readResult = await this.performRead(transaction);
// If it does exist stop and return.
if (readResult.type !== "absent") {
return readResult;
}
}
// Create the document
const parentUri = getParentUri(this.uri)!;
const response = await this.context.fetch(parentUri, {
method: "post",
headers: {
"content-type": "text/turtle",
slug: getSlug(this.uri),
},
});
if (ServerHttpError.is(response)) {
return new ServerHttpError(this.uri, response);
}
if (UnauthenticatedHttpError.is(response)) {
return new UnauthenticatedHttpError(this.uri, response);
}
if (HttpErrorResult.isnt(response)) {
return new UnexpectedHttpError(this.uri, response);
}
addResourceRdfToContainer(this.uri, transaction);
return new DataResult(this.uri);
} catch (err) {
return UnexpectedError.fromThrown(this.uri, err);
): Promise<UploadResultWithoutOverwrite | UploadResult> {
const UPLOAD_KEY = "upload";
const transaction = this.context.solidLdoDataset.startTransaction();
const result = await this.requestBatcher.queueProcess({
name: UPLOAD_KEY,
args: [
{ uri: this.uri, transaction, fetch: this.context.fetch },
blob,
mimeType,
overwrite,
],
perform: uploadResource,
modifyQueue: (queue, isLoading, args) => {
const lastElementInQueue = queue[queue.length - 1];
return (
lastElementInQueue &&
lastElementInQueue.name === UPLOAD_KEY &&
!!lastElementInQueue.args[3] === !!args[3]
);
},
});
if (result.type !== "error") {
transaction.commit();
}
return result;
}
// abstract upload(
// blob: Blob,
// mimeType: string,
// overwrite?: boolean,
// ): Promise<BinaryLeaf | ResourceError>;
// abstract updateData(
// changes: DatasetChanges,
// ): Promise<DataLeaf | ResourceError>;
/**
* Update the data on this resource
* @param changes
*/
updateDataResource(_changes: DatasetChanges): Promise<UpdateResult> {
throw new Error("Not Implemented");
}
/**
* Delete this resource
@ -243,9 +161,8 @@ export class LeafRequester {
const transaction = this.context.solidLdoDataset.startTransaction();
const result = await this.requestBatcher.queueProcess({
name: DELETE_KEY,
args: [transaction],
perform: (transaction: TransactionalDataset<Quad>) =>
this.performDelete(transaction),
args: [{ uri: this.uri, transaction, fetch: this.context.fetch }],
perform: deleteResource,
modifyQueue: (queue, isLoading) => {
if (queue.length === 0) {
return isLoading[DELETE_KEY];
@ -259,40 +176,4 @@ export class LeafRequester {
}
return result;
}
/**
* Helper method to perform this delete action
*/
private async performDelete(
transaction: TransactionalDataset<Quad>,
): Promise<DeleteResult> {
try {
const response = await this.context.fetch(this.uri, {
method: "delete",
});
if (ServerHttpError.is(response)) {
return new ServerHttpError(this.uri, response);
}
if (UnauthenticatedHttpError.is(response)) {
return new UnauthenticatedHttpError(this.uri, response);
}
// 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(this.uri),
);
deleteResourceRdfFromContainer(this.uri, transaction);
return new AbsentResult(this.uri);
}
return new UnexpectedHttpError(this.uri, response);
} catch (err) {
return UnexpectedError.fromThrown(this.uri, err);
}
}
}

@ -1,5 +1,10 @@
import { ErrorResult } from "./ErrorResult";
export type HttpErrorResultType =
| ServerHttpError
| UnexpectedHttpError
| UnauthenticatedHttpError;
export abstract class HttpErrorResult extends ErrorResult {
public readonly status: number;
public readonly headers: Headers;
@ -26,6 +31,19 @@ export abstract class HttpErrorResult extends ErrorResult {
static isnt(response: Response) {
return response.status < 200 || response.status >= 300;
}
static checkResponse(uri: string, response: Response) {
if (ServerHttpError.is(response)) {
return new ServerHttpError(uri, response);
}
if (UnauthenticatedHttpError.is(response)) {
return new UnauthenticatedHttpError(uri, response);
}
if (HttpErrorResult.isnt(response)) {
return new UnexpectedHttpError(uri, response);
}
return undefined;
}
}
export class UnexpectedHttpError extends HttpErrorResult {

@ -0,0 +1,72 @@
import {
addResourceRdfToContainer,
getParentUri,
getSlug,
} from "../../util/rdfUtils";
import type { BinaryResult } from "../requestResults/BinaryResult";
import type { TurtleFormattingError } from "../requestResults/DataResult";
import { DataResult } from "../requestResults/DataResult";
import { UnexpectedError } from "../requestResults/ErrorResult";
import type { HttpErrorResultType } from "../requestResults/HttpErrorResult";
import { HttpErrorResult } from "../requestResults/HttpErrorResult";
import { deleteResource } from "./deleteResource";
import { readResource } from "./readResource";
import type { RequestParams } from "./requestParams";
export type CreateResult = DataResult | HttpErrorResultType | UnexpectedError;
export type CreateResultWithoutOverwrite =
| CreateResult
| TurtleFormattingError
| BinaryResult;
export function createDataResource(
params: RequestParams,
overwrite?: false,
): Promise<CreateResultWithoutOverwrite>;
export function createDataResource(
params: RequestParams,
overwrite: true,
): Promise<CreateResult>;
export function createDataResource(
params: RequestParams,
overwrite?: boolean,
): Promise<CreateResultWithoutOverwrite | CreateResult>;
export async function createDataResource(
params: RequestParams,
overwrite?: boolean,
): Promise<CreateResultWithoutOverwrite> {
const { uri, transaction, fetch } = params;
try {
if (overwrite) {
const deleteResult = await deleteResource(params);
// Return if it wasn't deleted
if (deleteResult.type !== "absent") {
return deleteResult;
}
} else {
// Perform a read to check if it exists
const readResult = await readResource(params);
// If it does exist stop and return.
if (readResult.type !== "absent") {
return readResult;
}
}
// Create the document
const parentUri = getParentUri(uri)!;
const response = await fetch(parentUri, {
method: "post",
headers: {
"content-type": "text/turtle",
slug: getSlug(uri),
},
});
const httpError = HttpErrorResult.checkResponse(uri, response);
if (httpError) return httpError;
addResourceRdfToContainer(uri, transaction);
return new DataResult(uri);
} catch (err) {
return UnexpectedError.fromThrown(uri, err);
}
}

@ -0,0 +1,38 @@
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 { deleteResourceRdfFromContainer } from "../../util/rdfUtils";
export type DeleteResult = AbsentResult | HttpErrorResultType | UnexpectedError;
export async function deleteResource({
uri,
fetch,
transaction,
}: RequestParams): Promise<DeleteResult> {
try {
const response = await fetch(uri, {
method: "delete",
});
// 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);
}
return new UnexpectedHttpError(uri, response);
} catch (err) {
return UnexpectedError.fromThrown(uri, err);
}
}

@ -0,0 +1,53 @@
import { DataResult } from "../requestResults/DataResult";
import type { TurtleFormattingError } from "../requestResults/DataResult";
import {
HttpErrorResult,
type HttpErrorResultType,
} from "../requestResults/HttpErrorResult";
import { UnexpectedError } from "../requestResults/ErrorResult";
import { AbsentResult } from "../requestResults/AbsentResult";
import { BinaryResult } from "../requestResults/BinaryResult";
import {
addRawTurtleToDataset,
addResourceRdfToContainer,
} from "../../util/rdfUtils";
import type { RequestParams } from "./requestParams";
export type ReadResult =
| AbsentResult
| DataResult
| BinaryResult
| HttpErrorResultType
| TurtleFormattingError
| UnexpectedError;
export async function readResource({
uri,
fetch,
transaction,
}: RequestParams): Promise<ReadResult> {
try {
// Fetch options to determine the document type
const response = await fetch(uri);
if (AbsentResult.is(response)) {
return new AbsentResult(uri);
}
const httpErrorResult = HttpErrorResult.checkResponse(uri, response);
if (httpErrorResult) return httpErrorResult;
// Add this resource to the container
addResourceRdfToContainer(uri, transaction);
if (DataResult.is(response)) {
// Parse Turtle
const rawTurtle = await response.text();
return addRawTurtleToDataset(rawTurtle, transaction, uri);
} else {
// Load Blob
const blob = await response.blob();
return new BinaryResult(uri, blob);
}
} catch (err) {
return UnexpectedError.fromThrown(uri, err);
}
}

@ -0,0 +1,8 @@
import type { TransactionalDataset } from "@ldo/subscribable-dataset";
import type { Quad } from "@rdfjs/types";
export interface RequestParams {
uri: string;
fetch: typeof fetch;
transaction: TransactionalDataset<Quad>;
}

@ -0,0 +1,14 @@
import type { DatasetChanges } from "@ldo/rdf-utils";
import type { DataResult } from "../requestResults/DataResult";
import type { HttpErrorResultType } from "../requestResults/HttpErrorResult";
import type { UnexpectedError } from "../requestResults/ErrorResult";
import type { RequestParams } from "./requestParams";
export type UpdateResult = DataResult | HttpErrorResultType | UnexpectedError;
export async function updateDataResource(
_params: RequestParams,
_datasetChanges: DatasetChanges,
): Promise<UpdateResult> {
throw new Error("Not Implemented");
}

@ -0,0 +1,85 @@
import {
addResourceRdfToContainer,
getParentUri,
getSlug,
} from "../../util/rdfUtils";
import { BinaryResult } from "../requestResults/BinaryResult";
import type {
DataResult,
TurtleFormattingError,
} from "../requestResults/DataResult";
import { UnexpectedError } from "../requestResults/ErrorResult";
import {
HttpErrorResult,
type HttpErrorResultType,
} from "../requestResults/HttpErrorResult";
import { deleteResource } from "./deleteResource";
import { readResource } from "./readResource";
import type { RequestParams } from "./requestParams";
export type UploadResult = BinaryResult | HttpErrorResultType | UnexpectedError;
export type UploadResultWithoutOverwrite =
| UploadResult
| TurtleFormattingError
| DataResult;
export function uploadResource(
params: RequestParams,
blob: Blob,
mimeType: string,
overwrite?: false,
): Promise<UploadResultWithoutOverwrite>;
export function uploadResource(
params: RequestParams,
blob: Blob,
mimeType: string,
overwrite: true,
): Promise<UploadResult>;
export function uploadResource(
params: RequestParams,
blob: Blob,
mimeType: string,
overwrite?: boolean,
): Promise<UploadResultWithoutOverwrite | UploadResult>;
export async function uploadResource(
params: RequestParams,
blob: Blob,
mimeType: string,
overwrite?: boolean,
): Promise<UploadResultWithoutOverwrite | UploadResult> {
const { uri, transaction, fetch } = params;
try {
if (overwrite) {
const deleteResult = await deleteResource(params);
// Return if it wasn't deleted
if (deleteResult.type !== "absent") {
return deleteResult;
}
} else {
// Perform a read to check if it exists
const readResult = await readResource(params);
// If it does exist stop and return.
if (readResult.type !== "absent") {
return readResult;
}
}
// Create the document
const parentUri = getParentUri(uri)!;
const response = await fetch(parentUri, {
method: "post",
headers: {
"content-type": mimeType,
slug: getSlug(uri),
},
body: blob,
});
const httpError = HttpErrorResult.checkResponse(uri, response);
if (httpError) return httpError;
addResourceRdfToContainer(uri, transaction);
return new BinaryResult(uri, blob);
} catch (err) {
return UnexpectedError.fromThrown(uri, err);
}
}

@ -1,3 +1,9 @@
import type { ContainerUri } from "../util/uriTypes";
import { Resource } from "./Resource";
export class Container extends Resource {}
export class Container {
readonly uri: ContainerUri;
private
isFetched():
}

@ -13,74 +13,74 @@ export interface ConcreteInstance {
}
// REMEMBER: This file should be replaced with non abstract methods
export abstract class ConcreteLeaf extends Resource {
// // All intance variables
// private readonly i: SolidLdoDatasetContext;
// uri: string;
// abstract type(): LeafType["type"];
// // Loading Methods
// isLoading(): boolean {
// return (
// this.isCreating() ||
// this.isReading() ||
// this.isUpdating() ||
// this.isDeletinng()
// );
// }
// abstract isCreating(): boolean;
// abstract isReading(): boolean;
// abstract isUpdating(): boolean;
// abstract isDeletinng(): boolean;
// isDoingInitialFetch(): boolean {
// return this.isReading() && !this.didInitialFetch();
// }
// // Checkers
// abstract didInitialFetch(): boolean;
// abstract isFetched(): boolean;
// abstract isUnfetched(): boolean;
// abstract isBinary: boolean | undefined;
// abstract isDataResource(): boolean | undefined;
// // Read Methods
// abstract read(): Promise<PresentLeafType | LdoSolidError>;
// abstract readIfUnfetched(): Promise<PresentLeafType | LdoSolidError>;
// // Create Methods
// abstract createOrOverwrite(): Promise<DataLeaf | LdoSolidError>;
// abstract createOrOverwrite(blob: Blob): Promise<BinaryLeaf | LdoSolidError>;
// abstract createIfAbsent(): Promise<LeafType | LdoSolidError>;
// abstract createIfAbsent(blob: Blob): Promise<LeafType | LdoSolidError>;
// // Delete Method
// abstract delete(): Promise<AbsentLeaf | LdoSolidError>;
// // Parent Container Methods -- Remember to change for Container
// abstract getCachedParentContainer(): ContainerType | LdoSolidError;
// abstract getParentContainer(): Promise<PresentContainer | LdoSolidError>;
// abstract reloadParentContainer(): Promise<PresentContainer | LdoSolidError>;
// abstract getRootContainerFromCache():
// | ContainerType
// | undefined
// | LdoSolidError;
// abstract getRootContainer(): Promise<
// FetchedContainerType | undefined | LdoSolidError
// >;
// abstract getRootContainerFromPod(): Promise<
// FetchedContainerType | undefined | LdoSolidError
// >;
// // Exclusing Methods =========================================================
// // Data Methods (Data Leaf Only)
// abstract getLdoDataset(): LdoDataset | LeafMethodNotAllowedError;
// abstract reloadLdoDataset(): Promise<LdoDataset | LeafMethodNotAllowedError>;
// abstract hasData(): boolean | LeafMethodNotAllowedError;
// abstract reloadHasData(): Promise<boolean | LeafMethodNotAllowedError>;
// abstract update(
// changes: DatasetChanges,
// ): Promise<DataLeaf | LdoSolidError | LeafMethodNotAllowedError>;
// // Binary Methods (Binary Only)
// abstract getMimeType(): string | LeafMethodNotAllowedError;
// abstract reloadMimeType(): Promise<string | LeafMethodNotAllowedError>;
// // Create Methods (AbsentLeaf Only)
// abstract create(): Promise<
// DataLeaf | LdoSolidError | LeafMethodNotAllowedError
// >;
// abstract create(
// blob: Blob,
// ): Promise<BinaryLeaf | LdoSolidError | LeafMethodNotAllowedError>;
export class Leaf extends Resource {
// All intance variables
private readonly i: SolidLdoDatasetContext;
uri: string;
abstract type(): LeafType["type"];
// Loading Methods
isLoading(): boolean {
return (
this.isCreating() ||
this.isReading() ||
this.isUpdating() ||
this.isDeletinng()
);
}
abstract isCreating(): boolean;
abstract isReading(): boolean;
abstract isUpdating(): boolean;
abstract isDeletinng(): boolean;
isDoingInitialFetch(): boolean {
return this.isReading() && !this.didInitialFetch();
}
// Checkers
abstract didInitialFetch(): boolean;
abstract isFetched(): boolean;
abstract isUnfetched(): boolean;
abstract isBinary: boolean | undefined;
abstract isDataResource(): boolean | undefined;
// Read Methods
abstract read(): Promise<PresentLeafType | LdoSolidError>;
abstract readIfUnfetched(): Promise<PresentLeafType | LdoSolidError>;
// Create Methods
abstract createOrOverwrite(): Promise<DataLeaf | LdoSolidError>;
abstract createOrOverwrite(blob: Blob): Promise<BinaryLeaf | LdoSolidError>;
abstract createIfAbsent(): Promise<LeafType | LdoSolidError>;
abstract createIfAbsent(blob: Blob): Promise<LeafType | LdoSolidError>;
// Delete Method
abstract delete(): Promise<AbsentLeaf | LdoSolidError>;
// Parent Container Methods -- Remember to change for Container
abstract getCachedParentContainer(): ContainerType | LdoSolidError;
abstract getParentContainer(): Promise<PresentContainer | LdoSolidError>;
abstract reloadParentContainer(): Promise<PresentContainer | LdoSolidError>;
abstract getRootContainerFromCache():
| ContainerType
| undefined
| LdoSolidError;
abstract getRootContainer(): Promise<
FetchedContainerType | undefined | LdoSolidError
>;
abstract getRootContainerFromPod(): Promise<
FetchedContainerType | undefined | LdoSolidError
>;
// Exclusing Methods =========================================================
// Data Methods (Data Leaf Only)
abstract getLdoDataset(): LdoDataset | LeafMethodNotAllowedError;
abstract reloadLdoDataset(): Promise<LdoDataset | LeafMethodNotAllowedError>;
abstract hasData(): boolean | LeafMethodNotAllowedError;
abstract reloadHasData(): Promise<boolean | LeafMethodNotAllowedError>;
abstract update(
changes: DatasetChanges,
): Promise<DataLeaf | LdoSolidError | LeafMethodNotAllowedError>;
// Binary Methods (Binary Only)
abstract getMimeType(): string | LeafMethodNotAllowedError;
abstract reloadMimeType(): Promise<string | LeafMethodNotAllowedError>;
// Create Methods (AbsentLeaf Only)
abstract create(): Promise<
DataLeaf | LdoSolidError | LeafMethodNotAllowedError
>;
abstract create(
blob: Blob,
): Promise<BinaryLeaf | LdoSolidError | LeafMethodNotAllowedError>;
}

@ -1,10 +1,9 @@
import { parseRdf } from "@ldo/ldo";
import { namedNode, quad as createQuad } from "@rdfjs/data-model";
import { DataResult } from "../requester/requesterResults/DataResult";
import { TurtleFormattingError } from "../requester/requesterResults/DataResult";
import { DataResult } from "../requester/requestResults/DataResult";
import { TurtleFormattingError } from "../requester/requestResults/DataResult";
import type { Dataset } from "@rdfjs/types";
import { isContainerUri } from "./uriTypes";
import { TransactionalDataset } from "@ldo/subscribable-dataset";
const ldpContains = namedNode("http://www.w3.org/ns/ldp#contains");
const rdfType = namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
@ -55,15 +54,10 @@ export function addResourceRdfToContainer(
dataset: Dataset,
) {
const parentUri = getParentUri(resourceUri);
console.log("Before thing");
console.log(dataset.toString());
if (parentUri) {
const parentNode = namedNode(parentUri);
const resourceNode = namedNode(resourceUri);
dataset.add(createQuad(parentNode, ldpContains, resourceNode, parentNode));
console.log("In Between thing");
console.log(dataset.toString());
console.log((dataset as TransactionalDataset).getChanges());
dataset.add(createQuad(resourceNode, rdfType, ldpResource, parentNode));
if (isContainerUri(resourceUri)) {
dataset.add(
@ -71,9 +65,8 @@ export function addResourceRdfToContainer(
);
dataset.add(createQuad(resourceNode, rdfType, ldpContainer, parentNode));
}
addResourceRdfToContainer(parentUri, dataset);
}
console.log("After thing");
console.log(dataset.toString());
}
export async function addRawTurtleToDataset(

@ -4,6 +4,8 @@ import type { SolidLdoDataset } from "../src/SolidLdoDataset";
import { createSolidLdoDataset } from "../src/createSolidLdoDataset";
import { LeafRequester } from "../src/requester/LeafRequester";
import { namedNode, quad as createQuad } from "@rdfjs/data-model";
import type { BinaryResult } from "../src/requester/requestResults/BinaryResult";
import { Readable } from "stream";
describe("Leaf Requester", () => {
let app: App;
@ -68,6 +70,11 @@ describe("Leaf Requester", () => {
]);
});
/**
* ===========================================================================
* Read
* ===========================================================================
*/
it("reads data", async () => {
const leafRequester = new LeafRequester(
`${ROOT_COONTAINER}test_leaf/sample.ttl`,
@ -94,6 +101,11 @@ describe("Leaf Requester", () => {
expect(result.type).toBe("absent");
});
/**
* ===========================================================================
* Create
* ===========================================================================
*/
it("creates a data resource that doesn't exist while not overwriting", async () => {
const leafRequester = new LeafRequester(
`${ROOT_COONTAINER}test_leaf/sample2.ttl`,
@ -120,7 +132,6 @@ describe("Leaf Requester", () => {
);
const result = await leafRequester.createDataResource(true);
expect(result.type).toBe("data");
console.log(solidLdoDataset.toString());
expect(
solidLdoDataset.has(
createQuad(
@ -191,6 +202,11 @@ describe("Leaf Requester", () => {
).toBe(true);
});
/**
* ===========================================================================
* Delete
* ===========================================================================
*/
it("deletes data", async () => {
solidLdoDataset.add(
createQuad(

Loading…
Cancel
Save