@powerhousedao/academy 4.1.0-dev.17 → 4.1.0-dev.18
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
CHANGED
|
@@ -29,41 +29,40 @@ A subgraph in Powerhouse is a **GraphQL-based modular data component** that exte
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const admins = await operationalStore.get("admins");
|
|
36
|
-
return admins.includes(session.user);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
```
|
|
32
|
+
## Example: Implement a search subgraph based on data from the reactor
|
|
33
|
+
|
|
34
|
+
In this example we implement a subgraph which allows to search through todo-list documents in a specific document drive.
|
|
40
35
|
|
|
41
|
-
|
|
36
|
+
First we will generate the subgraph with the help of the ph cli, then we will define the GraphQL schema and implement the resolvers and finally we will start the reactor and execute a query through the GraphQL Gateway.
|
|
37
|
+
|
|
38
|
+
### 1. Generate the subgraph
|
|
42
39
|
|
|
43
40
|
Let's start by generating a new subgraph. For our tutorial we will create a new subgraph within our To-do List project.
|
|
44
41
|
Open your project and start your terminal.
|
|
45
42
|
The Powerhouse toolkit provides a command-line utility to create new subgraphs easily.
|
|
46
43
|
|
|
47
44
|
```bash title="Run the following command to generate a new subgraph"
|
|
48
|
-
ph generate --subgraph
|
|
45
|
+
ph generate --subgraph search-todos
|
|
49
46
|
```
|
|
50
47
|
|
|
51
48
|
```bash title="Expected Output"
|
|
52
|
-
Loaded templates:
|
|
53
|
-
FORCED: ./subgraphs/
|
|
49
|
+
Loaded templates: /projects/powerhouse/powerhouse/packages/codegen/dist/src/codegen/.hygen/templates
|
|
50
|
+
FORCED: ./subgraphs/search-todos/index.ts
|
|
54
51
|
skipped: ./subgraphs/index.ts
|
|
55
52
|
inject: ./subgraphs/index.ts
|
|
53
|
+
|
|
54
|
+
Loaded templates: /projects/powerhouse/powerhouse/packages/codegen/dist/src/codegen/.hygen/templates
|
|
55
|
+
FORCED: ./subgraphs/search-todos/resolvers.ts
|
|
56
|
+
FORCED: ./subgraphs/search-todos/schema.ts
|
|
56
57
|
```
|
|
57
58
|
|
|
58
59
|
### What happened?
|
|
59
|
-
1. A new subgraph was created in `./subgraphs/
|
|
60
|
+
1. A new subgraph was created in `./subgraphs/search-todos/`
|
|
60
61
|
2. The subgraph was automatically registered in your project's registry
|
|
61
62
|
3. Basic boilerplate code was generated with an example query
|
|
62
63
|
|
|
63
64
|
If we now run `ph reactor` we will see the new subgraph being registered during the startup of the Reactor.
|
|
64
|
-
> Registered /
|
|
65
|
-
|
|
66
|
-
Alternatively, when you are running a local reactor with `ph reactor`, a series of subgraphs will automatically get registered, among those, one for the available document models in your Powerhouse project.
|
|
65
|
+
> Registered /graphql/search-todos subgraph.
|
|
67
66
|
|
|
68
67
|
```
|
|
69
68
|
Initializing Subgraph Manager...
|
|
@@ -73,7 +72,7 @@ Initializing Subgraph Manager...
|
|
|
73
72
|
> Registered /d/:drive subgraph.
|
|
74
73
|
> Updating router
|
|
75
74
|
> Registered /graphql supergraph
|
|
76
|
-
> Registered /graphql/
|
|
75
|
+
> Registered /graphql/search-todos subgraph.
|
|
77
76
|
> Updating router
|
|
78
77
|
> Registered /graphql supergraph
|
|
79
78
|
➜ Reactor: http://localhost:4001/d/powerhouse
|
|
@@ -81,337 +80,61 @@ Initializing Subgraph Manager...
|
|
|
81
80
|
|
|
82
81
|
## 2. Building a to-do list subgraph
|
|
83
82
|
|
|
84
|
-
Now that we've generated our subgraph
|
|
83
|
+
Now that we've generated our subgraph its tome to define the GraphQL schema and implement the resolvers.
|
|
85
84
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
Before building our subgraph, let's recall the structure of our To-do List document model from the [DocumentModelCreation tutorial](/academy/MasteryTrack/DocumentModelCreation/SpecifyTheStateSchema):
|
|
89
|
-
|
|
90
|
-
```graphql
|
|
91
|
-
type ToDoListState {
|
|
92
|
-
items: [ToDoItem!]!
|
|
93
|
-
stats: ToDoListStats!
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
type ToDoItem {
|
|
97
|
-
id: ID!
|
|
98
|
-
text: String!
|
|
99
|
-
checked: Boolean!
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
type ToDoListStats {
|
|
103
|
-
total: Int!
|
|
104
|
-
checked: Int!
|
|
105
|
-
unchecked: Int
|
|
106
|
-
}
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
The document model has these operations:
|
|
110
|
-
- `ADD_TODO_ITEM`: Adds a new to-do item
|
|
111
|
-
- `UPDATE_TODO_ITEM`: Updates an existing to-do item
|
|
112
|
-
- `DELETE_TODO_ITEM`: Deletes a to-do item
|
|
113
|
-
|
|
114
|
-
### 2.2 Define the subgraph schema
|
|
115
|
-
|
|
116
|
-
Now let's create a subgraph that provides enhanced querying capabilities for our To-do List documents.
|
|
117
|
-
|
|
118
|
-
**Step 1: Define the schema in `subgraphs/to-do-list/schema.ts` by creating the file:**
|
|
85
|
+
**Step 1: Define the schema in `subgraphs/search-todos/schema.ts` by creating the file:**
|
|
119
86
|
|
|
120
87
|
```typescript
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
# Dashboard-style summary query - returns high-level metrics
|
|
124
|
-
# Similar to ToDoListStats from document model but optimized for quick queries
|
|
125
|
-
todoList: TodoListSummary
|
|
126
|
-
|
|
127
|
-
# Filtered list query - lets you get items by completion status
|
|
128
|
-
# More flexible than the basic document model - can filter checked/unchecked
|
|
129
|
-
todoItems(checked: Boolean): [TodoItem!]!
|
|
130
|
-
|
|
131
|
-
# Count-only query - when you just need numbers, not full data
|
|
132
|
-
# Faster than getting full list when you only need totals for dashboards
|
|
133
|
-
todoItemsCount(checked: Boolean): Int!
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
# This mirrors ToDoListStats from the document model
|
|
137
|
-
# But it's a "view" optimized for summary reports and dashboards
|
|
138
|
-
type TodoListSummary {
|
|
139
|
-
total: Int! # Total number of items
|
|
140
|
-
checked: Int! # Number of completed items
|
|
141
|
-
unchecked: Int! # Number of pending items
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
# This matches the ToDoItem from the document model
|
|
145
|
-
# Same data structure, but accessed through subgraph queries for filtering
|
|
146
|
-
type TodoItem {
|
|
147
|
-
id: ID! # Unique identifier
|
|
148
|
-
text: String! # The task description
|
|
149
|
-
checked: Boolean! # Completion status
|
|
150
|
-
}
|
|
151
|
-
}`
|
|
152
|
-
```
|
|
153
|
-
|
|
88
|
+
import { gql } from "graphql-tag";
|
|
89
|
+
import type { DocumentNode } from "graphql";
|
|
154
90
|
|
|
155
|
-
|
|
156
|
-
|
|
91
|
+
export const schema: DocumentNode = gql`
|
|
92
|
+
"""
|
|
93
|
+
Subgraph definition
|
|
94
|
+
"""
|
|
157
95
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
When someone asks your system a question through GraphQL, the resolver:
|
|
162
|
-
|
|
163
|
-
1. **Understands the request** - "The user wants unchecked items"
|
|
164
|
-
2. **Knows where to get the data** - "I need to check the todo_items database table"
|
|
165
|
-
3. **Applies the right filters** - "Only get items where checked = false"
|
|
166
|
-
4. **Returns the answer** - "Here are the 5 unchecked items"
|
|
167
|
-
|
|
168
|
-
**The three resolvers serve different business needs:**
|
|
169
|
-
|
|
170
|
-
- **`todoList` Resolver - The Dashboard**
|
|
171
|
-
- **Business value**: Perfect for executive dashboards or KPI displays
|
|
172
|
-
- **Use case**: "We have 150 total tasks, 89 completed, 61 pending"
|
|
173
|
-
- **Users**: Executives, managers, anyone needing high-level metrics
|
|
174
|
-
|
|
175
|
-
- **`todoItems` Resolver - The Detailed List**
|
|
176
|
-
- **Business value**: Great for operational views where people need to see actual tasks
|
|
177
|
-
- **Use case**: "Show me all pending tasks" or "Show me everything"
|
|
178
|
-
- **Users**: Workers, operators, anyone who needs to act on specific items
|
|
179
|
-
|
|
180
|
-
- **`todoItemsCount` Resolver - The Counter**
|
|
181
|
-
- **Business value**: Super fast for analytics or when you only need numbers
|
|
182
|
-
- **Use case**: "How many completed tasks do we have?" → "47"
|
|
183
|
-
- **Users**: Analysts, automated systems, performance dashboards
|
|
184
|
-
|
|
185
|
-
**Why this architecture matters:**
|
|
186
|
-
- **Performance**: Count queries are much faster than getting full lists when you only need numbers
|
|
187
|
-
- **User Experience**: Different resolvers serve different user needs efficiently
|
|
188
|
-
- **Flexibility**: Users can ask for exactly what they need, nothing more, nothing less
|
|
189
|
-
|
|
190
|
-
</details>
|
|
191
|
-
|
|
192
|
-
**Step 2: Create resolvers in `subgraphs/to-do-list/resolvers.ts`:**
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
// subgraphs/to-do-list/resolvers.ts
|
|
196
|
-
interface SubgraphInstance {
|
|
197
|
-
operationalStore: any;
|
|
96
|
+
type Query {
|
|
97
|
+
searchTodos(driveId: String!, searchTerm: String!): [String!]!
|
|
198
98
|
}
|
|
199
99
|
|
|
200
|
-
|
|
201
|
-
Query: {
|
|
202
|
-
todoList: async () => {
|
|
203
|
-
const items = await subgraphInstance.operationalStore.getAll("todo_items");
|
|
204
|
-
const total = items.length;
|
|
205
|
-
const checked = items.filter((item: any) => item.checked).length;
|
|
206
|
-
const unchecked = total - checked;
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
total,
|
|
210
|
-
checked,
|
|
211
|
-
unchecked
|
|
212
|
-
};
|
|
213
|
-
},
|
|
214
|
-
|
|
215
|
-
todoItems: async (parent: any, { checked }: any) => {
|
|
216
|
-
let query = subgraphInstance.operationalStore.select("*").from("todo_items");
|
|
217
|
-
|
|
218
|
-
if (checked !== undefined) {
|
|
219
|
-
query = query.where("checked", checked);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const items = await query.orderBy("created_at", "asc");
|
|
223
|
-
return items;
|
|
224
|
-
},
|
|
225
|
-
|
|
226
|
-
todoItemsCount: async (parent: any, { checked }: any) => {
|
|
227
|
-
let query = subgraphInstance.operationalStore.count("* as count").from("todo_items");
|
|
228
|
-
|
|
229
|
-
if (checked !== undefined) {
|
|
230
|
-
query = query.where("checked", checked);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
const result = await query.first();
|
|
234
|
-
return result?.count || 0;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
```
|
|
100
|
+
`;
|
|
239
101
|
|
|
240
|
-
**Step 3: Implement the main class in `subgraphs/to-do-list/index.ts`:**
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
// subgraphs/to-do-list/index.ts
|
|
244
|
-
import { typeDefs } from './schema.js';
|
|
245
|
-
import { createResolvers } from './resolvers.js';
|
|
246
|
-
|
|
247
|
-
export default class ToDoListSubgraph {
|
|
248
|
-
// Define the API endpoint where this subgraph will be accessible
|
|
249
|
-
// Users can query this at: http://localhost:4001/graphql/to-do-list
|
|
250
|
-
path = '/to-do-list';
|
|
251
|
-
|
|
252
|
-
// GraphQL schema definition (what queries are available)
|
|
253
|
-
typeDefs = typeDefs;
|
|
254
|
-
|
|
255
|
-
// Query handlers (how to fetch the data)
|
|
256
|
-
resolvers: any;
|
|
257
|
-
|
|
258
|
-
// Database interface (injected by Powerhouse framework)
|
|
259
|
-
operationalStore: any;
|
|
260
|
-
|
|
261
|
-
constructor() {
|
|
262
|
-
// Connect the resolvers to this subgraph instance
|
|
263
|
-
// This gives resolvers access to the database through this.operationalStore
|
|
264
|
-
this.resolvers = createResolvers(this);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// Called once when the subgraph starts up
|
|
268
|
-
async onSetup() {
|
|
269
|
-
await this.createOperationalTables();
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Create the database tables we need for storing todo items
|
|
273
|
-
async createOperationalTables() {
|
|
274
|
-
await this.operationalStore.schema.createTableIfNotExists(
|
|
275
|
-
"todo_items", // Table name
|
|
276
|
-
(table: any) => {
|
|
277
|
-
table.string("id").primary(); // Unique identifier for each todo item
|
|
278
|
-
table.string("text").notNullable(); // The actual todo task text
|
|
279
|
-
table.boolean("checked").defaultTo(false); // Completion status (unchecked by default)
|
|
280
|
-
table.timestamp("created_at").defaultTo(this.operationalStore.fn.now()); // When item was created
|
|
281
|
-
table.timestamp("updated_at").defaultTo(this.operationalStore.fn.now()); // When item was last modified
|
|
282
|
-
}
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
// Event processor: Keeps subgraph data synchronized with document model changes
|
|
287
|
-
// When users add/update/delete todos in Connect, this method handles the updates
|
|
288
|
-
async process(event: any) {
|
|
289
|
-
// Handle new todo item creation
|
|
290
|
-
if (event.type === "ADD_TODO_ITEM") {
|
|
291
|
-
await this.operationalStore.insert("todo_items", {
|
|
292
|
-
id: event.input.id,
|
|
293
|
-
text: event.input.text,
|
|
294
|
-
checked: false,
|
|
295
|
-
created_at: new Date(),
|
|
296
|
-
updated_at: new Date()
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
console.log(`Added todo item: ${event.input.text}`);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Handle todo item updates (text changes, checking/unchecking)
|
|
303
|
-
if (event.type === "UPDATE_TODO_ITEM") {
|
|
304
|
-
const updateData: any = {
|
|
305
|
-
updated_at: new Date() // Always update the timestamp
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
// Only update fields that were actually changed
|
|
309
|
-
if (event.input.text !== undefined) {
|
|
310
|
-
updateData.text = event.input.text;
|
|
311
|
-
}
|
|
312
|
-
if (event.input.checked !== undefined) {
|
|
313
|
-
updateData.checked = event.input.checked;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
await this.operationalStore.update("todo_items")
|
|
317
|
-
.where("id", event.input.id)
|
|
318
|
-
.update(updateData);
|
|
319
|
-
|
|
320
|
-
console.log(`Updated todo item: ${event.input.id}`);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Handle todo item deletion
|
|
324
|
-
if (event.type === "DELETE_TODO_ITEM") {
|
|
325
|
-
await this.operationalStore.delete("todo_items")
|
|
326
|
-
.where("id", event.input.id);
|
|
327
|
-
|
|
328
|
-
console.log(`Deleted todo item: ${event.input.id}`);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
102
|
```
|
|
333
103
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
**What this multi-file approach provides:**
|
|
337
|
-
|
|
338
|
-
1. **Schema separation** (`schema.ts`): Clean GraphQL type definitions
|
|
339
|
-
2. **Resolver isolation** (`resolvers.ts`): Business logic separated from structure
|
|
340
|
-
3. **Main orchestration** (`index.ts`): Combines everything and handles lifecycle methods
|
|
341
|
-
|
|
342
|
-
**Key features implemented:**
|
|
343
|
-
- A `todo_items` operational table to store individual to-do items
|
|
344
|
-
- Fields that match our document model structure
|
|
345
|
-
- Timestamps for tracking when items were created and updated
|
|
346
|
-
- Resolvers that fetch and filter todo items from the operational store
|
|
347
|
-
- Event processing to keep the subgraph data synchronized with document model changes
|
|
348
|
-
|
|
349
|
-
### 2.4 Understanding the document model event integration
|
|
104
|
+
**Step 2: Create resolvers in `subgraphs/search-todos/resolvers.ts`:**
|
|
350
105
|
|
|
351
|
-
Notice that our `index.ts` file already includes a `process` method - this is the **processor integration** that keeps our subgraph synchronized with To-do List document model events. When users interact with To-do List documents through Connect, this method automatically handles the updates.
|
|
352
|
-
|
|
353
|
-
**How the existing processor integration works:**
|
|
354
|
-
|
|
355
|
-
The `process` method in our `index.ts` file handles three types of document model events:
|
|
356
|
-
|
|
357
|
-
**1. Adding new todo items:**
|
|
358
106
|
```typescript
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
107
|
+
// subgraphs/search-todos/resolvers.ts
|
|
108
|
+
import { type Subgraph } from "@powerhousedao/reactor-api";
|
|
109
|
+
import { type ToDoListDocument } from "document-models/to-do-list/index.js";
|
|
110
|
+
|
|
111
|
+
export const getResolvers = (subgraph: Subgraph) => {
|
|
112
|
+
const reactor = subgraph.reactor;
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
Query: {
|
|
116
|
+
searchTodos: async (parent: unknown, args: { driveId: string, searchTerm: string }) => {
|
|
117
|
+
const documents = await reactor.getDocuments(args.driveId);
|
|
118
|
+
const todoItems: string[] = [];
|
|
119
|
+
for (const docId of documents) {
|
|
120
|
+
const doc: ToDoListDocument = await reactor.getDocument(docId);
|
|
121
|
+
if (doc.header.documentType !== "powerhouse/todo-list") {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const amountEntries = doc.state.global.items.filter(e => e.text.includes(args.searchTerm)).length;
|
|
126
|
+
if (amountEntries > 0) {
|
|
127
|
+
todoItems.push(docId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return todoItems;
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
};
|
|
369
135
|
|
|
370
|
-
**2. Updating existing items:**
|
|
371
|
-
```typescript
|
|
372
|
-
if (event.type === "UPDATE_TODO_ITEM") {
|
|
373
|
-
// Only update fields that were actually changed
|
|
374
|
-
const updateData = { updated_at: new Date() };
|
|
375
|
-
if (event.input.text !== undefined) updateData.text = event.input.text;
|
|
376
|
-
if (event.input.checked !== undefined) updateData.checked = event.input.checked;
|
|
377
|
-
|
|
378
|
-
await this.operationalStore.update("todo_items")
|
|
379
|
-
.where("id", event.input.id)
|
|
380
|
-
.update(updateData);
|
|
381
|
-
}
|
|
382
136
|
```
|
|
383
137
|
|
|
384
|
-
**3. Deleting items:**
|
|
385
|
-
```typescript
|
|
386
|
-
if (event.type === "DELETE_TODO_ITEM") {
|
|
387
|
-
await this.operationalStore.delete("todo_items")
|
|
388
|
-
.where("id", event.input.id);
|
|
389
|
-
}
|
|
390
|
-
```
|
|
391
|
-
|
|
392
|
-
**The integration happens automatically:**
|
|
393
|
-
1. **User action**: Someone adds a todo item in Connect
|
|
394
|
-
2. **Document model**: Processes the `ADD_TODO_ITEM` operation
|
|
395
|
-
3. **Framework routing**: Powerhouse automatically calls your subgraph's `process` method
|
|
396
|
-
4. **Subgraph response**: Your `process` method updates the operational store
|
|
397
|
-
5. **Query availability**: Users can now query the updated data via GraphQL
|
|
398
|
-
|
|
399
|
-
### 2.5 Summary of what we've built
|
|
400
|
-
|
|
401
|
-
Our complete To-do List subgraph includes:
|
|
402
|
-
|
|
403
|
-
- **GraphQL schema** (`schema.ts`): Defines `todoList`, `todoItems`, and `todoItemsCount` queries
|
|
404
|
-
- **Resolvers** (`resolvers.ts`): Handle data fetching and filtering from the operational store
|
|
405
|
-
- **Main subgraph class** (`index.ts`): Coordinates everything and includes:
|
|
406
|
-
- **Operational table creation**: Sets up the `todo_items` table with proper schema
|
|
407
|
-
- **Event processing**: The `process` method keeps subgraph data synchronized with document model changes
|
|
408
|
-
- **Real-time updates**: Automatically handles `ADD_TODO_ITEM`, `UPDATE_TODO_ITEM`, and `DELETE_TODO_ITEM` events
|
|
409
|
-
|
|
410
|
-
**Key features:**
|
|
411
|
-
- **Filtering capability**: The `todoItems` query accepts an optional `checked` parameter
|
|
412
|
-
- **Performance optimization**: The `todoItemsCount` query returns just numbers when you don't need full data
|
|
413
|
-
- **Real-time synchronization**: Changes in Connect immediately appear in subgraph queries
|
|
414
|
-
- **Complete statistics**: The `todoList` query returns total, checked, and unchecked counts
|
|
415
138
|
|
|
416
139
|
## 3. Testing the to-do list subgraph
|
|
417
140
|
|
|
@@ -421,15 +144,10 @@ To activate the subgraph, run:
|
|
|
421
144
|
```bash
|
|
422
145
|
ph reactor
|
|
423
146
|
```
|
|
424
|
-
Or, for full system startup:
|
|
425
|
-
|
|
426
|
-
```bash title="Start the Reactor & Connect in Studio or Locally"
|
|
427
|
-
ph dev
|
|
428
|
-
```
|
|
429
147
|
|
|
430
148
|
You should see the subgraph being registered in the console output:
|
|
431
149
|
```
|
|
432
|
-
> Registered /graphql/
|
|
150
|
+
> Registered /graphql/search-todos subgraph.
|
|
433
151
|
```
|
|
434
152
|
|
|
435
153
|
### 3.2. Create some test data
|
|
@@ -452,87 +170,15 @@ http://localhost:4001/graphql/to-do-list
|
|
|
452
170
|
|
|
453
171
|
### 3.4. Test the queries
|
|
454
172
|
|
|
455
|
-
**Query 1:
|
|
173
|
+
**Query 1: Search for Todos **
|
|
456
174
|
```graphql
|
|
457
175
|
query {
|
|
458
|
-
|
|
459
|
-
total
|
|
460
|
-
checked
|
|
461
|
-
unchecked
|
|
462
|
-
}
|
|
176
|
+
searchTodos(driveId: "powerhouse", searchTerm: "test")
|
|
463
177
|
}
|
|
464
178
|
```
|
|
465
179
|
|
|
466
|
-
**Query 2: Get all to-do items**
|
|
467
|
-
```graphql
|
|
468
|
-
query {
|
|
469
|
-
todoItems {
|
|
470
|
-
id
|
|
471
|
-
text
|
|
472
|
-
checked
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
**Query 3: Get only unchecked items**
|
|
478
|
-
```graphql
|
|
479
|
-
query {
|
|
480
|
-
todoItems(checked: false) {
|
|
481
|
-
id
|
|
482
|
-
text
|
|
483
|
-
checked
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
```
|
|
487
|
-
|
|
488
|
-
**Query 4: Get count of completed items**
|
|
489
|
-
```graphql
|
|
490
|
-
query {
|
|
491
|
-
todoItemsCount(checked: true)
|
|
492
|
-
}
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
### 3.5. Expected responses
|
|
496
|
-
|
|
497
|
-
**For the statistics query:**
|
|
498
|
-
```json
|
|
499
|
-
{
|
|
500
|
-
"data": {
|
|
501
|
-
"todoList": {
|
|
502
|
-
"total": 3,
|
|
503
|
-
"checked": 1,
|
|
504
|
-
"unchecked": 2
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
```
|
|
509
|
-
|
|
510
|
-
**For the items query:**
|
|
511
|
-
```json
|
|
512
|
-
{
|
|
513
|
-
"data": {
|
|
514
|
-
"todoItems": [
|
|
515
|
-
{
|
|
516
|
-
"id": "item-1",
|
|
517
|
-
"text": "Learn about subgraphs",
|
|
518
|
-
"checked": false
|
|
519
|
-
},
|
|
520
|
-
{
|
|
521
|
-
"id": "item-2",
|
|
522
|
-
"text": "Build a To-do List subgraph",
|
|
523
|
-
"checked": true
|
|
524
|
-
},
|
|
525
|
-
{
|
|
526
|
-
"id": "item-3",
|
|
527
|
-
"text": "Test the subgraph",
|
|
528
|
-
"checked": false
|
|
529
|
-
}
|
|
530
|
-
]
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
```
|
|
534
180
|
|
|
535
|
-
### 3.
|
|
181
|
+
### 3.5. Test real-time updates
|
|
536
182
|
|
|
537
183
|
To verify that your subgraph stays synchronized with document changes:
|
|
538
184
|
|