@powerhousedao/academy 5.0.0-staging.2 → 5.0.0-staging.21
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/.vscode/settings.json +1 -1
- package/CHANGELOG.md +119 -0
- package/README.md +3 -3
- package/babel.config.js +1 -1
- package/blog/BeyondCommunication-ABlueprintForDevelopment.md +25 -24
- package/blog/TheChallengeOfChange.md +21 -21
- package/docs/academy/01-GetStarted/00-ExploreDemoPackage.mdx +61 -24
- package/docs/academy/01-GetStarted/01-CreateNewPowerhouseProject.md +21 -12
- package/docs/academy/01-GetStarted/02-DefineToDoListDocumentModel.md +24 -19
- package/docs/academy/01-GetStarted/03-ImplementOperationReducers.md +44 -41
- package/docs/academy/01-GetStarted/04-BuildToDoListEditor.md +10 -10
- package/docs/academy/01-GetStarted/05-SpecDrivenAI.md +143 -0
- package/docs/academy/01-GetStarted/home.mdx +185 -90
- package/docs/academy/01-GetStarted/styles.module.css +5 -5
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/01-Prerequisites.md +46 -18
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/02-StandardDocumentModelWorkflow.md +118 -68
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/03-BuilderTools.md +75 -33
- package/docs/academy/02-MasteryTrack/01-BuilderEnvironment/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/01-WhatIsADocumentModel.md +30 -21
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/02-SpecifyTheStateSchema.md +41 -37
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md +29 -25
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md +36 -37
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/05-ImplementDocumentReducers.md +128 -109
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/06-ImplementDocumentModelTests.md +95 -86
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/07-ExampleToDoListRepository.md +7 -9
- package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/01-BuildingDocumentEditors.md +65 -47
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/02-ConfiguringDrives.md +77 -62
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/03-BuildingADriveExplorer.md +360 -349
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/00-DocumentToolbar.mdx +16 -10
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/01-OperationHistory.md +10 -7
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/02-RevisionHistoryTimeline.md +26 -11
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/06-DocumentTools/_category_.json +6 -6
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/01-RenownAuthenticationFlow.md +14 -7
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/02-Authorization.md +0 -1
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/07-Authorization/_category_.json +5 -5
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/_category_.json +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/01-GraphQLAtPowerhouse.md +45 -33
- package/docs/academy/02-MasteryTrack/04-WorkWithData/02-UsingTheAPI.mdx +61 -18
- package/docs/academy/02-MasteryTrack/04-WorkWithData/03-UsingSubgraphs.md +50 -54
- package/docs/academy/02-MasteryTrack/04-WorkWithData/04-analytics-processor.md +126 -110
- package/docs/academy/02-MasteryTrack/04-WorkWithData/05-RelationalDbProcessor.md +75 -45
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/GraphQL References/QueryingADocumentWithGraphQL.md +23 -21
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/best-practices.md +9 -9
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/graphql/index.md +11 -23
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/graphql/integration.md +25 -9
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/intro.md +10 -10
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/benchmarks.md +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/index.md +16 -11
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/memory.md +6 -5
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/schema.md +2 -2
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/typescript/utilities.md +7 -5
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/use-cases/maker.md +32 -58
- package/docs/academy/02-MasteryTrack/04-WorkWithData/06-Analytics Engine/use-cases/processors.md +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/07-drive-analytics.md +105 -71
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_01-SetupBuilderEnvironment.md +22 -0
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_02-CreateNewPowerhouseProject.md +9 -8
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_03-GenerateAnAnalyticsProcessor.md +28 -32
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_04-UpdateAnalyticsProcessor.md +25 -26
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_ARCHIVE-AnalyticsProcessorTutorial/_category_.json +1 -1
- package/docs/academy/02-MasteryTrack/04-WorkWithData/_category_.json +7 -7
- package/docs/academy/02-MasteryTrack/05-Launch/01-IntroductionToPackages.md +3 -4
- package/docs/academy/02-MasteryTrack/05-Launch/02-PublishYourProject.md +69 -45
- package/docs/academy/02-MasteryTrack/05-Launch/03-SetupEnvironment.md +70 -40
- package/docs/academy/02-MasteryTrack/05-Launch/04-ConfigureEnvironment.md +1 -0
- package/docs/academy/02-MasteryTrack/05-Launch/_category_.json +7 -7
- package/docs/academy/02-MasteryTrack/_category_.json +6 -6
- package/docs/academy/03-ExampleUsecases/Chatroom/02-CreateNewPowerhouseProject.md +5 -3
- package/docs/academy/03-ExampleUsecases/Chatroom/03-DefineChatroomDocumentModel.md +38 -37
- package/docs/academy/03-ExampleUsecases/Chatroom/04-ImplementOperationReducers.md +45 -41
- package/docs/academy/03-ExampleUsecases/Chatroom/05-ImplementChatroomEditor.md +14 -14
- package/docs/academy/03-ExampleUsecases/Chatroom/06-LaunchALocalReactor.md +6 -6
- package/docs/academy/03-ExampleUsecases/Chatroom/_category_.json +1 -1
- package/docs/academy/04-APIReferences/00-PowerhouseCLI.md +14 -7
- package/docs/academy/04-APIReferences/01-ReactHooks.md +177 -129
- package/docs/academy/04-APIReferences/04-RelationalDatabase.md +121 -113
- package/docs/academy/04-APIReferences/05-PHDocumentMigrationGuide.md +48 -41
- package/docs/academy/04-APIReferences/_category_.json +6 -6
- package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +1 -2
- package/docs/academy/05-Architecture/01-WorkingWithTheReactor.md +11 -8
- package/docs/academy/05-Architecture/05-DocumentModelTheory/_category_.json +1 -1
- package/docs/academy/05-Architecture/_category_.json +6 -6
- package/docs/academy/06-ComponentLibrary/00-DocumentEngineering.md +25 -23
- package/docs/academy/06-ComponentLibrary/02-CreateCustomScalars.md +105 -93
- package/docs/academy/06-ComponentLibrary/03-IntegrateIntoAReactComponent.md +1 -0
- package/docs/academy/06-ComponentLibrary/_category_.json +7 -7
- package/docs/academy/07-Cookbook.md +267 -34
- package/docs/academy/08-Glossary.md +7 -1
- package/docs/bookofpowerhouse/01-Overview.md +2 -2
- package/docs/bookofpowerhouse/02-GeneralFrameworkAndPhilosophy.md +1 -7
- package/docs/bookofpowerhouse/03-PowerhouseSoftwareArchitecture.md +10 -7
- package/docs/bookofpowerhouse/04-DevelopmentApproaches.md +10 -4
- package/docs/bookofpowerhouse/05-SNOsandANewModelForOSSandPublicGoods.md +23 -30
- package/docs/bookofpowerhouse/06-SNOsInActionAndPlatformEconomies.md +0 -7
- package/docusaurus.config.ts +64 -66
- package/package.json +1 -1
- package/scripts/generate-combined-cli-docs.ts +43 -13
- package/sidebars.ts +1 -0
- package/src/components/HomepageFeatures/index.tsx +171 -78
- package/src/components/HomepageFeatures/styles.module.css +1 -2
- package/src/css/custom.css +89 -89
- package/src/pages/_archive-homepage.tsx +17 -16
- package/src/theme/DocCardList/index.tsx +9 -8
- package/static.json +6 -6
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
# What is a document model?
|
|
2
2
|
|
|
3
3
|
:::tip
|
|
4
|
-
This chapter on **Document Model Creation** will help you with an in depth practicial understanding while building an **advanced to-do list** document model.
|
|
4
|
+
This chapter on **Document Model Creation** will help you with an in depth practicial understanding while building an **advanced to-do list** document model.
|
|
5
5
|
Although not required, if you have completed the 'Get Started' tutorial you will revisit familiar topics and can update your existing document model.
|
|
6
6
|
:::
|
|
7
7
|
|
|
8
8
|
:::info **Definition: What is a Document Model?**
|
|
9
9
|
A Document Model is a programmable document structure that defines how data is stored, changed, and interpreted in a decentralized system. It acts like a living blueprint—capturing state, tracking changes, and enabling interaction through defined operations.
|
|
10
10
|
|
|
11
|
-
For instance, an invoice document model might define fields like
|
|
11
|
+
For instance, an invoice document model might define fields like _issuer_, _lineItems_, and _status_, with operations such as _AddLineItem_ and _MarkAsPaid_.
|
|
12
12
|
:::
|
|
13
13
|
|
|
14
|
-
A Document Model can be understood as:
|
|
15
|
-
|
|
16
|
-
- A
|
|
17
|
-
- A
|
|
14
|
+
A Document Model can be understood as:
|
|
15
|
+
|
|
16
|
+
- A structured software framework that represents and **manages business logic** within a digital environment.
|
|
17
|
+
- A sophisticated template that **encapsulates the essential aspects of a digital process or a set of data**.
|
|
18
|
+
- A blueprints that define how data is **captured, manipulated, and visualised** within a system.
|
|
18
19
|
- A **standardized way to store, modify, and query data** in scalable, decentralized applications.
|
|
19
20
|
|
|
20
21
|
### **How does a document model function?**
|
|
@@ -27,7 +28,7 @@ Each document model consists of three key components:
|
|
|
27
28
|
2. **Document Operations** – Defines how the document can be modified.
|
|
28
29
|
3. **Event History** – Maintains an append-only log of changes.
|
|
29
30
|
|
|
30
|
-
Document models leverage **event sourcing, CQRS (Command Query Responsibility Segregation), and an append-only architecture** to ensure immutability, auditability, and scalability.
|
|
31
|
+
Document models leverage **event sourcing, CQRS (Command Query Responsibility Segregation), and an append-only architecture** to ensure immutability, auditability, and scalability.
|
|
31
32
|
|
|
32
33
|
---
|
|
33
34
|
|
|
@@ -43,19 +44,19 @@ Example of a **GraphQL-like state schema** for an invoice document:
|
|
|
43
44
|
|
|
44
45
|
```graphql
|
|
45
46
|
type InvoiceState {
|
|
46
|
-
id: OID!
|
|
47
|
-
issuer: OID!
|
|
48
|
-
recipient: OID!
|
|
49
|
-
status: String
|
|
50
|
-
dueDate: DateTime
|
|
47
|
+
id: OID! # Unique identifier for the invoice
|
|
48
|
+
issuer: OID! # Reference to the issuing entity
|
|
49
|
+
recipient: OID! # Reference to the recipient entity
|
|
50
|
+
status: String # (value: "DRAFT") # Invoice status
|
|
51
|
+
dueDate: DateTime # Payment due date
|
|
51
52
|
lineItems: [LineItem!]! # List of line items
|
|
52
|
-
totalAmount: Currency
|
|
53
|
+
totalAmount: Currency # Computed field for total invoice value
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
type LineItem {
|
|
56
57
|
id: OID!
|
|
57
58
|
description: String
|
|
58
|
-
quantity: Int
|
|
59
|
+
quantity: Int
|
|
59
60
|
unitPrice: Currency
|
|
60
61
|
}
|
|
61
62
|
```
|
|
@@ -80,7 +81,7 @@ Example operations for modifying an invoice:
|
|
|
80
81
|
input AddLineItemInput {
|
|
81
82
|
invoiceId: OID!
|
|
82
83
|
description: String
|
|
83
|
-
quantity: Int
|
|
84
|
+
quantity: Int
|
|
84
85
|
unitPrice: Currency
|
|
85
86
|
}
|
|
86
87
|
|
|
@@ -94,7 +95,7 @@ input MarkAsPaidInput {
|
|
|
94
95
|
}
|
|
95
96
|
```
|
|
96
97
|
|
|
97
|
-
Each operation **modifies the document state** without altering past data.
|
|
98
|
+
Each operation **modifies the document state** without altering past data.
|
|
98
99
|
Instead, a new event is appended to the document history.
|
|
99
100
|
|
|
100
101
|
---
|
|
@@ -109,7 +110,7 @@ Every operation applied to a document is **stored as an event** in an append-onl
|
|
|
109
110
|
[
|
|
110
111
|
{ "timestamp": 1700000001, "operation": "CREATE_INVOICE", "data": { "id": "inv-001", "issuer": "company-123", "recipient": "client-456" } },
|
|
111
112
|
{ "timestamp": 1700000100, "operation": "ADD_LINE_ITEM", "data": { "description": "Software Development", "quantity": 10, "unitPrice": 100 } },
|
|
112
|
-
{ "timestamp": 1700000200, "operation": "MARK_AS_PAID", "data": {}
|
|
113
|
+
{ "timestamp": 1700000200, "operation": "MARK_AS_PAID", "data": {}
|
|
113
114
|
```
|
|
114
115
|
|
|
115
116
|
### **Event history benefits:**
|
|
@@ -136,7 +137,11 @@ Document models in Powerhouse rely on **event-driven architecture, event sourcin
|
|
|
136
137
|
```json
|
|
137
138
|
{
|
|
138
139
|
"operation": "CREATE_INVOICE",
|
|
139
|
-
"data": {
|
|
140
|
+
"data": {
|
|
141
|
+
"id": "inv-001",
|
|
142
|
+
"issuer": "company-123",
|
|
143
|
+
"recipient": "client-456"
|
|
144
|
+
}
|
|
140
145
|
}
|
|
141
146
|
```
|
|
142
147
|
|
|
@@ -155,7 +160,11 @@ Adding a line item:
|
|
|
155
160
|
```json
|
|
156
161
|
{
|
|
157
162
|
"operation": "ADD_LINE_ITEM",
|
|
158
|
-
"data": {
|
|
163
|
+
"data": {
|
|
164
|
+
"description": "Software Development",
|
|
165
|
+
"quantity": 10,
|
|
166
|
+
"unitPrice": 100
|
|
167
|
+
}
|
|
159
168
|
}
|
|
160
169
|
```
|
|
161
170
|
|
|
@@ -198,8 +207,8 @@ Document Models offer a range of features that can be leveraged to create sophis
|
|
|
198
207
|
- **Collaboration**: Empower decentralized teams to build, modify, and share documents asynchronously.
|
|
199
208
|
- **Extensibility**: Add new fields, operations, and integrations over time without rewriting logic.
|
|
200
209
|
|
|
201
|
-
Document Models are a powerful primitive within the Powerhouse vision, offering a flexible, structured, and efficient way to manage business logic and data.
|
|
210
|
+
Document Models are a powerful primitive within the Powerhouse vision, offering a flexible, structured, and efficient way to manage business logic and data.
|
|
202
211
|
|
|
203
212
|
### Up next: How to build a document model
|
|
204
213
|
|
|
205
|
-
In the next chapters, we'll teach you how to build a To-do List document model while explaining all of the theory that is involved.
|
|
214
|
+
In the next chapters, we'll teach you how to build a To-do List document model while explaining all of the theory that is involved.
|
|
@@ -5,29 +5,34 @@ The state schema is the backbone of your document model. It defines the structur
|
|
|
5
5
|
## Core concepts
|
|
6
6
|
|
|
7
7
|
### Types
|
|
8
|
+
|
|
8
9
|
At the heart of GraphQL SDL are **types**. Types define the shape of your data. You can define custom object types that represent the entities in your document. For example, in a `ToDoList` document, you might have a `ToDoListState` type and a `ToDoItem` type.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
- **`ToDoListState`**: This could be the root type representing the overall state of the to-do list. It might contain a list of `ToDoItem` objects.
|
|
12
|
+
- **`ToDoItem`**: This type would represent an individual to-do item, with properties like an `id`, `text` (the task description), and `checked` (a boolean indicating if the task is completed).
|
|
12
13
|
|
|
13
14
|
### Fields
|
|
15
|
+
|
|
14
16
|
Each type has **fields**, which represent the properties of that type. Each field has a name and a type. For instance, the `ToDoItem` type would have an `id` field of type `ID!`, a `text` field of type `String!`, and a `checked` field of type `Boolean!`.
|
|
15
17
|
|
|
16
18
|
### Scalars
|
|
19
|
+
|
|
17
20
|
GraphQL has a set of built-in **scalar types**:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
- `String`: A UTF‐8 character sequence.
|
|
23
|
+
- `Int`: A signed 32‐bit integer.
|
|
24
|
+
- `Float`: A signed double-precision floating-point value.
|
|
25
|
+
- `Boolean`: `true` or `false`.
|
|
26
|
+
- `ID`: A unique identifier, often used as a key for a field. It is serialized in the same way as a String; however, it is not intended to be human-readable.
|
|
23
27
|
|
|
24
28
|
In addition to these standard types, the Powerhouse Document-Engineering system introduces custom scalars that are linked to reusable front-end components. These scalars are tailored for the web3 ecosystem and will be explored in the Component Library section of the documentation.
|
|
25
29
|
|
|
26
30
|
### Lists and non-null
|
|
27
31
|
|
|
28
32
|
You can modify types using lists and non-null indicators:
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
|
|
34
|
+
- **Lists**: To indicate that a field will return a list of a certain type, you wrap the type in square brackets, e.g., `[ToDoItem!]!`. This means the field `items` in `ToDoListState` will be a list of `ToDoItem` objects.
|
|
35
|
+
- **Non-Null**: To indicate that a field cannot be null, you add an exclamation mark `!` after the type name, e.g., `String!`. This means that the `text` field of a `ToDoItem` must always have a value. The outer `!` in `[ToDoItem!]!` means the list itself cannot be null (it must be at least an empty list), and the inner `!` on `ToDoItem!` means that every item within that list must also be non-null.
|
|
31
36
|
|
|
32
37
|
## Example: ToDoList state schema
|
|
33
38
|
|
|
@@ -56,21 +61,21 @@ type ToDoListStats {
|
|
|
56
61
|
|
|
57
62
|
### Breakdown:
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
- **`ToDoListState` type**:
|
|
65
|
+
- `items: [ToDoItem!]!`: This field defines that our `ToDoListState` contains a list called `items`.
|
|
66
|
+
- `[ToDoItem!]`: This signifies that `items` is a list of `ToDoItem` objects.
|
|
67
|
+
- `ToDoItem!`: The `!` after `ToDoItem` means that no item in the list can be null. Each entry must be a valid `ToDoItem`.
|
|
68
|
+
- The final `!` after `[ToDoItem!]` means that the `items` list itself cannot be null. It can be an empty list `[]`, but it cannot be absent.
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
- **`ToDoItem` type**:
|
|
71
|
+
- `id: ID!`: Each `ToDoItem` has a unique identifier that cannot be null. This is crucial for referencing specific items, for example, when updating or deleting them.
|
|
72
|
+
- `text: String!`: The textual description of the to-do item. It cannot be null, ensuring every to-do has a description.
|
|
73
|
+
- `checked: Boolean!`: Indicates whether the to-do item is completed. It defaults to a boolean value (true or false) and cannot be null.
|
|
69
74
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
- **`ToDoListStats` type**: This type holds the summary statistics for the to-do list.
|
|
76
|
+
- `total: Int!`: The total count of all to-do items. This field must be an integer and cannot be null.
|
|
77
|
+
- `checked: Int!`: The number of to-do items that are marked as completed. This must be an integer and cannot be null.
|
|
78
|
+
- `unchecked: Int!`: The number of to-do items that are still pending. This also must be an integer and cannot be null.
|
|
74
79
|
|
|
75
80
|
## Best practices for designing your state schema
|
|
76
81
|
|
|
@@ -78,9 +83,9 @@ type ToDoListStats {
|
|
|
78
83
|
2. **Clarity and Explicitness**: Name your types and fields clearly and descriptively. This makes the schema easier to understand and maintain.
|
|
79
84
|
3. **Use Non-Null Wisely**: Enforce data integrity by using non-null (`!`) for fields that must always have a value. However, be mindful not to over-constrain if a field can genuinely be optional.
|
|
80
85
|
4. **Normalize vs. Denormalize**:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
- **Normalization**: Similar to relational databases, you can normalize your data by having distinct types and linking them via IDs. This can reduce data redundancy. For example, if you had `User` and `ToDoItem` and wanted to assign tasks, you might have an `assigneeId` field in `ToDoItem` that links to a `User`'s `id`.
|
|
87
|
+
- **Denormalization**: Sometimes, for performance or simplicity, you might embed data directly. For instance, if user information associated with a to-do item was very simple and only used in that context, you might embed user fields directly in `ToDoItem`.
|
|
88
|
+
- The choice depends on your specific use case, query patterns, and how data is updated.
|
|
84
89
|
5. **Consider Future Needs**: While you shouldn't over-engineer, think a little about potential future enhancements. For example, adding a `createdAt: String` or `dueDate: String` field to `ToDoItem` might be useful later.
|
|
85
90
|
6. **Root State Type**: It's a common pattern to have a single root type for your document state (e.g., `ToDoListState`). This provides a clear entry point for accessing all document data.
|
|
86
91
|
|
|
@@ -91,26 +96,26 @@ By carefully defining your state schema, you lay a solid foundation for your Pow
|
|
|
91
96
|
Now that you understand the concepts behind the state schema, let's put it into practice. This section will guide you through creating a document model specification for the advanced ToDoList example discussed above.
|
|
92
97
|
|
|
93
98
|
<details>
|
|
94
|
-
<summary>Tutorial: The state schema specification</summary>
|
|
99
|
+
<summary>Tutorial: The state schema specification</summary>
|
|
95
100
|
|
|
96
101
|
### Prerequisites
|
|
97
102
|
|
|
98
|
-
-
|
|
99
|
-
-
|
|
103
|
+
- You have a Powerhouse project set up. If not, please follow the [Create a new Powerhouse Project](../../GetStarted/CreateNewPowerhouseProject) tutorial.
|
|
104
|
+
- Connect Studio is running. If not, navigate to your project directory in the terminal and run `ph connect`.
|
|
100
105
|
|
|
101
106
|
### Steps
|
|
102
107
|
|
|
103
108
|
1. **Create a New Document Model**:
|
|
104
|
-
-
|
|
105
|
-
-
|
|
109
|
+
- With Connect Studio open in your browser, navigate into your local drive.
|
|
110
|
+
- At the bottom of the page in the 'New Document' section, click the `DocumentModel` button to create a new document model specification.
|
|
106
111
|
|
|
107
112
|
2. **Define Document Metadata**:
|
|
108
|
-
-
|
|
109
|
-
-
|
|
113
|
+
- **Name**: Give your document model a descriptive name, for example, `ToDoList`. **Pay close attention to capitalization, as it influences our code.**
|
|
114
|
+
- **Document Type**: In the 'Document Type' field, enter a unique identifier for this document type: `powerhouse/todolist`.
|
|
110
115
|
|
|
111
116
|
3. **Specify the State Schema**:
|
|
112
|
-
-
|
|
113
|
-
-
|
|
117
|
+
- In the code editor provided, you'll see a template for a GraphQL schema.
|
|
118
|
+
- Replace the entire content of the editor with the advanced `ToDoList` schema we've designed in this chapter:
|
|
114
119
|
|
|
115
120
|
```graphql
|
|
116
121
|
# The state of our ToDoList
|
|
@@ -134,8 +139,8 @@ Now that you understand the concepts behind the state schema, let's put it into
|
|
|
134
139
|
```
|
|
135
140
|
|
|
136
141
|
4. **Sync Schema and View Initial State**:
|
|
137
|
-
-
|
|
138
|
-
-
|
|
142
|
+
- After pasting the schema, click the **'Sync with schema'** button.
|
|
143
|
+
- This action processes your schema and generates an initial JSON state for your document model based on the `ToDoListState` type. You can view this initial state, which helps you verify that your schema is structured correctly.
|
|
139
144
|
|
|
140
145
|
For now, you can ignore the "Modules & Operations" section. We will define and implement the operations that modify this state in the upcoming sections of this Mastery Track.
|
|
141
146
|
|
|
@@ -144,4 +149,3 @@ By completing these steps, you have successfully specified the data structure fo
|
|
|
144
149
|
</details>
|
|
145
150
|
|
|
146
151
|
For a complete, working example, you can always have a look at the [Example ToDoList Repository](/academy/MasteryTrack/DocumentModelCreation/ExampleToDoListRepository) which contains the full implementation of the concepts discussed in this Mastery Track.
|
|
147
|
-
|
package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/03-SpecifyDocumentOperations.md
CHANGED
|
@@ -8,9 +8,9 @@ In Powerhouse, document models adhere to event sourcing principles. This means t
|
|
|
8
8
|
|
|
9
9
|
For example, in our `To-do List` document model, operations might include:
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
- `ADD_TODO_ITEM`: To add a new task.
|
|
12
|
+
- `UPDATE_TODO_ITEM`: To modify an existing task (e.g., change its text or mark it as completed).
|
|
13
|
+
- `DELETE_TODO_ITEM`: To remove a task.
|
|
14
14
|
|
|
15
15
|
Each operation acts as a command that, when applied, transitions the document from one state to the next. The complete history of these operations defines the document's journey to its current state.
|
|
16
16
|
|
|
@@ -40,9 +40,9 @@ input DeleteTodoItemInput {
|
|
|
40
40
|
|
|
41
41
|
These `input` types are not just abstract definitions; they are the **specifications for our document operations**.
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
- **`AddTodoItemInput`** specifies that to execute an `ADD_TODO_ITEM` operation, we need an `id` and `text` for the new item.
|
|
44
|
+
- **`UpdateTodoItemInput`** specifies that for an `UPDATE_TODO_ITEM` operation, we need the `id` of the item to update, and optionally new `text` or a `checked` status.
|
|
45
|
+
- **`DeleteTodoItemInput`** specifies that a `DELETE_TODO_ITEM` operation requires the `id` of the item to be removed.
|
|
46
46
|
|
|
47
47
|
The Powerhouse Connect application uses these GraphQL input types when you define operations within a module (e.g., the `to_do_list` module with operations `ADD_TODO_ITEM`, `UPDATE_TODO_ITEM`, `DELETE_TODO_ITEM`).
|
|
48
48
|
|
|
@@ -51,36 +51,40 @@ The Powerhouse Connect application uses these GraphQL input types when you defin
|
|
|
51
51
|
Careful design of your document operations is crucial for a robust and maintainable document model. Here are some key considerations:
|
|
52
52
|
|
|
53
53
|
### 1. Granularity
|
|
54
|
+
|
|
54
55
|
Operations should be granular enough to represent distinct user intentions or logical changes.
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
- **Too coarse:** An operation like `MODIFY_TODOLIST` that takes a whole new list of items would be too broad. It would be hard to track specific changes and could lead to complex reducer logic.
|
|
58
|
+
- **Too fine:** While possible, having separate operations like `SET_TODO_ITEM_TEXT` and `SET_TODO_ITEM_CHECKED_STATUS` might be overly verbose if these are often updated together. `UPDATE_TODO_ITEM` with optional fields offers a good balance.
|
|
59
|
+
- **Just right:** The `ADD_TODO_ITEM`, `UPDATE_TODO_ITEM`, and `DELETE_TODO_ITEM` operations for our `ToDoList` are good examples. They represent clear, atomic changes.
|
|
59
60
|
|
|
60
61
|
### 2. Naming conventions
|
|
62
|
+
|
|
61
63
|
Clear and consistent naming makes your operations understandable. A common convention is `VERB_NOUN` or `VERB_NOUN_SUBJECT`.
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
- Examples: `ADD_ITEM`, `UPDATE_USER_PROFILE`, `ASSIGN_TASK_TO_USER`.
|
|
66
|
+
- In our case: `ADD_TODO_ITEM`, `UPDATE_TODO_ITEM`, `DELETE_TODO_ITEM`.
|
|
65
67
|
|
|
66
68
|
The name you provide in the Connect UI (e.g., `ADD_TODO_ITEM`) directly corresponds to the operation type that will be recorded and that your reducers will handle.
|
|
67
69
|
|
|
68
70
|
### 3. Input types (payloads)
|
|
71
|
+
|
|
69
72
|
The input type for an operation (its payload) should contain all the necessary information to perform that operation, and nothing more.
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
- **Completeness:** If an operation needs a user ID to authorize a change, include it in the input.
|
|
75
|
+
- **Conciseness:** Avoid including data that isn't directly used by the operation.
|
|
76
|
+
- **Clarity:** Use descriptive field names within your input types. `action.input.text` is clearer than `action.input.t`.
|
|
74
77
|
|
|
75
78
|
The GraphQL `input` types we defined earlier (`AddTodoItemInput`, `UpdateTodoItemInput`, `DeleteTodoItemInput`) serve precisely this purpose. They ensure that whoever triggers an operation provides the correct data in the correct format.
|
|
76
79
|
|
|
77
80
|
### 4. Immutability and pure functions
|
|
78
|
-
|
|
81
|
+
|
|
82
|
+
While not specified in the operation definition itself, remember that the _implementation_ of these operations (the reducers) should treat state as immutable and behave as pure functions. The operation specification (input type) provides the data for these pure functions.
|
|
79
83
|
|
|
80
84
|
## Role in event sourcing and CQRS
|
|
81
85
|
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
- **Events:** Each successfully executed operation is recorded as an event in the document's history. This history provides an audit trail and allows for replaying events to reconstruct state, which is invaluable for debugging and understanding how a document evolved.
|
|
87
|
+
- **Commands:** Document operations are essentially "commands" in a Command Query Responsibility Segregation (CQRS) pattern. They represent an intent to change the state. The processing of this command (by the reducer) leads to one or more events being stored and the state being updated.
|
|
84
88
|
|
|
85
89
|
## From specification to implementation
|
|
86
90
|
|
|
@@ -95,7 +99,7 @@ The generated code from `ph generate` (as seen in `03-ImplementOperationReducers
|
|
|
95
99
|
For example, the `ToDoListToDoListOperations` type generated by Powerhouse will expect methods corresponding to `addTodoItemOperation`, `updateTodoItemOperation`, and `deleteTodoItemOperation`.
|
|
96
100
|
|
|
97
101
|
```typescript
|
|
98
|
-
import { ToDoListToDoListOperations } from
|
|
102
|
+
import { ToDoListToDoListOperations } from "../../gen/to-do-list/operations.js";
|
|
99
103
|
|
|
100
104
|
export const reducer: ToDoListToDoListOperations = {
|
|
101
105
|
addTodoItemOperation(state, action, dispatch) {
|
|
@@ -121,12 +125,12 @@ Assuming you have already defined the state schema for the `To-do List` as cover
|
|
|
121
125
|
|
|
122
126
|
1. **Create a Module for Operations:**
|
|
123
127
|
Below the schema editor in Connect, find the input field labeled `Add module`. Modules help organize your operations.
|
|
124
|
-
|
|
128
|
+
- Type `to_do_list` into the field and press Enter.
|
|
125
129
|
|
|
126
130
|
2. **Add the `ADD_TODO_ITEM` Operation:**
|
|
127
131
|
A new field, `Add operation`, will appear under your new module.
|
|
128
|
-
|
|
129
|
-
|
|
132
|
+
- Type `ADD_TODO_ITEM` into this field and press Enter.
|
|
133
|
+
- An editor will appear for the operation's input type. You need to define the data required for this operation. Paste the following GraphQL `input` definition into the editor:
|
|
130
134
|
|
|
131
135
|
```graphql
|
|
132
136
|
# Defines a GraphQL input type for adding a new to-do item
|
|
@@ -137,8 +141,8 @@ Assuming you have already defined the state schema for the `To-do List` as cover
|
|
|
137
141
|
```
|
|
138
142
|
|
|
139
143
|
3. **Add the `UPDATE_TODO_ITEM` Operation:**
|
|
140
|
-
|
|
141
|
-
|
|
144
|
+
- In the `Add operation` field again, type `UPDATE_TODO_ITEM` and press Enter.
|
|
145
|
+
- Paste the corresponding `input` definition into its editor:
|
|
142
146
|
|
|
143
147
|
```graphql
|
|
144
148
|
# Defines a GraphQL input type for updating a to-do item
|
|
@@ -150,8 +154,8 @@ Assuming you have already defined the state schema for the `To-do List` as cover
|
|
|
150
154
|
```
|
|
151
155
|
|
|
152
156
|
4. **Add the `DELETE_TODO_ITEM` Operation:**
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
- Finally, type `DELETE_TODO_ITEM` in the `Add operation` field and press Enter.
|
|
158
|
+
- Paste its `input` definition:
|
|
155
159
|
|
|
156
160
|
```graphql
|
|
157
161
|
# Defines a GraphQL input type for deleting a to-do item
|
package/docs/academy/02-MasteryTrack/02-DocumentModelCreation/04-UseTheDocumentModelGenerator.md
CHANGED
|
@@ -39,45 +39,43 @@ The generator creates a new directory specific to your document model, usually l
|
|
|
39
39
|
For example, using `Invoice.phdm.zip` would result in a directory structure under `document-models/invoice/`. Inside this directory, you will find:
|
|
40
40
|
|
|
41
41
|
1. **`spec.json` (or similar JSON representation):**
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
- **Purpose:** This file is a JSON representation of your document model specification, derived directly from the `.phdm.zip` file. It contains the parsed schema, operation definitions, document type, and other metadata.
|
|
43
|
+
- **Significance:** It serves as the canonical, machine-readable definition of your model within the project, which other tools or processes might reference.
|
|
44
44
|
|
|
45
45
|
2. **`schema.graphql`:**
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
- **Purpose:** This file contains the raw GraphQL Schema Definition Language (SDL) for both the state and operations of your document model, exactly as you defined it in Connect.
|
|
47
|
+
- **Significance:** Provides a human-readable reference of the schema and can be useful for quick checks or for tools that might directly consume GraphQL SDL.
|
|
48
48
|
|
|
49
49
|
3. **The `gen/` Directory (Generated Code):**
|
|
50
50
|
This directory is pivotal as it houses all the code automatically generated by the tool. **You should generally avoid manually editing files within the `gen/` directory**, as they will be overwritten if you regenerate the model.
|
|
51
51
|
Key files within `gen/` include:
|
|
52
|
+
- **`types.ts`:**
|
|
53
|
+
- **Purpose:** Contains TypeScript interfaces and type definitions derived from your GraphQL schema. This includes types for your document's state (e.g., `InvoiceState`), any complex types used within the state (e.g., `LineItem`), and types for the inputs of each defined operation (e.g., `AddLineItemInput`).
|
|
54
|
+
- **Significance:** This is the cornerstone of type safety in your document model implementation. By using these generated types, you ensure that your reducer logic and any client-side interactions adhere to the defined data structures, catching errors at compile-time rather than runtime.
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
+
- **`operations.ts` (or `creators.ts`, `actions.ts`):**
|
|
57
|
+
- **Purpose:** This file exports "action creator" functions for each operation defined in your schema. These functions take the input parameters for an operation and return a correctly structured action object that can be processed by the reducer system.
|
|
58
|
+
- **Significance:** Action creators simplify the process of creating and dispatching operations, reduce the likelihood of errors in action formatting, and improve code readability. For example, instead of manually constructing an action object like `{ type: "ADD_LINE_ITEM", input: { ... } }`, you'd use a function like `creators.addLineItem({ ... })`.
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
- **`utils.ts`:**
|
|
61
|
+
- **Purpose:** Often includes utility functions related to your document model. A common utility is a function to create an empty or initial instance of your document (e.g., `utils.createDocument()`). This is based on the default values and structure defined in your state schema.
|
|
62
|
+
- **Significance:** Provides convenient helpers for common tasks, particularly for initializing new documents in tests or application code.
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
* **`reducer.ts` (or similar, defining the reducer interface/skeleton):**
|
|
66
|
-
* **Purpose:** This file might contain a TypeScript interface or a skeleton object that your actual reducer implementation (in the `src/` directory) will need to conform to. It outlines the expected shape of the reducer map, ensuring that you provide an implementation for every defined operation.
|
|
67
|
-
* **Significance:** Guides the implementation of your reducers and helps maintain consistency, ensuring that all defined operations are accounted for.
|
|
64
|
+
- **`reducer.ts` (or similar, defining the reducer interface/skeleton):**
|
|
65
|
+
- **Purpose:** This file might contain a TypeScript interface or a skeleton object that your actual reducer implementation (in the `src/` directory) will need to conform to. It outlines the expected shape of the reducer map, ensuring that you provide an implementation for every defined operation.
|
|
66
|
+
- **Significance:** Guides the implementation of your reducers and helps maintain consistency, ensuring that all defined operations are accounted for.
|
|
68
67
|
|
|
69
68
|
4. **The `src/` Directory (Source Code for Your Implementation):**
|
|
70
69
|
This directory is where you, the developer, will write the custom logic for your document model. Unlike the `gen/` directory, files here are meant to be manually edited.
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
* **Significance:** Helps in organizing shared logic or complex computations that might be used across multiple reducers or other parts of your model's ecosystem.
|
|
70
|
+
- **`reducers/`:**
|
|
71
|
+
- **`your-model-name.ts` (e.g., `invoice.ts`):** This is the most important file you'll work with after generation. It's where you implement the **reducer functions** for each operation. The generator usually creates a skeleton file with function stubs for each operation, which you then fill in with the actual state transition logic.
|
|
72
|
+
- **Significance:** This is the heart of your document model's behavior, defining how the state changes in response to each operation. The next step in the Mastery Track will typically focus on implementing these reducers.
|
|
73
|
+
- **`reducers/tests/`:**
|
|
74
|
+
- **`your-model-name.test.ts` (e.g., `invoice.test.ts`):** A placeholder or basic test file is often generated here, encouraging you to write unit tests for your reducer logic.
|
|
75
|
+
- **Significance:** Emphasizes the importance of testing your document model's core logic to ensure correctness and reliability.
|
|
76
|
+
- **`utils/` (optional):**
|
|
77
|
+
- **Purpose:** You can create this directory for any custom utility functions specific to your document model's implementation that don't fit directly into the reducers.
|
|
78
|
+
- **Significance:** Helps in organizing shared logic or complex computations that might be used across multiple reducers or other parts of your model's ecosystem.
|
|
81
79
|
|
|
82
80
|
## Benefits of using the document model generator
|
|
83
81
|
|
|
@@ -101,27 +99,28 @@ This tutorial assumes you have completed the previous steps in this Mastery Trac
|
|
|
101
99
|
|
|
102
100
|
### Prerequisites
|
|
103
101
|
|
|
104
|
-
|
|
102
|
+
- **`ToDoList.phdm.zip` file**: You must have the document model specification file exported from Connect. If you do not have this file, please revisit the previous sections on specifying the state schema and operations.
|
|
105
103
|
|
|
106
104
|
### Steps
|
|
107
105
|
|
|
108
106
|
1. **Place the Specification File in Your Project**:
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
- Navigate to the root directory of your Powerhouse project.
|
|
108
|
+
- Move or copy your `ToDoList.phdm.zip` file into this directory.
|
|
111
109
|
|
|
112
110
|
2. **Run the Generator Command**:
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
- Open your terminal in the root directory of your Powerhouse project.
|
|
112
|
+
- Execute the `ph generate` command, pointing to your specification file:
|
|
113
|
+
|
|
115
114
|
```bash
|
|
116
115
|
ph generate ToDoList.phdm.zip
|
|
117
116
|
```
|
|
118
117
|
|
|
119
118
|
3. **Explore the Generated Files**:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
119
|
+
- After the command completes successfully, you will find a new directory: `document-models/to-do-list/`.
|
|
120
|
+
- Take a moment to explore its contents, which will match the structure described earlier in this document:
|
|
121
|
+
- `spec.json` and `schema.graphql`: The definition of your model.
|
|
122
|
+
- `gen/`: Type-safe, generated code including `types.ts`, `operations.ts`, etc.
|
|
123
|
+
- `src/`: The skeleton for your implementation, most importantly `src/reducers/to-do-list.ts`, which will contain empty functions for `addTodoItemOperation`, `updateTodoItemOperation`, and `deleteTodoItemOperation`, ready for you to implement.
|
|
125
124
|
|
|
126
125
|
With these files generated, you have successfully scaffolded your document model. The project is now set up for you to implement the core business logic.
|
|
127
126
|
|