@powerhousedao/academy 0.1.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/CHANGELOG.md +9 -0
  3. package/Dockerfile +31 -0
  4. package/ProcFile +1 -0
  5. package/README.md +43 -0
  6. package/babel.config.js +3 -0
  7. package/blog/BeyondCommunication-ABlueprintForDevelopment.md +88 -0
  8. package/blog/TheChallengeOfChange.md +86 -0
  9. package/blog/images/Iteration.png +0 -0
  10. package/blog/images/RAD.png +0 -0
  11. package/docs/academy/01-GetStarted/00-GetStarted.mdx +181 -0
  12. package/docs/academy/01-GetStarted/01_InstallDemoPackage.md +38 -0
  13. package/docs/academy/01-GetStarted/02-ToDoList/01-CreateNewPowerhouseProject.md +97 -0
  14. package/docs/academy/01-GetStarted/02-ToDoList/02-DefineToDoListDocumentModel.md +86 -0
  15. package/docs/academy/01-GetStarted/02-ToDoList/03-ImplementOperationReducers.md +201 -0
  16. package/docs/academy/01-GetStarted/02-ToDoList/04-BuildToDoListEditor.md +494 -0
  17. package/docs/academy/01-GetStarted/02-ToDoList/_category_.json +8 -0
  18. package/docs/academy/01-GetStarted/02-ToDoList/images/DocumentModelHeader.png +0 -0
  19. package/docs/academy/01-GetStarted/02-ToDoList/images/DocumentModelOperations.png +0 -0
  20. package/docs/academy/01-GetStarted/02-ToDoList/images/OpenDocumentModelEditor.gif +0 -0
  21. package/docs/academy/01-GetStarted/02-ToDoList/images/completeEditor.png +0 -0
  22. package/docs/academy/01-GetStarted/02-ToDoList/images/connectApp.gif +0 -0
  23. package/docs/academy/01-GetStarted/02-ToDoList/images/form.png +0 -0
  24. package/docs/academy/01-GetStarted/02-ToDoList/images/mytodolist.gif +0 -0
  25. package/docs/academy/01-GetStarted/02-ToDoList/images/reducers.png +0 -0
  26. package/docs/academy/01-GetStarted/02-ToDoList/images/vscode.png +0 -0
  27. package/docs/academy/01-GetStarted/styles.module.css +99 -0
  28. package/docs/academy/02-AdvancedTutorial/01-Create/00-BuilderTools.md +234 -0
  29. package/docs/academy/02-AdvancedTutorial/01-Create/01-SetupBuilderEnvironment.md +247 -0
  30. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/04-UtilitiesAndTips.md +79 -0
  31. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/01-SetupBuilderEnvironment.md +216 -0
  32. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/02-CreateNewPowerhouseProject.md +78 -0
  33. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/03-DefineChatroomDocumentModel.md +139 -0
  34. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/04-ImplementOperationReducers.md +364 -0
  35. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/05-ImplementChatroomEditor.md +194 -0
  36. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/06-LaunchALocalReactor.md +15 -0
  37. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/_category_.json +8 -0
  38. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/image-1.png +0 -0
  39. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/image-2.png +0 -0
  40. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/image-3.png +0 -0
  41. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/image-4.png +0 -0
  42. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/image-5.png +0 -0
  43. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/image.png +0 -0
  44. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/images/ChatRoomConnectApp.gif +0 -0
  45. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/images/ChatRoomTest.gif +0 -0
  46. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/images/completeEditor.png +0 -0
  47. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/images/form.png +0 -0
  48. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/images/reducers.png +0 -0
  49. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/Chatroom/images/vscode.png +0 -0
  50. package/docs/academy/02-AdvancedTutorial/01-Create/02-MoreTutorials/_category_.json +8 -0
  51. package/docs/academy/02-AdvancedTutorial/01-Create/02-StandardDocumentModelWorkflow.md +229 -0
  52. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/01-BuildingBeautifulDocumentEditors.md +109 -0
  53. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/02-ConfiguringDrives.md +51 -0
  54. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/03-BuildingADriveExplorer.md +174 -0
  55. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/07-DocumentTools/01-OperationHistory.md +67 -0
  56. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/07-DocumentTools/02-RevisionHistoryTimeline.md +132 -0
  57. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/07-DocumentTools/_category_.json +7 -0
  58. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/07-DocumentTools/images/committer-address-popup.png +0 -0
  59. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/07-DocumentTools/images/revision-hash-popup.png +0 -0
  60. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/07-DocumentTools/images/revision-history-list.png +0 -0
  61. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/07-DocumentTools/images/signature-details-popup.png +0 -0
  62. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/_category_.json +8 -0
  63. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/images/CreateDrive.png +0 -0
  64. package/docs/academy/02-AdvancedTutorial/03-BuildingUserExperiences/images/mytodolist.gif +0 -0
  65. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/01-ReadingAndWritingThroughTheAPI.mdx +121 -0
  66. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/02-GraphQLAtPowerhouse.md +156 -0
  67. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/03-WorkingWithSubgraphs/02-GraphQLAndSubgraphs.mdx +119 -0
  68. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/03-WorkingWithSubgraphs/03-WorkingWithSubgraphs.md +312 -0
  69. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/03-WorkingWithSubgraphs/_category_.json +8 -0
  70. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/04-analytics-processor.md +342 -0
  71. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/01-SetupBuilderEnvironment.md +215 -0
  72. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/02-CreateNewPowerhouseProject.md +55 -0
  73. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/03-GenerateAnAnalyticsProcessor.md +173 -0
  74. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/04-UpdateAnalyticsProcessor.md +223 -0
  75. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/_category_.json +8 -0
  76. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/images/Create-SPV.gif +0 -0
  77. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/images/Create-a-new-asset.png +0 -0
  78. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/images/Create-a-transaction.gif +0 -0
  79. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/images/Transaction-table.png +0 -0
  80. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/images/create-a-new-RWA-document.gif +0 -0
  81. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/05-AnalyticsProcessorTutorial/images/granularity.png +0 -0
  82. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/GraphQL References/QueryingADocumentWithGraphQL.md +244 -0
  83. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/GraphQL References/rwa-reports/listener-raw.png +0 -0
  84. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/GraphQL References/rwa-reports/raw-reports1.png +0 -0
  85. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/GraphQL References/rwa-reports/raw-reports2.png +0 -0
  86. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/GraphQL References/rwa-reports/rwaRegister.png +0 -0
  87. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/apse.png +0 -0
  88. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/best-practices.md +60 -0
  89. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/filter.png +0 -0
  90. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/filteroptions.png +0 -0
  91. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/graphql/index.md +166 -0
  92. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/graphql/integration.md +75 -0
  93. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/dbs.png +0 -0
  94. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/high-level.jpg +0 -0
  95. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/indexeddb.png +0 -0
  96. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/libs-core.jpg +0 -0
  97. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/libs.jpg +0 -0
  98. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/lod.jpg +0 -0
  99. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/logo.png +0 -0
  100. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/navbar.png +0 -0
  101. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/overview-1.jpg +0 -0
  102. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/overview-2.jpg +0 -0
  103. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/overview-3.jpg +0 -0
  104. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/overview-4.jpg +0 -0
  105. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/overview-5.jpg +0 -0
  106. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/overview-6.jpg +0 -0
  107. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/paths-1.jpg +0 -0
  108. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/images/paths-2.jpg +0 -0
  109. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/intro.md +149 -0
  110. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/benchmarks.md +27 -0
  111. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/browser.md +77 -0
  112. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/compatibility.md +14 -0
  113. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/index.md +230 -0
  114. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/memory.md +72 -0
  115. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/pg.md +63 -0
  116. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/schema.md +14 -0
  117. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/typescript/utilities.md +102 -0
  118. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/use-cases/index.md +7 -0
  119. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/use-cases/maker.md +652 -0
  120. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/06-Analytics Engine/use-cases/processors.md +3 -0
  121. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/_category_.json +8 -0
  122. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/images/OperationHistory.png +0 -0
  123. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/images/OperationsQuery.png +0 -0
  124. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/images/QueryDocumentID.png +0 -0
  125. package/docs/academy/02-AdvancedTutorial/04-WorkWithData/images/SwitchboardButton.png +0 -0
  126. package/docs/academy/02-AdvancedTutorial/05-Launch/00-IntegrateInAFront-End +3 -0
  127. package/docs/academy/02-AdvancedTutorial/05-Launch/01-IntroducingFusion +18 -0
  128. package/docs/academy/02-AdvancedTutorial/05-Launch/02-IntroductionToPackages.md +79 -0
  129. package/docs/academy/02-AdvancedTutorial/05-Launch/02-PublishYourProject.md +230 -0
  130. package/docs/academy/02-AdvancedTutorial/05-Launch/03-RunOnACloudServer.md +279 -0
  131. package/docs/academy/02-AdvancedTutorial/05-Launch/03-SetupEnvironment.md +436 -0
  132. package/docs/academy/02-AdvancedTutorial/05-Launch/04-GraphQLNamespacing +44 -0
  133. package/docs/academy/02-AdvancedTutorial/05-Launch/05-LaunchYourBackend.md +3 -0
  134. package/docs/academy/02-AdvancedTutorial/05-Launch/06-LaunchYourFrontend.md +3 -0
  135. package/docs/academy/02-AdvancedTutorial/05-Launch/_category_.json +8 -0
  136. package/docs/academy/02-AdvancedTutorial/05-Launch/images/SSHConnection.png +0 -0
  137. package/docs/academy/02-AdvancedTutorial/05-Launch/images/homedesign.png +0 -0
  138. package/docs/academy/02-AdvancedTutorial/05-Launch/images/keyconcepts.png +0 -0
  139. package/docs/academy/02-AdvancedTutorial/05-Launch/images/tutorialschema.png +0 -0
  140. package/docs/academy/02-AdvancedTutorial/06-Authorization/Authorization.md +100 -0
  141. package/docs/academy/02-AdvancedTutorial/_category_.json +7 -0
  142. package/docs/academy/03-APIReferences/00-PowerhouseCLI.md +1 -0
  143. package/docs/academy/03-APIReferences/_category_.json +7 -0
  144. package/docs/academy/04-ComponentLibrary/01-PowerhouseDesignSystem.md +94 -0
  145. package/docs/academy/04-ComponentLibrary/02-BuildingWithScalars.md +54 -0
  146. package/docs/academy/04-ComponentLibrary/03-Scalar-Components/01-phid-field.mdx +72 -0
  147. package/docs/academy/04-ComponentLibrary/03-Scalar-Components/02-input-field.mdx +0 -0
  148. package/docs/academy/04-ComponentLibrary/04-Complex-Components/01-sidebar.mdx +36 -0
  149. package/docs/academy/04-ComponentLibrary/05-Layout-Components/01-test-toupdate.mdx +61 -0
  150. package/docs/academy/04-ComponentLibrary/06-Fragments/01-test-toupdate.mdx +61 -0
  151. package/docs/academy/04-ComponentLibrary/_category_.json +8 -0
  152. package/docs/academy/05-Architecture/00-PowerhouseArchitecture.md +50 -0
  153. package/docs/academy/05-Architecture/01-WorkingWithTheReactor.md +48 -0
  154. package/docs/academy/05-Architecture/02-ReferencingMonorepoPackages +65 -0
  155. package/docs/academy/05-Architecture/04-MovingBeyondCRUD +61 -0
  156. package/docs/academy/05-Architecture/05-DocumentModelTheory/01-WhatIsADocumentModel.md +188 -0
  157. package/docs/academy/05-Architecture/05-DocumentModelTheory/02-DAOandDocumentsModelsQ+A.md +177 -0
  158. package/docs/academy/05-Architecture/05-DocumentModelTheory/02-domain-modeling.md +103 -0
  159. package/docs/academy/05-Architecture/05-DocumentModelTheory/03-BenefitsOfDocumentModels.md +95 -0
  160. package/docs/academy/05-Architecture/05-DocumentModelTheory/05-best-practices.md +257 -0
  161. package/docs/academy/05-Architecture/05-DocumentModelTheory/_category_.json +8 -0
  162. package/docs/academy/05-Architecture/05-DocumentModelTheory/three-data-layers.png +0 -0
  163. package/docs/academy/05-Architecture/_category_.json +7 -0
  164. package/docs/academy/05-Architecture/images/image.png +0 -0
  165. package/docs/academy/06-Cookbook.md +905 -0
  166. package/docs/academy/07-Glossary.md +50 -0
  167. package/docs/bookofpowerhouse/01-Overview.md +29 -0
  168. package/docs/bookofpowerhouse/02-GeneralFrameworkAndPhilosophy.md +15 -0
  169. package/docs/bookofpowerhouse/03-PowerhouseSoftwareArchitecture.md +33 -0
  170. package/docs/bookofpowerhouse/04-DevelopmentApproaches.md +36 -0
  171. package/docs/bookofpowerhouse/05-SNOsandANewModelForOSSandPublicGoods.md +73 -0
  172. package/docs/bookofpowerhouse/06-SNOsInActionAndPlatformEconomies.md +17 -0
  173. package/docs/renown/01-intro.md +18 -0
  174. package/docs/renown/02-renown-login-flow.md +60 -0
  175. package/docusaurus +0 -0
  176. package/docusaurus.config.ts +170 -0
  177. package/package.json +50 -0
  178. package/powerhouse-docs@0.0.0 +0 -0
  179. package/sidebars.ts +33 -0
  180. package/src/components/HomepageFeatures/index.tsx +250 -0
  181. package/src/components/HomepageFeatures/styles.module.css +267 -0
  182. package/src/css/custom.css +450 -0
  183. package/src/pages/index.module.css +37 -0
  184. package/src/pages/index.tsx +42 -0
  185. package/src/pages/markdown-page.md +7 -0
  186. package/static/.nojekyll +0 -0
  187. package/static/fonts/FranieBold.otf +0 -0
  188. package/static/fonts/FranieRegular.otf +0 -0
  189. package/static/img/Powerhouse Website Drive.png +0 -0
  190. package/static/img/Powerhouse Website Storage Layer (1).png +0 -0
  191. package/static/img/Powerhouse Website Storage Layer.png +0 -0
  192. package/static/img/Powerhouse-main-light.svg +13 -0
  193. package/static/img/Powerhouse-main.svg +13 -0
  194. package/static/img/Renown Intro Diagram.png +0 -0
  195. package/static/img/Union.svg +3 -0
  196. package/static/img/academy/icons/Advanced.svg +4 -0
  197. package/static/img/academy/icons/Book.svg +5 -0
  198. package/static/img/academy/icons/Cookbook.svg +3 -0
  199. package/static/img/academy/icons/Create.svg +3 -0
  200. package/static/img/academy/icons/Data.svg +3 -0
  201. package/static/img/academy/icons/Editor.svg +3 -0
  202. package/static/img/academy/icons/Flash.svg +3 -0
  203. package/static/img/academy/icons/Launch.svg +3 -0
  204. package/static/img/academy-icon.png +0 -0
  205. package/static/img/connect-icon.png +0 -0
  206. package/static/img/connect.png +0 -0
  207. package/static/img/docusaurus-social-card.jpg +0 -0
  208. package/static/img/docusaurus.png +0 -0
  209. package/static/img/empty-background.png +0 -0
  210. package/static/img/favicon.ico +0 -0
  211. package/static/img/fusion-icon.png +0 -0
  212. package/static/img/fusion.png +0 -0
  213. package/static/img/ph-icon-light.svg +3 -0
  214. package/static/img/powerhouse-layer.png +0 -0
  215. package/static/img/powerhouse-storage-layer.png +0 -0
  216. package/static/img/reactor.png +0 -0
  217. package/static/img/renown-icon.png +0 -0
  218. package/static/img/renown.png +0 -0
  219. package/static/img/switchboard-icon.png +0 -0
  220. package/static/img/switchboard.png +0 -0
  221. package/static/img/undraw_docusaurus_mountain.svg +171 -0
  222. package/static/img/undraw_docusaurus_react.svg +170 -0
  223. package/static/img/undraw_docusaurus_tree.svg +40 -0
  224. package/static/img/video-placeholder.svg +16 -0
  225. package/static.json +7 -0
  226. package/tsconfig.json +7 -0
@@ -0,0 +1,312 @@
1
+ # Working with Subgraphs
2
+
3
+ This tutorial will demonstrate how to create and customize a subgraph using our ToDoList 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
+ #### Additionaly, 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 ToDoList 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
+ ![ToDo_createDocument](https://i.ibb.co/GQTZr7Wk/Screenshot-2025-05-01-at-1-22-23-PM.png)
259
+
260
+ - Get the document state using the `GetDocument` query.
261
+ ![GetDocument](https://i.ibb.co/v47cj4Q4/Screenshot-2025-05-01-at-1-22-41-PM.png)
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 ToDoList 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
+
@@ -0,0 +1,8 @@
1
+ {
2
+ "label": "Working With Subgraphs",
3
+ "position": 4,
4
+ "link": {
5
+ "type": "generated-index",
6
+ "description": "Learn how to work with graphQL, subgraphs, and processors in Powerhouse."
7
+ }
8
+ }
@@ -0,0 +1,342 @@
1
+ # Analytics Processors
2
+
3
+ An Analytics Processor is an object that can track analytics for operations and state changes on a set of document models. These analytics can be used to generate bespoke dashboards and reports, specific to the type or implementation of the document model.
4
+
5
+ ## Generating an Analytics Processor with the CLI
6
+
7
+ The `ph-cli` utility can be used to generate the scaffolding for an Analytics Processor.
8
+
9
+ ```
10
+ npx @powerhousedao/ph-cli generate --processor-type analytics --document-models ./my-document-models
11
+ ```
12
+
13
+ This will generate two files: a class that implements `IProcessor` and a `ProcessorFactory` function that creates an instance of your processor. We can start with the factory.
14
+
15
+ ### `ProcessorFactory`
16
+
17
+ If one has not already been created, the generator will create an `index.ts` that contains a `processorFactory` function:
18
+
19
+ ```typescript
20
+ export const processorFactory =
21
+ (module: any) =>
22
+ (driveId: string): ProcessorRecord[] => {
23
+ return [
24
+ {
25
+ processor: new MyAnalyticsProcessor(module.analyticsStore),
26
+ filter: {
27
+ branch: ["main"],
28
+ documentId: ["*"],
29
+ scope: ["*"],
30
+ documentType: ["*"],
31
+ },
32
+ },
33
+ ];
34
+ };
35
+ ```
36
+
37
+ This function appears complicated at first, but provides for great flexibility.
38
+
39
+ The outside function (`(module: any) => ProcessorFactory`) will be called by the host application (`Reactor`, `Connect`, etc) a single time at initialization. This is intended to resolve external dependencies through the `module` object. In the case of this processor, you can see how the `module` object contains the `analyticsStore`.
40
+
41
+ Next, for each drive created, the returned function (`(driveId:string): ProcessorRecord[]`) will be called. This means that this custom function will be responsible for determining which processors are added for each drive. Applications are free to reuse processors or pass in application-specific dependencies in to each processor.
42
+
43
+ The `filter` parameter allows a user to tune which updates the processor receives. Usage is straightfoward: each field of the filter parameter can receive one to many patterns. The array for each field describes an `OR` operator. That is, `["a", "b"]` would match `"a"` or `"b"`. However, matches across fields describe an `AND` operator. That is, an update must match on `branch` `AND` `documentId` `AND` `documentType` `AND` `scope`.
44
+
45
+ Globs are accepted as input, but not regexes.
46
+
47
+ ```
48
+ {
49
+ branch: ["main"],
50
+ documentId: ["*"],
51
+ documentType: ["doc-type-a", "doc-type-b"],
52
+ scope: ["global", "local"],
53
+ }
54
+ ```
55
+
56
+ This example would match updates for:
57
+
58
+ ```
59
+ ("main" branch) AND (any documentId) AND ("doc-type-a" OR "doc-type-b" documentType) AND ("global" OR "local" scope)
60
+ ```
61
+
62
+ ### onStrands
63
+
64
+ The `onStrands` method is the meat of the processor. This is the function called for all the updates matching the filter. Here is what will be generated for you:
65
+
66
+ ```typescript
67
+ async onStrands<TDocument extends PHDocument>(
68
+ strands: InternalTransmitterUpdate<TDocument>[]
69
+ ): Promise<void> {
70
+ // nothing to update
71
+ if (strands.length === 0) {
72
+ return;
73
+ }
74
+
75
+ const analyticsInputs: AnalyticsSeriesInput[] = [];
76
+ for (const strand of strands) {
77
+ if (strand.operations.length === 0) {
78
+ continue;
79
+ }
80
+
81
+ const firstOp = strand.operations[0];
82
+ const source = AnalyticsPath.fromString(
83
+ `ph/${strand.driveId}/${strand.documentId}/${strand.branch}/${strand.scope}`,
84
+ );
85
+
86
+ if (firstOp.index === 0) {
87
+ await this.clearSource(source);
88
+ }
89
+
90
+ for (const operation of strand.operations) {
91
+ console.log(">>> ", operation.type);
92
+
93
+ // add analytics to the analyticsInputs array
94
+ }
95
+ }
96
+
97
+ if (analyticsInputs.length > 0) {
98
+ // batch insert all analytics data
99
+ await this.analyticsStore.addSeriesValues(analyticsInputs);
100
+ }
101
+ }
102
+ ```
103
+
104
+ This function provides a list of `strand` objects, each with a list of document-model operations (`InternalOperationUpdate[]`) on them. Essentially, it is a list of lists. Each operation will have the previous state of the document and the next state. This allows analytics capture from new state, deltas, or the operations themselves.
105
+
106
+ > Note that on the first operation (given by `firstOp.index === 0`), it is best practice to clear any previous analytics series for that source. This is so that we do not dual insert operations.
107
+
108
+ Model-specific code will go where the `console.log` statement currently resides.
109
+
110
+ > It is best practice to batch insert all updates to the analytics system. In this example, we add all updates to an array of inputs, then insert them all at once. This is optimal over `await`-ing each separate value.
111
+
112
+ ## Learn By Example: RwaAnalyticsProcessor
113
+
114
+ In the `reactor-local` package, we have implemented a processor for the `makerdao/rwa-portfolio` document type. This is a document model that tracks MakerDAO's Real World Asset (RWA) portfolio. It was initially generated using the `ph-cli` utility.
115
+
116
+ In the case of the RWA processor, we only want to process updates for the rwa-specific document type, but across all documents. This is why the filter looks like:
117
+
118
+ ```js
119
+ {
120
+ branch: ["main"],
121
+ documentId: ["*"],
122
+ documentType: ["makerdao/rwa-portfolio"],
123
+ scope: ["global"],
124
+ }
125
+ ```
126
+
127
+ Inside of the `onStrands` function, past the boilerplate, we see what is essentially a giant switch statement.
128
+
129
+ ```typescript
130
+ if (operation.type === "CREATE_GROUP_TRANSACTION") {
131
+ const groupTransaction = operation.input as CreateGroupTransactionInput;
132
+ if (
133
+ groupTransaction.type !== "AssetPurchase" &&
134
+ groupTransaction.type !== "AssetSale" &&
135
+ groupTransaction.type !== "PrincipalDraw" &&
136
+ groupTransaction.type !== "PrincipalReturn"
137
+ ) {
138
+ continue;
139
+ }
140
+
141
+ // elided
142
+ }
143
+ ```
144
+
145
+ Since we have knowledge of this specific document model, we can cast the operation input to a specific type. Then, since we only want to track analytics for operations that create transactions, and we can filter out a few transaction types.
146
+
147
+ Below that, we can see how we are capturing analytics data:
148
+
149
+ ```typescript
150
+ // create good dimensions that we will want to filter on later
151
+ const dimensions = {
152
+ asset: AnalyticsPath.fromString(
153
+ `sky/rwas/assets/t-bills/${fixedIncomeTransaction.assetId}`,
154
+ ),
155
+ portfolio: AnalyticsPath.fromString(
156
+ `sky/rwas/portfolios/${documentId}`,
157
+ ),
158
+ };
159
+
160
+ // create the series values
161
+ const args = {
162
+ dimensions,
163
+ metric: "AssetBalance",
164
+ source,
165
+ start: DateTime.fromISO(fixedIncomeTransaction.entryTime),
166
+ value:
167
+ groupTransaction.type === "AssetPurchase"
168
+ ? fixedIncomeTransaction.amount
169
+ : -fixedIncomeTransaction.amount,
170
+ };
171
+
172
+ analyticsInputs.push(args);
173
+ ```
174
+
175
+ With this processor implementation, we can now write queries against processor analytics updates. For example, a GQL query might look like the following:
176
+
177
+ ```graphql
178
+ query Analytics($filter: AnalyticsFilter) {
179
+ analytics {
180
+ series(filter: $filter) {
181
+ start
182
+ end
183
+ rows {
184
+ dimensions {
185
+ name
186
+ path
187
+ }
188
+ metric
189
+ value
190
+ unit
191
+ }
192
+ }
193
+ }
194
+ }
195
+ ```
196
+
197
+ With variables:
198
+
199
+ ```json
200
+ {
201
+ "filter": {
202
+ "granularity": "annual",
203
+ "start": "2024-01-01",
204
+ "end": "2025-01-01",
205
+ "metrics": [
206
+ "AssetBalance",
207
+ ],
208
+ "dimensions": [
209
+ {
210
+ "name": "asset",
211
+ "select": "sky/rwas",
212
+ "lod": 2
213
+ }
214
+ ]
215
+ }
216
+ }
217
+ ```
218
+
219
+ ## Learn By Example: Document Operations
220
+
221
+ The RWA processor example pulls information from operation _inputs_ to insert analytics data. Another use case might be to capture meta-analytics from the states themselves.
222
+
223
+ This processor listens to all documents of type `powerhouse/document-drive`, and since the `document-drive` is itself implemented on top of the document model core systems, this means that we can process all virtual file system operations. This processor count basic usage metrics using document operations and states.
224
+
225
+ ```typescript
226
+ import { IAnalyticsStore } from "@powerhousedao/reactor-api";
227
+ import { AnalyticsPath } from "@powerhousedao/reactor-api";
228
+ import { AnalyticsSeriesInput } from "@powerhousedao/reactor-api";
229
+ import { InternalTransmitterUpdate, IProcessor } from "document-drive";
230
+ import { AddFileInput, DeleteNodeInput } from "document-drive/drive-document-model/gen/types";
231
+ import { PHDocument } from "document-model";
232
+ import { DateTime } from "luxon";
233
+
234
+ // iterates over state nodes and retrieves one by id
235
+ const findNode = (state: any, id: string) => {
236
+ const { nodes } = state;
237
+ for (const node of nodes) {
238
+ if (node.id === id) {
239
+ return node;
240
+ }
241
+ }
242
+
243
+ return null;
244
+ };
245
+
246
+ export class DriveProcessorProcessor implements IProcessor {
247
+ constructor(private readonly analyticsStore: IAnalyticsStore) {
248
+ //
249
+ }
250
+
251
+ async onStrands<TDocument extends PHDocument>(
252
+ strands: InternalTransmitterUpdate<TDocument>[]
253
+ ): Promise<void> {
254
+ if (strands.length === 0) {
255
+ return;
256
+ }
257
+
258
+ const values:AnalyticsSeriesInput[] = [];
259
+
260
+ for (const strand of strands) {
261
+ const operations = strand.operations;
262
+ await Promise.all(operations.map((operation) => {
263
+ const source = AnalyticsPath.fromString(`switchboard/default/${strand.driveId}`);
264
+
265
+ const start = DateTime.fromISO(operation.timestamp);
266
+ const dimensions: any = {
267
+ documentType: AnalyticsPath.fromString(`document/type/powerhouse/document-drive`),
268
+ };
269
+
270
+ if (operation.index === 0) {
271
+ this.analyticsStore.clearSeriesBySource(source);
272
+ }
273
+
274
+ switch (operation.type) {
275
+ case "ADD_FILE": {
276
+ // count documents of each type (ADD_FILE, input.documentType)
277
+
278
+ // lookup node in state
279
+ const input = operation.input as AddFileInput;
280
+ const node = findNode(strand.state, input.id);
281
+ if (!node) {
282
+ return Promise.resolve();
283
+ }
284
+
285
+ dimensions["kind"] = AnalyticsPath.fromString(`document/kind/${node.kind}`);
286
+
287
+ // increment by adding a 1
288
+ values.push({
289
+ source,
290
+ start,
291
+ value: 1,
292
+ metric: "Count",
293
+ dimensions,
294
+ });
295
+
296
+ break;
297
+ }
298
+ case "ADD_FOLDER": {
299
+ dimensions["kind"] = AnalyticsPath.fromString("document/kind/folder");
300
+
301
+ // increment by adding a 1
302
+ values.push({
303
+ source,
304
+ start,
305
+ value: 1,
306
+ metric: "Count",
307
+ dimensions,
308
+ });
309
+
310
+ break;
311
+ }
312
+ case "DELETE_NODE": {
313
+ // the operation only contains the id, so lookup deleted item type in previous state
314
+ const input = operation.input as DeleteNodeInput;
315
+ const node = findNode(operation.previousState, input.id);
316
+ if (!node) {
317
+ return Promise.resolve();
318
+ }
319
+
320
+ dimensions["kind"] = AnalyticsPath.fromString(`document/kind/${node.kind}`);
321
+
322
+ // decrement by adding a -1
323
+ values.push({
324
+ source,
325
+ start,
326
+ value: -1,
327
+ metric: "Count",
328
+ dimensions,
329
+ });
330
+
331
+ break;
332
+ }
333
+ }
334
+ }));
335
+ }
336
+
337
+ await this.analyticsStore.addSeriesValues(values);
338
+ }
339
+
340
+ async onDisconnect() {}
341
+ }
342
+ ```