diff --git a/packages/solid-react/.eslintrc b/packages/react/.eslintrc
similarity index 100%
rename from packages/solid-react/.eslintrc
rename to packages/react/.eslintrc
diff --git a/packages/solid-react/.gitignore b/packages/react/.gitignore
similarity index 100%
rename from packages/solid-react/.gitignore
rename to packages/react/.gitignore
diff --git a/packages/solid-react/LICENSE.txt b/packages/react/LICENSE.txt
similarity index 100%
rename from packages/solid-react/LICENSE.txt
rename to packages/react/LICENSE.txt
diff --git a/packages/solid-react/README.md b/packages/react/README.md
similarity index 73%
rename from packages/solid-react/README.md
rename to packages/react/README.md
index 51c51f9..1eb1bbf 100644
--- a/packages/solid-react/README.md
+++ b/packages/react/README.md
@@ -1,6 +1,6 @@
-# @ldo/solid-react
+# @ldo/react
-`@ldo/solid-react` provides tool and hooks for easily building Solid applications using react.
+`@ldo/react` provides tool and hooks for easily building Solid applications using react.
## Guide
@@ -17,7 +17,7 @@ npx run @ldo/cli init
Now install the @ldo/solid library
```
-npm i @ldo/solid @ldo/solid-react
+npm i @ldo/solid @ldo/react
```
@@ -28,13 +28,13 @@ Manual Installation
If you already have generated ShapeTypes, you may install the `@ldo/ldo` and `@ldo/solid` libraries independently.
```
-npm i @ldo/ldo @ldo/solid @ldo/solid-react
+npm i @ldo/ldo @ldo/solid @ldo/react
```
## Simple Example
-Below is a simple example of @ldo/solid-react in a real use-case. Assume that a ShapeType was previously generated and placed at `./.ldo/solidProfile.shapeTypess`.
+Below is a simple example of @ldo/react in a real use-case. Assume that a ShapeType was previously generated and placed at `./.ldo/solidProfile.shapeTypess`.
```typescript
@@ -45,7 +45,7 @@ import {
useResource,
useSolidAuth,
useSubject,
-} from "@ldo/solid-react";
+} from "@ldo/react";
import { SolidProfileShapeShapeType } from "./.ldo/solidProfile.shapeTypes";
import { changeData, commitData } from "@ldo/solid";
@@ -115,18 +115,18 @@ export default App;
Providers
- - [BrowserSolidLdoProvider](https://ldo.js.org/latest/api/solid-react/BrowserSolidLdoProvider/)
- - [SolidLdoProvider](https://ldo.js.org/latest/api/solid-react/SolidLdoProvider/)
+ - [BrowserSolidLdoProvider](https://ldo.js.org/latest/api/react/BrowserSolidLdoProvider/)
+ - [SolidLdoProvider](https://ldo.js.org/latest/api/react/SolidLdoProvider/)
Hooks
- - [useLdo](https://ldo.js.org/latest/api/solid-react/useLdo/)
- - [useResource](https://ldo.js.org/latest/api/solid-react/useResource/)
- - [useRootContainer](https://ldo.js.org/latest/api/solid-react/useRootContainer/)
- - [useSolidAuth](https://ldo.js.org/latest/api/solid-react/useSolidAuth/)
- - [useSubject](https://ldo.js.org/latest/api/solid-react/useSubject/)
- - [useMatchSubject](https://ldo.js.org/latest/api/solid-react/useMatchSubject/)
- - [useMatchObject](https://ldo.js.org/latest/api/solid-react/useMatchSubject/)
- - [useSubscribeToResource](https://ldo.js.org/latest/api/solid-react/useMatchSubject/)
+ - [useLdo](https://ldo.js.org/latest/api/react/useLdo/)
+ - [useResource](https://ldo.js.org/latest/api/react/useResource/)
+ - [useRootContainer](https://ldo.js.org/latest/api/react/useRootContainer/)
+ - [useSolidAuth](https://ldo.js.org/latest/api/react/useSolidAuth/)
+ - [useSubject](https://ldo.js.org/latest/api/react/useSubject/)
+ - [useMatchSubject](https://ldo.js.org/latest/api/react/useMatchSubject/)
+ - [useMatchObject](https://ldo.js.org/latest/api/react/useMatchSubject/)
+ - [useSubscribeToResource](https://ldo.js.org/latest/api/react/useMatchSubject/)
## 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/).
diff --git a/packages/solid-react/jest.config.js b/packages/react/jest.config.js
similarity index 100%
rename from packages/solid-react/jest.config.js
rename to packages/react/jest.config.js
diff --git a/packages/solid-react/jest.setup.ts b/packages/react/jest.setup.ts
similarity index 100%
rename from packages/solid-react/jest.setup.ts
rename to packages/react/jest.setup.ts
diff --git a/packages/solid-react/package.json b/packages/react/package.json
similarity index 96%
rename from packages/solid-react/package.json
rename to packages/react/package.json
index 0f38c26..51dddff 100644
--- a/packages/solid-react/package.json
+++ b/packages/react/package.json
@@ -1,5 +1,5 @@
{
- "name": "@ldo/solid-react",
+ "name": "@ldo/react",
"version": "1.0.0-alpha.1",
"description": "A React library for LDO and Solid",
"main": "dist/index.js",
@@ -40,7 +40,7 @@
"@ldo/dataset": "^1.0.0-alpha.1",
"@ldo/jsonld-dataset-proxy": "^1.0.0-alpha.1",
"@ldo/ldo": "^1.0.0-alpha.1",
- "@ldo/solid": "^1.0.0-alpha.1",
+ "@ldo/connected": "^1.0.0-alpha.1",
"@ldo/subscribable-dataset": "^1.0.0-alpha.1",
"@rdfjs/data-model": "^1.2.0",
"cross-fetch": "^3.1.6"
diff --git a/packages/solid-react/src/BrowserSolidLdoProvider.tsx b/packages/react/src/BrowserSolidLdoProvider.tsx
similarity index 100%
rename from packages/solid-react/src/BrowserSolidLdoProvider.tsx
rename to packages/react/src/BrowserSolidLdoProvider.tsx
diff --git a/packages/solid-react/src/SolidAuthContext.ts b/packages/react/src/SolidAuthContext.ts
similarity index 100%
rename from packages/solid-react/src/SolidAuthContext.ts
rename to packages/react/src/SolidAuthContext.ts
diff --git a/packages/solid-react/src/SolidLdoProvider.tsx b/packages/react/src/SolidLdoProvider.tsx
similarity index 100%
rename from packages/solid-react/src/SolidLdoProvider.tsx
rename to packages/react/src/SolidLdoProvider.tsx
diff --git a/packages/solid-react/src/UnauthenticatedSolidLdoProvider.tsx b/packages/react/src/UnauthenticatedSolidLdoProvider.tsx
similarity index 100%
rename from packages/solid-react/src/UnauthenticatedSolidLdoProvider.tsx
rename to packages/react/src/UnauthenticatedSolidLdoProvider.tsx
diff --git a/packages/solid-react/src/index.ts b/packages/react/src/index.ts
similarity index 100%
rename from packages/solid-react/src/index.ts
rename to packages/react/src/index.ts
diff --git a/packages/solid-react/src/useLdoMethods.ts b/packages/react/src/useLdoMethods.ts
similarity index 100%
rename from packages/solid-react/src/useLdoMethods.ts
rename to packages/react/src/useLdoMethods.ts
diff --git a/packages/solid-react/src/useMatchObject.ts b/packages/react/src/useMatchObject.ts
similarity index 100%
rename from packages/solid-react/src/useMatchObject.ts
rename to packages/react/src/useMatchObject.ts
diff --git a/packages/solid-react/src/useMatchSubject.ts b/packages/react/src/useMatchSubject.ts
similarity index 100%
rename from packages/solid-react/src/useMatchSubject.ts
rename to packages/react/src/useMatchSubject.ts
diff --git a/packages/solid-react/src/useResource.ts b/packages/react/src/useResource.ts
similarity index 100%
rename from packages/solid-react/src/useResource.ts
rename to packages/react/src/useResource.ts
diff --git a/packages/solid-react/src/useRootContainer.ts b/packages/react/src/useRootContainer.ts
similarity index 100%
rename from packages/solid-react/src/useRootContainer.ts
rename to packages/react/src/useRootContainer.ts
diff --git a/packages/solid-react/src/useSubject.ts b/packages/react/src/useSubject.ts
similarity index 100%
rename from packages/solid-react/src/useSubject.ts
rename to packages/react/src/useSubject.ts
diff --git a/packages/solid-react/src/useSubscribeToResource.ts b/packages/react/src/useSubscribeToResource.ts
similarity index 100%
rename from packages/solid-react/src/useSubscribeToResource.ts
rename to packages/react/src/useSubscribeToResource.ts
diff --git a/packages/solid-react/src/util/TrackingProxyContext.ts b/packages/react/src/util/TrackingProxyContext.ts
similarity index 100%
rename from packages/solid-react/src/util/TrackingProxyContext.ts
rename to packages/react/src/util/TrackingProxyContext.ts
diff --git a/packages/solid-react/src/util/TrackingSetProxy.ts b/packages/react/src/util/TrackingSetProxy.ts
similarity index 100%
rename from packages/solid-react/src/util/TrackingSetProxy.ts
rename to packages/react/src/util/TrackingSetProxy.ts
diff --git a/packages/solid-react/src/util/TrackingSubjectProxy.ts b/packages/react/src/util/TrackingSubjectProxy.ts
similarity index 100%
rename from packages/solid-react/src/util/TrackingSubjectProxy.ts
rename to packages/react/src/util/TrackingSubjectProxy.ts
diff --git a/packages/solid-react/src/util/useTrackingProxy.ts b/packages/react/src/util/useTrackingProxy.ts
similarity index 100%
rename from packages/solid-react/src/util/useTrackingProxy.ts
rename to packages/react/src/util/useTrackingProxy.ts
diff --git a/packages/solid-react/test/.ldo/post.context.ts b/packages/react/test/.ldo/post.context.ts
similarity index 100%
rename from packages/solid-react/test/.ldo/post.context.ts
rename to packages/react/test/.ldo/post.context.ts
diff --git a/packages/solid-react/test/.ldo/post.schema.ts b/packages/react/test/.ldo/post.schema.ts
similarity index 100%
rename from packages/solid-react/test/.ldo/post.schema.ts
rename to packages/react/test/.ldo/post.schema.ts
diff --git a/packages/solid-react/test/.ldo/post.shapeTypes.ts b/packages/react/test/.ldo/post.shapeTypes.ts
similarity index 100%
rename from packages/solid-react/test/.ldo/post.shapeTypes.ts
rename to packages/react/test/.ldo/post.shapeTypes.ts
diff --git a/packages/solid-react/test/.ldo/post.typings.ts b/packages/react/test/.ldo/post.typings.ts
similarity index 100%
rename from packages/solid-react/test/.ldo/post.typings.ts
rename to packages/react/test/.ldo/post.typings.ts
diff --git a/packages/solid-react/test/Integration.test.tsx b/packages/react/test/Integration.test.tsx
similarity index 100%
rename from packages/solid-react/test/Integration.test.tsx
rename to packages/react/test/Integration.test.tsx
diff --git a/packages/solid-react/test/setUpServer.ts b/packages/react/test/setUpServer.ts
similarity index 100%
rename from packages/solid-react/test/setUpServer.ts
rename to packages/react/test/setUpServer.ts
diff --git a/packages/solid-react/test/test-server/configs/components-config/unauthenticatedServer.json b/packages/react/test/test-server/configs/components-config/unauthenticatedServer.json
similarity index 100%
rename from packages/solid-react/test/test-server/configs/components-config/unauthenticatedServer.json
rename to packages/react/test/test-server/configs/components-config/unauthenticatedServer.json
diff --git a/packages/solid-react/test/test-server/configs/solid-css-seed.json b/packages/react/test/test-server/configs/solid-css-seed.json
similarity index 100%
rename from packages/solid-react/test/test-server/configs/solid-css-seed.json
rename to packages/react/test/test-server/configs/solid-css-seed.json
diff --git a/packages/solid-react/test/test-server/configs/template/wac/.acl.hbs b/packages/react/test/test-server/configs/template/wac/.acl.hbs
similarity index 100%
rename from packages/solid-react/test/test-server/configs/template/wac/.acl.hbs
rename to packages/react/test/test-server/configs/template/wac/.acl.hbs
diff --git a/packages/solid-react/test/test-server/configs/template/wac/profile/card.acl.hbs b/packages/react/test/test-server/configs/template/wac/profile/card.acl.hbs
similarity index 100%
rename from packages/solid-react/test/test-server/configs/template/wac/profile/card.acl.hbs
rename to packages/react/test/test-server/configs/template/wac/profile/card.acl.hbs
diff --git a/packages/solid-react/test/test-server/runServer.ts b/packages/react/test/test-server/runServer.ts
similarity index 100%
rename from packages/solid-react/test/test-server/runServer.ts
rename to packages/react/test/test-server/runServer.ts
diff --git a/packages/solid-react/test/test-server/solidServer.helper.ts b/packages/react/test/test-server/solidServer.helper.ts
similarity index 100%
rename from packages/solid-react/test/test-server/solidServer.helper.ts
rename to packages/react/test/test-server/solidServer.helper.ts
diff --git a/packages/solid-react/tsconfig.build.json b/packages/react/tsconfig.build.json
similarity index 100%
rename from packages/solid-react/tsconfig.build.json
rename to packages/react/tsconfig.build.json
diff --git a/packages/solid/.eslintrc b/packages/solid/.eslintrc
deleted file mode 100644
index 83c51a9..0000000
--- a/packages/solid/.eslintrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": ["../../.eslintrc"]
-}
\ No newline at end of file
diff --git a/packages/solid/.gitignore b/packages/solid/.gitignore
deleted file mode 100644
index 5ed9aae..0000000
--- a/packages/solid/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-test/data
\ No newline at end of file
diff --git a/packages/solid/LICENSE.txt b/packages/solid/LICENSE.txt
deleted file mode 100644
index b87e67e..0000000
--- a/packages/solid/LICENSE.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 Jackson Morgan
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
diff --git a/packages/solid/README.md b/packages/solid/README.md
deleted file mode 100644
index 94c9ada..0000000
--- a/packages/solid/README.md
+++ /dev/null
@@ -1,238 +0,0 @@
-# @ldo/solid
-
-@ldo/solid is a client that implements the Solid specification with the use of Linked Data Objects.
-
-## Installation
-
-Navigate into your project's root folder and run the following command:
-```
-cd my_project/
-npx run @ldo/cli init
-```
-
-Now install the @ldo/solid library
-
-```
-npm i @ldo/solid
-```
-
-
-
-Manual Installation
-
-
-If you already have generated ShapeTypes, you may install the `@ldo/ldo` and `@ldo/solid` libraries independently.
-
-```
-npm i @ldo/ldo @ldo/solid
-```
-
-
-## Simple Examples
-
-Below is a simple example of @ldo/solid. Assume that a ShapeType was previously generated and placed at `./.ldo/foafProfile.shapeTypes`. Also assume we have a shape type for social media at `./.ldo/socialMediaPost.shapeTypes`
-
-```typescript
-import { changeData, commitData, createSolidLdoDataset } from "@ldo/solid";
-import { fetch, getDefaultSession } from "@inrupt/solid-client-authn-browser";
-import { FoafProfileShapeType } from "./.ldo/foafProfile.shapeTypes";
-import { SocialMediaPostShapeType } from "./.ldo/socialMediaPost.shapeTypes";
-
-async function main() {
- /**
- * ===========================================================================
- * READING DATA FROM A POD
- * ===========================================================================
- */
-
- // Before we begin using @ldo/solid. Let's get the WebId of the current user
- const webIdUri = getDefaultSession().info.webId;
- if (!webIdUri) throw new Error("User is not logged in");
-
- // Now let's proceed with @ldo/solid. Our first step is setting up a
- // SolidLdoDataset. You can think of this dataset as a local store for all the
- // information in the Solidverse. Don't forget to pass the authenticated fetch
- // function to do your queries!
- const solidLdoDataset = createSolidLdoDataset({ fetch });
-
- // We'll start with getting a representation of our WebId's resource
- const webIdResource = solidLdoDataset.getResource(webIdUri);
-
- // This resource is currently unfetched
- console.log(webIdResource.isUnfetched()); // Logs true
-
- // So let's fetch it! Running the `read` command will make a request to get
- // the WebId.
- const readResult = await webIdResource.read();
-
- // @ldo/solid will never throw an error. Instead, it will return errors. This
- // design decision was made to force you to handle any errors. It may seem a
- // bit annoying at first, but it will result in more resiliant code. You can
- // easily follow intellisense tooltips to see what kinds of errors each action
- // can throw.
- if (readResult.isError) {
- switch (readResult.type) {
- case "serverError":
- console.error("The solid server had an error:", readResult.message);
- return;
- case "noncompliantPodError":
- console.error("The Pod responded in a way not compliant with the spec");
- return;
- default:
- console.error("Some other error was detected:", readResult.message);
- }
- }
-
- // When fetching a data resource, read triples will automatically be added to
- // the solidLdoDataset. You can access them using Linked Data Objects. In
- // the following example we're using a Profile Linked Data Object that was
- // generated with the init step.
- const profile = solidLdoDataset
- .usingType(FoafProfileShapeType)
- .fromSubject(webIdUri);
-
- // Now you can read "profile" like any JSON.
- console.log(profile.name);
-
- /**
- * ===========================================================================
- * MODIFYING DATA
- * ===========================================================================
- */
-
- // When we want to modify data the first step is to use the `changeData`
- // function. We pass in an object that we want to change (in this case,
- // "profile") as well an a list of any resources to which we want those
- // changes to be applied (in this case, just the webIdResource). This gives
- // us a new variable (conventionally named with a c for "changed") that we can
- // write changes to.
- const cProfile = changeData(profile, webIdResource);
-
- // We can make changes just like it's regular JSON
- cProfile.name = "Captain Cool Dude";
-
- // Committing data is as easy as running the "commitData" function.
- const commitResult = await commitData(cProfile);
-
- // Remember to check for and handle errors! We'll keep it short this time.
- if (commitResult.isError) throw commitResult;
-
- /**
- * ===========================================================================
- * CREATING NEW RESOURCES
- * ===========================================================================
- */
-
- // Let's create some social media posts to be stored on the Solid Pod!
- // Our first step is going to be finding where to place these posts. In the
- // future, there will be advanced ways to determine the location of resources
- // but for now, let's throw it in the root folder.
-
- // But, first, let's find out where the root folder is. We can take our WebId
- // resource and call `getRootContainer`. Let's assume the root container has
- // a URI "https://example.com/"
- const rootContainer = await webIdResource.getRootContainer();
- if (rootContainer.isError) throw rootContainer;
-
- // Now, let's create a container for our posts
- const createPostContainerResult =
- await rootContainer.createChildIfAbsent("social-posts/");
- if (createPostContainerResult.isError) throw createPostContainerResult;
-
- // Most results store the affected resource in the "resource" field. This
- // container has the URI "https://example.com/social-posts/"
- const postContainer = createPostContainerResult.resource;
-
- // Now that we have our container, let's make a Post resource! This is a data
- // resource, which means we can put raw Solid Data (RDF) into it.
- const postResourceResult =
- await postContainer.createChildAndOverwrite("post1.ttl");
- if (postResourceResult.isError) throw postResourceResult;
- const postResource = postResourceResult.resource;
-
- // We can also create binary resources with things like images
- const imageResourceResult = await postContainer.uploadChildAndOverwrite(
- // name of the binary
- "image1.svg",
- // A blob for the binary
- new Blob([``]),
- // mime type of the binary
- "image/svg+xml",
- );
- if (imageResourceResult.isError) throw imageResourceResult;
- const imageResource = imageResourceResult.resource;
-
- /**
- * ===========================================================================
- * CREATING NEW DATA
- * ===========================================================================
- */
-
- // We create data in a similar way to the way we modify data. We can use the
- // "createData" method.
- const cPost = solidLdoDataset.createData(
- // An LDO ShapeType saying that this is a social media psot
- SocialMediaPostShapeType,
- // The URI of the post (in this case we'll make it the same as the resource)
- postResource.uri,
- // The resource we should write it to
- postResource,
- );
-
- // We can add new data
- cPost.text = "Check out this bad svg:";
- cPost.image = { "@id": imageResource.uri };
-
- // And now we commit data
- const newDataResult = await commitData(cPost);
- if (newDataResult.isError) throw newDataResult;
-
- /**
- * ===========================================================================
- * DELETING RESOURCES
- * ===========================================================================
- */
-
- // Deleting resources can be done with a single method call. In this case,
- // the container will be deleted along with all its contained resources
- const deleteResult = await postContainer.delete();
- if (deleteResult.isError) throw deleteResult;
-}
-main();
-```
-
-## API Details
-
-SolidLdoDataset
-
- - [createSolidLdoDataset](https://ldo.js.org/latest/api/solid/functions/createSolidLdoDataset/)
- - [SolidLdoDataset](https://ldo.js.org/latest/api/solid/classes/SolidLdoDataset/)
-
-Resources (Manage batching requests)
-
- - [LeafUri](https://ldo.js.org/latest/api/solid/types/LeafUri/)
- - [ContainerUri](https://ldo.js.org/latest/api/solid/types/ContainerUri/)
- - [Leaf](https://ldo.js.org/latest/api/solid/classes/Leaf/)
- - [Container](https://ldo.js.org/latest/api/solid/classes/Container/)
-
-Standalone Functions
-
- - [checkRootContainter](https://ldo.js.org/latest/api/solid/functions/checkRootContainer/)
- - [createDataResource](https://ldo.js.org/latest/api/solid/functions/createDataResource/)
- - [deleteResource](https://ldo.js.org/latest/api/solid/functions/deleteResource/)
- - [readResource](https://ldo.js.org/latest/api/solid/functions/readResource/)
- - [updateResource](https://ldo.js.org/latest/api/solid/functions/updateResource/)
- - [uploadResource](https://ldo.js.org/latest/api/solid/functions/uploadResource/)
-
-Data Functions
- - [changeData](https://ldo.js.org/latest/api/solid/functions/changeData/)
- - [commitData](https://ldo.js.org/latest/api/solid/functions/commitData/)
-
-## 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/).
-
-[
](https://nlnet.nl/)
-[
](https://nlnet.nl/)
-
-## Liscense
-MIT
diff --git a/packages/solid/babel.config.js b/packages/solid/babel.config.js
deleted file mode 100644
index 721e8b8..0000000
--- a/packages/solid/babel.config.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = { presets: ["@babel/preset-env"] };
diff --git a/packages/solid/jest.config.js b/packages/solid/jest.config.js
deleted file mode 100644
index c55a5f7..0000000
--- a/packages/solid/jest.config.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// eslint-disable-next-line @typescript-eslint/no-var-requires
-const sharedConfig = require("../../jest.config.js");
-module.exports = {
- ...sharedConfig,
- rootDir: "./",
- setupFiles: ["/test/setup-tests.ts"],
- transform: {
- "^.+\\.(ts|tsx)?$": "ts-jest",
- "^.+\\.(js|jsx)$": "babel-jest",
- },
-};
diff --git a/packages/solid/package.json b/packages/solid/package.json
deleted file mode 100644
index ce4a648..0000000
--- a/packages/solid/package.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "name": "@ldo/solid",
- "version": "1.0.0-alpha.1",
- "description": "A library for LDO and Solid",
- "main": "dist/index.js",
- "scripts": {
- "example": "ts-node ./example/example.ts",
- "build": "tsc --project tsconfig.build.json",
- "watch": "tsc --watch",
- "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
- "test:watch": "jest --watch",
- "prepublishOnly": "npm run test && npm run build",
- "build:ldo": "ldo build --input src/.shapes --output src/.ldo",
- "lint": "eslint src/** --fix --no-error-on-unmatched-pattern",
- "docs": "typedoc --plugin typedoc-plugin-markdown"
- },
- "repository": {
- "type": "git",
- "url": "git+https://github.com/o-development/ldobjects.git"
- },
- "author": "Jackson Morgan",
- "license": "MIT",
- "bugs": {
- "url": "https://github.com/o-development/ldobjects/issues"
- },
- "homepage": "https://github.com/o-development/ldobjects/tree/main/packages/solid#readme",
- "devDependencies": {
- "@inrupt/solid-client-authn-core": "^2.2.6",
- "@ldo/cli": "^1.0.0-alpha.1",
- "@rdfjs/data-model": "^1.2.0",
- "@rdfjs/types": "^1.0.1",
- "@solid-notifications/types": "^0.1.2",
- "@solid/community-server": "^7.1.3",
- "@types/jest": "^27.0.3",
- "cross-env": "^7.0.3",
- "dotenv": "^16.3.1",
- "jest-rdf": "^1.8.0",
- "ts-jest": "^27.1.2",
- "ts-node": "^10.9.1",
- "typed-emitter": "^2.1.0",
- "typedoc": "^0.25.4",
- "typedoc-plugin-markdown": "^3.17.1"
- },
- "dependencies": {
- "@ldo/dataset": "^1.0.0-alpha.1",
- "@ldo/ldo": "^1.0.0-alpha.1",
- "@ldo/rdf-utils": "^1.0.0-alpha.1",
- "@solid-notifications/subscription": "^0.1.2",
- "cross-fetch": "^3.1.6",
- "http-link-header": "^1.1.1",
- "ws": "^8.18.0"
- },
- "files": [
- "dist",
- "src"
- ],
- "publishConfig": {
- "access": "public"
- },
- "gitHead": "0287cd6371f06630763568dec5e41653f7b8583e"
-}
diff --git a/packages/solid/src/.ldo/solid.context.ts b/packages/solid/src/.ldo/solid.context.ts
deleted file mode 100644
index 7f50b27..0000000
--- a/packages/solid/src/.ldo/solid.context.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import { LdoJsonldContext } from "@ldo/ldo";
-
-/**
- * =============================================================================
- * solidContext: JSONLD Context for solid
- * =============================================================================
- */
-export const solidContext: LdoJsonldContext = {
- type: {
- "@id": "@type",
- "@isCollection": true,
- },
- Container: {
- "@id": "http://www.w3.org/ns/ldp#Container",
- "@context": {
- type: {
- "@id": "@type",
- "@isCollection": true,
- },
- modified: {
- "@id": "http://purl.org/dc/terms/modified",
- "@type": "http://www.w3.org/2001/XMLSchema#string",
- },
- contains: {
- "@id": "http://www.w3.org/ns/ldp#contains",
- "@type": "@id",
- "@isCollection": true,
- },
- mtime: {
- "@id": "http://www.w3.org/ns/posix/stat#mtime",
- "@type": "http://www.w3.org/2001/XMLSchema#decimal",
- },
- size: {
- "@id": "http://www.w3.org/ns/posix/stat#size",
- "@type": "http://www.w3.org/2001/XMLSchema#integer",
- },
- },
- },
- Resource: {
- "@id": "http://www.w3.org/ns/ldp#Resource",
- "@context": {
- type: {
- "@id": "@type",
- "@isCollection": true,
- },
- modified: {
- "@id": "http://purl.org/dc/terms/modified",
- "@type": "http://www.w3.org/2001/XMLSchema#string",
- },
- contains: {
- "@id": "http://www.w3.org/ns/ldp#contains",
- "@type": "@id",
- "@isCollection": true,
- },
- mtime: {
- "@id": "http://www.w3.org/ns/posix/stat#mtime",
- "@type": "http://www.w3.org/2001/XMLSchema#decimal",
- },
- size: {
- "@id": "http://www.w3.org/ns/posix/stat#size",
- "@type": "http://www.w3.org/2001/XMLSchema#integer",
- },
- },
- },
- modified: {
- "@id": "http://purl.org/dc/terms/modified",
- "@type": "http://www.w3.org/2001/XMLSchema#string",
- },
- contains: {
- "@id": "http://www.w3.org/ns/ldp#contains",
- "@type": "@id",
- "@isCollection": true,
- },
- Resource2: {
- "@id": "http://www.w3.org/ns/iana/media-types/text/turtle#Resource",
- "@context": {
- type: {
- "@id": "@type",
- "@isCollection": true,
- },
- modified: {
- "@id": "http://purl.org/dc/terms/modified",
- "@type": "http://www.w3.org/2001/XMLSchema#string",
- },
- mtime: {
- "@id": "http://www.w3.org/ns/posix/stat#mtime",
- "@type": "http://www.w3.org/2001/XMLSchema#decimal",
- },
- size: {
- "@id": "http://www.w3.org/ns/posix/stat#size",
- "@type": "http://www.w3.org/2001/XMLSchema#integer",
- },
- },
- },
- mtime: {
- "@id": "http://www.w3.org/ns/posix/stat#mtime",
- "@type": "http://www.w3.org/2001/XMLSchema#decimal",
- },
- size: {
- "@id": "http://www.w3.org/ns/posix/stat#size",
- "@type": "http://www.w3.org/2001/XMLSchema#integer",
- },
- storage: {
- "@id": "http://www.w3.org/ns/pim/space#storage",
- "@type": "@id",
- "@isCollection": true,
- },
-};
diff --git a/packages/solid/src/.ldo/solid.schema.ts b/packages/solid/src/.ldo/solid.schema.ts
deleted file mode 100644
index 4d9adc0..0000000
--- a/packages/solid/src/.ldo/solid.schema.ts
+++ /dev/null
@@ -1,233 +0,0 @@
-import { Schema } from "shexj";
-
-/**
- * =============================================================================
- * solidSchema: ShexJ Schema for solid
- * =============================================================================
- */
-export const solidSchema: Schema = {
- type: "Schema",
- shapes: [
- {
- id: "http://www.w3.org/ns/lddps#Container",
- type: "ShapeDecl",
- shapeExpr: {
- type: "Shape",
- expression: {
- id: "http://www.w3.org/ns/lddps#ContainerShape",
- type: "EachOf",
- expressions: [
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
- valueExpr: {
- type: "NodeConstraint",
- values: [
- "http://www.w3.org/ns/ldp#Container",
- "http://www.w3.org/ns/ldp#Resource",
- ],
- },
- min: 0,
- max: -1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "A container on a Solid server",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://purl.org/dc/terms/modified",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#string",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "Date modified",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/ldp#contains",
- valueExpr: "http://www.w3.org/ns/lddps#Resource",
- min: 0,
- max: -1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "Defines a Solid Resource",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/posix/stat#mtime",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#decimal",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "?",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/posix/stat#size",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#integer",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "size of this container",
- },
- },
- ],
- },
- ],
- },
- extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
- },
- },
- {
- id: "http://www.w3.org/ns/lddps#Resource",
- type: "ShapeDecl",
- shapeExpr: {
- type: "Shape",
- expression: {
- id: "http://www.w3.org/ns/lddps#ResourceShape",
- type: "EachOf",
- expressions: [
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
- valueExpr: {
- type: "NodeConstraint",
- values: [
- "http://www.w3.org/ns/ldp#Resource",
- "http://www.w3.org/ns/iana/media-types/text/turtle#Resource",
- ],
- },
- min: 0,
- max: -1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "Any resource on a Solid server",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://purl.org/dc/terms/modified",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#string",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "Date modified",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/posix/stat#mtime",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#decimal",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "?",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/posix/stat#size",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#integer",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "size of this container",
- },
- },
- ],
- },
- ],
- },
- extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
- },
- },
- {
- id: "http://www.w3.org/ns/lddps#ProfileWithStorage",
- type: "ShapeDecl",
- shapeExpr: {
- type: "Shape",
- expression: {
- id: "http://www.w3.org/ns/lddps#ProfileWithStorageShape",
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/pim/space#storage",
- valueExpr: {
- type: "NodeConstraint",
- nodeKind: "iri",
- },
- min: 0,
- max: -1,
- },
- extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
- },
- },
- ],
-};
diff --git a/packages/solid/src/.ldo/solid.shapeTypes.ts b/packages/solid/src/.ldo/solid.shapeTypes.ts
deleted file mode 100644
index 69ddd90..0000000
--- a/packages/solid/src/.ldo/solid.shapeTypes.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import { ShapeType } from "@ldo/ldo";
-import { solidSchema } from "./solid.schema";
-import { solidContext } from "./solid.context";
-import { Container, Resource, ProfileWithStorage } from "./solid.typings";
-
-/**
- * =============================================================================
- * LDO ShapeTypes solid
- * =============================================================================
- */
-
-/**
- * Container ShapeType
- */
-export const ContainerShapeType: ShapeType = {
- schema: solidSchema,
- shape: "http://www.w3.org/ns/lddps#Container",
- context: solidContext,
-};
-
-/**
- * Resource ShapeType
- */
-export const ResourceShapeType: ShapeType = {
- schema: solidSchema,
- shape: "http://www.w3.org/ns/lddps#Resource",
- context: solidContext,
-};
-
-/**
- * ProfileWithStorage ShapeType
- */
-export const ProfileWithStorageShapeType: ShapeType = {
- schema: solidSchema,
- shape: "http://www.w3.org/ns/lddps#ProfileWithStorage",
- context: solidContext,
-};
diff --git a/packages/solid/src/.ldo/solid.typings.ts b/packages/solid/src/.ldo/solid.typings.ts
deleted file mode 100644
index 0405e75..0000000
--- a/packages/solid/src/.ldo/solid.typings.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { LdoJsonldContext, LdSet } from "@ldo/ldo";
-
-/**
- * =============================================================================
- * Typescript Typings for solid
- * =============================================================================
- */
-
-/**
- * Container Type
- */
-export interface Container {
- "@id"?: string;
- "@context"?: LdoJsonldContext;
- /**
- * A container on a Solid server
- */
- type?: LdSet<
- | {
- "@id": "Container";
- }
- | {
- "@id": "Resource";
- }
- >;
- /**
- * Date modified
- */
- modified?: string;
- /**
- * Defines a Solid Resource
- */
- contains?: LdSet;
- /**
- * ?
- */
- mtime?: number;
- /**
- * size of this container
- */
- size?: number;
-}
-
-/**
- * Resource Type
- */
-export interface Resource {
- "@id"?: string;
- "@context"?: LdoJsonldContext;
- /**
- * Any resource on a Solid server
- */
- type?: LdSet<
- | {
- "@id": "Resource";
- }
- | {
- "@id": "Resource2";
- }
- >;
- /**
- * Date modified
- */
- modified?: string;
- /**
- * ?
- */
- mtime?: number;
- /**
- * size of this container
- */
- size?: number;
-}
-
-/**
- * ProfileWithStorage Type
- */
-export interface ProfileWithStorage {
- "@id"?: string;
- "@context"?: LdoJsonldContext;
- storage?: LdSet<{
- "@id": string;
- }>;
-}
diff --git a/packages/solid/src/.ldo/wac.context.ts b/packages/solid/src/.ldo/wac.context.ts
deleted file mode 100644
index 6f6c9fd..0000000
--- a/packages/solid/src/.ldo/wac.context.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import { LdoJsonldContext } from "@ldo/ldo";
-
-/**
- * =============================================================================
- * wacContext: JSONLD Context for wac
- * =============================================================================
- */
-export const wacContext: LdoJsonldContext = {
- type: {
- "@id": "@type",
- },
- Authorization: {
- "@id": "http://www.w3.org/ns/auth/acl#Authorization",
- "@context": {
- type: {
- "@id": "@type",
- },
- accessTo: {
- "@id": "http://www.w3.org/ns/auth/acl#accessTo",
- "@type": "@id",
- },
- default: {
- "@id": "http://www.w3.org/ns/auth/acl#default",
- "@type": "@id",
- },
- agent: {
- "@id": "http://www.w3.org/ns/auth/acl#agent",
- "@type": "@id",
- "@isCollection": true,
- },
- agentGroup: {
- "@id": "http://www.w3.org/ns/auth/acl#agentGroup",
- "@type": "@id",
- "@isCollection": true,
- },
- agentClass: {
- "@id": "http://www.w3.org/ns/auth/acl#agentClass",
- "@isCollection": true,
- },
- mode: {
- "@id": "http://www.w3.org/ns/auth/acl#mode",
- "@isCollection": true,
- },
- },
- },
- accessTo: {
- "@id": "http://www.w3.org/ns/auth/acl#accessTo",
- "@type": "@id",
- },
- default: {
- "@id": "http://www.w3.org/ns/auth/acl#default",
- "@type": "@id",
- },
- agent: {
- "@id": "http://www.w3.org/ns/auth/acl#agent",
- "@type": "@id",
- "@isCollection": true,
- },
- agentGroup: {
- "@id": "http://www.w3.org/ns/auth/acl#agentGroup",
- "@type": "@id",
- "@isCollection": true,
- },
- agentClass: {
- "@id": "http://www.w3.org/ns/auth/acl#agentClass",
- "@isCollection": true,
- },
- AuthenticatedAgent: "http://www.w3.org/ns/auth/acl#AuthenticatedAgent",
- Agent: "http://xmlns.com/foaf/0.1/Agent",
- mode: {
- "@id": "http://www.w3.org/ns/auth/acl#mode",
- "@isCollection": true,
- },
- Read: "http://www.w3.org/ns/auth/acl#Read",
- Write: "http://www.w3.org/ns/auth/acl#Write",
- Append: "http://www.w3.org/ns/auth/acl#Append",
- Control: "http://www.w3.org/ns/auth/acl#Control",
-};
diff --git a/packages/solid/src/.ldo/wac.schema.ts b/packages/solid/src/.ldo/wac.schema.ts
deleted file mode 100644
index 2d54115..0000000
--- a/packages/solid/src/.ldo/wac.schema.ts
+++ /dev/null
@@ -1,169 +0,0 @@
-import { Schema } from "shexj";
-
-/**
- * =============================================================================
- * wacSchema: ShexJ Schema for wac
- * =============================================================================
- */
-export const wacSchema: Schema = {
- type: "Schema",
- shapes: [
- {
- id: "http://www.w3.org/ns/auth/acls#Authorization",
- type: "ShapeDecl",
- shapeExpr: {
- type: "Shape",
- expression: {
- id: "http://www.w3.org/ns/auth/acls#AuthorizationShape",
- type: "EachOf",
- expressions: [
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
- valueExpr: {
- type: "NodeConstraint",
- values: ["http://www.w3.org/ns/auth/acl#Authorization"],
- },
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "Denotes this as an acl:Authorization",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/auth/acl#accessTo",
- valueExpr: {
- type: "NodeConstraint",
- nodeKind: "iri",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "The subject of this authorization",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/auth/acl#default",
- valueExpr: {
- type: "NodeConstraint",
- nodeKind: "iri",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "The container subject of this authorization",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/auth/acl#agent",
- valueExpr: {
- type: "NodeConstraint",
- nodeKind: "iri",
- },
- min: 0,
- max: -1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value:
- "An agent is a person, social entity or software identified by a URI, e.g., a WebID denotes an agent",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/auth/acl#agentGroup",
- valueExpr: {
- type: "NodeConstraint",
- nodeKind: "iri",
- },
- min: 0,
- max: -1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value:
- "Denotes a group of agents being given the access permission",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/auth/acl#agentClass",
- valueExpr: {
- type: "NodeConstraint",
- values: [
- "http://www.w3.org/ns/auth/acl#AuthenticatedAgent",
- "http://xmlns.com/foaf/0.1/Agent",
- ],
- },
- min: 0,
- max: -1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value:
- "An agent class is a class of persons or entities identified by a URI.",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/ns/auth/acl#mode",
- valueExpr: {
- type: "NodeConstraint",
- values: [
- "http://www.w3.org/ns/auth/acl#Read",
- "http://www.w3.org/ns/auth/acl#Write",
- "http://www.w3.org/ns/auth/acl#Append",
- "http://www.w3.org/ns/auth/acl#Control",
- ],
- },
- min: 0,
- max: -1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value:
- "Denotes a class of operations that the agents can perform on a resource.",
- },
- },
- ],
- },
- ],
- },
- extra: ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
- },
- },
- ],
-};
diff --git a/packages/solid/src/.ldo/wac.shapeTypes.ts b/packages/solid/src/.ldo/wac.shapeTypes.ts
deleted file mode 100644
index 6689590..0000000
--- a/packages/solid/src/.ldo/wac.shapeTypes.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { ShapeType } from "@ldo/ldo";
-import { wacSchema } from "./wac.schema";
-import { wacContext } from "./wac.context";
-import { Authorization } from "./wac.typings";
-
-/**
- * =============================================================================
- * LDO ShapeTypes wac
- * =============================================================================
- */
-
-/**
- * Authorization ShapeType
- */
-export const AuthorizationShapeType: ShapeType = {
- schema: wacSchema,
- shape: "http://www.w3.org/ns/auth/acls#Authorization",
- context: wacContext,
-};
diff --git a/packages/solid/src/.ldo/wac.typings.ts b/packages/solid/src/.ldo/wac.typings.ts
deleted file mode 100644
index 40860e0..0000000
--- a/packages/solid/src/.ldo/wac.typings.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import { LdoJsonldContext, LdSet } from "@ldo/ldo";
-
-/**
- * =============================================================================
- * Typescript Typings for wac
- * =============================================================================
- */
-
-/**
- * Authorization Type
- */
-export interface Authorization {
- "@id"?: string;
- "@context"?: LdoJsonldContext;
- /**
- * Denotes this as an acl:Authorization
- */
- type: {
- "@id": "Authorization";
- };
- /**
- * The subject of this authorization
- */
- accessTo?: {
- "@id": string;
- };
- /**
- * The container subject of this authorization
- */
- default?: {
- "@id": string;
- };
- /**
- * An agent is a person, social entity or software identified by a URI, e.g., a WebID denotes an agent
- */
- agent?: LdSet<{
- "@id": string;
- }>;
- /**
- * Denotes a group of agents being given the access permission
- */
- agentGroup?: LdSet<{
- "@id": string;
- }>;
- /**
- * An agent class is a class of persons or entities identified by a URI.
- */
- agentClass?: LdSet<
- | {
- "@id": "AuthenticatedAgent";
- }
- | {
- "@id": "Agent";
- }
- >;
- /**
- * Denotes a class of operations that the agents can perform on a resource.
- */
- mode?: LdSet<
- | {
- "@id": "Read";
- }
- | {
- "@id": "Write";
- }
- | {
- "@id": "Append";
- }
- | {
- "@id": "Control";
- }
- >;
-}
diff --git a/packages/solid/src/.shapes/solid.shex b/packages/solid/src/.shapes/solid.shex
deleted file mode 100644
index f90f1b5..0000000
--- a/packages/solid/src/.shapes/solid.shex
+++ /dev/null
@@ -1,43 +0,0 @@
-PREFIX xsd:
-PREFIX rdf:
-PREFIX rdfs:
-PREFIX ldp:
-PREFIX ldps:
-PREFIX dct:
-PREFIX stat:
-PREFIX tur:
-PREFIX pim:
-
-ldps:Container EXTRA a {
- $ldps:ContainerShape (
- a [ ldp:Container ldp:Resource ]*
- // rdfs:comment "A container on a Solid server";
- dct:modified xsd:string?
- // rdfs:comment "Date modified";
- ldp:contains @ldps:Resource*
- // rdfs:comment "Defines a Solid Resource";
- stat:mtime xsd:decimal?
- // rdfs:comment "?";
- stat:size xsd:integer?
- // rdfs:comment "size of this container";
- )
-}
-
-ldps:Resource EXTRA a {
- $ldps:ResourceShape (
- a [ ldp:Resource tur:Resource ]*
- // rdfs:comment "Any resource on a Solid server";
- dct:modified xsd:string?
- // rdfs:comment "Date modified";
- stat:mtime xsd:decimal?
- // rdfs:comment "?";
- stat:size xsd:integer?
- // rdfs:comment "size of this container";
- )
-}
-
-ldps:ProfileWithStorage EXTRA a {
- $ldps:ProfileWithStorageShape (
- pim:storage IRI *;
- )
-}
diff --git a/packages/solid/src/.shapes/wac.shex b/packages/solid/src/.shapes/wac.shex
deleted file mode 100644
index 5ff19cd..0000000
--- a/packages/solid/src/.shapes/wac.shex
+++ /dev/null
@@ -1,23 +0,0 @@
-PREFIX acl:
-PREFIX acls:
-PREFIX foaf:
-PREFIX rdfs:
-
-acls:Authorization EXTRA a {
- $acls:AuthorizationShape (
- a [ acl:Authorization ]
- // rdfs:comment "Denotes this as an acl:Authorization";
- acl:accessTo IRI?
- // rdfs:comment "The subject of this authorization";
- acl:default IRI?
- // rdfs:comment "The container subject of this authorization";
- acl:agent IRI*
- // rdfs:comment "An agent is a person, social entity or software identified by a URI, e.g., a WebID denotes an agent";
- acl:agentGroup IRI*
- // rdfs:comment "Denotes a group of agents being given the access permission";
- acl:agentClass [ acl:AuthenticatedAgent foaf:Agent ]*
- // rdfs:comment "An agent class is a class of persons or entities identified by a URI.";
- acl:mode [ acl:Read acl:Write acl:Append acl:Control ]*
- // rdfs:comment "Denotes a class of operations that the agents can perform on a resource.";
- )
-}
diff --git a/packages/solid/src/ResourceStore.ts b/packages/solid/src/ResourceStore.ts
deleted file mode 100644
index 5ecbafe..0000000
--- a/packages/solid/src/ResourceStore.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import { Container } from "./resource/Container";
-import { Leaf } from "./resource/Leaf";
-import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext";
-import type { ContainerUri, LeafUri } from "./util/uriTypes";
-import { isContainerUri } from "./util/uriTypes";
-
-/**
- * Options for getting a resource
- */
-export interface ResourceGetterOptions {
- /**
- * If autoLoad is set to true and the resource is unfetched, `read` will be called.
- *
- * @default false
- */
- autoLoad?: boolean;
-}
-
-/**
- * @internal
- * A store of Solid resources
- */
-export class ResourceStore {
- /**
- * @internal
- *
- * A mapping between a resource URI and a Solid resource
- */
- protected resourceMap: Map;
- /**
- * @internal
- *
- * Context about the SolidLdoDataset
- */
- protected context: SolidLdoDatasetContext;
-
- /**
- * @param context - A SolidLdoDatasetContext of the parent SolidLdoDataset
- */
- constructor(context: SolidLdoDatasetContext) {
- this.resourceMap = new Map();
- this.context = context;
- }
-
- /**
- * Gets a resource representation
- *
- * @param uri - The URI of the resource
- * @param options - ResourceGetterOptions
- *
- * @returns The resource representation
- */
- get(uri: ContainerUri, options?: ResourceGetterOptions): Container;
- get(uri: LeafUri, options?: ResourceGetterOptions): Leaf;
- get(uri: string, options?: ResourceGetterOptions): Leaf | Container;
- get(uri: string, options?: ResourceGetterOptions): Leaf | Container {
- // Normalize URI by removing hash
- const url = new URL(uri);
- url.hash = "";
- const normalizedUri = url.toString();
-
- // Get the document and return if exists
- let resource = this.resourceMap.get(normalizedUri);
- if (!resource) {
- if (isContainerUri(normalizedUri)) {
- resource = new Container(normalizedUri, this.context);
- } else {
- resource = new Leaf(normalizedUri as LeafUri, this.context);
- }
- this.resourceMap.set(normalizedUri, resource);
- }
-
- if (options?.autoLoad) {
- resource.read();
- }
-
- return resource;
- }
-}
diff --git a/packages/solid/src/SolidLdoDataset.ts b/packages/solid/src/SolidLdoDataset.ts
deleted file mode 100644
index dc16d09..0000000
--- a/packages/solid/src/SolidLdoDataset.ts
+++ /dev/null
@@ -1,169 +0,0 @@
-import type { LdoBase, ShapeType } from "@ldo/ldo";
-import { LdoDataset, startTransaction } from "@ldo/ldo";
-import type { Dataset, DatasetFactory, Quad } from "@rdfjs/types";
-import type { Container } from "./resource/Container";
-import type { Leaf } from "./resource/Leaf";
-import type { ResourceGetterOptions } from "./ResourceStore";
-import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext";
-import type { ContainerUri, LeafUri } from "./util/uriTypes";
-import { SolidLdoTransactionDataset } from "./SolidLdoTransactionDataset";
-import type { ITransactionDatasetFactory } from "@ldo/subscribable-dataset";
-import type { SubjectNode } from "@ldo/rdf-utils";
-import type { Resource } from "./resource/Resource";
-import type { CheckRootResultError } from "./requester/requests/checkRootContainer";
-import type { NoRootContainerError } from "./requester/results/error/NoRootContainerError";
-import type { ReadResultError } from "./requester/requests/readResource";
-import { ProfileWithStorageShapeType } from "./.ldo/solid.shapeTypes";
-import type { GetStorageContainerFromWebIdSuccess } from "./requester/results/success/CheckRootContainerSuccess";
-import type { ISolidLdoDataset } from "./types";
-
-/**
- * A SolidLdoDataset has all the functionality of an LdoDataset with the added
- * functionality of keeping track of fetched Solid Resources.
- *
- * It is recommended to use the { @link createSolidLdoDataset } to initialize
- * this class
- *
- * @example
- * ```typescript
- * import { createSolidLdoDataset } from "@ldo/solid";
- * import { ProfileShapeType } from "./.ldo/profile.shapeTypes.ts"
- *
- * // ...
- *
- * const solidLdoDataset = createSolidLdoDataset();
- *
- * const profileDocument = solidLdoDataset
- * .getResource("https://example.com/profile");
- * await profileDocument.read();
- *
- * const profile = solidLdoDataset
- * .using(ProfileShapeType)
- * .fromSubject("https://example.com/profile#me");
- * ```
- */
-export class SolidLdoDataset extends LdoDataset implements ISolidLdoDataset {
- /**
- * @internal
- */
- public context: SolidLdoDatasetContext;
-
- /**
- * @param context - SolidLdoDatasetContext
- * @param datasetFactory - An optional dataset factory
- * @param transactionDatasetFactory - A factory for creating transaction datasets
- * @param initialDataset - A set of triples to initialize this dataset
- */
- constructor(
- context: SolidLdoDatasetContext,
- datasetFactory: DatasetFactory,
- transactionDatasetFactory: ITransactionDatasetFactory,
- initialDataset?: Dataset,
- ) {
- super(datasetFactory, transactionDatasetFactory, initialDataset);
- this.context = context;
- }
-
- /**
- * Retireves a representation (either a LeafResource or a ContainerResource)
- * of a Solid Resource at the given URI. This resource represents the
- * current state of the resource: whether it is currently fetched or in the
- * process of fetching as well as some information about it.
- *
- * @param uri - the URI of the resource
- * @param options - Special options for getting the resource
- *
- * @returns a Leaf or Container Resource
- *
- * @example
- * ```typescript
- * const profileDocument = solidLdoDataset
- * .getResource("https://example.com/profile");
- * ```
- */
- getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container;
- getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf;
- getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container {
- return this.context.resourceStore.get(uri, options);
- }
-
- public startTransaction(): SolidLdoTransactionDataset {
- return new SolidLdoTransactionDataset(
- this,
- this.context,
- this.datasetFactory,
- this.transactionDatasetFactory,
- );
- }
-
- /**
- * Shorthand for solidLdoDataset
- * .usingType(shapeType)
- * .write(...resources.map((r) => r.uri))
- * .fromSubject(subject);
- * @param shapeType - The shapetype to represent the data
- * @param subject - A subject URI
- * @param resources - The resources changes to should written to
- */
- createData(
- shapeType: ShapeType,
- subject: string | SubjectNode,
- resource: Resource,
- ...additionalResources: Resource[]
- ): Type {
- const resources = [resource, ...additionalResources];
- const linkedDataObject = this.usingType(shapeType)
- .write(...resources.map((r) => r.uri))
- .fromSubject(subject);
- startTransaction(linkedDataObject);
- return linkedDataObject;
- }
-
- /**
- * Gets a list of root storage containers for a user given their WebId
- * @param webId: The webId for the user
- * @returns A list of storages if successful, an error if not
- * @example
- * ```typescript
- * const result = await solidLdoDataset
- * .getStorageFromWebId("https://example.com/profile/card#me");
- * if (result.isError) {
- * // Do something
- * }
- * console.log(result.storageContainer[0].uri);
- * ```
- */
- async getStorageFromWebId(
- webId: LeafUri,
- ): Promise<
- | GetStorageContainerFromWebIdSuccess
- | CheckRootResultError
- | ReadResultError
- | NoRootContainerError
- > {
- const webIdResource = this.getResource(webId);
- const readResult = await webIdResource.readIfUnfetched();
- if (readResult.isError) return readResult;
- const profile = this.usingType(ProfileWithStorageShapeType).fromSubject(
- webId,
- );
- if (profile.storage && profile.storage.size > 0) {
- const containers = profile.storage.map((storageNode) =>
- this.getResource(storageNode["@id"] as ContainerUri),
- );
- return {
- type: "getStorageContainerFromWebIdSuccess",
- isError: false,
- storageContainers: containers,
- };
- }
- const getContainerResult = await webIdResource.getRootContainer();
- if (getContainerResult.type === "container")
- return {
- type: "getStorageContainerFromWebIdSuccess",
- isError: false,
- storageContainers: [getContainerResult],
- };
- return getContainerResult;
- }
-}
diff --git a/packages/solid/src/SolidLdoDatasetContext.ts b/packages/solid/src/SolidLdoDatasetContext.ts
deleted file mode 100644
index c78b50b..0000000
--- a/packages/solid/src/SolidLdoDatasetContext.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type { ResourceStore } from "./ResourceStore";
-import type { SolidLdoDataset } from "./SolidLdoDataset";
-
-/**
- * Context to be shared between aspects of a SolidLdoDataset
- */
-export interface SolidLdoDatasetContext {
- /**
- * A pointer to the parent SolidLdoDataset
- */
- solidLdoDataset: SolidLdoDataset;
- /**
- * The resource store of the SolidLdoDataset
- */
- resourceStore: ResourceStore;
- /**
- * Http fetch function
- */
- fetch: typeof fetch;
-}
diff --git a/packages/solid/src/SolidLdoTransactionDataset.ts b/packages/solid/src/SolidLdoTransactionDataset.ts
deleted file mode 100644
index 4a2306e..0000000
--- a/packages/solid/src/SolidLdoTransactionDataset.ts
+++ /dev/null
@@ -1,186 +0,0 @@
-import { LdoTransactionDataset } from "@ldo/ldo";
-import type { ISolidLdoDataset } from "./types";
-import type { ResourceGetterOptions } from "./ResourceStore";
-import type { Container } from "./resource/Container";
-import type { Leaf } from "./resource/Leaf";
-import {
- isContainerUri,
- type ContainerUri,
- type LeafUri,
-} from "./util/uriTypes";
-import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext";
-import type { DatasetFactory, Quad } from "@rdfjs/types";
-import {
- updateDatasetInBulk,
- type ITransactionDatasetFactory,
-} from "@ldo/subscribable-dataset";
-import type { AggregateSuccess } from "./requester/results/success/SuccessResult";
-import type { ResourceResult } from "./resource/resourceResult/ResourceResult";
-import type {
- IgnoredInvalidUpdateSuccess,
- UpdateDefaultGraphSuccess,
- UpdateSuccess,
-} from "./requester/results/success/UpdateSuccess";
-import { AggregateError } from "./requester/results/error/ErrorResult";
-import type {
- UpdateResult,
- UpdateResultError,
-} from "./requester/requests/updateDataResource";
-import type { DatasetChanges, GraphNode } from "@ldo/rdf-utils";
-import { splitChangesByGraph } from "./util/splitChangesByGraph";
-
-/**
- * A SolidLdoTransactionDataset has all the functionality of a SolidLdoDataset
- * and represents a transaction to the parent SolidLdoDataset.
- *
- * It is recommended to use the `startTransaction` method on a SolidLdoDataset
- * to initialize this class
- *
- * @example
- * ```typescript
- * import { createSolidLdoDataset } from "@ldo/solid";
- * import { ProfileShapeType } from "./.ldo/profile.shapeTypes.ts"
- *
- * // ...
- *
- * const solidLdoDataset = createSolidLdoDataset();
- *
- * const profileDocument = solidLdoDataset
- * .getResource("https://example.com/profile");
- * await profileDocument.read();
- *
- * const transaction = solidLdoDataset.startTransaction();
- *
- * const profile = transaction
- * .using(ProfileShapeType)
- * .fromSubject("https://example.com/profile#me");
- * profile.name = "Some Name";
- * await transaction.commitToPod();
- * ```
- */
-export class SolidLdoTransactionDataset
- extends LdoTransactionDataset
- implements ISolidLdoDataset
-{
- /**
- * @internal
- */
- public context: SolidLdoDatasetContext;
-
- /**
- * @param context - SolidLdoDatasetContext
- * @param datasetFactory - An optional dataset factory
- * @param transactionDatasetFactory - A factory for creating transaction datasets
- * @param initialDataset - A set of triples to initialize this dataset
- */
- constructor(
- parentDataset: ISolidLdoDataset,
- context: SolidLdoDatasetContext,
- datasetFactory: DatasetFactory,
- transactionDatasetFactory: ITransactionDatasetFactory,
- ) {
- super(parentDataset, datasetFactory, transactionDatasetFactory);
- this.context = context;
- }
-
- /**
- * Retireves a representation (either a LeafResource or a ContainerResource)
- * of a Solid Resource at the given URI. This resource represents the
- * current state of the resource: whether it is currently fetched or in the
- * process of fetching as well as some information about it.
- *
- * @param uri - the URI of the resource
- * @param options - Special options for getting the resource
- *
- * @returns a Leaf or Container Resource
- *
- * @example
- * ```typescript
- * const profileDocument = solidLdoDataset
- * .getResource("https://example.com/profile");
- * ```
- */
- getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container;
- getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf;
- getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container;
- getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container {
- return this.context.resourceStore.get(uri, options);
- }
-
- public startTransaction(): SolidLdoTransactionDataset {
- return new SolidLdoTransactionDataset(
- this,
- this.context,
- this.datasetFactory,
- this.transactionDatasetFactory,
- );
- }
-
- async commitToPod(): Promise<
- | AggregateSuccess<
- ResourceResult
- >
- | AggregateError
- > {
- const changes = this.getChanges();
- const changesByGraph = splitChangesByGraph(changes);
-
- // Iterate through all changes by graph in
- const results: [
- GraphNode,
- DatasetChanges,
- UpdateResult | IgnoredInvalidUpdateSuccess | UpdateDefaultGraphSuccess,
- ][] = await Promise.all(
- Array.from(changesByGraph.entries()).map(
- async ([graph, datasetChanges]) => {
- if (graph.termType === "DefaultGraph") {
- // Undefined means that this is the default graph
- updateDatasetInBulk(this.parentDataset, datasetChanges);
- return [
- graph,
- datasetChanges,
- {
- type: "updateDefaultGraphSuccess",
- isError: false,
- } as UpdateDefaultGraphSuccess,
- ];
- }
- if (isContainerUri(graph.value)) {
- return [
- graph,
- datasetChanges,
- {
- type: "ignoredInvalidUpdateSuccess",
- isError: false,
- } as IgnoredInvalidUpdateSuccess,
- ];
- }
- const resource = this.getResource(graph.value as LeafUri);
- const updateResult = await resource.update(datasetChanges);
- return [graph, datasetChanges, updateResult];
- },
- ),
- );
-
- // If one has errored, return error
- const errors = results.filter((result) => result[2].isError);
-
- if (errors.length > 0) {
- return new AggregateError(
- errors.map((result) => result[2] as UpdateResultError),
- );
- }
- return {
- isError: false,
- type: "aggregateSuccess",
- results: results
- .map((result) => result[2])
- .filter(
- (result): result is ResourceResult =>
- result.type === "updateSuccess" ||
- result.type === "updateDefaultGraphSuccess" ||
- result.type === "ignoredInvalidUpdateSuccess",
- ),
- };
- }
-}
diff --git a/packages/solid/src/createSolidLdoDataset.ts b/packages/solid/src/createSolidLdoDataset.ts
deleted file mode 100644
index dfafe85..0000000
--- a/packages/solid/src/createSolidLdoDataset.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import type { Dataset, DatasetFactory } from "@rdfjs/types";
-import { SolidLdoDataset } from "./SolidLdoDataset";
-
-import type { SolidLdoDatasetContext } from "./SolidLdoDatasetContext";
-import { createDataset, createDatasetFactory } from "@ldo/dataset";
-import { ResourceStore } from "./ResourceStore";
-import { guaranteeFetch } from "./util/guaranteeFetch";
-import { createTransactionDatasetFactory } from "@ldo/subscribable-dataset";
-
-/**
- * Options for createSolidDataset
- */
-export interface CreateSolidLdoDatasetOptions {
- /**
- * A fetch function. Most often, this is the fetch function from @inrupt/solid-clieht-authn-js
- */
- fetch?: typeof fetch;
- /**
- * An initial dataset
- * @default A blank dataset
- */
- dataset?: Dataset;
- /**
- * An RDFJS DatasetFactory
- * @default An extended RDFJS DatasetFactory
- */
- datasetFactory?: DatasetFactory;
-}
-
-/**
- * Creates a SolidLdoDataset
- *
- * @param options - CreateSolidLdoDatasetOptions
- * @returns A SolidLdoDataset
- *
- * @example
- * ```typescript
- * import { createSolidLdoDataset } from "@ldo/solid";
- * import { fetch } from "@inrupt/solid-client-authn-browswer";
- *
- * const solidLdoDataset = createSolidLdoDataset({ fetch });
- * ```
- */
-export function createSolidLdoDataset(
- options?: CreateSolidLdoDatasetOptions,
-): SolidLdoDataset {
- const finalFetch = guaranteeFetch(options?.fetch);
- const finalDatasetFactory = options?.datasetFactory || createDatasetFactory();
- const finalDataset = options?.dataset || createDataset();
-
- // Ignoring because of circular dependency
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- const context: SolidLdoDatasetContext = {
- fetch: finalFetch,
- };
- const solidLdoDataset = new SolidLdoDataset(
- context,
- finalDatasetFactory,
- createTransactionDatasetFactory(),
- finalDataset,
- );
- const resourceStore = new ResourceStore(context);
- context.solidLdoDataset = solidLdoDataset;
- context.resourceStore = resourceStore;
-
- return solidLdoDataset;
-}
diff --git a/packages/solid/src/index.ts b/packages/solid/src/index.ts
deleted file mode 100644
index 41ff71c..0000000
--- a/packages/solid/src/index.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-export * from "./createSolidLdoDataset";
-export * from "./SolidLdoDataset";
-export * from "./SolidLdoDatasetContext";
-export * from "./SolidLdoTransactionDataset";
-
-export * from "./resource/Resource";
-export * from "./resource/Container";
-export * from "./resource/Leaf";
-
-export * from "./util/uriTypes";
-
-export * from "./methods";
-
-export * from "./requester/requests/checkRootContainer";
-export * from "./requester/requests/createDataResource";
-export * from "./requester/requests/deleteResource";
-export * from "./requester/requests/readResource";
-export * from "./requester/requests/requestOptions";
-export * from "./requester/requests/updateDataResource";
-export * from "./requester/requests/uploadResource";
-
-export * from "./resource/wac/WacRule";
-export * from "./resource/wac/getWacRule";
-export * from "./resource/wac/getWacUri";
-export * from "./resource/wac/setWacRule";
-export * from "./resource/wac/results/GetWacRuleSuccess";
-export * from "./resource/wac/results/GetWacUriSuccess";
-export * from "./resource/wac/results/SetWacRuleSuccess";
-export * from "./resource/wac/results/WacRuleAbsent";
-
-export * from "./types";
diff --git a/packages/solid/src/methods.ts b/packages/solid/src/methods.ts
deleted file mode 100644
index 5fb36a7..0000000
--- a/packages/solid/src/methods.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { startTransaction, type LdoBase, write, getDataset } from "@ldo/ldo";
-import type { Resource } from "./resource/Resource";
-import type { Quad } from "@rdfjs/types";
-import { _proxyContext, getProxyFromObject } from "@ldo/jsonld-dataset-proxy";
-import type { SubscribableDataset } from "@ldo/subscribable-dataset";
-import type { SolidLdoTransactionDataset } from "./SolidLdoTransactionDataset";
-
-/**
- * Begins tracking changes to eventually commit.
- *
- * @param input - A linked data object to track changes on
- * @param resource - A resource that all additions will eventually be committed to
- * @param additionalResources - Any additional resources that changes will eventually be committed to
- *
- * @returns A transactable Linked Data Object
- *
- * @example
- * ```typescript
- * import { changeData } from "@ldo/solid";
- *
- * // ...
- *
- * const profile = solidLdoDataset
- * .using(ProfileShapeType)
- * .fromSubject("https://example.com/profile#me");
- * const resource = solidLdoDataset.getResource("https://example.com/profile");
- *
- * const cProfile = changeData(profile, resource);
- * cProfile.name = "My New Name";
- * const result = await commitData(cProfile);
- * ```
- */
-export function changeData(
- input: Type,
- resource: Resource,
- ...additionalResources: Resource[]
-): Type {
- const resources = [resource, ...additionalResources];
- // Clone the input and set a graph
- const [transactionLdo] = write(...resources.map((r) => r.uri)).usingCopy(
- input,
- );
- // Start a transaction with the input
- startTransaction(transactionLdo);
- // Return
- return transactionLdo;
-}
-
-/**
- * Commits the transaction to the global dataset, syncing all subscribing
- * components and Solid Pods
- *
- * @param input - A transactable linked data object
- *
- * @example
- * ```typescript
- * import { changeData } from "@ldo/solid";
- *
- * // ...
- *
- * const profile = solidLdoDataset
- * .using(ProfileShapeType)
- * .fromSubject("https://example.com/profile#me");
- * const resource = solidLdoDataset.getResource("https://example.com/profile");
- *
- * const cProfile = changeData(profile, resource);
- * cProfile.name = "My New Name";
- * const result = await commitData(cProfile);
- * ```
- */
-export async function commitData(
- input: LdoBase,
-): ReturnType {
- const transactionDataset = getDataset(input) as SolidLdoTransactionDataset;
- const result = await transactionDataset.commitToPod();
- if (result.isError) return result;
- // Take the LdoProxy out of commit mode. This uses hidden methods of JSONLD-DATASET-PROXY
- const proxy = getProxyFromObject(input);
- proxy[_proxyContext] = proxy[_proxyContext].duplicate({
- dataset: proxy[_proxyContext].state
- .parentDataset as SubscribableDataset,
- });
- return result;
-}
diff --git a/packages/solid/src/requester/BatchedRequester.ts b/packages/solid/src/requester/BatchedRequester.ts
deleted file mode 100644
index 7c0b5a8..0000000
--- a/packages/solid/src/requester/BatchedRequester.ts
+++ /dev/null
@@ -1,190 +0,0 @@
-import { ANY_KEY, RequestBatcher } from "../util/RequestBatcher";
-import type { SolidLdoDatasetContext } from "../SolidLdoDatasetContext";
-import type {
- ContainerCreateAndOverwriteResult,
- ContainerCreateIfAbsentResult,
- LeafCreateAndOverwriteResult,
- LeafCreateIfAbsentResult,
-} from "./requests/createDataResource";
-import { createDataResource } from "./requests/createDataResource";
-import type {
- ReadContainerResult,
- ReadLeafResult,
-} from "./requests/readResource";
-import { readResource } from "./requests/readResource";
-import type { DeleteResult } from "./requests/deleteResource";
-import { deleteResource } from "./requests/deleteResource";
-import { modifyQueueByMergingEventsWithTheSameKeys } from "./util/modifyQueueFuntions";
-
-const READ_KEY = "read";
-const CREATE_KEY = "createDataResource";
-const DELETE_KEY = "delete";
-
-/**
- * @internal
- *
- * A singleton for handling batched requests
- */
-export abstract class BatchedRequester {
- /**
- * @internal
- * A request batcher to maintain state for ongoing requests
- */
- protected readonly requestBatcher = new RequestBatcher();
-
- /**
- * The uri of the resource
- */
- abstract readonly uri: string;
-
- /**
- * @internal
- * SolidLdoDatasetContext for the parent SolidLdoDataset
- */
- protected context: SolidLdoDatasetContext;
-
- /**
- * @param context - SolidLdoDatasetContext for the parent SolidLdoDataset
- */
- constructor(context: SolidLdoDatasetContext) {
- this.context = context;
- }
-
- /**
- * Checks if the resource is currently making any request
- * @returns true if the resource is making any requests
- */
- isLoading(): boolean {
- return this.requestBatcher.isLoading(ANY_KEY);
- }
-
- /**
- * Checks if the resource is currently executing a create request
- * @returns true if the resource is currently executing a create request
- */
- isCreating(): boolean {
- return this.requestBatcher.isLoading(CREATE_KEY);
- }
-
- /**
- * Checks if the resource is currently executing a read request
- * @returns true if the resource is currently executing a read request
- */
- isReading(): boolean {
- return this.requestBatcher.isLoading(READ_KEY);
- }
-
- /**
- * Checks if the resource is currently executing a delete request
- * @returns true if the resource is currently executing a delete request
- */
- isDeletinng(): boolean {
- return this.requestBatcher.isLoading(DELETE_KEY);
- }
-
- /**
- * Read this resource.
- * @returns A ReadLeafResult or a ReadContainerResult depending on the uri of
- * this resource
- */
- async read(): Promise {
- const transaction = this.context.solidLdoDataset.startTransaction();
- const result = await this.requestBatcher.queueProcess({
- name: READ_KEY,
- args: [this.uri, { dataset: transaction, fetch: this.context.fetch }],
- perform: readResource,
- modifyQueue: modifyQueueByMergingEventsWithTheSameKeys(READ_KEY),
- after: (result) => {
- if (!result.isError) {
- transaction.commit();
- }
- },
- });
- return result;
- }
-
- /**
- * Delete this resource
- * @returns A DeleteResult
- */
- async delete(): Promise {
- const transaction = this.context.solidLdoDataset.startTransaction();
- const result = await this.requestBatcher.queueProcess({
- name: DELETE_KEY,
- args: [this.uri, { dataset: transaction, fetch: this.context.fetch }],
- perform: deleteResource,
- modifyQueue: modifyQueueByMergingEventsWithTheSameKeys(DELETE_KEY),
- after: (result) => {
- if (!result.isError) {
- transaction.commit();
- }
- },
- });
- return result;
- }
-
- /**
- * Creates a Resource
- * @param overwrite - If true, this will orverwrite the resource if it already
- * exists
- * @returns A ContainerCreateAndOverwriteResult or a
- * LeafCreateAndOverwriteResult depending on this resource's URI
- */
- createDataResource(
- overwrite: true,
- ): Promise;
- createDataResource(
- overwrite?: false,
- ): Promise;
- createDataResource(
- overwrite?: boolean,
- ): Promise<
- | ContainerCreateAndOverwriteResult
- | LeafCreateAndOverwriteResult
- | ContainerCreateIfAbsentResult
- | LeafCreateIfAbsentResult
- >;
- async createDataResource(
- overwrite?: boolean,
- ): Promise<
- | ContainerCreateAndOverwriteResult
- | LeafCreateAndOverwriteResult
- | ContainerCreateIfAbsentResult
- | LeafCreateIfAbsentResult
- > {
- const transaction = this.context.solidLdoDataset.startTransaction();
- const result = await this.requestBatcher.queueProcess({
- name: CREATE_KEY,
- args: [
- this.uri,
- overwrite,
- { dataset: transaction, fetch: this.context.fetch },
- ],
- perform: createDataResource,
- modifyQueue: (queue, currentlyLoading, args) => {
- const lastElementInQueue = queue[queue.length - 1];
- if (
- lastElementInQueue &&
- lastElementInQueue.name === CREATE_KEY &&
- !!lastElementInQueue.args[1] === !!args[1]
- ) {
- return lastElementInQueue;
- }
- if (
- currentlyLoading &&
- currentlyLoading.name === CREATE_KEY &&
- !!currentlyLoading.args[1] === !!args[1]
- ) {
- return currentlyLoading;
- }
- return undefined;
- },
- after: (result) => {
- if (!result.isError) {
- transaction.commit();
- }
- },
- });
- return result;
- }
-}
diff --git a/packages/solid/src/requester/ContainerBatchedRequester.ts b/packages/solid/src/requester/ContainerBatchedRequester.ts
deleted file mode 100644
index 42d744b..0000000
--- a/packages/solid/src/requester/ContainerBatchedRequester.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import type { SolidLdoDatasetContext } from "../SolidLdoDatasetContext";
-import type { ContainerUri } from "../util/uriTypes";
-import { BatchedRequester } from "./BatchedRequester";
-import type { CheckRootResult } from "./requests/checkRootContainer";
-import { checkRootContainer } from "./requests/checkRootContainer";
-import type {
- ContainerCreateAndOverwriteResult,
- ContainerCreateIfAbsentResult,
-} from "./requests/createDataResource";
-import type { ReadContainerResult } from "./requests/readResource";
-import { modifyQueueByMergingEventsWithTheSameKeys } from "./util/modifyQueueFuntions";
-
-export const IS_ROOT_CONTAINER_KEY = "isRootContainer";
-
-/**
- * @internal
- *
- * A singleton to handle batched requests for containers
- */
-export class ContainerBatchedRequester extends BatchedRequester {
- /**
- * The URI of the container
- */
- readonly uri: ContainerUri;
-
- /**
- * @param uri - The URI of the container
- * @param context - SolidLdoDatasetContext of the parent dataset
- */
- constructor(uri: ContainerUri, context: SolidLdoDatasetContext) {
- super(context);
- this.uri = uri;
- }
-
- /**
- * Reads the container
- * @returns A ReadContainerResult
- */
- read(): Promise {
- return super.read() as Promise;
- }
-
- /**
- * Creates the container
- * @param overwrite - If true, this will orverwrite the resource if it already
- * exists
- */
- createDataResource(
- overwrite: true,
- ): Promise;
- createDataResource(overwrite?: false): Promise;
- createDataResource(
- overwrite?: boolean,
- ): Promise;
- createDataResource(
- overwrite?: boolean,
- ): Promise<
- ContainerCreateIfAbsentResult | ContainerCreateAndOverwriteResult
- > {
- return super.createDataResource(overwrite) as Promise<
- ContainerCreateIfAbsentResult | ContainerCreateAndOverwriteResult
- >;
- }
-
- /**
- * Checks to see if this container is a root container
- * @returns A CheckRootResult
- */
- async isRootContainer(): Promise {
- return this.requestBatcher.queueProcess({
- name: IS_ROOT_CONTAINER_KEY,
- args: [this.uri as ContainerUri, { fetch: this.context.fetch }],
- perform: checkRootContainer,
- modifyQueue: modifyQueueByMergingEventsWithTheSameKeys(
- IS_ROOT_CONTAINER_KEY,
- ),
- });
- }
-}
diff --git a/packages/solid/src/requester/LeafBatchedRequester.ts b/packages/solid/src/requester/LeafBatchedRequester.ts
deleted file mode 100644
index c40b63a..0000000
--- a/packages/solid/src/requester/LeafBatchedRequester.ts
+++ /dev/null
@@ -1,172 +0,0 @@
-import type { DatasetChanges } from "@ldo/rdf-utils";
-import { mergeDatasetChanges } from "@ldo/subscribable-dataset";
-import type { Quad } from "@rdfjs/types";
-import type { SolidLdoDatasetContext } from "../SolidLdoDatasetContext";
-import type { LeafUri } from "../util/uriTypes";
-import { BatchedRequester } from "./BatchedRequester";
-import type {
- LeafCreateAndOverwriteResult,
- LeafCreateIfAbsentResult,
-} from "./requests/createDataResource";
-import type { ReadLeafResult } from "./requests/readResource";
-import type { UpdateResult } from "./requests/updateDataResource";
-import { updateDataResource } from "./requests/updateDataResource";
-import { uploadResource } from "./requests/uploadResource";
-
-export const UPDATE_KEY = "update";
-export const UPLOAD_KEY = "upload";
-
-/**
- * @internal
- *
- * A singleton to handle batched requests for leafs
- */
-export class LeafBatchedRequester extends BatchedRequester {
- /**
- * The URI of the leaf
- */
- readonly uri: LeafUri;
-
- /**
- * @param uri - the URI of the leaf
- * @param context - SolidLdoDatasetContext of the parent dataset
- */
- constructor(uri: LeafUri, context: SolidLdoDatasetContext) {
- super(context);
- this.uri = uri;
- }
-
- /**
- * Checks if the resource is currently executing an update request
- * @returns true if the resource is currently executing an update request
- */
- isUpdating(): boolean {
- return this.requestBatcher.isLoading(UPDATE_KEY);
- }
-
- /**
- * Checks if the resource is currently executing an upload request
- * @returns true if the resource is currently executing an upload request
- */
- isUploading(): boolean {
- return this.requestBatcher.isLoading(UPLOAD_KEY);
- }
-
- /**
- * Reads the leaf
- * @returns A ReadLeafResult
- */
- async read(): Promise {
- return super.read() as Promise;
- }
-
- /**
- * Creates the leaf as a data resource
- * @param overwrite - If true, this will orverwrite the resource if it already
- * exists
- */
- createDataResource(overwrite: true): Promise;
- createDataResource(overwrite?: false): Promise;
- createDataResource(
- overwrite?: boolean,
- ): Promise;
- createDataResource(
- overwrite?: boolean,
- ): Promise {
- return super.createDataResource(overwrite) as Promise<
- LeafCreateIfAbsentResult | LeafCreateAndOverwriteResult
- >;
- }
-
- /**
- * Update the data on this resource
- * @param changes - DatasetChanges that should be applied to the Pod
- */
- async updateDataResource(
- changes: DatasetChanges,
- ): Promise {
- const result = await this.requestBatcher.queueProcess({
- name: UPDATE_KEY,
- args: [
- this.uri,
- changes,
- { fetch: this.context.fetch, dataset: this.context.solidLdoDataset },
- ],
- perform: updateDataResource,
- modifyQueue: (queue, currentlyProcessing, [, changes]) => {
- if (queue[queue.length - 1]?.name === UPDATE_KEY) {
- // Merge Changes
- const originalChanges = queue[queue.length - 1].args[1];
- mergeDatasetChanges(originalChanges, changes);
- return queue[queue.length - 1];
- }
- return undefined;
- },
- });
- return result;
- }
-
- /**
- * Upload a binary at this resource's URI
- * @param blob - A binary blob
- * @param mimeType - the mime type of the blob
- * @param overwrite: If true, will overwrite an existing file
- */
- upload(
- blob: Blob,
- mimeType: string,
- overwrite: true,
- ): Promise;
- upload(
- blob: Blob,
- mimeType: string,
- overwrite?: false,
- ): Promise;
- upload(
- blob: Blob,
- mimeType: string,
- overwrite?: boolean,
- ): Promise;
- async upload(
- blob: Blob,
- mimeType: string,
- overwrite?: boolean,
- ): Promise {
- const transaction = this.context.solidLdoDataset.startTransaction();
- const result = await this.requestBatcher.queueProcess({
- name: UPLOAD_KEY,
- args: [
- this.uri,
- blob,
- mimeType,
- overwrite,
- { dataset: transaction, fetch: this.context.fetch },
- ],
- perform: uploadResource,
- modifyQueue: (queue, currentlyLoading, args) => {
- const lastElementInQueue = queue[queue.length - 1];
- if (
- lastElementInQueue &&
- lastElementInQueue.name === UPLOAD_KEY &&
- !!lastElementInQueue.args[3] === !!args[3]
- ) {
- return lastElementInQueue;
- }
- if (
- currentlyLoading &&
- currentlyLoading.name === UPLOAD_KEY &&
- !!currentlyLoading.args[3] === !!args[3]
- ) {
- return currentlyLoading;
- }
- return undefined;
- },
- after: (result) => {
- if (!result.isError) {
- transaction.commit();
- }
- },
- });
- return result;
- }
-}
diff --git a/packages/solid/src/requester/requests/checkRootContainer.ts b/packages/solid/src/requester/requests/checkRootContainer.ts
deleted file mode 100644
index 2c8df9f..0000000
--- a/packages/solid/src/requester/requests/checkRootContainer.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import type { BasicRequestOptions } from "./requestOptions";
-import { parse as parseLinkHeader } from "http-link-header";
-import type { CheckRootContainerSuccess } from "../results/success/CheckRootContainerSuccess";
-import type {
- HttpErrorResultType,
- UnexpectedHttpError,
-} from "../results/error/HttpErrorResult";
-import { HttpErrorResult } from "../results/error/HttpErrorResult";
-import { UnexpectedResourceError } from "../results/error/ErrorResult";
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-import type { ContainerUri } from "../../util/uriTypes";
-
-/**
- * checkRootContainer result
- */
-export type CheckRootResult = CheckRootContainerSuccess | CheckRootResultError;
-
-/**
- * All possible errors checkRootResult can return
- */
-export type CheckRootResultError =
- | HttpErrorResultType
- | UnexpectedHttpError
- | UnexpectedResourceError;
-
-/**
- * @internal
- * Checks provided headers to see if a given URI is a root container as defined
- * in the [solid specification section 4.1](https://solidproject.org/TR/protocol#storage-resource)
- *
- * @param uri - the URI of the container resource
- * @param headers - headers returned when making a GET request to the resource
- * @returns CheckRootContainerSuccess if there is not error
- */
-export function checkHeadersForRootContainer(
- uri: ContainerUri,
- headers: Headers,
-): CheckRootContainerSuccess {
- const linkHeader = headers.get("link");
- if (!linkHeader) {
- return {
- uri,
- isRootContainer: false,
- type: "checkRootContainerSuccess",
- isError: false,
- };
- }
- const parsedLinkHeader = parseLinkHeader(linkHeader);
- const types = parsedLinkHeader.get("rel", "type");
- const isRootContainer = types.some(
- (type) => type.uri === "http://www.w3.org/ns/pim/space#Storage",
- );
- return {
- uri,
- isRootContainer,
- type: "checkRootContainerSuccess",
- isError: false,
- };
-}
-
-/**
- * Performs a request to the Pod to check if the given URI is a root container
- * as defined in the [solid specification section 4.1](https://solidproject.org/TR/protocol#storage-resource)
- *
- * @param uri - the URI of the container resource
- * @param options - options variable to pass a fetch function
- * @returns CheckResourceSuccess if there is no error
- *
- * @example
- * ```typescript
- * import { checkRootContainer } from "@ldo/solid";
- * import { fetch } from "@inrupt/solid-client-authn-browser";
- *
- * const result = await checkRootContainer("https://example.com/", { fetch });
- * if (!result.isError) {
- * // true if the container is a root container
- * console.log(result.isRootContainer);
- * }
- * ```
- */
-export async function checkRootContainer(
- uri: ContainerUri,
- options?: BasicRequestOptions,
-): Promise {
- try {
- const fetch = guaranteeFetch(options?.fetch);
- // Fetch options to determine the document type
- // Note cache: "no-store": we don't want to depend on cached results because
- // web browsers do not cache link headers
- // https://github.com/CommunitySolidServer/CommunitySolidServer/issues/1959
- const response = await fetch(uri, { method: "HEAD", cache: "no-store" });
- const httpErrorResult = HttpErrorResult.checkResponse(uri, response);
- if (httpErrorResult) return httpErrorResult;
-
- return checkHeadersForRootContainer(uri, response.headers);
- } catch (err) {
- return UnexpectedResourceError.fromThrown(uri, err);
- }
-}
diff --git a/packages/solid/src/requester/requests/createDataResource.ts b/packages/solid/src/requester/requests/createDataResource.ts
deleted file mode 100644
index 4c5bd5c..0000000
--- a/packages/solid/src/requester/requests/createDataResource.ts
+++ /dev/null
@@ -1,241 +0,0 @@
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-import {
- addResourceRdfToContainer,
- getParentUri,
- getSlug,
-} from "../../util/rdfUtils";
-import type { ContainerUri, LeafUri } from "../../util/uriTypes";
-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 type { CreateSuccess } from "../results/success/CreateSuccess";
-import type { AbsentReadSuccess } from "../results/success/ReadSuccess";
-import type { DeleteResultError } from "./deleteResource";
-import { deleteResource } from "./deleteResource";
-import type {
- ReadContainerResult,
- ReadLeafResult,
- ReadResultError,
-} from "./readResource";
-import { readResource } from "./readResource";
-import type { DatasetRequestOptions } from "./requestOptions";
-
-/**
- * All possible return values when creating and overwriting a container
- */
-export type ContainerCreateAndOverwriteResult =
- | CreateSuccess
- | CreateAndOverwriteResultErrors;
-
-/**
- * All possible return values when creating and overwriting a leaf
- */
-export type LeafCreateAndOverwriteResult =
- | CreateSuccess
- | CreateAndOverwriteResultErrors;
-
-/**
- * All possible return values when creating a container if absent
- */
-export type ContainerCreateIfAbsentResult =
- | CreateSuccess
- | Exclude
- | CreateIfAbsentResultErrors;
-
-/**
- * All possible return values when creating a leaf if absent
- */
-export type LeafCreateIfAbsentResult =
- | CreateSuccess
- | Exclude
- | CreateIfAbsentResultErrors;
-
-/**
- * All possible errors returned by creating and overwriting a resource
- */
-export type CreateAndOverwriteResultErrors = DeleteResultError | CreateErrors;
-
-/**
- * All possible errors returned by creating a resource if absent
- */
-export type CreateIfAbsentResultErrors = ReadResultError | CreateErrors;
-
-/**
- * All possible errors returned by creating a resource
- */
-export type CreateErrors = HttpErrorResultType | UnexpectedResourceError;
-
-/**
- * Creates a data resource (RDF resource) at the provided URI. This resource
- * could also be a container.
- *
- * @param uri - The URI of the resource
- * @param overwrite - If true, the request will overwrite any previous resource
- * at this URI.
- * @param options - Options to provide a fetch function and a local dataset to
- * update.
- * @returns One of many create results depending on the input
- *
- * @example
- * `createDataResource` can be used to create containers.
- *
- * ```typescript
- * import { createDataResource } from "@ldo/solid";
- * import { fetch } from "@inrupt/solid-client-autn-js";
- *
- * const result = await createDataResource(
- * "https://example.com/container/",
- * true,
- * { fetch },
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- *
- * @example
- * `createDataResource` can also create a blank data resource at the provided
- * URI.
- *
- * ```typescript
- * import { createDataResource } from "@ldo/solid";
- * import { fetch } from "@inrupt/solid-client-autn-js";
- *
- * const result = await createDataResource(
- * "https://example.com/container/someResource.ttl",
- * true,
- * { fetch },
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- *
- * @example
- * Any local RDFJS dataset passed to the `options` field will be updated with
- * any new RDF data from the create process.
- *
- * ```typescript
- * import { createDataResource } from "@ldo/solid";
- * import { createDataset } from "@ldo/dataset"
- * import { fetch } from "@inrupt/solid-client-autn-js";
- *
- * const localDataset = createDataset();
- * const result = await createDataResource(
- * "https://example.com/container/someResource.ttl",
- * true,
- * { fetch, dataset: localDataset },
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
-export function createDataResource(
- uri: ContainerUri,
- overwrite: true,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: LeafUri,
- overwrite: true,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: ContainerUri,
- overwrite?: false,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: LeafUri,
- overwrite?: false,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: ContainerUri,
- overwrite?: boolean,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: LeafUri,
- overwrite?: boolean,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: string,
- overwrite: true,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: string,
- overwrite?: false,
- options?: DatasetRequestOptions,
-): Promise;
-export function createDataResource(
- uri: string,
- overwrite?: boolean,
- options?: DatasetRequestOptions,
-): Promise<
- | ContainerCreateAndOverwriteResult
- | LeafCreateAndOverwriteResult
- | ContainerCreateIfAbsentResult
- | LeafCreateIfAbsentResult
->;
-export async function createDataResource(
- uri: string,
- overwrite?: boolean,
- options?: DatasetRequestOptions,
-): Promise<
- | ContainerCreateAndOverwriteResult
- | LeafCreateAndOverwriteResult
- | ContainerCreateIfAbsentResult
- | LeafCreateIfAbsentResult
-> {
- try {
- const fetch = guaranteeFetch(options?.fetch);
- let didOverwrite = false;
- if (overwrite) {
- const deleteResult = await deleteResource(uri, options);
- // Return if it wasn't deleted
- if (deleteResult.isError) return deleteResult;
- didOverwrite = deleteResult.resourceExisted;
- } else {
- // Perform a read to check if it exists
- const readResult = await readResource(uri, options);
-
- // If it does exist stop and return.
- if (readResult.type !== "absentReadSuccess") {
- return readResult;
- }
- }
- // Create the document
- const parentUri = getParentUri(uri)!;
- const headers: HeadersInit = {
- "content-type": "text/turtle",
- slug: getSlug(uri),
- };
- if (isContainerUri(uri)) {
- headers.link = '; rel="type"';
- }
- const response = await fetch(parentUri, {
- method: "post",
- headers,
- });
-
- const httpError = HttpErrorResult.checkResponse(uri, response);
- if (httpError) return httpError;
-
- if (options?.dataset) {
- addResourceRdfToContainer(uri, options.dataset);
- }
- return {
- isError: false,
- type: "createSuccess",
- uri,
- didOverwrite,
- };
- } catch (err) {
- return UnexpectedResourceError.fromThrown(uri, err);
- }
-}
diff --git a/packages/solid/src/requester/requests/deleteResource.ts b/packages/solid/src/requester/requests/deleteResource.ts
deleted file mode 100644
index cc8f084..0000000
--- a/packages/solid/src/requester/requests/deleteResource.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import { namedNode } from "@rdfjs/data-model";
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-import { deleteResourceRdfFromContainer } from "../../util/rdfUtils";
-import { UnexpectedResourceError } from "../results/error/ErrorResult";
-import type { HttpErrorResultType } from "../results/error/HttpErrorResult";
-import { UnexpectedHttpError } from "../results/error/HttpErrorResult";
-import { HttpErrorResult } from "../results/error/HttpErrorResult";
-import type { DeleteSuccess } from "../results/success/DeleteSuccess";
-import type { DatasetRequestOptions } from "./requestOptions";
-import type { IBulkEditableDataset } from "@ldo/subscribable-dataset";
-import type { Quad } from "@rdfjs/types";
-
-/**
- * All possible return values for deleteResource
- */
-export type DeleteResult = DeleteSuccess | DeleteResultError;
-
-/**
- * All possible errors that can be returned by deleteResource
- */
-export type DeleteResultError = HttpErrorResultType | UnexpectedResourceError;
-
-/**
- * Deletes a resource on a Pod at a given URL.
- *
- * @param uri - The URI for the resource that should be deleted
- * @param options - Options to provide a fetch function and a local dataset to
- * update.
- * @returns a DeleteResult
- *
- * @example
- * `deleteResource` will send a request to a Solid Pod using the provided fetch
- * function. A local dataset can also be provided. It will be updated with any
- * new information from the delete.
- *
- * ```typescript
- * import { deleteResource } from "@ldo/solid";
- * import { createDataset } from "@ldo/dataset"
- * import { fetch } from "@inrupt/solid-client-autn-js";
- *
- * const localDataset = createDataset();
- * const result = await deleteResource(
- * "https://example.com/container/someResource.ttl",
- * { fetch, dataset: localDataset },
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
-export async function deleteResource(
- uri: string,
- options?: DatasetRequestOptions,
-): Promise {
- try {
- const fetch = guaranteeFetch(options?.fetch);
- const response = await fetch(uri, {
- method: "delete",
- });
- const errorResult = HttpErrorResult.checkResponse(uri, response);
- if (errorResult) return errorResult;
-
- // Specifically check for a 205. Annoyingly, the server will return 200 even
- // if it hasn't been deleted when you're unauthenticated. 404 happens when
- // the document never existed
- if (response.status === 205 || response.status === 404) {
- if (options?.dataset)
- updateDatasetOnSuccessfulDelete(uri, options.dataset);
- return {
- isError: false,
- type: "deleteSuccess",
- uri,
- resourceExisted: response.status === 205,
- };
- }
- return new UnexpectedHttpError(uri, response);
- } catch (err) {
- return UnexpectedResourceError.fromThrown(uri, err);
- }
-}
-
-/**
- * Assuming a successful delete has just been performed, this function updates
- * datastores to reflect that.
- *
- * @param uri - The uri of the resouce that was removed
- * @param dataset - The dataset that should be updated
- */
-export function updateDatasetOnSuccessfulDelete(
- uri: string,
- dataset: IBulkEditableDataset,
-): void {
- dataset.deleteMatches(undefined, undefined, undefined, namedNode(uri));
- deleteResourceRdfFromContainer(uri, dataset);
-}
diff --git a/packages/solid/src/requester/requests/readResource.ts b/packages/solid/src/requester/requests/readResource.ts
deleted file mode 100644
index 4b9a7bc..0000000
--- a/packages/solid/src/requester/requests/readResource.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-import type { UnexpectedHttpError } from "../results/error/HttpErrorResult";
-import {
- HttpErrorResult,
- type HttpErrorResultType,
-} from "../results/error/HttpErrorResult";
-import {
- addRawTurtleToDataset,
- addResourceRdfToContainer,
-} from "../../util/rdfUtils";
-import type { DatasetRequestOptions } from "./requestOptions";
-import type { ContainerUri, LeafUri } from "../../util/uriTypes";
-import { isContainerUri } from "../../util/uriTypes";
-import type { BinaryReadSuccess } from "../results/success/ReadSuccess";
-import type {
- ContainerReadSuccess,
- DataReadSuccess,
-} 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";
-import { checkHeadersForRootContainer } from "./checkRootContainer";
-import { namedNode } from "@rdfjs/data-model";
-
-/**
- * All possible return values for reading a leaf
- */
-export type ReadLeafResult =
- | BinaryReadSuccess
- | DataReadSuccess
- | AbsentReadSuccess
- | ReadResultError;
-
-/**
- * All possible return values for reading a container
- */
-export type ReadContainerResult =
- | ContainerReadSuccess
- | AbsentReadSuccess
- | ReadResultError;
-
-/**
- * All possible errors the readResource function can return
- */
-export type ReadResultError =
- | HttpErrorResultType
- | NoncompliantPodError
- | UnexpectedHttpError
- | UnexpectedResourceError;
-
-/**
- * Reads resource at a provided URI and returns the result
- *
- * @param uri - The URI of the resource
- * @param options - Options to provide a fetch function and a local dataset to
- * update.
- * @returns ReadResult
- *
- * @example
- * ```typescript
- * import { deleteResource } from "@ldo/solid";
- * import { createDataset } from "@ldo/dataset"
- * import { fetch } from "@inrupt/solid-client-autn-js";
- *
- * const dataset = createDataset();
- * const result = await readResource(
- * "https://example.com/container/someResource.ttl",
- * { fetch, dataset },
- * );
- * if (!result.isError) {
- * if (result.type === "absentReadSuccess") {
- * // There was no problem reading the resource, but it doesn't exist
- * } else if (result.type === "dataReadSuccess") {
- * // The resource was read and it is an RDF resource. The dataset provided
- * // dataset will also be loaded with the data from the resource
- * } else if (result.type === "binaryReadSuccess") {
- * // The resource is a binary
- * console.log(result.blob);
- * console.log(result.mimeType);
- * }
- * }
- * ```
- */
-export async function readResource(
- uri: LeafUri,
- options?: DatasetRequestOptions,
-): Promise;
-export async function readResource(
- uri: ContainerUri,
- options?: DatasetRequestOptions,
-): Promise;
-export async function readResource(
- uri: string,
- options?: DatasetRequestOptions,
-): Promise;
-export async function readResource(
- uri: string,
- options?: DatasetRequestOptions,
-): Promise {
- try {
- const fetch = guaranteeFetch(options?.fetch);
- // Fetch options to determine the document type
- const response = await fetch(uri, {
- headers: { accept: "text/turtle, */*" },
- });
- if (response.status === 404) {
- // Clear existing data if present
- if (options?.dataset) {
- options.dataset.deleteMatches(
- undefined,
- undefined,
- undefined,
- namedNode(uri),
- );
- }
-
- return {
- isError: false,
- type: "absentReadSuccess",
- uri,
- recalledFromMemory: false,
- };
- }
- const httpErrorResult = HttpErrorResult.checkResponse(uri, response);
- if (httpErrorResult) return httpErrorResult;
-
- // Add this resource to the container
- if (options?.dataset) {
- addResourceRdfToContainer(uri, options.dataset);
- }
-
- const contentType = response.headers.get("content-type");
- if (!contentType) {
- return new NoncompliantPodError(
- uri,
- "Resource requests must return a content-type header.",
- );
- }
-
- if (contentType.startsWith("text/turtle")) {
- // Parse Turtle
- const rawTurtle = await response.text();
- if (options?.dataset) {
- const result = await addRawTurtleToDataset(
- rawTurtle,
- options.dataset,
- uri,
- );
- if (result) return result;
- }
- if (isContainerUri(uri)) {
- const result = checkHeadersForRootContainer(uri, response.headers);
- return {
- isError: false,
- type: "containerReadSuccess",
- uri,
- recalledFromMemory: false,
- isRootContainer: result.isRootContainer,
- };
- }
- return {
- isError: false,
- type: "dataReadSuccess",
- uri,
- recalledFromMemory: false,
- };
- } else {
- // Load Blob
- const blob = await response.blob();
- return {
- isError: false,
- type: "binaryReadSuccess",
- uri,
- recalledFromMemory: false,
- blob,
- mimeType: contentType,
- };
- }
- } catch (err) {
- return UnexpectedResourceError.fromThrown(uri, err);
- }
-}
diff --git a/packages/solid/src/requester/requests/requestOptions.ts b/packages/solid/src/requester/requests/requestOptions.ts
deleted file mode 100644
index 376c043..0000000
--- a/packages/solid/src/requester/requests/requestOptions.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import type { IBulkEditableDataset } from "@ldo/subscribable-dataset";
-import type { Quad } from "@rdfjs/types";
-
-/**
- * Request Options to be passed to request functions
- */
-export interface BasicRequestOptions {
- /**
- * A fetch function usually imported from @inrupt/solid-client-authn-js
- */
- fetch?: typeof fetch;
-}
-
-/**
- * Request options with a dataset component
- */
-export interface DatasetRequestOptions extends BasicRequestOptions {
- /**
- * A dataset to be modified with any new information obtained from a request
- */
- dataset?: IBulkEditableDataset;
-}
diff --git a/packages/solid/src/requester/requests/updateDataResource.ts b/packages/solid/src/requester/requests/updateDataResource.ts
deleted file mode 100644
index 9b0237f..0000000
--- a/packages/solid/src/requester/requests/updateDataResource.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import type { DatasetChanges } from "@ldo/rdf-utils";
-import { changesToSparqlUpdate } from "@ldo/rdf-utils";
-import type { Quad } from "@rdfjs/types";
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-import type { LeafUri } from "../../util/uriTypes";
-import { UnexpectedResourceError } from "../results/error/ErrorResult";
-import type { HttpErrorResultType } from "../results/error/HttpErrorResult";
-import { HttpErrorResult } from "../results/error/HttpErrorResult";
-import type { UpdateSuccess } from "../results/success/UpdateSuccess";
-import type { DatasetRequestOptions } from "./requestOptions";
-
-/**
- * All return values for updateDataResource
- */
-export type UpdateResult = UpdateSuccess | UpdateResultError;
-
-/**
- * All errors updateDataResource can return
- */
-export type UpdateResultError = HttpErrorResultType | UnexpectedResourceError;
-
-/**
- * Updates a specific data resource with the provided dataset changes
- *
- * @param uri - the URI of the data resource
- * @param datasetChanges - A set of triples added and removed from this dataset
- * @param options - Options to provide a fetch function and a local dataset to
- * update.
- * @returns An UpdateResult
- *
- * @example
- * ```typescript
- * import {
- * updateDataResource,
- * transactionChanges,
- * changeData,
- * createSolidLdoDataset,
- * } from "@ldo/solid";
- * import { fetch } from "@inrupt/solid-client-authn-browser";
- *
- * // Initialize an LDO dataset
- * const solidLdoDataset = createSolidLdoDataset();
- * // Get a Linked Data Object
- * const profile = solidLdoDataset
- * .usingType(ProfileShapeType)
- * .fromSubject("https://example.com/profile#me");
- * // Create a transaction to change data
- * const cProfile = changeData(
- * profile,
- * solidLdoDataset.getResource("https://example.com/profile"),
- * );
- * cProfile.name = "John Doe";
- * // Get data in "DatasetChanges" form
- * const datasetChanges = transactionChanges(someLinkedDataObject);
- * // Use "updateDataResource" to apply the changes
- * const result = await updateDataResource(
- * "https://example.com/profile",
- * datasetChanges,
- * { fetch, dataset: solidLdoDataset },
- * );
- * ```
- */
-export async function updateDataResource(
- uri: LeafUri,
- datasetChanges: DatasetChanges,
- options?: DatasetRequestOptions,
-): Promise {
- try {
- // Optimistically add data
- options?.dataset?.bulk(datasetChanges);
- const fetch = guaranteeFetch(options?.fetch);
-
- // Make request
- const sparqlUpdate = await changesToSparqlUpdate(datasetChanges);
- const response = await fetch(uri, {
- method: "PATCH",
- body: sparqlUpdate,
- headers: {
- "Content-Type": "application/sparql-update",
- },
- });
- const httpError = HttpErrorResult.checkResponse(uri, response);
- if (httpError) {
- // Handle error rollback
- if (options?.dataset) {
- options.dataset.bulk({
- added: datasetChanges.removed,
- removed: datasetChanges.added,
- });
- }
- return httpError;
- }
- return {
- isError: false,
- type: "updateSuccess",
- uri,
- };
- } catch (err) {
- return UnexpectedResourceError.fromThrown(uri, err);
- }
-}
diff --git a/packages/solid/src/requester/requests/uploadResource.ts b/packages/solid/src/requester/requests/uploadResource.ts
deleted file mode 100644
index fcce355..0000000
--- a/packages/solid/src/requester/requests/uploadResource.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-import {
- addResourceRdfToContainer,
- getParentUri,
- getSlug,
-} from "../../util/rdfUtils";
-import type { LeafUri } from "../../util/uriTypes";
-import { UnexpectedResourceError } from "../results/error/ErrorResult";
-import { HttpErrorResult } from "../results/error/HttpErrorResult";
-import type {
- LeafCreateAndOverwriteResult,
- LeafCreateIfAbsentResult,
-} from "./createDataResource";
-import { deleteResource } from "./deleteResource";
-import { readResource } from "./readResource";
-import type { DatasetRequestOptions } from "./requestOptions";
-
-/**
- * Uploads a binary resource at the provided URI
- *
- * @param uri - The URI of the resource
- * @param overwrite - If true, the request will overwrite any previous resource
- * at this URI.
- * @param options - Options to provide a fetch function and a local dataset to
- * update.
- * @returns One of many create results depending on the input
- *
- * @example
- * Any local RDFJS dataset passed to the `options` field will be updated with
- * any new RDF data from the create process.
- *
- * ```typescript
- * import { createDataResource } from "@ldo/solid";
- * import { createDataset } from "@ldo/dataset"
- * import { fetch } from "@inrupt/solid-client-autn-js";
- *
- * const localDataset = createDataset();
- * const result = await uploadResource(
- * "https://example.com/container/someResource.txt",
- * new Blob("some text."),
- * "text/txt",
- * true,
- * { fetch, dataset: localDataset },
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
-export function uploadResource(
- uri: LeafUri,
- blob: Blob,
- mimeType: string,
- overwrite: true,
- options?: DatasetRequestOptions,
-): Promise;
-export function uploadResource(
- uri: LeafUri,
- blob: Blob,
- mimeType: string,
- overwrite?: false,
- options?: DatasetRequestOptions,
-): Promise;
-export function uploadResource(
- uri: LeafUri,
- blob: Blob,
- mimeType: string,
- overwrite?: boolean,
- options?: DatasetRequestOptions,
-): Promise;
-export async function uploadResource(
- uri: LeafUri,
- blob: Blob,
- mimeType: string,
- overwrite?: boolean,
- options?: DatasetRequestOptions,
-): Promise {
- try {
- const fetch = guaranteeFetch(options?.fetch);
- let didOverwrite = false;
- if (overwrite) {
- const deleteResult = await deleteResource(uri, options);
- // Return if it wasn't deleted
- if (deleteResult.isError) return deleteResult;
- didOverwrite = deleteResult.resourceExisted;
- } else {
- // Perform a read to check if it exists
- const readResult = await readResource(uri, options);
- // If it does exist stop and return.
- if (readResult.type !== "absentReadSuccess") {
- 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;
-
- if (options?.dataset) {
- addResourceRdfToContainer(uri, options.dataset);
- }
- return {
- isError: false,
- type: "createSuccess",
- uri,
- didOverwrite,
- };
- } catch (err) {
- const thing = UnexpectedResourceError.fromThrown(uri, err);
- return thing;
- }
-}
diff --git a/packages/solid/src/requester/results/RequesterResult.ts b/packages/solid/src/requester/results/RequesterResult.ts
deleted file mode 100644
index 2c51cfb..0000000
--- a/packages/solid/src/requester/results/RequesterResult.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-/**
- * A type returned by all request functions
- */
-export interface RequesterResult {
- type: string;
- isError: boolean;
-}
diff --git a/packages/solid/src/requester/results/error/AccessControlError.ts b/packages/solid/src/requester/results/error/AccessControlError.ts
deleted file mode 100644
index a4c5a18..0000000
--- a/packages/solid/src/requester/results/error/AccessControlError.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/* istanbul ignore file */
-import { ResourceError } from "./ErrorResult";
-
-/**
- * An error: Could not fetch access rules
- */
-export class AccessRuleFetchError extends ResourceError {
- readonly type = "accessRuleFetchError" as const;
-
- /**
- * @param uri - The uri of the resource for which access rules couldn't be
- * fetched
- * @param message - A custom message for the error
- */
- constructor(uri: string, message?: string) {
- super(uri, message || `${uri} had trouble fetching access rules.`);
- }
-}
diff --git a/packages/solid/src/requester/results/error/ErrorResult.ts b/packages/solid/src/requester/results/error/ErrorResult.ts
deleted file mode 100644
index 84a29ad..0000000
--- a/packages/solid/src/requester/results/error/ErrorResult.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-import type { RequesterResult } from "../RequesterResult";
-
-/**
- * A result indicating that the request failed in some kind of way
- */
-export abstract class ErrorResult extends Error implements RequesterResult {
- /**
- * Indicates the specific type of error
- */
- abstract type: string;
-
- /**
- * Always true
- */
- readonly isError = true as const;
-
- /**
- * @param message - a custom message for the error
- */
- constructor(message?: string) {
- super(message || "An unkown error was encountered.");
- }
-}
-
-/**
- * An error for a specific resource
- */
-export abstract class ResourceError extends ErrorResult {
- /**
- * The URI of the resource
- */
- readonly uri: string;
-
- /**
- * @param uri - The URI of the resource
- * @param message - A custom message for the error
- */
- constructor(uri: string, message?: string) {
- super(message || `An unkown error for ${uri}`);
- this.uri = uri;
- }
-}
-
-/**
- * An error that aggregates many errors
- */
-export class AggregateError extends ErrorResult {
- readonly type = "aggregateError" as const;
-
- /**
- * A list of all errors returned
- */
- readonly errors: ErrorType[];
-
- /**
- * @param errors - List of all errors returned
- * @param message - A custom message for the error
- */
- constructor(
- errors: (ErrorType | AggregateError)[],
- message?: string,
- ) {
- const allErrors: ErrorType[] = [];
- errors.forEach((error) => {
- if (error instanceof AggregateError) {
- error.errors.forEach((subError) => {
- allErrors.push(subError);
- });
- } else {
- allErrors.push(error);
- }
- });
- super(
- message ||
- `Encountered multiple errors:${allErrors.reduce(
- (agg, cur) => `${agg}\n${cur}`,
- "",
- )}`,
- );
- this.errors = allErrors;
- }
-}
-
-/**
- * Represents some error that isn't handled under other errors. This is usually
- * returned when something threw an error that LDO did not expect.
- */
-export class UnexpectedResourceError extends ResourceError {
- readonly type = "unexpectedResourceError" as const;
-
- /**
- * The error that was thrown
- */
- error: Error;
-
- /**
- * @param uri - URI of the resource
- * @param error - The error that was thrown
- */
- constructor(uri: string, error: Error) {
- super(uri, error.message);
- this.error = error;
- }
-
- /**
- * @internal
- *
- * Creates an UnexpectedResourceError from a thrown error
- * @param uri - The URI of the resource
- * @param err - The thrown error
- * @returns an UnexpectedResourceError
- */
- static fromThrown(uri: string, err: unknown) {
- if (err instanceof Error) {
- return new UnexpectedResourceError(uri, err);
- } else if (typeof err === "string") {
- return new UnexpectedResourceError(uri, new Error(err));
- } else {
- return new UnexpectedResourceError(
- uri,
- new Error(`Error of type ${typeof err} thrown: ${err}`),
- );
- }
- }
-}
diff --git a/packages/solid/src/requester/results/error/HttpErrorResult.ts b/packages/solid/src/requester/results/error/HttpErrorResult.ts
deleted file mode 100644
index 69cc821..0000000
--- a/packages/solid/src/requester/results/error/HttpErrorResult.ts
+++ /dev/null
@@ -1,160 +0,0 @@
-import { ResourceError } from "./ErrorResult";
-
-/**
- * A set of standard errors that can be returned as a result of an HTTP request
- */
-export type HttpErrorResultType =
- | ServerHttpError
- | UnexpectedHttpError
- | UnauthenticatedHttpError
- | UnauthorizedHttpError;
-
-/**
- * An error caused by an HTTP request
- */
-export abstract class HttpErrorResult extends ResourceError {
- /**
- * The status of the HTTP request
- */
- public readonly status: number;
-
- /**
- * Headers returned by the HTTP request
- */
- public readonly headers: Headers;
-
- /**
- * Response returned by the HTTP request
- */
- public readonly response: Response;
-
- /**
- * @param uri - URI of the resource
- * @param response - The response returned by the HTTP requests
- * @param message - A custom message for the error
- */
- constructor(uri: string, response: Response, message?: string) {
- super(
- uri,
- message ||
- `Request for ${uri} returned ${response.status} (${response.statusText}).`,
- );
- this.status = response.status;
- this.headers = response.headers;
- this.response = response;
- }
-
- /**
- * Checks to see if a given response does not constitute an HTTP Error
- * @param response - The response of the request
- * @returns true if the response does not constitute an HTTP Error
- */
- static isnt(response: Response) {
- return (
- !(response.status >= 200 && response.status < 300) &&
- response.status !== 404 &&
- response.status !== 304
- );
- }
-
- /**
- * Checks a given response to see if it is a ServerHttpError, an
- * UnauthenticatedHttpError or a some unexpected error.
- * @param uri - The uri of the request
- * @param response - The response of the request
- * @returns An error if the response calls for it. Undefined if not.
- */
- 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 (UnauthorizedHttpError.is(response)) {
- return new UnauthorizedHttpError(uri, response);
- }
- if (HttpErrorResult.isnt(response)) {
- return new UnexpectedHttpError(uri, response);
- }
- return undefined;
- }
-}
-
-/**
- * An unexpected error as a result of an HTTP request. This is usually returned
- * when the HTTP request returns a status code LDO does not recognize.
- */
-export class UnexpectedHttpError extends HttpErrorResult {
- readonly type = "unexpectedHttpError" as const;
-}
-
-/**
- * An UnauthenticatedHttpError triggers when a Solid server returns a 401 status
- * indicating that the request is not authenticated.
- */
-export class UnauthenticatedHttpError extends HttpErrorResult {
- readonly type = "unauthenticatedError" as const;
-
- /**
- * Indicates if a specific response constitutes an UnauthenticatedHttpError
- * @param response - The request response
- * @returns true if this response constitutes an UnauthenticatedHttpError
- */
- static is(response: Response) {
- return response.status === 401;
- }
-}
-
-/**
- * An UnauthenticatedHttpError triggers when a Solid server returns a 403 status
- * indicating that the request is not authorized.
- */
-export class UnauthorizedHttpError extends HttpErrorResult {
- readonly type = "unauthorizedError" as const;
-
- /**
- * Indicates if a specific response constitutes an UnauthenticatedHttpError
- * @param response - The request response
- * @returns true if this response constitutes an UnauthenticatedHttpError
- */
- static is(response: Response) {
- return response.status === 403;
- }
-}
-
-/**
- * An NotFoundHttpError triggers when a Solid server returns a 404 status. This
- * error is not returned in most cases as a "absent" resource is not considered
- * an error, but it is thrown while trying for find a WAC rule for a resource
- * that does not exist.
- */
-export class NotFoundHttpError extends HttpErrorResult {
- readonly type = "notFoundError" as const;
-
- /**
- * Indicates if a specific response constitutes an NotFoundHttpError
- * @param response - The request response
- * @returns true if this response constitutes an NotFoundHttpError
- */
- static is(response: Response) {
- return response.status === 404;
- }
-}
-
-/**
- * A ServerHttpError triggers when a Solid server returns a 5XX status,
- * indicating that an error happened on the server.
- */
-export class ServerHttpError extends HttpErrorResult {
- readonly type = "serverError" as const;
-
- /**
- * Indicates if a specific response constitutes a ServerHttpError
- * @param response - The request response
- * @returns true if this response constitutes a ServerHttpError
- */
- static is(response: Response) {
- return response.status >= 500 && response.status < 600;
- }
-}
diff --git a/packages/solid/src/requester/results/error/InvalidUriError.ts b/packages/solid/src/requester/results/error/InvalidUriError.ts
deleted file mode 100644
index e1c3201..0000000
--- a/packages/solid/src/requester/results/error/InvalidUriError.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { ResourceError } from "./ErrorResult";
-
-/**
- * An InvalidUriError is returned when a URI was provided that is not a valid
- * URI.
- */
-export class InvalidUriError extends ResourceError {
- readonly type = "invalidUriError" as const;
-
- constructor(uri: string, message?: string) {
- super(uri, message || `${uri} is an invalid uri.`);
- }
-}
diff --git a/packages/solid/src/requester/results/error/NoRootContainerError.ts b/packages/solid/src/requester/results/error/NoRootContainerError.ts
deleted file mode 100644
index 8a17f2f..0000000
--- a/packages/solid/src/requester/results/error/NoRootContainerError.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { ResourceError } from "./ErrorResult";
-
-/**
- * A NoncompliantPodError is returned when the server responded in a way that is
- * not compliant with the Solid specification.
- */
-export class NoRootContainerError extends ResourceError {
- readonly type = "noRootContainerError" as const;
-
- /**
- * @param uri - the URI of the requested resource
- * @param message - a custom message for the error
- */
- constructor(uri: string) {
- super(uri, `${uri} has not root container.`);
- }
-}
diff --git a/packages/solid/src/requester/results/error/NoncompliantPodError.ts b/packages/solid/src/requester/results/error/NoncompliantPodError.ts
deleted file mode 100644
index b981414..0000000
--- a/packages/solid/src/requester/results/error/NoncompliantPodError.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { ResourceError } from "./ErrorResult";
-
-/**
- * A NoncompliantPodError is returned when the server responded in a way that is
- * not compliant with the Solid specification.
- */
-export class NoncompliantPodError extends ResourceError {
- readonly type = "noncompliantPodError" as const;
-
- /**
- * @param uri - the URI of the requested resource
- * @param message - a custom message for the error
- */
- constructor(uri: string, message?: string) {
- super(
- uri,
- `Response from ${uri} is not compliant with the Solid Specification: ${message}`,
- );
- }
-}
diff --git a/packages/solid/src/requester/results/success/CheckRootContainerSuccess.ts b/packages/solid/src/requester/results/success/CheckRootContainerSuccess.ts
deleted file mode 100644
index 77a435f..0000000
--- a/packages/solid/src/requester/results/success/CheckRootContainerSuccess.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import type { Container } from "../../../resource/Container";
-import type { ResourceSuccess, SuccessResult } from "./SuccessResult";
-
-/**
- * Indicates that the request to check if a resource is the root container was
- * a success.
- */
-export interface CheckRootContainerSuccess extends ResourceSuccess {
- type: "checkRootContainerSuccess";
- /**
- * True if this resoure is the root container
- */
- isRootContainer: boolean;
-}
-
-export interface GetStorageContainerFromWebIdSuccess extends SuccessResult {
- type: "getStorageContainerFromWebIdSuccess";
- storageContainers: Container[];
-}
diff --git a/packages/solid/src/requester/results/success/CreateSuccess.ts b/packages/solid/src/requester/results/success/CreateSuccess.ts
deleted file mode 100644
index 3d83b9f..0000000
--- a/packages/solid/src/requester/results/success/CreateSuccess.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { ResourceSuccess } from "./SuccessResult";
-
-/**
- * Indicates that the request to create the resource was a success.
- */
-export interface CreateSuccess extends ResourceSuccess {
- type: "createSuccess";
- /**
- * True if there was a resource that existed before at the given URI that was
- * overwritten
- */
- didOverwrite: boolean;
-}
diff --git a/packages/solid/src/requester/results/success/DeleteSuccess.ts b/packages/solid/src/requester/results/success/DeleteSuccess.ts
deleted file mode 100644
index 0345a1c..0000000
--- a/packages/solid/src/requester/results/success/DeleteSuccess.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import type { ResourceSuccess } from "./SuccessResult";
-
-/**
- * Indicates that the request to delete a resource was a success.
- */
-export interface DeleteSuccess extends ResourceSuccess {
- type: "deleteSuccess";
-
- /**
- * True if there was a resource at the provided URI that was deleted. False if
- * a resource didn't exist.
- */
- resourceExisted: boolean;
-}
diff --git a/packages/solid/src/requester/results/success/ReadSuccess.ts b/packages/solid/src/requester/results/success/ReadSuccess.ts
deleted file mode 100644
index 756642a..0000000
--- a/packages/solid/src/requester/results/success/ReadSuccess.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import type { ResourceSuccess, SuccessResult } from "./SuccessResult";
-
-/**
- * Indicates that the request to read a resource was a success
- */
-export interface ReadSuccess extends ResourceSuccess {
- /**
- * True if the resource was recalled from local memory rather than a recent
- * request
- */
- recalledFromMemory: boolean;
-}
-
-/**
- * Indicates that the read request was successful and that the resource
- * retrieved was a binary resource.
- */
-export interface BinaryReadSuccess extends ReadSuccess {
- type: "binaryReadSuccess";
- /**
- * The raw data for the binary resource
- */
- blob: Blob;
- /**
- * The mime type of the binary resource
- */
- mimeType: string;
-}
-
-/**
- * Indicates that the read request was successful and that the resource
- * retrieved was a data (RDF) resource.
- */
-export interface DataReadSuccess extends ReadSuccess {
- type: "dataReadSuccess";
-}
-
-/**
- * Indicates that the read request was successful and that the resource
- * retrieved was a container resource.
- */
-export interface ContainerReadSuccess extends ReadSuccess {
- type: "containerReadSuccess";
- /**
- * True if this container is a root container
- */
- isRootContainer: boolean;
-}
-
-/**
- * Indicates that the read request was successful, but no resource exists at
- * the provided URI.
- */
-export interface AbsentReadSuccess extends ReadSuccess {
- type: "absentReadSuccess";
-}
-
-/**
- * A helper function that checks to see if a result is a ReadSuccess result
- *
- * @param result - the result to check
- * @returns true if the result is a ReadSuccessResult result
- */
-export function isReadSuccess(result: SuccessResult): result is ReadSuccess {
- return (
- result.type === "binaryReadSuccess" ||
- result.type === "dataReadSuccess" ||
- result.type === "absentReadSuccess" ||
- result.type === "containerReadSuccess"
- );
-}
diff --git a/packages/solid/src/requester/results/success/SuccessResult.ts b/packages/solid/src/requester/results/success/SuccessResult.ts
deleted file mode 100644
index 35b891c..0000000
--- a/packages/solid/src/requester/results/success/SuccessResult.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import type { RequesterResult } from "../RequesterResult";
-
-/**
- * Indicates that some action taken by LDO was a success
- */
-export interface SuccessResult extends RequesterResult {
- isError: false;
-}
-
-/**
- * Indicates that a request to a resource was aa success
- */
-export interface ResourceSuccess extends SuccessResult {
- /**
- * The URI of the resource
- */
- uri: string;
-}
-
-/**
- * A grouping of multiple successes as a result of an action
- */
-export interface AggregateSuccess
- extends SuccessResult {
- type: "aggregateSuccess";
-
- /**
- * An array of all successesses
- */
- results: SuccessType[];
-}
diff --git a/packages/solid/src/requester/results/success/Unfetched.ts b/packages/solid/src/requester/results/success/Unfetched.ts
deleted file mode 100644
index 9d8db38..0000000
--- a/packages/solid/src/requester/results/success/Unfetched.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { ResourceSuccess } from "./SuccessResult";
-
-/**
- * Indicates that a specific resource is unfetched
- */
-export interface Unfetched extends ResourceSuccess {
- type: "unfetched";
-}
diff --git a/packages/solid/src/requester/results/success/UpdateSuccess.ts b/packages/solid/src/requester/results/success/UpdateSuccess.ts
deleted file mode 100644
index 5b740a0..0000000
--- a/packages/solid/src/requester/results/success/UpdateSuccess.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import type { ResourceSuccess } from "./SuccessResult";
-
-/**
- * Indicates that an update request to a resource was successful
- */
-export interface UpdateSuccess extends ResourceSuccess {
- type: "updateSuccess";
-}
-
-/**
- * Indicates that an update request to the default graph was successful. This
- * data was not written to a Pod. It was only written locally.
- */
-export interface UpdateDefaultGraphSuccess extends ResourceSuccess {
- type: "updateDefaultGraphSuccess";
-}
-
-/**
- * Indicates that LDO ignored an invalid update (usually because a container
- * attempted an update)
- */
-export interface IgnoredInvalidUpdateSuccess extends ResourceSuccess {
- type: "ignoredInvalidUpdateSuccess";
-}
diff --git a/packages/solid/src/requester/util/modifyQueueFuntions.ts b/packages/solid/src/requester/util/modifyQueueFuntions.ts
deleted file mode 100644
index 780b5d1..0000000
--- a/packages/solid/src/requester/util/modifyQueueFuntions.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-import type { WaitingProcess } from "../../util/RequestBatcher";
-
-/**
- * @internal
- *
- * A helper function for a common way to modify the batch queue. This merges
- * the incoming request with the currently executing request or the last request
- * in the queue if its keys are the same.
- *
- * @param key - the key of the incoming request
- * @returns a modifyQueue function
- */
-export function modifyQueueByMergingEventsWithTheSameKeys(key: string) {
- return (
- queue: WaitingProcess[],
- currentlyLoading: WaitingProcess | undefined,
- ) => {
- if (queue.length === 0 && currentlyLoading?.name === key) {
- return currentlyLoading;
- } else if (queue[queue.length - 1]?.name === key) {
- return queue[queue.length - 1];
- }
- return undefined;
- };
-}
diff --git a/packages/solid/src/resource/Container.ts b/packages/solid/src/resource/Container.ts
deleted file mode 100644
index 2670e28..0000000
--- a/packages/solid/src/resource/Container.ts
+++ /dev/null
@@ -1,599 +0,0 @@
-import { namedNode } from "@rdfjs/data-model";
-import { ContainerBatchedRequester } from "../requester/ContainerBatchedRequester";
-import type {
- CheckRootResult,
- CheckRootResultError,
-} from "../requester/requests/checkRootContainer";
-import type {
- ContainerCreateAndOverwriteResult,
- ContainerCreateIfAbsentResult,
- LeafCreateAndOverwriteResult,
- LeafCreateIfAbsentResult,
-} from "../requester/requests/createDataResource";
-import type {
- DeleteResult,
- DeleteResultError,
-} from "../requester/requests/deleteResource";
-import type {
- ReadContainerResult,
- ReadResultError,
-} from "../requester/requests/readResource";
-import { AggregateError } from "../requester/results/error/ErrorResult";
-import type { DeleteSuccess } from "../requester/results/success/DeleteSuccess";
-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 type { ResourceResult } from "./resourceResult/ResourceResult";
-import { NoRootContainerError } from "../requester/results/error/NoRootContainerError";
-
-/**
- * Represents the current status of a specific container on a Pod as known by
- * LDO.
- *
- * @example
- * ```typescript
- * const container = solidLdoDataset
- * .getResource("https://example.com/container/");
- * ```
- */
-export class Container extends Resource {
- /**
- * The URI of the container
- */
- readonly uri: ContainerUri;
-
- /**
- * @internal
- * Batched Requester for the Container
- */
- protected requester: ContainerBatchedRequester;
-
- /**
- * @internal
- * True if this is the root container, false if not, undefined if unknown
- */
- protected rootContainer: boolean | undefined;
-
- /**
- * Indicates that this resource is a container resource
- */
- readonly type = "container" as const;
-
- /**
- * Indicates that this resource is not an error
- */
- readonly isError = false as const;
-
- /**
- * The status of the last request made for this container
- */
- status:
- | SharedStatuses
- | ReadContainerResult
- | ContainerCreateAndOverwriteResult
- | ContainerCreateIfAbsentResult
- | CheckRootResult;
-
- /**
- * @param uri - The uri of the container
- * @param context - SolidLdoDatasetContext for the parent dataset
- */
- constructor(uri: ContainerUri, context: SolidLdoDatasetContext) {
- super(context);
- this.uri = uri;
- this.requester = new ContainerBatchedRequester(uri, context);
- this.status = { isError: false, type: "unfetched", uri };
- }
-
- /**
- * Checks if this container is a root container
- * @returns true if this container is a root container, false if not, and
- * undefined if this is unknown at the moment.
- *
- * @example
- * ```typescript
- * // Returns "undefined" when the container is unfetched
- * console.log(container.isRootContainer());
- * const result = await container.read();
- * if (!result.isError) {
- * // Returns true or false
- * console.log(container.isRootContainer());
- * }
- * ```
- */
- isRootContainer(): boolean | undefined {
- return this.rootContainer;
- }
-
- /**
- * ===========================================================================
- * READ METHODS
- * ===========================================================================
- */
-
- /**
- * @internal
- * A helper method updates this container's internal state upon read success
- * @param result - the result of the read success
- */
- protected updateWithReadSuccess(
- result: ContainerReadSuccess | AbsentReadSuccess,
- ): void {
- super.updateWithReadSuccess(result);
- if (result.type === "containerReadSuccess") {
- this.rootContainer = result.isRootContainer;
- }
- }
-
- /**
- * Reads the container
- * @returns A read result
- *
- * @example
- * ```typescript
- * const result = await container.read();
- * if (result.isError) {
- * // Do something
- * }
- * ```
- */
- async read(): Promise> {
- const result = (await this.handleRead()) as ReadContainerResult;
- if (result.isError) return result;
- return { ...result, resource: this };
- }
-
- /**
- * @internal
- * Converts the current state of this container to a readResult
- * @returns a ReadContainerResult
- */
- protected toReadResult(): ResourceResult {
- if (this.isAbsent()) {
- return {
- isError: false,
- type: "absentReadSuccess",
- uri: this.uri,
- recalledFromMemory: true,
- resource: this,
- };
- } else {
- return {
- isError: false,
- type: "containerReadSuccess",
- uri: this.uri,
- recalledFromMemory: true,
- isRootContainer: this.isRootContainer()!,
- resource: this,
- };
- }
- }
-
- /**
- * Makes a request to read this container if it hasn't been fetched yet. If it
- * has, return the cached informtation
- * @returns a ReadContainerResult
- *
- * @example
- * ```typescript
- * const result = await container.read();
- * if (!result.isError) {
- * // Will execute without making a request
- * const result2 = await container.readIfUnfetched();
- * }
- * ```
- */
- async readIfUnfetched(): Promise<
- ResourceResult
- > {
- return super.readIfUnfetched() as Promise<
- ResourceResult
- >;
- }
-
- /**
- * ===========================================================================
- * PARENT CONTAINER METHODS
- * ===========================================================================
- */
-
- /**
- * @internal
- * Checks if this container is a root container by making a request
- * @returns CheckRootResult
- */
- private async checkIfIsRootContainer(): Promise<
- ResourceResult
- > {
- const rootContainerResult = await this.requester.isRootContainer();
- this.status = rootContainerResult;
- if (rootContainerResult.isError) return rootContainerResult;
- this.rootContainer = rootContainerResult.isRootContainer;
- this.emit("update");
- return { ...rootContainerResult, resource: this };
- }
-
- /**
- * Gets the root container of this container. If this container is the root
- * container, this function returns itself.
- * @returns The root container for this container or undefined if there is no
- * root container.
- *
- * @example
- * Suppose the root container is at `https://example.com/`
- *
- * ```typescript
- * const container = ldoSolidDataset
- * .getResource("https://example.com/container/");
- * const rootContainer = await container.getRootContainer();
- * if (!rootContainer.isError) {
- * // logs "https://example.com/"
- * console.log(rootContainer.uri);
- * }
- * ```
- */
- async getRootContainer(): Promise<
- Container | CheckRootResultError | NoRootContainerError
- > {
- const parentContainerResult = await this.getParentContainer();
- if (parentContainerResult?.isError) return parentContainerResult;
- if (!parentContainerResult) {
- return this.isRootContainer() ? this : new NoRootContainerError(this.uri);
- }
- return parentContainerResult.getRootContainer();
- }
-
- /**
- * Gets the parent container for this container by making a request
- * @returns The parent container or undefined if there is no parent container
- * because this container is the root container
- *
- * @example
- * Suppose the root container is at `https://example.com/`
- *
- * ```typescript
- * const root = solidLdoDataset.getResource("https://example.com/");
- * const container = solidLdoDataset
- * .getResource("https://example.com/container");
- * const rootParent = await root.getParentContainer();
- * console.log(rootParent); // Logs "undefined"
- * const containerParent = await container.getParentContainer();
- * if (!containerParent.isError) {
- * // Logs "https://example.com/"
- * console.log(containerParent.uri);
- * }
- * ```
- */
- async getParentContainer(): Promise<
- Container | CheckRootResultError | undefined
- > {
- if (this.rootContainer === undefined) {
- const checkResult = await this.checkIfIsRootContainer();
- if (checkResult.isError) return checkResult;
- }
- if (this.rootContainer) return undefined;
- const parentUri = getParentUri(this.uri);
- if (!parentUri) {
- return undefined;
- }
- return this.context.resourceStore.get(parentUri);
- }
-
- /**
- * Lists the currently cached children of this container (no request is made)
- * @returns An array of children
- *
- * ```typescript
- * const result = await container.read();
- * if (!result.isError) {
- * const children = container.children();
- * children.forEach((child) => {
- * console.log(child.uri);
- * });
- * }
- * ```
- */
- children(): (Leaf | Container)[] {
- const childQuads = this.context.solidLdoDataset.match(
- namedNode(this.uri),
- ldpContains,
- null,
- namedNode(this.uri),
- );
- return childQuads.toArray().map((childQuad) => {
- return this.context.resourceStore.get(childQuad.object.value);
- });
- }
-
- /**
- * Returns a child resource with a given name (slug)
- * @param slug - the given name for that child resource
- * @returns the child resource (either a Leaf or Container depending on the
- * name)
- *
- * @example
- * ```typescript
- * const root = solidLdoDataset.getResource("https://example.com/");
- * const container = solidLdoDataset.child("container/");
- * // Logs "https://example.com/container/"
- * console.log(container.uri);
- * const resource = container.child("resource.ttl");
- * // Logs "https://example.com/container/resource.ttl"
- * console.log(resource.uri);
- * ```
- */
- child(slug: ContainerUri): Container;
- child(slug: LeafUri): Leaf;
- child(slug: string): Leaf | Container;
- child(slug: string): Leaf | Container {
- return this.context.resourceStore.get(`${this.uri}${slug}`);
- }
-
- /**
- * ===========================================================================
- * CHILD CREATORS
- * ===========================================================================
- */
-
- /**
- * Creates a resource and overwrites any existing resource that existed at the
- * URI
- *
- * @param slug - the name of the resource
- * @return the result of creating that resource
- *
- * @example
- * ```typescript
- * const container = solidLdoDataset
- * .getResource("https://example.com/container/");
- * cosnt result = await container.createChildAndOverwrite("resource.ttl");
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- createChildAndOverwrite(
- slug: ContainerUri,
- ): Promise>;
- createChildAndOverwrite(
- slug: LeafUri,
- ): Promise>;
- createChildAndOverwrite(
- slug: string,
- ): Promise<
- ResourceResult<
- ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult,
- Leaf | Container
- >
- >;
- createChildAndOverwrite(
- slug: string,
- ): Promise<
- ResourceResult<
- ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult,
- Leaf | Container
- >
- > {
- return this.child(slug).createAndOverwrite();
- }
-
- /**
- * Creates a resource only if that resource doesn't already exist on the Solid
- * Pod
- *
- * @param slug - the name of the resource
- * @return the result of creating that resource
- *
- * @example
- * ```typescript
- * const container = solidLdoDataset
- * .getResource("https://example.com/container/");
- * cosnt result = await container.createChildIfAbsent("resource.ttl");
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- createChildIfAbsent(
- slug: ContainerUri,
- ): Promise>;
- createChildIfAbsent(
- slug: LeafUri,
- ): Promise>;
- createChildIfAbsent(
- slug: string,
- ): Promise<
- ResourceResult<
- ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult,
- Leaf | Container
- >
- >;
- createChildIfAbsent(
- slug: string,
- ): Promise<
- ResourceResult<
- ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult,
- Leaf | Container
- >
- > {
- return this.child(slug).createIfAbsent();
- }
-
- /**
- * Creates a new binary resource and overwrites any existing resource that
- * existed at the URI
- *
- * @param slug - the name of the resource
- * @return the result of creating that resource
- *
- * @example
- * ```typescript
- * const container = solidLdoDataset
- * .getResource("https://example.com/container/");
- * cosnt result = await container.uploadChildAndOverwrite(
- * "resource.txt",
- * new Blob("some text."),
- * "text/txt",
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async uploadChildAndOverwrite(
- slug: LeafUri,
- blob: Blob,
- mimeType: string,
- ): Promise> {
- return this.child(slug).uploadAndOverwrite(blob, mimeType);
- }
-
- /**
- * Creates a new binary resource and overwrites any existing resource that
- * existed at the URI
- *
- * @param slug - the name of the resource
- * @return the result of creating that resource
- *
- * @example
- * ```typescript
- * const container = solidLdoDataset
- * .getResource("https://example.com/container/");
- * cosnt result = await container.uploadChildIfAbsent(
- * "resource.txt",
- * new Blob("some text."),
- * "text/txt",
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async uploadChildIfAbsent(
- slug: LeafUri,
- blob: Blob,
- mimeType: string,
- ): Promise> {
- return this.child(slug).uploadIfAbsent(blob, mimeType);
- }
-
- /**
- * Deletes all contents in this container
- * @returns An AggregateSuccess or Aggregate error corresponding with all the
- * deleted resources
- *
- * @example
- * ```typescript
- * const result = container.clear();
- * if (!result.isError) {
- * console.log("All deleted resources:");
- * result.results.forEach((result) => console.log(result.uri));
- * }
- * ```
- */
- async clear(): Promise<
- ResourceResult<
- | AggregateSuccess>
- | AggregateError,
- Container
- >
- > {
- const readResult = await this.read();
- if (readResult.isError) return new AggregateError([readResult]);
- const results = (
- await Promise.all(
- this.children().map(async (child) => {
- return child.delete();
- }),
- )
- ).flat();
- const errors = results.filter(
- (
- value,
- ): value is
- | DeleteResultError
- | AggregateError => value.isError,
- );
- if (errors.length > 0) {
- return new AggregateError(errors);
- }
- return {
- isError: false,
- type: "aggregateSuccess",
- results: results as ResourceResult[],
- resource: this,
- };
- }
-
- /**
- * Deletes this container and all its contents
- * @returns A Delete result for this container
- *
- * ```typescript
- * const result = await container.delete();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async delete(): Promise<
- ResourceResult<
- DeleteResult | AggregateError,
- Container
- >
- > {
- const clearResult = await this.clear();
- if (clearResult.isError) return clearResult;
- const deleteResult = await this.handleDelete();
- if (deleteResult.isError) return deleteResult;
- return { ...deleteResult, resource: this };
- }
-
- /**
- * Creates a container at this URI and overwrites any that already exists
- * @returns ContainerCreateAndOverwriteResult
- *
- * @example
- * ```typescript
- * const result = await container.createAndOverwrite();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async createAndOverwrite(): Promise<
- ResourceResult
- > {
- const createResult =
- (await this.handleCreateAndOverwrite()) as ContainerCreateAndOverwriteResult;
- if (createResult.isError) return createResult;
- return { ...createResult, resource: this };
- }
-
- /**
- * Creates a container at this URI if the container doesn't already exist
- * @returns ContainerCreateIfAbsentResult
- *
- * @example
- * ```typescript
- * const result = await container.createIfAbsent();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async createIfAbsent(): Promise<
- ResourceResult
- > {
- const createResult =
- (await this.handleCreateIfAbsent()) as ContainerCreateIfAbsentResult;
- if (createResult.isError) return createResult;
- return { ...createResult, resource: this };
- }
-}
diff --git a/packages/solid/src/resource/Leaf.ts b/packages/solid/src/resource/Leaf.ts
deleted file mode 100644
index 7272f15..0000000
--- a/packages/solid/src/resource/Leaf.ts
+++ /dev/null
@@ -1,559 +0,0 @@
-import type { DatasetChanges } from "@ldo/rdf-utils";
-import type { Quad } from "@rdfjs/types";
-import { LeafBatchedRequester } from "../requester/LeafBatchedRequester";
-import type { CheckRootResultError } from "../requester/requests/checkRootContainer";
-import type {
- LeafCreateAndOverwriteResult,
- LeafCreateIfAbsentResult,
-} from "../requester/requests/createDataResource";
-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 type { AbsentReadSuccess } from "../requester/results/success/ReadSuccess";
-import type {
- BinaryReadSuccess,
- DataReadSuccess,
-} from "../requester/results/success/ReadSuccess";
-import type { ResourceSuccess } from "../requester/results/success/SuccessResult";
-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 { ResourceResult } from "./resourceResult/ResourceResult";
-import type { NoRootContainerError } from "../requester/results/error/NoRootContainerError";
-
-/**
- * Represents the current status of a specific Leaf on a Pod as known by LDO.
- *
- * @example
- * ```typescript
- * const leaf = solidLdoDataset
- * .getResource("https://example.com/container/resource.ttl");
- * ```
- */
-export class Leaf extends Resource {
- /**
- * The URI of the leaf
- */
- readonly uri: LeafUri;
-
- /**
- * @internal
- * Batched Requester for the Leaf
- */
- protected requester: LeafBatchedRequester;
-
- /**
- * Indicates that this resource is a leaf resource
- */
- readonly type = "leaf" as const;
-
- /**
- * Indicates that this resource is not an error
- */
- readonly isError = false as const;
-
- /**
- * The status of the last request made for this leaf
- */
- status:
- | SharedStatuses
- | ReadLeafResult
- | LeafCreateAndOverwriteResult
- | LeafCreateIfAbsentResult
- | UpdateResult;
-
- /**
- * @internal
- * The raw binary data if this leaf is a Binary resource
- */
- protected binaryData: { blob: Blob; mimeType: string } | undefined;
-
- /**
- * @param uri - The uri of the leaf
- * @param context - SolidLdoDatasetContext for the parent dataset
- */
- constructor(uri: LeafUri, context: SolidLdoDatasetContext) {
- super(context);
- const uriObject = new URL(uri);
- uriObject.hash = "";
- this.uri = uriObject.toString() as LeafUri;
- this.requester = new LeafBatchedRequester(uri, context);
- this.status = { isError: false, type: "unfetched", uri };
- }
-
- /**
- * ===========================================================================
- * GETTERS
- * ===========================================================================
- */
-
- /**
- * Checks to see if the resource is currently uploading data
- * @returns true if the current resource is uploading
- *
- * @example
- * ```typescript
- * leaf.uploadAndOverwrite(new Blob("some text"), "text/txt").then(() => {
- * // Logs "false"
- * console.log(leaf.isUploading())
- * });
- * // Logs "true"
- * console.log(leaf.isUploading());
- * ```
- */
- isUploading(): boolean {
- return this.requester.isUploading();
- }
-
- /**
- * Checks to see if the resource is currently updating data
- * @returns true if the current resource is updating
- *
- * @example
- * ```typescript
- * leaf.update(datasetChanges).then(() => {
- * // Logs "false"
- * console.log(leaf.isUpdating())
- * });
- * // Logs "true"
- * console.log(leaf.isUpdating());
- * ```
- */
- isUpdating(): boolean {
- return this.requester.isUpdating();
- }
-
- /**
- * If this resource is a binary resource, returns the mime type
- * @returns The mime type if this resource is a binary resource, undefined
- * otherwise
- *
- * @example
- * ```typescript
- * // Logs "text/txt"
- * console.log(leaf.getMimeType());
- * ```
- */
- getMimeType(): string | undefined {
- return this.binaryData?.mimeType;
- }
-
- /**
- * If this resource is a binary resource, returns the Blob
- * @returns The Blob if this resource is a binary resource, undefined
- * otherwise
- *
- * @example
- * ```typescript
- * // Logs "some text."
- * console.log(leaf.getBlob()?.toString());
- * ```
- */
- getBlob(): Blob | undefined {
- return this.binaryData?.blob;
- }
-
- /**
- * Check if this resource is a binary resource
- * @returns True if this resource is a binary resource, false if not,
- * undefined if unknown
- *
- * @example
- * ```typescript
- * // Logs "undefined"
- * console.log(leaf.isBinary());
- * const result = await leaf.read();
- * if (!result.isError) {
- * // Logs "true"
- * console.log(leaf.isBinary());
- * }
- * ```
- */
- isBinary(): boolean | undefined {
- if (!this.didInitialFetch) {
- return undefined;
- }
- return !!this.binaryData;
- }
-
- /**
- * Check if this resource is a data (RDF) resource
- * @returns True if this resource is a data resource, false if not, undefined
- * if unknown
- *
- * @example
- * ```typescript
- * // Logs "undefined"
- * console.log(leaf.isDataResource());
- * const result = await leaf.read();
- * if (!result.isError) {
- * // Logs "true"
- * console.log(leaf.isDataResource());
- * }
- * ```
- */
- isDataResource(): boolean | undefined {
- if (!this.didInitialFetch) {
- return undefined;
- }
- return !this.binaryData;
- }
-
- /**
- * ===========================================================================
- * READ METHODS
- * ===========================================================================
- */
-
- /**
- * @internal
- * A helper method updates this leaf's internal state upon read success
- * @param result - the result of the read success
- */
- protected updateWithReadSuccess(
- result: BinaryReadSuccess | DataReadSuccess | AbsentReadSuccess,
- ): void {
- super.updateWithReadSuccess(result);
- if (result.type === "binaryReadSuccess") {
- this.binaryData = { blob: result.blob, mimeType: result.mimeType };
- } else {
- this.binaryData = undefined;
- }
- }
-
- /**
- * Reads the leaf by making a request
- * @returns A read result
- *
- * @example
- * ```typescript
- * const result = await leaf.read();
- * if (result.isError) {
- * // Do something
- * }
- * ```
- */
- async read(): Promise> {
- const result = (await this.handleRead()) as ReadLeafResult;
- if (result.isError) return result;
- return { ...result, resource: this };
- }
-
- /**
- * @internal
- * Converts the current state of this leaf to a readResult
- * @returns a ReadLeafResult
- */
- protected toReadResult(): ResourceResult {
- if (this.isAbsent()) {
- return {
- isError: false,
- type: "absentReadSuccess",
- uri: this.uri,
- recalledFromMemory: true,
- resource: this,
- };
- } else if (this.isBinary()) {
- return {
- isError: false,
- type: "binaryReadSuccess",
- uri: this.uri,
- recalledFromMemory: true,
- blob: this.binaryData!.blob,
- mimeType: this.binaryData!.mimeType,
- resource: this,
- };
- } else {
- return {
- isError: false,
- type: "dataReadSuccess",
- uri: this.uri,
- recalledFromMemory: true,
- resource: this,
- };
- }
- }
-
- /**
- * Makes a request to read this leaf if it hasn't been fetched yet. If it has,
- * return the cached informtation
- * @returns a ReadLeafResult
- *
- * @example
- * ```typescript
- * const result = await leaf.read();
- * if (!result.isError) {
- * // Will execute without making a request
- * const result2 = await leaf.readIfUnfetched();
- * }
- * ```
- */
- async readIfUnfetched(): Promise> {
- return super.readIfUnfetched() as Promise<
- ResourceResult
- >;
- }
-
- /**
- * ===========================================================================
- * PARENT CONTAINER METHODS
- * ===========================================================================
- */
-
- /**
- * Gets the parent container for this leaf by making a request
- * @returns The parent container
- *
- * @example
- * ```typescript
- * const leaf = solidLdoDataset
- * .getResource("https://example.com/container/resource.ttl");
- * const leafParent = await leaf.getParentContainer();
- * if (!leafParent.isError) {
- * // Logs "https://example.com/container/"
- * console.log(leafParent.uri);
- * }
- * ```
- */
- async getParentContainer(): Promise {
- const parentUri = getParentUri(this.uri)!;
- return this.context.resourceStore.get(parentUri);
- }
-
- /**
- * Gets the root container for this leaf.
- * @returns The root container for this leaf
- *
- * @example
- * Suppose the root container is at `https://example.com/`
- *
- * ```typescript
- * const leaf = ldoSolidDataset
- * .getResource("https://example.com/container/resource.ttl");
- * const rootContainer = await leaf.getRootContainer();
- * if (!rootContainer.isError) {
- * // logs "https://example.com/"
- * console.log(rootContainer.uri);
- * }
- * ```
- */
- async getRootContainer(): Promise<
- Container | CheckRootResultError | NoRootContainerError
- > {
- // Check to see if this document has a pim:storage if so, use that
-
- // If not, traverse the tree
- const parent = await this.getParentContainer();
- return parent.getRootContainer();
- }
-
- /**
- * ===========================================================================
- * DELETE METHODS
- * ===========================================================================
- */
-
- /**
- * @internal
- * A helper method updates this leaf's internal state upon delete success
- * @param result - the result of the delete success
- */
- public updateWithDeleteSuccess(result: DeleteSuccess) {
- super.updateWithDeleteSuccess(result);
- this.binaryData = undefined;
- }
-
- /**
- * Deletes this leaf and all its contents
- * @returns A Delete result for this leaf
- *
- * ```typescript
- * const result = await container.leaf();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async delete(): Promise {
- return this.handleDelete();
- }
-
- /**
- * ===========================================================================
- * CREATE METHODS
- * ===========================================================================
- */
-
- /**
- * A helper method updates this leaf's internal state upon create success
- * @param _result - the result of the create success
- */
- protected updateWithCreateSuccess(_result: ResourceSuccess): void {
- this.binaryData = undefined;
- }
-
- /**
- * Creates a leaf at this URI and overwrites any that already exists
- * @returns LeafCreateAndOverwriteResult
- *
- * @example
- * ```typescript
- * const result = await leaf.createAndOverwrite();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async createAndOverwrite(): Promise<
- ResourceResult
- > {
- const createResult =
- (await this.handleCreateAndOverwrite()) as LeafCreateAndOverwriteResult;
- if (createResult.isError) return createResult;
- return { ...createResult, resource: this };
- }
-
- /**
- * Creates a leaf at this URI if the leaf doesn't already exist
- * @returns LeafCreateIfAbsentResult
- *
- * @example
- * ```typescript
- * const result = await leaf.createIfAbsent();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async createIfAbsent(): Promise<
- ResourceResult
- > {
- const createResult =
- (await this.handleCreateIfAbsent()) as LeafCreateIfAbsentResult;
- if (createResult.isError) return createResult;
- return { ...createResult, resource: this };
- }
-
- /**
- * ===========================================================================
- * UPLOAD METHODS
- * ===========================================================================
- */
-
- /**
- * Uploads a binary resource to this URI. If there is already a resource
- * present at this URI, it will be overwritten
- *
- * @param blob - the Blob of the binary
- * @param mimeType - the MimeType of the binary
- * @returns A LeafCreateAndOverwriteResult
- *
- * @example
- * ```typescript
- * const result = await leaf.uploadAndOverwrite(
- * new Blob("some text."),
- * "text/txt",
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async uploadAndOverwrite(
- blob: Blob,
- mimeType: string,
- ): Promise> {
- 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, resource: this };
- }
-
- /**
- * Uploads a binary resource to this URI tf there not is already a resource
- * present at this URI.
- *
- * @param blob - the Blob of the binary
- * @param mimeType - the MimeType of the binary
- * @returns A LeafCreateIfAbsentResult
- *
- * @example
- * ```typescript
- * const result = await leaf.uploadIfAbsent(
- * new Blob("some text."),
- * "text/txt",
- * );
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- async uploadIfAbsent(
- blob: Blob,
- mimeType: string,
- ): Promise> {
- 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, resource: this };
- }
-
- /**
- * ===========================================================================
- * UPDATE METHODS
- * ===========================================================================
- */
-
- /**
- * Updates a data resource with the changes provided
- * @param changes - Dataset changes that will be applied to the resoruce
- * @returns An UpdateResult
- *
- * @example
- * ```typescript
- * import {
- * updateDataResource,
- * transactionChanges,
- * changeData,
- * createSolidLdoDataset,
- * } from "@ldo/solid";
- *
- * //...
- *
- * // Get a Linked Data Object
- * const profile = solidLdoDataset
- * .usingType(ProfileShapeType)
- * .fromSubject("https://example.com/profile#me");
- * cosnt resource = solidLdoDataset
- * .getResource("https://example.com/profile");
- * // Create a transaction to change data
- * const cProfile = changeData(profile, resource);
- * cProfile.name = "John Doe";
- * // Get data in "DatasetChanges" form
- * const datasetChanges = transactionChanges(someLinkedDataObject);
- * // Use "update" to apply the changes
- * cosnt result = resource.update(datasetChanges);
- * ```
- */
- async update(
- changes: DatasetChanges,
- ): Promise> {
- 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, resource: this };
- }
-}
diff --git a/packages/solid/src/resource/Resource.ts b/packages/solid/src/resource/Resource.ts
deleted file mode 100644
index 79c6e1c..0000000
--- a/packages/solid/src/resource/Resource.ts
+++ /dev/null
@@ -1,834 +0,0 @@
-import type { SolidLdoDatasetContext } from "../SolidLdoDatasetContext";
-import type {
- ContainerCreateAndOverwriteResult,
- ContainerCreateIfAbsentResult,
- LeafCreateAndOverwriteResult,
- LeafCreateIfAbsentResult,
-} from "../requester/requests/createDataResource";
-import type {
- ReadContainerResult,
- ReadLeafResult,
-} from "../requester/requests/readResource";
-import type { BatchedRequester } from "../requester/BatchedRequester";
-import type { CheckRootResultError } from "../requester/requests/checkRootContainer";
-import type TypedEmitter from "typed-emitter";
-import EventEmitter from "events";
-import { getParentUri } from "../util/rdfUtils";
-import type { RequesterResult } from "../requester/results/RequesterResult";
-import {
- updateDatasetOnSuccessfulDelete,
- type DeleteResult,
-} from "../requester/requests/deleteResource";
-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 { ResourceResult } from "./resourceResult/ResourceResult";
-import type { Container } from "./Container";
-import type { Leaf } from "./Leaf";
-import type { WacRule } from "./wac/WacRule";
-import type { GetWacUriError, GetWacUriResult } from "./wac/getWacUri";
-import { getWacUri } from "./wac/getWacUri";
-import { getWacRuleWithAclUri, type GetWacRuleResult } from "./wac/getWacRule";
-import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
-import { setWacRuleForAclUri, type SetWacRuleResult } from "./wac/setWacRule";
-import type { LeafUri } from "../util/uriTypes";
-import type { NoRootContainerError } from "../requester/results/error/NoRootContainerError";
-import type {
- NotificationSubscription,
- SubscriptionCallbacks,
-} from "./notifications/NotificationSubscription";
-import { Websocket2023NotificationSubscription } from "./notifications/Websocket2023NotificationSubscription";
-import type { NotificationMessage } from "./notifications/NotificationMessage";
-
-/**
- * Statuses shared between both Leaf and Container
- */
-export type SharedStatuses = Unfetched | DeleteResult | CreateSuccess;
-
-/**
- * Represents the current status of a specific Resource on a Pod as known by LDO.
- */
-export abstract class Resource extends (EventEmitter as new () => TypedEmitter<{
- update: () => void;
- notification: () => void;
-}>) {
- /**
- * @internal
- * The SolidLdoDatasetContext from the Parent Dataset
- */
- protected readonly context: SolidLdoDatasetContext;
-
- /**
- * The uri of the resource
- */
- abstract readonly uri: string;
-
- /**
- * The type of resource (leaf or container)
- */
- abstract readonly type: string;
-
- /**
- * The status of the last request made for this resource
- */
- abstract status: RequesterResult;
-
- /**
- * @internal
- * Batched Requester for the Resource
- */
- protected abstract readonly requester: BatchedRequester;
-
- /**
- * @internal
- * True if this resource has been fetched at least once
- */
- protected didInitialFetch: boolean = false;
-
- /**
- * @internal
- * True if this resource has been fetched but does not exist
- */
- protected absent: boolean | undefined;
-
- /**
- * @internal
- * If a wac uri is fetched, it is cached here
- */
- protected wacUri?: LeafUri;
-
- /**
- * @internal
- * If a wac rule was fetched, it is cached here
- */
- protected wacRule?: WacRule;
-
- /**
- * @internal
- * Handles notification subscriptions
- */
- protected notificationSubscription: NotificationSubscription;
-
- /**
- * @param context - SolidLdoDatasetContext for the parent dataset
- */
- constructor(context: SolidLdoDatasetContext) {
- super();
- this.context = context;
- this.notificationSubscription = new Websocket2023NotificationSubscription(
- this,
- this.onNotification.bind(this),
- this.context,
- );
- }
-
- /**
- * ===========================================================================
- * GETTERS
- * ===========================================================================
- */
-
- /**
- * Checks to see if this resource is loading in any way
- * @returns true if the resource is currently loading
- *
- * @example
- * ```typescript
- * resource.read().then(() => {
- * // Logs "false"
- * console.log(resource.isLoading())
- * });
- * // Logs "true"
- * console.log(resource.isLoading());
- * ```
- */
- isLoading(): boolean {
- return this.requester.isLoading();
- }
-
- /**
- * Checks to see if this resource is being created
- * @returns true if the resource is currently being created
- *
- * @example
- * ```typescript
- * resource.read().then(() => {
- * // Logs "false"
- * console.log(resource.isCreating())
- * });
- * // Logs "true"
- * console.log(resource.isCreating());
- * ```
- */
- isCreating(): boolean {
- return this.requester.isCreating();
- }
-
- /**
- * Checks to see if this resource is being read
- * @returns true if the resource is currently being read
- *
- * @example
- * ```typescript
- * resource.read().then(() => {
- * // Logs "false"
- * console.log(resource.isReading())
- * });
- * // Logs "true"
- * console.log(resource.isReading());
- * ```
- */
- isReading(): boolean {
- return this.requester.isReading();
- }
-
- /**
- * Checks to see if this resource is being deleted
- * @returns true if the resource is currently being deleted
- *
- * @example
- * ```typescript
- * resource.read().then(() => {
- * // Logs "false"
- * console.log(resource.isDeleting())
- * });
- * // Logs "true"
- * console.log(resource.isDeleting());
- * ```
- */
- isDeleting(): boolean {
- return this.requester.isDeletinng();
- }
-
- /**
- * Checks to see if this resource is being read for the first time
- * @returns true if the resource is currently being read for the first time
- *
- * @example
- * ```typescript
- * resource.read().then(() => {
- * // Logs "false"
- * console.log(resource.isDoingInitialFetch())
- * });
- * // Logs "true"
- * console.log(resource.isDoingInitialFetch());
- * ```
- */
- isDoingInitialFetch(): boolean {
- return this.isReading() && !this.isFetched();
- }
-
- /**
- * Checks to see if this resource is being read for a subsequent time
- * @returns true if the resource is currently being read for a subsequent time
- *
- * @example
- * ```typescript
- * await resource.read();
- * resource.read().then(() => {
- * // Logs "false"
- * console.log(resource.isCreating())
- * });
- * // Logs "true"
- * console.log(resource.isCreating());
- * ```
- */
- isReloading(): boolean {
- return this.isReading() && this.isFetched();
- }
-
- /**
- * ===========================================================================
- * CHECKERS
- * ===========================================================================
- */
-
- /**
- * Check to see if this resource has been fetched
- * @returns true if this resource has been fetched before
- *
- * @example
- * ```typescript
- * // Logs "false"
- * console.log(resource.isFetched());
- * const result = await resource.read();
- * if (!result.isError) {
- * // Logs "true"
- * console.log(resource.isFetched());
- * }
- * ```
- */
- isFetched(): boolean {
- return this.didInitialFetch;
- }
-
- /**
- * Check to see if this resource is currently unfetched
- * @returns true if the resource is currently unfetched
- *
- * @example
- * ```typescript
- * // Logs "true"
- * console.log(resource.isUnetched());
- * const result = await resource.read();
- * if (!result.isError) {
- * // Logs "false"
- * console.log(resource.isUnfetched());
- * }
- * ```
- */
- isUnfetched(): boolean {
- return !this.didInitialFetch;
- }
-
- /**
- * Is this resource currently absent (it does not exist)
- * @returns true if the resource is absent, false if not, undefined if unknown
- *
- * @example
- * ```typescript
- * // Logs "undefined"
- * console.log(resource.isAbsent());
- * const result = await resource.read();
- * if (!result.isError) {
- * // False if the resource exists, true if it does not
- * console.log(resource.isAbsent());
- * }
- * ```
- */
- isAbsent(): boolean | undefined {
- return this.absent;
- }
-
- /**
- * Is this resource currently present on the Pod
- * @returns false if the resource is absent, true if not, undefined if unknown
- *
- * @example
- * ```typescript
- * // Logs "undefined"
- * console.log(resource.isPresent());
- * const result = await resource.read();
- * if (!result.isError) {
- * // True if the resource exists, false if it does not
- * console.log(resource.isPresent());
- * }
- * ```
- */
- isPresent(): boolean | undefined {
- return this.absent === undefined ? undefined : !this.absent;
- }
-
- /**
- * Is this resource currently listening to notifications from this document
- * @returns true if the resource is subscribed to notifications, false if not
- *
- * @example
- * ```typescript
- * await resource.subscribeToNotifications();
- * // Logs "true"
- * console.log(resource.isSubscribedToNotifications());
- * ```
- */
- isSubscribedToNotifications(): boolean {
- return this.notificationSubscription.isSubscribedToNotifications();
- }
-
- /**
- * ===========================================================================
- * HELPER METHODS
- * ===========================================================================
- */
-
- /**
- * @internal
- * Emits an update event for both this resource and the parent
- */
- protected emitThisAndParent() {
- this.emit("update");
- const parentUri = getParentUri(this.uri);
- if (parentUri) {
- const parentContainer = this.context.resourceStore.get(parentUri);
- parentContainer.emit("update");
- }
- }
-
- /**
- * ===========================================================================
- * READ METHODS
- * ===========================================================================
- */
-
- /**
- * @internal
- * A helper method updates this resource's internal state upon read success
- * @param result - the result of the read success
- */
- protected updateWithReadSuccess(result: ReadSuccess) {
- this.absent = result.type === "absentReadSuccess";
- this.didInitialFetch = true;
- }
-
- /**
- * @internal
- * A helper method that handles the core functions for reading
- * @returns ReadResult
- */
- protected async handleRead(): Promise {
- const result = await this.requester.read();
- this.status = result;
- if (result.isError) return result;
- this.updateWithReadSuccess(result);
- this.emitThisAndParent();
- return result;
- }
-
- /**
- * @internal
- * Converts the current state of this resource to a readResult
- * @returns a ReadResult
- */
- protected abstract toReadResult(): ResourceResult<
- ReadLeafResult | ReadContainerResult,
- Container | Leaf
- >;
-
- /**
- * Reads the resource
- */
- abstract read(): Promise<
- ResourceResult
- >;
-
- /**
- * Reads the resource if it isn't fetched yet
- * @returns a ReadResult
- */
- async readIfUnfetched(): Promise<
- ResourceResult
- > {
- if (this.didInitialFetch) {
- const readResult = this.toReadResult();
- this.status = readResult;
- return readResult;
- }
- return this.read();
- }
-
- /**
- * ===========================================================================
- * DELETE METHODS
- * ===========================================================================
- */
-
- /**
- * @internal
- * A helper method updates this resource's internal state upon delete success
- * @param result - the result of the delete success
- */
- public updateWithDeleteSuccess(_result: DeleteSuccess) {
- this.absent = true;
- this.didInitialFetch = true;
- }
-
- /**
- * @internal
- * Helper method that handles the core functions for deleting a resource
- * @returns DeleteResult
- */
- protected async handleDelete(): Promise {
- const result = await this.requester.delete();
- this.status = result;
- if (result.isError) return result;
- this.updateWithDeleteSuccess(result);
- this.emitThisAndParent();
- return result;
- }
-
- /**
- * ===========================================================================
- * CREATE METHODS
- * ===========================================================================
- */
-
- /**
- * A helper method updates this resource's internal state upon create success
- * @param _result - the result of the create success
- */
- protected updateWithCreateSuccess(result: ResourceSuccess) {
- this.absent = false;
- this.didInitialFetch = true;
- if (isReadSuccess(result)) {
- this.updateWithReadSuccess(result);
- }
- }
-
- /**
- * Creates a resource at this URI and overwrites any that already exists
- * @returns CreateAndOverwriteResult
- *
- * @example
- * ```typescript
- * const result = await resource.createAndOverwrite();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- abstract createAndOverwrite(): Promise<
- ResourceResult<
- ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult,
- Leaf | Container
- >
- >;
-
- /**
- * @internal
- * Helper method that handles the core functions for creating and overwriting
- * a resource
- * @returns DeleteResult
- */
- protected async handleCreateAndOverwrite(): Promise<
- ContainerCreateAndOverwriteResult | LeafCreateAndOverwriteResult
- > {
- const result = await this.requester.createDataResource(true);
- this.status = result;
- if (result.isError) return result;
- this.updateWithCreateSuccess(result);
- this.emitThisAndParent();
- return result;
- }
-
- /**
- * Creates a resource at this URI if the resource doesn't already exist
- * @returns CreateIfAbsentResult
- *
- * @example
- * ```typescript
- * const result = await leaf.createIfAbsent();
- * if (!result.isError) {
- * // Do something
- * }
- * ```
- */
- abstract createIfAbsent(): Promise<
- ResourceResult<
- ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult,
- Leaf | Container
- >
- >;
-
- /**
- * @internal
- * Helper method that handles the core functions for creating a resource if
- * absent
- * @returns DeleteResult
- */
- protected async handleCreateIfAbsent(): Promise<
- ContainerCreateIfAbsentResult | LeafCreateIfAbsentResult
- > {
- const result = await this.requester.createDataResource();
- this.status = result;
- if (result.isError) return result;
- this.updateWithCreateSuccess(result);
- this.emitThisAndParent();
- return result;
- }
-
- /**
- * ===========================================================================
- * PARENT CONTAINER METHODS
- * ===========================================================================
- */
-
- /**
- * Gets the root container for this resource.
- * @returns The root container for this resource
- *
- * @example
- * Suppose the root container is at `https://example.com/`
- *
- * ```typescript
- * const resource = ldoSolidDataset
- * .getResource("https://example.com/container/resource.ttl");
- * const rootContainer = await resource.getRootContainer();
- * if (!rootContainer.isError) {
- * // logs "https://example.com/"
- * console.log(rootContainer.uri);
- * }
- * ```
- */
- abstract getRootContainer(): Promise<
- Container | CheckRootResultError | NoRootContainerError
- >;
-
- abstract getParentContainer(): Promise<
- Container | CheckRootResultError | undefined
- >;
-
- /**
- * ===========================================================================
- * WEB ACCESS CONTROL METHODS
- * ===========================================================================
- */
-
- /**
- * Retrieves the URI for the web access control (WAC) rules for this resource
- * @param options - set the "ignoreCache" field to true to ignore any cached
- * information on WAC rules.
- * @returns WAC Rules results
- */
- protected async getWacUri(options?: {
- ignoreCache: boolean;
- }): Promise {
- // Get the wacUri if not already present
- if (!options?.ignoreCache && this.wacUri) {
- return {
- type: "getWacUriSuccess",
- wacUri: this.wacUri,
- isError: false,
- uri: this.uri,
- };
- }
-
- const wacUriResult = await getWacUri(this.uri, {
- fetch: this.context.fetch,
- });
- if (wacUriResult.isError) {
- return wacUriResult;
- }
- this.wacUri = wacUriResult.wacUri;
- return wacUriResult;
- }
-
- /**
- * Retrieves web access control (WAC) rules for this resource
- * @param options - set the "ignoreCache" field to true to ignore any cached
- * information on WAC rules.
- * @returns WAC Rules results
- *
- * @example
- * ```typescript
- * const resource = ldoSolidDataset
- * .getResource("https://example.com/container/resource.ttl");
- * const wacRulesResult = await resource.getWac();
- * if (!wacRulesResult.isError) {
- * const wacRules = wacRulesResult.wacRule;
- * // True if the resource is publicly readable
- * console.log(wacRules.public.read);
- * // True if authenticated agents can write to the resource
- * console.log(wacRules.authenticated.write);
- * // True if the given WebId has append access
- * console.log(
- * wacRules.agent[https://example.com/person1/profile/card#me].append
- * );
- * // True if the given WebId has control access
- * console.log(
- * wacRules.agent[https://example.com/person1/profile/card#me].control
- * );
- * }
- * ```
- */
- async getWac(options?: {
- ignoreCache: boolean;
- }): Promise {
- // Return the wac rule if it's already cached
- if (!options?.ignoreCache && this.wacRule) {
- return {
- type: "getWacRuleSuccess",
- uri: this.uri,
- isError: false,
- wacRule: this.wacRule,
- };
- }
-
- // Get the wac uri
- const wacUriResult = await this.getWacUri(options);
- if (wacUriResult.isError) return wacUriResult;
-
- // Get the wac rule
- const wacResult = await getWacRuleWithAclUri(wacUriResult.wacUri, {
- fetch: this.context.fetch,
- });
- if (wacResult.isError) return wacResult;
- // If the wac rules was successfully found
- if (wacResult.type === "getWacRuleSuccess") {
- this.wacRule = wacResult.wacRule;
- return wacResult;
- }
-
- // If the WacRule is absent
- const parentResource = await this.getParentContainer();
- if (parentResource?.isError) return parentResource;
- if (!parentResource) {
- return new NoncompliantPodError(
- this.uri,
- `Resource "${this.uri}" has no Effective ACL resource`,
- );
- }
- return parentResource.getWac();
- }
-
- /**
- * Sets access rules for a specific resource
- * @param wacRule - the access rules to set
- * @returns SetWacRuleResult
- *
- * @example
- * ```typescript
- * const resource = ldoSolidDataset
- * .getResource("https://example.com/container/resource.ttl");
- * const wacRulesResult = await resource.setWac({
- * public: {
- * read: true,
- * write: false,
- * append: false,
- * control: false
- * },
- * authenticated: {
- * read: true,
- * write: false,
- * append: true,
- * control: false
- * },
- * agent: {
- * "https://example.com/person1/profile/card#me": {
- * read: true,
- * write: true,
- * append: true,
- * control: true
- * }
- * }
- * });
- * ```
- */
- async setWac(wacRule: WacRule): Promise {
- const wacUriResult = await this.getWacUri();
- if (wacUriResult.isError) return wacUriResult;
-
- const result = await setWacRuleForAclUri(
- wacUriResult.wacUri,
- wacRule,
- this.uri,
- {
- fetch: this.context.fetch,
- },
- );
- if (result.isError) return result;
- this.wacRule = result.wacRule;
- return result;
- }
-
- /**
- * ===========================================================================
- * SUBSCRIPTION METHODS
- * ===========================================================================
- */
-
- /**
- * Activates Websocket subscriptions on this resource. Updates, deletions,
- * and creations on this resource will be tracked and all changes will be
- * relected in LDO's resources and graph.
- *
- * @param onNotificationError - A callback function if there is an error
- * with notifications.
- * @returns SubscriptionId: A string to use to unsubscribe
- *
- * @example
- * ```typescript
- * const resource = solidLdoDataset
- * .getResource("https://example.com/spiderman");
- * // A listener for if anything about spiderman in the global dataset is
- * // changed. Note that this will also listen for any local changes as well
- * // as changes to remote resources to which you have notification
- * // subscriptions enabled.
- * solidLdoDataset.addListener(
- * [namedNode("https://example.com/spiderman#spiderman"), null, null, null],
- * () => {
- * // Triggers when the file changes on the Pod or locally
- * console.log("Something changed about SpiderMan");
- * },
- * );
- *
- * // Subscribe
- * const subscriptionId = await testContainer.subscribeToNotifications({
- * // These are optional callbacks. A subscription will automatically keep
- * // the dataset in sync. Use these callbacks for additional functionality.
- * onNotification: (message) => console.log(message),
- * onNotificationError: (err) => console.log(err.message)
- * });
- * // ... From there you can wait for a file to be changed on the Pod.
- */
- async subscribeToNotifications(
- callbacks?: SubscriptionCallbacks,
- ): Promise {
- return await this.notificationSubscription.subscribeToNotifications(
- callbacks,
- );
- }
-
- /**
- * @internal
- * Function that triggers whenever a notification is recieved.
- */
- protected async onNotification(message: NotificationMessage): Promise {
- const objectResource = this.context.solidLdoDataset.getResource(
- message.object,
- );
- switch (message.type) {
- case "Update":
- case "Add":
- await objectResource.read();
- return;
- case "Delete":
- case "Remove":
- // Delete the resource without have to make an additional read request
- updateDatasetOnSuccessfulDelete(
- message.object,
- this.context.solidLdoDataset,
- );
- objectResource.updateWithDeleteSuccess({
- type: "deleteSuccess",
- isError: false,
- uri: message.object,
- resourceExisted: true,
- });
- return;
- }
- }
-
- /**
- * Unsubscribes from changes made to this resource on the Pod
- *
- * @returns UnsubscribeResult
- *
- * @example
- * ```typescript
- * const subscriptionId = await testContainer.subscribeToNotifications();
- * await testContainer.unsubscribeFromNotifications(subscriptionId);
- * ```
- */
- async unsubscribeFromNotifications(subscriptionId: string): Promise {
- return this.notificationSubscription.unsubscribeFromNotification(
- subscriptionId,
- );
- }
-
- /**
- * Unsubscribes from all notifications on this resource
- *
- * @returns UnsubscribeResult[]
- *
- * @example
- * ```typescript
- * const subscriptionResult = await testContainer.subscribeToNotifications();
- * await testContainer.unsubscribeFromAllNotifications();
- * ```
- */
- async unsubscribeFromAllNotifications(): Promise {
- return this.notificationSubscription.unsubscribeFromAllNotifications();
- }
-}
diff --git a/packages/solid/src/resource/notifications/NotificationMessage.ts b/packages/solid/src/resource/notifications/NotificationMessage.ts
deleted file mode 100644
index 14e5c2d..0000000
--- a/packages/solid/src/resource/notifications/NotificationMessage.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * A message sent from the Pod as a notification
- */
-export interface NotificationMessage {
- "@context": string | string[];
- id: string;
- type: "Update" | "Delete" | "Remove" | "Add";
- object: string;
- published: string;
-}
diff --git a/packages/solid/src/resource/notifications/NotificationSubscription.ts b/packages/solid/src/resource/notifications/NotificationSubscription.ts
deleted file mode 100644
index 4961075..0000000
--- a/packages/solid/src/resource/notifications/NotificationSubscription.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import type { SolidLdoDatasetContext } from "../../SolidLdoDatasetContext";
-import type { Resource } from "../Resource";
-import type { NotificationMessage } from "./NotificationMessage";
-import type { NotificationCallbackError } from "./results/NotificationErrors";
-import { v4 } from "uuid";
-
-export interface SubscriptionCallbacks {
- onNotification?: (message: NotificationMessage) => void;
- // TODO: make notification errors more specific
- onNotificationError?: (error: Error) => void;
-}
-
-/**
- * @internal
- * Abstract class for notification subscription methods.
- */
-export abstract class NotificationSubscription {
- protected resource: Resource;
- protected parentSubscription: (message: NotificationMessage) => void;
- protected context: SolidLdoDatasetContext;
- protected subscriptions: Record = {};
- private isOpen: boolean = false;
-
- constructor(
- resource: Resource,
- parentSubscription: (message: NotificationMessage) => void,
- context: SolidLdoDatasetContext,
- ) {
- this.resource = resource;
- this.parentSubscription = parentSubscription;
- this.context = context;
- }
-
- public isSubscribedToNotifications(): boolean {
- return this.isOpen;
- }
-
- /**
- * ===========================================================================
- * PUBLIC
- * ===========================================================================
- */
-
- /**
- * @internal
- * subscribeToNotifications
- */
- async subscribeToNotifications(
- subscriptionCallbacks?: SubscriptionCallbacks,
- ): Promise {
- const subscriptionId = v4();
- this.subscriptions[subscriptionId] = subscriptionCallbacks ?? {};
- if (!this.isOpen) {
- await this.open();
- this.setIsOpen(true);
- }
- return subscriptionId;
- }
-
- /**
- * @internal
- * unsubscribeFromNotification
- */
- async unsubscribeFromNotification(subscriptionId: string): Promise {
- if (
- !!this.subscriptions[subscriptionId] &&
- Object.keys(this.subscriptions).length === 1
- ) {
- await this.close();
- this.setIsOpen(false);
- }
- delete this.subscriptions[subscriptionId];
- }
-
- /**
- * @internal
- * unsubscribeFromAllNotifications
- */
- async unsubscribeFromAllNotifications(): Promise {
- await Promise.all(
- Object.keys(this.subscriptions).map((id) =>
- this.unsubscribeFromNotification(id),
- ),
- );
- }
-
- /**
- * ===========================================================================
- * HELPERS
- * ===========================================================================
- */
-
- /**
- * @internal
- * Opens the subscription
- */
- protected abstract open(): Promise;
-
- /**
- * @internal
- * Closes the subscription
- */
- protected abstract close(): Promise;
-
- /**
- * ===========================================================================
- * CALLBACKS
- * ===========================================================================
- */
-
- /**
- * @internal
- * onNotification
- */
- protected onNotification(message: NotificationMessage): void {
- this.parentSubscription(message);
- Object.values(this.subscriptions).forEach(({ onNotification }) => {
- onNotification?.(message);
- });
- }
-
- /**
- * @internal
- * onNotificationError
- */
- protected onNotificationError(message: NotificationCallbackError): void {
- Object.values(this.subscriptions).forEach(({ onNotificationError }) => {
- onNotificationError?.(message);
- });
- if (message.type === "disconnectedNotAttemptingReconnectError") {
- this.setIsOpen(false);
- }
- }
-
- /**
- * @internal
- * setIsOpen
- */
- protected setIsOpen(status: boolean) {
- const shouldUpdate = status !== this.isOpen;
- this.isOpen = status;
- if (shouldUpdate) this.resource.emit("update");
- }
-}
diff --git a/packages/solid/src/resource/notifications/Websocket2023NotificationSubscription.ts b/packages/solid/src/resource/notifications/Websocket2023NotificationSubscription.ts
deleted file mode 100644
index 80c51cd..0000000
--- a/packages/solid/src/resource/notifications/Websocket2023NotificationSubscription.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import { UnexpectedResourceError } from "../../requester/results/error/ErrorResult";
-import { NotificationSubscription } from "./NotificationSubscription";
-import { SubscriptionClient } from "@solid-notifications/subscription";
-import { WebSocket } from "ws";
-import {
- DisconnectedAttemptingReconnectError,
- DisconnectedNotAttemptingReconnectError,
- UnsupportedNotificationError,
-} from "./results/NotificationErrors";
-import type { NotificationMessage } from "./NotificationMessage";
-import type { Resource } from "../Resource";
-import type { SolidLdoDatasetContext } from "../../SolidLdoDatasetContext";
-import type {
- ChannelType,
- NotificationChannel,
-} from "@solid-notifications/types";
-
-const CHANNEL_TYPE =
- "http://www.w3.org/ns/solid/notifications#WebSocketChannel2023";
-
-export class Websocket2023NotificationSubscription extends NotificationSubscription {
- private socket: WebSocket | undefined;
- private createWebsocket: (address: string) => WebSocket;
-
- // Reconnection data
- // How often we should attempt a reconnection
- private reconnectInterval = 5000;
- // How many attempts have already been tried for a reconnection
- private reconnectAttempts = 0;
- // Whether or not the socket was manually closes
- private isManualClose = false;
- // Maximum number of attempts to reconnect
- private maxReconnectAttempts = 6;
-
- constructor(
- resource: Resource,
- parentSubscription: (message: NotificationMessage) => void,
- context: SolidLdoDatasetContext,
- createWebsocket?: (address: string) => WebSocket,
- ) {
- super(resource, parentSubscription, context);
- this.createWebsocket = createWebsocket ?? createWebsocketDefault;
- }
-
- async open(): Promise {
- try {
- const notificationChannel = await this.discoverNotificationChannel();
- await this.subscribeToWebsocket(notificationChannel);
- } catch (err) {
- if (
- err instanceof Error &&
- err.message.startsWith("Discovery did not succeed")
- ) {
- this.onNotificationError(
- new UnsupportedNotificationError(this.resource.uri, err.message),
- );
- } else {
- this.onNotificationError(
- UnexpectedResourceError.fromThrown(this.resource.uri, err),
- );
- }
- this.onClose();
- }
- }
-
- public async discoverNotificationChannel(): Promise {
- const client = new SubscriptionClient(this.context.fetch);
- return await client.subscribe(
- this.resource.uri,
- CHANNEL_TYPE as ChannelType,
- );
- }
-
- public async subscribeToWebsocket(
- notificationChannel: NotificationChannel,
- ): Promise {
- this.socket = this.createWebsocket(
- notificationChannel.receiveFrom as string,
- );
-
- this.socket.onopen = () => {
- this.reconnectAttempts = 0; // Reset attempts on successful connection
- this.isManualClose = false; // Reset manual close flag
- };
-
- this.socket.onmessage = (message) => {
- const messageData = message.data.toString();
- // TODO uncompliant Pod error on misformatted message
- this.onNotification(JSON.parse(messageData) as NotificationMessage);
- };
-
- this.socket.onclose = this.onClose.bind(this);
-
- this.socket.onerror = (err) => {
- this.onNotificationError(
- new UnexpectedResourceError(this.resource.uri, err.error),
- );
- };
- return;
- }
-
- private onClose() {
- if (!this.isManualClose) {
- // Attempt to reconnect only if the disconnection was unintentional
- if (this.reconnectAttempts < this.maxReconnectAttempts) {
- this.reconnectAttempts++;
- setTimeout(() => {
- this.open();
- }, this.reconnectInterval);
- this.onNotificationError(
- new DisconnectedAttemptingReconnectError(
- this.resource.uri,
- `Attempting to reconnect to Websocket for ${this.resource.uri}.`,
- ),
- );
- } else {
- this.onNotificationError(
- new DisconnectedNotAttemptingReconnectError(
- this.resource.uri,
- `Lost connection to websocket for ${this.resource.uri}.`,
- ),
- );
- }
- }
- }
-
- protected async close(): Promise {
- this.socket?.terminate();
- }
-}
-
-function createWebsocketDefault(address: string) {
- return new WebSocket(address);
-}
diff --git a/packages/solid/src/resource/notifications/results/NotificationErrors.ts b/packages/solid/src/resource/notifications/results/NotificationErrors.ts
deleted file mode 100644
index f196c86..0000000
--- a/packages/solid/src/resource/notifications/results/NotificationErrors.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type { UnexpectedResourceError } from "../../../requester/results/error/ErrorResult";
-import { ResourceError } from "../../../requester/results/error/ErrorResult";
-
-export type NotificationCallbackError =
- | DisconnectedAttemptingReconnectError
- | DisconnectedNotAttemptingReconnectError
- | UnsupportedNotificationError
- | UnexpectedResourceError;
-
-/**
- * Indicates that the requested method for receiving notifications is not
- * supported by this Pod.
- */
-export class UnsupportedNotificationError extends ResourceError {
- readonly type = "unsupportedNotificationError" as const;
-}
-
-/**
- * Indicates that the socket has disconnected and is attempting to reconnect.
- */
-export class DisconnectedAttemptingReconnectError extends ResourceError {
- readonly type = "disconnectedAttemptingReconnectError" as const;
-}
-
-/**
- * Indicates that the socket has disconnected and is attempting to reconnect.
- */
-export class DisconnectedNotAttemptingReconnectError extends ResourceError {
- readonly type = "disconnectedNotAttemptingReconnectError" as const;
-}
diff --git a/packages/solid/src/resource/resourceResult/ResourceResult.ts b/packages/solid/src/resource/resourceResult/ResourceResult.ts
deleted file mode 100644
index 3132fd1..0000000
--- a/packages/solid/src/resource/resourceResult/ResourceResult.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import type { RequesterResult } from "../../requester/results/RequesterResult";
-import type { Container } from "../Container";
-import type { Leaf } from "../Leaf";
-
-/**
- * Adds an additional field "resource" to SuccessResults.
- */
-export type ResourceSuccess<
- Result extends RequesterResult,
- ResourceType extends Leaf | Container,
-> = Result & { resource: ResourceType };
-
-/**
- * Adds an additional field "resource" to Results.
- */
-export type ResourceResult<
- Result extends RequesterResult,
- ResourceType extends Leaf | Container,
-> = Result extends Error ? Result : ResourceSuccess;
diff --git a/packages/solid/src/resource/wac/WacRule.ts b/packages/solid/src/resource/wac/WacRule.ts
deleted file mode 100644
index 150ed52..0000000
--- a/packages/solid/src/resource/wac/WacRule.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * A list of modes that a certain agent has access to
- */
-export interface AccessModeList {
- read: boolean;
- append: boolean;
- write: boolean;
- control: boolean;
-}
-
-/**
- * A list of modes for each kind of agent
- */
-export interface WacRule {
- public: AccessModeList;
- authenticated: AccessModeList;
- agent: Record;
-}
diff --git a/packages/solid/src/resource/wac/getWacRule.ts b/packages/solid/src/resource/wac/getWacRule.ts
deleted file mode 100644
index 3c2b68f..0000000
--- a/packages/solid/src/resource/wac/getWacRule.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-import type { GetWacRuleSuccess } from "./results/GetWacRuleSuccess";
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-import type { BasicRequestOptions } from "../../requester/requests/requestOptions";
-import type { HttpErrorResultType } from "../../requester/results/error/HttpErrorResult";
-import { HttpErrorResult } from "../../requester/results/error/HttpErrorResult";
-import type { NoncompliantPodError } from "../../requester/results/error/NoncompliantPodError";
-import type { UnexpectedResourceError } from "../../requester/results/error/ErrorResult";
-import { rawTurtleToDataset } from "../../util/rdfUtils";
-import { AuthorizationShapeType } from "../../.ldo/wac.shapeTypes";
-import type { AccessModeList, WacRule } from "./WacRule";
-import type { Authorization } from "../../.ldo/wac.typings";
-import type { WacRuleAbsent } from "./results/WacRuleAbsent";
-
-export type GetWacRuleError =
- | HttpErrorResultType
- | NoncompliantPodError
- | UnexpectedResourceError;
-export type GetWacRuleResult =
- | GetWacRuleSuccess
- | GetWacRuleError
- | WacRuleAbsent;
-
-/**
- * Given the URI of an ACL document, return the Web Access Control (WAC) rules
- * @param aclUri: The URI for the ACL document
- * @param options: Options object to include an authenticated fetch function
- * @returns GetWacRuleResult
- */
-export async function getWacRuleWithAclUri(
- aclUri: string,
- options?: BasicRequestOptions,
-): Promise {
- const fetch = guaranteeFetch(options?.fetch);
- const response = await fetch(aclUri);
- const errorResult = HttpErrorResult.checkResponse(aclUri, response);
- if (errorResult) return errorResult;
-
- if (response.status === 404) {
- return {
- type: "wacRuleAbsent",
- uri: aclUri,
- isError: false,
- };
- }
-
- // Parse Turtle
- const rawTurtle = await response.text();
- const rawTurtleResult = await rawTurtleToDataset(rawTurtle, aclUri);
- if (rawTurtleResult.isError) return rawTurtleResult;
- const dataset = rawTurtleResult.dataset;
- const authorizations = dataset
- .usingType(AuthorizationShapeType)
- .matchSubject(
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
- "http://www.w3.org/ns/auth/acl#Authorization",
- );
-
- const wacRule: WacRule = {
- public: {
- read: false,
- write: false,
- append: false,
- control: false,
- },
- authenticated: {
- read: false,
- write: false,
- append: false,
- control: false,
- },
- agent: {},
- };
-
- function applyAccessModesToList(
- accessModeList: AccessModeList,
- authorization: Authorization,
- ): void {
- authorization.mode?.forEach((mode) => {
- accessModeList[mode["@id"].toLowerCase()] = true;
- });
- }
-
- authorizations.forEach((authorization) => {
- if (
- authorization.agentClass?.some(
- (agentClass) => agentClass["@id"] === "Agent",
- )
- ) {
- applyAccessModesToList(wacRule.public, authorization);
- applyAccessModesToList(wacRule.authenticated, authorization);
- }
- if (
- authorization.agentClass?.some(
- (agentClass) => agentClass["@id"] === "AuthenticatedAgent",
- )
- ) {
- applyAccessModesToList(wacRule.authenticated, authorization);
- }
- authorization.agent?.forEach((agent) => {
- if (!wacRule.agent[agent["@id"]]) {
- wacRule.agent[agent["@id"]] = {
- read: false,
- write: false,
- append: false,
- control: false,
- };
- }
- applyAccessModesToList(wacRule.agent[agent["@id"]], authorization);
- });
- });
-
- return {
- type: "getWacRuleSuccess",
- uri: aclUri,
- isError: false,
- wacRule,
- };
-}
diff --git a/packages/solid/src/resource/wac/getWacUri.ts b/packages/solid/src/resource/wac/getWacUri.ts
deleted file mode 100644
index d402c8b..0000000
--- a/packages/solid/src/resource/wac/getWacUri.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import type { GetWacUriSuccess } from "./results/GetWacUriSuccess";
-import type { HttpErrorResultType } from "../../requester/results/error/HttpErrorResult";
-import {
- HttpErrorResult,
- NotFoundHttpError,
-} from "../../requester/results/error/HttpErrorResult";
-import { UnexpectedResourceError } from "../../requester/results/error/ErrorResult";
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-import type { BasicRequestOptions } from "../../requester/requests/requestOptions";
-import { NoncompliantPodError } from "../../requester/results/error/NoncompliantPodError";
-import { parse as parseLinkHeader } from "http-link-header";
-import type { LeafUri } from "../../util/uriTypes";
-
-export type GetWacUriError =
- | HttpErrorResultType
- | NotFoundHttpError
- | NoncompliantPodError
- | UnexpectedResourceError;
-export type GetWacUriResult = GetWacUriSuccess | GetWacUriError;
-
-/**
- * Get the URI for the WAC rules of a specific resource
- * @param resourceUri: the URI of the resource
- * @param options: Options object to include an authenticated fetch function
- * @returns GetWacUriResult
- */
-export async function getWacUri(
- resourceUri: string,
- options?: BasicRequestOptions,
-): Promise {
- try {
- const fetch = guaranteeFetch(options?.fetch);
- const response = await fetch(resourceUri, {
- method: "head",
- });
- const errorResult = HttpErrorResult.checkResponse(resourceUri, response);
- if (errorResult) return errorResult;
- if (NotFoundHttpError.is(response)) {
- return new NotFoundHttpError(
- resourceUri,
- response,
- "Could not get access control rules because the resource does not exist.",
- );
- }
- // Get the URI from the link header
- const linkHeader = response.headers.get("link");
- if (!linkHeader) {
- return new NoncompliantPodError(
- resourceUri,
- "No link header present in request.",
- );
- }
- const parsedLinkHeader = parseLinkHeader(linkHeader);
- const aclUris = parsedLinkHeader.get("rel", "acl");
- if (aclUris.length !== 1) {
- return new NoncompliantPodError(
- resourceUri,
- `There must be one link with a rel="acl"`,
- );
- }
- return {
- type: "getWacUriSuccess",
- isError: false,
- uri: resourceUri,
- wacUri: aclUris[0].uri as LeafUri,
- };
- } catch (err: unknown) {
- return UnexpectedResourceError.fromThrown(resourceUri, err);
- }
-}
diff --git a/packages/solid/src/resource/wac/results/GetWacRuleSuccess.ts b/packages/solid/src/resource/wac/results/GetWacRuleSuccess.ts
deleted file mode 100644
index 4dd17b6..0000000
--- a/packages/solid/src/resource/wac/results/GetWacRuleSuccess.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult";
-import type { WacRule } from "../WacRule";
-
-/**
- * Returned when a WAC rule is successfully retrieved
- */
-export interface GetWacRuleSuccess extends ResourceSuccess {
- type: "getWacRuleSuccess";
- /**
- * The rule that was retrieved
- */
- wacRule: WacRule;
-}
diff --git a/packages/solid/src/resource/wac/results/GetWacUriSuccess.ts b/packages/solid/src/resource/wac/results/GetWacUriSuccess.ts
deleted file mode 100644
index 3694d9f..0000000
--- a/packages/solid/src/resource/wac/results/GetWacUriSuccess.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult";
-import type { LeafUri } from "../../../util/uriTypes";
-
-/**
- * Returned when the URI for a resources ACL document was successfully retried
- */
-export interface GetWacUriSuccess extends ResourceSuccess {
- type: "getWacUriSuccess";
- /**
- * The URI of the ACL document
- */
- wacUri: LeafUri;
-}
diff --git a/packages/solid/src/resource/wac/results/SetWacRuleSuccess.ts b/packages/solid/src/resource/wac/results/SetWacRuleSuccess.ts
deleted file mode 100644
index a79b928..0000000
--- a/packages/solid/src/resource/wac/results/SetWacRuleSuccess.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult";
-import type { WacRule } from "../WacRule";
-
-/**
- * Returned when rules were successfully written
- */
-export interface SetWacRuleSuccess extends ResourceSuccess {
- type: "setWacRuleSuccess";
- /**
- * The written rule
- */
- wacRule: WacRule;
-}
diff --git a/packages/solid/src/resource/wac/results/WacRuleAbsent.ts b/packages/solid/src/resource/wac/results/WacRuleAbsent.ts
deleted file mode 100644
index 7bec46a..0000000
--- a/packages/solid/src/resource/wac/results/WacRuleAbsent.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { ResourceSuccess } from "../../../requester/results/success/SuccessResult";
-
-/**
- * Returned if no WAC rule was returned from the server
- */
-export interface WacRuleAbsent extends ResourceSuccess {
- type: "wacRuleAbsent";
-}
diff --git a/packages/solid/src/resource/wac/setWacRule.ts b/packages/solid/src/resource/wac/setWacRule.ts
deleted file mode 100644
index 1569cb7..0000000
--- a/packages/solid/src/resource/wac/setWacRule.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import { createLdoDataset } from "@ldo/ldo";
-import type { BasicRequestOptions } from "../../requester/requests/requestOptions";
-import type { UnexpectedResourceError } from "../../requester/results/error/ErrorResult";
-import {
- HttpErrorResult,
- type HttpErrorResultType,
-} from "../../requester/results/error/HttpErrorResult";
-import { isContainerUri, type LeafUri } from "../../util/uriTypes";
-import type { AccessModeList, WacRule } from "./WacRule";
-import type { SetWacRuleSuccess } from "./results/SetWacRuleSuccess";
-import type { Authorization } from "../../.ldo/wac.typings";
-import { AuthorizationShapeType } from "../../.ldo/wac.shapeTypes";
-import { v4 } from "uuid";
-import { guaranteeFetch } from "../../util/guaranteeFetch";
-
-export type SetWacRuleError = HttpErrorResultType | UnexpectedResourceError;
-export type SetWacRuleResult = SetWacRuleSuccess | SetWacRuleError;
-
-/**
- * Given the URI of an ACL document and some WAC rules, set the WAC rules of
- * that document
- * @param aclUri: The URI for the ACL document
- * @param newRule: A new WAC rule to set. This will overwrite old rules
- * @param accessTo: The document this rule refers to
- * @param options: Options object to include an authenticated fetch function
- * @returns SetWacRuleResult
- */
-export async function setWacRuleForAclUri(
- aclUri: LeafUri,
- newRule: WacRule,
- accessTo: string,
- options?: BasicRequestOptions,
-): Promise {
- const fetch = guaranteeFetch(options?.fetch);
- // The rule map keeps track of all the rules that are currently being used
- // so that similar rules can be grouped together
- const ruleMap: Record = {};
- // The dataset that will eventually be sent to the Pod
- const dataset = createLdoDataset();
-
- // Helper function to add rules to the dataset by grouping them in the ruleMap
- function addRuleToDataset(
- type: "public" | "authenticated" | "agent",
- accessModeList: AccessModeList,
- agentId?: string,
- ) {
- const accessModeListHash = hashAccessModeList(accessModeList);
- // No need to add if all access is false
- if (accessModeListHash === "") return;
- if (!ruleMap[accessModeListHash]) {
- const authorization = dataset
- .usingType(AuthorizationShapeType)
- .fromSubject(`${aclUri}#${v4()}`);
- authorization.type = { "@id": "Authorization" };
- if (accessModeList.read) authorization.mode?.add({ "@id": "Read" });
- if (accessModeList.write) authorization.mode?.add({ "@id": "Write" });
- if (accessModeList.append) authorization.mode?.add({ "@id": "Append" });
- if (accessModeList.control) authorization.mode?.add({ "@id": "Control" });
- authorization.accessTo = { "@id": accessTo };
- if (isContainerUri(accessTo)) {
- authorization.default = { "@id": accessTo };
- }
- ruleMap[accessModeListHash] = authorization;
- }
- const authorization = ruleMap[accessModeListHash];
- // Add agents to the rule
- if (type === "public") {
- authorization.agentClass?.add({ "@id": "Agent" });
- } else if (type === "authenticated") {
- authorization.agentClass?.add({ "@id": "AuthenticatedAgent" });
- } else if (type === "agent" && agentId) {
- authorization.agent?.add({ "@id": agentId });
- }
- }
-
- // Add each rule to the dataset
- addRuleToDataset("public", newRule.public);
- addRuleToDataset("authenticated", newRule.authenticated);
- Object.entries(newRule.agent).forEach(([agentUri, accessModeList]) => {
- addRuleToDataset("agent", accessModeList, agentUri);
- });
-
- // Save to Pod
- const response = await fetch(aclUri, {
- method: "PUT",
- headers: {
- "content-type": "text/turtle",
- },
- body: dataset.toString(),
- });
- const errorResult = HttpErrorResult.checkResponse(aclUri, response);
- if (errorResult) return errorResult;
-
- return {
- type: "setWacRuleSuccess",
- uri: aclUri,
- isError: false,
- wacRule: newRule,
- };
-}
-
-// Hashes the access mode list for use in the rule map
-function hashAccessModeList(list: AccessModeList): string {
- return Object.entries(list).reduce(
- (agg, [key, isPresent]) => (isPresent ? agg + key : agg),
- "",
- );
-}
diff --git a/packages/solid/src/types.ts b/packages/solid/src/types.ts
deleted file mode 100644
index 91141ea..0000000
--- a/packages/solid/src/types.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { ILdoDataset } from "@ldo/ldo";
-import type { ResourceGetterOptions } from "./ResourceStore";
-import type { Container } from "./resource/Container";
-import type { Leaf } from "./resource/Leaf";
-import type { ContainerUri, LeafUri } from "./util/uriTypes";
-import type { SolidLdoTransactionDataset } from "./SolidLdoTransactionDataset";
-
-/**
- * A SolidLdoDataset provides methods for getting Solid resources.
- */
-export interface ISolidLdoDataset extends ILdoDataset {
- startTransaction(): SolidLdoTransactionDataset;
-
- getResource(uri: ContainerUri, options?: ResourceGetterOptions): Container;
- getResource(uri: LeafUri, options?: ResourceGetterOptions): Leaf;
- getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container;
- getResource(uri: string, options?: ResourceGetterOptions): Leaf | Container;
-}
diff --git a/packages/solid/src/util/RequestBatcher.ts b/packages/solid/src/util/RequestBatcher.ts
deleted file mode 100644
index 4528ec1..0000000
--- a/packages/solid/src/util/RequestBatcher.ts
+++ /dev/null
@@ -1,187 +0,0 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
-export interface WaitingProcess {
- name: string;
- args: Args;
- perform: (...args: Args) => Promise;
- awaitingResolutions: ((returnValue: Return) => void)[];
- awaitingRejections: ((err: any) => void)[];
- after?: (result: Return) => void;
-}
-
-export const ANY_KEY = "any";
-
-/**
- * Options for processes that are waiting to execute
- */
-export interface WaitingProcessOptions {
- /**
- * The name of the process like "read" or "delete"
- */
- name: string;
- /**
- * The arguements supplied to the process
- */
- args: Args;
- /**
- * A function that will be triggered when it's time to execute this process
- * @param args - arguments supplied to the process
- * @returns a return type
- */
- perform: (...args: Args) => Promise;
- /**
- * A custom function to modify the queue based on the current state of the
- * queue
- * @param processQueue - The current process queue
- * @param currentlyProcessing - The Process that is currently executing
- * @param args - provided args
- * @returns A WaitingProcess that this request should listen to, or undefined
- * if it should create its own
- */
- modifyQueue: (
- processQueue: WaitingProcess[],
- currentlyProcessing: WaitingProcess | undefined,
- args: Args,
- ) => WaitingProcess | undefined;
- after?: (result: Return) => void;
-}
-
-/**
- * @internal
- * A utility for batching a request
- */
-export class RequestBatcher {
- /**
- * A mapping between a process key and the last time in UTC a process of that
- * key was executed.
- */
- private lastRequestTimestampMap: Record = {};
-
- /**
- * A pointer to the current process the batcher is working on
- */
- private currentlyProcessing: WaitingProcess | undefined =
- undefined;
-
- /**
- * A queue of upcoming processes
- */
- private processQueue: WaitingProcess[] = [];
-
- /**
- * The amount of time (in milliseconds) between requests of the same key
- */
- public batchMillis: number;
-
- /**
- * @param options - options, including the value for batchMillis
- */
- constructor(
- options?: Partial<{
- batchMillis: number;
- }>,
- ) {
- this.batchMillis = options?.batchMillis || 1000;
- }
-
- /**
- * Check if the request batcher is currently working on a process
- * @param key - the key of the process to check
- * @returns true if the batcher is currently working on the provided process
- */
- public isLoading(key: string): boolean {
- if (key === ANY_KEY) return !!this.currentlyProcessing;
- return this.currentlyProcessing?.name === key;
- }
-
- /**
- * Triggers the next process in the queue or triggers a timeout to wait to
- * execute the next process in the queue if not enough time has passed since
- * the last process was triggered.
- */
- private triggerOrWaitProcess() {
- if (!this.processQueue[0] || this.currentlyProcessing) {
- return;
- }
- this.currentlyProcessing = this.processQueue.shift();
- const processName = this.currentlyProcessing!.name;
-
- // Set last request timestamp if not available
- if (!this.lastRequestTimestampMap[processName]) {
- this.lastRequestTimestampMap[processName] = Date.UTC(0, 0, 0, 0, 0, 0, 0);
- }
-
- const lastRequestTimestamp = this.lastRequestTimestampMap[processName];
- const timeSinceLastTrigger = Date.now() - lastRequestTimestamp;
-
- const triggerProcess = async () => {
- this.lastRequestTimestampMap[processName] = Date.now();
- this.lastRequestTimestampMap[ANY_KEY] = Date.now();
- // Remove the process from the queue
- const processToTrigger = this.currentlyProcessing;
- if (processToTrigger) {
- this.currentlyProcessing = processToTrigger;
- try {
- const returnValue = await processToTrigger.perform(
- ...processToTrigger.args,
- );
- if (processToTrigger.after) {
- processToTrigger.after(returnValue);
- }
- processToTrigger.awaitingResolutions.forEach((callback) => {
- callback(returnValue);
- });
- } catch (err) {
- processToTrigger.awaitingRejections.forEach((callback) => {
- callback(err);
- });
- }
- this.currentlyProcessing = undefined;
-
- this.triggerOrWaitProcess();
- }
- };
-
- if (timeSinceLastTrigger < this.batchMillis) {
- setTimeout(triggerProcess, this.batchMillis - timeSinceLastTrigger);
- } else {
- triggerProcess();
- }
- }
-
- /**
- * Adds a process to the queue and waits for the process to be complete
- * @param options - WaitingProcessOptions
- * @returns A promise that resolves when the process resolves
- */
- public async queueProcess(
- options: WaitingProcessOptions,
- ): Promise {
- return new Promise((resolve, reject) => {
- const shouldAwait = options.modifyQueue(
- this.processQueue,
- this.currentlyProcessing,
- options.args,
- );
-
- if (shouldAwait) {
- shouldAwait.awaitingResolutions.push(resolve);
- shouldAwait.awaitingRejections.push(reject);
- return;
- }
-
- const waitingProcess: WaitingProcess = {
- name: options.name,
- args: options.args,
- perform: options.perform,
- awaitingResolutions: [resolve],
- awaitingRejections: [reject],
- after: options.after,
- };
- // HACK: Ugly cast
- this.processQueue.push(
- waitingProcess as unknown as WaitingProcess,
- );
- this.triggerOrWaitProcess();
- });
- }
-}
diff --git a/packages/solid/src/util/guaranteeFetch.ts b/packages/solid/src/util/guaranteeFetch.ts
deleted file mode 100644
index 987b7b4..0000000
--- a/packages/solid/src/util/guaranteeFetch.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import crossFetch from "cross-fetch";
-
-/**
- * @internal
- * Guantees that some kind of fetch is available
- *
- * @param fetchInput - A potential fetch object
- * @returns a proper fetch object. Cross-fetch is default
- */
-export function guaranteeFetch(fetchInput?: typeof fetch): typeof fetch {
- return fetchInput || crossFetch;
-}
diff --git a/packages/solid/src/util/rdfUtils.ts b/packages/solid/src/util/rdfUtils.ts
deleted file mode 100644
index d10a737..0000000
--- a/packages/solid/src/util/rdfUtils.ts
+++ /dev/null
@@ -1,149 +0,0 @@
-import type { LdoDataset } from "@ldo/ldo";
-import { parseRdf } from "@ldo/ldo";
-import { namedNode, quad as createQuad } from "@rdfjs/data-model";
-import type { Dataset } from "@rdfjs/types";
-import type { ContainerUri } from "./uriTypes";
-import { isContainerUri } from "./uriTypes";
-import { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
-import { UnexpectedResourceError } from "../requester/results/error/ErrorResult";
-
-export const ldpContains = namedNode("http://www.w3.org/ns/ldp#contains");
-export const rdfType = namedNode(
- "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
-);
-export const ldpResource = namedNode("http://www.w3.org/ns/ldp#Resource");
-export const ldpContainer = namedNode("http://www.w3.org/ns/ldp#Container");
-export const ldpBasicContainer = namedNode(
- "http://www.w3.org/ns/ldp#BasicContainer",
-);
-
-/**
- * @internal
- * Gets the URI of a parent according the the Solid Spec
- *
- * @param uri - the child URI
- * @returns A parent URI or undefined if not possible
- */
-export function getParentUri(uri: string): ContainerUri | undefined {
- const urlObject = new URL(uri);
- const pathItems = urlObject.pathname.split("/");
- if (
- pathItems.length < 2 ||
- (pathItems.length === 2 && pathItems[1].length === 0)
- ) {
- return undefined;
- }
- if (pathItems[pathItems.length - 1] === "") {
- pathItems.pop();
- }
- pathItems.pop();
- urlObject.pathname = `${pathItems.join("/")}/`;
- return urlObject.toString() as ContainerUri;
-}
-
-/**
- * @internal
- * Gets the slug (last part of the path) for a given URI
- *
- * @param uri - the full URI
- * @returns the slug of the URI
- */
-export function getSlug(uri: string): string {
- const urlObject = new URL(uri);
- const pathItems = urlObject.pathname.split("/");
- return pathItems[pathItems.length - 1] || pathItems[pathItems.length - 2];
-}
-
-/**
- * @internal
- * Deletes mention of a resource from the provided dataset
- *
- * @param resourceUri - the resource to delete
- * @param dataset - dataset to modify
- */
-export function deleteResourceRdfFromContainer(
- resourceUri: string,
- dataset: Dataset,
-) {
- const parentUri = getParentUri(resourceUri);
- if (parentUri) {
- const parentNode = namedNode(parentUri);
- const resourceNode = namedNode(resourceUri);
- dataset.delete(
- createQuad(parentNode, ldpContains, resourceNode, parentNode),
- );
- dataset.deleteMatches(resourceNode, undefined, undefined, parentNode);
- }
-}
-
-/**
- * @internal
- * Adds a resource to a container in an RDF dataset
- *
- * @param resourceUri - the resource to add
- * @param dataset - the dataset to modify
- */
-export function addResourceRdfToContainer(
- resourceUri: string,
- dataset: Dataset,
-) {
- const parentUri = getParentUri(resourceUri);
- if (parentUri) {
- const parentNode = namedNode(parentUri);
- const resourceNode = namedNode(resourceUri);
- dataset.add(createQuad(parentNode, ldpContains, resourceNode, parentNode));
- dataset.add(createQuad(resourceNode, rdfType, ldpResource, parentNode));
- if (isContainerUri(resourceUri)) {
- dataset.add(
- createQuad(resourceNode, rdfType, ldpBasicContainer, parentNode),
- );
- dataset.add(createQuad(resourceNode, rdfType, ldpContainer, parentNode));
- }
- addResourceRdfToContainer(parentUri, dataset);
- }
-}
-
-/**
- * @internal
- * Adds raw turtle to the provided dataset
- * @param rawTurtle - String of raw turtle
- * @param dataset - the dataset to modify
- * @param baseUri - base URI to parsing turtle
- * @returns Undefined if successful, noncompliantPodError if not
- */
-export async function addRawTurtleToDataset(
- rawTurtle: string,
- dataset: Dataset,
- baseUri: string,
-): Promise {
- const rawTurtleResult = await rawTurtleToDataset(rawTurtle, baseUri);
- if (rawTurtleResult.isError) return rawTurtleResult;
- const loadedDataset = rawTurtleResult.dataset;
- const graphNode = namedNode(baseUri);
- // Destroy all triples that were once a part of this resouce
- dataset.deleteMatches(undefined, undefined, undefined, graphNode);
- // Add the triples from the fetched item
- dataset.addAll(
- loadedDataset.map((quad) =>
- createQuad(quad.subject, quad.predicate, quad.object, graphNode),
- ),
- );
-}
-
-export async function rawTurtleToDataset(
- rawTurtle: string,
- baseUri: string,
-): Promise<{ isError: false; dataset: LdoDataset } | NoncompliantPodError> {
- try {
- const loadedDataset = await parseRdf(rawTurtle, {
- baseIRI: baseUri,
- });
- return { isError: false, dataset: loadedDataset };
- } catch (err) {
- const error = UnexpectedResourceError.fromThrown(baseUri, err);
- return new NoncompliantPodError(
- baseUri,
- `Request returned noncompliant turtle: ${error.message}\n${rawTurtle}`,
- );
- }
-}
diff --git a/packages/solid/src/util/splitChangesByGraph.ts b/packages/solid/src/util/splitChangesByGraph.ts
deleted file mode 100644
index 007253f..0000000
--- a/packages/solid/src/util/splitChangesByGraph.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import { createDataset } from "@ldo/dataset";
-import type { GraphNode, DatasetChanges } from "@ldo/rdf-utils";
-import type { Quad } from "@rdfjs/types";
-import { defaultGraph, namedNode, quad as createQuad } from "@rdfjs/data-model";
-
-/**
- * @internal
- * Converts an RDFJS Graph Node to a string hash
- * @param graphNode - the node to convert
- * @returns a unique string corresponding to the node
- */
-export function graphNodeToString(graphNode: GraphNode): string {
- return graphNode.termType === "DefaultGraph"
- ? "defaultGraph()"
- : graphNode.value;
-}
-
-/**
- * @internal
- * Converts a unique string to a GraphNode
- * @param input - the unique string
- * @returns A graph node
- */
-export function stringToGraphNode(input: string): GraphNode {
- return input === "defaultGraph()" ? defaultGraph() : namedNode(input);
-}
-
-/**
- * Splits all changes in a DatasetChanges into individual DatasetChanges grouped
- * by the quad graph.
- * @param changes - Changes to split
- * @returns A map between the quad graph and the changes associated with that
- * graph
- */
-export function splitChangesByGraph(
- changes: DatasetChanges,
-): Map> {
- const changesMap: Record> = {};
- changes.added?.forEach((quad) => {
- const graphHash = graphNodeToString(quad.graph as GraphNode);
- if (!changesMap[graphHash]) {
- changesMap[graphHash] = {};
- }
- if (!changesMap[graphHash].added) {
- changesMap[graphHash].added = createDataset();
- }
- changesMap[graphHash].added?.add(
- createQuad(quad.subject, quad.predicate, quad.object, quad.graph),
- );
- });
-
- changes.removed?.forEach((quad) => {
- const graphHash = graphNodeToString(quad.graph as GraphNode);
- if (!changesMap[graphHash]) {
- changesMap[graphHash] = {};
- }
- if (!changesMap[graphHash].removed) {
- changesMap[graphHash].removed = createDataset();
- }
- changesMap[graphHash].removed?.add(
- createQuad(quad.subject, quad.predicate, quad.object, quad.graph),
- );
- });
-
- const finalMap = new Map>();
- Object.entries(changesMap).forEach(([key, value]) => {
- finalMap.set(stringToGraphNode(key), value);
- });
- return finalMap;
-}
diff --git a/packages/solid/src/util/uriTypes.ts b/packages/solid/src/util/uriTypes.ts
deleted file mode 100644
index aa15152..0000000
--- a/packages/solid/src/util/uriTypes.ts
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- * A LeafUri is any URI that has a pahtname that ends in a "/". It represents a
- * container.
- */
-// The & {} allows for alias preservation
-// eslint-disable-next-line @typescript-eslint/ban-types
-export type ContainerUri = `${string}/${NonPathnameEnding}` & {};
-
-/**
- * A LeafUri is any URI that does not have a pahtname that ends in a "/". It
- * represents a data resource or a binary resource. Not a container.
- */
-export type LeafUri =
- // The & {} allows for alias preservation
- // eslint-disable-next-line @typescript-eslint/ban-types
- `${string}${EveryLegalPathnameCharacterOtherThanSlash}${NonPathnameEnding}` & {};
-
-/**
- * Checks if a provided string is a Container URI
- * @param uri - the string to check
- * @returns true if the string is a container URI
- */
-export function isContainerUri(uri: string): uri is ContainerUri {
- const url = new URL(uri);
- return url.pathname.endsWith("/");
-}
-
-/**
- * Checks if a provided string is a leaf URI
- * @param uri - the string to check
- * @returns true if the string is a leaf URI
- */
-export function isLeafUri(uri: string): uri is LeafUri {
- return !isContainerUri(uri);
-}
-
-/**
- * @internal
- */
-type NonPathnameEnding = "" | `?${string}` | `#${string}`;
-
-/**
- * @internal
- */
-type EveryLegalPathnameCharacterOtherThanSlash =
- | "A"
- | "B"
- | "C"
- | "D"
- | "E"
- | "F"
- | "G"
- | "H"
- | "I"
- | "J"
- | "K"
- | "L"
- | "M"
- | "N"
- | "O"
- | "P"
- | "Q"
- | "R"
- | "S"
- | "T"
- | "U"
- | "V"
- | "W"
- | "X"
- | "Y"
- | "Z"
- | "a"
- | "b"
- | "c"
- | "d"
- | "e"
- | "f"
- | "g"
- | "h"
- | "i"
- | "j"
- | "k"
- | "l"
- | "m"
- | "n"
- | "o"
- | "p"
- | "q"
- | "r"
- | "s"
- | "t"
- | "u"
- | "v"
- | "w"
- | "x"
- | "y"
- | "z"
- | "1"
- | "2"
- | "3"
- | "4"
- | "5"
- | "6"
- | "7"
- | "8"
- | "9"
- | "0"
- | "-"
- | "."
- | "_"
- | "~"
- | ":"
- | "["
- | "]"
- | "@"
- | "!"
- | "$"
- | "&"
- | "'"
- | "("
- | ")"
- | "*"
- | "+"
- | ","
- | ";"
- | "=";
diff --git a/packages/solid/test/.ldo/post.context.ts b/packages/solid/test/.ldo/post.context.ts
deleted file mode 100644
index dafbe33..0000000
--- a/packages/solid/test/.ldo/post.context.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { ContextDefinition } from "jsonld";
-
-/**
- * =============================================================================
- * postContext: JSONLD Context for post
- * =============================================================================
- */
-export const postContext: ContextDefinition = {
- type: {
- "@id": "@type",
- },
- SocialMediaPosting: "http://schema.org/SocialMediaPosting",
- CreativeWork: "http://schema.org/CreativeWork",
- Thing: "http://schema.org/Thing",
- articleBody: {
- "@id": "http://schema.org/articleBody",
- "@type": "http://www.w3.org/2001/XMLSchema#string",
- },
- uploadDate: {
- "@id": "http://schema.org/uploadDate",
- "@type": "http://www.w3.org/2001/XMLSchema#date",
- },
- image: {
- "@id": "http://schema.org/image",
- "@type": "@id",
- },
- publisher: {
- "@id": "http://schema.org/publisher",
- "@type": "@id",
- },
-};
diff --git a/packages/solid/test/.ldo/post.schema.ts b/packages/solid/test/.ldo/post.schema.ts
deleted file mode 100644
index 39e8b63..0000000
--- a/packages/solid/test/.ldo/post.schema.ts
+++ /dev/null
@@ -1,155 +0,0 @@
-import { Schema } from "shexj";
-
-/**
- * =============================================================================
- * postSchema: ShexJ Schema for post
- * =============================================================================
- */
-export const postSchema: Schema = {
- type: "Schema",
- shapes: [
- {
- id: "https://example.com/PostSh",
- type: "ShapeDecl",
- shapeExpr: {
- type: "Shape",
- expression: {
- type: "EachOf",
- expressions: [
- {
- type: "TripleConstraint",
- predicate: "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
- valueExpr: {
- type: "NodeConstraint",
- values: [
- "http://schema.org/SocialMediaPosting",
- "http://schema.org/CreativeWork",
- "http://schema.org/Thing",
- ],
- },
- },
- {
- type: "TripleConstraint",
- predicate: "http://schema.org/articleBody",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#string",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#label",
- object: {
- value: "articleBody",
- },
- },
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "The actual body of the article. ",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://schema.org/uploadDate",
- valueExpr: {
- type: "NodeConstraint",
- datatype: "http://www.w3.org/2001/XMLSchema#date",
- },
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#label",
- object: {
- value: "uploadDate",
- },
- },
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value:
- "Date when this media object was uploaded to this site.",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://schema.org/image",
- valueExpr: {
- type: "NodeConstraint",
- nodeKind: "iri",
- },
- min: 0,
- max: 1,
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#label",
- object: {
- value: "image",
- },
- },
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value:
- "A media object that encodes this CreativeWork. This property is a synonym for encoding.",
- },
- },
- ],
- },
- {
- type: "TripleConstraint",
- predicate: "http://schema.org/publisher",
- valueExpr: {
- type: "NodeConstraint",
- nodeKind: "iri",
- },
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#label",
- object: {
- value: "publisher",
- },
- },
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value: "The publisher of the creative work.",
- },
- },
- ],
- },
- ],
- },
- annotations: [
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#label",
- object: {
- value: "SocialMediaPost",
- },
- },
- {
- type: "Annotation",
- predicate: "http://www.w3.org/2000/01/rdf-schema#comment",
- object: {
- value:
- "A post to a social media platform, including blog posts, tweets, Facebook posts, etc.",
- },
- },
- ],
- },
- },
- ],
-};
diff --git a/packages/solid/test/.ldo/post.shapeTypes.ts b/packages/solid/test/.ldo/post.shapeTypes.ts
deleted file mode 100644
index 4c50683..0000000
--- a/packages/solid/test/.ldo/post.shapeTypes.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { ShapeType } from "@ldo/ldo";
-import { postSchema } from "./post.schema";
-import { postContext } from "./post.context";
-import { PostSh } from "./post.typings";
-
-/**
- * =============================================================================
- * LDO ShapeTypes post
- * =============================================================================
- */
-
-/**
- * PostSh ShapeType
- */
-export const PostShShapeType: ShapeType = {
- schema: postSchema,
- shape: "https://example.com/PostSh",
- context: postContext,
-};
diff --git a/packages/solid/test/.ldo/post.typings.ts b/packages/solid/test/.ldo/post.typings.ts
deleted file mode 100644
index 9ebaf71..0000000
--- a/packages/solid/test/.ldo/post.typings.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { ContextDefinition } from "jsonld";
-
-/**
- * =============================================================================
- * Typescript Typings for post
- * =============================================================================
- */
-
-/**
- * PostSh Type
- */
-export interface PostSh {
- "@id"?: string;
- "@context"?: ContextDefinition;
- type:
- | {
- "@id": "SocialMediaPosting";
- }
- | {
- "@id": "CreativeWork";
- }
- | {
- "@id": "Thing";
- };
- /**
- * The actual body of the article.
- */
- articleBody?: string;
- /**
- * Date when this media object was uploaded to this site.
- */
- uploadDate: string;
- /**
- * A media object that encodes this CreativeWork. This property is a synonym for encoding.
- */
- image?: {
- "@id": string;
- };
- /**
- * The publisher of the creative work.
- */
- publisher: {
- "@id": string;
- };
-}
diff --git a/packages/solid/test/ErrorResult.test.ts b/packages/solid/test/ErrorResult.test.ts
deleted file mode 100644
index 50da070..0000000
--- a/packages/solid/test/ErrorResult.test.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-import {
- AggregateError,
- ErrorResult,
- ResourceError,
- UnexpectedResourceError,
-} from "../src/requester/results/error/ErrorResult";
-import { InvalidUriError } from "../src/requester/results/error/InvalidUriError";
-
-describe("ErrorResult", () => {
- describe("fromThrown", () => {
- it("returns an UnexpecteResourceError if a string is provided", () => {
- expect(
- UnexpectedResourceError.fromThrown("https://example.com/", "hello")
- .message,
- ).toBe("hello");
- });
-
- it("returns an UnexpecteResourceError if an odd valud is provided", () => {
- expect(
- UnexpectedResourceError.fromThrown("https://example.com/", 5).message,
- ).toBe("Error of type number thrown: 5");
- });
- });
-
- describe("AggregateError", () => {
- it("flattens aggregate errors provided to the constructor", () => {
- const err1 = UnexpectedResourceError.fromThrown("https://abc.com", "1");
- const err2 = UnexpectedResourceError.fromThrown("https://abc.com", "2");
- const err3 = UnexpectedResourceError.fromThrown("https://abc.com", "3");
- const err4 = UnexpectedResourceError.fromThrown("https://abc.com", "4");
- const aggErr1 = new AggregateError([err1, err2]);
- const aggErr2 = new AggregateError([err3, err4]);
- const finalAgg = new AggregateError([aggErr1, aggErr2]);
- expect(finalAgg.errors.length).toBe(4);
- });
- });
-
- describe("default messages", () => {
- class ConcreteResourceError extends ResourceError {
- readonly type = "concreteResourceError" as const;
- }
- class ConcreteErrorResult extends ErrorResult {
- readonly type = "concreteErrorResult" as const;
- }
-
- it("ResourceError fallsback to a default message if none is provided", () => {
- expect(new ConcreteResourceError("https://example.com/").message).toBe(
- "An unkown error for https://example.com/",
- );
- });
-
- it("ErrorResult fallsback to a default message if none is provided", () => {
- expect(new ConcreteErrorResult().message).toBe(
- "An unkown error was encountered.",
- );
- });
-
- it("InvalidUriError fallsback to a default message if none is provided", () => {
- expect(new InvalidUriError("https://example.com/").message).toBe(
- "https://example.com/ is an invalid uri.",
- );
- });
- });
-});
diff --git a/packages/solid/test/Integration.test.ts b/packages/solid/test/Integration.test.ts
deleted file mode 100644
index 4c63a19..0000000
--- a/packages/solid/test/Integration.test.ts
+++ /dev/null
@@ -1,2264 +0,0 @@
-import type { App } from "@solid/community-server";
-import type {
- Container,
- ContainerUri,
- Leaf,
- LeafUri,
- SolidLdoDataset,
- UpdateResultError,
-} from "../src";
-import {
- changeData,
- commitData,
- createSolidLdoDataset,
- SolidLdoTransactionDataset,
-} from "../src";
-import { ROOT_CONTAINER, WEB_ID, createApp } from "./solidServer.helper";
-import {
- namedNode,
- quad as createQuad,
- literal,
- defaultGraph,
-} from "@rdfjs/data-model";
-import type { CreateSuccess } from "../src/requester/results/success/CreateSuccess";
-import type { AggregateSuccess } from "../src/requester/results/success/SuccessResult";
-import type {
- IgnoredInvalidUpdateSuccess,
- UpdateDefaultGraphSuccess,
- UpdateSuccess,
-} from "../src/requester/results/success/UpdateSuccess";
-import type {
- ResourceResult,
- ResourceSuccess,
-} from "../src/resource/resourceResult/ResourceResult";
-import type {
- AggregateError,
- UnexpectedResourceError,
-} from "../src/requester/results/error/ErrorResult";
-import type { InvalidUriError } from "../src/requester/results/error/InvalidUriError";
-import { Buffer } from "buffer";
-import { PostShShapeType } from "./.ldo/post.shapeTypes";
-import type {
- ServerHttpError,
- UnauthenticatedHttpError,
- UnexpectedHttpError,
-} from "../src/requester/results/error/HttpErrorResult";
-import type { NoncompliantPodError } from "../src/requester/results/error/NoncompliantPodError";
-import type { GetWacRuleSuccess } from "../src/resource/wac/results/GetWacRuleSuccess";
-import type { WacRule } from "../src/resource/wac/WacRule";
-import type { GetStorageContainerFromWebIdSuccess } from "../src/requester/results/success/CheckRootContainerSuccess";
-import { generateAuthFetch } from "./authFetch.helper";
-import { wait } from "./utils.helper";
-import fs from "fs/promises";
-import path from "path";
-
-const TEST_CONTAINER_SLUG = "test_ldo/";
-const TEST_CONTAINER_URI =
- `${ROOT_CONTAINER}${TEST_CONTAINER_SLUG}` as ContainerUri;
-const SAMPLE_DATA_URI = `${TEST_CONTAINER_URI}sample.ttl` as LeafUri;
-const SAMPLE2_DATA_SLUG = "sample2.ttl";
-const SAMPLE2_DATA_URI = `${TEST_CONTAINER_URI}${SAMPLE2_DATA_SLUG}` as LeafUri;
-const SAMPLE_BINARY_URI = `${TEST_CONTAINER_URI}sample.txt` as LeafUri;
-const SAMPLE2_BINARY_SLUG = `sample2.txt`;
-const SAMPLE2_BINARY_URI =
- `${TEST_CONTAINER_URI}${SAMPLE2_BINARY_SLUG}` as LeafUri;
-const SAMPLE_CONTAINER_URI =
- `${TEST_CONTAINER_URI}sample_container/` as ContainerUri;
-const SAMPLE_PROFILE_URI = `${TEST_CONTAINER_URI}profile.ttl` as LeafUri;
-const SPIDER_MAN_TTL = `@base .
-@prefix rdf: .
-@prefix rdfs: .
-@prefix foaf: .
-@prefix rel: .
-
-<#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 .`;
-const TEST_CONTAINER_TTL = `@prefix dc: .
-@prefix ldp: .
-@prefix posix: .
-@prefix xsd: .
-
-<> "sample.txt";
- a ldp:Container, ldp:BasicContainer, ldp:Resource;
- dc:modified "2023-10-20T13:57:14.000Z"^^xsd:dateTime.
- a ldp:Resource, ;
- dc:modified "2023-10-20T13:57:14.000Z"^^xsd:dateTime.
- a ldp:Resource, ;
- dc:modified "2023-10-20T13:57:14.000Z"^^xsd:dateTime.
-<> posix:mtime 1697810234;
- ldp:contains , .
- posix:mtime 1697810234;
- posix:size 522.
- posix:mtime 1697810234;
- posix:size 10.`;
-const TEST_CONTAINER_ACL_URI = `${TEST_CONTAINER_URI}.acl`;
-const TEST_CONTAINER_ACL = `<#b30e3fd1-b5a8-4763-ad9d-e95de9cf7933> a ;
- <${TEST_CONTAINER_URI}>;
- <${TEST_CONTAINER_URI}>;
- , , , ;
- <${WEB_ID}>;
- , .`;
-const SAMPLE_PROFILE_TTL = `
-@prefix pim: .
-
-<${SAMPLE_PROFILE_URI}> pim:storage , .
-`;
-
-async function testRequestLoads(
- request: () => Promise,
- loadingResource: Leaf | Container,
- loadingValues: Partial<{
- isLoading: boolean;
- isCreating: boolean;
- isReading: boolean;
- isUploading: boolean;
- isReloading: boolean;
- isDeleting: boolean;
- isUpdating: boolean;
- isDoingInitialFetch: boolean;
- }>,
-): Promise {
- const allLoadingValues = {
- isLoading: false,
- isCreating: false,
- isReading: false,
- isUploading: false,
- isReloading: false,
- isDeleting: false,
- isUpdating: false,
- isDoingInitialFetch: false,
- ...loadingValues,
- };
- const [returnVal] = await Promise.all([
- request(),
- (async () => {
- Object.entries(allLoadingValues).forEach(([key, value]) => {
- if (
- loadingResource.type === "container" &&
- (key === "isUploading" || key === "isUpdating")
- ) {
- return;
- }
- expect(loadingResource[key]()).toBe(value);
- });
- })(),
- ]);
- return returnVal;
-}
-
-describe("Integration", () => {
- let app: App;
- let authFetch: typeof fetch;
- let fetchMock: jest.Mock<
- Promise,
- [input: RequestInfo | URL, init?: RequestInit | undefined]
- >;
- let solidLdoDataset: SolidLdoDataset;
-
- let previousJestId: string | undefined;
- let previousNodeEnv: string | undefined;
- beforeAll(async () => {
- // Remove Jest ID so that community solid server doesn't use the Jest Import
- previousJestId = process.env.JEST_WORKER_ID;
- previousNodeEnv = process.env.NODE_ENV;
- delete process.env.JEST_WORKER_ID;
- process.env.NODE_ENV = "other_test";
- // Start up the server
- app = await createApp();
- await app.start();
-
- authFetch = await generateAuthFetch();
- });
-
- afterAll(async () => {
- app.stop();
- process.env.JEST_WORKER_ID = previousJestId;
- process.env.NODE_ENV = previousNodeEnv;
- const testDataPath = path.join(__dirname, "./data");
- await fs.rm(testDataPath, { recursive: true, force: true });
- });
-
- beforeEach(async () => {
- fetchMock = jest.fn(authFetch);
- solidLdoDataset = createSolidLdoDataset({ fetch: fetchMock });
- // Create a new document called sample.ttl
- await authFetch(ROOT_CONTAINER, {
- method: "POST",
- headers: {
- link: '; rel="type"',
- slug: TEST_CONTAINER_SLUG,
- },
- });
- await authFetch(TEST_CONTAINER_ACL_URI, {
- method: "PUT",
- headers: {
- "content-type": "text/turtle",
- },
- body: TEST_CONTAINER_ACL,
- });
- await Promise.all([
- authFetch(TEST_CONTAINER_URI, {
- method: "POST",
- headers: { "content-type": "text/turtle", slug: "sample.ttl" },
- body: SPIDER_MAN_TTL,
- }),
- authFetch(TEST_CONTAINER_URI, {
- method: "POST",
- headers: { "content-type": "text/plain", slug: "sample.txt" },
- body: "some text.",
- }),
- authFetch(TEST_CONTAINER_URI, {
- method: "POST",
- headers: { "content-type": "text/turtle", slug: "profile.ttl" },
- body: SAMPLE_PROFILE_TTL,
- }),
- ]);
- });
-
- afterEach(async () => {
- await Promise.all([
- authFetch(SAMPLE_DATA_URI, {
- method: "DELETE",
- }),
- authFetch(SAMPLE2_DATA_URI, {
- method: "DELETE",
- }),
- authFetch(SAMPLE_BINARY_URI, {
- method: "DELETE",
- }),
- authFetch(SAMPLE2_BINARY_URI, {
- method: "DELETE",
- }),
- authFetch(SAMPLE_PROFILE_URI, {
- method: "DELETE",
- }),
- authFetch(SAMPLE_CONTAINER_URI, {
- method: "DELETE",
- }),
- ]);
- await authFetch(TEST_CONTAINER_URI, {
- method: "DELETE",
- });
- });
-
- /**
- * General
- */
- describe("General", () => {
- it("Does not include the hash when creating a resource", () => {
- const resource = solidLdoDataset.getResource(
- "https://example.com/thing#hash",
- );
- expect(resource.uri).toBe("https://example.com/thing");
- });
- });
-
- /**
- * Read
- */
- describe("read", () => {
- it("Reads a data leaf", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.type).toBe("dataReadSuccess");
- expect(
- solidLdoDataset.match(
- namedNode("http://example.org/#spiderman"),
- namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
- namedNode("http://example.org/#green-goblin"),
- ).size,
- ).toBe(1);
- expect(resource.isBinary()).toBe(false);
- expect(resource.isDataResource()).toBe(true);
- expect(resource.isPresent()).toBe(true);
- });
-
- it("Auto reads a resource", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI, {
- autoLoad: true,
- });
- // Wait until the resource is auto-loaded
- await new Promise((resolve) => {
- const interval = setInterval(() => {
- if (!resource.isReading()) {
- clearInterval(interval);
- resolve();
- }
- }, 250);
- });
- expect(
- solidLdoDataset.match(
- namedNode("http://example.org/#spiderman"),
- namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
- namedNode("http://example.org/#green-goblin"),
- ).size,
- ).toBe(1);
- });
-
- it("Reads a container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.type).toBe("containerReadSuccess");
- expect(resource.children().length).toBe(3);
- });
-
- it("Reads a binary leaf", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_BINARY_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.type).toBe("binaryReadSuccess");
- expect(resource.isBinary()).toBe(true);
- expect(await resource.getBlob()?.text()).toBe("some text.");
- });
-
- it("Returns an absent result if the document doesn't exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.type).toBe("absentReadSuccess");
- if (result.type !== "absentReadSuccess") return;
- expect(result.resource.isAbsent()).toBe(true);
- });
-
- it("Returns an ServerError when an 500 error is returned", async () => {
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 }));
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
-
- it("Returns an Unauthorized error if a 403 error is returned", async () => {
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 403 }));
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(true);
- expect(result.type).toBe("unauthorizedError");
- });
-
- it("Returns an UnauthenticatedError on an 401 error is returned", async () => {
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 401 }));
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(true);
- expect(result.type).toBe("unauthenticatedError");
- });
-
- it("Returns an UnexpectedHttpError on a strange number error is returned", async () => {
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 3942 }));
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(true);
- expect(result.type).toBe("unexpectedHttpError");
- });
-
- it("Returns a NoncompliantPod error when no content type is returned", async () => {
- fetchMock.mockResolvedValueOnce(
- new Response(undefined, { status: 200, headers: {} }),
- );
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(true);
- if (!result.isError) return;
- expect(result.type).toBe("noncompliantPodError");
- expect(result.message).toMatch(
- /\Response from .* is not compliant with the Solid Specification: Resource requests must return a content-type header\./,
- );
- });
-
- it("Returns a NoncompliantPod error if invalid turtle is provided", async () => {
- fetchMock.mockResolvedValueOnce(
- new Response("Error", {
- status: 200,
- headers: new Headers({ "content-type": "text/turtle" }),
- }),
- );
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(true);
- if (!result.isError) return;
- expect(result.type).toBe("noncompliantPodError");
- expect(result.message).toMatch(
- /\Response from .* is not compliant with the Solid Specification: Request returned noncompliant turtle: Unexpected "Error" on line 1\./,
- );
- });
-
- it("Parses Turtle even when the content type contains parameters", async () => {
- fetchMock.mockResolvedValueOnce(
- new Response(SPIDER_MAN_TTL, {
- status: 200,
- headers: new Headers({ "content-type": "text/turtle;charset=utf-8" }),
- }),
- );
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(false);
- if (result.isError) return;
- expect(result.type).toBe("dataReadSuccess");
- });
-
- it("Returns an UnexpectedResourceError if an unknown error is triggered", async () => {
- fetchMock.mockRejectedValueOnce(new Error("Something happened."));
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const result = await testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(true);
- if (!result.isError) return;
- expect(result.type).toBe("unexpectedResourceError");
- expect(result.message).toBe("Something happened.");
- });
-
- it("Does not return 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 testRequestLoads(() => resource.read(), resource, {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- });
- expect(result.isError).toBe(false);
- if (result.isError) return;
- expect(result.resource.isRootContainer()).toBe(false);
- });
-
- it("knows nothing about a leaf resource if it is not fetched", () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- expect(resource.isBinary()).toBe(undefined);
- expect(resource.isDataResource()).toBe(undefined);
- expect(resource.isUnfetched()).toBe(true);
- expect(resource.isPresent()).toBe(undefined);
- });
-
- it("batches the read request when a read request is currently happening", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const [result, result1] = await Promise.all([
- resource.read(),
- resource.read(),
- ]);
-
- expect(fetchMock).toHaveBeenCalledTimes(1);
- expect(result.type).toBe("dataReadSuccess");
- expect(result1.type).toBe("dataReadSuccess");
- });
-
- it("batches the read request when a read request is in queue", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const [, result, result1] = await Promise.all([
- resource.createAndOverwrite(),
- resource.read(),
- resource.read(),
- ]);
-
- expect(fetchMock).toHaveBeenCalledTimes(3);
- expect(result.type).toBe("dataReadSuccess");
- expect(result1.type).toBe("dataReadSuccess");
- });
- });
-
- /**
- * readIfUnfetched
- */
- describe("readIfUnfetched", () => {
- it("reads an unfetched container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () => resource.readIfUnfetched(),
- resource,
- {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- },
- );
- expect(result.type).toBe("containerReadSuccess");
- expect(resource.children().length).toBe(3);
- });
-
- it("reads an unfetched leaf", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const result = await testRequestLoads(
- () => resource.readIfUnfetched(),
- resource,
- {
- isLoading: true,
- isReading: true,
- isDoingInitialFetch: true,
- },
- );
- expect(result.type).toBe("dataReadSuccess");
- expect(
- solidLdoDataset.match(
- namedNode("http://example.org/#spiderman"),
- namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
- namedNode("http://example.org/#green-goblin"),
- ).size,
- ).toBe(1);
- });
-
- it("returns a cached existing container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- await resource.read();
- fetchMock.mockClear();
- const result = await resource.readIfUnfetched();
- expect(fetchMock).not.toHaveBeenCalled();
- expect(result.type).toBe("containerReadSuccess");
- expect(resource.children().length).toBe(3);
- });
-
- it("returns a cached existing data leaf", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- await resource.read();
- fetchMock.mockClear();
- const result = await resource.readIfUnfetched();
- expect(result.type).toBe("dataReadSuccess");
- expect(
- solidLdoDataset.match(
- namedNode("http://example.org/#spiderman"),
- namedNode("http://www.perceive.net/schemas/relationship/enemyOf"),
- namedNode("http://example.org/#green-goblin"),
- ).size,
- ).toBe(1);
- });
-
- it("returns a cached existing binary leaf", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_BINARY_URI);
- await resource.read();
- fetchMock.mockClear();
- const result = await resource.readIfUnfetched();
- expect(result.type).toBe("binaryReadSuccess");
- });
-
- it("returns a cached absent container", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_CONTAINER_URI);
- await resource.read();
- fetchMock.mockClear();
- const result = await resource.readIfUnfetched();
- expect(fetchMock).not.toHaveBeenCalled();
- expect(result.type).toBe("absentReadSuccess");
- });
-
- it("returns a cached absent leaf", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- await resource.read();
- fetchMock.mockClear();
- const result = await resource.readIfUnfetched();
- expect(fetchMock).not.toHaveBeenCalled();
- expect(result.type).toBe("absentReadSuccess");
- });
- });
-
- /**
- * 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);
- expect(result.isRootContainer()).toBe(true);
- });
-
- it("Returns an error if there is no root container", async () => {
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 200,
- headers: new Headers({ "content-type": "text/turtle" }),
- }),
- );
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 200,
- headers: new Headers({ "content-type": "text/turtle" }),
- }),
- );
- 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("noRootContainerError");
- expect(result.message).toMatch(/\.* has not root container\./);
- });
-
- 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.");
- });
-
- it("returns a NonCompliantPodError when there is no root", async () => {
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 200,
- headers: new Headers({
- "content-type": "text/turtle",
- link: '; rel="type"',
- }),
- }),
- );
- const resource = solidLdoDataset.getResource(ROOT_CONTAINER);
- const result = await resource.getRootContainer();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("noRootContainerError");
- });
- });
-
- /**
- * Get Storage From WebId
- */
- describe("getStorageFromWebId", () => {
- it("Gets storage when a pim:storage field isn't present", async () => {
- const result = await solidLdoDataset.getStorageFromWebId(SAMPLE_DATA_URI);
- expect(result.type).toBe("getStorageContainerFromWebIdSuccess");
- const realResult = result as GetStorageContainerFromWebIdSuccess;
- expect(realResult.storageContainers.length).toBe(1);
- expect(realResult.storageContainers[0].uri).toBe(ROOT_CONTAINER);
- });
-
- it("Gets storage when a pim:storage field is present", async () => {
- const result =
- await solidLdoDataset.getStorageFromWebId(SAMPLE_PROFILE_URI);
- expect(result.type).toBe("getStorageContainerFromWebIdSuccess");
- const realResult = result as GetStorageContainerFromWebIdSuccess;
- expect(realResult.storageContainers.length).toBe(2);
- expect(realResult.storageContainers[0].uri).toBe(
- "https://example.com/A/",
- );
- expect(realResult.storageContainers[1].uri).toBe(
- "https://example.com/B/",
- );
- });
-
- it("Passes any errors returned from the read method", async () => {
- fetchMock.mockRejectedValueOnce(new Error("Something happened."));
- const result = await solidLdoDataset.getStorageFromWebId(SAMPLE_DATA_URI);
- expect(result.isError).toBe(true);
- });
-
- it("Passes any errors returned from the getRootContainer method", async () => {
- fetchMock.mockResolvedValueOnce(new Response(""));
- fetchMock.mockRejectedValueOnce(new Error("Something happened."));
- const result = await solidLdoDataset.getStorageFromWebId(SAMPLE_DATA_URI);
- expect(result.isError).toBe(true);
- });
- });
-
- /**
- * ===========================================================================
- * Create
- * ===========================================================================
- */
- describe("createAndOverwrite", () => {
- it("creates a document that doesn't exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () => resource.createAndOverwrite(),
- resource,
- {
- isLoading: true,
- isCreating: true,
- },
- );
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(false);
- 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 resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () => resource.createAndOverwrite(),
- resource,
- {
- isLoading: true,
- isCreating: true,
- },
- );
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(true);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE_DATA_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container.children().some((child) => child.uri === SAMPLE_DATA_URI),
- ).toBe(true);
- });
-
- it("creates a container", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_CONTAINER_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () => resource.createAndOverwrite(),
- resource,
- {
- isLoading: true,
- isCreating: true,
- },
- );
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(false);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE_CONTAINER_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container
- .children()
- .some((child) => child.uri === SAMPLE_CONTAINER_URI),
- ).toBe(true);
- });
-
- it("returns and error if creating a container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 500,
- }),
- );
- const result = await resource.createAndOverwrite();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
-
- it("returns a delete error if delete failed", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 500,
- }),
- );
- const result = await resource.createAndOverwrite();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
-
- it("returns an error if the create fetch fails", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockImplementationOnce(async (...args) => {
- return authFetch(...args);
- });
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 500,
- }),
- );
- const result = await resource.createAndOverwrite();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
-
- it("returns an unexpected error if some unknown error is triggered", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockImplementationOnce(async (...args) => {
- return authFetch(...args);
- });
- fetchMock.mockImplementationOnce(async () => {
- throw new Error("Some Unknown");
- });
- const result = await resource.createAndOverwrite();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("unexpectedResourceError");
- });
-
- it("batches the create request while waiting on another request", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const [, result1, result2] = await Promise.all([
- resource.read(),
- resource.createAndOverwrite(),
- resource.createAndOverwrite(),
- ]);
-
- expect(result1.type).toBe("createSuccess");
- expect(result2.type).toBe("createSuccess");
- // 1 for read, 1 for delete in createAndOverwrite, 1 for create
- expect(fetchMock).toHaveBeenCalledTimes(3);
- });
-
- it("batches the create request while waiting on a similar request", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const [result1, result2] = await Promise.all([
- resource.createAndOverwrite(),
- resource.createAndOverwrite(),
- ]);
-
- expect(result1.type).toBe("createSuccess");
- expect(result2.type).toBe("createSuccess");
- // 1 for delete in createAndOverwrite, 1 for create
- expect(fetchMock).toHaveBeenCalledTimes(2);
- });
- });
-
- describe("createIfAbsent", () => {
- it("creates a data resource that doesn't exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () => resource.createIfAbsent(),
- resource,
- {
- isLoading: true,
- isCreating: true,
- },
- );
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(false);
- 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("doesn't overwrite a resources that does exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () => resource.createIfAbsent(),
- resource,
- {
- isLoading: true,
- isCreating: true,
- },
- );
-
- expect(result.type).toBe("dataReadSuccess");
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE_DATA_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container.children().some((child) => child.uri === SAMPLE_DATA_URI),
- ).toBe(true);
- });
-
- it("creates a container that doesn't exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_CONTAINER_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () => resource.createIfAbsent(),
- resource,
- {
- isLoading: true,
- isCreating: true,
- },
- );
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(false);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE_CONTAINER_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container
- .children()
- .some((child) => child.uri === SAMPLE_CONTAINER_URI),
- ).toBe(true);
- });
-
- it("returns an error if creating a container", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_CONTAINER_URI);
- fetchMock.mockResolvedValueOnce(
- new Response(SAMPLE_CONTAINER_URI, {
- status: 500,
- }),
- );
- const result = await resource.createIfAbsent();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
-
- it("returns an error if creating a leaf", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- fetchMock.mockResolvedValueOnce(
- new Response(SAMPLE2_DATA_URI, {
- status: 500,
- }),
- );
- const result = await resource.createIfAbsent();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
- });
-
- /**
- * Delete
- */
- describe("deleteResource", () => {
- it("returns an unexpected http error if an unexpected value is returned", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 214,
- }),
- );
- const result = await resource.delete();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("unexpectedHttpError");
- });
-
- it("returns an unexpected resource error if an unknown error is triggered", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockImplementationOnce(async () => {
- throw new Error("Some unknwon");
- });
- const result = await resource.delete();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("unexpectedResourceError");
- });
-
- it("deletes a container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await resource.delete();
- expect(result.type === "deleteSuccess");
- });
-
- it("returns an error on container read when deleting a container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- fetchMock.mockImplementation(async (input, init) => {
- if (
- (init?.method === "get" || !init?.method) &&
- input === TEST_CONTAINER_URI
- ) {
- return new Response(SAMPLE_DATA_URI, {
- status: 500,
- });
- }
- return authFetch(input, init);
- });
- const result = await resource.delete();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("aggregateError");
- const aggregateError = result as AggregateError<
- | ServerHttpError
- | UnexpectedHttpError
- | UnauthenticatedHttpError
- | UnexpectedResourceError
- | NoncompliantPodError
- >;
- expect(aggregateError.errors[0].type).toBe("serverError");
- });
-
- it("returns an error on child delete when deleting a container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- fetchMock.mockImplementation(async (input, init) => {
- if (init?.method === "delete" && input === SAMPLE_DATA_URI) {
- return new Response(SAMPLE_DATA_URI, {
- status: 500,
- });
- }
- return authFetch(input, init);
- });
- const result = await resource.delete();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("aggregateError");
- const aggregateError = result as AggregateError<
- | ServerHttpError
- | UnexpectedHttpError
- | UnauthenticatedHttpError
- | UnexpectedResourceError
- | NoncompliantPodError
- >;
- expect(aggregateError.errors[0].type).toBe("serverError");
- });
-
- it("returns an error on container delete when deleting a container", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- fetchMock.mockImplementation(async (input, init) => {
- if (init?.method === "delete" && input === TEST_CONTAINER_URI) {
- return new Response(SAMPLE_DATA_URI, {
- status: 500,
- });
- }
- return authFetch(input, init);
- });
- const result = await resource.delete();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
- });
-
- /**
- * Update
- */
- describe("updateDataResource", () => {
- const normanQuad = createQuad(
- namedNode("http://example.org/#green-goblin"),
- namedNode("http://xmlns.com/foaf/0.1/name"),
- literal("Norman Osborn"),
- namedNode(SAMPLE_DATA_URI),
- );
-
- const goblinQuad = createQuad(
- namedNode("http://example.org/#green-goblin"),
- namedNode("http://xmlns.com/foaf/0.1/name"),
- literal("Green Goblin"),
- namedNode(SAMPLE_DATA_URI),
- );
-
- it("applies changes to a Pod", async () => {
- const result = await testRequestLoads(
- () => {
- const transaction = solidLdoDataset.startTransaction();
- transaction.add(normanQuad);
- transaction.delete(goblinQuad);
- return transaction.commitToPod();
- },
- solidLdoDataset.getResource(SAMPLE_DATA_URI),
- {
- isLoading: true,
- isUpdating: true,
- },
- );
- expect(result.type).toBe("aggregateSuccess");
- const aggregateSuccess = result as AggregateSuccess<
- ResourceSuccess
- >;
- expect(aggregateSuccess.results.length).toBe(1);
- expect(aggregateSuccess.results[0].type === "updateSuccess").toBe(true);
- expect(solidLdoDataset.has(normanQuad)).toBe(true);
- expect(solidLdoDataset.has(goblinQuad)).toBe(false);
- });
-
- it("applies only remove changes to the Pod", async () => {
- const result = await testRequestLoads(
- () => {
- const transaction = solidLdoDataset.startTransaction();
- transaction.delete(goblinQuad);
- return transaction.commitToPod();
- },
- solidLdoDataset.getResource(SAMPLE_DATA_URI),
- {
- isLoading: true,
- isUpdating: true,
- },
- );
- expect(result.type).toBe("aggregateSuccess");
- const aggregateSuccess = result as AggregateSuccess<
- ResourceSuccess
- >;
- expect(aggregateSuccess.results.length).toBe(1);
- expect(aggregateSuccess.results[0].type === "updateSuccess").toBe(true);
- expect(solidLdoDataset.has(goblinQuad)).toBe(false);
- });
-
- it("handles an HTTP error", async () => {
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 }));
-
- const transaction = solidLdoDataset.startTransaction();
- transaction.add(normanQuad);
- transaction.delete(goblinQuad);
- const result = await transaction.commitToPod();
-
- expect(result.isError).toBe(true);
- expect(result.type).toBe("aggregateError");
- const aggregateError = result as AggregateError<
- UpdateResultError | InvalidUriError
- >;
- expect(aggregateError.errors.length).toBe(1);
- expect(aggregateError.errors[0].type).toBe("serverError");
- });
-
- it("handles an unknown request", async () => {
- fetchMock.mockImplementationOnce(() => {
- throw new Error("Some Error");
- });
- const transaction = solidLdoDataset.startTransaction();
- transaction.add(normanQuad);
- transaction.delete(goblinQuad);
- const result = await transaction.commitToPod();
- expect(result.isError).toBe(true);
- expect(result.type).toBe("aggregateError");
- const aggregateError = result as AggregateError<
- UpdateResultError | InvalidUriError
- >;
- expect(aggregateError.errors.length).toBe(1);
- expect(aggregateError.errors[0].type).toBe("unexpectedResourceError");
- });
-
- it("ignores update when trying to update a container", async () => {
- const badContainerQuad = createQuad(
- namedNode("http://example.org/#green-goblin"),
- namedNode("http://xmlns.com/foaf/0.1/name"),
- literal("Norman Osborn"),
- namedNode(SAMPLE_CONTAINER_URI),
- );
- const transaction = solidLdoDataset.startTransaction();
- transaction.add(badContainerQuad);
- const result = await transaction.commitToPod();
- expect(result.isError).toBe(false);
- expect(result.type).toBe("aggregateSuccess");
- const aggregateSuccess = result as AggregateSuccess<
- UpdateSuccess | IgnoredInvalidUpdateSuccess
- >;
- expect(aggregateSuccess.results.length).toBe(1);
- expect(aggregateSuccess.results[0].type).toBe(
- "ignoredInvalidUpdateSuccess",
- );
- });
-
- it("writes to the default graph without fetching", async () => {
- const defaultGraphQuad = createQuad(
- namedNode("http://example.org/#green-goblin"),
- namedNode("http://xmlns.com/foaf/0.1/name"),
- literal("Norman Osborn"),
- defaultGraph(),
- );
- const transaction = solidLdoDataset.startTransaction();
- transaction.add(defaultGraphQuad);
- const result = await transaction.commitToPod();
- expect(result.type).toBe("aggregateSuccess");
- const aggregateSuccess = result as AggregateSuccess<
- ResourceSuccess
- >;
- expect(aggregateSuccess.results.length).toBe(1);
- expect(aggregateSuccess.results[0].type).toBe(
- "updateDefaultGraphSuccess",
- );
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode("http://example.org/#green-goblin"),
- namedNode("http://xmlns.com/foaf/0.1/name"),
- literal("Norman Osborn"),
- defaultGraph(),
- ),
- ),
- ).toBe(true);
- });
-
- it("batches data update changes", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
-
- const transaction1 = solidLdoDataset.startTransaction();
- transaction1.delete(goblinQuad);
- const transaction2 = solidLdoDataset.startTransaction();
- transaction2.add(normanQuad);
-
- const [, updateResult1, updateResult2] = await Promise.all([
- resource.read(),
- transaction1.commitToPod(),
- transaction2.commitToPod(),
- ]);
- expect(updateResult1.type).toBe("aggregateSuccess");
- expect(updateResult2.type).toBe("aggregateSuccess");
- expect(fetchMock).toHaveBeenCalledTimes(2);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode("http://example.org/#green-goblin"),
- namedNode("http://xmlns.com/foaf/0.1/name"),
- literal("Norman Osborn"),
- namedNode(SAMPLE_DATA_URI),
- ),
- ),
- ).toBe(true);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode("http://example.org/#green-goblin"),
- namedNode("http://xmlns.com/foaf/0.1/name"),
- literal("Green Goblin"),
- namedNode(SAMPLE_DATA_URI),
- ),
- ),
- ).toBe(false);
- });
- });
-
- it("allows a transaction on a transaction", () => {
- const transaction = solidLdoDataset.startTransaction();
- const transaction2 = transaction.startTransaction();
- expect(transaction2).toBeInstanceOf(SolidLdoTransactionDataset);
- });
-
- /**
- * ===========================================================================
- * Upload
- * ===========================================================================
- */
- describe("uploadAndOverwrite", () => {
- it("uploads a document that doesn't exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_BINARY_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () =>
- resource.uploadAndOverwrite(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- ),
- resource,
- {
- isLoading: true,
- isUploading: true,
- },
- );
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(false);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE2_BINARY_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container.children().some((child) => child.uri === SAMPLE2_BINARY_URI),
- ).toBe(true);
- expect(resource.getMimeType()).toBe("text/plain");
- expect(resource.isBinary()).toBe(true);
- expect(resource.isDataResource()).toBe(false);
- });
-
- it("creates a binary resource that doesn't exist while overwriting", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_BINARY_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () =>
- resource.uploadAndOverwrite(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- ),
- resource,
- {
- isLoading: true,
- isUploading: true,
- },
- );
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(true);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE_BINARY_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container.children().some((child) => child.uri === SAMPLE_BINARY_URI),
- ).toBe(true);
- });
-
- it("returns a delete error if delete failed", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_BINARY_URI);
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 500,
- }),
- );
- const result = await resource.uploadAndOverwrite(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- );
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
-
- it("returns an error if the create fetch fails", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_BINARY_URI);
- fetchMock.mockImplementationOnce(async (...args) => {
- return authFetch(...args);
- });
- fetchMock.mockResolvedValueOnce(
- new Response(TEST_CONTAINER_TTL, {
- status: 500,
- }),
- );
- const result = await resource.uploadAndOverwrite(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- );
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
-
- it("returns an unexpected error if some unknown error is triggered", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_BINARY_URI);
- fetchMock.mockImplementationOnce(async (...args) => {
- return authFetch(...args);
- });
- fetchMock.mockImplementationOnce(async () => {
- throw new Error("Some Unknown");
- });
- const result = await resource.uploadAndOverwrite(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- );
- expect(result.isError).toBe(true);
- expect(result.type).toBe("unexpectedResourceError");
- });
-
- it("batches the upload request while waiting on another request", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const [, result1, result2] = await Promise.all([
- resource.read(),
- resource.uploadAndOverwrite(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- ),
- resource.uploadAndOverwrite(
- Buffer.from("some text 2.") as unknown as Blob,
- "text/plain",
- ),
- ]);
-
- expect(result1.type).toBe("createSuccess");
- expect(result2.type).toBe("createSuccess");
- // 1 for read, 1 for delete in createAndOverwrite, 1 for create
- expect(fetchMock).toHaveBeenCalledTimes(3);
- expect(resource.getBlob()?.toString()).toBe("some text 2.");
- });
-
- it("batches the upload request while waiting on a similar request", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const [result1, result2] = await Promise.all([
- resource.uploadAndOverwrite(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- ),
- resource.uploadAndOverwrite(
- Buffer.from("some text 2.") as unknown as Blob,
- "text/plain",
- ),
- ]);
-
- expect(result1.type).toBe("createSuccess");
- expect(result2.type).toBe("createSuccess");
- // 1 for delete in createAndOverwrite, 1 for create
- expect(fetchMock).toHaveBeenCalledTimes(2);
- expect(resource.getBlob()?.toString()).toBe("some text 2.");
- });
- });
-
- describe("uploadIfAbsent", () => {
- it("creates a binary resource that doesn't exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_BINARY_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () =>
- resource.uploadIfAbsent(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- ),
- resource,
- {
- isLoading: true,
- isUploading: true,
- },
- );
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as CreateSuccess;
- expect(createSuccess.didOverwrite).toBe(false);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE2_BINARY_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container.children().some((child) => child.uri === SAMPLE2_BINARY_URI),
- ).toBe(true);
- });
-
- it("doesn't overwrite a binary resource that does exist", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_BINARY_URI);
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await testRequestLoads(
- () =>
- resource.uploadIfAbsent(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- ),
- resource,
- {
- isLoading: true,
- isUploading: true,
- },
- );
-
- expect(result.type).toBe("binaryReadSuccess");
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE_BINARY_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- container.children().some((child) => child.uri === SAMPLE_BINARY_URI),
- ).toBe(true);
- });
-
- it("returns an error if an error is encountered", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_BINARY_URI);
- fetchMock.mockResolvedValueOnce(
- new Response(SAMPLE2_BINARY_URI, {
- status: 500,
- }),
- );
- const result = await resource.uploadIfAbsent(
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- );
- expect(result.isError).toBe(true);
- expect(result.type).toBe("serverError");
- });
- });
-
- /**
- * ===========================================================================
- * Methods
- * ===========================================================================
- */
- describe("methods", () => {
- it("creates a data object for a specific subject", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const post = solidLdoDataset.createData(
- PostShShapeType,
- "https://example.com/subject",
- resource,
- );
- post.type = { "@id": "CreativeWork" };
- expect(post.type["@id"]).toBe("CreativeWork");
- const result = await commitData(post);
- expect(result.type).toBe("aggregateSuccess");
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode("https://example.com/subject"),
- namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
- namedNode("http://schema.org/CreativeWork"),
- namedNode(SAMPLE_DATA_URI),
- ),
- ),
- ).toBe(true);
- });
-
- it("handles an error when committing data", async () => {
- fetchMock.mockResolvedValueOnce(
- new Response(SAMPLE_DATA_URI, {
- status: 500,
- }),
- );
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const post = solidLdoDataset.createData(
- PostShShapeType,
- "https://example.com/subject",
- resource,
- );
- post.type = { "@id": "CreativeWork" };
- expect(post.type["@id"]).toBe("CreativeWork");
- const result = await commitData(post);
- expect(result.isError).toBe(true);
- });
-
- it("uses changeData to start a transaction", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- solidLdoDataset.add(
- createQuad(
- namedNode("https://example.com/subject"),
- namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
- namedNode("http://schema.org/CreativeWork"),
- namedNode(SAMPLE_DATA_URI),
- ),
- );
- const post = solidLdoDataset
- .usingType(PostShShapeType)
- .fromSubject("https://example.com/subject");
- const cPost = changeData(post, resource);
- cPost.type = { "@id": "SocialMediaPosting" };
- expect(cPost.type["@id"]).toBe("SocialMediaPosting");
- const result = await commitData(cPost);
- expect(result.isError).toBe(false);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode("https://example.com/subject"),
- namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"),
- namedNode("http://schema.org/SocialMediaPosting"),
- namedNode(SAMPLE_DATA_URI),
- ),
- ),
- ).toBe(true);
- });
- });
-
- /**
- * ===========================================================================
- * Container-Specific Methods
- * ===========================================================================
- */
- describe("container specific", () => {
- it("returns the child with the child method", () => {
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const child = container.child(SAMPLE2_DATA_SLUG);
- expect(child.uri).toBe(SAMPLE2_DATA_URI);
- });
-
- it("runs createAndOverwrite for a child via the createChildAndOverwrite method", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await resource.createChildAndOverwrite(SAMPLE2_DATA_SLUG);
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as ResourceResult;
- expect(createSuccess.resource.uri).toBe(SAMPLE2_DATA_URI);
- expect(createSuccess.didOverwrite).toBe(false);
- 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(
- resource.children().some((child) => child.uri === SAMPLE2_DATA_URI),
- ).toBe(true);
- });
-
- it("runs createIfAbsent for a child via the createChildIfAbsent method", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await resource.createChildIfAbsent(SAMPLE2_DATA_SLUG);
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as ResourceResult;
- expect(createSuccess.resource.uri).toBe(SAMPLE2_DATA_URI);
- expect(createSuccess.didOverwrite).toBe(false);
- 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(
- resource.children().some((child) => child.uri === SAMPLE2_DATA_URI),
- ).toBe(true);
- });
-
- it("runs uploadAndOverwrite for a child via the uploadChildAndOverwrite method", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await resource.uploadChildAndOverwrite(
- SAMPLE2_BINARY_SLUG,
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- );
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as ResourceResult;
- expect(createSuccess.resource.uri).toBe(SAMPLE2_BINARY_URI);
- expect(createSuccess.didOverwrite).toBe(false);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE2_BINARY_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- resource.children().some((child) => child.uri === SAMPLE2_BINARY_URI),
- ).toBe(true);
- });
-
- it("runs uploadIfAbsent for a child via the uploadChildIfAbsent method", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await resource.uploadChildIfAbsent(
- SAMPLE2_BINARY_SLUG,
- Buffer.from("some text.") as unknown as Blob,
- "text/plain",
- );
-
- expect(result.type).toBe("createSuccess");
- const createSuccess = result as ResourceResult;
- expect(createSuccess.resource.uri).toBe(SAMPLE2_BINARY_URI);
- expect(createSuccess.didOverwrite).toBe(false);
- expect(
- solidLdoDataset.has(
- createQuad(
- namedNode(TEST_CONTAINER_URI),
- namedNode("http://www.w3.org/ns/ldp#contains"),
- namedNode(SAMPLE2_BINARY_URI),
- namedNode(TEST_CONTAINER_URI),
- ),
- ),
- ).toBe(true);
- expect(
- resource.children().some((child) => child.uri === SAMPLE2_BINARY_URI),
- ).toBe(true);
- });
- });
-
- /**
- * ===========================================================================
- * ACCESS CONTROL
- * ===========================================================================
- */
- describe("getWacRule", () => {
- it("Fetches a wac rules for a container that has a corresponding acl", async () => {
- const container = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const wacResult = await container.getWac();
- expect(wacResult.isError).toBe(false);
- const wacSuccess = wacResult as GetWacRuleSuccess;
- expect(wacSuccess.wacRule.public).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- expect(wacSuccess.wacRule.authenticated).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- });
-
- it("Gets wac rules of a parent resource for a resource that does not have a corresponding acl", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(false);
- const wacSuccess = wacResult as GetWacRuleSuccess;
- expect(wacSuccess.wacRule.public).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- expect(wacSuccess.wacRule.authenticated).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- });
-
- it("uses cached values for a retrieved resource", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- await resource.getWac();
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(false);
- const wacSuccess = wacResult as GetWacRuleSuccess;
- expect(wacSuccess.wacRule.public).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- expect(wacSuccess.wacRule.authenticated).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- expect(wacSuccess.wacRule.agent[WEB_ID]).toEqual({
- read: true,
- write: true,
- append: true,
- control: true,
- });
- });
-
- it("returns an error when an error is encountered fetching the aclUri", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 }));
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("serverError");
- });
-
- it("returns an error when a document is not found", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("notFoundError");
- });
-
- it("returns a non-compliant error if a response is returned without a link header", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(
- new Response("Error", {
- status: 200,
- }),
- );
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("noncompliantPodError");
- expect((wacResult as NoncompliantPodError).message).toBe(
- `Response from ${SAMPLE_DATA_URI} is not compliant with the Solid Specification: No link header present in request.`,
- );
- });
-
- it("returns a non-compliant error if a response is returned without an ACL link", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(
- new Response("Error", {
- status: 200,
- headers: { link: `; rel="describedBy"` },
- }),
- );
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("noncompliantPodError");
- expect((wacResult as NoncompliantPodError).message).toBe(
- `Response from ${SAMPLE_DATA_URI} is not compliant with the Solid Specification: There must be one link with a rel="acl"`,
- );
- });
-
- it("Returns an UnexpectedResourceError if an unknown error is triggered while getting the wac URI", async () => {
- fetchMock.mockRejectedValueOnce(new Error("Something happened."));
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const result = await resource.getWac();
- expect(result.isError).toBe(true);
- if (!result.isError) return;
- expect(result.type).toBe("unexpectedResourceError");
- expect(result.message).toBe("Something happened.");
- });
-
- it("Returns an error if the request to get the ACL fails", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(
- new Response("", {
- status: 200,
- headers: { link: `; rel="acl"` },
- }),
- );
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 }));
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("serverError");
- });
-
- it("Returns a non-compliant error if the root uri has no ACL", () => {});
-
- it("Returns an error if the request to the ACL resource returns invalid turtle", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(
- new Response("", {
- status: 200,
- headers: { link: `; rel="acl"` },
- }),
- );
- fetchMock.mockResolvedValueOnce(
- new Response("BAD TURTLE", { status: 200 }),
- );
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("noncompliantPodError");
- expect((wacResult as NoncompliantPodError).message).toBe(
- `Response from card.acl is not compliant with the Solid Specification: Request returned noncompliant turtle: Unexpected "BAD" on line 1.\nBAD TURTLE`,
- );
- });
-
- it("Returns an error if there was a problem getting the parent resource", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- fetchMock.mockResolvedValueOnce(
- new Response("", {
- status: 200,
- headers: { link: `; rel="acl"` },
- }),
- );
- fetchMock.mockResolvedValueOnce(new Response("", { status: 404 }));
- fetchMock.mockResolvedValueOnce(new Response("", { status: 500 }));
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("serverError");
- });
-
- it("returns a NonCompliantPodError when this is the root resource and it doesn't have an ACL", async () => {
- const resource = solidLdoDataset.getResource(ROOT_CONTAINER);
- fetchMock.mockResolvedValueOnce(
- new Response("", {
- status: 200,
- headers: { link: `; rel="acl"` },
- }),
- );
- fetchMock.mockResolvedValueOnce(new Response("", { status: 404 }));
- const wacResult = await resource.getWac();
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("noncompliantPodError");
- expect((wacResult as NoncompliantPodError).message).toBe(
- `Response from ${ROOT_CONTAINER} is not compliant with the Solid Specification: Resource "${ROOT_CONTAINER}" has no Effective ACL resource`,
- );
- });
- });
-
- describe("setWacRule", () => {
- const newRules: WacRule = {
- public: { read: true, write: false, append: false, control: false },
- authenticated: {
- read: true,
- write: false,
- append: true,
- control: false,
- },
- agent: {
- [WEB_ID]: { read: true, write: true, append: true, control: true },
- },
- };
-
- it("sets wac rules for a resource that didn't have one before", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const result = await resource.setWac(newRules);
- expect(result.isError).toBe(false);
- expect(result.type).toBe("setWacRuleSuccess");
- const readResult = await resource.getWac({ ignoreCache: true });
- expect(readResult.isError).toBe(false);
- expect(readResult.type).toBe("getWacRuleSuccess");
- const rules = (readResult as GetWacRuleSuccess).wacRule;
- expect(rules).toEqual(newRules);
- });
-
- it("overwrites an existing access control rule", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- const result = await resource.setWac(newRules);
- expect(result.isError).toBe(false);
- expect(result.type).toBe("setWacRuleSuccess");
- const readResult = await resource.getWac({ ignoreCache: true });
- expect(readResult.isError).toBe(false);
- expect(readResult.type).toBe("getWacRuleSuccess");
- const rules = (readResult as GetWacRuleSuccess).wacRule;
- expect(rules).toEqual(newRules);
- });
-
- it("Does not write a rule when access is not granted to an agent", async () => {
- const moreRules = {
- ...newRules,
- public: { read: false, write: false, append: false, control: false },
- };
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const result = await resource.setWac(moreRules);
- expect(result.isError).toBe(false);
- expect(result.type).toBe("setWacRuleSuccess");
- const readResult = await resource.getWac({ ignoreCache: true });
- expect(readResult.isError).toBe(false);
- expect(readResult.type).toBe("getWacRuleSuccess");
- const rules = (readResult as GetWacRuleSuccess).wacRule;
- expect(rules).toEqual(moreRules);
- });
-
- it("returns an error when an error is encountered fetching the aclUri", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- fetchMock.mockResolvedValueOnce(new Response("Error", { status: 500 }));
- const wacResult = await resource.setWac(newRules);
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("serverError");
- });
-
- it("Returns an error when the request to write the access rules throws an error", async () => {
- const resource = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- fetchMock.mockResolvedValueOnce(
- new Response("", {
- status: 200,
- headers: { link: `; rel="acl"` },
- }),
- );
- fetchMock.mockResolvedValueOnce(new Response("", { status: 500 }));
- const wacResult = await resource.setWac(newRules);
- expect(wacResult.isError).toBe(true);
- expect(wacResult.type).toBe("serverError");
- });
- });
-
- /**
- * ===========================================================================
- * NOTIFICATION SUBSCRIPTIONS
- * ===========================================================================
- */
- describe("Notification Subscriptions", () => {
- const spidermanNode = namedNode("http://example.org/#spiderman");
- const foafNameNode = namedNode("http://xmlns.com/foaf/0.1/name");
-
- it("handles notification when a resource is updated", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- await resource.read();
-
- const spidermanCallback = jest.fn();
- solidLdoDataset.addListener(
- [spidermanNode, null, null, null],
- spidermanCallback,
- );
-
- const subscriptionId = await resource.subscribeToNotifications();
-
- expect(resource.isSubscribedToNotifications()).toBe(true);
-
- await authFetch(SAMPLE_DATA_URI, {
- method: "PATCH",
- body: 'INSERT DATA { "Peter Parker" . }',
- headers: {
- "Content-Type": "application/sparql-update",
- },
- });
- await wait(1000);
-
- expect(
- solidLdoDataset.match(
- spidermanNode,
- foafNameNode,
- literal("Peter Parker"),
- ).size,
- ).toBe(1);
- expect(spidermanCallback).toHaveBeenCalledTimes(1);
-
- // Notification is not propogated after unsubscribe
- spidermanCallback.mockClear();
- await resource.unsubscribeFromNotifications(subscriptionId);
- expect(resource.isSubscribedToNotifications()).toBe(false);
- await authFetch(SAMPLE_DATA_URI, {
- method: "PATCH",
- body: 'INSERT DATA { "Miles Morales" . }',
- headers: {
- "Content-Type": "application/sparql-update",
- },
- });
- await wait(50);
-
- expect(spidermanCallback).not.toHaveBeenCalled();
- expect(
- solidLdoDataset.match(
- spidermanNode,
- foafNameNode,
- literal("Miles Morales"),
- ).size,
- ).toBe(0);
- });
-
- it("handles notification when subscribed to a child that is deleted", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const testContainer = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- await resource.read();
-
- const spidermanCallback = jest.fn();
- solidLdoDataset.addListener(
- [spidermanNode, null, null, null],
- spidermanCallback,
- );
-
- const containerCallback = jest.fn();
- solidLdoDataset.addListener(
- [namedNode(TEST_CONTAINER_URI), null, null, null],
- containerCallback,
- );
-
- await resource.subscribeToNotifications();
-
- await authFetch(SAMPLE_DATA_URI, {
- method: "DELETE",
- });
- await wait(1000);
-
- expect(solidLdoDataset.match(spidermanNode, null, null).size).toBe(0);
- expect(
- testContainer.children().some((child) => child.uri === SAMPLE_DATA_URI),
- ).toBe(false);
- expect(spidermanCallback).toHaveBeenCalledTimes(1);
- expect(containerCallback).toHaveBeenCalledTimes(1);
-
- await resource.unsubscribeFromAllNotifications();
- });
-
- it("handles notification when subscribed to a parent with a deleted child", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const testContainer = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- await resource.read();
-
- const spidermanCallback = jest.fn();
- solidLdoDataset.addListener(
- [spidermanNode, null, null, null],
- spidermanCallback,
- );
-
- const containerCallback = jest.fn();
- solidLdoDataset.addListener(
- [namedNode(TEST_CONTAINER_URI), null, null, null],
- containerCallback,
- );
-
- await testContainer.subscribeToNotifications();
-
- await authFetch(SAMPLE_DATA_URI, {
- method: "DELETE",
- });
- await wait(1000);
-
- expect(solidLdoDataset.match(spidermanNode, null, null).size).toBe(0);
- expect(
- testContainer.children().some((child) => child.uri === SAMPLE_DATA_URI),
- ).toBe(false);
- expect(spidermanCallback).toHaveBeenCalledTimes(1);
- expect(containerCallback).toHaveBeenCalledTimes(1);
-
- await testContainer.unsubscribeFromAllNotifications();
- });
-
- it("handles notification when subscribed to a parent with an added child", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE2_DATA_URI);
- const testContainer = solidLdoDataset.getResource(TEST_CONTAINER_URI);
- await resource.read();
-
- const spidermanCallback = jest.fn();
- solidLdoDataset.addListener(
- [spidermanNode, null, null, null],
- spidermanCallback,
- );
-
- const containerCallback = jest.fn();
- solidLdoDataset.addListener(
- [namedNode(TEST_CONTAINER_URI), null, null, null],
- containerCallback,
- );
-
- await testContainer.subscribeToNotifications();
-
- await authFetch(TEST_CONTAINER_URI, {
- method: "POST",
- headers: { "content-type": "text/turtle", slug: "sample2.ttl" },
- body: SPIDER_MAN_TTL,
- });
- await wait(1000);
-
- expect(solidLdoDataset.match(spidermanNode, null, null).size).toBe(4);
- expect(
- testContainer
- .children()
- .some((child) => child.uri === SAMPLE2_DATA_URI),
- ).toBe(true);
- expect(spidermanCallback).toHaveBeenCalledTimes(1);
- expect(containerCallback).toHaveBeenCalledTimes(1);
-
- await testContainer.unsubscribeFromAllNotifications();
- });
-
- it("returns an error when it cannot subscribe to a notification", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const onError = jest.fn();
-
- await app.stop();
- await resource.subscribeToNotifications({ onNotificationError: onError });
- expect(onError).toHaveBeenCalledTimes(2);
- await app.start();
- });
-
- it("returns an error when the server doesnt support websockets", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const onError = jest.fn();
-
- await app.stop();
- const disabledWebsocketsApp = await createApp(
- path.join(__dirname, "./configs/server-config-without-websocket.json"),
- );
- await disabledWebsocketsApp.start();
-
- await resource.subscribeToNotifications({ onNotificationError: onError });
- expect(onError).toHaveBeenCalledTimes(2);
-
- await disabledWebsocketsApp.stop();
- await app.start();
- });
-
- it("attempts to reconnect multiple times before giving up.", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- const onError = jest.fn();
-
- await app.stop();
- const disabledWebsocketsApp = await createApp(
- path.join(__dirname, "./configs/server-config-without-websocket.json"),
- );
- await disabledWebsocketsApp.start();
-
- await resource.subscribeToNotifications({ onNotificationError: onError });
-
- // TODO: This is a bad test because of the wait. Instead inject better
- // numbers into the websocket class.
- await wait(35000);
-
- expect(onError).toHaveBeenCalledTimes(14);
- expect(onError.mock.calls[1][0].type).toBe(
- "disconnectedAttemptingReconnectError",
- );
- expect(onError.mock.calls[13][0].type).toBe(
- "disconnectedNotAttemptingReconnectError",
- );
-
- await disabledWebsocketsApp.stop();
- await app.start();
- });
-
- it("causes no problems when unsubscribing when not subscribed", async () => {
- const resource = solidLdoDataset.getResource(SAMPLE_DATA_URI);
- await resource.unsubscribeFromAllNotifications();
- expect(resource.isSubscribedToNotifications()).toBe(false);
- });
- });
-});
diff --git a/packages/solid/test/LeafRequester.test.ts b/packages/solid/test/LeafRequester.test.ts
deleted file mode 100644
index 72dd179..0000000
--- a/packages/solid/test/LeafRequester.test.ts
+++ /dev/null
@@ -1,256 +0,0 @@
-// import type { App } from "@solid/community-server";
-// import { getAuthenticatedFetch, ROOT_COONTAINER } from "./solidServer.helper";
-// 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";
-
-describe("Leaf Requester", () => {
- it("trivial", () => {
- expect(true).toBe(true);
- });
-});
-
-// describe.skip("Leaf 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_COONTAINER}test_leaf/`, {
-// method: "POST",
-// headers: { "content-type": "text/turtle", slug: "sample.ttl" },
-// body: `@base .
-// @prefix rdf: .
-// @prefix rdfs: .
-// @prefix foaf: .
-// @prefix rel: .
-
-// <#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",
-// }),
-// ]);
-// });
-
-// /**
-// * ===========================================================================
-// * Read
-// * ===========================================================================
-// */
-// it("reads data", async () => {
-// const leafRequester = new LeafRequester(
-// `${ROOT_COONTAINER}test_leaf/sample.ttl`,
-// solidLdoDataset.context,
-// );
-// const result = await leafRequester.read();
-// expect(result.type).toBe("data");
-// expect(
-// solidLdoDataset.match(
-// null,
-// null,
-// null,
-// namedNode(`${ROOT_COONTAINER}test_leaf/sample.ttl`),
-// ).size,
-// ).toBe(7);
-// });
-
-// it("reads data that doesn't exist", async () => {
-// const leafRequester = new LeafRequester(
-// `${ROOT_COONTAINER}test_leaf/doesnotexist.ttl`,
-// solidLdoDataset.context,
-// );
-// const result = await leafRequester.read();
-// 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`,
-// solidLdoDataset.context,
-// );
-// const result = await leafRequester.createDataResource();
-// 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 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);
-// });
-
-// /**
-// * ===========================================================================
-// * Delete
-// * ===========================================================================
-// */
-// it("deletes data", async () => {
-// solidLdoDataset.add(
-// createQuad(
-// namedNode("a"),
-// namedNode("b"),
-// namedNode("c"),
-// namedNode(`${ROOT_COONTAINER}/test_leaf/sample.ttl`),
-// ),
-// );
-// solidLdoDataset.add(
-// 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/`),
-// ),
-// );
-// const leafRequester = new LeafRequester(
-// `${ROOT_COONTAINER}/test_leaf/sample.ttl`,
-// solidLdoDataset.context,
-// );
-// const result = await leafRequester.delete();
-// expect(result.type).toBe("absent");
-// expect(
-// solidLdoDataset.match(
-// null,
-// null,
-// null,
-// namedNode(`${ROOT_COONTAINER}/test_leaf/sample.ttl`),
-// ).size,
-// ).toBe(0);
-// 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(false);
-// });
-// });
diff --git a/packages/solid/test/RequestBatcher.test.ts b/packages/solid/test/RequestBatcher.test.ts
deleted file mode 100644
index 38ff5a2..0000000
--- a/packages/solid/test/RequestBatcher.test.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import type { WaitingProcess } from "../src/util/RequestBatcher";
-import { RequestBatcher } from "../src/util/RequestBatcher";
-
-describe("RequestBatcher", () => {
- type ReadWaitingProcess = WaitingProcess<[string], string>;
-
- it("Batches a request", async () => {
- const requestBatcher = new RequestBatcher({ batchMillis: 500 });
- const perform = async (input: string): Promise => {
- await wait(100);
- return `Hello ${input}`;
- };
- const perform1 = jest.fn(perform);
- const perform2 = jest.fn(perform);
- const perform3 = jest.fn((input: string): Promise => {
- expect(requestBatcher.isLoading("read")).toBe(true);
- return perform(input);
- });
- const perform4 = jest.fn(perform);
-
- const modifyQueue = (queue, currentlyProcessing, input: [string]) => {
- const last = queue[queue.length - 1];
- if (last?.name === "read") {
- (last as ReadWaitingProcess).args[0] += input;
- return last;
- }
- return undefined;
- };
-
- let return1: string = "";
- let return2: string = "";
- let return3: string = "";
- let return4: string = "";
-
- expect(requestBatcher.isLoading("read")).toBe(false);
-
- await Promise.all([
- requestBatcher
- .queueProcess<[string], string>({
- name: "read",
- args: ["a"],
- perform: perform1,
- modifyQueue,
- })
- .then((val) => (return1 = val)),
- requestBatcher
- .queueProcess<[string], string>({
- name: "read",
- args: ["b"],
- perform: perform2,
- modifyQueue,
- })
- .then((val) => (return2 = val)),
- ,
- requestBatcher
- .queueProcess<[string], string>({
- name: "read",
- args: ["c"],
- perform: perform3,
- modifyQueue,
- })
- .then((val) => (return3 = val)),
- ,
- requestBatcher
- .queueProcess<[string], string>({
- name: "read",
- args: ["d"],
- perform: perform4,
- modifyQueue,
- })
- .then((val) => (return4 = val)),
- ,
- ]);
-
- expect(return1).toBe("Hello a");
- expect(return2).toBe("Hello bcd");
- expect(return3).toBe("Hello bcd");
- expect(return4).toBe("Hello bcd");
-
- expect(perform1).toHaveBeenCalledTimes(1);
- expect(perform1).toHaveBeenCalledWith("a");
- expect(perform2).toHaveBeenCalledTimes(1);
- expect(perform2).toHaveBeenCalledWith("bcd");
- expect(perform3).toHaveBeenCalledTimes(0);
- expect(perform4).toHaveBeenCalledTimes(0);
- });
-
- it("sets a default batch millis", () => {
- const requestBatcher = new RequestBatcher();
- expect(requestBatcher.batchMillis).toBe(1000);
- });
-
- it("handles an error being thrown in the process", () => {
- const requestBatcher = new RequestBatcher({ batchMillis: 500 });
- const perform = async (_input: string): Promise => {
- throw new Error("Test Error");
- };
- const perform1 = jest.fn(perform);
- expect(() =>
- requestBatcher.queueProcess<[string], string>({
- name: "read",
- args: ["a"],
- perform: perform1,
- modifyQueue: () => undefined,
- }),
- ).rejects.toThrowError("Test Error");
- });
-});
-
-function wait(millis: number): Promise {
- return new Promise((resolve) => setTimeout(resolve, millis));
-}
diff --git a/packages/solid/test/Websocket2023NotificationSubscription.test.ts b/packages/solid/test/Websocket2023NotificationSubscription.test.ts
deleted file mode 100644
index 1f97b0d..0000000
--- a/packages/solid/test/Websocket2023NotificationSubscription.test.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import type { WebSocket, Event, ErrorEvent } from "ws";
-import { Websocket2023NotificationSubscription } from "../src/resource/notifications/Websocket2023NotificationSubscription";
-import type { SolidLdoDatasetContext } from "../src";
-import { Leaf } from "../src";
-import type { NotificationChannel } from "@solid-notifications/types";
-
-describe("Websocket2023NotificationSubscription", () => {
- it("returns an error when websockets have an error", async () => {
- const WebSocketMock: WebSocket = {} as WebSocket;
-
- const subscription = new Websocket2023NotificationSubscription(
- new Leaf("https://example.com", {
- fetch,
- } as unknown as SolidLdoDatasetContext),
- () => {},
- {} as unknown as SolidLdoDatasetContext,
- () => WebSocketMock,
- );
-
- const subPromise = subscription.subscribeToWebsocket({
- receiveFrom: "http://example.com",
- } as unknown as NotificationChannel);
- WebSocketMock.onopen?.({} as Event);
-
- await subPromise;
-
- WebSocketMock.onerror?.({ error: new Error("Test Error") } as ErrorEvent);
- });
-
- it("returns an error when websockets have an error at the beginning", async () => {
- const WebSocketMock: WebSocket = {} as WebSocket;
-
- const subscription = new Websocket2023NotificationSubscription(
- new Leaf("https://example.com", {
- fetch,
- } as unknown as SolidLdoDatasetContext),
- () => {},
- {} as unknown as SolidLdoDatasetContext,
- () => WebSocketMock,
- );
-
- const subPromise = subscription.subscribeToWebsocket({
- receiveFrom: "http://example.com",
- } as unknown as NotificationChannel);
- WebSocketMock.onerror?.({ error: new Error("Test Error") } as ErrorEvent);
- await subPromise;
- });
-});
diff --git a/packages/solid/test/authFetch.helper.ts b/packages/solid/test/authFetch.helper.ts
deleted file mode 100644
index fffee6a..0000000
--- a/packages/solid/test/authFetch.helper.ts
+++ /dev/null
@@ -1,112 +0,0 @@
-import type { KeyPair } from "@inrupt/solid-client-authn-core";
-import {
- buildAuthenticatedFetch,
- createDpopHeader,
- generateDpopKeyPair,
-} from "@inrupt/solid-client-authn-core";
-import fetch from "cross-fetch";
-
-const config = {
- podName: process.env.USER_NAME || "example",
- email: process.env.EMAIL || "hello@example.com",
- password: process.env.PASSWORD || "abc123",
-};
-
-async function getAuthorization(): Promise {
- // First we request the account API controls to find out where we can log in
- const indexResponse = await fetch("http://localhost:3001/.account/");
- const { controls } = await indexResponse.json();
-
- // And then we log in to the account API
- const response = await fetch(controls.password.login, {
- method: "POST",
- headers: { "content-type": "application/json" },
- body: JSON.stringify({
- email: config.email,
- password: config.password,
- }),
- });
- // This authorization value will be used to authenticate in the next step
- const result = await response.json();
- return result.authorization;
-}
-
-async function getSecret(
- authorization: string,
-): Promise<{ id: string; secret: string; resource: string }> {
- // Now that we are logged in, we need to request the updated controls from the server.
- // These will now have more values than in the previous example.
- const indexResponse = await fetch("http://localhost:3001/.account/", {
- headers: { authorization: `CSS-Account-Token ${authorization}` },
- });
- const { controls } = await indexResponse.json();
-
- // Here we request the server to generate a token on our account
- const response = await fetch(controls.account.clientCredentials, {
- method: "POST",
- headers: {
- authorization: `CSS-Account-Token ${authorization}`,
- "content-type": "application/json",
- },
- // The name field will be used when generating the ID of your token.
- // The WebID field determines which WebID you will identify as when using the token.
- // Only WebIDs linked to your account can be used.
- body: JSON.stringify({
- name: "my-token",
- webId: `http://localhost:3001/${config.podName}/profile/card#me`,
- }),
- });
-
- // These are the identifier and secret of your token.
- // Store the secret somewhere safe as there is no way to request it again from the server!
- // The `resource` value can be used to delete the token at a later point in time.
- const response2 = await response.json();
- return response2;
-}
-
-async function getAccessToken(
- id: string,
- secret: string,
-): Promise<{ accessToken: string; dpopKey: KeyPair }> {
- try {
- // A key pair is needed for encryption.
- // This function from `solid-client-authn` generates such a pair for you.
- const dpopKey = await generateDpopKeyPair();
-
- // These are the ID and secret generated in the previous step.
- // Both the ID and the secret need to be form-encoded.
- const authString = `${encodeURIComponent(id)}:${encodeURIComponent(
- secret,
- )}`;
- // This URL can be found by looking at the "token_endpoint" field at
- // http://localhost:3001/.well-known/openid-configuration
- // if your server is hosted at http://localhost:3000/.
- const tokenUrl = "http://localhost:3001/.oidc/token";
- const response = await fetch(tokenUrl, {
- method: "POST",
- headers: {
- // The header needs to be in base64 encoding.
- authorization: `Basic ${Buffer.from(authString).toString("base64")}`,
- "content-type": "application/x-www-form-urlencoded",
- dpop: await createDpopHeader(tokenUrl, "POST", dpopKey),
- },
- body: "grant_type=client_credentials&scope=webid",
- });
-
- // This is the Access token that will be used to do an authenticated request to the server.
- // The JSON also contains an "expires_in" field in seconds,
- // which you can use to know when you need request a new Access token.
- const response2 = await response.json();
- return { accessToken: response2.access_token, dpopKey };
- } catch (err) {
- console.error(err);
- throw err;
- }
-}
-
-export async function generateAuthFetch() {
- const authorization = await getAuthorization();
- const { id, secret } = await getSecret(authorization);
- const { accessToken, dpopKey } = await getAccessToken(id, secret);
- return await buildAuthenticatedFetch(accessToken, { dpopKey });
-}
diff --git a/packages/solid/test/configs/server-config-without-websocket.json b/packages/solid/test/configs/server-config-without-websocket.json
deleted file mode 100644
index 626d082..0000000
--- a/packages/solid/test/configs/server-config-without-websocket.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld",
- "import": [
- "css:config/app/init/initialize-root.json",
- "css:config/app/main/default.json",
- "css:config/app/variables/default.json",
- "css:config/http/handler/default.json",
- "css:config/http/middleware/default.json",
- "css:config/http/notifications/webhooks.json",
- "css:config/http/server-factory/http.json",
- "css:config/http/static/default.json",
- "css:config/identity/access/public.json",
- "css:config/identity/email/default.json",
- "css:config/identity/handler/no-accounts.json",
- "css:config/identity/oidc/default.json",
- "css:config/identity/ownership/token.json",
- "css:config/identity/pod/static.json",
- "css:config/ldp/authentication/dpop-bearer.json",
- "css:config/ldp/authorization/webacl.json",
- "css:config/ldp/handler/default.json",
- "css:config/ldp/metadata-parser/default.json",
- "css:config/ldp/metadata-writer/default.json",
- "css:config/ldp/modes/default.json",
- "css:config/storage/backend/file.json",
- "css:config/storage/key-value/resource-store.json",
- "css:config/storage/location/root.json",
- "css:config/storage/middleware/default.json",
- "css:config/util/auxiliary/acl.json",
- "css:config/util/identifiers/suffix.json",
- "css:config/util/index/default.json",
- "css:config/util/logging/winston.json",
- "css:config/util/representation-conversion/default.json",
- "css:config/util/resource-locker/file.json",
- "css:config/util/variables/default.json"
- ],
- "@graph": [
- {
- "comment": [
- "A Solid server that stores its resources on disk and uses WAC for authorization.",
- "No registration and the root container is initialized to allow full access for everyone so make sure to change this."
- ]
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/solid/test/configs/server-config.json b/packages/solid/test/configs/server-config.json
deleted file mode 100644
index 5e96784..0000000
--- a/packages/solid/test/configs/server-config.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "@context": [
- "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^7.0.0/components/context.jsonld"
- ],
- "import": [
- "css:config/app/init/static-root.json",
- "css:config/app/main/default.json",
- "css:config/app/variables/default.json",
- "css:config/http/handler/default.json",
- "css:config/http/middleware/default.json",
- "css:config/http/notifications/all.json",
- "css:config/http/server-factory/http.json",
- "css:config/http/static/default.json",
- "css:config/identity/access/public.json",
- "css:config/identity/email/default.json",
- "css:config/identity/handler/default.json",
- "css:config/identity/oidc/default.json",
- "css:config/identity/ownership/token.json",
- "css:config/identity/pod/static.json",
- "css:config/ldp/authentication/dpop-bearer.json",
- "css:config/ldp/authorization/webacl.json",
- "css:config/ldp/handler/default.json",
- "css:config/ldp/metadata-parser/default.json",
- "css:config/ldp/metadata-writer/default.json",
- "css:config/ldp/modes/default.json",
- "css:config/storage/backend/memory.json",
- "css:config/storage/key-value/resource-store.json",
- "css:config/storage/location/pod.json",
- "css:config/storage/middleware/default.json",
- "css:config/util/auxiliary/acl.json",
- "css:config/util/identifiers/suffix.json",
- "css:config/util/index/default.json",
- "css:config/util/logging/winston.json",
- "css:config/util/representation-conversion/default.json",
- "css:config/util/resource-locker/memory.json",
- "css:config/util/variables/default.json"
- ],
- "@graph": [
- {
- "comment": "A Solid server that stores its resources on disk and uses WAC for authorization."
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/solid/test/configs/solid-css-seed.json b/packages/solid/test/configs/solid-css-seed.json
deleted file mode 100644
index 5894d0d..0000000
--- a/packages/solid/test/configs/solid-css-seed.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[
- {
- "email": "hello@example.com",
- "password": "abc123",
- "pods": [
- { "name": "example" }
- ]
- }
-]
\ No newline at end of file
diff --git a/packages/solid/test/guaranteeFetch.test.ts b/packages/solid/test/guaranteeFetch.test.ts
deleted file mode 100644
index 92cf6c4..0000000
--- a/packages/solid/test/guaranteeFetch.test.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { guaranteeFetch } from "../src/util/guaranteeFetch";
-import crossFetch from "cross-fetch";
-
-describe("guaranteeFetch", () => {
- it("returns crossfetch when no fetch is provided", () => {
- expect(guaranteeFetch()).toBe(crossFetch);
- });
-});
diff --git a/packages/solid/test/setup-tests.ts b/packages/solid/test/setup-tests.ts
deleted file mode 100644
index f4378ae..0000000
--- a/packages/solid/test/setup-tests.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { config } from "dotenv";
-
-config();
diff --git a/packages/solid/test/solidServer.helper.ts b/packages/solid/test/solidServer.helper.ts
deleted file mode 100644
index 38069d5..0000000
--- a/packages/solid/test/solidServer.helper.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-// Taken from https://github.com/comunica/comunica/blob/b237be4265c353a62a876187d9e21e3bc05123a3/engines/query-sparql/test/QuerySparql-solid-test.ts#L9
-
-import * as path from "path";
-import type { App } from "@solid/community-server";
-import { AppRunner, resolveModulePath } from "@solid/community-server";
-import "jest-rdf";
-
-export const SERVER_DOMAIN = process.env.SERVER || "http://localhost:3001/";
-export const ROOT_ROUTE = process.env.ROOT_CONTAINER || "";
-export const ROOT_CONTAINER = `${SERVER_DOMAIN}${ROOT_ROUTE}`;
-export const WEB_ID =
- process.env.WEB_ID || `${SERVER_DOMAIN}example/profile/card#me`;
-
-// Use an increased timeout, since the CSS server takes too much setup time.
-jest.setTimeout(40_000);
-
-export async function createApp(customConfigPath?: string): Promise {
- if (process.env.SERVER) {
- return {
- start: () => {},
- stop: () => {},
- } as App;
- }
- const appRunner = new AppRunner();
-
- return appRunner.create({
- loaderProperties: {
- mainModulePath: resolveModulePath(""),
- typeChecking: false,
- },
- config: customConfigPath ?? resolveModulePath("config/file-root.json"),
- variableBindings: {},
- shorthand: {
- port: 3_001,
- loggingLevel: "off",
- seedConfig: path.join(__dirname, "configs", "solid-css-seed.json"),
- rootFilePath: path.join(__dirname, "./data"),
- },
- });
-}
diff --git a/packages/solid/test/uriTypes.test.ts b/packages/solid/test/uriTypes.test.ts
deleted file mode 100644
index 589e874..0000000
--- a/packages/solid/test/uriTypes.test.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { isLeafUri } from "../src";
-
-describe("isLeafUri", () => {
- it("returns true if the given value is a leaf URI", () => {
- expect(isLeafUri("https://example.com/index.ttl")).toBe(true);
- });
-});
diff --git a/packages/solid/test/utils.helper.ts b/packages/solid/test/utils.helper.ts
deleted file mode 100644
index 109fa51..0000000
--- a/packages/solid/test/utils.helper.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export async function wait(millis: number) {
- return new Promise((resolve) => setTimeout(resolve, millis));
-}
diff --git a/packages/solid/tsconfig.build.json b/packages/solid/tsconfig.build.json
deleted file mode 100644
index 4bd5a5e..0000000
--- a/packages/solid/tsconfig.build.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "extends": "../../tsconfig.base.json",
- "compilerOptions": {
- "outDir": "./dist",
- },
- "include": ["./src"]
-}
\ No newline at end of file
diff --git a/packages/solid/typedoc.json b/packages/solid/typedoc.json
deleted file mode 100644
index c0e7b5d..0000000
--- a/packages/solid/typedoc.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "entryPoints": ["src/index.ts"],
- "out": "docs",
- "allReflectionsHaveOwnDocument": true,
- "hideInPageTOC": true,
- "hideBreadcrumbs": true,
-}
\ No newline at end of file