@powerhousedao/academy 5.1.0-dev.7 → 5.1.0-dev.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +10 -5
  3. package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +116 -213
  4. package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +378 -0
  5. package/docs/academy/01-GetStarted/{04-BuildToDoListEditor.md → 05-BuildToDoListEditor.md} +42 -7
  6. package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/05-VetraStudio.md +47 -6
  7. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +5 -2
  8. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +4 -0
  9. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +4 -0
  10. package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +111 -35
  11. package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +255 -76
  12. package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +281 -160
  13. package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +188 -35
  14. package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +95 -7
  15. package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
  16. package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +171 -0
  17. package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +462 -0
  18. package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +422 -0
  19. package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +384 -0
  20. package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +8 -0
  21. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +2 -2
  22. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +1 -1
  23. package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +6 -2
  24. package/docs/academy/04-APIReferences/01-ReactHooks.md +2 -2
  25. package/docs/academy/{01-GetStarted/07-VetraRemoteDrive.md → 04-APIReferences/06-VetraRemoteDrive.md} +1 -1
  26. package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +28 -28
  27. package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +13 -13
  28. package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +87 -22
  29. package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +7 -39
  30. package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +72 -24
  31. package/docs/academy/08-Glossary.md +7 -0
  32. package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +37 -41
  33. package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +38 -30
  34. package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +24 -16
  35. package/docusaurus.config.ts +20 -0
  36. package/package.json +1 -1
  37. package/sidebars.ts +22 -3
  38. package/src/css/custom.css +27 -0
  39. package/docs/academy/01-GetStarted/06-ReactorMCP.md +0 -58
  40. package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +0 -65
  41. package/docs/academy/05-Architecture/04-MovingBeyondCRUD +0 -61
  42. /package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/images/Modules.png +0 -0
  43. /package/docs/academy/{01-GetStarted → 02-MasteryTrack/01-BuilderEnvironment}/images/VetraStudioDrive.png +0 -0
  44. /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline → 02-RevisionHistoryTimeline/360/237/232/247"} +0 -0
  45. /package/docs/academy/{10-TodoListTutorial → 03-ExampleUsecases/TodoList}/00-GetTheStarterCode.md +0 -0
  46. /package/docs/academy/{10-TodoListTutorial → 03-ExampleUsecases/TodoList}/01-GenerateTodoListDocumentModel.md +0 -0
  47. /package/docs/academy/{10-TodoListTutorial → 03-ExampleUsecases/TodoList}/04-GenerateTodoListDocumentEditor.md +0 -0
  48. /package/docs/academy/{10-TodoListTutorial → 03-ExampleUsecases/TodoList}/06-GenerateTodoDriveExplorer.md +0 -0
  49. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{01-WhatIsADocumentModel → 360/237/232/247 /01-WhatIsADocumentModel"} +0 -0
  50. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{02-DAOandDocumentsModelsQ+A → 360/237/232/247 /02-DAOandDocumentsModelsQ+A"} +0 -0
  51. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{02-domain-modeling → 360/237/232/247 /02-domain-modeling"} +0 -0
  52. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{03-BenefitsOfDocumentModels → 360/237/232/247 /03-BenefitsOfDocumentModels"} +0 -0
  53. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{04-UtilitiesAndTips → 360/237/232/247 /04-UtilitiesAndTips"} +0 -0
  54. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{05-best-practices → 360/237/232/247 /05-best-practices"} +0 -0
  55. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{_category_.json → 360/237/232/247 /_category_.json"} +0 -0
  56. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{three-data-layers.png → 360/237/232/247 /three-data-layers.png"} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 5.1.0-dev.9 (2025-12-05)
2
+
3
+ ### 🩹 Fixes
4
+
5
+ - **renown:** small ui fixes and made connectcrypto and renown id available in hooks ([c06e17226](https://github.com/powerhouse-inc/powerhouse/commit/c06e17226))
6
+
7
+ ### ❤️ Thank You
8
+
9
+ - Frank
10
+
11
+ ## 5.1.0-dev.8 (2025-12-05)
12
+
13
+ This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
14
+
1
15
  ## 5.1.0-dev.7 (2025-12-04)
2
16
 
3
17
  This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
@@ -175,18 +175,23 @@ document-models/todo-list/
175
175
  └── schema.graphql # GraphQL schema
176
176
  ```
177
177
 
178
- ### Compare with reference
178
+ :::tip Check your work
179
179
 
180
- Verify your generated files match the expected structure:
180
+ To make sure everything works as expected:
181
181
 
182
182
  ```bash
183
+ # Check types compile correctly
184
+ pnpm tsc
185
+
186
+ # Check linting passes
187
+ pnpm lint
188
+
183
189
  # Compare your generated files with step-2
184
190
  git diff tutorial/step-2-generate-todo-list-document-model -- document-models/todo-list/
185
-
186
- # List what was generated in the reference
187
- git ls-tree -r --name-only tutorial/step-2-generate-todo-list-document-model document-models/todo-list/
188
191
  ```
189
192
 
193
+ :::
194
+
190
195
  ### Up next: reducers
191
196
 
192
197
  Up next, you'll learn how to implement the runtime logic and components that will use the `TodoList` document model specification you've just created and exported.
@@ -1,70 +1,48 @@
1
- # Implement the document model
1
+ # Implement the document model reducers
2
2
 
3
3
  :::tip Tutorial Repository
4
- 📦 **Reference Code**:
5
- - **Reducer Implementation**: [step-3-implement-reducer-operation-handlers](https://github.com/powerhouse-inc/todo-tutorial/tree/step-3-implement-reducer-operation-handlers)
6
- - **Tests Implementation**: [step-4-implement-tests-for-todos-operations](https://github.com/powerhouse-inc/todo-tutorial/tree/step-4-implement-tests-for-todos-operations)
4
+ 📦 **Reference Code**: [step-3-implement-reducer-operation-handlers](https://github.com/powerhouse-inc/todo-tutorial/tree/step-3-implement-reducer-operation-handlers)
7
5
 
8
- This tutorial covers two steps:
9
- 1. **Step 3**: Implementing the reducer logic for add, update, and delete operations
10
- 2. **Step 4**: Writing comprehensive tests for the reducers
11
-
12
- You can view the exact code changes between steps using `git diff step-3-implement-reducer-operation-handlers step-4-implement-tests-for-todos-operations`
6
+ This step focuses on implementing the reducer logic for add, update, and delete operations.
13
7
  :::
14
8
 
15
9
  <details>
16
10
  <summary>📖 How to use this tutorial</summary>
17
11
 
18
- This tutorial covers **two steps**: implementing reducers (step-3) and tests (step-4).
19
-
20
12
  ### Compare your reducer implementation
21
13
 
22
14
  After implementing your reducers:
23
15
 
24
16
  ```bash
25
- # Compare your reducers with step-3
17
+ # Compare your reducers with the reference
26
18
  git diff tutorial/step-3-implement-reducer-operation-handlers -- document-models/todo-list/src/reducers/
27
19
 
28
20
  # View the reference reducer implementation
29
21
  git show tutorial/step-3-implement-reducer-operation-handlers:document-models/todo-list/src/reducers/todos.ts
30
22
  ```
31
23
 
32
- ### Compare your tests
33
-
34
- After writing tests:
35
-
36
- ```bash
37
- # Compare your tests with step-4
38
- git diff tutorial/step-4-implement-tests-for-todos-operations -- document-models/todo-list/src/tests/
39
-
40
- # See what changed from step-3 to step-4
41
- git diff tutorial/step-3-implement-reducer-operation-handlers..tutorial/step-4-implement-tests-for-todos-operations
42
- ```
43
-
44
24
  ### Visual comparison with GitHub Desktop
45
25
 
46
26
  After committing your work, compare visually:
47
27
  1. **Branch** menu → **"Compare to Branch..."**
48
- 2. Select `tutorial/step-3-implement-reducer-operation-handlers` or `tutorial/step-4-implement-tests-for-todos-operations`
28
+ 2. Select `tutorial/step-3-implement-reducer-operation-handlers`
49
29
  3. Review differences in the visual interface
50
30
 
51
- See step 1 for detailed GitHub Desktop instructions.
52
-
53
31
  ### If you get stuck
54
32
 
55
33
  View or reset to a specific step:
56
34
 
57
35
  ```bash
58
- # View the reducer code from step-3
36
+ # View the reducer code
59
37
  git show tutorial/step-3-implement-reducer-operation-handlers:document-models/todo-list/src/reducers/todos.ts
60
38
 
61
- # Reset to step-3 (WARNING: loses your changes)
39
+ # Reset to this step (WARNING: loses your changes)
62
40
  git reset --hard tutorial/step-3-implement-reducer-operation-handlers
63
41
  ```
64
42
 
65
43
  </details>
66
44
 
67
- In this section, we will implement and test the operation reducers for the **To-do List** document model. For this, you have to export the document model specification from the Connect application and import it into your Powerhouse project directory.
45
+ In this section, we will implement the operation reducers for the **To-do List** document model. For this, you need to export the document model specification from Connect and import it into your Powerhouse project directory.
68
46
 
69
47
  To export the document model specification, follow the steps in the [Define ToDoList Document Model](/academy/GetStarted/DefineToDoListDocumentModel) section.
70
48
 
@@ -86,21 +64,21 @@ Either step will import the document model specification into your Powerhouse pr
86
64
 
87
65
  ![vscode image](./images/vscode.png)
88
66
 
89
- ## In your project directory
67
+ ## Generate the document model code
90
68
 
91
69
  The next steps will take place in the VSCode editor. Make sure to have it open and the terminal window inside VSCode open as well.
92
70
 
93
- To write the operation reducers of the **To-do List** document model, you need to generate the document model code from the document model specification file you have exported into the Powerhouse project directory.
71
+ To write the operation reducers of the **To-do List** document model, you need to generate the document model code from the document model specification file you have exported.
94
72
 
95
- To do this, run the following command in the terminal:
73
+ Run the following command in the terminal:
96
74
 
97
75
  ```bash
98
76
  ph generate TodoList.phd
99
77
  ```
100
78
 
101
- Now you can navigate to `/document-models/todo-list/src/reducers/todos.ts` and start writing the operation reducers.
79
+ ## Explore the generated reducer file
102
80
 
103
- Open the `todos.ts` file and you should see the scaffolding code that needs to be filled for the three operations you have specified earlier. The generated file will look like this:
81
+ Navigate to `/document-models/todo-list/src/reducers/todos.ts` and open it. You should see scaffolding code that needs to be filled for the three operations you specified:
104
82
 
105
83
  ```typescript
106
84
  import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
@@ -121,224 +99,149 @@ export const todoListTodosOperations: TodoListTodosOperations = {
121
99
  };
122
100
  ```
123
101
 
124
- ## Write the operation reducers
102
+ ## Implement the operation reducers
125
103
 
126
- 1. Copy and paste the code below into the `todos.ts` file in the `reducers` folder.
127
- 2. Save the file.
104
+ Let's implement each reducer one by one.
128
105
 
129
- <details>
130
- <summary>Operation Reducers</summary>
106
+ ### Step 1: Add the import
107
+
108
+ First, add the `generateId` import at the top of the file:
131
109
 
132
110
  ```typescript
111
+ // added-line
133
112
  import { generateId } from "document-model/core";
134
113
  import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
114
+ ```
115
+
116
+ ### Step 2: Implement addTodoItemOperation
135
117
 
136
- // Export the operations object that implements all three todo operations
118
+ Replace the boilerplate `addTodoItemOperation` with the actual implementation:
119
+
120
+ ```typescript
137
121
  export const todoListTodosOperations: TodoListTodosOperations = {
122
+ // removed-start
123
+ addTodoItemOperation(state, action) {
124
+ // TODO: Implement "addTodoItemOperation" reducer
125
+ throw new Error('Reducer "addTodoItemOperation" not yet implemented');
126
+ },
127
+ // removed-end
128
+ // added-start
138
129
  addTodoItemOperation(state, action) {
139
- // Generate a unique ID for the new todo item
140
- // Using generateId() from document-model/core ensures uniqueness
141
130
  const id = generateId();
142
-
143
- // Add the new item to the state
144
- // Powerhouse uses Immer.js, so this "mutation" is actually immutable
145
131
  state.items.push({ ...action.input, id, checked: false });
146
132
  },
147
-
133
+ // added-end
148
134
  updateTodoItemOperation(state, action) {
149
- // Find the item to update by its ID
150
- const item = state.items.find((item) => item.id === action.input.id);
151
-
152
- // Return early if item not found (you could also throw an error)
153
- if (!item) return;
154
-
155
- // Update only the fields that are provided (partial update)
156
- // Using nullish coalescing (??) to keep existing values if undefined
157
- item.text = action.input.text ?? item.text;
158
- item.checked = action.input.checked ?? item.checked;
135
+ // ...
159
136
  },
160
-
161
137
  deleteTodoItemOperation(state, action) {
162
- // Filter out the item with the matching ID
163
- // This creates a new array without the deleted item
164
- state.items = state.items.filter((item) => item.id !== action.input.id);
138
+ // ...
165
139
  },
166
140
  };
141
+ ```
167
142
 
168
- ````
169
- </details>
143
+ **What's happening here:**
144
+ - We generate a unique ID using `generateId()` from `document-model/core`
145
+ - We push a new item to the `items` array with the input text, new ID, and `checked: false`
146
+ - Under the hood, Powerhouse uses Immer.js, so this "mutation" is actually immutable
170
147
 
171
- ## Write the operation reducers tests
148
+ ### Step 3: Implement updateTodoItemOperation
172
149
 
173
- In order to make sure the operation reducers are working as expected, you need to write tests for them.
150
+ Replace the boilerplate `updateTodoItemOperation`:
174
151
 
175
- Navigate to `/document-models/todo-list/src/tests/todos.test.ts` and replace the scaffolding code with comprehensive tests.
152
+ ```typescript
153
+ // removed-start
154
+ updateTodoItemOperation(state, action) {
155
+ // TODO: Implement "updateTodoItemOperation" reducer
156
+ throw new Error('Reducer "updateTodoItemOperation" not yet implemented');
157
+ },
158
+ // removed-end
159
+ // added-start
160
+ updateTodoItemOperation(state, action) {
161
+ const item = state.items.find((item) => item.id === action.input.id);
162
+ if (!item) return;
163
+ item.text = action.input.text ?? item.text;
164
+ item.checked = action.input.checked ?? item.checked;
165
+ },
166
+ // added-end
167
+ ```
176
168
 
177
- Here are the tests for the three operations implemented in the reducers file. The test file:
178
- - Uses Vitest for testing
179
- - Generates mock data using `@powerhousedao/codegen`
180
- - Creates an empty TodoList document model
181
- - Tests add, update, and delete operations
182
- - Verifies both the operation history and the resulting state
169
+ **What's happening here:**
170
+ - We find the item by its ID
171
+ - We return early if the item is not found
172
+ - We use nullish coalescing (`??`) to only update fields that are provided
183
173
 
184
- <details>
185
- <summary>Operation Reducers Tests</summary>
174
+ ### Step 4: Implement deleteTodoItemOperation
175
+
176
+ Replace the boilerplate `deleteTodoItemOperation`:
186
177
 
187
178
  ```typescript
188
- import { describe, it, expect } from "vitest";
189
- import { generateMock } from "@powerhousedao/codegen";
190
- import type {
191
- AddTodoItemInput,
192
- DeleteTodoItemInput,
193
- UpdateTodoItemInput,
194
- } from "todo-tutorial/document-models/todo-list";
195
- import {
196
- reducer,
197
- utils,
198
- isTodoListDocument,
199
- addTodoItem,
200
- AddTodoItemInputSchema,
201
- updateTodoItem,
202
- UpdateTodoItemInputSchema,
203
- deleteTodoItem,
204
- DeleteTodoItemInputSchema,
205
- TodoItemSchema,
206
- } from "todo-tutorial/document-models/todo-list";
207
-
208
- describe("Todos Operations", () => {
209
- // Test adding a new todo item
210
- it("should handle addTodoItem operation", () => {
211
- const document = utils.createDocument();
212
- const input: AddTodoItemInput = generateMock(AddTodoItemInputSchema());
213
-
214
- const updatedDocument = reducer(document, addTodoItem(input));
215
- expect(isTodoListDocument(updatedDocument)).toBe(true);
216
-
217
- // Verify the operation was recorded
218
- expect(updatedDocument.operations.global).toHaveLength(1);
219
- expect(updatedDocument.operations.global[0].action.type).toBe("ADD_TODO_ITEM");
220
- expect(updatedDocument.operations.global[0].action.input).toStrictEqual(input);
221
- expect(updatedDocument.operations.global[0].index).toEqual(0);
222
- });
223
-
224
- // Test updating a todo item's text
225
- it("should handle updateTodoItem operation to update text", () => {
226
- const mockItem = generateMock(TodoItemSchema());
227
- const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
228
- input.id = mockItem.id;
229
- const newText = "new text";
230
- input.text = newText;
231
- input.checked = undefined;
232
-
233
- const document = utils.createDocument({
234
- global: {
235
- items: [mockItem],
236
- },
237
- });
238
-
239
- const updatedDocument = reducer(document, updateTodoItem(input));
240
- expect(isTodoListDocument(updatedDocument)).toBe(true);
241
-
242
- // Verify the operation was recorded
243
- expect(updatedDocument.operations.global).toHaveLength(1);
244
- expect(updatedDocument.operations.global[0].action.type).toBe("UPDATE_TODO_ITEM");
245
-
246
- // Verify the state was updated correctly
247
- const updatedItem = updatedDocument.state.global.items.find(
248
- (item) => item.id === input.id,
249
- );
250
- expect(updatedItem?.text).toBe(newText);
251
- expect(updatedItem?.checked).toBe(mockItem.checked);
252
- });
253
-
254
- // Test updating a todo item's checked status
255
- it("should handle updateTodoItem operation to update checked", () => {
256
- const mockItem = generateMock(TodoItemSchema());
257
- const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
258
- input.id = mockItem.id;
259
- const newChecked = !mockItem.checked;
260
- input.checked = newChecked;
261
- input.text = undefined;
262
-
263
- const document = utils.createDocument({
264
- global: {
265
- items: [mockItem],
266
- },
267
- });
268
-
269
- const updatedDocument = reducer(document, updateTodoItem(input));
270
- expect(isTodoListDocument(updatedDocument)).toBe(true);
271
-
272
- const updatedItem = updatedDocument.state.global.items.find(
273
- (item) => item.id === input.id,
274
- );
275
- expect(updatedItem?.text).toBe(mockItem.text);
276
- expect(updatedItem?.checked).toBe(newChecked);
277
- });
278
-
279
- // Test deleting a todo item
280
- it("should handle deleteTodoItem operation", () => {
281
- const mockItem = generateMock(TodoItemSchema());
282
- const document = utils.createDocument({
283
- global: {
284
- items: [mockItem],
285
- },
286
- });
287
-
288
- const input: DeleteTodoItemInput = generateMock(DeleteTodoItemInputSchema());
289
- input.id = mockItem.id;
290
-
291
- const updatedDocument = reducer(document, deleteTodoItem(input));
292
- expect(isTodoListDocument(updatedDocument)).toBe(true);
293
-
294
- // Verify the operation was recorded
295
- expect(updatedDocument.operations.global).toHaveLength(1);
296
- expect(updatedDocument.operations.global[0].action.type).toBe("DELETE_TODO_ITEM");
297
-
298
- // Verify the item was removed from state
299
- const updatedItems = updatedDocument.state.global.items;
300
- expect(updatedItems).toHaveLength(0);
301
- });
302
- });
179
+ // removed-start
180
+ deleteTodoItemOperation(state, action) {
181
+ // TODO: Implement "deleteTodoItemOperation" reducer
182
+ throw new Error('Reducer "deleteTodoItemOperation" not yet implemented');
183
+ },
184
+ // removed-end
185
+ // added-start
186
+ deleteTodoItemOperation(state, action) {
187
+ state.items = state.items.filter((item) => item.id !== action.input.id);
188
+ },
189
+ // added-end
303
190
  ```
304
191
 
305
- </details>
192
+ **What's happening here:**
193
+ - We filter out the item with the matching ID
194
+ - This creates a new array without the deleted item
306
195
 
307
- Now you can run the tests to make sure the operation reducers are working as expected.
196
+ ## Complete reducer file
308
197
 
309
- ```bash
310
- pnpm run test
311
- ```
198
+ Here's the complete implementation:
312
199
 
313
- Output should be as follows:
200
+ <details>
201
+ <summary>Complete todos.ts</summary>
314
202
 
315
- ```bash
316
- document-models/todo-list/src/tests/document-model.test.ts (3 tests) 1ms
317
- document-models/todo-list/src/tests/todos.test.ts (4 tests) 8ms
203
+ ```typescript
204
+ import { generateId } from "document-model/core";
205
+ import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
318
206
 
319
- Test Files 2 passed (2)
320
- Tests 7 passed (7)
321
- Start at 19:37:33
322
- Duration 1.84s (transform 75ms, setup 0ms, collect 2.03s, tests 9ms, environment 0ms, prepare 92ms)
207
+ export const todoListTodosOperations: TodoListTodosOperations = {
208
+ addTodoItemOperation(state, action) {
209
+ const id = generateId();
210
+ state.items.push({ ...action.input, id, checked: false });
211
+ },
212
+
213
+ updateTodoItemOperation(state, action) {
214
+ const item = state.items.find((item) => item.id === action.input.id);
215
+ if (!item) return;
216
+ item.text = action.input.text ?? item.text;
217
+ item.checked = action.input.checked ?? item.checked;
218
+ },
219
+
220
+ deleteTodoItemOperation(state, action) {
221
+ state.items = state.items.filter((item) => item.id !== action.input.id);
222
+ },
223
+ };
323
224
  ```
324
225
 
325
- If you got the same output, you have successfully implemented the operation reducers and tests for the **To-do List** document model. Congratulations, you've successfully set up the backbone for a simple **To-do List** document.
226
+ </details>
326
227
 
327
- ## Compare with reference branches
228
+ :::tip Check your work
328
229
 
329
- Verify your implementation matches the tutorial steps:
230
+ To make sure everything works as expected:
330
231
 
331
232
  ```bash
332
- # View step-3 reducer implementation
333
- git show tutorial/step-3-implement-reducer-operation-handlers:document-models/todo-list/src/reducers/todos.ts
233
+ # Check types compile correctly
234
+ pnpm tsc
334
235
 
335
- # View step-4 test implementation
336
- git show tutorial/step-4-implement-tests-for-todos-operations:document-models/todo-list/src/tests/todos.test.ts
236
+ # Check linting passes
237
+ pnpm lint
337
238
 
338
- # See what changed between step-3 and step-4
339
- git diff tutorial/step-3-implement-reducer-operation-handlers..tutorial/step-4-implement-tests-for-todos-operations
239
+ # Compare with reference implementation
240
+ git diff tutorial/step-3-implement-reducer-operation-handlers -- document-models/todo-list/src/reducers/
340
241
  ```
341
242
 
342
- ## Up next: To-do list editor
243
+ :::
244
+
245
+ ## Up next: Writing tests
343
246
 
344
- In the next chapter of this introduction track you will learn how to implement an editor for your document model so you can see a simple user interface for the **To-do List** document model in action.
247
+ In the next chapter, you'll write comprehensive tests to verify your reducer implementations work correctly.