@powerhousedao/academy 5.1.0-dev.9 → 5.1.0-staging.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.
- package/CHANGELOG.md +37 -0
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +54 -18
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +21 -16
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +1 -24
- package/docs/academy/01-GetStarted/04-WriteDocumentModelTests.md +63 -16
- package/docs/academy/01-GetStarted/05-BuildToDoListEditor.md +22 -25
- package/docs/academy/01-GetStarted/images/Modules.png +0 -0
- package/docs/academy/01-GetStarted/images/VetraStudioDrive.png +0 -0
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/05-VetraStudio.md +20 -22
- package/docs/academy/02-MasteryTrack/05-Launch/05-DockerDeployment.md +384 -0
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +35 -98
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +243 -170
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +257 -49
- package/package.json +1 -1
- package/sidebars.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,40 @@
|
|
|
1
|
+
## 5.1.0-staging.0 (2025-12-08)
|
|
2
|
+
|
|
3
|
+
This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
5
|
+
## 5.1.0-dev.14 (2025-12-08)
|
|
6
|
+
|
|
7
|
+
### 🚀 Features
|
|
8
|
+
|
|
9
|
+
- **connect, switchboard:** added healthcheck route ([9a0671113](https://github.com/powerhouse-inc/powerhouse/commit/9a0671113))
|
|
10
|
+
- **academy:** added docker build and publish workflow ([b17562994](https://github.com/powerhouse-inc/powerhouse/commit/b17562994))
|
|
11
|
+
|
|
12
|
+
### ❤️ Thank You
|
|
13
|
+
|
|
14
|
+
- Frank
|
|
15
|
+
|
|
16
|
+
## 5.1.0-dev.13 (2025-12-08)
|
|
17
|
+
|
|
18
|
+
This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
|
|
19
|
+
|
|
20
|
+
## 5.1.0-dev.12 (2025-12-08)
|
|
21
|
+
|
|
22
|
+
This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
|
|
23
|
+
|
|
24
|
+
## 5.1.0-dev.11 (2025-12-08)
|
|
25
|
+
|
|
26
|
+
This was a version bump only for @powerhousedao/academy to align it with other projects, there were no code changes.
|
|
27
|
+
|
|
28
|
+
## 5.1.0-dev.10 (2025-12-06)
|
|
29
|
+
|
|
30
|
+
### 🚀 Features
|
|
31
|
+
|
|
32
|
+
- **design-system:** added remotes inspector and channel inspector components ([093896ebf](https://github.com/powerhouse-inc/powerhouse/commit/093896ebf))
|
|
33
|
+
|
|
34
|
+
### ❤️ Thank You
|
|
35
|
+
|
|
36
|
+
- Guillermo Puente @gpuente
|
|
37
|
+
|
|
1
38
|
## 5.1.0-dev.9 (2025-12-05)
|
|
2
39
|
|
|
3
40
|
### 🩹 Fixes
|
|
@@ -9,6 +9,23 @@ This tutorial step has a corresponding branch in the repository. You can:
|
|
|
9
9
|
- Compare your implementation using `git diff`
|
|
10
10
|
:::
|
|
11
11
|
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
This tutorial guides you through creating a simplified version of a 'Powerhouse project' for a **To-do List**.
|
|
15
|
+
A Powerhouse project primarily consists of a document model and its editor.
|
|
16
|
+
As your projects use-case expands you can add data-integrations or a specific drive-app as seen in the demo package.
|
|
17
|
+
|
|
18
|
+
For todays purpose, you'll be using Connect, our user-centric collaboration tool and Vetra Studio, the builder tooling through which developers can access and manage specifications of your project.
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
- Powerhouse CLI installed: `pnpm install -g ph-cmd` or `npm install -g ph-cmd --legacy-peer-deps`
|
|
23
|
+
- node.js 22 and a package manager (pnpm or npm) installed
|
|
24
|
+
- Visual Studio Code (or your preferred IDE)
|
|
25
|
+
- Terminal/Command Prompt access
|
|
26
|
+
|
|
27
|
+
If you need help with installing the prerequisites you can visit our page [prerequisites](/academy/MasteryTrack/BuilderEnvironment/Prerequisites)
|
|
28
|
+
|
|
12
29
|
<details>
|
|
13
30
|
<summary>📖 How to use this tutorial</summary>
|
|
14
31
|
|
|
@@ -88,23 +105,6 @@ git reset --hard tutorial/step-2-generate-todo-list-document-model
|
|
|
88
105
|
|
|
89
106
|
</details>
|
|
90
107
|
|
|
91
|
-
## Overview
|
|
92
|
-
|
|
93
|
-
This tutorial guides you through creating a simplified version of a 'Powerhouse project' for a **To-do List**.
|
|
94
|
-
A Powerhouse project primarily consists of a document model and its editor.
|
|
95
|
-
As your projects use-case expands you can add data-integrations or a specific drive-app as seen in the demo package.
|
|
96
|
-
|
|
97
|
-
For todays purpose, you'll be using Connect, our user-centric collaboration tool and Vetra Studio, the builder tooling through which developers can access and manage specifications of your project.
|
|
98
|
-
|
|
99
|
-
## Prerequisites
|
|
100
|
-
|
|
101
|
-
- Powerhouse CLI installed: `pnpm install -g ph-cmd` or `npm install -g ph-cmd --legacy-peer-deps`
|
|
102
|
-
- node.js 22 and a package manager (pnpm or npm) installed
|
|
103
|
-
- Visual Studio Code (or your preferred IDE)
|
|
104
|
-
- Terminal/Command Prompt access
|
|
105
|
-
|
|
106
|
-
If you need help with installing the prerequisites you can visit our page [prerequisites](/academy/MasteryTrack/BuilderEnvironment/Prerequisites)
|
|
107
|
-
|
|
108
108
|
## Quick start
|
|
109
109
|
|
|
110
110
|
Create a new Powerhouse project with a single command:
|
|
@@ -144,7 +144,41 @@ Navigate to the newly created project directory:
|
|
|
144
144
|
cd todo-tutorial
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
## Develop a single document model in
|
|
147
|
+
## Develop a single document model in Vetra Studio
|
|
148
|
+
|
|
149
|
+
**Vetra Studio** is the builder's orchestration hub for assembling all specifications needed for your package. It provides a **Vetra Studio Drive** to access, manage, and share document model specifications, editors, and data integrations—all through a visual interface. For deeper coverage, see the [Vetra Studio documentation](/academy/MasteryTrack/BuilderEnvironment/VetraStudio).
|
|
150
|
+
|
|
151
|
+
Once in the project directory, run the `ph vetra` command to start a Vetra Studio Drive where you'll be defining your specifications.
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
ph vetra
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The host application for Vetra Studio will start and you will see the following output:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
➜ Local: http://localhost:3000/
|
|
162
|
+
➜ Network: http://192.168.5.110:3000/
|
|
163
|
+
➜ press h + enter to show help
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
A new browser window will open and you will see the Vetra Studio. If it doesn't open automatically, you can open it manually by navigating to `http://localhost:3000/` in your browser.
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
<figure className="image-container">
|
|
170
|
+
<img
|
|
171
|
+
src={require("./images/VetraStudioDrive.png").default}
|
|
172
|
+
alt="Vetra Studio Drive"
|
|
173
|
+
/>
|
|
174
|
+
<figcaption>The Vetra Studio Drive, a builder app that collects all of the specification of a package.</figcaption>
|
|
175
|
+
</figure>
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
Create a new document model by clicking the Document Modesl 'Add new specification' button. Name your document TodoList (PascalCase, no spaces or hyphens). If you've followed the steps correctly, you'll have an empty TodoList document where you can define the 'Document Specifications' in the next step.
|
|
179
|
+
|
|
180
|
+
<details>
|
|
181
|
+
<summary>Alternatively: Develop a single document model in Connect</summary>
|
|
148
182
|
|
|
149
183
|
Once in the project directory, run the `ph connect` command to start a local instance of the Connect application. This allows you to start your document model specification document.
|
|
150
184
|
Run the following command to start the Connect application:
|
|
@@ -173,6 +207,8 @@ Clear the storage of your localhost application as it might has an old session c
|
|
|
173
207
|
|
|
174
208
|
If you've followed the steps correctly, you'll have an empty `TodoList` document where you can define the **'Document Specifications'**.
|
|
175
209
|
|
|
210
|
+
</details>
|
|
211
|
+
|
|
176
212
|
## Verify your setup
|
|
177
213
|
|
|
178
214
|
At this point, your project structure should match the `step-1-initialize-with-ph-init` branch. You should have:
|
|
@@ -49,16 +49,16 @@ See step 1 for detailed GitHub Desktop instructions.
|
|
|
49
49
|
|
|
50
50
|
</details>
|
|
51
51
|
|
|
52
|
-
In this tutorial, you will learn how to define the specifications for a **
|
|
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.
|
|
53
53
|
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
54
|
|
|
55
|
-
Before you start, make sure you have
|
|
55
|
+
Before you start, make sure you have Vetra Studio running locally with the command:
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
ph
|
|
58
|
+
ph vetra
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
Vetra Studio will start and you will see the following output:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
64
|
➜ Local: http://localhost:3000/
|
|
@@ -83,16 +83,16 @@ Documents in Powerhouse leverage **event sourcing principles**, where every stat
|
|
|
83
83
|
<summary>State schema of our simplified TodoList</summary>
|
|
84
84
|
|
|
85
85
|
```graphql
|
|
86
|
-
# The state of our TodoList
|
|
86
|
+
# The state of our TodoList - contains an array of todo items
|
|
87
87
|
type TodoListState {
|
|
88
88
|
items: [TodoItem!]!
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
# A single to-do item
|
|
91
|
+
# A single to-do item with its properties
|
|
92
92
|
type TodoItem {
|
|
93
|
-
id: OID!
|
|
94
|
-
text: String!
|
|
95
|
-
checked: Boolean!
|
|
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)
|
|
96
96
|
}
|
|
97
97
|
```
|
|
98
98
|
|
|
@@ -100,24 +100,29 @@ type TodoItem {
|
|
|
100
100
|
|
|
101
101
|
<details>
|
|
102
102
|
<summary>Operations schema of our simplified TodoList</summary>
|
|
103
|
+
|
|
103
104
|
```graphql
|
|
104
105
|
# 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
|
|
105
107
|
input AddTodoItemInput {
|
|
106
|
-
text: String!
|
|
108
|
+
text: String! # The text for the new todo item
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
# 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
|
|
110
114
|
input UpdateTodoItemInput {
|
|
111
|
-
id: OID!
|
|
112
|
-
text: String
|
|
113
|
-
checked: Boolean
|
|
115
|
+
id: OID! # Required: which item to update
|
|
116
|
+
text: String # Optional: new text value
|
|
117
|
+
checked: Boolean # Optional: new checked state
|
|
114
118
|
}
|
|
115
119
|
|
|
116
120
|
# Defines a GraphQL input type for deleting a to-do item
|
|
117
121
|
input DeleteTodoItemInput {
|
|
118
|
-
id: OID!
|
|
122
|
+
id: OID! # The ID of the item to delete
|
|
119
123
|
}
|
|
120
124
|
```
|
|
125
|
+
|
|
121
126
|
</details>
|
|
122
127
|
|
|
123
128
|
## Define the document model specification
|
|
@@ -126,7 +131,7 @@ To be able to define the document model, you need to open the document model edi
|
|
|
126
131
|
|
|
127
132
|
### The steps below show you how to do this:
|
|
128
133
|
|
|
129
|
-
1. In
|
|
134
|
+
1. In Vetra Studio, click on **'document model'** to open the document model specification editor.
|
|
130
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.**
|
|
131
136
|
3. You'll be presented with a form to fill in metadata about the document model. Fill in the details in the respective fields.
|
|
132
137
|
|
|
@@ -155,7 +160,7 @@ Check below screenshot for the complete implementation:
|
|
|
155
160
|
|
|
156
161
|
## Verify your document model generation
|
|
157
162
|
|
|
158
|
-
|
|
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/`:
|
|
159
164
|
|
|
160
165
|
```
|
|
161
166
|
document-models/todo-list/
|
|
@@ -42,9 +42,7 @@ git reset --hard tutorial/step-3-implement-reducer-operation-handlers
|
|
|
42
42
|
|
|
43
43
|
</details>
|
|
44
44
|
|
|
45
|
-
In this section, we will implement the operation reducers for the **To-do List** document model.
|
|
46
|
-
|
|
47
|
-
To export the document model specification, follow the steps in the [Define ToDoList Document Model](/academy/GetStarted/DefineToDoListDocumentModel) section.
|
|
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.
|
|
48
46
|
|
|
49
47
|
## Understanding reducers in document models
|
|
50
48
|
|
|
@@ -55,27 +53,6 @@ Reducers are a core concept in Powerhouse document models. They implement the st
|
|
|
55
53
|
The reducers provide the actual implementation of what happens when those operations are performed.
|
|
56
54
|
:::
|
|
57
55
|
|
|
58
|
-
To import the document model specification into your Powerhouse project, you can either:
|
|
59
|
-
|
|
60
|
-
- Copy and paste the file directly into the root of your Powerhouse project.
|
|
61
|
-
- Or drag and drop the file into the Powerhouse project directory in the VSCode editor as seen in the image below:
|
|
62
|
-
|
|
63
|
-
Either step will import the document model specification into your Powerhouse project.
|
|
64
|
-
|
|
65
|
-

|
|
66
|
-
|
|
67
|
-
## Generate the document model code
|
|
68
|
-
|
|
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.
|
|
70
|
-
|
|
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.
|
|
72
|
-
|
|
73
|
-
Run the following command in the terminal:
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
ph generate TodoList.phd
|
|
77
|
-
```
|
|
78
|
-
|
|
79
56
|
## Explore the generated reducer file
|
|
80
57
|
|
|
81
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:
|
|
@@ -53,20 +53,31 @@ import {
|
|
|
53
53
|
|
|
54
54
|
describe("Todos Operations", () => {
|
|
55
55
|
it("should handle addTodoItem operation", () => {
|
|
56
|
-
//
|
|
56
|
+
// The `createDocument` utility function from your document model creates
|
|
57
|
+
// a new empty document, i.e. one with your default initial state
|
|
57
58
|
const document = utils.createDocument();
|
|
58
59
|
|
|
59
|
-
// generateMock
|
|
60
|
+
// The generateMock function takes one of your generated input schemas
|
|
61
|
+
// and creates an object populated with random values for each field
|
|
60
62
|
const input = generateMock(AddTodoItemInputSchema());
|
|
61
63
|
|
|
62
|
-
// call
|
|
64
|
+
// We call your document model's reducer with the new document we just created
|
|
65
|
+
// and the action we want to test, `addTodoItem` in this case.
|
|
66
|
+
// The reducer returns a new object, which is the document with the action applied.
|
|
67
|
+
// If successful, there will be an operation which corresponds to this action
|
|
68
|
+
// in the updated document's operations list.
|
|
63
69
|
const updatedDocument = reducer(document, addTodoItem(input));
|
|
64
70
|
|
|
65
|
-
//
|
|
71
|
+
// When you generate a document model, we give you validation utilities like
|
|
72
|
+
// `isTodoListDocument` which confirms the document is of the correct form
|
|
73
|
+
// in a way that TypeScript recognizes
|
|
66
74
|
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
67
75
|
|
|
68
|
-
//
|
|
76
|
+
// At the start a document will have 0 operations, so after applying this action
|
|
77
|
+
// there should now be one operation
|
|
69
78
|
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
79
|
+
|
|
80
|
+
// The operation added to the list should correspond to the correct action type
|
|
70
81
|
expect(updatedDocument.operations.global[0].action.type).toBe("ADD_TODO_ITEM");
|
|
71
82
|
});
|
|
72
83
|
|
|
@@ -124,36 +135,54 @@ it("should handle updateTodoItem operation", () => {
|
|
|
124
135
|
|
|
125
136
|
```typescript
|
|
126
137
|
it("should handle updateTodoItem operation to update text", () => {
|
|
127
|
-
//
|
|
138
|
+
// We need there to already be a todo item in the document,
|
|
139
|
+
// since we want to test updating an existing item
|
|
128
140
|
const mockItem = generateMock(TodoItemSchema());
|
|
141
|
+
|
|
142
|
+
// We also need to generate a mock input for the update operation we are testing
|
|
129
143
|
const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
|
|
130
144
|
|
|
131
|
-
//
|
|
145
|
+
// Since the mocks are generated with random values, we need to set the `id`
|
|
146
|
+
// on our mock input to match the `id` of the existing mock item
|
|
132
147
|
input.id = mockItem.id;
|
|
148
|
+
|
|
149
|
+
// We want to easily check if the item's text was updated to our new value,
|
|
150
|
+
// so we assign a variable and use that for the mock input's text field
|
|
133
151
|
const newText = "new text";
|
|
134
152
|
input.text = newText;
|
|
135
|
-
|
|
153
|
+
|
|
154
|
+
// We are only testing updating the text here, so we want the checked field
|
|
155
|
+
// on the input to be undefined, i.e. it should not change anything on the existing item
|
|
156
|
+
input.checked = undefined;
|
|
136
157
|
|
|
137
|
-
//
|
|
158
|
+
// We can pass a different initial state to the `createDocument` utility,
|
|
159
|
+
// so in this case we pass in an `items` array with our existing item already in it
|
|
138
160
|
const document = utils.createDocument({
|
|
139
161
|
global: {
|
|
140
162
|
items: [mockItem],
|
|
141
163
|
},
|
|
142
164
|
});
|
|
143
165
|
|
|
166
|
+
// Create an updated document by applying the reducer with the action and input
|
|
144
167
|
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
168
|
+
|
|
169
|
+
// Use our validator to check that the document conforms to the document model schema
|
|
145
170
|
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
146
171
|
|
|
147
|
-
//
|
|
172
|
+
// There should now be one operation in the operations list
|
|
148
173
|
expect(updatedDocument.operations.global).toHaveLength(1);
|
|
149
174
|
expect(updatedDocument.operations.global[0].action.type).toBe("UPDATE_TODO_ITEM");
|
|
150
175
|
|
|
151
|
-
//
|
|
176
|
+
// Find the updated item in the items list by its `id`
|
|
152
177
|
const updatedItem = updatedDocument.state.global.items.find(
|
|
153
178
|
(item) => item.id === input.id,
|
|
154
179
|
);
|
|
180
|
+
|
|
181
|
+
// The item's text should now be updated to be our new text
|
|
155
182
|
expect(updatedItem?.text).toBe(newText);
|
|
156
|
-
|
|
183
|
+
|
|
184
|
+
// The item's `checked` field should be unchanged
|
|
185
|
+
expect(updatedItem?.checked).toBe(mockItem.checked);
|
|
157
186
|
});
|
|
158
187
|
```
|
|
159
188
|
|
|
@@ -161,27 +190,45 @@ it("should handle updateTodoItem operation to update text", () => {
|
|
|
161
190
|
|
|
162
191
|
```typescript
|
|
163
192
|
it("should handle updateTodoItem operation to update checked", () => {
|
|
193
|
+
// Generate a mock existing item
|
|
164
194
|
const mockItem = generateMock(TodoItemSchema());
|
|
195
|
+
|
|
196
|
+
// Generate a mock input
|
|
165
197
|
const input: UpdateTodoItemInput = generateMock(UpdateTodoItemInputSchema());
|
|
166
198
|
|
|
199
|
+
// Set the mock input's `id` to the mock item's `id`
|
|
167
200
|
input.id = mockItem.id;
|
|
168
|
-
|
|
201
|
+
|
|
202
|
+
// We want the new `checked` field value to be the opposite of the
|
|
203
|
+
// randomly generated value from the mock
|
|
204
|
+
const newChecked = !mockItem.checked;
|
|
169
205
|
input.checked = newChecked;
|
|
170
|
-
|
|
206
|
+
|
|
207
|
+
// Leave the `text` field unchanged
|
|
208
|
+
input.text = undefined;
|
|
171
209
|
|
|
210
|
+
// Create a document with the existing item in it
|
|
172
211
|
const document = utils.createDocument({
|
|
173
212
|
global: {
|
|
174
213
|
items: [mockItem],
|
|
175
214
|
},
|
|
176
215
|
});
|
|
177
216
|
|
|
217
|
+
// Apply the reducer with the action and the mock input
|
|
178
218
|
const updatedDocument = reducer(document, updateTodoItem(input));
|
|
219
|
+
|
|
220
|
+
// Validate your document
|
|
179
221
|
expect(isTodoListDocument(updatedDocument)).toBe(true);
|
|
180
222
|
|
|
223
|
+
// Get the updated item by its `id`
|
|
181
224
|
const updatedItem = updatedDocument.state.global.items.find(
|
|
182
225
|
(item) => item.id === input.id,
|
|
183
226
|
);
|
|
184
|
-
|
|
227
|
+
|
|
228
|
+
// The item's `text` field should remain unchanged
|
|
229
|
+
expect(updatedItem?.text).toBe(mockItem.text);
|
|
230
|
+
|
|
231
|
+
// The item's `checked` field should be updated to our new checked value
|
|
185
232
|
expect(updatedItem?.checked).toBe(newChecked);
|
|
186
233
|
});
|
|
187
234
|
```
|
|
@@ -374,5 +421,5 @@ Expected test output:
|
|
|
374
421
|
|
|
375
422
|
## Up next: Building the editor
|
|
376
423
|
|
|
377
|
-
In the next chapter, you'll learn how to implement a user interface (editor) for your document model so you can interact with it visually
|
|
424
|
+
In the next chapter, you'll learn how to implement a user interface (editor) for your document model so you can interact with it visually.
|
|
378
425
|
|
|
@@ -66,28 +66,11 @@ See step 1 for detailed GitHub Desktop instructions.
|
|
|
66
66
|
|
|
67
67
|
In this chapter we will continue with the interface or editor implementation of the **To-do List** document model. This means you will create a simple user interface for the **To-do List** document model which will be used inside the Connect app to create, update and delete your ToDoList items.
|
|
68
68
|
|
|
69
|
-
##
|
|
69
|
+
## Add a document editor specification in Vetra Studio.
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
This command reads the **To-do List** document model definition from the `document-models` folder and generates the editor template in the `editors/todo-list-editor` folder.
|
|
71
|
+
Go back to Vetra Studio and click the 'Add new specification' button in the User Experiences column under 'Editors'. This will create an editor template for your document model.
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
pnpm generate --editor todo-list-editor --document-types powerhouse/todo-list
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Notice the `--editor` flag which specifies the editor name, and the `--document-types` flag defines the document type `powerhouse/todo-list`.
|
|
79
|
-
|
|
80
|
-
Once complete, you'll have a new directory structure:
|
|
81
|
-
|
|
82
|
-
```
|
|
83
|
-
editors/todo-list-editor/
|
|
84
|
-
├── components/
|
|
85
|
-
│ └── EditName.tsx # Auto-generated component for editing document name
|
|
86
|
-
├── editor.tsx # Main editor component (to be customized)
|
|
87
|
-
└── module.ts # Editor module configuration
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
Navigate to the `editors/todo-list-editor/editor.tsx` file and open it in your editor. You'll see a basic template ready for customization.
|
|
73
|
+
Give the editor the name `todo-list-editor` and select the correct document model. In our case that's the `powerhouse/todo-list`
|
|
91
74
|
|
|
92
75
|
### Editor implementation options
|
|
93
76
|
|
|
@@ -97,7 +80,7 @@ When building your editor component within the Powerhouse ecosystem, you have se
|
|
|
97
80
|
2. **Tailwind CSS:** Connect Studio comes with Tailwind CSS integrated. You can directly use Tailwind utility classes for rapid, consistent styling without writing separate CSS files.
|
|
98
81
|
3. **Custom CSS Files:** You can import traditional CSS files (`.css`) to apply custom styles or integrate existing style libraries.
|
|
99
82
|
|
|
100
|
-
|
|
83
|
+
Vetra Studio Preview provides a dynamic local environment, by running `ph vetra --watch` you can visualize your components instantly as you build them, regardless of the styling method you choose.
|
|
101
84
|
Manual build steps are typically only needed when publishing packages.
|
|
102
85
|
|
|
103
86
|
## Build the editor with components
|
|
@@ -193,6 +176,11 @@ import { useSelectedTodoListDocument } from "todo-tutorial/document-models/todo-
|
|
|
193
176
|
|
|
194
177
|
/** Component for adding a new todo item to the selected todo list */
|
|
195
178
|
export function AddTodo() {
|
|
179
|
+
// The hooks for getting documents also return a dispatch function
|
|
180
|
+
// for dispatching actions to modify the document.
|
|
181
|
+
// This is the same pattern you will have seen in React's `useReducer` hook,
|
|
182
|
+
// except you don't need to pass the initial state.
|
|
183
|
+
// The document we are working with _is_ the initial state.
|
|
196
184
|
const [todoList, dispatch] = useSelectedTodoListDocument();
|
|
197
185
|
|
|
198
186
|
if (!todoList) return null;
|
|
@@ -205,6 +193,8 @@ export function AddTodo() {
|
|
|
205
193
|
const text = addTodoInput.value;
|
|
206
194
|
if (!text) return;
|
|
207
195
|
|
|
196
|
+
// Dispatch the addTodoItem action - this will call the reducer
|
|
197
|
+
// we implemented earlier and update the document state
|
|
208
198
|
dispatch(addTodoItem({ text }));
|
|
209
199
|
|
|
210
200
|
form.reset();
|
|
@@ -303,6 +293,10 @@ type Props = {
|
|
|
303
293
|
*/
|
|
304
294
|
export function Todo({ todo }: Props) {
|
|
305
295
|
const [isEditing, setIsEditing] = useState(false);
|
|
296
|
+
|
|
297
|
+
// Even though this component is for a single todo item and not the whole list,
|
|
298
|
+
// we can use the exact same hook for dispatching updates to it.
|
|
299
|
+
// The dispatch function works for any action supported by a TodoList document.
|
|
306
300
|
const [todoList, dispatch] = useSelectedTodoListDocument();
|
|
307
301
|
|
|
308
302
|
if (!todoList) return null;
|
|
@@ -318,6 +312,9 @@ export function Todo({ todo }: Props) {
|
|
|
318
312
|
const textInput = form.elements.namedItem("todoText") as HTMLInputElement;
|
|
319
313
|
const text = textInput.value;
|
|
320
314
|
if (!text) return;
|
|
315
|
+
|
|
316
|
+
// We can use the dispatch function for any of the actions
|
|
317
|
+
// supported by a TodoList document
|
|
321
318
|
dispatch(updateTodoItem({ id: todo.id, text }));
|
|
322
319
|
setIsEditing(false);
|
|
323
320
|
};
|
|
@@ -461,17 +458,17 @@ export function TodoListName() {
|
|
|
461
458
|
|
|
462
459
|
## Test your editor
|
|
463
460
|
|
|
464
|
-
Now you can run the
|
|
461
|
+
Now you can run the Vetra Studio Preview and see the **To-do List** editor in action:
|
|
465
462
|
|
|
466
463
|
```bash
|
|
467
|
-
ph
|
|
464
|
+
ph vetra --watch
|
|
468
465
|
```
|
|
469
466
|
|
|
470
|
-
In
|
|
467
|
+
In the bottom right corner you'll find a new Document Model that you can create: **To-do List**.
|
|
471
468
|
Click on it to create a new To-do List document.
|
|
472
469
|
|
|
473
470
|
:::info Live Development
|
|
474
|
-
The editor will update dynamically as you make changes, so you can experiment with styling and functionality while seeing your results appear in
|
|
471
|
+
The editor will update dynamically as you make changes, so you can experiment with styling and functionality while seeing your results appear in Vetra Studio in real-time.
|
|
475
472
|
:::
|
|
476
473
|
|
|
477
474
|
**Try it out:**
|
|
Binary file
|
|
Binary file
|
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
# Vetra Studio
|
|
2
2
|
|
|
3
|
-
:::tip Important
|
|
4
|
-
|
|
5
|
-
## Vision: Specification Driven AI
|
|
6
|
-
|
|
7
|
-
In the **'Get Started'** chapter we've been making use of strict schema definition principles to communicate the intended use case of our reactive documents.
|
|
8
|
-
The **schema definition language**, is a not only a shared language that bridges the gap between developer, designer and analyst but also the gap between builder and AI-agent through **specification driven AI control**.
|
|
9
|
-
|
|
10
|
-
- Communicate your solution and intent through a structured specification framework designed for AI collaboration.
|
|
11
|
-
- Specifications enable precise, iterative edits, since all our specification documents are machine-readable and executable.
|
|
12
|
-
:::
|
|
13
|
-
|
|
14
3
|
## Introducing Vetra Studio
|
|
15
4
|
|
|
16
|
-
**Vetra Studio Drive**: Serves as a hub for developers to access, manage & share specification through a remote Vetra drive.
|
|
17
|
-
**Vetra Package Library**: Store, publish and fork git repositories of packages in the Vetra Package Library.
|
|
18
|
-
Visit the [Vetra Package Library here](https://vetra.io/packages)
|
|
19
|
-
|
|
20
|
-
**Vetra Studio Drive** functions as the orchestration hub where you as a builder assemble all the necessary specifications for your intended use-case, software solution or package. For each of the different **modules** that together form a package a **specification document** can be created in Vetra Studio Drive.
|
|
5
|
+
- **Vetra Studio Drive**: Serves as a hub for developers to access, manage & share specification through a remote Vetra drive. It functions as the orchestration hub where you as a builder assemble all the necessary specifications for your intended use-case, software solution or package. For each of the different **modules** that together form a package a
|
|
6
|
+
- **Vetra Package Library**: Store, publish and fork git repositories of packages in the Vetra Package Library.
|
|
7
|
+
Visit the [Vetra Package Library here](https://vetra.io/packages)
|
|
21
8
|
|
|
22
9
|
As Vetra Studio matures each of these specification documents will offer an interface by which you as a builder get more control over the modules that make up your package.
|
|
23
|
-
For now
|
|
10
|
+
For now the specification documents offer you a template for code generation.
|
|
24
11
|
|
|
25
12
|
<figure className="image-container">
|
|
26
13
|
<img
|
|
@@ -142,6 +129,17 @@ In standard mode:
|
|
|
142
129
|
|
|
143
130
|
Vetra Studio integrates deeply with Claude through MCP (Model Control Protocol). This is where AI comes into the mix and you get the chance to have greater control and direction over what your llm is coding for you.
|
|
144
131
|
|
|
132
|
+
<details>
|
|
133
|
+
<summary>**Specification Driven AI**</summary>
|
|
134
|
+
|
|
135
|
+
In the **'Get Started'** chapter we've been making use of strict schema definition principles to communicate the intended use case of our reactive documents.
|
|
136
|
+
The **schema definition language**, is a not only a shared language that bridges the gap between developer, designer and analyst but also the gap between builder and AI-agent through **specification driven AI control**.
|
|
137
|
+
|
|
138
|
+
- Communicate your solution and intent through a structured specification framework designed for AI collaboration.
|
|
139
|
+
- Specifications enable precise, iterative edits, since all our specification documents are machine-readable and executable.
|
|
140
|
+
|
|
141
|
+
</details>
|
|
142
|
+
|
|
145
143
|
#### 1. Start the Reactor MCP:
|
|
146
144
|
|
|
147
145
|
Make sure you are in the same directory as your project.
|
|
@@ -168,19 +166,19 @@ Connected to MCP successfully! I can see there's a
|
|
|
168
166
|
running and ready for document model operations.
|
|
169
167
|
```
|
|
170
168
|
|
|
169
|
+
<details>
|
|
170
|
+
<summary>🤖 Reactor MCP Overview</summary>
|
|
171
|
+
|
|
171
172
|
### Key Reactor MCP Features
|
|
172
173
|
|
|
174
|
+
**Reactor-mcp** is a Model Context Protocol (MCP) server that bridges AI agents with Powerhouse document operations.
|
|
175
|
+
|
|
173
176
|
- It supports automatic document model creation from natural language descriptions
|
|
174
177
|
- It implements a smart editor based on the underlying document models
|
|
175
178
|
- It automatically triggers code generation when documents reach valid state
|
|
176
179
|
- The MCP server enables the agent to work with both existing and newly created document models
|
|
177
180
|
- Vetra supports integration with custom remote drives, allowing users to create, share and manage documents within these drives
|
|
178
181
|
|
|
179
|
-
<details>
|
|
180
|
-
<summary>🤖 Reactor MCP Overview</summary>
|
|
181
|
-
|
|
182
|
-
**Reactor-mcp** is a Model Context Protocol (MCP) server that bridges AI agents with Powerhouse document operations.
|
|
183
|
-
|
|
184
182
|
**Document Operations:**
|
|
185
183
|
- `createDocument` / `getDocument` / `deleteDocument` - Manage documents
|
|
186
184
|
- `addActions` - Modify document state through operations
|