Updated the ldo docs

main
jaxoncreed 2 years ago
parent 0c0f037786
commit eabe009c44
  1. 3
      Readme.md
  2. 63679
      package-lock.json
  3. 55
      packages/cli/README.md
  4. 4
      packages/cli/src/index.ts
  5. 286
      packages/ldo/README.md
  6. 10
      packages/ldo/src/LdoDatasetFactory.ts
  7. 4
      packages/ldo/src/ShapeType.ts
  8. 9
      packages/ldo/src/createLdoDataset.ts
  9. 88
      packages/solid/test/ContainerRequester.test.ts
  10. 198
      packages/solid/test/SolidLdoDataset.test.ts
  11. 3
      packages/solid/test/utils.helper.ts
  12. 5
      packages/subscribable-dataset/src/WrapperSubscribableDataset.ts

@ -2,6 +2,9 @@
This is a monorepo that contains all libraries associated with Linked Data Objects (LDO).
## Documentation
Full documentation can be found at [ldo.js.org](https://ldo.js.org).
## Tutorial
[A tutorial for how to use LDO](./documentation/solid-react-tutorial.md) is available here.

63679
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,28 +1,61 @@
# LDO-CLI
# @ldo/cli
A command line interface for Linked Data Objects. LDO-CLI builds `.shex` shapes into LDO types.
The `@ldo/cli` is a command line interface for initializing LDO and building ShapeTypes.
## Setup
Install the CLI
### Automatic Setup
To setup LDO, `cd` into your typescript project and run `npx @ldo/cli init`.
```bash
npm i @ldo/cli --save-dev
cd my-typescript-project
npx @ldo/cli init
```
Set up a shapes folder
### Manual Setup
The following is handled by the __automatic setup__:
Install the LDO dependencies.
```bash
mkdir .shapes
npm install @ldo/ldo
npm install @ldo/cli --save-dev
```
Place ShexC shapes inside `.shex` files
Create a folder to store your ShEx shapes:
```bash
touch ./.shapes/example.shex
mkdir shapes
```
Create a script to build ShEx shapes and convert them into Linked Data Objects. You can put this script in `package.json`
```json
{
...
scripts: {
...
"build:ldo": "ldo build --input ./shapes --output ./ldo"
...
}
...
}
```
Build the shpaes
## Generating a ShapeType
@ldo/cli generates shape types using the `*.shex` files in the "input" folder. If you followed the instructions above, run the following command:
```bash
ldo build --input ./.shapes --output ./.ldo
npm run build:ldo
```
This will generate five files:
- `./ldo/foafProfile.shapeTypes.ts` <-- This is the important file
- `./ldo/foafProfile.typings.ts`
- `./ldo/foafProfile.schema.ts`
- `./ldo/foafProfile.context.ts`
## API Details
- [`init` command](https://ldo.js.org/api/cli/init/)
- [`build` command](https://ldo.js.org/api/cli/build/)
```
## Sponsorship

@ -12,8 +12,8 @@ program
program
.command("build")
.description("Build contents of a shex folder into Shape Types")
.option("-i, --input <inputPath>", "Provide the input path", "./shapes")
.option("-o, --output <outputPath>", "Provide the output path", "./ldo")
.option("-i, --input <inputPath>", "Provide the input path", "./.shapes")
.option("-o, --output <outputPath>", "Provide the output path", "./.ldo")
.action(build);
program

@ -1,89 +1,36 @@
# LDO (Linked Data Objects)
# @ldo/ldo
LDO (Linked Data Objects) is a library that lets you easily manipulate RDF as if it were a standard TypeScript object that follows a [ShEx](https://shex.io) shape you define.
`@ldo/ldo` is the primary interface for accessing Linked Data Objects given raw RDF.
For a full tutorial of using LDO to build React Solid applications, see [this tutorial](https://medium.com/@JacksonMorgan/building-solid-apps-with-ldo-6127a5a1979c).
## Guide
## Setup
A full walkthrough for using the `@ldo/ldo` library can be found in the [For RDF Usage Guide](https://ldo.js.org/raw_rdf/).
### Automatic Setup
To setup LDO, `cd` into your typescript project and run `npx @ldo/cli init`.
## Installation
```bash
cd my-typescript-project
npx @ldo/cli init
```
### Manual Setup
The following is handled by the __automatic setup__:
Install the LDO dependencies.
```bash
npm install @ldo/ldo
npm install @ldo/cli --save-dev
```
### Automatic Installation
Create a folder to store your ShEx shapes:
```bash
mkdir shapes
Navigate into your project's root folder and run the following command:
```
Create a script to build ShEx shapes and convert them into Linked Data Objects. You can put this script in `package.json`
```json
{
...
scripts: {
...
"build:ldo": "ldo build --input ./shapes --output ./ldo"
...
}
...
}
cd my_project/
npx run @ldo/cli init
```
## Creating ShEx Schemas
LDO uses [ShEx](https://shex.io) as a schema for the RDF data in your project. To add a ShEx schema to your project, simply create a file ending in `.shex` to the `shapes` folder.
For more information on writing ShEx schemas see the [ShEx Primer](http://shex.io/shex-primer/index.html).
### Manual Installation
`./shapes/foafProfile.shex`:
```shex
PREFIX ex: <https://example.com/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
If you already have generated ShapeTypes, you may install the `@ldo/ldo` library independently.
ex:FoafProfile EXTRA a {
a [ foaf:Person ]
// rdfs:comment "Defines the node as a Person (from foaf)" ;
foaf:name xsd:string ?
// rdfs:comment "Define a person's name." ;
foaf:img xsd:string ?
// rdfs:comment "Photo link but in string form" ;
foaf:knows @ex:FoafProfile *
// rdfs:comment "A list of WebIds for all the people this user knows." ;
}
```
To build the shape, run:
```bash
npm run build:ldo
npm i @ldo/ldo
```
This will generate five files:
- `./ldo/foafProfile.shapeTypes.ts` <-- This is the important file
- `./ldo/foafProfile.typings.ts`
- `./ldo/foafProfile.schema.ts`
- `./ldo/foafProfile.context.ts`
## Simple Example
Below is a simple example of LDO in a real use-case (changing the name on a Solid Pod)
Below is a simple example of LDO in a real use-case (changing the name on a Solid Pod). Assume that a ShapeType was previously generated and placed at `./.ldo/foafProfile.shapeTypes`.
```typescript
import { parseRdf, startTransaction, toSparqlUpdate, toTurtle } from "ldo";
import { FoafProfileShapeType } from "./ldo/foafProfile.shapeTypes";
import { FoafProfileShapeType } from "./.ldo/foafProfile.shapeTypes";
async function run() {
const rawTurtle = `
@ -161,200 +108,49 @@ async function run() {
run();
```
## Getting an LDO Dataset
An LDO Dataset is a kind of [RDF JS Dataset](https://rdf.js.org/dataset-spec/) that can create linked data objects.
LDO datasets can be created in two ways:
`createLdoDataset(initialDataset?: Dataset<Quad, Quad> | Quad[])`
```typescript
import { createLdoDataset } from "ldo";
const ldoDataset = createLdoDataset();
```
- `initialDataset`: An optional dataset or array of quads for the new dataset.
## API Details
`parseRdf(data: string, parserOptions?: ParserOptions)`
```typescript
import { parseRdf } from "ldo";
Types
const rawTurtle = "...";
const ldoDataset = parseRdf(rawTurtle, { baseIRI: "https://example.com/" });
```
- [`LdoBase`](https://ldo.js.org/api/ldo/LdoBase/)
- [`ShapeType`](https://ldo.js.org/api/ldo/ShapeType/)
- `data`: The raw data to parse as a `string`.
- `options` (optional): Parse options containing the following keys:
- `format` (optional): The format the data is in. The following are acceptable formats: `Turtle`, `TriG`, `N-Triples`, `N-Quads`, `N3`, `Notation3`.
- `baseIRI` (optional): If this data is hosted at a specific location, you can provide the baseIRI of that location.
- `blankNodePrefix` (optional): If blank nodes should have a prefix, that should be provided here.
- `factory` (optional): a RDF Data Factory from [`@rdfjs/data-model`](https://www.npmjs.com/package/@rdfjs/data-model).
Getting a LdoDataset
## Getting a Linked Data Object
Once you have an LdoDataset we can get a Linked Data Object. A linked data object feels just like a JavaScript object literal, but when you make modifications to it, it will affect the underlying LdoDataset.
- [`parseRdf`](https://ldo.js.org/api/ldo/parseRdf/)
- [`createLdoDatasetFactory`](https://ldo.js.org/api/ldo/createLdoDatasetFactory/)
- [`LdoDatasetFactory`](https://ldo.js.org/api/ldo/LdoDatasetFactory/)
- [`createLdoDataset`](https://ldo.js.org/api/ldo/createLdoDataset/)
- [`LdoDataset`](https://ldo.js.org/api/ldo/LdoDataset/)
Thie first step is defining which Shape Type you want to retrieve from the dataset. We can use the generated shape types and the `usingType()` method for this.
Getting a Linked Data Object
```typescript
import { FoafProfileShapeType } from "./ldo/foafProfile.shapeTypes.ts";
- [`LdoBuilder`](https://ldo.js.org/api/ldo/LdoBuilder/)
// ... Get the LdoDataset
Converting a Linked Data Object to Raw RDF
ldoDataset.usingType(FoafProfileShapeType);
```
- [`toTurtle`](https://ldo.js.org/api/ldo/toTurtle/)
- [`toNTriples`](https://ldo.js.org/api/ldo/toNTriples/)
- [`serialize`](https://ldo.js.org/api/ldo/serialize/)
Next, we want to identify exactly what part of the dataset we want to extract. We can do this in a few ways:
Transactions
### `.fromSubject(entryNode)`
`fromSubject` lets you define a an `entryNode`, the place of entry for the graph. The object returned by `jsonldDatasetProxy` will represent the given node. This parameter accepts both `namedNode`s and `blankNode`s. `fromSubject` takes a generic type representing the typescript type of the given subject.
- [transactions](https://ldo.js.org/api/ldo/transactions/)
- [`toSparqlUpdate`](https://ldo.js.org/api/ldo/toSparqlUpdate/)
```typescript
const profile = ldoDataset
.usingType(FoafProfileShapeType)
.fromSubject("http://example.com/Person1");
```
Language Tag Support
### `.matchSubject(predicate?, object?, graph?)`
`matchSubject` returns a Jsonld Dataset Proxy representing all subjects in the dataset matching the given predicate, object, and graph.
- [`languageOf`](https://ldo.js.org/api/ldo/languageOf/)
- [`setLanguagePreferences`](https://ldo.js.org/api/ldo/setLanguagePreferences/)
```typescript
const profiles = ldoDataset
.usingType(FoafProfileShapeType)
.matchSubject(
namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
namedNode("http://xmlns.com/foaf/0.1/Person")
);
profiles.forEach((person) => {
console.log(person.fn);
});
```
Graph Support
### `.matchObject(subject?, predicate?, object?)`
`matchObject` returns a Jsonld Dataset Proxy representing all objects in the dataset matching the given subject, predicate, and graph.
- [`graphOf`](https://ldo.js.org/api/ldo/graphOf/)
- [`write`](https://ldo.js.org/api/ldo/write/)
```typescript
const friendsOfPerson1 = ldoDataset
.usingType(FoafProfileShapeType)
.matchSubject(
namedNode("http://example.com/Person1"),
namedNode("http://xmlns.com/foaf/0.1/knows")
);
friendsOfPerson1.forEach((person) => {
console.log(person.fn);
});
```
### `.fromJson(inputData)`
`fromJson` will take any regular Json, add the information to the dataset, and return a Jsonld Dataset Proxy representing the given data.
Other Helper Functions
```typescript
const person2 = ldoDataset
.usingType(FoafProfileShapeType)
.fromJson({
"@id": "http://example.com/Person2",
fn: ["Jane Doe"],
});
```
## Getting and Setting Data on a Linked Data Object
Once you've created a Linked Data Object, you can get and set data as if it were a normal TypeScript Object. For specific details, see the documentation at [JSONLD Dataset Proxy](https://github.com/o-development/jsonld-dataset-proxy/blob/master/Readme.md).
```typescript
import { LinkedDataObject } from "ldo";
import { FoafProfileFactory } from "./ldo/foafProfile.ldoFactory.ts";
import { FoafProfile } from "./ldo/foafProfile.typings";
aysnc function start() {
const profile: FoafProfile = // Create LDO
// Logs "Aang"
console.log(profile.name);
// Logs "Person"
console.log(profile.type);
// Logs 1
console.log(profile.knows?.length);
// Logs "Katara"
console.log(profile.knows?.[0].name);
profile.name = "Bonzu Pippinpaddleopsicopolis III"
// Logs "Bonzu Pippinpaddleopsicopolis III"
console.log(profile.name);
profile.knows?.push({
type: "Person",
name: "Sokka"
});
// Logs 2
console.log(profile.knows?.length);
// Logs "Katara" and "Sokka"
profile.knows?.forEach((person) => console.log(person.name));
}
```
## Converting a Linked Data Object back to RDF
A linked data object can be converted into RDF in multiple ways:
### `toTurtle(linkedDataObject)`
```typescript
import { toTurtle } from "ldo"
// ...
const rawTurtle: string = await toTurtle(profile);
```
### `toNTiples(linkedDataObject)`
```typescript
import { toNTriples } from "ldo"
// ...
const rawNTriples: string = await toNTriples(profile);
```
### `serialize(linkedDataObject, options)`
```typescript
const rawTurtle: string = await profile.$serialize({
format: "Turtle",
prefixes: {
ex: "https://example.com/",
foaf: "http://xmlns.com/foaf/0.1/",
}
});
```
`serialize(linkedDataObject, options)` provides general serialization based on provided options:
- `foramt` (optional): The format to serialize to. The following are acceptable formats: `Turtle`, `TriG`, `N-Triples`, `N-Quads`, `N3`, `Notation3`.
- `prefixes`: The prefixes for those serializations that use prefixes.
## Transactions
Sometimes, you want to keep track of changes you make for the object. This is where transactions come in handy.
To start a transaction, use the `startTransaction(linkedDataObject)` function. From then on, all transactions will be tracked, but not added to the original ldoDataset. You can view the changes using the `transactionChanges(linkedDataObject)` or `toSparqlUpdate(linkedDataObject)` methods. When you're done with the transaction, you can run the `commitTransaction(linkedDataObject)` method to add the changes to the original ldoDataset.
```typescript
import {
startTransaction,
transactionChanges,
toSparqlUpdate,
commitTransaction,
} from "ldo";
// ... Get the profile linked data object
startTransaction(profile);
profile.name = "Kuzon"
const changes = transactionChanges(profile));
// Logs: <https://example.com/aang> <http://xmlns.com/foaf/0.1/name> "Kuzon"
console.log(changes.added?.toString())
// Logs: <https://example.com/aang> <http://xmlns.com/foaf/0.1/name> "Aang"
console.log(changes.removed?.toString())
console.log(await toSparqlUpdate(profile));
commitTransaction(profile);
```
## Other LDO Helper Functions
### `getDataset(linkedDataObject)`
Returns the Linked Data Object's underlying RDFJS dataset. Modifying this dataset will change the Linked Data Object as well.
```typescript
import { getDataset } from "ldo"
const dataset = getDataset(profile);
```
- [`getDataset`](https://ldo.js.org/api/ldo/getDataset/)
## Sponsorship
This project was made possible by a grant from NGI Zero Entrust via nlnet. Learn more on the [NLnet project page](https://nlnet.nl/project/SolidUsableApps/).

@ -6,10 +6,20 @@ import { LdoDataset } from "./LdoDataset";
*/
export class LdoDatasetFactory implements DatasetFactory<Quad, Quad> {
private datasetFactory: DatasetFactory<Quad, Quad>;
/**
* @constructor
* @param datasetFactory A generic dataset factory this factory will wrap
*/
constructor(datasetFactory: DatasetFactory<Quad, Quad>) {
this.datasetFactory = datasetFactory;
}
/**
* Creates an LdoDataset
* @param quads A list of quads to initialize the dataset
* @returns an LdoDataset
*/
dataset(quads?: Dataset<Quad, Quad> | Quad[]): LdoDataset {
return new LdoDataset(
this.datasetFactory,

@ -2,7 +2,9 @@ import type { ContextDefinition } from "jsonld";
import type { Schema } from "shexj";
import type { LdoBase } from "./util";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
/**
* A collection of information required by LDO
*/
export type ShapeType<Type extends LdoBase> = {
schema: Schema;
shape: string;

@ -2,6 +2,10 @@ import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types";
import { createDataset } from "@ldo/dataset";
import { LdoDatasetFactory } from "./LdoDatasetFactory";
/**
* Creates an LDO Dataset Factory
* @returns An LDO Dataset Factory
*/
export function createLdoDatasetFactory() {
const datasetFactory: DatasetFactory<Quad> = {
dataset: (quads?: Dataset<Quad> | Quad[]): Dataset<Quad> => {
@ -11,6 +15,11 @@ export function createLdoDatasetFactory() {
return new LdoDatasetFactory(datasetFactory);
}
/**
* Create an LDO Dataset
* @param initialDataset
* @returns An LDO Dataset Factory
*/
export function createLdoDataset(
initialDataset?: Dataset<Quad, Quad> | Quad[],
) {

@ -1,88 +0,0 @@
// import type { App } from "@solid/community-server";
// import { getAuthenticatedFetch, ROOT_CONTAINER } from "./solidServer.helper";
// import type { SolidLdoDataset } from "../src/SolidLdoDataset";
// import { createSolidLdoDataset } from "../src/createSolidLdoDataset";
// import { ContainerRequester } from "../src/requester/ContainerRequester";
// import type { ContainerUri } from "../src/util/uriTypes";
// describe.skip("Container Requester", () => {
// let _app: App;
// let authFetch: typeof fetch;
// let fetchMock: typeof fetch;
// let solidLdoDataset: SolidLdoDataset;
// beforeAll(async () => {
// // Start up the server
// // app = await createApp();
// // await app.start();
// authFetch = await getAuthenticatedFetch();
// });
// beforeEach(async () => {
// fetchMock = jest.fn(authFetch);
// solidLdoDataset = createSolidLdoDataset({ fetch: fetchMock });
// // Create a new document called sample.ttl
// await Promise.all([
// authFetch(`${ROOT_CONTAINER}test_leaf/`, {
// method: "POST",
// headers: { "content-type": "text/turtle", slug: "sample.ttl" },
// body: `@base <http://example.org/> .
// @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
// @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
// @prefix foaf: <http://xmlns.com/foaf/0.1/> .
// @prefix rel: <http://www.perceive.net/schemas/relationship/> .
// <#green-goblin>
// rel:enemyOf <#spiderman> ;
// a foaf:Person ; # in the context of the Marvel universe
// foaf:name "Green Goblin" .
// <#spiderman>
// rel:enemyOf <#green-goblin> ;
// a foaf:Person ;
// foaf:name "Spiderman", "Человек-паук"@ru .`,
// }),
// authFetch(`${ROOT_COONTAINER}test_leaf/`, {
// method: "PUT",
// headers: { "content-type": "text/plain", slug: "sample.txt" },
// body: `some text.`,
// }),
// ]);
// });
// afterEach(async () => {
// await Promise.all([
// authFetch(`${ROOT_COONTAINER}test_leaf/sample.ttl`, {
// method: "DELETE",
// }),
// authFetch(`${ROOT_COONTAINER}test_leaf/sample2.ttl`, {
// method: "DELETE",
// }),
// authFetch(`${ROOT_COONTAINER}test_leaf/sample.txt`, {
// method: "DELETE",
// }),
// authFetch(`${ROOT_COONTAINER}test_leaf/sample2.txt`, {
// method: "DELETE",
// }),
// ]);
// });
// it("Checks if a root container is a root container", async () => {
// const leafRequester = new ContainerRequester(
// `${ROOT_COONTAINER}` as ContainerUri,
// solidLdoDataset.context,
// );
// const result = await leafRequester.isRootContainer();
// expect(result).toBe(true);
// });
// it("Checks if a non root container is a root container", async () => {
// const leafRequester = new ContainerRequester(
// `${ROOT_COONTAINER}/test_leaf/`,
// solidLdoDataset.context,
// );
// const result = await leafRequester.isRootContainer();
// expect(result).toBe(false);
// });
// });

@ -6,7 +6,8 @@ import {
createApp,
getAuthenticatedFetch,
} from "./solidServer.helper";
import { namedNode } from "@rdfjs/data-model";
import { namedNode, quad as createQuad } from "@rdfjs/data-model";
import { wait } from "./utils.helper";
const TEST_CONTAINER_SLUG = "test_ldo/";
const TEST_CONTAINER_URI =
@ -30,6 +31,24 @@ const SPIDER_MAN_TTL = `@base <http://example.org/> .
rel:enemyOf <#green-goblin> ;
a foaf:Person ;
foaf:name "Spiderman", "Человек-паук"@ru .`;
const TEST_CONTAINER_TTL = `@prefix dc: <http://purl.org/dc/terms/>.
@prefix ldp: <http://www.w3.org/ns/ldp#>.
@prefix posix: <http://www.w3.org/ns/posix/stat#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
<> <urn:npm:solid:community-server:http:slug> "sample.txt";
a ldp:Container, ldp:BasicContainer, ldp:Resource;
dc:modified "2023-10-20T13:57:14.000Z"^^xsd:dateTime.
<sample.ttl> a ldp:Resource, <http://www.w3.org/ns/iana/media-types/text/turtle#Resource>;
dc:modified "2023-10-20T13:57:14.000Z"^^xsd:dateTime.
<sample.txt> a ldp:Resource, <http://www.w3.org/ns/iana/media-types/text/plain#Resource>;
dc:modified "2023-10-20T13:57:14.000Z"^^xsd:dateTime.
<> posix:mtime 1697810234;
ldp:contains <sample.ttl>, <sample.txt>.
<sample.ttl> posix:mtime 1697810234;
posix:size 522.
<sample.txt> posix:mtime 1697810234;
posix:size 10.`;
describe("SolidLdoDataset", () => {
let app: App;
@ -95,6 +114,9 @@ describe("SolidLdoDataset", () => {
]);
});
/**
* Read
*/
describe("read", () => {
it("Reads a data leaf", async () => {
const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
@ -199,7 +221,7 @@ describe("SolidLdoDataset", () => {
it("Returns an error if there is no link header for a container request", async () => {
fetchMock.mockResolvedValueOnce(
new Response(SPIDER_MAN_TTL, {
new Response(TEST_CONTAINER_TTL, {
status: 200,
headers: new Headers({ "content-type": "text/turtle" }),
}),
@ -214,4 +236,176 @@ describe("SolidLdoDataset", () => {
);
});
});
/**
* Get Root Container
*/
describe("rootContainer", () => {
it("Finds the root container", async () => {
const resource = solidLdoDataset.getResource(SAMPLE2_BINARY_URI);
const result = await resource.getRootContainer();
expect(result.type).toBe("container");
if (result.type !== "container") return;
expect(result.uri).toBe(ROOT_CONTAINER);
});
it("Returns an error if there is no link header for a container request", async () => {
fetchMock.mockResolvedValueOnce(
new Response(TEST_CONTAINER_TTL, {
status: 200,
headers: new Headers({ "content-type": "text/turtle" }),
}),
);
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await resource.getRootContainer();
expect(result.isError).toBe(true);
if (!result.isError) return;
expect(result.type).toBe("noncompliantPodError");
expect(result.message).toBe(
"Response from https://solidweb.me/jackson3/test_ldo/ is not compliant with the Solid Specification: No link header present in request.",
);
});
it("An error to be returned if a common http error is encountered", async () => {
fetchMock.mockResolvedValueOnce(
new Response(TEST_CONTAINER_TTL, {
status: 500,
}),
);
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await resource.getRootContainer();
expect(result.isError).toBe(true);
expect(result.type).toBe("serverError");
});
it("Returns an UnexpectedResourceError if an unknown error is triggered", async () => {
fetchMock.mockRejectedValueOnce(new Error("Something happened."));
const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
const result = await resource.getRootContainer();
expect(result.isError).toBe(true);
if (!result.isError) return;
expect(result.type).toBe("unexpectedResourceError");
expect(result.message).toBe("Something happened.");
});
});
/**
* Create Data Resource
*/
describe("createDataResource", () => {
it("creates a document that doesn't exist", async () => {
const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
fetchMock.mockImplementationOnce(async (...args) => {
console.log("before");
await wait(500);
console.log("after");
return authFetch(...args);
});
const [result] = await Promise.all([
resource.createAndOverwrite(),
(async () => {
await wait(100);
console.log("Checking");
expect(resource.isLoading()).toBe(true);
expect(resource.isCreating()).toBe(true);
expect(resource.isReading()).toBe(false);
expect(resource.isUploading).toBe(false);
expect(resource.isReloading()).toBe(false);
expect(resource.isDeleting()).toBe(false);
})(),
]);
expect(result.type).toBe("createSuccess");
expect(
solidLdoDataset.has(
createQuad(
namedNode(TEST_CONTAINER_URI),
namedNode("http://www.w3.org/ns/ldp#contains"),
namedNode(SAMPLE2_DATA_URI),
namedNode(TEST_CONTAINER_URI),
),
),
).toBe(true);
expect(
container.children().some((child) => child.uri === SAMPLE2_DATA_URI),
).toBe(true);
});
// it("creates a data resource that doesn't exist while overwriting", async () => {
// const leafRequester = new LeafRequester(
// `${ROOT_COONTAINER}test_leaf/sample2.ttl`,
// solidLdoDataset.context,
// );
// const result = await leafRequester.createDataResource(true);
// expect(result.type).toBe("data");
// expect(
// solidLdoDataset.has(
// createQuad(
// namedNode(`${ROOT_COONTAINER}test_leaf/`),
// namedNode("http://www.w3.org/ns/ldp#contains"),
// namedNode(`${ROOT_COONTAINER}test_leaf/sample2.ttl`),
// namedNode(`${ROOT_COONTAINER}test_leaf/`),
// ),
// ),
// ).toBe(true);
// });
// it("creates a data resource that does exist while not overwriting", async () => {
// const leafRequester = new LeafRequester(
// `${ROOT_COONTAINER}test_leaf/sample.ttl`,
// solidLdoDataset.context,
// );
// const result = await leafRequester.createDataResource();
// expect(result.type).toBe("data");
// expect(
// solidLdoDataset.has(
// createQuad(
// namedNode("http://example.org/#spiderman"),
// namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
// namedNode("http://example.org/#green-goblin"),
// namedNode(`${ROOT_COONTAINER}test_leaf/sample.ttl`),
// ),
// ),
// ).toBe(true);
// expect(
// solidLdoDataset.has(
// createQuad(
// namedNode(`${ROOT_COONTAINER}test_leaf/`),
// namedNode("http://www.w3.org/ns/ldp#contains"),
// namedNode(`${ROOT_COONTAINER}test_leaf/sample.ttl`),
// namedNode(`${ROOT_COONTAINER}test_leaf/`),
// ),
// ),
// ).toBe(true);
// });
// it("creates a data resource that does exist while overwriting", async () => {
// const leafRequester = new LeafRequester(
// `${ROOT_COONTAINER}test_leaf/sample.ttl`,
// solidLdoDataset.context,
// );
// const result = await leafRequester.createDataResource(true);
// expect(result.type).toBe("data");
// expect(
// solidLdoDataset.has(
// createQuad(
// namedNode("http://example.org/#spiderman"),
// namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
// namedNode("http://example.org/#green-goblin"),
// namedNode(`${ROOT_COONTAINER}test_leaf/sample.ttl`),
// ),
// ),
// ).toBe(false);
// expect(
// solidLdoDataset.has(
// createQuad(
// namedNode(`${ROOT_COONTAINER}test_leaf/`),
// namedNode("http://www.w3.org/ns/ldp#contains"),
// namedNode(`${ROOT_COONTAINER}test_leaf/sample.ttl`),
// namedNode(`${ROOT_COONTAINER}test_leaf/`),
// ),
// ),
// ).toBe(true);
// });
});
});

@ -0,0 +1,3 @@
export async function wait(millis: number) {
return new Promise((resolve) => setTimeout(resolve, millis));
}

@ -49,9 +49,8 @@ export default class WrapperSubscribableDataset<
new Map();
/**
*
* @param datasetFactory
* @param initialDataset
* @param datasetFactory A RDF/JS Dataset Factory
* @param initialDataset An RDF/JS Dataset with initial Quads
*/
constructor(
datasetFactory: DatasetFactory<InAndOutQuad, InAndOutQuad>,

Loading…
Cancel
Save