@powerhousedao/academy 5.1.0-staging.0 → 5.1.0

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 (76) hide show
  1. package/CHANGELOG.md +46 -1148
  2. package/blog/BeyondCommunication-ABlueprintForDevelopment.md +1 -2
  3. package/blog/TheChallengeOfChange.md +0 -1
  4. package/docs/academy/00-EthereumArgentinaHackathon.md +207 -0
  5. package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +27 -24
  6. package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +10 -155
  7. package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +35 -122
  8. package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +155 -178
  9. package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +218 -0
  10. package/docs/academy/{02-MasteryTrack/01-BuilderEnvironment → 01-GetStarted}/05-VetraStudio.md +22 -62
  11. package/docs/academy/01-GetStarted/06-ReactorMCP.md +58 -0
  12. package/docs/academy/01-GetStarted/_04-BuildToDoListEditor +1 -1
  13. package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +2 -2
  14. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +44 -75
  15. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +22 -28
  16. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +31 -28
  17. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +206 -211
  18. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +62 -176
  19. package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +0 -21
  20. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +319 -309
  21. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +0 -4
  22. package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +0 -4
  23. package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -1
  24. package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +35 -111
  25. package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +79 -195
  26. package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +241 -435
  27. package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +27 -388
  28. package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +7 -95
  29. package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
  30. package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +2 -6
  31. package/docs/academy/04-APIReferences/01-ReactHooks.md +501 -291
  32. package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +39 -7
  33. package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +65 -0
  34. package/docs/academy/05-Architecture/04-MovingBeyondCRUD +61 -0
  35. package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +24 -72
  36. package/docs/academy/08-Glossary.md +0 -7
  37. package/docusaurus.config.ts +3 -28
  38. package/package.json +1 -1
  39. package/sidebars.ts +13 -49
  40. package/src/css/custom.css +18 -26
  41. package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +0 -425
  42. package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +0 -557
  43. package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/images/Modules.png +0 -0
  44. package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/images/VetraStudioDrive.png +0 -0
  45. package/docs/academy/02-MasteryTrack/05-Launch/05-DockerDeployment.md +0 -384
  46. package/docs/academy/03-ExampleUsecases/TodoList/00-GetTheStarterCode.md +0 -24
  47. package/docs/academy/03-ExampleUsecases/TodoList/01-GenerateTodoListDocumentModel.md +0 -211
  48. package/docs/academy/03-ExampleUsecases/TodoList/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
  49. package/docs/academy/03-ExampleUsecases/TodoList/03-AddTestsForTodoListActions.md +0 -462
  50. package/docs/academy/03-ExampleUsecases/TodoList/04-GenerateTodoListDocumentEditor.md +0 -45
  51. package/docs/academy/03-ExampleUsecases/TodoList/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
  52. package/docs/academy/03-ExampleUsecases/TodoList/06-GenerateTodoDriveExplorer.md +0 -61
  53. package/docs/academy/03-ExampleUsecases/TodoList/07-AddSharedComponentForShowingTodoListStats.md +0 -384
  54. package/docs/academy/03-ExampleUsecases/TodoList/_category_.json +0 -8
  55. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/VetraPackageLibrary.md +0 -7
  56. package/docs/academy/03-ExampleUsecases/VetraPackageLibrary/_category_.json +0 -9
  57. package/docs/academy/04-APIReferences/06-VetraRemoteDrive.md +0 -160
  58. package/docs/academy/04-APIReferences/renown-sdk/00-Overview.md +0 -316
  59. package/docs/academy/04-APIReferences/renown-sdk/01-Authentication.md +0 -672
  60. package/docs/academy/04-APIReferences/renown-sdk/02-APIReference.md +0 -957
  61. package/docs/academy/04-APIReferences/renown-sdk/_category_.json +0 -8
  62. package/docs/academy/10-TodoListTutorial/02-ImplementTodoListDocumentModelReducerOperationHandlers.md +0 -171
  63. package/docs/academy/10-TodoListTutorial/03-AddTestsForTodoListActions.md +0 -462
  64. package/docs/academy/10-TodoListTutorial/05-ImplementTodoListDocumentEditorUIComponents.md +0 -422
  65. package/docs/academy/10-TodoListTutorial/07-AddSharedComponentForShowingTodoListStats.md +0 -370
  66. package/static/img/Vetra-logo-dark.svg +0 -11
  67. package/static/img/vetra-logo-light.svg +0 -11
  68. /package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/{02-RevisionHistoryTimeline/360/237/232/247" → 02-RevisionHistoryTimeline} +0 -0
  69. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /01-WhatIsADocumentModel" → 01-WhatIsADocumentModel} +0 -0
  70. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-DAOandDocumentsModelsQ+A" → 02-DAOandDocumentsModelsQ+A} +0 -0
  71. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /02-domain-modeling" → 02-domain-modeling} +0 -0
  72. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /03-BenefitsOfDocumentModels" → 03-BenefitsOfDocumentModels} +0 -0
  73. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /04-UtilitiesAndTips" → 04-UtilitiesAndTips} +0 -0
  74. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /05-best-practices" → 05-best-practices} +0 -0
  75. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /_category_.json" → _category_.json} +0 -0
  76. /package/docs/academy/05-Architecture/05-DocumentModelTheory/{360/237/232/247 /three-data-layers.png" → three-data-layers.png} +0 -0
@@ -1,64 +1,15 @@
1
1
  # Write the document specification
2
2
 
3
- :::tip Tutorial Repository
4
- 📦 **Reference Code**: [step-2-generate-todo-list-document-model](https://github.com/powerhouse-inc/todo-tutorial/tree/step-2-generate-todo-list-document-model)
5
-
6
- This tutorial step has a corresponding branch. After completing this step, your project will have a generated document model with:
7
- - Document model specification files (`todo-list.json`, `schema.graphql`)
8
- - Auto-generated TypeScript types and action creators
9
- - Reducer scaffolding ready for implementation
10
- :::
11
-
12
- <details>
13
- <summary>📖 How to use this tutorial</summary>
14
-
15
- **Prerequisites**: Complete step 1 and set up the tutorial remote (see previous step).
16
-
17
- ### Compare your generated code
18
-
19
- After running `ph generate TodoList.phdm.zip`, compare with the reference:
20
-
21
- ```bash
22
- # Compare all generated files with step-2
23
- git diff tutorial/step-2-generate-todo-list-document-model
24
-
25
- # Compare specific directory
26
- git diff tutorial/step-2-generate-todo-list-document-model -- document-models/todo-list/
27
- ```
28
-
29
- ### See what was generated
30
-
31
- View the complete step-2 reference code:
32
-
33
- ```bash
34
- # List files in the tutorial's step-2
35
- git ls-tree -r --name-only tutorial/step-2-generate-todo-list-document-model document-models/
36
-
37
- # View a specific file from step-2
38
- git show tutorial/step-2-generate-todo-list-document-model:document-models/todo-list/schema.graphql
39
- ```
40
-
41
- ### Visual comparison with GitHub Desktop
42
-
43
- After making a commit, use GitHub Desktop for visual diff:
44
- 1. **Branch** menu → **"Compare to Branch..."**
45
- 2. Select `tutorial/step-2-generate-todo-list-document-model`
46
- 3. Review all file differences in the visual interface
47
-
48
- See step 1 for detailed GitHub Desktop instructions.
49
-
50
- </details>
51
-
52
- In this tutorial, you will learn how to define the specifications for a **To-do List** document model within Vetra Studio using its GraphQL schema, and then export the resulting document model specification document for your Powerhouse project.
3
+ In this tutorial, you will learn how to define the specifications for a **To-do List** document model within the Connect application using its GraphQL schema, and then export the resulting document model specification document for your Powerhouse project.
53
4
  If you don't have a document specification file created yet, have a look at the previous step of this tutorial to create a new document specification.
54
5
 
55
- Before you start, make sure you have Vetra Studio running locally with the command:
6
+ Before you start, make sure you have the Connect application running locally with the command:
56
7
 
57
8
  ```bash
58
- ph vetra
9
+ ph connect
59
10
  ```
60
11
 
61
- Vetra Studio will start and you will see the following output:
12
+ The Connect application will start and you will see the following output:
62
13
 
63
14
  ```bash
64
15
  ➜ Local: http://localhost:3000/
@@ -66,13 +17,14 @@ Vetra Studio will start and you will see the following output:
66
17
  ➜ press h + enter to show help
67
18
  ```
68
19
 
69
- ## TodoList document specification
20
+ ## To-do list document specification
70
21
 
71
- Make sure you have named your document model `TodoList` (PascalCase, no spaces or hyphens).
72
- **Pay close attention to capitalization, as it influences our code generation.**
22
+ Likely you have called your project 'ToDoList'.
23
+ If you've used a different name, please create a new document specification named 'ToDoList'.
24
+ **Pay close attention to capitalization, as it influences our code.**
73
25
 
74
26
  We'll continue with this project to teach you how to create a document model specification and later an editor for your document model. We use the **GraphQL Schema Definition Language** (SDL) to define the schema for the document model.
75
- Below, you can see the SDL for the `TodoList` document model.
27
+ Below, you can see the SDL for the `To-do List` document model.
76
28
 
77
29
  :::info
78
30
  This schema defines the **data structure** of the document model and the types involved in its operations, which are detailed further as input types.
@@ -80,49 +32,48 @@ Documents in Powerhouse leverage **event sourcing principles**, where every stat
80
32
  :::
81
33
 
82
34
  <details>
83
- <summary>State schema of our simplified TodoList</summary>
35
+ <summary>State schema of our simplified To-do list</summary>
84
36
 
85
37
  ```graphql
86
- # The state of our TodoList - contains an array of todo items
87
- type TodoListState {
88
- items: [TodoItem!]!
38
+ # The state of our ToDoList
39
+ type ToDoListState {
40
+ items: [ToDoItem!]!
89
41
  }
90
42
 
91
- # A single to-do item with its properties
92
- type TodoItem {
93
- id: OID! # Unique identifier for each to-do item
94
- text: String! # The text description of the to-do item
95
- checked: Boolean! # Status of the to-do item (checked/unchecked)
43
+ # A single to-do item
44
+ type ToDoItem {
45
+ id: ID!
46
+ text: String!
47
+ checked: Boolean!
96
48
  }
97
49
  ```
98
50
 
99
51
  </details>
100
52
 
101
53
  <details>
102
- <summary>Operations schema of our simplified TodoList</summary>
103
-
54
+ <summary>Operations schema of our simplified to-do list</summary>
104
55
  ```graphql
105
56
  # Defines a GraphQL input type for adding a new to-do item
106
- # Only text is required - ID is generated automatically, checked defaults to false
107
57
  input AddTodoItemInput {
108
- text: String! # The text for the new todo item
58
+ id: ID!
59
+ text: String!
109
60
  }
110
61
 
111
62
  # Defines a GraphQL input type for updating a to-do item
112
- # ID is required to identify which item to update
113
- # text and checked are optional - only provided fields will be updated
63
+
114
64
  input UpdateTodoItemInput {
115
- id: OID! # Required: which item to update
116
- text: String # Optional: new text value
117
- checked: Boolean # Optional: new checked state
65
+ id: ID!
66
+ text: String
67
+ checked: Boolean
118
68
  }
119
69
 
120
70
  # Defines a GraphQL input type for deleting a to-do item
71
+
121
72
  input DeleteTodoItemInput {
122
- id: OID! # The ID of the item to delete
73
+ id: ID!
123
74
  }
124
- ```
125
75
 
76
+ ````
126
77
  </details>
127
78
 
128
79
  ## Define the document model specification
@@ -131,21 +82,22 @@ To be able to define the document model, you need to open the document model edi
131
82
 
132
83
  ### The steps below show you how to do this:
133
84
 
134
- 1. In Vetra Studio, click on **'document model'** to open the document model specification editor.
135
- 2. Name your document model `TodoList` (PascalCase, no spaces or hyphens) in the Connect application. **Pay close attention to capitalization, as it influences code generation.**
85
+ 1. In the Connect application, click on **'document model'** to open the document model specification editor.
86
+ 2. Name your document model '**ToDoList**' in the Connect application, paying close attention to capitalization.
136
87
  3. You'll be presented with a form to fill in metadata about the document model. Fill in the details in the respective fields.
137
88
 
138
- In the **Document Type** field, type `powerhouse/todo-list` (lowercase with hyphen). This defines the new type of document that will be created with this document model specification.
89
+ In the **Document Type** field, type `powerhouse/todolist`. This defines the new type of document that will be created with this document model specification.
139
90
 
140
- ![TodoList Document Model Form Metadata](./images/DocumentModelHeader.png)
91
+ ![ToDoList Document Model Form Metadata](./images/DocumentModelHeader.png)
141
92
 
142
93
  4. In the code editor, you can see the SDL for the document model. Replace the existing SDL template with the SDL defined in the [State Schema](#state-schema) section. Only copy and paste the types, leaving the inputs for the next step. You can, however, already press the 'Sync with schema' button to set the initial state of your document model specification based on your Schema Definition Language.
143
- 5. Below the editor, find the input field `Add module`. You'll use this to create and name a module for organizing your input operations. In this case, we will name the module `todos`. Press enter.
94
+ 5. Below the editor, find the input field `Add module`. You'll use this to create and name a module for organizing your input operations. In this case, we will name the module `to_do_list`. Press enter.
144
95
  6. Now there is a new field, called `Add operation`. Here you will have to add each input operation to the module, one by one.
145
96
  7. Inside the `Add operation` field, type `ADD_TODO_ITEM` and press enter. A small editor will appear underneath it, with an empty input type that you have to fill. Copy the first input type from the [Operations Schema](#operations-schema) section and paste it in the editor. The editor should look like this:
146
97
 
147
98
  ```graphql
148
99
  input AddTodoItemInput {
100
+ id: ID!
149
101
  text: String!
150
102
  }
151
103
  ```
@@ -158,46 +110,7 @@ Check below screenshot for the complete implementation:
158
110
 
159
111
  ![ToDoList Document Model](./images/DocumentModelOperations.png)
160
112
 
161
- ## Verify your document model generation
162
-
163
- If you have been watching the terminal in your IDE you will see that Vetra has been tracking your changes and scaffolding your directory. Your project should have the following structure in `document-models/todo-list/`:
164
-
165
- ```
166
- document-models/todo-list/
167
- ├── gen/ # Auto-generated code (don't edit)
168
- │ ├── actions.ts
169
- │ ├── creators.ts # Action creator functions
170
- │ ├── types.ts # TypeScript type definitions
171
- │ ├── reducer.ts
172
- │ └── todos/
173
- │ └── operations.ts # Operation type definitions
174
- ├── src/ # Your custom implementation
175
- │ ├── reducers/
176
- │ │ └── todos.ts # Reducer functions (to implement next)
177
- │ └── tests/
178
- │ └── todos.test.ts # Test file scaffolding
179
- ├── todo-list.json # Document model specification
180
- └── schema.graphql # GraphQL schema
181
- ```
182
-
183
- :::tip Check your work
184
-
185
- To make sure everything works as expected:
186
-
187
- ```bash
188
- # Check types compile correctly
189
- pnpm tsc
190
-
191
- # Check linting passes
192
- pnpm lint
193
-
194
- # Compare your generated files with step-2
195
- git diff tutorial/step-2-generate-todo-list-document-model -- document-models/todo-list/
196
- ```
197
-
198
- :::
199
-
200
113
  ### Up next: reducers
201
114
 
202
- 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.
115
+ 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.
203
116
 
@@ -1,48 +1,8 @@
1
- # Implement the document model reducers
1
+ # Implement the document model
2
2
 
3
- :::tip Tutorial Repository
4
- 📦 **Reference Code**: [step-3-implement-reducer-operation-handlers](https://github.com/powerhouse-inc/todo-tutorial/tree/step-3-implement-reducer-operation-handlers)
3
+ 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.
5
4
 
6
- This step focuses on implementing the reducer logic for add, update, and delete operations.
7
- :::
8
-
9
- <details>
10
- <summary>📖 How to use this tutorial</summary>
11
-
12
- ### Compare your reducer implementation
13
-
14
- After implementing your reducers:
15
-
16
- ```bash
17
- # Compare your reducers with the reference
18
- git diff tutorial/step-3-implement-reducer-operation-handlers -- document-models/todo-list/src/reducers/
19
-
20
- # View the reference reducer implementation
21
- git show tutorial/step-3-implement-reducer-operation-handlers:document-models/todo-list/src/reducers/todos.ts
22
- ```
23
-
24
- ### Visual comparison with GitHub Desktop
25
-
26
- After committing your work, compare visually:
27
- 1. **Branch** menu → **"Compare to Branch..."**
28
- 2. Select `tutorial/step-3-implement-reducer-operation-handlers`
29
- 3. Review differences in the visual interface
30
-
31
- ### If you get stuck
32
-
33
- View or reset to a specific step:
34
-
35
- ```bash
36
- # View the reducer code
37
- git show tutorial/step-3-implement-reducer-operation-handlers:document-models/todo-list/src/reducers/todos.ts
38
-
39
- # Reset to this step (WARNING: loses your changes)
40
- git reset --hard tutorial/step-3-implement-reducer-operation-handlers
41
- ```
42
-
43
- </details>
44
-
45
- In this section, we will implement the operation reducers for the **To-do List** document model. In the previous step Vetra imported our document specification and scaffolded our directory through code generation. If not, you can revisit the [Define TodoList Document Model](/academy/GetStarted/DefineToDoListDocumentModel) section.
5
+ To export the document model specification, follow the steps in the [Define ToDoList Document Model](/academy/GetStarted/DefineToDoListDocumentModel) section.
46
6
 
47
7
  ## Understanding reducers in document models
48
8
 
@@ -53,172 +13,189 @@ Reducers are a core concept in Powerhouse document models. They implement the st
53
13
  The reducers provide the actual implementation of what happens when those operations are performed.
54
14
  :::
55
15
 
56
- ## Explore the generated reducer file
16
+ To import the document model specification into your Powerhouse project, you can either:
57
17
 
58
- 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:
18
+ - Copy and paste the file directly into the root of your Powerhouse project.
19
+ - Or drag and drop the file into the Powerhouse project directory in the VSCode editor as seen in the image below:
59
20
 
60
- ```typescript
61
- import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
62
-
63
- export const todoListTodosOperations: TodoListTodosOperations = {
64
- addTodoItemOperation(state, action) {
65
- // TODO: Implement "addTodoItemOperation" reducer
66
- throw new Error('Reducer "addTodoItemOperation" not yet implemented');
67
- },
68
- updateTodoItemOperation(state, action) {
69
- // TODO: Implement "updateTodoItemOperation" reducer
70
- throw new Error('Reducer "updateTodoItemOperation" not yet implemented');
71
- },
72
- deleteTodoItemOperation(state, action) {
73
- // TODO: Implement "deleteTodoItemOperation" reducer
74
- throw new Error('Reducer "deleteTodoItemOperation" not yet implemented');
75
- },
76
- };
77
- ```
21
+ Either step will import the document model specification into your Powerhouse project.
78
22
 
79
- ## Implement the operation reducers
23
+ ![vscode image](./images/vscode.png)
80
24
 
81
- Let's implement each reducer one by one.
25
+ ## In your project directory
82
26
 
83
- ### Step 1: Add the import
27
+ 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.
84
28
 
85
- First, add the `generateId` import at the top of the file:
29
+ 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.
86
30
 
87
- ```typescript
88
- // added-line
89
- import { generateId } from "document-model/core";
90
- import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
91
- ```
92
-
93
- ### Step 2: Implement addTodoItemOperation
31
+ To do this, run the following command in the terminal:
94
32
 
95
- Replace the boilerplate `addTodoItemOperation` with the actual implementation:
96
-
97
- ```typescript
98
- export const todoListTodosOperations: TodoListTodosOperations = {
99
- // removed-start
100
- addTodoItemOperation(state, action) {
101
- // TODO: Implement "addTodoItemOperation" reducer
102
- throw new Error('Reducer "addTodoItemOperation" not yet implemented');
103
- },
104
- // removed-end
105
- // added-start
106
- addTodoItemOperation(state, action) {
107
- const id = generateId();
108
- state.items.push({ ...action.input, id, checked: false });
109
- },
110
- // added-end
111
- updateTodoItemOperation(state, action) {
112
- // ...
113
- },
114
- deleteTodoItemOperation(state, action) {
115
- // ...
116
- },
117
- };
33
+ ```bash
34
+ ph generate ToDoList.phdm.zip
118
35
  ```
119
36
 
120
- **What's happening here:**
121
- - We generate a unique ID using `generateId()` from `document-model/core`
122
- - We push a new item to the `items` array with the input text, new ID, and `checked: false`
123
- - Under the hood, Powerhouse uses Immer.js, so this "mutation" is actually immutable
37
+ Now you can navigate to `/document-models/to-do-list/src/reducers/to-do-list.ts` and start writing the operation reducers.
124
38
 
125
- ### Step 3: Implement updateTodoItemOperation
39
+ Open the `to-do-list.ts` file and you should see the code that needs to be filled for the three operations you have specified earlier. The image below shows the code that needs to be filled:
126
40
 
127
- Replace the boilerplate `updateTodoItemOperation`:
41
+ ![to-do-list ts file](./images/reducers.png)
128
42
 
129
- ```typescript
130
- // removed-start
131
- updateTodoItemOperation(state, action) {
132
- // TODO: Implement "updateTodoItemOperation" reducer
133
- throw new Error('Reducer "updateTodoItemOperation" not yet implemented');
134
- },
135
- // removed-end
136
- // added-start
137
- updateTodoItemOperation(state, action) {
138
- const item = state.items.find((item) => item.id === action.input.id);
139
- if (!item) return;
140
- item.text = action.input.text ?? item.text;
141
- item.checked = action.input.checked ?? item.checked;
142
- },
143
- // added-end
144
- ```
43
+ ## Write the operation reducers
145
44
 
146
- **What's happening here:**
147
- - We find the item by its ID
148
- - We return early if the item is not found
149
- - We use nullish coalescing (`??`) to only update fields that are provided
45
+ 1. Copy and paste the code below into the `to-do-list.ts` file in the `reducers` folder.
46
+ 2. Save the file.
150
47
 
151
- ### Step 4: Implement deleteTodoItemOperation
48
+ <details>
49
+ <summary>Operation Reducers</summary>
50
+ ```typescript
51
+ import { ToDoListToDoListOperations } from '../../gen/to-do-list/operations.js';
52
+
53
+ // REMARKS: This is our main reducer object that implements all operations defined in the schema.
54
+ // The ToDoListToDoListOperations type is auto-generated from our SDL and ensures type safety.
55
+ export const reducer: ToDoListToDoListOperations = {
56
+ // REMARKS: The addTodoItemOperation adds a new item to our todolist.
57
+ // - state: The current document state that we can modify
58
+ // - action: Contains the operation type and input data from the client
59
+ // - dispatch: Function to trigger additional operations (not used here)
60
+ addTodoItemOperation(state, action, dispatch) {
61
+ // REMARKS: While this looks like we're directly mutating state, Powerhouse
62
+ // handles immutability behind the scenes, creating a new state object.
63
+ state.items.push({
64
+ id: action.input.id, // Using the client-provided ID
65
+ text: action.input.text, // Setting the todo text from input
66
+ checked: false, // New items always start unchecked
67
+ });
68
+ },
69
+
70
+ // REMARKS: The updateTodoItemOperation modifies an existing todo item.
71
+ // It handles partial updates, allowing only specific fields to be updated.
72
+ updateTodoItemOperation(state, action, dispatch) {
73
+ // REMARKS: First find the item we want to update by its ID
74
+ const item = state.items.find(item => item.id === action.input.id);
75
+
76
+ // REMARKS: Proper error handling if item doesn't exist
77
+ if (!item) {
78
+ throw new Error(`Item with id ${action.input.id} not found`);
79
+ }
80
+
81
+ // REMARKS: We only update fields that were included in the input
82
+ // This allows for partial updates (only update what was provided)
83
+ if (action.input.text) {
84
+ item.text = action.input.text;
85
+ }
86
+ if (typeof action.input.checked === 'boolean') {
87
+ item.checked = action.input.checked;
88
+ }
89
+
90
+ },
91
+
92
+ // REMARKS: The deleteTodoItemOperation removes an item from the list.
93
+ // This showcases functional programming with array filters for immutable updates.
94
+ deleteTodoItemOperation(state, action, dispatch) {
95
+ // REMARKS: Create a new array containing only items that don't match the ID
96
+ // This is a common pattern for immutable array updates in JavaScript
97
+ state.items = state.items.filter(item => item.id !== action.input.id);
98
+ },
99
+ };
152
100
 
153
- Replace the boilerplate `deleteTodoItemOperation`:
101
+ ````
102
+ </details>
154
103
 
155
- ```typescript
156
- // removed-start
157
- deleteTodoItemOperation(state, action) {
158
- // TODO: Implement "deleteTodoItemOperation" reducer
159
- throw new Error('Reducer "deleteTodoItemOperation" not yet implemented');
160
- },
161
- // removed-end
162
- // added-start
163
- deleteTodoItemOperation(state, action) {
164
- state.items = state.items.filter((item) => item.id !== action.input.id);
165
- },
166
- // added-end
167
- ```
104
+ ## Write the operation reducers tests
168
105
 
169
- **What's happening here:**
170
- - We filter out the item with the matching ID
171
- - This creates a new array without the deleted item
106
+ In order to make sure the operation reducers are working as expected, you need to write tests for them.
172
107
 
173
- ## Complete reducer file
108
+ Navigate to `/document-models/to-do-list/src/reducers/tests/to-do-list.test.ts` and copy and paste the code below into the file. Save the file.
174
109
 
175
- Here's the complete implementation:
110
+ Here are the tests for the three operations implemented in the reducers file. This test file creates an empty ToDoList document model, then adds a todo item, updates it and deletes it.
176
111
 
177
112
  <details>
178
- <summary>Complete todos.ts</summary>
179
-
113
+ <summary>Operation Reducers Tests</summary>
180
114
  ```typescript
181
- import { generateId } from "document-model/core";
182
- import type { TodoListTodosOperations } from "todo-tutorial/document-models/todo-list";
183
-
184
- export const todoListTodosOperations: TodoListTodosOperations = {
185
- addTodoItemOperation(state, action) {
186
- const id = generateId();
187
- state.items.push({ ...action.input, id, checked: false });
188
- },
189
-
190
- updateTodoItemOperation(state, action) {
191
- const item = state.items.find((item) => item.id === action.input.id);
192
- if (!item) return;
193
- item.text = action.input.text ?? item.text;
194
- item.checked = action.input.checked ?? item.checked;
195
- },
196
-
197
- deleteTodoItemOperation(state, action) {
198
- state.items = state.items.filter((item) => item.id !== action.input.id);
199
- },
200
- };
201
- ```
115
+ import utils from '../../gen/utils.js';
116
+ import { reducer } from '../../gen/reducer.js';
117
+ import * as creators from '../../gen/creators.js';
118
+ import { ToDoListDocument } from '../../gen/types.js';
119
+
120
+ // REMARKS:
121
+ // These tests demonstrate the event sourcing principles of our document model.
122
+ // Each operation is recorded in the document's operations list and affects the state.
123
+
124
+ describe('Todolist Operations', () => {
125
+ let document: ToDoListDocument;
126
+
127
+ beforeEach(() => {
128
+ // REMARKS: We start with a fresh, empty document for each test
129
+ document = utils.createDocument();
130
+ });
131
+
132
+ it('should handle addTodoItem operation', () => {
133
+ // REMARKS: We create an input object matching our AddTodoItemInput schema
134
+ const input = { id: '1', text: 'Buy milk' };
135
+
136
+ // REMARKS: We apply the operation to get a new document state
137
+ // Note how we use the creators to generate the operation action
138
+ const updatedDocument = reducer(document, creators.addTodoItem(input));
139
+
140
+ // REMARKS: We verify that:
141
+ // 1. The operation was recorded in the document's operation history
142
+ // 2. The state was updated according to our reducer implementation
143
+ expect(updatedDocument.operations.global).toHaveLength(1);
144
+ expect(updatedDocument.operations.global[0].type).toBe('ADD_TODO_ITEM');
145
+ expect(updatedDocument.state.global.items).toHaveLength(1);
146
+ expect(updatedDocument.state.global.items[0].text).toBe('Buy milk');
147
+ });
148
+
149
+ it('should handle updateTodoItem operation', () => {
150
+ // REMARKS: For update, we first need to add an item, then update it
151
+ // This demonstrates the sequential application of operations
152
+ const addInput = { id: '1', text: 'Buy milk' };
153
+ const updateInput = { id: '1', text: 'Buy bread' };
154
+
155
+ // REMARKS: Operations are applied in sequence, building up document state
156
+ const createdDocument = reducer(document, creators.addTodoItem(addInput));
157
+ const updatedDocument = reducer(createdDocument, creators.updateTodoItem(updateInput));
158
+
159
+ // REMARKS: Now we have 2 operations in history, and the state reflects both
160
+ expect(updatedDocument.operations.global).toHaveLength(2);
161
+ expect(updatedDocument.state.global.items[0].text).toBe('Buy bread');
162
+ });
163
+
164
+ it('should handle deleteTodoItem operation', () => {
165
+ // REMARKS: Similar pattern - add an item, then delete it
166
+ const addInput = { id: '1', text: 'Buy milk' };
167
+ const deleteInput = { id: '1' };
168
+
169
+ const createdDocument = reducer(document, creators.addTodoItem(addInput));
170
+ const updatedDocument = reducer(createdDocument, creators.deleteTodoItem(deleteInput));
171
+
172
+ // REMARKS: After deletion, we still have 2 operations in history,
173
+ // but the items array is now empty again in the final state
174
+ expect(updatedDocument.operations.global).toHaveLength(2);
175
+ expect(updatedDocument.state.global.items).toHaveLength(0);
176
+ });
177
+ });
178
+ ````
202
179
 
203
180
  </details>
204
181
 
205
- :::tip Check your work
206
-
207
- To make sure everything works as expected:
182
+ Now you can run the tests to make sure the operation reducers are working as expected.
208
183
 
209
184
  ```bash
210
- # Check types compile correctly
211
- pnpm tsc
185
+ pnpm run test
186
+ ```
212
187
 
213
- # Check linting passes
214
- pnpm lint
188
+ Output should be as follows:
215
189
 
216
- # Compare with reference implementation
217
- git diff tutorial/step-3-implement-reducer-operation-handlers -- document-models/todo-list/src/reducers/
190
+ ```bash
191
+ Test Files 2 passed (2)
192
+ Tests 5 passed (5)
193
+ Start at 12:04:57
194
+ Duration 417ms (transform 79ms, setup 0ms, collect 174ms, tests 12ms, environment 0ms, prepare 158ms)
218
195
  ```
219
196
 
220
- :::
197
+ 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.
221
198
 
222
- ## Up next: Writing tests
199
+ ## Up next: To-do list editor
223
200
 
224
- In the next chapter, you'll write comprehensive tests to verify your reducer implementations work correctly.
201
+ 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.