@powerhousedao/academy 4.1.0-dev.8 → 4.1.0-staging.1

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.
@@ -29,41 +29,40 @@ A subgraph in Powerhouse is a **GraphQL-based modular data component** that exte
29
29
 
30
30
 
31
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
- ```
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
- ## 1. How to generate a subgraph
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 to-do-list
45
+ ph generate --subgraph search-todos
49
46
  ```
50
47
 
51
48
  ```bash title="Expected Output"
52
- Loaded templates: node_modules/@powerhousedao/codegen/dist/codegen/.hygen/templates
53
- FORCED: ./subgraphs/to-do-list/index.ts
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/to-do-list/`
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 /todolist subgraph.
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,345 +72,69 @@ Initializing Subgraph Manager...
73
72
  > Registered /d/:drive subgraph.
74
73
  > Updating router
75
74
  > Registered /graphql supergraph
76
- > Registered /graphql/to-do-list subgraph.
75
+ > Registered /graphql/search-todos subgraph.
77
76
  > Updating router
78
77
  > Registered /graphql supergraph
79
78
  ➜ Reactor: http://localhost:4001/d/powerhouse
80
79
  ```
81
80
 
82
- ## 2. Building a to-do list subgraph
83
-
84
- Now that we've generated our subgraph, let's build a complete To-do List subgraph that extends the functionality of our To-do List document model. This subgraph will provide additional querying capabilities and demonstrate how subgraphs work with document models.
85
-
86
- ### 2.1 Understanding the to-do list document model
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
81
+ ## 2. Building a search subgraph
115
82
 
116
- Now let's create a subgraph that provides enhanced querying capabilities for our To-do List documents.
83
+ Now that we've generated our subgraph its tome to define the GraphQL schema and implement the resolvers.
117
84
 
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
- export const typeDefs = `
122
- type Query {
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
-
154
-
155
- <details>
156
- <summary> #### Understanding resolvers </summary>
88
+ import { gql } from "graphql-tag";
89
+ import type { DocumentNode } from "graphql";
157
90
 
158
- Before diving into the technical implementation, let's understand why these three different query types matter for your product.
159
- Think of resolvers as custom API endpoints that are automatically created based on what your users actually need to know about your data.
91
+ export const schema: DocumentNode = gql`
92
+ """
93
+ Subgraph definition
94
+ """
160
95
 
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
- export const createResolvers = (subgraphInstance: SubgraphInstance) => ({
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
- ```
239
-
240
- **Step 3: Implement the main class in `subgraphs/to-do-list/index.ts`:**
100
+ `;
241
101
 
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
- ### 2.3 Understanding the implementation
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
350
-
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:**
104
+ **Step 2: Create resolvers in `subgraphs/search-todos/resolvers.ts`:**
354
105
 
355
- The `process` method in our `index.ts` file handles three types of document model events:
356
-
357
- **1. Adding new todo items:**
358
- ```typescript
359
- if (event.type === "ADD_TODO_ITEM") {
360
- await this.operationalStore.insert("todo_items", {
361
- id: event.input.id,
362
- text: event.input.text,
363
- checked: false,
364
- created_at: new Date(),
365
- updated_at: new Date()
366
- });
367
- }
368
- ```
369
-
370
- **2. Updating existing items:**
371
106
  ```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
- ```
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/todolist") {
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
+ };
383
135
 
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
136
  ```
391
137
 
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,21 +144,21 @@ 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/to-do-list subgraph.
150
+ > Registered /graphql/search-todos subgraph.
433
151
  ```
434
152
 
435
153
  ### 3.2. Create some test data
436
154
  Before testing queries, let's create some To-do List documents with test data:
437
155
 
438
- 1. Open Connect at `http://localhost:3001` in another terminal
156
+ 1. Start Connect
157
+ ```bash
158
+ ph connect
159
+ ```
160
+
161
+ 1. Open Connect at `http://localhost:3000` in the browser
439
162
  2. Add the 'remote' drive that is running locally via the (+) 'Add Drive' button. Add 'http://localhost:4001/d/powerhouse'
440
163
  3. Create a new To-do List document
441
164
  4. Add some test items:
@@ -447,92 +170,21 @@ Before testing queries, let's create some To-do List documents with test data:
447
170
  Open your browser and go to:
448
171
 
449
172
  ```bash
450
- http://localhost:4001/graphql/to-do-list
173
+ http://localhost:4001/graphql
451
174
  ```
452
175
 
453
176
  ### 3.4. Test the queries
454
177
 
455
- **Query 1: Get To-do List statistics**
178
+ **Query 1: Search for Todos **
456
179
  ```graphql
457
180
  query {
458
- todoList {
459
- total
460
- checked
461
- unchecked
462
- }
181
+ searchTodos(driveId: "powerhouse", searchTerm: "Test")
463
182
  }
464
183
  ```
465
184
 
466
- **Query 2: Get all to-do items**
467
- ```graphql
468
- query {
469
- todoItems {
470
- id
471
- text
472
- checked
473
- }
474
- }
475
- ```
185
+ You should get a list of the document Ids which contain the search term "Test".
476
186
 
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
-
535
- ### 3.6. Test real-time updates
187
+ ### 3.5. Test real-time updates
536
188
 
537
189
  To verify that your subgraph stays synchronized with document changes:
538
190
 
@@ -544,9 +196,10 @@ To verify that your subgraph stays synchronized with document changes:
544
196
 
545
197
  This demonstrates the real-time synchronization between the document model and the subgraph through event processing.
546
198
 
547
- ## 4. Working with the supergraph or gateway
548
199
 
549
- 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.
200
+ ## 4. Working with the GraphQL Gateway
201
+
202
+ The GraphQL Gateway 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.
550
203
 
551
204
  ### 4.1 Key concepts
552
205
 
@@ -181,10 +181,10 @@ Strands represent a batch of operations that happened to documents. Each strand
181
181
  import { type IRelationalDb } from "document-drive/processors/types";
182
182
  import { RelationalDbProcessor } from "document-drive/processors/relational";
183
183
  import { type InternalTransmitterUpdate } from "document-drive/server/listener/transmitter/internal";
184
- import type { ToDoListDocument } from "../../document-models/to-do-list/index.js";
184
+ import type { ToDoListDocument } from "../document-models/to-do-list/index.js";
185
185
 
186
- import { up } from "./migrations.js";
187
- import { type DB } from "./schema.js";
186
+ import { up } from "./todo-indexer/migrations.js";
187
+ import { type DB } from "./todo-indexer/schema.js";
188
188
 
189
189
  // Define the document type this processor handles
190
190
  type DocumentType = ToDoListDocument;
@@ -268,19 +268,41 @@ A subgraph is a GraphQL schema that exposes your processed data to clients. It:
268
268
 
269
269
  ### Configure the Subgraph
270
270
 
271
- Open `./subgraphs/todo/index.ts` and configure the resolvers:
271
+ Open `./subgraphs/todo/schema.ts` and configure the schema:
272
272
 
273
273
  ```ts
274
- import { Subgraph } from "@powerhousedao/reactor-api";
275
274
  import { gql } from "graphql-tag";
275
+ import type { DocumentNode } from "graphql";
276
+
277
+ export const schema: DocumentNode = gql`
278
+
279
+ # Define the structure of a todo item as returned by GraphQL
280
+ type ToDoListEntry {
281
+ task: String! # The task description (! means required/non-null)
282
+ status: Boolean! # The completion status (true = done, false = pending)
283
+ }
284
+
285
+ # Define available queries
286
+ type Query {
287
+ todos(driveId: ID!): [ToDoListEntry] # Get array of todos for a specific drive
288
+ }
289
+ `;
290
+
291
+ ```
292
+
293
+ Open `./subgraphs/todo/resolvers.ts` and configure the resolvers:
294
+
295
+ ```ts
296
+ // subgraphs/search-todos/resolvers.ts
297
+ import { type Subgraph } from "@powerhousedao/reactor-api";
298
+ import { type ToDoListDocument } from "document-models/to-do-list/index.js";
276
299
  import { TodoIndexerProcessor } from "../../processors/todo-indexer/index.js";
277
300
 
278
- export class TodoSubgraph extends Subgraph {
279
- // Human-readable name for this subgraph
280
- name = "Todos";
301
+ export const getResolvers = (subgraph: Subgraph) => {
302
+ const reactor = subgraph.reactor;
303
+ const relationalDb = subgraph.relationalDb;
281
304
 
282
- // GraphQL resolvers - functions that fetch data for each field
283
- resolvers = {
305
+ return {
284
306
  Query: {
285
307
  todos: {
286
308
  // Resolver function for the "todos" query
@@ -288,7 +310,7 @@ export class TodoSubgraph extends Subgraph {
288
310
  resolve: async (_: any, args: {driveId: string}) => {
289
311
  // Query the database using the processor's static query method
290
312
  // This gives us access to the namespaced database for the specific drive
291
- const todos = await TodoIndexerProcessor.query(args.driveId, this.relationalDb)
313
+ const todos = await TodoIndexerProcessor.query(args.driveId, relationalDb)
292
314
  .selectFrom("todo") // Select from the "todo" table
293
315
  .selectAll() // Get all columns
294
316
  .execute(); // Execute the query
@@ -302,29 +324,10 @@ export class TodoSubgraph extends Subgraph {
302
324
  },
303
325
  },
304
326
  };
305
-
306
- // GraphQL schema definition using GraphQL Schema Definition Language (SDL)
307
- typeDefs = gql`
308
-
309
- # Define the structure of a todo item as returned by GraphQL
310
- type ToDoListEntry {
311
- task: String! # The task description (! means required/non-null)
312
- status: Boolean! # The completion status (true = done, false = pending)
313
- }
314
-
315
- # Define available queries
316
- type Query {
317
- todos(driveId: ID!): [ToDoListEntry] # Get array of todos for a specific drive
318
- }
319
- `;
320
-
321
- // Cleanup method called when the subgraph disconnects
322
- async onDisconnect() {
323
- // Add any cleanup logic here if needed
324
- }
325
- }
327
+ };
326
328
  ```
327
329
 
330
+
328
331
  ## Now query the data via the supergraph.
329
332
 
330
333
  **Understanding the Supergraph**
@@ -344,7 +347,7 @@ The Powerhouse supergraph for any given remote drive or reactor can be found und
344
347
  ph reactor
345
348
  ```
346
349
 
347
- - Open the GraphQL editor in your browser:
350
+ - This will return an endpoint, but you'll need to change the url of the endpoint to the following URL:
348
351
 
349
352
  ```
350
353
  http://localhost:4001/graphql