@powerhousedao/academy 3.3.0-dev.1 → 3.3.0-dev.3
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 +20 -0
- package/docs/academy/01-GetStarted/home.mdx +1 -1
- package/docs/academy/02-MasteryTrack/03-BuildingUserExperiences/02-ConfiguringDrives.md +2 -2
- package/docs/academy/02-MasteryTrack/04-WorkWithData/{02-GraphQLAtPowerhouse.md → 01-GraphQLAtPowerhouse.md} +132 -4
- package/docs/academy/02-MasteryTrack/04-WorkWithData/{01-ReadingAndWritingThroughTheAPI.mdx → 02-UsingTheAPI.mdx} +11 -7
- package/docs/academy/02-MasteryTrack/04-WorkWithData/03-UsingSubgraphs.md +649 -0
- package/docs/academy/04-APIReferences/04-OperationalDatabase.md +798 -0
- package/package.json +1 -1
- package/src/components/HomepageFeatures/index.tsx +2 -2
- package/docs/academy/02-MasteryTrack/04-WorkWithData/03-WorkingWithSubgraphs/02-GraphQLAndSubgraphs.mdx +0 -119
- package/docs/academy/02-MasteryTrack/04-WorkWithData/03-WorkingWithSubgraphs/03-WorkingWithSubgraphs.md +0 -312
- package/docs/academy/02-MasteryTrack/04-WorkWithData/03-WorkingWithSubgraphs/_category_.json +0 -8
package/package.json
CHANGED
|
@@ -25,7 +25,7 @@ const FeatureList: FeatureItem[] = [
|
|
|
25
25
|
{
|
|
26
26
|
title: "Switchboard",
|
|
27
27
|
imageSrc: require("@site/static/img/switchboard.png").default,
|
|
28
|
-
docPath: "/docs/academy/MasteryTrack/WorkWithData/
|
|
28
|
+
docPath: "/docs/academy/MasteryTrack/WorkWithData/UsingTheAPI",
|
|
29
29
|
description: <>Get access to the open API interface with Switchboard</>,
|
|
30
30
|
},
|
|
31
31
|
{
|
|
@@ -200,7 +200,7 @@ export default function HomepageFeatures() {
|
|
|
200
200
|
<h3 className={styles.cardTitle}>Work with Data</h3>
|
|
201
201
|
</div>
|
|
202
202
|
<div className={styles.cardContent}>
|
|
203
|
-
<a href="//docs/academy/MasteryTrack/WorkWithData/
|
|
203
|
+
<a href="//docs/academy/MasteryTrack/WorkWithData/UsingTheAPI" className={styles.pathButton}>Reading & Writing through the API</a>
|
|
204
204
|
<a href="/docs/academy/MasteryTrack/WorkWithData/WorkingWithSubgraphs" className={styles.pathButton}>Create your own Subgraph</a>
|
|
205
205
|
<a href="/docs/academy/WorkWithData/Analytics Engine/intro" className={styles.pathButton}>Using the Analytics Engine</a>
|
|
206
206
|
</div>
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
# GraphQL and subgraphs
|
|
2
|
-
|
|
3
|
-
GraphQL plays a fundamental role in defining document model data schemas, handling data access patterns, and enabling event-driven workflows within the Powerhouse ecosystem.
|
|
4
|
-
This document provides an intro to graphQL and how it is used at Powerhouse when dealing with subgraphs
|
|
5
|
-
|
|
6
|
-
More specifically, GraphQL is used as:
|
|
7
|
-
- The **schema definition language (SDL)** for defining our document models and thereby self-documenting the API to the data model. It allows developers to define the structure and relationships of data in a strongly-typed format.
|
|
8
|
-
- As the **query language in subgraphs**, which allow different services to expose and query structured data dynamically.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
## Powerhouse's use of GraphQL subgraphs
|
|
12
|
-
Powerhouse structures its data into subgraphs, which are modular GraphQL services that connect to the Reactor, Powerhouse's core data infrastructure, or Operational Data Stores fueled by data from a processor.
|
|
13
|
-
|
|
14
|
-
### Fetching data from the Reactor
|
|
15
|
-
|
|
16
|
-
Powerhouse uses GraphQL to expose system-level data, such as drives, users, and operational records.
|
|
17
|
-
Example: The **System Subgraph** allows querying of drives, stored files and folders.
|
|
18
|
-
|
|
19
|
-
### Operational data stores
|
|
20
|
-
|
|
21
|
-
Custom subgraphs can be created to store and retrieve operational data in real time.
|
|
22
|
-
Example: A subgraph can track file uploads and expose this data via GraphQL queries. ????
|
|
23
|
-
|
|
24
|
-
??
|
|
25
|
-
|
|
26
|
-
```graphql
|
|
27
|
-
type File {
|
|
28
|
-
id: ID!
|
|
29
|
-
name: String!
|
|
30
|
-
size: Int!
|
|
31
|
-
createdAt: DateTime!
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type Query {
|
|
35
|
-
getFile(id: ID!): File
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
This schema ensures that every File entity has an ID, name, size, and timestamp.
|
|
39
|
-
|
|
40
|
-
??
|
|
41
|
-
|
|
42
|
-
In Powerhouse, each subgraph has its own SDL, ensuring modularity and flexibility while working within the ecosystem.
|
|
43
|
-
|
|
44
|
-
## CQRS breakdown
|
|
45
|
-
|
|
46
|
-
Powerhouse uses CQRS to separate write operations (commands) from read operations (queries).
|
|
47
|
-
This improves system scalability and flexibility.
|
|
48
|
-
- GraphQL Queries handle read operations, retrieving structured data efficiently.
|
|
49
|
-
- GraphQL Mutations handle write operations, modifying the state in a controlled manner.
|
|
50
|
-
|
|
51
|
-
Powerhouse's subgraphs act as the read layer, while processors handle write operations into operational data stores. This prevents conflicts between querying and modifying data.
|
|
52
|
-
|
|
53
|
-
| Layer | Role | GraphQL Usage | Implementation |
|
|
54
|
-
| --- | --- | --- | --- |
|
|
55
|
-
| Write Model (Commands) | Handles state changes (adding, modifying, deleting) | GraphQL Mutations | Processor |
|
|
56
|
-
| Read Model (Queries) | Optimized for fetching/reading/retrieving data | GraphQL Queries | Subgraph |
|
|
57
|
-
|
|
58
|
-
### Read and write separation
|
|
59
|
-
**Read Model (Query)**
|
|
60
|
-
|
|
61
|
-
- Optimized for data retrieval
|
|
62
|
-
- Structured using GraphQL Queries
|
|
63
|
-
- Aggregates and exposes data via a subgraph
|
|
64
|
-
- Pulls data from Operational Data Stores, Analytics Stores, and Reactor
|
|
65
|
-
- Subgraphs do not directly modify the data—they only expose pre-processed information
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
```graphql title="Example of a Powerhouse Contributor schema in GraphQL"
|
|
70
|
-
query {
|
|
71
|
-
getFile(id: "123") {
|
|
72
|
-
name
|
|
73
|
-
size
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
**Write Model (Mutation)**
|
|
79
|
-
- Handles state changes (adding, modifying, deleting)
|
|
80
|
-
- Structured using GraphQL Mutations
|
|
81
|
-
- Writes data to Operational Data Stores
|
|
82
|
-
|
|
83
|
-
```graphql title="Example of a Powerhouse Contributor schema in GraphQL"
|
|
84
|
-
mutation {
|
|
85
|
-
createFile(name: "document.pdf", size: 1024) {
|
|
86
|
-
id
|
|
87
|
-
name
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### GraphQL and event-driven architecture (EDA)
|
|
93
|
-
Event-Driven Architecture (EDA) enables asynchronous processing where events trigger actions. Powerhouse uses GraphQL to expose real-time event data from its Reactor and Operational Data Stores.
|
|
94
|
-
|
|
95
|
-
How GraphQL Fits into EDA
|
|
96
|
-
- **Real-Time Data Exposure** – Subgraphs fetch event-based data updates.
|
|
97
|
-
- **Event Subscription Mechanism** – Powerhouse is working towards integrating GraphQL Subscriptions for real-time updates.
|
|
98
|
-
- **Efficient Decoupling** – Events are stored in an operational datastore, and GraphQL queries retrieve structured results.
|
|
99
|
-
|
|
100
|
-
#### Example: Powerhouse's event flow
|
|
101
|
-
1. Processor detects an event (e.g., file upload).
|
|
102
|
-
2. Writes event data to the Operational Data Store.
|
|
103
|
-
3. Subgraph exposes the updated data via GraphQL.
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
## GraphQL subscriptions
|
|
107
|
-
Although Powerhouse currently uses queries and mutations, GraphQL Subscriptions could allow real-time streaming of event-based data.
|
|
108
|
-
|
|
109
|
-
#### Example (future implementation):
|
|
110
|
-
|
|
111
|
-
```graphql
|
|
112
|
-
subscription {
|
|
113
|
-
fileUploaded {
|
|
114
|
-
id
|
|
115
|
-
name
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
This would enable clients to listen for new file uploads without polling.
|
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
# Working with subgraphs
|
|
2
|
-
|
|
3
|
-
This tutorial will demonstrate how to create and customize a subgraph using our To-do List project as an example.
|
|
4
|
-
Let's start with the basics and gradually add more complex features and functionality.
|
|
5
|
-
|
|
6
|
-
## What is a subgraph?
|
|
7
|
-
|
|
8
|
-
A subgraph in Powerhouse is a **GraphQL-based modular data component** that extends the functionality of your document models. While document models handle the core state and operations, subgraphs can:
|
|
9
|
-
1. Connect to external APIs or databases
|
|
10
|
-
2. Add custom queries and mutations
|
|
11
|
-
3. Automate interactions between different document models
|
|
12
|
-
4. Provide additional backend functionality
|
|
13
|
-
|
|
14
|
-
### Subgraphs can retrieve data from
|
|
15
|
-
|
|
16
|
-
- **The Reactor** – The core Powerhouse data system or network node.
|
|
17
|
-
- **Operational Data Stores** – Structured data storage for operational processes, offering real-time updates, for querying structured data.
|
|
18
|
-
- **Analytics Stores** – Aggregated historical data, useful for insights, reporting and business intelligence.
|
|
19
|
-
|
|
20
|
-
### Subgraphs consist of
|
|
21
|
-
|
|
22
|
-
- **A schema** – Which defines the GraphQL Queries and Mutations.
|
|
23
|
-
- **Resolvers** – Which handle data fetching and logic.
|
|
24
|
-
- **Context Fields** – Additional metadata that helps in resolving data efficiently.
|
|
25
|
-
|
|
26
|
-
#### Additionally, context fields allow resolvers to access extra information, such as:
|
|
27
|
-
- **User authentication** (e.g., checking if a user is an admin).
|
|
28
|
-
- **External data sources** (e.g., analytics).
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```typescript title="Example of a context field"
|
|
33
|
-
context: {
|
|
34
|
-
admin: async (session) => {
|
|
35
|
-
const admins = await operationalStore.get("admins");
|
|
36
|
-
return admins.includes(session.user);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## 1. How to generate a subgraph
|
|
42
|
-
|
|
43
|
-
Lets start by generating a new subgraph. For our tutorial we will create a new subgraph within our To-do List project.
|
|
44
|
-
Open your project and start your terminal.
|
|
45
|
-
The Powerhouse toolkit provides a command-line utility to create new subgraphs easily.
|
|
46
|
-
|
|
47
|
-
```bash title="Run the following command to generate a new subgraph"
|
|
48
|
-
ph generate --subgraph <to-do-list-subgraph>
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
```bash title="Expected Output"
|
|
52
|
-
Loaded templates: node_modules/@powerhousedao/codegen/dist/codegen/.hygen/templates
|
|
53
|
-
FORCED: ./subgraphs/to-do-list-subgraph/index.ts
|
|
54
|
-
skipped: ./subgraphs/index.ts
|
|
55
|
-
inject: ./subgraphs/index.ts
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### What happened?
|
|
59
|
-
1. A new subgraph was created in `./subgraphs/to-do-list-subgraph/`
|
|
60
|
-
2. The subgraph was automatically registered in your project's registry
|
|
61
|
-
3. Basic boilerplate code was generated with an example query
|
|
62
|
-
|
|
63
|
-
If we now run 'phreactor' we will see the new subgraph being registered during the startup of the Reactor.
|
|
64
|
-
> Registered /todolist subgraph.
|
|
65
|
-
|
|
66
|
-
## 2. Customizing your subgraph with a schema
|
|
67
|
-
|
|
68
|
-
Now that we've generated our subgraph, let's open it and define the schema inside the `index.ts` file.
|
|
69
|
-
|
|
70
|
-
### 2.1 Define the schema
|
|
71
|
-
|
|
72
|
-
Here we define the schema (typeDefs) which defines the structure of your queries and mutations.
|
|
73
|
-
For educational purposes we will define a simple query that mimics the functionality of the todoList interface (or editor):
|
|
74
|
-
- Returns the total number of todo's
|
|
75
|
-
- The number of todo's that are checked
|
|
76
|
-
- The number of todo's that are not checked
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
```graphql
|
|
81
|
-
type Query {
|
|
82
|
-
fileIds: [String]
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### What happened?
|
|
87
|
-
|
|
88
|
-
- Added two queries: todoList and todoItems
|
|
89
|
-
- Created an operational table todo_items to store the todo items
|
|
90
|
-
- Added resolvers to fetch and filter todo items
|
|
91
|
-
- Removed the example code
|
|
92
|
-
- The todoItems query accepts an optional checked parameter to filter items by their status
|
|
93
|
-
- The todoList query returns the full list with its statistics
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
### 2.2 Implement the resolver for the subgraph's schema
|
|
97
|
-
Resolvers define how data is retrieved or modified.
|
|
98
|
-
If you query for a specific value you can retrieve the value from either the reactor itself or an operational datastore.
|
|
99
|
-
We'll look into this in more detail in the next section.
|
|
100
|
-
|
|
101
|
-
```js
|
|
102
|
-
resolvers: {
|
|
103
|
-
Query: {
|
|
104
|
-
fileIds: async () => {
|
|
105
|
-
return ["file1", "file2", "file3"];
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### 2.3 Add operational data storage (optional)
|
|
112
|
-
If you need to persist data, initialize an operational datastore inside onSetup():
|
|
113
|
-
|
|
114
|
-
```typescript title="Adding an operational datastore"
|
|
115
|
-
async onSetup() {
|
|
116
|
-
await this.createOperationalTables();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async createOperationalTables() {
|
|
120
|
-
await this.operationalStore.schema.createTableIfNotExists(
|
|
121
|
-
"fileIds",
|
|
122
|
-
(table) => {
|
|
123
|
-
table.string("id").primary();
|
|
124
|
-
}
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### 2.4 Fetching from an operational store
|
|
130
|
-
If your subgraph interacts with an Operational Data Store, modify the resolver:
|
|
131
|
-
|
|
132
|
-
```typescript title="Example of a resolver that fetches data from an operational store"
|
|
133
|
-
resolvers: {
|
|
134
|
-
Query: {
|
|
135
|
-
fileIds: async (_, __, { operationalStore }) => {
|
|
136
|
-
return await operationalStore.getAll("fileIds");
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
### 2.5 Connecting to a processor (optional, but recommended)
|
|
143
|
-
|
|
144
|
-
#### Why connect a processor?
|
|
145
|
-
Subgraphs alone are limited. A subgraph only queries data, but doesn't generate or store it.
|
|
146
|
-
To make subgraphs useful, connect them with processors that update the data dynamically.
|
|
147
|
-
**A processor listens to system events and updates the operational store in real-time.**
|
|
148
|
-
|
|
149
|
-
Making use of a processor allows for:
|
|
150
|
-
- **Live updates** instead of static data.
|
|
151
|
-
- **Scalable architecture** through event-driven data changes.
|
|
152
|
-
- **Seamless integration** with other Powerhouse components.
|
|
153
|
-
|
|
154
|
-
Inside your processor, you can listen for new files, which in turn update the datastore:
|
|
155
|
-
|
|
156
|
-
```typescript title="Example: Creating a Simple Processor"
|
|
157
|
-
async process(event) {
|
|
158
|
-
if (event.type === "ADD_FILE") {
|
|
159
|
-
await this.operationalStore.insert("fileIds", { id: event.fileId });
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
Then, modify your subgraph resolver to return real-time data:
|
|
165
|
-
|
|
166
|
-
```js
|
|
167
|
-
resolvers: {
|
|
168
|
-
Query: {
|
|
169
|
-
fileIds: async (_, __, { operationalStore }) => {
|
|
170
|
-
return await operationalStore.getAll("fileIds");
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
## 3. Testing the subgraph
|
|
177
|
-
|
|
178
|
-
### 3.1. Start the reactor
|
|
179
|
-
To activate the subgraph, run:
|
|
180
|
-
|
|
181
|
-
```bash
|
|
182
|
-
ph reactor
|
|
183
|
-
```
|
|
184
|
-
Or, for full system startup:
|
|
185
|
-
|
|
186
|
-
```bash title="Start the Reactor & Connect in Studio or Locally
|
|
187
|
-
ph dev
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
### 3.2. Access GraphQL playground
|
|
191
|
-
Open your browser and go to:
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
http://localhost:4001/<subgraph-name>
|
|
195
|
-
```
|
|
196
|
-
Example:
|
|
197
|
-
|
|
198
|
-
```bash
|
|
199
|
-
http://localhost:4001/test-subgraph
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
### 3.3. Run a query
|
|
203
|
-
|
|
204
|
-
```graphql
|
|
205
|
-
query {
|
|
206
|
-
fileIds
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### 3.4. Expected response
|
|
211
|
-
If everything works, you should see:
|
|
212
|
-
|
|
213
|
-
```json
|
|
214
|
-
{
|
|
215
|
-
"data": {
|
|
216
|
-
"fileIds": ["file1", "file2", "file3"]
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
## 4. Working with the supergraph or gateway
|
|
222
|
-
|
|
223
|
-
A supergraph is a GraphQL schema that combines multiple underlying GraphQL APIs, known as subgraphs, into a single, unified graph. This architecture allows different teams to work independently on their respective services (subgraphs) while providing a single entry point for clients or users to query all available data
|
|
224
|
-
|
|
225
|
-
### 4.1 Key concepts
|
|
226
|
-
|
|
227
|
-
* **Subgraph:** An independent GraphQL service with its own schema. Each subgraph typically represents a specific domain or microservice within a larger system.
|
|
228
|
-
* **Gateway/Router:** A server that sits in front of the subgraphs. It receives client queries, consults the supergraph schema, and routes parts of the query to the relevant subgraphs. It then stitches the results back together before sending the final response to the client.
|
|
229
|
-
|
|
230
|
-
### 4.2 Benefits of using a supergraph
|
|
231
|
-
|
|
232
|
-
* **Federated Architecture:** Enables a microservices-based approach where different teams can own and operate their services independently.
|
|
233
|
-
* **Scalability:** Individual subgraphs can be scaled independently based on their specific needs.
|
|
234
|
-
* **Improved Developer Experience:** Clients interact with a single, consistent GraphQL API, simplifying data fetching and reducing the need to manage multiple endpoints.
|
|
235
|
-
* **Schema Evolution:** Subgraphs can evolve their schemas independently, and the supergraph can be updated without breaking existing clients, as long as breaking changes are managed carefully.
|
|
236
|
-
* **Clear Separation of Concerns:** Each subgraph focuses on a specific domain, leading to more maintainable and understandable codebases.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
### 4.3 Use the Powerhouse supergraph
|
|
240
|
-
|
|
241
|
-
The Powerhouse supergraph for any given remote drive or reactor can be found under `http://localhost:4001/graphql`. The gateway / supergraph available on `/graphql` combines all the subgraphs, except for the drive subgraph (which is accessible via `/d/:driveId`). To get to the endpoint open your localhost by starting the reactor and adding `graphql` to the end of the url. The following commands explain how you can test & try the supergraph.
|
|
242
|
-
|
|
243
|
-
- Start the reactor:
|
|
244
|
-
|
|
245
|
-
```bash
|
|
246
|
-
ph reactor
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
- Open the GraphQL editor in your browser:
|
|
250
|
-
|
|
251
|
-
```
|
|
252
|
-
http://localhost:4001/graphql
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
The supergraph allows to both query & mutate data from the same endpoint.
|
|
256
|
-
|
|
257
|
-
- Create a todo document in the `powerhouse` drive using the `ToDo_createDocument` mutation.
|
|
258
|
-

|
|
259
|
-
|
|
260
|
-
- Get the document state using the `GetDocument` query.
|
|
261
|
-

|
|
262
|
-
|
|
263
|
-
- In a different terminal, start connect:
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
ph connect
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
- Open Connect and add the `powerhouse` drive:
|
|
270
|
-
|
|
271
|
-
```
|
|
272
|
-
http://localhost:4001/d/powerhouse
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
- You should now see the todo document you've created earlier. Edit the todo document with the document editor and add a few tasks that you can query later.
|
|
276
|
-
|
|
277
|
-
- Go back to the GraphQL explorer and use the `GetDocument` query again — you should see the updated state.
|
|
278
|
-
|
|
279
|
-
This is a quick example of how the supegraph can be used.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
## Subgraphs are particularly useful for
|
|
283
|
-
|
|
284
|
-
1. **Cross-Document Interactions**: For example, connecting a To-do List with an Invoice document model:
|
|
285
|
-
- When an invoice-related task is marked complete, update the invoice status
|
|
286
|
-
- When an invoice is paid, automatically check off related tasks
|
|
287
|
-
|
|
288
|
-
2. **External Integrations**:
|
|
289
|
-
- Sync tasks with external project management tools
|
|
290
|
-
- Connect with notification systems
|
|
291
|
-
- Integrate with analytics platforms
|
|
292
|
-
|
|
293
|
-
3. **Custom Business Logic**:
|
|
294
|
-
- Implement complex task prioritization
|
|
295
|
-
- Add automated task assignments
|
|
296
|
-
- Create custom reporting functionality
|
|
297
|
-
|
|
298
|
-
### Prebuilt subgraphs
|
|
299
|
-
|
|
300
|
-
Some subgraphs (e.g., System Subgraph, Drive Subgraph) already exist.
|
|
301
|
-
To integrate with them, register them via the Reactor API.
|
|
302
|
-
|
|
303
|
-
### Future enhancements
|
|
304
|
-
|
|
305
|
-
Bridge Processors and Subgraphs – Currently, there's a gap in how processors and subgraphs interact. Powerhouse might improve this in future updates.
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|