# CRUD (RDF Data)

{% hint style="info" %}
For information on structured data, or [Resource Description Framework (RDF)](https://docs.inrupt.com/reference/glossary#rdf-resource) data, see [structured-data-rdf-resources](https://docs.inrupt.com/reference/rdf/structured-data-rdf-resources "mention").
{% endhint %}

To read and write [RDF data](https://docs.inrupt.com/reference/glossary#rdf-resource) to [Pods](https://docs.inrupt.com/reference/glossary#pods), Inrupt provides the [**`solid-client`**](https://inrupt.github.io/solid-client-js/) library.

### Required Access

By default, **`solid-client`** functions make unauthenticated requests. To perform read/write operations on restricted [Resources](https://docs.inrupt.com/reference/glossary#resource) (i.e., not open to the general public), the user must be authenticated with appropriate access to that Resource. Then, to make authenticated requests, pass to the various read/write functions the authenticated session’s **`fetch`** function.

{% tabs %}
{% tab title="Create" %}
The creation operation creates the Resource and updates the content of the parent [Container](https://docs.inrupt.com/reference/glossary#container) with the new Resource’s metadata.

{% hint style="info" %}
**Access**

To create a Resource, either **`Append`** or **`Write`** access is required.
{% endhint %}

<table><thead><tr><th width="160.4140625">Target Resource</th><th>Required Access</th></tr></thead><tbody><tr><td><a href="../../../reference/glossary#soliddataset">SolidDataset</a></td><td><p>Either <strong><code>Append</code></strong> or <strong><code>Write</code></strong> access to the parent Container, depending on the library’s function:</p><ul><li><a href="https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#savesoliddatasetin%20container"><code>saveSolidDatasetInContainer()</code></a>: Either <strong><code>Append</code></strong> or <strong><code>Write</code></strong> access to the parent Container.</li><li><a href="https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#savesoliddatasetat"><code>saveSolidDatasetAt()</code></a>: <strong><code>Write</code></strong> access to the parent Container.</li></ul></td></tr><tr><td><a href="../../../reference/glossary#container">Container</a></td><td>Either <strong><code>Append</code></strong> or <strong><code>Write</code></strong> access on the <strong>parent</strong> Container (under which the new Container is to be created) allows <a href="../../../reference/glossary#agent">Agents</a> to create a new Container.</td></tr></tbody></table>
{% endtab %}

{% tab title="Read" %}
For read operations, the user requires **`Read`** access.

<table><thead><tr><th width="160.984375">Target Resource</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://docs.inrupt.com/reference/glossary#term-SolidDataset">SolidDataset</a></td><td><strong><code>Read</code></strong> access on the target SolidDataset allows agents to read/retrieve the SolidDataset (regardless of the access on the parent Container).</td></tr><tr><td><a href="https://docs.inrupt.com/reference/glossary/#term-Container">Container</a></td><td><p><strong><code>Read</code></strong> access on the target Container (analogous to a folder in a file system) allow agents to read/retrieve the Container as a resource (not the resource(s) under the Container). That is, Read access only affects read operation on the Container itself.</p><p>Reading a Container (which stores metadata about the resources contained within the Container) allows a client to discover what resources are contained inside the Container and their resource type (i.e., analogous to an <strong><code>ls</code></strong> on a folder in a file system).</p></td></tr></tbody></table>
{% endtab %}

{% tab title="Update" %}
For update operations, the user requires **`Append`** or **`Write`** access, depending on the specific update operation.

<table><thead><tr><th width="161.66796875">Target Resource</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://docs.inrupt.com/reference/glossary#term-SolidDataset">SolidDataset</a></td><td><ul><li>Either <strong><code>Append</code></strong> or <strong><code>Write</code></strong> access on the target SolidDataset allows agents to add to the resource: new <a href="https://docs.inrupt.com/developer-tools/javascript/client-libraries/reference/glossary/#term-Thing">Things</a>; new properties and value(s) for existing Things.</li><li><strong><code>Write</code></strong> access on an RDF resource allows agents to delete Things from the resource.</li><li><strong><code>Write</code></strong> access on an RDF resource allows agents to update property/value for existing Things in the resource.</li></ul></td></tr><tr><td><a href="https://docs.inrupt.com/reference/glossary/#term-Container">Container</a></td><td><p>To add resources to the Container, see the <strong><code>Create</code></strong> tab.</p><p>To delete resources from the Container, see the <strong><code>Delete</code></strong> tab.</p></td></tr></tbody></table>
{% endtab %}

{% tab title="Delete" %}
For delete operations, the user requires **`Write`** access.

<table><thead><tr><th width="160.10546875">Target</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://docs.inrupt.com/reference/glossary#term-SolidDataset">SolidDataset</a></td><td>To delete a SolidDataset, <strong><code>Write</code></strong> access on both the parent Container and the target SolidDataset allows agents to delete the target SolidDataset.</td></tr><tr><td><a href="https://docs.inrupt.com/reference/glossary/#term-Container">Container</a></td><td><p><strong><code>Write</code></strong> access on both the parent Container and the target Container allows agents to delete the target Container.</p><p>To delete a Container, the target Container must be empty.</p></td></tr></tbody></table>
{% endtab %}
{% endtabs %}

### Prerequisite for Restricted Data

To make authenticated requests, you can use one of Inrupt’s authentication libraries to login and pass the [fetch()](https://inrupt.github.io/solid-client-authn-js/browser/functions.html#fetch) function as an option to **`solid-client`** functions. Inrupt provides the following libraries for authentication:

* **`solid-client-authn-browser`** library to authenticate in a browser.
* **`solid-client-authn-node`** library to authenticate in Node.js.

The following example uses **`solid-client-authn-browser`** to authenticate a user and use the authenticated Session’s [`fetch()`](https://inrupt.github.io/solid-client-authn-js/browser/functions.html#fetch) function to make authenticated requests:

<pre class="language-javascript"><code class="lang-javascript">import { handleIncomingRedirect, login, fetch, getDefaultSession } from '@inrupt/solid-client-authn-browser'
import { getSolidDataset, saveSolidDatasetAt } from "@inrupt/solid-client";

async function loginAndFetch() {
  // 1. Call the handleIncomingRedirect() function,
  //    - Which completes the login flow if redirected back to this page as part of login; or
  //    - Which is a No-op if not part of login.
  await handleIncomingRedirect();

  // 2. Start the Login Process if not already logged in.
  if (!getDefaultSession().info.isLoggedIn) {
    await login({
      oidcIssuer: "https://login.inrupt.com",
      redirectUrl: new URL("/", window.location.href).toString(),
      clientName: "My application"
    });
  }

  // ...
  // const exampleSolidDatasetURL = ...;
  
  // 3. Make authenticated requests by passing `fetch` to the solid-client functions.
  // For example, the user must be someone with Read access to the specified URL.
  const myDataset = await getSolidDataset(
    exampleSolidDatasetURL, 
<strong>    { fetch: fetch }  // fetch function from authenticated session
</strong>  );

  // ...
  
  // For example, the user must be someone with Write access to the specified URL.
  const savedSolidDataset = await saveSolidDatasetAt(
    exampleSolidDatasetURL,
    myChangedDataset,
<strong>    { fetch: fetch }  // fetch function from authenticated session
</strong>  );
}

loginAndFetch();
</code></pre>

For more information on authentication, see [authentication](https://docs.inrupt.com/sdk/javascript-sdk/authentication "mention").

For files saved in a Pod, their URL acts as the unique identifier. Their URLs are relative to the Pod's URL. For example:

* **`https://storage.inrupt.com/{someIdentifier}/pictures/picture.jpg`**
* **`https://storage.inrupt.com/{someIdentifier}/data/inventory1.pdf`**

where **`https://storage.inrupt.com/{someIdentifier}/`** is the Pod's URL.

Inrupt’s **`solid-client`** library provides [**`getPodUrlAll`**](https://api.docs.inrupt.com/docs/developer-tools/api/javascript/solid-client/modules/profile_webid.html#getpodurlall) to get the Pod's URL or, if the user has multiple Pods, the list of Pod URLs.

```javascript
import { getPodUrlAll } from "@inrupt/solid-client";

// Returns a list of URLs

const mystorages = await getPodUrlAll(webID, { fetch: fetch });
```

### Assumptions

The following examples assumes:

* The application has used the **`solid-client-authn-browser`** library to handle login and has an authenticated [`fetch`](https://inrupt.github.io/solid-client-authn-js/browser/functions.html#fetch) function.
* The logged-in user has the appropriate permissions to perform the specified SolidDataset operations.

### Read Data

To read data with **`solid-client`**:

1. Use [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset) to fetch the SolidDataset. You must have **`Read`** access to the SolidDataset.
2. Then, use either:
   * [getThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#getthing) to get a single data entity from the fetched SolidDataset, or
   * [getThingAll](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#getthingall) to get all data entities from the fetched SolidDataset.
3. Then, from the data entity (i.e., **`Thing`**), you can [get](https://inrupt.github.io/solid-client-js/modules/thing_get.html) specific data. For a list of the **`get`** functions, see [thing/get module](https://inrupt.github.io/solid-client-js/modules/thing_get.html).

#### 0. Import

For the examples, import the following objects from the client libraries:

```javascript
import {
  getSolidDataset,
  getThing,
  getStringNoLocale,
  getUrlAll
} from "@inrupt/solid-client";

```

#### 1. Fetch the **`SolidDataset`**

Use [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset) to fetch the **`SolidDataset`** that contains the data:

* Pass the **`SolidDataset`** URL to [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset). In the following example, the **`SolidDataset`** is the reading list document created as part of Getting Started.
* To make an authenticated request, the example includes a **`fetch`** function associated with a logged in Session.

```javascript
  const myDataset = await getSolidDataset(
    readingListUrl,
    { fetch: fetch }          // fetch from authenticated session
  );
```

#### 2. Get the Data Entity **`Thing`**

From the fetched SolidDataset, you can use either:

* [getThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#getthing) with the Thing’s URL to get a single data entity, or
* [getThingAll](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#getthingall) to get all data entities from the dataset.

Typically, but not always, a Thing’s URL is the SolidDataset’s URL appended with a hash fragment **`#<something>`**; that is, **`<SolidDataset URL>#<something>`**,

In the reading list example, the **`titles`** (Things) use the hash fragment **`#title<number>`**,

The following example uses [getThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#getthing) to retrieve a book title from the previously fetched SolidDataset (i.e., the reading list document).

```javascript
  const itemForWeek = getThing(
    myDataset,
    `${readingListUrl}#title${weekNum}`
  );
```

#### 3. Read Data Attribute of a Thing

Like the **`Thing`** and **`SolidDataset`**, each property (such as **`name`**, etc.) of a **`Thing`** is also identified by a URL. That is, when storing the **`name`** of a book, you do not store the data under the string identifier **`name`**, Instead, you use a URL identifier, such as **`https://schema.org/name`** from the **`https://schema.org`** Vocabulary (or some other URL).

A property can have zero, one or more values, and the value is typed; e.g., a string, an integer, or a URL if pointing to other Things. To retrieve the data, use the appropriate [get](https://inrupt.github.io/solid-client-js/modules/thing_get.html) function depending on the data type and the number of values for the property.

<table data-header-hidden><thead><tr><th width="177.8359375"></th><th width="183.6796875"></th><th width="230.85546875"></th><th></th></tr></thead><tbody><tr><td><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getboolean">getBoolean</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getbooleanall">getBooleanAll</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getdate">getDate</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getdateall">getDateAll</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getdatetime">getDatetime</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getdatetimeall">getDatetimeAll</a></p></td><td><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getdecimal">getDecimal</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getdecimalall">getDecimalAll</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getinteger">getInteger</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getintegerall">getIntegerAll</a></p></td><td><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getstringbylocaleall">getStringByLocaleAll</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getstringnolocale">getStringNoLocale</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getstringnolocaleall">getStringNoLocaleAll</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getstringwithlocale">getStringWithLocale</a><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#getstringwithlocaleall">getStringWithLocaleAll</a></p></td><td><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#gettime">getTime</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#gettimeall">getTimeAll</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#geturl">getUrl</a></p><p><a href="https://inrupt.github.io/solid-client-js/modules/thing_get.html#geturlall">getUrlAll</a></p></td></tr></tbody></table>

{% hint style="info" %}
Note

These types are specific to Solid, i.e. they are not JavaScript types. As such, there is a distinction between integers and decimals as well as a separate type for URLs.
{% endhint %}

To the [get](https://inrupt.github.io/solid-client-js/modules/thing_get.html) function, pass the URL that identifies the property to fetch. To encourage interoperability, various Vocabularies exist to identify common data. For example:

* **`https://schema.org/name`** identifies a string that represents a name of a Thing.

```javascript
  // In this example, use `getStringNoLocale` to get a single string data value from the Thing.
  // (i.e., "https://schema.org/name") value as a string.
  const title = getStringNoLocale(itemForWeek, "https://schema.org/name");
```

### Write Data

#### Write a New SolidDataset

**0. Import**

For the examples, import the following objects from the client libraries:

```javascript
import { login, handleIncomingRedirect, getDefaultSession, fetch } from "@inrupt/solid-client-authn-browser";

import {
  addUrl,
  addStringNoLocale,
  buildThing,
  createSolidDataset,
  createThing,
  setThing,
  saveSolidDatasetAt,
} from "@inrupt/solid-client";
```

**1. Create a new `SolidDataset`**

You can use [createSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#createsoliddataset) to create a new SolidDataset. For example:

```javascript
// Create a new SolidDataset for Writing 101
let courseSolidDataset = createSolidDataset();
```

**2. Create a new `Thing`**

{% tabs %}
{% tab title="Fluent API" %}
First, use [createThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#creatething) to create a new Thing (i.e., data entity) for the SolidDataset. Pass the function a **`name`** for the Thing. Typically, a Thing’s URL is the SolidDataset’s URL appended with a **`#`** hash fragment. Upon save, the specified **`name`** becomes the **`#`** hash fragment; i.e., the Thing’s URL becomes **`<SolidDatasetURL>#<name>.`**

Then, you can use the [buildThing()](https://inrupt.github.io/solid-client-js/modules/thing_build.html#buildthing) and the [ThingBuilder functions](https://inrupt.github.io/solid-client-js/modules/thing_build.html#buildthing) (Fluent API) to generate the Thing with the data modifications.

For example:

```javascript
// Create a new Thing for "book1"; Thing's URL will include the hash #book1.
// Use Fluent API to add properties to the new Thing, and 
// build a new Thing with the properties.
// Note: solid-client functions do not modify objects passed in as arguments. 
// Instead the functions return new objects with the modifications.
const newBookThing1 = buildThing(createThing({ name: "book1" }))
  .addStringNoLocale("https://schema.org/name", "ABC123 of Example Literature")
  .addUrl(RDF.type, "https://schema.org/Book")
  .build();
```

The example creates a new Thing with name `book1` (which will be part of its URL), and using the Fluent API, adds the following Thing properties and value:

<table data-header-hidden><thead><tr><th width="285.83984375"></th><th></th></tr></thead><tbody><tr><td><code>SCHEMA_INRUPT.name</code></td><td><code>"ABC123 of Example Literature"</code></td></tr><tr><td><code>RDF.type</code></td><td><code>"https://schema.org/Book"</code></td></tr></tbody></table>

{% hint style="info" %}
The **`solid-client`** library’s functions (such as the various add/set/remove functions) do not modify the objects that are passed in as arguments. Instead, the library’s functions return a new object with the requested changes, and do not modify the passed-in objects.
{% endhint %}
{% endtab %}

{% tab title="Non-Fluent Alternative" %}
First, use [createThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#creatething) to create a new Thing (i.e., data entity) for the SolidDataset. Pass the function a **name** for the Thing. Typically, a Thing’s URL is the SolidDataset’s URL appended with a # hash fragment. Upon save, the specified **name** becomes the **#** hash fragment; i.e., the Thing’s URL becomes **`<SolidDatasetURL>#<name>`**.

Then, use the series of add/set/remove functions to create a new Thing with the data modifications:

* [thing/add](https://inrupt.github.io/solid-client-js/modules/thing_add.html) functions that return a new Thing modified with new data added,
* [thing/set](https://inrupt.github.io/solid-client-js/modules/thing_set.html) functions that return a new Thing modified with the specified data, and
* [thing/remove](https://inrupt.github.io/solid-client-js/modules/thing_remove.html) functions that return a new Thing modified with specified data removed.

```javascript
// Create a new Thing for "book2"; Thing's URL will include the hash #book2.
// Use various add functions to add properties to the Thing
// Note: solid-client functions do not modify objects passed in as arguments. 
// Instead the functions return new objects with the modifications.
let newBookThing2 = createThing({ name: "book2" });
newBookThing2 = addStringNoLocale(newBookThing2, SCHEMA_INRUPT.name, "ZYX987 of Example Poetry");
newBookThing2 = addUrl(newBookThing2, RDF.type, "https://schema.org/Book");
```

The example creates a new Thing with name `book2` (which will be part of its URL), and using a sequence of [thing/add](https://inrupt.github.io/solid-client-js/modules/thing_add.html) functions to add the following Thing properties:

| `SCHEMA_INRUPT.name` | `"ZYX987 of Example Poetry"` |
| -------------------- | ---------------------------- |
| `RDF.type`           | `"https://schema.org/Book"`  |

{% hint style="info" %}
The solid-client library’s functions (such as the various add/set/remove functions) do not modify the objects that are passed in as arguments. Instead, the library’s functions return a new object with the requested changes, and do not modify the passed-in objects.
{% endhint %}
{% endtab %}
{% endtabs %}

**3. Insert Things into** **`SolidDataset`**

Use [setThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#setthing) to create a SolidDataset that contains the Things.

For example:

```javascript
// Update SolidDataset with the book1 and book2 Things.
// Note: solid-client functions do not modify objects passed in as arguments. 
// Instead the functions return new objects with the modifications.
courseSolidDataset = setThing(courseSolidDataset, newBookThing1);
courseSolidDataset = setThing(courseSolidDataset, newBookThing2);
```

The **`solid-client`** library’s functions (such as the various add/set/remove functions) do not modify the objects that are passed in as arguments. Instead, the library’s functions return a new object with the requested changes, and do not modify the passed-in objects.

**4. Save the `SolidDataset`**

Use [saveSolidDataSetAt](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#savesoliddatasetat) to save the SolidDataset to the Pod and return the SolidDataset. For example:

```javascript
  // Save the SolidDataset at the specified URL.
  // The function returns a SolidDataset that reflects your sent data
  const savedSolidDataset = await saveSolidDatasetAt(
    "https://pod.example.com/universityZ/fall2021/courses/Writing101",
    courseSolidDataset,
    { fetch: fetch }             // fetch from authenticated Session
  );
```

When using [saveSolidDataSetAt](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#savesoliddatasetat), the Solid server creates any intermediary Containers as needed.

#### Modify an Existing SolidDataset

**0. Import**

For the examples, import the following objects from the client libraries:

```javascript
import { login, handleIncomingRedirect, getDefaultSession, fetch } from "@inrupt/solid-client-authn-browser";

import {
  buildThing,
  createThing,
  getSolidDataset,
  getThing,  
  setStringNoLocale,
  setThing,
  saveSolidDatasetAt,
} from "@inrupt/solid-client";

```

**1. Retrieve the `SolidDataset`.**

You can use [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset) to fetch an existing SolidDataset. For example:

```javascript
// Get the SolidDataset for Writing 101 at the specified URL
const resourceURL = "https://pod.example.com/universityZ/fall2021/courses/Writing101";
let courseSolidDataset = await getSolidDataset(
  resourceURL,
  { fetch: fetch }
);
```

**2. Get the `Thing` to Modify**

{% tabs %}
{% tab title="Fluent API" %}
First, you can use [getThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#getthing) to get an existing Thing from the fetched SolidDataset. Pass the function the Thing’s URL. Typically, a Thing’s URL is **`<SolidDatasetURL>#<name>`**,

Then, you can use the [buildThing()](https://inrupt.github.io/solid-client-js/modules/thing_build.html#buildthing) and the [ThingBuilder functions](https://inrupt.github.io/solid-client-js/modules/thing_build.html#buildthing) (Fluent API) to generate the Thing with the data modifications.

For example:

```javascript
// Get the "book1" Thing from the retrieved SolidDataset; the Thing's URL will be the SolidDatatset URL with hash #book1.
// Use Fluent API to add a new property to the Thing, and 
// build a new Thing with the added property.
// Note: solid-client functions do not modify objects passed in as arguments. 
// Instead the functions return new objects with the modifications.
let book1Thing = getThing(courseSolidDataset, `${resourceURL}#book1`);
book1Thing = buildThing(book1Thing)
  .addInteger("https://schema.org/numberOfPages", 30)
  .build();
```

The example gets the **`book1`** Thing, and using the Fluent API, adds the following Thing property and value:

| `"https://schema.org/numberOfPages"` | `30` |
| ------------------------------------ | ---- |

{% hint style="info" %}
The **`solid-client`** library’s functions (such as the various add/set/remove functions) do not modify the objects that are passed in as arguments. Instead, the library’s functions return a new object with the requested changes, and do not modify the passed-in objects.
{% endhint %}
{% endtab %}

{% tab title="Non-Fluent Alternative" %}
First, you can use [getThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#getthing) to get an existing Thing from the fetched SolidDataset. Pass the function the Thing’s URL. Typically, a Thing’s URL is **`<SolidDatasetURL>#<name>`**.

Then, use the series of add/set/remove functions to modify the Thing with the data modifications:

* [thing/add](https://inrupt.github.io/solid-client-js/modules/thing_add.html) functions that return a new Thing modified with new data added,
* [thing/set](https://inrupt.github.io/solid-client-js/modules/thing_set.html) functions that return a new Thing modified with the specified data, and
* [thing/remove](https://inrupt.github.io/solid-client-js/modules/thing_remove.html) functions that return a new Thing modified with specified data removed.

For example:

```javascript
// Get the "book2" Thing from the retrieved SolidDataset; the Thing's URL will be the SolidDatatset URL with hash #book2.
// Use setStringNoLocale to return a new Thing with the name property set to "ZYX987 of Example Poesy"
// Note: solid-client functions do not modify objects passed in as arguments. 
// Instead the functions return new objects with the modifications.
let book2Thing = getThing(courseSolidDataset, `${resourceURL}#book2`);
book2Thing = setStringNoLocale(book2Thing, SCHEMA_INRUPT.name, "ZYX987 of Example Poesy");
```

The example gets the `book2` Thing, and uses a [setStringNoLocale](https://inrupt.github.io/solid-client-js/modules/thing_set.html#setstringnolocale) function to update the Thing’s `SCHEMA_INRUPT.name` value to `"ZYX987 of Example Poesy"`.

{% hint style="info" %}
The **`solid-client`** library’s functions (such as the various add/set/remove functions) do not modify the objects that are passed in as arguments. Instead, the library’s functions return a new object with the requested changes, and do not modify the passed-in objects.
{% endhint %}
{% endtab %}
{% endtabs %}

**3. Create a New `Thing` to Add**

In addition to being able to modify existing Things in the SolidDataset, you can add a new **`Thing`** to the existing SolidDataset.

First, use [createThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#creatething) to create a new Thing (i.e., data entity) for the SolidDataset. Pass the function a **`name`** for the Thing. Typically, a Thing’s URL is the SolidDataset’s URL appended with a **`#`** hash fragment. Upon save, the specified **`name`** becomes the **`#`** hash fragment; i.e., the Thing’s URL becomes **`<SolidDatasetURL>#<name>`**,

Then, you can use the [buildThing()](https://inrupt.github.io/solid-client-js/modules/thing_build.html#buildthing) and the [ThingBuilder functions](https://inrupt.github.io/solid-client-js/modules/thing_build.html#buildthing) (Fluent API) to generate the Thing with the data modifications.

The following example creates a new Thing with the name **`location`** (which will be part of its URL), and uses the Fluent API to add various properties and values.

```javascript
// Create a new Thing for "location"; Thing's URL will include the hash #location.
// Use Fluent API to add properties to the new Thing, and 
// build a new Thing with the properties.
// Note: solid-client functions do not modify objects passed in as arguments. 
// Instead the functions return new objects with the modifications.
const locationThing = buildThing(createThing({ name: "location" }))
  .addStringNoLocale("https://schema.org/name", "Sample Lecture Hall")
  .addUrl(RDF.type, "https://schema.org/Place")
  .build();
```

**4. Update the `SolidDataset` with Modified/New Things**

Use [setThing](https://inrupt.github.io/solid-client-js/modules/thing_thing.html#setthing) to create a SolidDataset with Thing modifications.

For example:

```javascript
// Update SolidDataset with the book1 and book2 and location Things.
// Note: solid-client functions do not modify objects passed in as arguments. 
// Instead the functions return new objects with the modifications.
courseSolidDataset = setThing(courseSolidDataset, book1Thing);
courseSolidDataset = setThing(courseSolidDataset, book2Thing);
courseSolidDataset = setThing(courseSolidDataset, locationThing);
```

In the returned SolidDataset, the **`book1`** and **`book2`** Things have been overwritten and the new **`location`** Thing has been added.

The **`solid-client`** library’s functions (such as the various add/set/remove functions) do not modify the objects that are passed in as arguments. Instead, the library’s functions return a new object with the requested changes, and do not modify the passed-in objects.

**5. Save the `SolidDataset`**

Use [saveSolidDataSetAt](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#savesoliddatasetat) to save the SolidDataset to the Pod and return the SolidDataset. For example:

```javascript
// Save the SolidDataset at the specified URL.
// The function returns a SolidDataset that reflects your sent data
const savedSolidDataset = await saveSolidDatasetAt(
  resourceURL,
  courseSolidDataset,
  { fetch: fetch }             // fetch from authenticated Session
);
```

A SolidDataset keeps track of the data changes compared to the data in the Pod. For **`set`** operations on existing properties, the changelog tracks both the old value and new values of the property being modified.

The save operation applies the changes from the changelog to the current SolidDataset. If the old value specified in the changelog does not correspond to the value currently in the Pod, the save operation will **error**.

#### Save Considerations

#### **Create vs. Update Operations**

[saveSolidDatasetAt](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#savesoliddatasetat) can be used to create new Resource or update an existing Resource in a Pod. If the passed-in Resource has an identifying URL, the function performs an update. If the passed-in Resource has no identifying URL, the function attempts to create a new Resource.

When creating a new Resource, the function adds the precondition that the Resource must not already exist. If the Resource already exists, the server will return a [412 Precondition Failed](https://docs.inrupt.com/sdk/error-codes#id-412-precondition-failed) error.

**Changelog Considerations**

A SolidDataset keeps track of the data changes compared to the data in the Pod. The save operation applies the changes from the changelog to the current SolidDataset:

* For **`add`** operations, the changelog keeps track of additions.
* For **`remove`** operations, the changelog keeps track of the deletions.
* For **`set`** operations, the changelog keeps track of the old and new values. As such, if the old value specified in the changelog does not correspond to the value currently in the Pod, the save operation will **error** with a [409 Conflict](https://docs.inrupt.com/sdk/error-codes#id-409-conflict).

In the [Modify an Existing SolidDataset](#modify-an-existing-soliddataset) example, the locally modified **`courseSolidDataset`** has a changelog that reflects:

* addition of a number of pages property for **`book1`**
* modification of the name property field (from old value to new value) for **`book2`**.
* addition of a new Thing **`location`**

**Scenario 1:** If another operation has modified the name property of **`book2`** after you have retrieved **`courseSolidDataset`** but before you save the locally modified **`courseSolidDataset`**, the save operation errors with [409 Conflict](https://docs.inrupt.com/sdk/error-codes#id-409-conflict).

**Scenario 2:** If another operation has separately added/modified/removed a property from **`book1`** after you have retrieved **`courseSolidDataset`** but before you the locally modified **`courseSolidDataset`**, the save operation succeeds, but the returned SolidDataset only reflects your changes. To make sure the SolidDataset accurately reflects all changes to date, call [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset) again after saving the data.

**Returned SolidDataset**

[saveSolidDatasetAt](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#savesoliddatasetat) returns a SolidDataset that reflects only the sent data. That means, if another process made separate non-conflicting modifications to the SolidDataset after you retrieved the SolidDataset but before you successfully saved, the returned SolidDataset only reflects your changes.

To make sure the SolidDataset reflects not just your changes, call [getSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#getsoliddataset) again after saving the data.

### Delete Data

#### Delete an Existing SolidDataset

{% hint style="info" %}
To delete a SolidDataset, you must have the `Write` access to the SolidDataset and its parent Container.
{% endhint %}

#### Delete API

To delete a SolidDataset from a Pod, you can use [deleteSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#deletesoliddataset) to remove the SolidDataset at the specified URL. To use, pass the function the following parameters:

<table><thead><tr><th width="197.72265625">Parameter</th><th>Value</th></tr></thead><tbody><tr><td>SolidDataset URL</td><td>The URL of the SolidDataset to delete.</td></tr><tr><td>Options object</td><td><p>An object that includes the following option:</p><p><strong><code>{ fetch: &#x3C;fetch func> }</code></strong></p><p><br><strong><code>fetch</code></strong> function from an authenticated session if deleting a restricted Resource (i.e., the general public cannot delete the specified SolidDataset).</p><p>Optional if the general public can delete the Resource.</p></td></tr></tbody></table>

The following example uses [deleteSolidDataset](https://inrupt.github.io/solid-client-js/modules/resource_solidDataset.html#deletesoliddataset) to delete the specified SolidDataset.

```javascript
import { login, handleIncomingRedirect, getDefaultSession, fetch } from "@inrupt/solid-client-authn-browser";

import {
  deleteSolidDataset
} from "@inrupt/solid-client";


// ... Various logic, including login logic, omitted for brevity.

try {
  await deleteSolidDataset(
    "https://pod.example.com/universityZ/fall2021/courses/Writing101", 
    { fetch: fetch }           // fetch function from authenticated session
  );
} catch (error) {
  //...
}
```
