# Writing the Data Layer
###### tags: `module-tutorial` `foundry-vtt`
This is the basic shape of what we're going to end up with.
```js=
class ToDoListData {
// all todos for all users
static get allToDos() {}
// get all todos for a given user
static getToDosForUser(userId) {}
// create a new todo for a given user
static createToDo(userId, toDoData) {}
// update a specific todo by id with the provided updateData
static updateToDo(todoId, updateData) {}
// delete a specific todo by id
static deleteToDo(todoId) {}
}
```
Our "Data Layer" should be a self-contained class which has methods and properties for accessing and editing our `ToDo`s. In our `scripts/todo-list.js` file, define a new class: `ToDoListData`.
```js=
class ToDoListData {
}
```
## I. Read
At most basic, we need a [`method`](https://developer.mozilla.org/en-US/docs/Glossary/Method) which accepts a userId and returns our `toDos` flag.
Since we decided to put ToDos as flags on the [User](https://foundryvtt.com/api/User.html) document, we need to do two things in this method:
1. Get the appropriate user from the [`game.users`](https://foundryvtt.com/api/Users.html) Collection.
1. Leverage [`User#getFlag`](https://foundryvtt.com/api/User.html#getFlag), providing our module as scope, and our flag name as key.
```js=
static getToDosForUser(userId) {
return game.users.get(userId)?.getFlag(ToDoList.ID, ToDoList.FLAGS.TODOS);
}
```
## II. Create
Creating a ToDo is very similar to the process for reading them. We need a method which accepts a `userId` and a new `ToDo`, which then adds the new ToDo to the object on the User flag.
```js=
static createToDo(userId, toDoData) {
// generate a random id for this new ToDo and populate the userId
const newToDo = {
isDone: false,
...toDoData,
id: foundry.utils.randomID(16),
userId,
}
// construct the update to insert the new ToDo
const newToDos = {
[newToDo.id]: newToDo
}
// update the database with the new ToDos
return game.users.get(userId)?.setFlag(ToDoList.id, ToDoList.FLAGS.TODOS, newToDos);
}
```
### Test!
Now that we have both Create and Read API methods defined, we can test things from the browser console.
```
ToDoListData.createToDo(game.userId, {label: 'Foo'});
```
:::danger
Uncaught (in promise) Error: Invalid scope for flag todos
:::
#### Debugging "Invalid scope"
"Invalid scope" is what Foundry Core complains about when we try to set or get a `flag` using a 'scope' argument (the first argument in [`Document#setFlag`](https://foundryvtt.com/api/abstract.Document.html#setFlag)) which does not match an active module's `name`.
Since our module's `name` is `"todo-list"`, when we `User#setFlag` we must use `setFlag('todo-list'...)`.
This is why we defined `ToDoList.ID` as `todo-list`. By setting this up as a constant, we can make sure we avoid typos and it'll be easy enough to change the name down the line if we need to.
Unfortunately we were still able to introduce a typo at the end of our `create` method:
```js=
game.users.get(userId)?.setFlag(ToDoList.id, ToDoList.FLAGS.TODOS, newToDos);
```
We accidentally used `ToDoList.id` instead of `ToDoList.ID`.
Fix that up, refresh Foundry and try again!
## III. Update
Updating an existing `ToDo` is a little tricky. Ideally we would like to only need to provide the ToDo's id and the update data. But since all our ToDos are split up and stored on different individual Users, we currently would need to provide both userId and ToDo id to update any given ToDo.
#### allToDos
To fix this, we would need some mapping of ToDo id to User id. Since our ToDo object has `userId` on it already, this could be accomplished with a big object containing all ToDos for all Users indexed by ToDo id.
We'll leverage `reduce` for this inside a [getter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get).
```js=
static get allToDos() {
const allToDos = game.users.reduce((accumulator, user) => {
const userTodos = this.getToDosForUser(user.id);
return {
...accumulator,
...userTodos
}
}, {});
return allToDos;
}
```
#### updateToDo
Now that we have a way to lookup which User a particular ToDo belongs to we can make an update method that accepts only ToDo id.
```js=
static updateToDo(toDoId, updateData) {
const relevantToDo = this.allToDos[toDoId];
// construct the update to send
const update = {
[toDoId]: updateData
}
// update the database with the updated ToDo list
return game.users.get(relevantToDo.userId)?.setFlag(ToDoList.ID, ToDoList.FLAGS.TODOS, update);
}
```
### Test!
Let's try to edit a ToDo we've already created.
First, use `ToDoListData.allToDos` to see all of the ToDos we have available. If there are none, use `ToDoListData.create` to make one.
```js=
ToDoListData.updateToDo("56r58vm2v197prr8", { label: 'bar' });
```

Success!
## IV. Delete
The last piece to our puzzle for an API which handles ToDos is removing one. Deletion of data is a special case in the Foundry data interaction playbook. At first glance it's as simple as setting our flag to be an object without a specific key in it, but this doesn't actually work how you might expect.
Foundry's [`Document#setFlag`](https://foundryvtt.com/api/abstract.Document.html#setFlag) is an [abstraction](https://developer.mozilla.org/en-US/docs/Glossary/Abstraction) around [`Document#update`](https://foundryvtt.com/api/abstract.Document.html#update). As such, it does not treat an undefined object or key as something which should be deleted. Instead, there is a specific syntax which must be used when we want to tell Foundry's database to delete a key.
```js=
someDocument.update({
['-=someKey']: null
})
```
We can abstract that away behind our method.
```js=
static deleteToDo(toDoId) {
const relevantToDo = this.allToDos[toDoId];
// Foundry specific syntax required to delete a key from a persisted object in the database
const keyDeletion = {
[`-=${toDoId}`]: null
}
// update the database with the updated ToDo list
return game.users.get(relevantToDo.userId)?.setFlag(ToDoList.ID, ToDoList.FLAGS.TODOS, keyDeletion);
}
```
#### Test!
Same as before, get a todo from `ToDoListData.allToDos` and then use our new method to delete it.
```
ToDoListData.deleteToDo('56r58vm2v197prr8');
```

Success!
## V. Bulk Update
There's one last thing we will want to be able to do and that's edit many todos at once. Effectively, we want to be able to handle a bunch of `updateToDo`s with one call.
To accomplish this, we will make a thin wrapper around the `setFlag` method we use in `updateToDo` just as a convience method:
```js=
static updateUserToDos(userId, updateData) {
return game.users.get(userId)?.setFlag(ToDoList.ID, ToDoList.FLAGS.TODOS, updateData);
}
```
#### Test!
Similar to the previous `updateToDo`, but we can affect several toDos at once, as long as they are on the same user.
```
ToDoListData.updateUserToDos('acfkPFqSPy01uJ3p', {
"gogdv4qvgydcr7sh": { isDone: true },
"yndgcuoq147g37nz": { isDone: true },
});
```

Success!
## V. Wrapping Up
We've powered through and written a class to help us handle our ToDo Data. This "ToDo API" is an abstraction on top of Foundry's own abstracted flags methods, but it will allow both us and others an easy way to interact with ToDos specifically.
<details>
<summary>Final ToDoListData class</summary>
```js=
/**
* The data layer for our todo-list module
*/
class ToDoListData {
/**
* get all toDos for all users indexed by the todo's id
*/
static get allToDos() {
const allToDos = game.users.reduce((accumulator, user) => {
const userTodos = this.getToDosForUser(user.id);
return {
...accumulator,
...userTodos
}
}, {});
return allToDos;
}
/**
* Gets all of a given user's ToDos
*
* @param {string} userId - id of the user whose ToDos to return
* @returns {Record<string, ToDo> | undefined}
*/
static getToDosForUser(userId) {
return game.users.get(userId)?.getFlag(ToDoList.ID, ToDoList.FLAGS.TODOS);
}
/**
*
* @param {string} userId - id of the user to add this ToDo to
* @param {Partial<ToDo>} toDoData - the ToDo data to use
*/
static createToDo(userId, toDoData) {
// generate a random id for this new ToDo and populate the userId
const newToDo = {
isDone: false,
label: '',
...toDoData,
id: foundry.utils.randomID(16),
userId,
}
// construct the update to insert the new ToDo
const newToDos = {
[newToDo.id]: newToDo
}
// update the database with the new ToDos
return game.users.get(userId)?.setFlag(ToDoList.ID, ToDoList.FLAGS.TODOS, newToDos);
}
/**
* Updates a given ToDo with the provided data.
*
* @param {string} toDoId - id of the ToDo to update
* @param {Partial<ToDo>} updateData - changes to be persisted
*/
static updateToDo(toDoId, updateData) {
const relevantToDo = this.allToDos[toDoId];
// construct the update to send
const update = {
[toDoId]: updateData
}
// update the database with the updated ToDo list
return game.users.get(relevantToDo.userId)?.setFlag(ToDoList.ID, ToDoList.FLAGS.TODOS, update);
}
/**
* Deletes a given ToDo
*
* @param {string} toDoId - id of the ToDo to delete
*/
static deleteToDo(toDoId) {
const relevantToDo = this.allToDos[toDoId];
// Foundry specific syntax required to delete a key from a persisted object in the database
const keyDeletion = {
[`-=${toDoId}`]: null
}
// update the database with the updated ToDo list
return game.users.get(relevantToDo.userId)?.setFlag(ToDoList.ID, ToDoList.FLAGS.TODOS, keyDeletion);
}
/**
* Updates the given user's ToDos with the provided updateData. This is
* useful for updating a single user's ToDos in bulk.
*
* @param {string} userId - user whose todos we are updating
* @param {object} updateData - data passed to setFlag
* @returns
*/
static updateUserToDos(userId, updateData) {
return game.users.get(userId)?.setFlag(ToDoList.ID, ToDoList.FLAGS.TODOS, updateData);
}
}
```
</details>
Next Steps: [Creating our UI](/yBOfhOcuQJKoH0MitG9mhg)
{%hackmd io_aG7zdTKyRe3cpLcsxzw %}