@powerhousedao/codegen 6.0.0-dev.15 → 6.0.0-dev.151

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 (656) hide show
  1. package/{dist/src/templates/boilerplate/LICENSE.js → LICENSE} +1 -4
  2. package/dist/file-builders-CNatGM0p.mjs +1653 -0
  3. package/dist/file-builders-CNatGM0p.mjs.map +1 -0
  4. package/dist/index-CHAnPBj2.d.mts +199 -0
  5. package/dist/index-CHAnPBj2.d.mts.map +1 -0
  6. package/dist/index-CJZGVSYg.d.mts +65 -0
  7. package/dist/index-CJZGVSYg.d.mts.map +1 -0
  8. package/dist/index.d.mts +298 -0
  9. package/dist/index.d.mts.map +1 -0
  10. package/dist/index.mjs +793 -0
  11. package/dist/index.mjs.map +1 -0
  12. package/dist/src/file-builders/index.d.mts +3 -0
  13. package/dist/src/file-builders/index.mjs +3 -0
  14. package/dist/src/name-builders/index.d.mts +2 -0
  15. package/dist/src/name-builders/index.mjs +146 -0
  16. package/dist/src/name-builders/index.mjs.map +1 -0
  17. package/dist/src/templates/index.d.mts +416 -0
  18. package/dist/src/templates/index.d.mts.map +1 -0
  19. package/dist/src/templates/index.mjs +2 -0
  20. package/dist/src/utils/index.d.mts +125 -0
  21. package/dist/src/utils/index.d.mts.map +1 -0
  22. package/dist/src/utils/index.mjs +380 -0
  23. package/dist/src/utils/index.mjs.map +1 -0
  24. package/dist/templates-Bn7kq5sb.mjs +4613 -0
  25. package/dist/templates-Bn7kq5sb.mjs.map +1 -0
  26. package/dist/types-e2ztuDtG.d.mts +87 -0
  27. package/dist/types-e2ztuDtG.d.mts.map +1 -0
  28. package/dist/validation-Bpg_44mW.d.mts +43 -0
  29. package/dist/validation-Bpg_44mW.d.mts.map +1 -0
  30. package/package.json +30 -59
  31. package/dist/index.d.ts +0 -8
  32. package/dist/index.d.ts.map +0 -1
  33. package/dist/index.js +0 -7
  34. package/dist/index.js.map +0 -1
  35. package/dist/src/codegen/.hygen/package.json +0 -6
  36. package/dist/src/codegen/.hygen/templates/powerhouse/generate-custom-subgraph/index.js +0 -10
  37. package/dist/src/codegen/.hygen/templates/powerhouse/generate-custom-subgraph/resolvers.esm.t +0 -17
  38. package/dist/src/codegen/.hygen/templates/powerhouse/generate-custom-subgraph/schema.esm.t +0 -16
  39. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/actions.esm.t +0 -16
  40. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/creators.esm.t +0 -9
  41. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/customUtils.esm.t +0 -5
  42. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/document-schema.esm.t +0 -56
  43. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/document-type.esm.t +0 -6
  44. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/documentModel.esm.t +0 -7
  45. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/documentModelTest.esm.t +0 -121
  46. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/hooks.esm.t +0 -49
  47. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/index.esm.t +0 -23
  48. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/index.js +0 -127
  49. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/module.esm.t +0 -22
  50. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/ph-factories.esm.t +0 -93
  51. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/reducer.esm.t +0 -46
  52. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/root-utils.esm.t +0 -11
  53. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/rootActions.esm.t +0 -13
  54. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/rootIndex.esm.t +0 -14
  55. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/schema.esm.t +0 -6
  56. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/src-index.esm.t +0 -5
  57. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/types.esm.t +0 -31
  58. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model/utils.esm.t +0 -77
  59. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-module/actions.esm.t +0 -22
  60. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-module/creators.esm.t +0 -37
  61. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-module/customTest.esm.t +0 -44
  62. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-module/error.esm.t +0 -36
  63. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-module/index.js +0 -71
  64. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-module/operations.esm.t +0 -17
  65. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-subgraph/index.js +0 -118
  66. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-subgraph/resolvers.esm.t +0 -130
  67. package/dist/src/codegen/.hygen/templates/powerhouse/generate-document-model-subgraph/schema.esm.t +0 -44
  68. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/CreateDocument.esm.t +0 -58
  69. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/DriveContents.esm.t +0 -23
  70. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/DriveExplorer.esm.t +0 -32
  71. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/EmptyState.esm.t +0 -19
  72. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/Files.esm.t +0 -29
  73. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/FolderTree.esm.t +0 -108
  74. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/Folders.esm.t +0 -28
  75. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/components/NavigationBreadcrumbs.esm.t +0 -14
  76. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/config.esm.t +0 -11
  77. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/editor.esm.t +0 -20
  78. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/index.js +0 -25
  79. package/dist/src/codegen/.hygen/templates/powerhouse/generate-drive-editor/module.esm.t +0 -15
  80. package/dist/src/codegen/.hygen/templates/powerhouse/generate-editor/editor.esm.t +0 -80
  81. package/dist/src/codegen/.hygen/templates/powerhouse/generate-editor/index.js +0 -90
  82. package/dist/src/codegen/.hygen/templates/powerhouse/generate-editor/module.esm.t +0 -16
  83. package/dist/src/codegen/.hygen/templates/powerhouse/generate-import-script/index.esm.t +0 -59
  84. package/dist/src/codegen/.hygen/templates/powerhouse/generate-import-script/index.js +0 -9
  85. package/dist/src/codegen/.hygen/templates/powerhouse/generate-import-script/utils.esm.t +0 -100
  86. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/factory.esm.t +0 -22
  87. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/index.esm.t +0 -62
  88. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/index.js +0 -12
  89. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/index.root.esm.t +0 -10
  90. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/index.root.inject.esm.t +0 -12
  91. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/lib.esm.t +0 -34
  92. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/lib.inject_call.esm.t +0 -7
  93. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/lib.inject_export.esm.t +0 -7
  94. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-analytics/lib.inject_import.esm.t +0 -7
  95. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/factory.esm.t +0 -40
  96. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/index.esm.t +0 -47
  97. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/index.js +0 -12
  98. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/index.root.esm.t +0 -10
  99. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/index.root.inject.esm.t +0 -12
  100. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/lib.esm.t +0 -34
  101. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/lib.inject_call.esm.t +0 -7
  102. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/lib.inject_export.esm.t +0 -9
  103. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/lib.inject_import.esm.t +0 -7
  104. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/migrations.esm.t +0 -23
  105. package/dist/src/codegen/.hygen/templates/powerhouse/generate-processor-relationalDb/schema.esm.t +0 -13
  106. package/dist/src/codegen/.hygen/templates/powerhouse/generate-subgraph/index.esm.t +0 -17
  107. package/dist/src/codegen/.hygen/templates/powerhouse/generate-subgraph/index.js +0 -10
  108. package/dist/src/codegen/.hygen/templates/powerhouse/generate-subgraph/lib.esm.t +0 -9
  109. package/dist/src/codegen/__tests__/config.d.ts +0 -3
  110. package/dist/src/codegen/__tests__/config.d.ts.map +0 -1
  111. package/dist/src/codegen/__tests__/config.js +0 -3
  112. package/dist/src/codegen/__tests__/config.js.map +0 -1
  113. package/dist/src/codegen/__tests__/constants.d.ts +0 -16
  114. package/dist/src/codegen/__tests__/constants.d.ts.map +0 -1
  115. package/dist/src/codegen/__tests__/constants.js +0 -16
  116. package/dist/src/codegen/__tests__/constants.js.map +0 -1
  117. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content-v3.d.ts +0 -2
  118. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content-v3.d.ts.map +0 -1
  119. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content-v3.js +0 -9
  120. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content-v3.js.map +0 -1
  121. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content.d.ts +0 -3
  122. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content.d.ts.map +0 -1
  123. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content.js +0 -33
  124. package/dist/src/codegen/__tests__/fixtures/expected-reducer-content.js.map +0 -1
  125. package/dist/src/codegen/__tests__/fixtures/run-generated-tests.d.ts +0 -2
  126. package/dist/src/codegen/__tests__/fixtures/run-generated-tests.d.ts.map +0 -1
  127. package/dist/src/codegen/__tests__/fixtures/run-generated-tests.js +0 -23
  128. package/dist/src/codegen/__tests__/fixtures/run-generated-tests.js.map +0 -1
  129. package/dist/src/codegen/__tests__/fixtures/typecheck.d.ts +0 -2
  130. package/dist/src/codegen/__tests__/fixtures/typecheck.d.ts.map +0 -1
  131. package/dist/src/codegen/__tests__/fixtures/typecheck.js +0 -23
  132. package/dist/src/codegen/__tests__/fixtures/typecheck.js.map +0 -1
  133. package/dist/src/codegen/__tests__/generate-doc-model.test.d.ts +0 -2
  134. package/dist/src/codegen/__tests__/generate-doc-model.test.d.ts.map +0 -1
  135. package/dist/src/codegen/__tests__/generate-doc-model.test.js +0 -233
  136. package/dist/src/codegen/__tests__/generate-doc-model.test.js.map +0 -1
  137. package/dist/src/codegen/__tests__/generate-drive-editor.test.d.ts +0 -2
  138. package/dist/src/codegen/__tests__/generate-drive-editor.test.d.ts.map +0 -1
  139. package/dist/src/codegen/__tests__/generate-drive-editor.test.js +0 -156
  140. package/dist/src/codegen/__tests__/generate-drive-editor.test.js.map +0 -1
  141. package/dist/src/codegen/__tests__/generate-editor.test.d.ts +0 -2
  142. package/dist/src/codegen/__tests__/generate-editor.test.d.ts.map +0 -1
  143. package/dist/src/codegen/__tests__/generate-editor.test.js +0 -115
  144. package/dist/src/codegen/__tests__/generate-editor.test.js.map +0 -1
  145. package/dist/src/codegen/__tests__/generate-manifest.test.d.ts +0 -2
  146. package/dist/src/codegen/__tests__/generate-manifest.test.d.ts.map +0 -1
  147. package/dist/src/codegen/__tests__/generate-manifest.test.js +0 -192
  148. package/dist/src/codegen/__tests__/generate-manifest.test.js.map +0 -1
  149. package/dist/src/codegen/__tests__/generate-versioned-document-model.test.d.ts +0 -2
  150. package/dist/src/codegen/__tests__/generate-versioned-document-model.test.d.ts.map +0 -1
  151. package/dist/src/codegen/__tests__/generate-versioned-document-model.test.js +0 -159
  152. package/dist/src/codegen/__tests__/generate-versioned-document-model.test.js.map +0 -1
  153. package/dist/src/codegen/__tests__/global-setup.d.ts +0 -2
  154. package/dist/src/codegen/__tests__/global-setup.d.ts.map +0 -1
  155. package/dist/src/codegen/__tests__/global-setup.js +0 -21
  156. package/dist/src/codegen/__tests__/global-setup.js.map +0 -1
  157. package/dist/src/codegen/__tests__/ts-morph-generator.test.d.ts +0 -2
  158. package/dist/src/codegen/__tests__/ts-morph-generator.test.d.ts.map +0 -1
  159. package/dist/src/codegen/__tests__/ts-morph-generator.test.js +0 -73
  160. package/dist/src/codegen/__tests__/ts-morph-generator.test.js.map +0 -1
  161. package/dist/src/codegen/__tests__/utils.d.ts +0 -7
  162. package/dist/src/codegen/__tests__/utils.d.ts.map +0 -1
  163. package/dist/src/codegen/__tests__/utils.js +0 -52
  164. package/dist/src/codegen/__tests__/utils.js.map +0 -1
  165. package/dist/src/codegen/generate.d.ts +0 -79
  166. package/dist/src/codegen/generate.d.ts.map +0 -1
  167. package/dist/src/codegen/generate.js +0 -334
  168. package/dist/src/codegen/generate.js.map +0 -1
  169. package/dist/src/codegen/graphql.d.ts +0 -36
  170. package/dist/src/codegen/graphql.d.ts.map +0 -1
  171. package/dist/src/codegen/graphql.js +0 -146
  172. package/dist/src/codegen/graphql.js.map +0 -1
  173. package/dist/src/codegen/hygen.d.ts +0 -47
  174. package/dist/src/codegen/hygen.d.ts.map +0 -1
  175. package/dist/src/codegen/hygen.js +0 -230
  176. package/dist/src/codegen/hygen.js.map +0 -1
  177. package/dist/src/codegen/index.d.ts +0 -7
  178. package/dist/src/codegen/index.d.ts.map +0 -1
  179. package/dist/src/codegen/index.js +0 -7
  180. package/dist/src/codegen/index.js.map +0 -1
  181. package/dist/src/codegen/kysely.d.ts +0 -6
  182. package/dist/src/codegen/kysely.d.ts.map +0 -1
  183. package/dist/src/codegen/kysely.js +0 -51
  184. package/dist/src/codegen/kysely.js.map +0 -1
  185. package/dist/src/codegen/types.d.ts +0 -9
  186. package/dist/src/codegen/types.d.ts.map +0 -1
  187. package/dist/src/codegen/types.js +0 -2
  188. package/dist/src/codegen/types.js.map +0 -1
  189. package/dist/src/codegen/utils.d.ts +0 -7
  190. package/dist/src/codegen/utils.d.ts.map +0 -1
  191. package/dist/src/codegen/utils.js +0 -79
  192. package/dist/src/codegen/utils.js.map +0 -1
  193. package/dist/src/create-lib/checkout-project.d.ts +0 -13
  194. package/dist/src/create-lib/checkout-project.d.ts.map +0 -1
  195. package/dist/src/create-lib/checkout-project.js +0 -47
  196. package/dist/src/create-lib/checkout-project.js.map +0 -1
  197. package/dist/src/create-lib/create-project.d.ts +0 -10
  198. package/dist/src/create-lib/create-project.d.ts.map +0 -1
  199. package/dist/src/create-lib/create-project.js +0 -98
  200. package/dist/src/create-lib/create-project.js.map +0 -1
  201. package/dist/src/create-lib/feature-flags.d.ts +0 -4
  202. package/dist/src/create-lib/feature-flags.d.ts.map +0 -1
  203. package/dist/src/create-lib/feature-flags.js +0 -4
  204. package/dist/src/create-lib/feature-flags.js.map +0 -1
  205. package/dist/src/create-lib/index.d.ts +0 -3
  206. package/dist/src/create-lib/index.d.ts.map +0 -1
  207. package/dist/src/create-lib/index.js +0 -3
  208. package/dist/src/create-lib/index.js.map +0 -1
  209. package/dist/src/create-lib/utils.d.ts +0 -8
  210. package/dist/src/create-lib/utils.d.ts.map +0 -1
  211. package/dist/src/create-lib/utils.js +0 -34
  212. package/dist/src/create-lib/utils.js.map +0 -1
  213. package/dist/src/file-builders/boilerplate/build-package-json.test.d.ts +0 -2
  214. package/dist/src/file-builders/boilerplate/build-package-json.test.d.ts.map +0 -1
  215. package/dist/src/file-builders/boilerplate/build-package-json.test.js +0 -28
  216. package/dist/src/file-builders/boilerplate/build-package-json.test.js.map +0 -1
  217. package/dist/src/file-builders/boilerplate/package-json-versions.test.d.ts +0 -2
  218. package/dist/src/file-builders/boilerplate/package-json-versions.test.d.ts.map +0 -1
  219. package/dist/src/file-builders/boilerplate/package-json-versions.test.js +0 -34
  220. package/dist/src/file-builders/boilerplate/package-json-versions.test.js.map +0 -1
  221. package/dist/src/file-builders/boilerplate/package.json.d.ts +0 -6
  222. package/dist/src/file-builders/boilerplate/package.json.d.ts.map +0 -1
  223. package/dist/src/file-builders/boilerplate/package.json.js +0 -18
  224. package/dist/src/file-builders/boilerplate/package.json.js.map +0 -1
  225. package/dist/src/file-builders/document-editor.d.ts +0 -8
  226. package/dist/src/file-builders/document-editor.d.ts.map +0 -1
  227. package/dist/src/file-builders/document-editor.js +0 -57
  228. package/dist/src/file-builders/document-editor.js.map +0 -1
  229. package/dist/src/file-builders/document-model/document-model.d.ts +0 -8
  230. package/dist/src/file-builders/document-model/document-model.d.ts.map +0 -1
  231. package/dist/src/file-builders/document-model/document-model.js +0 -246
  232. package/dist/src/file-builders/document-model/document-model.js.map +0 -1
  233. package/dist/src/file-builders/document-model/gen-dir.d.ts +0 -3
  234. package/dist/src/file-builders/document-model/gen-dir.d.ts.map +0 -1
  235. package/dist/src/file-builders/document-model/gen-dir.js +0 -201
  236. package/dist/src/file-builders/document-model/gen-dir.js.map +0 -1
  237. package/dist/src/file-builders/document-model/root-dir.d.ts +0 -3
  238. package/dist/src/file-builders/document-model/root-dir.d.ts.map +0 -1
  239. package/dist/src/file-builders/document-model/root-dir.js +0 -51
  240. package/dist/src/file-builders/document-model/root-dir.js.map +0 -1
  241. package/dist/src/file-builders/document-model/src-dir.d.ts +0 -3
  242. package/dist/src/file-builders/document-model/src-dir.d.ts.map +0 -1
  243. package/dist/src/file-builders/document-model/src-dir.js +0 -118
  244. package/dist/src/file-builders/document-model/src-dir.js.map +0 -1
  245. package/dist/src/file-builders/document-model/tests-dir.d.ts +0 -3
  246. package/dist/src/file-builders/document-model/tests-dir.d.ts.map +0 -1
  247. package/dist/src/file-builders/document-model/tests-dir.js +0 -127
  248. package/dist/src/file-builders/document-model/tests-dir.js.map +0 -1
  249. package/dist/src/file-builders/document-model/upgrades-dir.d.ts +0 -31
  250. package/dist/src/file-builders/document-model/upgrades-dir.d.ts.map +0 -1
  251. package/dist/src/file-builders/document-model/upgrades-dir.js +0 -135
  252. package/dist/src/file-builders/document-model/upgrades-dir.js.map +0 -1
  253. package/dist/src/file-builders/drive-editor.d.ts +0 -9
  254. package/dist/src/file-builders/drive-editor.d.ts.map +0 -1
  255. package/dist/src/file-builders/drive-editor.js +0 -164
  256. package/dist/src/file-builders/drive-editor.js.map +0 -1
  257. package/dist/src/file-builders/editor-common.d.ts +0 -13
  258. package/dist/src/file-builders/editor-common.d.ts.map +0 -1
  259. package/dist/src/file-builders/editor-common.js +0 -26
  260. package/dist/src/file-builders/editor-common.js.map +0 -1
  261. package/dist/src/file-builders/index-files.d.ts +0 -18
  262. package/dist/src/file-builders/index-files.d.ts.map +0 -1
  263. package/dist/src/file-builders/index-files.js +0 -25
  264. package/dist/src/file-builders/index-files.js.map +0 -1
  265. package/dist/src/file-builders/index.d.ts +0 -10
  266. package/dist/src/file-builders/index.d.ts.map +0 -1
  267. package/dist/src/file-builders/index.js +0 -9
  268. package/dist/src/file-builders/index.js.map +0 -1
  269. package/dist/src/file-builders/module-files.d.ts +0 -52
  270. package/dist/src/file-builders/module-files.d.ts.map +0 -1
  271. package/dist/src/file-builders/module-files.js +0 -230
  272. package/dist/src/file-builders/module-files.js.map +0 -1
  273. package/dist/src/file-builders/subgraphs.d.ts +0 -6
  274. package/dist/src/file-builders/subgraphs.d.ts.map +0 -1
  275. package/dist/src/file-builders/subgraphs.js +0 -53
  276. package/dist/src/file-builders/subgraphs.js.map +0 -1
  277. package/dist/src/file-builders/types.d.ts +0 -66
  278. package/dist/src/file-builders/types.d.ts.map +0 -1
  279. package/dist/src/file-builders/types.js +0 -2
  280. package/dist/src/file-builders/types.js.map +0 -1
  281. package/dist/src/index.d.ts +0 -5
  282. package/dist/src/index.d.ts.map +0 -1
  283. package/dist/src/index.js +0 -5
  284. package/dist/src/index.js.map +0 -1
  285. package/dist/src/name-builders/get-action-names.d.ts +0 -6
  286. package/dist/src/name-builders/get-action-names.d.ts.map +0 -1
  287. package/dist/src/name-builders/get-action-names.js +0 -16
  288. package/dist/src/name-builders/get-action-names.js.map +0 -1
  289. package/dist/src/name-builders/get-variable-names.d.ts +0 -48
  290. package/dist/src/name-builders/get-variable-names.d.ts.map +0 -1
  291. package/dist/src/name-builders/get-variable-names.js +0 -147
  292. package/dist/src/name-builders/get-variable-names.js.map +0 -1
  293. package/dist/src/name-builders/index.d.ts +0 -3
  294. package/dist/src/name-builders/index.d.ts.map +0 -1
  295. package/dist/src/name-builders/index.js +0 -3
  296. package/dist/src/name-builders/index.js.map +0 -1
  297. package/dist/src/templates/boilerplate/AGENTS.md.d.ts +0 -2
  298. package/dist/src/templates/boilerplate/AGENTS.md.d.ts.map +0 -1
  299. package/dist/src/templates/boilerplate/AGENTS.md.js +0 -408
  300. package/dist/src/templates/boilerplate/AGENTS.md.js.map +0 -1
  301. package/dist/src/templates/boilerplate/CLAUDE.md.d.ts +0 -2
  302. package/dist/src/templates/boilerplate/CLAUDE.md.d.ts.map +0 -1
  303. package/dist/src/templates/boilerplate/CLAUDE.md.js +0 -408
  304. package/dist/src/templates/boilerplate/CLAUDE.md.js.map +0 -1
  305. package/dist/src/templates/boilerplate/LICENSE.d.ts +0 -2
  306. package/dist/src/templates/boilerplate/LICENSE.d.ts.map +0 -1
  307. package/dist/src/templates/boilerplate/LICENSE.js.map +0 -1
  308. package/dist/src/templates/boilerplate/README.md.d.ts +0 -2
  309. package/dist/src/templates/boilerplate/README.md.d.ts.map +0 -1
  310. package/dist/src/templates/boilerplate/README.md.js +0 -194
  311. package/dist/src/templates/boilerplate/README.md.js.map +0 -1
  312. package/dist/src/templates/boilerplate/claude/settings.local.json.d.ts +0 -2
  313. package/dist/src/templates/boilerplate/claude/settings.local.json.d.ts.map +0 -1
  314. package/dist/src/templates/boilerplate/claude/settings.local.json.js +0 -18
  315. package/dist/src/templates/boilerplate/claude/settings.local.json.js.map +0 -1
  316. package/dist/src/templates/boilerplate/cursor/mcp.json.d.ts +0 -2
  317. package/dist/src/templates/boilerplate/cursor/mcp.json.d.ts.map +0 -1
  318. package/dist/src/templates/boilerplate/cursor/mcp.json.js +0 -12
  319. package/dist/src/templates/boilerplate/cursor/mcp.json.js.map +0 -1
  320. package/dist/src/templates/boilerplate/document-models/document-models.d.ts +0 -2
  321. package/dist/src/templates/boilerplate/document-models/document-models.d.ts.map +0 -1
  322. package/dist/src/templates/boilerplate/document-models/document-models.js +0 -7
  323. package/dist/src/templates/boilerplate/document-models/document-models.js.map +0 -1
  324. package/dist/src/templates/boilerplate/document-models/index.d.ts +0 -2
  325. package/dist/src/templates/boilerplate/document-models/index.d.ts.map +0 -1
  326. package/dist/src/templates/boilerplate/document-models/index.js +0 -2
  327. package/dist/src/templates/boilerplate/document-models/index.js.map +0 -1
  328. package/dist/src/templates/boilerplate/editors/editors.d.ts +0 -2
  329. package/dist/src/templates/boilerplate/editors/editors.d.ts.map +0 -1
  330. package/dist/src/templates/boilerplate/editors/editors.js +0 -7
  331. package/dist/src/templates/boilerplate/editors/editors.js.map +0 -1
  332. package/dist/src/templates/boilerplate/editors/index.d.ts +0 -2
  333. package/dist/src/templates/boilerplate/editors/index.d.ts.map +0 -1
  334. package/dist/src/templates/boilerplate/editors/index.js +0 -2
  335. package/dist/src/templates/boilerplate/editors/index.js.map +0 -1
  336. package/dist/src/templates/boilerplate/eslint.config.js.d.ts +0 -2
  337. package/dist/src/templates/boilerplate/eslint.config.js.d.ts.map +0 -1
  338. package/dist/src/templates/boilerplate/eslint.config.js.js +0 -140
  339. package/dist/src/templates/boilerplate/eslint.config.js.js.map +0 -1
  340. package/dist/src/templates/boilerplate/gemini/settings.json.d.ts +0 -2
  341. package/dist/src/templates/boilerplate/gemini/settings.json.d.ts.map +0 -1
  342. package/dist/src/templates/boilerplate/gemini/settings.json.js +0 -12
  343. package/dist/src/templates/boilerplate/gemini/settings.json.js.map +0 -1
  344. package/dist/src/templates/boilerplate/gitignore.d.ts +0 -2
  345. package/dist/src/templates/boilerplate/gitignore.d.ts.map +0 -1
  346. package/dist/src/templates/boilerplate/gitignore.js +0 -11
  347. package/dist/src/templates/boilerplate/gitignore.js.map +0 -1
  348. package/dist/src/templates/boilerplate/index.d.ts +0 -2
  349. package/dist/src/templates/boilerplate/index.d.ts.map +0 -1
  350. package/dist/src/templates/boilerplate/index.html.d.ts +0 -2
  351. package/dist/src/templates/boilerplate/index.html.d.ts.map +0 -1
  352. package/dist/src/templates/boilerplate/index.html.js +0 -31
  353. package/dist/src/templates/boilerplate/index.html.js.map +0 -1
  354. package/dist/src/templates/boilerplate/index.html.legacy.d.ts +0 -2
  355. package/dist/src/templates/boilerplate/index.html.legacy.d.ts.map +0 -1
  356. package/dist/src/templates/boilerplate/index.html.legacy.js +0 -36
  357. package/dist/src/templates/boilerplate/index.html.legacy.js.map +0 -1
  358. package/dist/src/templates/boilerplate/index.js +0 -8
  359. package/dist/src/templates/boilerplate/index.js.map +0 -1
  360. package/dist/src/templates/boilerplate/mcp.json.d.ts +0 -2
  361. package/dist/src/templates/boilerplate/mcp.json.d.ts.map +0 -1
  362. package/dist/src/templates/boilerplate/mcp.json.js +0 -12
  363. package/dist/src/templates/boilerplate/mcp.json.js.map +0 -1
  364. package/dist/src/templates/boilerplate/npmrc.d.ts +0 -2
  365. package/dist/src/templates/boilerplate/npmrc.d.ts.map +0 -1
  366. package/dist/src/templates/boilerplate/npmrc.js +0 -2
  367. package/dist/src/templates/boilerplate/npmrc.js.map +0 -1
  368. package/dist/src/templates/boilerplate/package.json.d.ts +0 -2
  369. package/dist/src/templates/boilerplate/package.json.d.ts.map +0 -1
  370. package/dist/src/templates/boilerplate/package.json.js +0 -115
  371. package/dist/src/templates/boilerplate/package.json.js.map +0 -1
  372. package/dist/src/templates/boilerplate/package.json.legacy.d.ts +0 -55
  373. package/dist/src/templates/boilerplate/package.json.legacy.d.ts.map +0 -1
  374. package/dist/src/templates/boilerplate/package.json.legacy.js +0 -55
  375. package/dist/src/templates/boilerplate/package.json.legacy.js.map +0 -1
  376. package/dist/src/templates/boilerplate/powerhouse.config.json.d.ts +0 -6
  377. package/dist/src/templates/boilerplate/powerhouse.config.json.d.ts.map +0 -1
  378. package/dist/src/templates/boilerplate/powerhouse.config.json.js +0 -46
  379. package/dist/src/templates/boilerplate/powerhouse.config.json.js.map +0 -1
  380. package/dist/src/templates/boilerplate/powerhouse.manifest.json.d.ts +0 -2
  381. package/dist/src/templates/boilerplate/powerhouse.manifest.json.d.ts.map +0 -1
  382. package/dist/src/templates/boilerplate/powerhouse.manifest.json.js +0 -19
  383. package/dist/src/templates/boilerplate/powerhouse.manifest.json.js.map +0 -1
  384. package/dist/src/templates/boilerplate/processors/index.d.ts +0 -2
  385. package/dist/src/templates/boilerplate/processors/index.d.ts.map +0 -1
  386. package/dist/src/templates/boilerplate/processors/index.js +0 -2
  387. package/dist/src/templates/boilerplate/processors/index.js.map +0 -1
  388. package/dist/src/templates/boilerplate/style.css.d.ts +0 -2
  389. package/dist/src/templates/boilerplate/style.css.d.ts.map +0 -1
  390. package/dist/src/templates/boilerplate/style.css.js +0 -17
  391. package/dist/src/templates/boilerplate/style.css.js.map +0 -1
  392. package/dist/src/templates/boilerplate/subgraphs/index.d.ts +0 -2
  393. package/dist/src/templates/boilerplate/subgraphs/index.d.ts.map +0 -1
  394. package/dist/src/templates/boilerplate/subgraphs/index.js +0 -2
  395. package/dist/src/templates/boilerplate/subgraphs/index.js.map +0 -1
  396. package/dist/src/templates/boilerplate/tsconfig.json.d.ts +0 -2
  397. package/dist/src/templates/boilerplate/tsconfig.json.d.ts.map +0 -1
  398. package/dist/src/templates/boilerplate/tsconfig.json.js +0 -46
  399. package/dist/src/templates/boilerplate/tsconfig.json.js.map +0 -1
  400. package/dist/src/templates/boilerplate/vite.config.ts.d.ts +0 -2
  401. package/dist/src/templates/boilerplate/vite.config.ts.d.ts.map +0 -1
  402. package/dist/src/templates/boilerplate/vite.config.ts.js +0 -21
  403. package/dist/src/templates/boilerplate/vite.config.ts.js.map +0 -1
  404. package/dist/src/templates/boilerplate/vitest.config.ts.d.ts +0 -2
  405. package/dist/src/templates/boilerplate/vitest.config.ts.d.ts.map +0 -1
  406. package/dist/src/templates/boilerplate/vitest.config.ts.js +0 -21
  407. package/dist/src/templates/boilerplate/vitest.config.ts.js.map +0 -1
  408. package/dist/src/templates/document-editor/editor.d.ts +0 -5
  409. package/dist/src/templates/document-editor/editor.d.ts.map +0 -1
  410. package/dist/src/templates/document-editor/editor.js +0 -85
  411. package/dist/src/templates/document-editor/editor.js.map +0 -1
  412. package/dist/src/templates/document-editor/module.d.ts +0 -7
  413. package/dist/src/templates/document-editor/module.d.ts.map +0 -1
  414. package/dist/src/templates/document-editor/module.js +0 -16
  415. package/dist/src/templates/document-editor/module.js.map +0 -1
  416. package/dist/src/templates/document-model/actions.d.ts +0 -3
  417. package/dist/src/templates/document-model/actions.d.ts.map +0 -1
  418. package/dist/src/templates/document-model/actions.js +0 -28
  419. package/dist/src/templates/document-model/actions.js.map +0 -1
  420. package/dist/src/templates/document-model/gen/actions.d.ts +0 -3
  421. package/dist/src/templates/document-model/gen/actions.d.ts.map +0 -1
  422. package/dist/src/templates/document-model/gen/actions.js +0 -40
  423. package/dist/src/templates/document-model/gen/actions.js.map +0 -1
  424. package/dist/src/templates/document-model/gen/creators.d.ts +0 -3
  425. package/dist/src/templates/document-model/gen/creators.d.ts.map +0 -1
  426. package/dist/src/templates/document-model/gen/creators.js +0 -16
  427. package/dist/src/templates/document-model/gen/creators.js.map +0 -1
  428. package/dist/src/templates/document-model/gen/document-schema.d.ts +0 -3
  429. package/dist/src/templates/document-model/gen/document-schema.d.ts.map +0 -1
  430. package/dist/src/templates/document-model/gen/document-schema.js +0 -56
  431. package/dist/src/templates/document-model/gen/document-schema.js.map +0 -1
  432. package/dist/src/templates/document-model/gen/document-type.d.ts +0 -3
  433. package/dist/src/templates/document-model/gen/document-type.d.ts.map +0 -1
  434. package/dist/src/templates/document-model/gen/document-type.js +0 -5
  435. package/dist/src/templates/document-model/gen/document-type.js.map +0 -1
  436. package/dist/src/templates/document-model/gen/index.d.ts +0 -3
  437. package/dist/src/templates/document-model/gen/index.d.ts.map +0 -1
  438. package/dist/src/templates/document-model/gen/index.js +0 -29
  439. package/dist/src/templates/document-model/gen/index.js.map +0 -1
  440. package/dist/src/templates/document-model/gen/modules/actions.d.ts +0 -8
  441. package/dist/src/templates/document-model/gen/modules/actions.d.ts.map +0 -1
  442. package/dist/src/templates/document-model/gen/modules/actions.js +0 -39
  443. package/dist/src/templates/document-model/gen/modules/actions.js.map +0 -1
  444. package/dist/src/templates/document-model/gen/modules/creators.d.ts +0 -3
  445. package/dist/src/templates/document-model/gen/modules/creators.d.ts.map +0 -1
  446. package/dist/src/templates/document-model/gen/modules/creators.js +0 -97
  447. package/dist/src/templates/document-model/gen/modules/creators.js.map +0 -1
  448. package/dist/src/templates/document-model/gen/modules/error.d.ts +0 -3
  449. package/dist/src/templates/document-model/gen/modules/error.d.ts.map +0 -1
  450. package/dist/src/templates/document-model/gen/modules/error.js +0 -73
  451. package/dist/src/templates/document-model/gen/modules/error.js.map +0 -1
  452. package/dist/src/templates/document-model/gen/modules/operations.d.ts +0 -3
  453. package/dist/src/templates/document-model/gen/modules/operations.d.ts.map +0 -1
  454. package/dist/src/templates/document-model/gen/modules/operations.js +0 -61
  455. package/dist/src/templates/document-model/gen/modules/operations.js.map +0 -1
  456. package/dist/src/templates/document-model/gen/ph-factories.d.ts +0 -3
  457. package/dist/src/templates/document-model/gen/ph-factories.d.ts.map +0 -1
  458. package/dist/src/templates/document-model/gen/ph-factories.js +0 -93
  459. package/dist/src/templates/document-model/gen/ph-factories.js.map +0 -1
  460. package/dist/src/templates/document-model/gen/reducer.d.ts +0 -3
  461. package/dist/src/templates/document-model/gen/reducer.d.ts.map +0 -1
  462. package/dist/src/templates/document-model/gen/reducer.js +0 -106
  463. package/dist/src/templates/document-model/gen/reducer.js.map +0 -1
  464. package/dist/src/templates/document-model/gen/schema/index.d.ts +0 -2
  465. package/dist/src/templates/document-model/gen/schema/index.d.ts.map +0 -1
  466. package/dist/src/templates/document-model/gen/schema/index.js +0 -6
  467. package/dist/src/templates/document-model/gen/schema/index.js.map +0 -1
  468. package/dist/src/templates/document-model/gen/types.d.ts +0 -3
  469. package/dist/src/templates/document-model/gen/types.d.ts.map +0 -1
  470. package/dist/src/templates/document-model/gen/types.js +0 -38
  471. package/dist/src/templates/document-model/gen/types.js.map +0 -1
  472. package/dist/src/templates/document-model/gen/utils.d.ts +0 -3
  473. package/dist/src/templates/document-model/gen/utils.d.ts.map +0 -1
  474. package/dist/src/templates/document-model/gen/utils.js +0 -77
  475. package/dist/src/templates/document-model/gen/utils.js.map +0 -1
  476. package/dist/src/templates/document-model/hooks.d.ts +0 -3
  477. package/dist/src/templates/document-model/hooks.d.ts.map +0 -1
  478. package/dist/src/templates/document-model/hooks.js +0 -52
  479. package/dist/src/templates/document-model/hooks.js.map +0 -1
  480. package/dist/src/templates/document-model/index.d.ts +0 -2
  481. package/dist/src/templates/document-model/index.d.ts.map +0 -1
  482. package/dist/src/templates/document-model/index.js +0 -9
  483. package/dist/src/templates/document-model/index.js.map +0 -1
  484. package/dist/src/templates/document-model/module.d.ts +0 -9
  485. package/dist/src/templates/document-model/module.d.ts.map +0 -1
  486. package/dist/src/templates/document-model/module.js +0 -26
  487. package/dist/src/templates/document-model/module.js.map +0 -1
  488. package/dist/src/templates/document-model/src/index.d.ts +0 -2
  489. package/dist/src/templates/document-model/src/index.d.ts.map +0 -1
  490. package/dist/src/templates/document-model/src/index.js +0 -5
  491. package/dist/src/templates/document-model/src/index.js.map +0 -1
  492. package/dist/src/templates/document-model/src/tests/document-model.test.d.ts +0 -3
  493. package/dist/src/templates/document-model/src/tests/document-model.test.d.ts.map +0 -1
  494. package/dist/src/templates/document-model/src/tests/document-model.test.js +0 -121
  495. package/dist/src/templates/document-model/src/tests/document-model.test.js.map +0 -1
  496. package/dist/src/templates/document-model/src/tests/module.test.d.ts +0 -6
  497. package/dist/src/templates/document-model/src/tests/module.test.d.ts.map +0 -1
  498. package/dist/src/templates/document-model/src/tests/module.test.js +0 -87
  499. package/dist/src/templates/document-model/src/tests/module.test.js.map +0 -1
  500. package/dist/src/templates/document-model/src/utils.d.ts +0 -2
  501. package/dist/src/templates/document-model/src/utils.d.ts.map +0 -1
  502. package/dist/src/templates/document-model/src/utils.js +0 -5
  503. package/dist/src/templates/document-model/src/utils.js.map +0 -1
  504. package/dist/src/templates/document-model/upgrades/upgrade-transition.d.ts +0 -7
  505. package/dist/src/templates/document-model/upgrades/upgrade-transition.d.ts.map +0 -1
  506. package/dist/src/templates/document-model/upgrades/upgrade-transition.js +0 -22
  507. package/dist/src/templates/document-model/upgrades/upgrade-transition.js.map +0 -1
  508. package/dist/src/templates/document-model/utils.d.ts +0 -3
  509. package/dist/src/templates/document-model/utils.d.ts.map +0 -1
  510. package/dist/src/templates/document-model/utils.js +0 -11
  511. package/dist/src/templates/document-model/utils.js.map +0 -1
  512. package/dist/src/templates/drive-editor/components/CreateDocument.d.ts +0 -2
  513. package/dist/src/templates/drive-editor/components/CreateDocument.d.ts.map +0 -1
  514. package/dist/src/templates/drive-editor/components/CreateDocument.js +0 -58
  515. package/dist/src/templates/drive-editor/components/CreateDocument.js.map +0 -1
  516. package/dist/src/templates/drive-editor/components/DriveContents.d.ts +0 -2
  517. package/dist/src/templates/drive-editor/components/DriveContents.d.ts.map +0 -1
  518. package/dist/src/templates/drive-editor/components/DriveContents.js +0 -24
  519. package/dist/src/templates/drive-editor/components/DriveContents.js.map +0 -1
  520. package/dist/src/templates/drive-editor/components/DriveExplorer.d.ts +0 -2
  521. package/dist/src/templates/drive-editor/components/DriveExplorer.d.ts.map +0 -1
  522. package/dist/src/templates/drive-editor/components/DriveExplorer.js +0 -32
  523. package/dist/src/templates/drive-editor/components/DriveExplorer.js.map +0 -1
  524. package/dist/src/templates/drive-editor/components/EmptyState.d.ts +0 -2
  525. package/dist/src/templates/drive-editor/components/EmptyState.d.ts.map +0 -1
  526. package/dist/src/templates/drive-editor/components/EmptyState.js +0 -19
  527. package/dist/src/templates/drive-editor/components/EmptyState.js.map +0 -1
  528. package/dist/src/templates/drive-editor/components/Files.d.ts +0 -2
  529. package/dist/src/templates/drive-editor/components/Files.d.ts.map +0 -1
  530. package/dist/src/templates/drive-editor/components/Files.js +0 -30
  531. package/dist/src/templates/drive-editor/components/Files.js.map +0 -1
  532. package/dist/src/templates/drive-editor/components/FolderTree.d.ts +0 -2
  533. package/dist/src/templates/drive-editor/components/FolderTree.d.ts.map +0 -1
  534. package/dist/src/templates/drive-editor/components/FolderTree.js +0 -108
  535. package/dist/src/templates/drive-editor/components/FolderTree.js.map +0 -1
  536. package/dist/src/templates/drive-editor/components/Folders.d.ts +0 -2
  537. package/dist/src/templates/drive-editor/components/Folders.d.ts.map +0 -1
  538. package/dist/src/templates/drive-editor/components/Folders.js +0 -28
  539. package/dist/src/templates/drive-editor/components/Folders.js.map +0 -1
  540. package/dist/src/templates/drive-editor/components/NavigationBreadcrumbs.d.ts +0 -2
  541. package/dist/src/templates/drive-editor/components/NavigationBreadcrumbs.d.ts.map +0 -1
  542. package/dist/src/templates/drive-editor/components/NavigationBreadcrumbs.js +0 -14
  543. package/dist/src/templates/drive-editor/components/NavigationBreadcrumbs.js.map +0 -1
  544. package/dist/src/templates/drive-editor/config.d.ts +0 -5
  545. package/dist/src/templates/drive-editor/config.d.ts.map +0 -1
  546. package/dist/src/templates/drive-editor/config.js +0 -11
  547. package/dist/src/templates/drive-editor/config.js.map +0 -1
  548. package/dist/src/templates/drive-editor/editor.d.ts +0 -2
  549. package/dist/src/templates/drive-editor/editor.d.ts.map +0 -1
  550. package/dist/src/templates/drive-editor/editor.js +0 -20
  551. package/dist/src/templates/drive-editor/editor.js.map +0 -1
  552. package/dist/src/templates/index.d.ts +0 -65
  553. package/dist/src/templates/index.d.ts.map +0 -1
  554. package/dist/src/templates/index.js +0 -65
  555. package/dist/src/templates/index.js.map +0 -1
  556. package/dist/src/ts-morph-generator/__tests__/ReducerGenerator.test.d.ts +0 -2
  557. package/dist/src/ts-morph-generator/__tests__/ReducerGenerator.test.d.ts.map +0 -1
  558. package/dist/src/ts-morph-generator/__tests__/ReducerGenerator.test.js +0 -491
  559. package/dist/src/ts-morph-generator/__tests__/ReducerGenerator.test.js.map +0 -1
  560. package/dist/src/ts-morph-generator/core/FileGenerator.d.ts +0 -11
  561. package/dist/src/ts-morph-generator/core/FileGenerator.d.ts.map +0 -1
  562. package/dist/src/ts-morph-generator/core/FileGenerator.js +0 -11
  563. package/dist/src/ts-morph-generator/core/FileGenerator.js.map +0 -1
  564. package/dist/src/ts-morph-generator/core/GenerationContext.d.ts +0 -39
  565. package/dist/src/ts-morph-generator/core/GenerationContext.d.ts.map +0 -1
  566. package/dist/src/ts-morph-generator/core/GenerationContext.js +0 -2
  567. package/dist/src/ts-morph-generator/core/GenerationContext.js.map +0 -1
  568. package/dist/src/ts-morph-generator/core/ReducerGenerator.d.ts +0 -12
  569. package/dist/src/ts-morph-generator/core/ReducerGenerator.d.ts.map +0 -1
  570. package/dist/src/ts-morph-generator/core/ReducerGenerator.js +0 -147
  571. package/dist/src/ts-morph-generator/core/ReducerGenerator.js.map +0 -1
  572. package/dist/src/ts-morph-generator/core/TSMorphCodeGenerator.d.ts +0 -20
  573. package/dist/src/ts-morph-generator/core/TSMorphCodeGenerator.d.ts.map +0 -1
  574. package/dist/src/ts-morph-generator/core/TSMorphCodeGenerator.js +0 -120
  575. package/dist/src/ts-morph-generator/core/TSMorphCodeGenerator.js.map +0 -1
  576. package/dist/src/ts-morph-generator/index.d.ts +0 -4
  577. package/dist/src/ts-morph-generator/index.d.ts.map +0 -1
  578. package/dist/src/ts-morph-generator/index.js +0 -4
  579. package/dist/src/ts-morph-generator/index.js.map +0 -1
  580. package/dist/src/ts-morph-generator/utilities/DeclarationManager.d.ts +0 -5
  581. package/dist/src/ts-morph-generator/utilities/DeclarationManager.d.ts.map +0 -1
  582. package/dist/src/ts-morph-generator/utilities/DeclarationManager.js +0 -10
  583. package/dist/src/ts-morph-generator/utilities/DeclarationManager.js.map +0 -1
  584. package/dist/src/ts-morph-generator/utilities/DirectoryManager.d.ts +0 -13
  585. package/dist/src/ts-morph-generator/utilities/DirectoryManager.d.ts.map +0 -1
  586. package/dist/src/ts-morph-generator/utilities/DirectoryManager.js +0 -45
  587. package/dist/src/ts-morph-generator/utilities/DirectoryManager.js.map +0 -1
  588. package/dist/src/ts-morph-generator/utilities/ImportManager.d.ts +0 -15
  589. package/dist/src/ts-morph-generator/utilities/ImportManager.d.ts.map +0 -1
  590. package/dist/src/ts-morph-generator/utilities/ImportManager.js +0 -50
  591. package/dist/src/ts-morph-generator/utilities/ImportManager.js.map +0 -1
  592. package/dist/src/ts-morph-generator/utilities/index.d.ts +0 -4
  593. package/dist/src/ts-morph-generator/utilities/index.d.ts.map +0 -1
  594. package/dist/src/ts-morph-generator/utilities/index.js +0 -4
  595. package/dist/src/ts-morph-generator/utilities/index.js.map +0 -1
  596. package/dist/src/utils/cli.d.ts +0 -26
  597. package/dist/src/utils/cli.d.ts.map +0 -1
  598. package/dist/src/utils/cli.js +0 -57
  599. package/dist/src/utils/cli.js.map +0 -1
  600. package/dist/src/utils/constants.d.ts +0 -13
  601. package/dist/src/utils/constants.d.ts.map +0 -1
  602. package/dist/src/utils/constants.js +0 -29
  603. package/dist/src/utils/constants.js.map +0 -1
  604. package/dist/src/utils/dependencies.d.ts +0 -12
  605. package/dist/src/utils/dependencies.d.ts.map +0 -1
  606. package/dist/src/utils/dependencies.js +0 -34
  607. package/dist/src/utils/dependencies.js.map +0 -1
  608. package/dist/src/utils/document-type-metadata.d.ts +0 -15
  609. package/dist/src/utils/document-type-metadata.d.ts.map +0 -1
  610. package/dist/src/utils/document-type-metadata.js +0 -67
  611. package/dist/src/utils/document-type-metadata.js.map +0 -1
  612. package/dist/src/utils/format-with-prettier.d.ts +0 -5
  613. package/dist/src/utils/format-with-prettier.d.ts.map +0 -1
  614. package/dist/src/utils/format-with-prettier.js +0 -20
  615. package/dist/src/utils/format-with-prettier.js.map +0 -1
  616. package/dist/src/utils/index.d.ts +0 -14
  617. package/dist/src/utils/index.d.ts.map +0 -1
  618. package/dist/src/utils/index.js +0 -14
  619. package/dist/src/utils/index.js.map +0 -1
  620. package/dist/src/utils/mock.d.ts +0 -3
  621. package/dist/src/utils/mock.d.ts.map +0 -1
  622. package/dist/src/utils/mock.js +0 -5
  623. package/dist/src/utils/mock.js.map +0 -1
  624. package/dist/src/utils/source-files.d.ts +0 -18
  625. package/dist/src/utils/source-files.d.ts.map +0 -1
  626. package/dist/src/utils/source-files.js +0 -39
  627. package/dist/src/utils/source-files.js.map +0 -1
  628. package/dist/src/utils/spawn-async.d.ts +0 -5
  629. package/dist/src/utils/spawn-async.d.ts.map +0 -1
  630. package/dist/src/utils/spawn-async.js +0 -29
  631. package/dist/src/utils/spawn-async.js.map +0 -1
  632. package/dist/src/utils/syntax-builders.d.ts +0 -8
  633. package/dist/src/utils/syntax-builders.d.ts.map +0 -1
  634. package/dist/src/utils/syntax-builders.js +0 -72
  635. package/dist/src/utils/syntax-builders.js.map +0 -1
  636. package/dist/src/utils/syntax-getters.d.ts +0 -9
  637. package/dist/src/utils/syntax-getters.d.ts.map +0 -1
  638. package/dist/src/utils/syntax-getters.js +0 -20
  639. package/dist/src/utils/syntax-getters.js.map +0 -1
  640. package/dist/src/utils/ts-morph-project.d.ts +0 -15
  641. package/dist/src/utils/ts-morph-project.d.ts.map +0 -1
  642. package/dist/src/utils/ts-morph-project.js +0 -28
  643. package/dist/src/utils/ts-morph-project.js.map +0 -1
  644. package/dist/src/utils/unsafe-utils.d.ts +0 -8
  645. package/dist/src/utils/unsafe-utils.d.ts.map +0 -1
  646. package/dist/src/utils/unsafe-utils.js +0 -23
  647. package/dist/src/utils/unsafe-utils.js.map +0 -1
  648. package/dist/src/utils/validation.d.ts +0 -18
  649. package/dist/src/utils/validation.d.ts.map +0 -1
  650. package/dist/src/utils/validation.js +0 -138
  651. package/dist/src/utils/validation.js.map +0 -1
  652. package/dist/tsconfig.tsbuildinfo +0 -1
  653. package/dist/vitest.config.d.ts +0 -3
  654. package/dist/vitest.config.d.ts.map +0 -1
  655. package/dist/vitest.config.js +0 -19
  656. package/dist/vitest.config.js.map +0 -1
@@ -0,0 +1,4613 @@
1
+ import { getActionInputName, getActionInputTypeNames, getActionType, getActionTypeName } from "./src/name-builders/index.mjs";
2
+ import { camelCase, capitalCase, constantCase, kebabCase, pascalCase } from "change-case";
3
+ import { css, html, js, json, md, ts, tsx, yaml } from "@tmpl/core";
4
+ //#region src/templates/app/components/CreateDocument.ts
5
+ const createDocumentFileTemplate = tsx`
6
+ import type { DocumentModelModule } from "document-model";
7
+ import {
8
+ showCreateDocumentModal,
9
+ useAllowedDocumentModelModules,
10
+ } from "@powerhousedao/reactor-browser";
11
+
12
+ /**
13
+ * Document creation UI component.
14
+ * Displays available document types as clickable buttons.
15
+ */
16
+ export function CreateDocument() {
17
+ const allowedDocumentModelModules = useAllowedDocumentModelModules();
18
+
19
+ return (
20
+ <div>
21
+ {/* Customize section title here */}
22
+ <h3 className="mb-3 mt-4 text-sm font-bold text-gray-600">
23
+ Create document
24
+ </h3>
25
+ {/* Customize layout by changing flex-wrap, gap, or grid layout */}
26
+ <div className="flex w-full flex-wrap gap-4">
27
+ {allowedDocumentModelModules?.map((documentModelModule) => {
28
+ return (
29
+ <CreateDocumentButton
30
+ key={documentModelModule.documentModel.global.id}
31
+ documentModelModule={documentModelModule}
32
+ />
33
+ );
34
+ })}
35
+ </div>
36
+ </div>
37
+ );
38
+ }
39
+
40
+ type Props = {
41
+ documentModelModule: DocumentModelModule;
42
+ };
43
+ function CreateDocumentButton({ documentModelModule }: Props) {
44
+ const documentType = documentModelModule.documentModel.global.id;
45
+ const documentModelName =
46
+ documentModelModule.documentModel.global.name || documentType;
47
+ const documentModelDescription =
48
+ documentModelModule.documentModel.global.description;
49
+ return (
50
+ <button
51
+ className="cursor-pointer rounded-md bg-gray-200 py-2 px-3 hover:bg-gray-300"
52
+ title={documentModelName}
53
+ aria-description={documentModelDescription}
54
+ onClick={() => showCreateDocumentModal(documentType)}
55
+ >
56
+ {documentModelName}
57
+ </button>
58
+ );
59
+ }
60
+ `.raw;
61
+ //#endregion
62
+ //#region src/templates/app/components/DriveContents.ts
63
+ const appDriveContentsFileTemplate = () => tsx`
64
+ import { CreateDocument } from "./CreateDocument.js";
65
+ import { EmptyState } from "./EmptyState.js";
66
+ import { Files } from "./Files.js";
67
+ import { Folders } from "./Folders.js";
68
+ import { NavigationBreadcrumbs } from "./NavigationBreadcrumbs.js";
69
+
70
+ /** Shows the documents and folders in the selected drive */
71
+ export function DriveContents() {
72
+ return (
73
+ <div className="space-y-6 px-6">
74
+ <NavigationBreadcrumbs />
75
+ <Folders />
76
+ <Files />
77
+ <EmptyState />
78
+ <CreateDocument />
79
+ </div>
80
+ );
81
+ }
82
+
83
+
84
+ `.raw;
85
+ //#endregion
86
+ //#region src/templates/app/components/DriveExplorer.ts
87
+ const driveExplorerFileTemplate = tsx`
88
+ import type { EditorProps } from "document-model";
89
+ import { FolderTree } from "./FolderTree.js";
90
+ import { DriveContents } from "./DriveContents.js";
91
+
92
+ /**
93
+ * Main drive explorer component with sidebar navigation and content area.
94
+ * Layout: Left sidebar (folder tree) + Right content area (files/folders + document editor)
95
+ */
96
+ export function DriveExplorer({ children }: EditorProps) {
97
+ // if a document is selected then it's editor will be passed as children
98
+ const showDocumentEditor = !!children;
99
+
100
+ return (
101
+ <div className="flex h-full">
102
+ <FolderTree />
103
+ <div className="flex-1 overflow-y-auto p-4">
104
+ {/* Conditional rendering: Document editor or folder contents */}
105
+ {showDocumentEditor ? (
106
+ /* Document editor view */
107
+ children
108
+ ) : (
109
+ /* Folder contents view */
110
+ <DriveContents />
111
+ )}
112
+ </div>
113
+ </div>
114
+ );
115
+ }
116
+ `.raw;
117
+ //#endregion
118
+ //#region src/templates/app/components/EmptyState.ts
119
+ const emptyStateFileTemplate = tsx`
120
+ import { useNodesInSelectedDriveOrFolder } from "@powerhousedao/reactor-browser";
121
+
122
+ /** Shows a message when the selected drive or folder is empty */
123
+ export function EmptyState() {
124
+ const nodes = useNodesInSelectedDriveOrFolder();
125
+ const hasNodes = nodes.length > 0;
126
+ if (hasNodes) return null;
127
+
128
+ return (
129
+ <div className="py-12 text-center text-gray-500">
130
+ <p className="text-lg">This folder is empty</p>
131
+ <p className="mt-2 text-sm">Create your first document or folder below</p>
132
+ </div>
133
+ );
134
+ }
135
+ `.raw;
136
+ //#endregion
137
+ //#region src/templates/app/components/Files.ts
138
+ const appFilesFileTemplate = () => tsx`
139
+ import { FileItem } from "@powerhousedao/design-system/connect";
140
+ import {
141
+ useNodesInSelectedDriveOrFolder,
142
+ isFileNodeKind,
143
+ } from "@powerhousedao/reactor-browser";
144
+
145
+ /** Shows the files in the selected drive or folder */
146
+ export function Files() {
147
+ const nodes = useNodesInSelectedDriveOrFolder();
148
+ const fileNodes = nodes.filter((n) => isFileNodeKind(n));
149
+ const hasFiles = fileNodes.length > 0;
150
+
151
+ if (!hasFiles) return null;
152
+
153
+ return (
154
+ <div>
155
+ <h3 className="mb-2 text-sm font-semibold text-gray-600">Documents</h3>
156
+ <div className="flex flex-wrap gap-4">
157
+ {fileNodes.map((fileNode) => (
158
+ <FileItem key={fileNode.id} fileNode={fileNode} />
159
+ ))}
160
+ </div>
161
+ </div>
162
+ );
163
+ }
164
+
165
+ `.raw;
166
+ //#endregion
167
+ //#region src/templates/app/components/Folders.ts
168
+ const appFoldersFileTemplate = () => tsx`
169
+ import { FolderItem } from "@powerhousedao/design-system/connect";
170
+ import {
171
+ useNodesInSelectedDriveOrFolder,
172
+ isFolderNodeKind,
173
+ } from "@powerhousedao/reactor-browser";
174
+
175
+ /** Shows the folders in the selected drive or folder */
176
+ export function Folders() {
177
+ const nodes = useNodesInSelectedDriveOrFolder();
178
+ const folderNodes = nodes.filter((n) => isFolderNodeKind(n));
179
+ const hasFolders = folderNodes.length > 0;
180
+ if (!hasFolders) return null;
181
+
182
+ return (
183
+ <div>
184
+ <h3 className="mb-2 text-sm font-bold text-gray-600">Folders</h3>
185
+ <div className="flex flex-wrap gap-4">
186
+ {folderNodes.map((folderNode) => (
187
+ <FolderItem key={folderNode.id} folderNode={folderNode} />
188
+ ))}
189
+ </div>
190
+ </div>
191
+ );
192
+ }
193
+ `.raw;
194
+ //#endregion
195
+ //#region src/templates/app/components/FolderTree.ts
196
+ const folderTreeFileTemplate = tsx`
197
+ import {
198
+ Sidebar,
199
+ SidebarProvider,
200
+ type SidebarNode,
201
+ } from "@powerhousedao/document-engineering";
202
+ import {
203
+ setSelectedNode,
204
+ useNodesInSelectedDrive,
205
+ useSelectedDrive,
206
+ useSelectedNode,
207
+ } from "@powerhousedao/reactor-browser";
208
+ import type { Node } from "@powerhousedao/shared/document-drive";
209
+ import { useMemo } from "react";
210
+
211
+ function buildSidebarNodes(
212
+ nodes: Node[],
213
+ parentId: string | null | undefined,
214
+ ): SidebarNode[] {
215
+ return nodes
216
+ .filter((n) => {
217
+ if (parentId == null) {
218
+ return n.parentFolder == null;
219
+ }
220
+ return n.parentFolder === parentId;
221
+ })
222
+ .map((node): SidebarNode => {
223
+ if (node.kind === "folder") {
224
+ return {
225
+ id: node.id,
226
+ title: node.name,
227
+ icon: "FolderClose" as const,
228
+ expandedIcon: "FolderOpen" as const,
229
+ children: buildSidebarNodes(nodes, node.id),
230
+ };
231
+ }
232
+ return {
233
+ id: node.id,
234
+ title: node.name,
235
+ icon: "File" as const,
236
+ };
237
+ });
238
+ }
239
+
240
+ function transformNodesToSidebarNodes(
241
+ nodes: Node[],
242
+ driveName: string,
243
+ ): SidebarNode[] {
244
+ return [
245
+ {
246
+ id: "root",
247
+ title: driveName,
248
+ icon: "Drive" as const,
249
+ children: buildSidebarNodes(nodes, null),
250
+ },
251
+ ];
252
+ }
253
+
254
+ /**
255
+ * Hierarchical folder tree navigation component using Sidebar from document-engineering.
256
+ * Displays folders and files in a tree structure with expand/collapse functionality, search, and resize support.
257
+ */
258
+ export function FolderTree() {
259
+ const [selectedDrive] = useSelectedDrive();
260
+ const nodes = useNodesInSelectedDrive();
261
+ const selectedNode = useSelectedNode();
262
+ const driveName = selectedDrive.header.name;
263
+ // Transform Node[] to hierarchical SidebarNode structure
264
+ const sidebarNodes = useMemo(
265
+ () => transformNodesToSidebarNodes(nodes || [], driveName),
266
+ [nodes, driveName],
267
+ );
268
+
269
+ const handleActiveNodeChange = (node: SidebarNode) => {
270
+ // If root node is selected, pass undefined to match existing behavior
271
+ if (node.id === "root") {
272
+ setSelectedNode(undefined);
273
+ } else {
274
+ setSelectedNode(node.id);
275
+ }
276
+ };
277
+ // Map selectedNodeId to activeNodeId (use "root" when undefined)
278
+ const activeNodeId =
279
+ !selectedNode || selectedNode.id === selectedDrive.header.id
280
+ ? "root"
281
+ : selectedNode.id;
282
+
283
+ return (
284
+ <SidebarProvider nodes={sidebarNodes}>
285
+ <Sidebar
286
+ className="pt-1"
287
+ nodes={sidebarNodes}
288
+ activeNodeId={activeNodeId}
289
+ onActiveNodeChange={handleActiveNodeChange}
290
+ sidebarTitle="Drive Explorer"
291
+ showSearchBar={true}
292
+ resizable={true}
293
+ allowPinning={false}
294
+ showStatusFilter={false}
295
+ initialWidth={256}
296
+ defaultLevel={2}
297
+ />
298
+ </SidebarProvider>
299
+ );
300
+ }
301
+ `.raw;
302
+ //#endregion
303
+ //#region src/templates/app/components/NavigationBreadcrumbs.ts
304
+ const driveExplorerNavigationBreadcrumbsFileTemplate = () => tsx`
305
+ import { Breadcrumbs } from "@powerhousedao/design-system/connect";
306
+
307
+ /** Shows the navigation breadcrumbs for the selected drive or folder */
308
+ export function NavigationBreadcrumbs() {
309
+ return (
310
+ <div className="border-b border-gray-200 pb-3 space-y-3">
311
+ <Breadcrumbs />
312
+ </div>
313
+ );
314
+ }
315
+ `.raw;
316
+ //#endregion
317
+ //#region src/templates/app/config.ts
318
+ const appConfigFileTemplate = (v) => ts`
319
+ import type { PHAppConfig } from "@powerhousedao/reactor-browser";
320
+
321
+ /** Editor config for the <%= pascalCaseAppName %> */
322
+ export const editorConfig: PHAppConfig = {
323
+ isDragAndDropEnabled: ${v.isDragAndDropEnabledString},
324
+ allowedDocumentTypes: ${v.allowedDocumentTypesString}
325
+ };
326
+ `.raw;
327
+ //#endregion
328
+ //#region src/templates/app/editor.ts
329
+ const appEditorFileTemplate = () => tsx`
330
+ import { useSetPHAppConfig } from "@powerhousedao/reactor-browser";
331
+ import type { EditorProps } from "document-model";
332
+ import { DriveExplorer } from "./components/DriveExplorer.js";
333
+ import { editorConfig } from "./config.js";
334
+
335
+ /** Editor component for the app */
336
+ export default function Editor(props: EditorProps) {
337
+ // set the config for this app
338
+ // you can update these configs in \`./config.ts\`
339
+ useSetPHAppConfig(editorConfig);
340
+ return (
341
+ <div className="bg-gray-50 p-6">
342
+ <DriveExplorer {...props} />
343
+ </div>
344
+ );
345
+ }
346
+ `.raw;
347
+ //#endregion
348
+ //#region src/templates/boilerplate/AGENTS.md.ts
349
+ const agentsTemplate = md`
350
+ # Powerhouse Document Models Assistant
351
+
352
+ This project creates document models, editors, processors and subgraphs for the Powerhouse ecosystem. Your role is to help users create these modules based on their needs.
353
+
354
+ ## Core Concepts
355
+
356
+ - **Document Model**: A template for creating documents. Defines schema and allowed operations for a document type.
357
+ - **Document**: An instance of a document model containing actual data that follows the model's structure and can be modified using operations.
358
+ - **Drive**: A document of type "powerhouse/document-drive" representing a collection of documents and folders. Add documents using "addActions" with "ADD_FILE" action.
359
+ - **Action**: A proposed change to a document (JSON object with action name and input). Dispatch using "addActions" tool.
360
+ - **Operation**: A completed change to a document containing the action plus metadata (index, timestamp, hash, errors). Actions become operations after dispatch.
361
+
362
+ ## Technology Primer
363
+
364
+ - **Reactor**: The core Powerhouse engine. It is modular and storage-agnostic, loads document models at runtime, and synchronizes documents across nodes via drives.
365
+ - **Reactor Package**: A deployable bundle that extends the Reactor. It contains one or more document models, editors, processors, and subgraphs. A Vetra project generates a Reactor Package.
366
+ - **Connect**: The Powerhouse web application for document management. End users open Connect to browse drives, create documents, and interact with editors.
367
+ - **Switchboard**: The Powerhouse API service. It exposes GraphQL and MCP endpoints so external tools can read/write documents programmatically.
368
+ - **Vetra**: The local development environment for building Reactor Packages. It includes Vetra Studio (a local Connect instance) and Vetra Switchboard (a local Switchboard with reactor-mcp). Start it with \`ph vetra\`.
369
+
370
+ ## CRITICAL: MCP Tool Usage Rules
371
+
372
+ **MANDATORY**: The \`reactor-mcp\` MUST BE USED when handling documents or document-models for the Powerhouse/Vetra ecosystem.
373
+ If the \`reactor-mcp\` server is unavailable, ask the user to run \`ph vetra\` on a separate terminal to start the server and try to reconnect to the MCP server, DO NOT run it yourself.
374
+
375
+ ### Key Requirements:
376
+
377
+ - Never set document IDs manually - they're auto-generated by 'createDocument'
378
+ - Minimize "addActions" calls by batching multiple actions together
379
+ - Add new document model documents to "vetra-{hash}" drive unless specified otherwise
380
+ - Always check document model schema before calling addActions
381
+ - Use MCP tools for ALL document and document-model operations
382
+
383
+ ## Document Model Creation Workflow
384
+
385
+ ### 1. Planning Phase
386
+
387
+ **MANDATORY**: Present your proposal to the user and ask for confirmation before implementing ANY document model.
388
+
389
+ - **ALWAYS** describe the proposed document model structure (state schema, operations, modules) before creating
390
+ - **NEVER** proceed with implementation without explicit user approval of your proposal
391
+ - When in doubt, ask for clarification
392
+ - Break complex models into logical modules and operations
393
+
394
+ #### Document Type ID Format
395
+
396
+ - **Type ID**: \`{organization}/{document-type-name}\` (e.g., \`pizza-plaza/order\`, \`acme/invoice\`)
397
+ - **File extension**: 2-4 characters with leading dot (e.g., \`.ordr\`, \`.inv\`)
398
+ - **Name**: Must match \`/[a-zA-Z][a-zA-Z0-9 ]*/\` — human-readable, capitalized (e.g., \`"Order"\`, \`"Invoice"\`)
399
+
400
+ ### 2. Pre-Implementation Requirements
401
+
402
+ **MANDATORY**: Check document model schema before making any MCP tool calls.
403
+
404
+ - **ALWAYS** use \`mcp__reactor-mcp__getDocumentModelSchema\` with \`type: "powerhouse/document-model"\` first
405
+ - Review input schema requirements for operations like \`ADD_MODULE\`, \`ADD_OPERATION\`, etc.
406
+ - Ensure all required parameters (like \`id\` or \`scope\` fields) are included in action inputs
407
+ - This prevents failed tool calls and reduces iteration
408
+
409
+ ### 3. Implementation Requirements
410
+
411
+ - Document model reducers must be **pure synchronous functions**
412
+ - Reducers receive current state and operation, always returning the same result
413
+ - Values like dates/IDs must come from operation input, not generated in reducer
414
+ - Reducer code goes into SET_OPERATION_REDUCER action (no function header needed)
415
+ - Reducers are wrapped with Mutative - you can mutate the state object directly
416
+ - External imports go at the beginning of the actual reducer file in \`src/\`
417
+ - Ensure that the reducer code of each operation in the document model schema is applied in \`document-models/<document-model-name>/src/reducers/<module-name>.ts\`
418
+
419
+ ### 4. Quality assurance
420
+
421
+ After doing changes to the code, or after creating a new document model or a new editor, _YOU MUST RUN_ the following commands to check for errors in your implementation:
422
+
423
+ - **TypeScript Check**: Run \`npm run tsc\` to validate type safety
424
+ - **ESLint Check**: Run \`npm run lint:fix\` to check for errors with ESLint
425
+
426
+ ## Document editor creation flow
427
+
428
+ **CRITICAL**: Creating a document editor is a **two-phase** process. You must NEVER skip Phase 1 or try to manually create editor files from scratch. The codegen system generates the boilerplate — your job is only to implement the UI inside it.
429
+
430
+ ### Phase 1: Create the editor document via MCP (MANDATORY FIRST STEP)
431
+
432
+ **NEVER** start by writing editor code, creating component files, or looking at how to scaffold an editor manually. The **only** way to create a new editor is through the MCP tools:
433
+
434
+ 1. Check if the document editor already exists. If it does, ask the user if a new one should be created or if the existing one should be reimplemented
435
+ 2. If it's a new editor, get the document editor schema using \`mcp__reactor-mcp__getDocumentModelSchema\` with \`type: "powerhouse/document-editor"\`
436
+ 3. Create a new editor document on the \`vetra-{hash}\` drive of type \`powerhouse/document-editor\` using \`mcp__reactor-mcp__addActions\` with the \`ADD_FILE\` action
437
+ 4. Configure the editor document with the required actions (set the editor name, target document model, etc.) according to the schema
438
+
439
+ ⚠️ **The editor document MUST be confirmed/published — if it is left as draft state, the codegen will NOT run and no editor files will be generated.** Make sure the document state is not "DRAFT" after creation.
440
+
441
+ 5. Once the editor document is confirmed on the drive, the codegen automatically runs and generates boilerplate files in the \`editors/\` folder, including hooks, type definitions, and the editor component shell
442
+
443
+ ### Phase 2: Implement the editor UI
444
+
445
+ Only **after** the codegen has produced the boilerplate files, proceed with the UI implementation:
446
+
447
+ - Inspect the generated files in the \`editors/\` folder — do NOT create new files for the main editor component; edit the generated one
448
+ - Inspect the hooks in \`editors/hooks\` as they should be useful
449
+ - Read the schema of the document model that the editor is for to know how to interact with it
450
+ - Every editor **MUST** include \`<DocumentToolbar />\` imported from \`@powerhousedao/design-system/connect/index\`. Place it at the top of the editor component — do not put anything next to it.
451
+ - Style the editor using tailwind classes or a style tag. If using a style tag, make sure to make the selectors specific to only apply to the editor component.
452
+ - Create modular components for the UI elements and place them on separate files to make it easier to maintain and update
453
+ - Consider using the React Components exported by \`@powerhousedao/design-system\` and \`@powerhousedao/document-engineering\`
454
+ - Separate business logic from presentation logic
455
+ - Use TypeScript for type safety, avoid using any and type casting
456
+ - Always check for type and lint errors after creating or modifying the editor
457
+ - **CRITICAL**: After creating a new editor, verify that \`editors/editors.ts\` includes the new editor module. The codegen should update this file automatically, but if it doesn't, manually add the import and include the editor in the \`editors\` array. Without this registration, Connect won't find an editor for the document type. Example:
458
+
459
+ ~~~typescript
460
+ import type { EditorModule } from "document-model";
461
+ import { TodoListEditor } from "./todo-list-editor/module.js";
462
+
463
+ export const editors: EditorModule[] = [TodoListEditor];
464
+ ~~~
465
+
466
+ ### Document Editor Implementation Pattern
467
+
468
+ **CRITICAL**: When implementing document editors, use the modern React hooks pattern from \`@powerhousedao/reactor-browser\`.
469
+
470
+ The following section is valid for editors that edit a single document type.
471
+
472
+ #### Required Imports and Setup
473
+
474
+ Using a "Todo" document model as example:
475
+
476
+ ~~~typescript
477
+ import { generateId } from "document-model";
478
+ import { useSelectedTodoDocument } from "../hooks/useTodoDocument.js";
479
+ import {
480
+ addTodo,
481
+ } from "../../document-models/todo/gen/creators.js";
482
+
483
+ export default function Editor() {
484
+ const [document, dispatch] = useSelectedTodoDocument();
485
+
486
+ function handleAddTodo(values: { title: string }) {
487
+ if (values.title) {
488
+ dispatch(addTodo({ id: generateId(), title: values.title }));
489
+ }
490
+ };
491
+
492
+ // Note: The \`useSelectedTodoDocument\` hook is auto-generated. Check the \`editors/hooks\` folder for the exact hook name.
493
+ // Action creators like \`addTodo\` are exported from the document model's \`gen/creators.js\` file.
494
+ ~~~
495
+
496
+ The \`useSelectedTodoDocument\` gets generated automatically so you don't need to implement it yourself.
497
+
498
+ ## ⚠️ CRITICAL: Generated Files & Modification Rules
499
+
500
+ ### Generated Files Rule
501
+
502
+ **NEVER edit files in \`gen/\` folders** - they are auto-generated and will be overwritten.
503
+
504
+ ### Document Model Modification Process
505
+
506
+ For ANY document model changes, follow this **mandatory** two-step process:
507
+
508
+ #### Step 1: Update Document Model via MCP
509
+
510
+ Use \`mcp__reactor-mcp__addActions\` with operations like:
511
+
512
+ - \`SET_OPERATION_SCHEMA\` - update input/output schemas
513
+ - \`SET_OPERATION_REDUCER\` - update reducer code
514
+ - \`SET_STATE_SCHEMA\` - update state definitions
515
+
516
+ #### Step 2: Update Existing Source Files
517
+
518
+ **ALSO manually update existing reducer files in \`src/\` folder** - these are NOT auto-generated.
519
+ Make sure to check if the operation reducer code needs to be updated after changing the state schema.
520
+
521
+ ### ⚠️ Critical Reminder
522
+
523
+ **ALWAYS do BOTH steps when fixing reducer issues:**
524
+
525
+ 1. ✅ Fix existing reducer files in \`src/\` manually
526
+ 2. ✅ Update document model via MCP with same fixes
527
+
528
+ **Forgetting step 2 means future code generations will still contain the bugs!**
529
+
530
+ ## Reducer Implementation Guidelines
531
+
532
+ ### ❌ Forbidden in Reducers (Non-Deterministic)
533
+
534
+ - \`crypto.randomUUID()\`, \`Math.random()\`, \`Date.now()\`, \`new Date()\`
535
+ - External API calls or side effects
536
+ - Asynchronous functions
537
+ - Any non-deterministic functions
538
+
539
+ ### ❌ Forbidden Patterns
540
+
541
+ ~~~typescript
542
+ // NEVER use fallback values with non-deterministic functions
543
+ id: action.input.id || crypto.randomUUID(); // ❌ FORBIDDEN
544
+ timestamp: action.input.timestamp || new Date(); // ❌ FORBIDDEN
545
+ ~~~
546
+
547
+ ### ✅ Required Pattern
548
+
549
+ All dynamic values must come from action input:
550
+
551
+ - **IDs**: Include \`id: OID!\` in input schema, use \`action.input.id\` in reducer
552
+ - **Timestamps**: Include \`timestamp: DateTime!\` in input schema
553
+ - **Computed values**: Calculate before dispatching action
554
+
555
+ ### Example
556
+
557
+ ~~~typescript
558
+ // ❌ BAD - impure reducer
559
+ const newItem = {
560
+ id: crypto.randomUUID(), // Non-deterministic
561
+ createdAt: new Date(), // Non-deterministic
562
+ };
563
+
564
+ // ✅ GOOD - pure reducer
565
+ const newItem = {
566
+ id: action.input.id, // From action input
567
+ createdAt: action.input.createdAt, // From action input
568
+ };
569
+ ~~~
570
+
571
+ ### Handling Nullable Input Types
572
+
573
+ **CRITICAL**: Be careful when handling optional input types:
574
+
575
+ - Optional input types use \`InputMaybe<T>\` allowing \`null | undefined | T\`.
576
+ - Optional state types use \`Maybe<T>\` = \`T | null\`.
577
+ - If there is no applicable default value then use \`|| null\`.
578
+
579
+ ~~~typescript
580
+ // ❌ BAD - Type error with Maybe<string>
581
+ amount: action.input.amount,
582
+ notes: action.input.notes,
583
+
584
+ // ✅ GOOD - Matches Maybe<T> = T | null
585
+ amount: action.input.amount || null,
586
+ notes: action.input.notes || [],
587
+ ~~~
588
+
589
+ Use truthy checks when conditionally assigning optional values from input to state:
590
+
591
+ ~~~typescript
592
+ // ❌ BAD - Type 'string | null' is not assignable to type 'string'.
593
+ if (action.input.field !== undefined) entry.field = action.input.field;
594
+
595
+ // ✅ GOOD - use truthy checks
596
+ if (action.input.field) state.field = action.input.field;
597
+
598
+ // ✅ GOOD - For booleans use explicit null/undefined checks
599
+ if (action.input.field !== undefined && action.input.field !== null)
600
+ state.field = action.input.field;
601
+ ~~~
602
+
603
+ ### Error Handling in Operations
604
+
605
+ **MANDATORY**: Define specific error types for each operation to handle invalid inputs and edge cases properly.
606
+ Action inputs are validated so they are guaranteed to respect the input schema.
607
+ Errors referenced in the reducer code will be imported automatically.
608
+
609
+ #### Error Definition Requirements
610
+
611
+ 1. **Add error definitions** to operations using \`ADD_OPERATION_ERROR\`:
612
+ - \`errorCode\`: Uppercase snake_case (e.g., \`"MISSING_ID"\`, \`"ENTRY_NOT_FOUND"\`)
613
+ - \`errorName\`: PascalCase ending with "Error" (e.g., \`"MissingIdError"\`, \`"EntryNotFoundError"\`)
614
+ - \`errorDescription\`: Human-readable description of the error condition
615
+
616
+ 2. **Error names must end with "Error"** for consistency and code generation
617
+
618
+ 3. **Use specific error types** rather than generic validation
619
+
620
+ 4. **Must use unique error names and ids**
621
+
622
+ #### Error Usage in Reducers
623
+
624
+ ~~~typescript
625
+ // ✅ GOOD - Throw specific errors by name
626
+ if (!action.input.id) {
627
+ throw new MissingIdError("ID is required for operation");
628
+ }
629
+
630
+ if (entryIndex === -1) {
631
+ throw new EntryNotFoundError(\`Entry not found\`);
632
+ }
633
+
634
+ // ❌ BAD - Generic Error
635
+ throw new Error("Something went wrong");
636
+
637
+ // ❌ BAD - Nested error access
638
+ throw new errors.ModuleName.MissingIdError("message");
639
+
640
+ // ❌ BAD - Do not import error classes in the reducer code,
641
+ import { MissingIdError } from "../../gen/module-name/error.js";
642
+
643
+ // ✅ GOOD - Simply reference the error and it will be imported automatically
644
+ throw new MissingIdError("message");
645
+ ~~~
646
+
647
+ #### Common Error Patterns
648
+
649
+ - **EntityNotFoundError**: Referenced entity doesn't exist
650
+ - **DuplicateIdError**: ID already exists when creating new entries
651
+ - **InvalidInputError**: Business logic violations
652
+ - **PermissionDeniedError**: Access control violations
653
+
654
+ #### Testing Reducer Errors
655
+
656
+ **CRITICAL**: When a reducer throws an error, the operation is **still added** to the document but with an \`.error\` property containing the error message as a string.
657
+
658
+ **DO NOT** use \`.toThrow()\` or \`expect(() => ...).toThrow()\` patterns when testing reducer errors.
659
+
660
+ ##### How Errors Work in Operations
661
+
662
+ 1. The reducer throws an error (e.g., \`throw new InvalidNameError("message")\`)
663
+ 2. The operation is still recorded in \`document.operations.global\` (or \`.local\`)
664
+ 3. The error message is stored in \`operation.error\` as a string
665
+ 4. **The state is NOT mutated** - it remains unchanged from before the operation
666
+
667
+ ##### Accessing the Correct Operation Index
668
+
669
+ **CRITICAL**: You must access the correct operation index. The index corresponds to how many operations were dispatched before it.
670
+
671
+ - If this is the **first** operation dispatched, access \`[0]\`
672
+ - If 3 operations were dispatched **before** the failing one, access \`[3]\`
673
+
674
+ ##### Example
675
+
676
+ ~~~typescript
677
+ it("should return error and not mutate state", () => {
678
+ const document = utils.createDocument();
679
+ const initialState = document.state.global.name;
680
+
681
+ const updatedDocument = reducer(document, setName({ name: "invalid" }));
682
+
683
+ // Access the correct operation index (0 = first operation)
684
+ expect(updatedDocument.operations.global[0].error).toBe(
685
+ "Name is not allowed",
686
+ );
687
+ // State remains unchanged
688
+ expect(updatedDocument.state.global.name).toBe(initialState);
689
+ });
690
+
691
+ // ❌ WRONG - Never use toThrow()
692
+ expect(() => reducer(document, setName({ name: "invalid" }))).toThrow();
693
+ ~~~
694
+
695
+ ## Document Model Structure
696
+
697
+ ### Core Components
698
+
699
+ - **Basic Metadata**: \`id\`, \`name\`, \`extension\`, \`description\`, \`author\` (name + website)
700
+ - **Specifications**: Versioned specs with \`version\`, \`changeLog\`, \`state\` (global/local with schema, initialValue, examples)
701
+ - **Modules**: Operational modules containing their operations
702
+
703
+ ## Available Document Model Operations (37 total)
704
+
705
+ | Category | Operations | Count |
706
+ | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
707
+ | **Header Management** | \`SET_MODEL_NAME\`, \`SET_MODEL_ID\`, \`SET_MODEL_EXTENSION\`, \`SET_MODEL_DESCRIPTION\`, \`SET_AUTHOR_NAME\`, \`SET_AUTHOR_WEBSITE\` | 6 |
708
+ | **Versioning** | ⚠️ **DO NOT USE** - Not implemented | 0 |
709
+ | **Module Management** | \`ADD_MODULE\`, \`SET_MODULE_NAME\`, \`SET_MODULE_DESCRIPTION\`, \`DELETE_MODULE\`, \`REORDER_MODULES\` | 5 |
710
+ | **Operation Management** | \`ADD_OPERATION\`, \`SET_OPERATION_NAME\`, \`SET_OPERATION_SCHEMA\`, \`SET_OPERATION_DESCRIPTION\`, \`SET_OPERATION_TEMPLATE\`, \`SET_OPERATION_REDUCER\`, \`MOVE_OPERATION\`, \`DELETE_OPERATION\`, \`REORDER_MODULE_OPERATIONS\` | 9 |
711
+ | **Operation Error Management** | \`ADD_OPERATION_ERROR\`, \`SET_OPERATION_ERROR_CODE\`, \`SET_OPERATION_ERROR_NAME\`, \`SET_OPERATION_ERROR_DESCRIPTION\`, \`SET_OPERATION_ERROR_TEMPLATE\`, \`DELETE_OPERATION_ERROR\`, \`REORDER_OPERATION_ERRORS\` | 7 |
712
+ | **Operation Example Management** | \`ADD_OPERATION_EXAMPLE\`, \`UPDATE_OPERATION_EXAMPLE\`, \`DELETE_OPERATION_EXAMPLE\`, \`REORDER_OPERATION_EXAMPLES\` | 4 |
713
+ | **State Management** | \`SET_STATE_SCHEMA\`, \`SET_INITIAL_STATE\`, \`ADD_STATE_EXAMPLE\`, \`UPDATE_STATE_EXAMPLE\`, \`DELETE_STATE_EXAMPLE\`, \`REORDER_STATE_EXAMPLES\` | 6 |
714
+
715
+ ## Best Practices & Design Principles
716
+
717
+ ### Scope Selection
718
+
719
+ - **\`scope: "global"\`**: State shared among all users with document access
720
+ - **\`scope: "local"\`**: State private to each individual user
721
+
722
+ ### Operation Design
723
+
724
+ - Use descriptive operation names (e.g., \`ADD_LINE_ITEM\`, \`UPDATE_RECIPIENT\`)
725
+ - One operation per user intent (separate concerns)
726
+ - Include comprehensive examples and error definitions
727
+ - Organize related operations into logical modules
728
+
729
+ ## GraphQL Schema Guidelines
730
+
731
+ ### Document State Schema
732
+
733
+ - **Most fields optional** to support creating empty documents
734
+ - Use required fields \`!\` only when absolutely necessary
735
+ - Defaults handled by operations, not schema
736
+
737
+ #### Mandatory vs Optional Field Rules
738
+
739
+ A user must always be able to create an **empty document** without providing any information. This drives the following rules:
740
+
741
+ - **Root type properties** can only be mandatory (\`!\`) if they have a logical default value (e.g., empty array, enum initial status)
742
+ - **Collections** should always use \`[Type!]!\` — inner \`!\` means no nulls in the array, outer \`!\` means the array itself defaults to empty
743
+ - **Child object fields** can be mandatory only if all their required properties also have logical defaults
744
+ - Use \`enum\` types for workflow statuses (e.g., \`status: OrderStatus!\` where the enum has an initial value like \`DRAFT\`)
745
+
746
+ ### ⚠️ CRITICAL: State Type Naming Convention
747
+
748
+ **MANDATORY**: The global state type name MUST follow this exact pattern:
749
+
750
+ ~~~graphql
751
+ type <DocumentModelName>State {
752
+ # your fields here
753
+ }
754
+ ~~~
755
+
756
+ **DO NOT** append "Global" to the state type name, even when defining global state:
757
+
758
+ ~~~graphql
759
+ // ❌ WRONG - Do not use "GlobalState" suffix
760
+ type TodoListGlobalState {
761
+ todos: [Todo!]!
762
+ }
763
+
764
+ // ✅ CORRECT - Use only "State" suffix
765
+ type TodoListState {
766
+ todos: [Todo!]!
767
+ }
768
+
769
+ // ✅ CORRECT - Use "LocalState" suffix for Local scope
770
+ type TodoListLocalState {
771
+ localTodos: [Todo!]!
772
+ }
773
+ ~~~
774
+
775
+ **Why this matters:**
776
+
777
+ - The code generator expects the type to be named \`<DocumentModelName>State\`
778
+ - Using \`GlobalState\` or \`LocalState\` suffix will cause TypeScript compilation errors
779
+ - This applies when using \`SET_STATE_SCHEMA\` with \`scope: "global"\`
780
+
781
+ **Rule**: For global state, the type should be \`<DocumentModelName>State\`. For local state (if needed), the type name should be \`<DocumentModelName>LocalState\`.
782
+
783
+ ### Available Scalar Types
784
+
785
+ | Standard | Custom Identity | Custom Amounts | Custom Specialized |
786
+ | --------- | ---------------------- | ------------------- | ------------------ |
787
+ | \`String\` | \`OID\` (Object ID) | \`Amount\` | \`EthereumAddress\` |
788
+ | \`Int\` | \`PHID\` (Powerhouse ID) | \`Amount_Tokens\` | \`EmailAddress\` |
789
+ | \`Float\` | \`OLabel\` | \`Amount_Money\` | \`Date\` |
790
+ | \`Boolean\` | | \`Amount_Fiat\` | \`DateTime\` |
791
+ | | | \`Amount_Currency\` | \`URL\` |
792
+ | | | \`Amount_Crypto\` | \`Currency\` |
793
+ | | | \`Amount_Percentage\` | |
794
+
795
+ ### Arrays and Objects
796
+
797
+ - **Arrays**: Must be mandatory \`[ObjectType!]!\`
798
+ - **Objects in arrays**: Must include \`OID!\` field for unique identification
799
+ - Include \`OLabel\` for metadata when relevant
800
+
801
+ #### OID vs PHID Usage
802
+
803
+ - \`OID\` is used as **primary key** (\`id: OID!\`) and **foreign key** (\`otherObjectId: OID!\`) within a document
804
+ - \`PHID\` is **only** for referencing **external documents** (other documents in the drive), typically alongside cached properties (like a link preview — title/snippet may become stale)
805
+ - **NEVER** use the \`ID\` type — it is a common GraphQL convention but is not used in Powerhouse document models
806
+
807
+ #### Collection Sorting & Trees
808
+
809
+ - **No need for \`position\` or \`weight\` properties** — maintain order via array index; operations like \`MOVE_X\` reorder the array directly
810
+ - **Trees**: Always define as a flat list with \`parentId: OID\` (root nodes have \`parentId = null\`); do NOT use recursive/nested types
811
+
812
+ ### Input Types
813
+
814
+ - Reflect user intent with descriptive names
815
+ - Simple, specific fields over complex nested types
816
+ - System auto-generates \`OID\` for new objects (users don't provide manually)
817
+
818
+ #### Input Type Naming Convention
819
+
820
+ - Root input type **MUST** be named \`<OperationName>Input\` (PascalCase of the operation name)
821
+ - Example: operation \`SET_CATEGORY_LABEL\` → input type \`SetCategoryLabelInput\`
822
+ - **Failing to follow this convention breaks the code generator**
823
+
824
+ #### Input Types Cannot Reference State Types
825
+
826
+ - In operation input schemas, **ONLY** \`enum\` types and scalar types from the state schema can be referenced directly
827
+ - All other state types must be **mirrored** with unique input types (e.g., state type \`MenuItem\` → input type \`NewMenuItemInput\` for the ADD operation)
828
+ - State \`enum\` types **MUST NOT** be redefined in input schemas — reference them directly
829
+ - Each operation should have its **own** input types; do not share mirror types across operations
830
+
831
+ #### Empty Input Workaround
832
+
833
+ - Input types with **zero fields** are not supported by the code generator
834
+ - Workaround: add \`_: Boolean\` as a dummy optional parameter
835
+
836
+ ~~~graphql
837
+ # ❌ BAD - empty input type breaks codegen
838
+ input ClearAllInput {}
839
+
840
+ # ✅ GOOD - dummy field workaround
841
+ input ClearAllInput {
842
+ _: Boolean
843
+ }
844
+ ~~~
845
+
846
+ ## Working with Drives
847
+
848
+ **MANDATORY**: Check the document-drive schema before performing drive operations.
849
+
850
+ ### Drive Types
851
+
852
+ There might be two drives available with a special use case:
853
+
854
+ 1. **Vetra Drive** (\`vetra-{hash}\`):
855
+ - Contains **source documents**: document models and document editors
856
+ - Used for development
857
+ - Add document model and editor definitions here
858
+
859
+ 2. **Preview Drive** (\`preview-{hash}\`, named "Vetra Preview"):
860
+ - Contains **demo and preview documents** (document instances)
861
+ - Used for showcasing and testing document models
862
+ - Add actual document instances here
863
+
864
+ ### Drive Operations
865
+
866
+ When working with drives (adding/removing documents, creating folders, etc.):
867
+
868
+ 1. **Always get the drive schema first**:
869
+
870
+ ~~~typescript
871
+ mcp__reactor -
872
+ mcp__getDocumentModelSchema({ type: "powerhouse/document-drive" });
873
+ ~~~
874
+
875
+ 2. **Review available operations** in the schema, such as:
876
+ - \`ADD_FILE\` - Add a document to the drive
877
+ - \`ADD_FOLDER\` - Create a new folder
878
+ - \`DELETE_NODE\` - Remove a file or folder (use this, NOT "DELETE_FILE")
879
+ - \`UPDATE_NODE\` - Update node properties
880
+ - \`MOVE_NODE\` - Move a node to different location
881
+
882
+ 3. **Check input schemas** for each operation to ensure you're passing correct parameters
883
+ `.raw;
884
+ //#endregion
885
+ //#region src/templates/boilerplate/claude/settings.local.json.ts
886
+ const claudeSettingsLocalTemplate = json`
887
+ {
888
+ "$schema": "https://json.schemastore.org/claude-code-settings.json",
889
+ "permissions": {
890
+ "allow": ["Bash(npm run tsc:*)", "Bash(npm run lint:*)"],
891
+ "deny": [
892
+ "Write(./document-models/*/gen/**)",
893
+ "Write(./.ph/**)",
894
+ "Edit(./document-models/*/gen/**)",
895
+ "Edit(./.ph/**)"
896
+ ]
897
+ },
898
+ "enableAllProjectMcpServers": true,
899
+ "enabledMcpjsonServers": ["reactor-mcp"]
900
+ }
901
+ `.raw;
902
+ //#endregion
903
+ //#region src/templates/boilerplate/cursor/mcp.json.ts
904
+ const cursorMcpTemplate = json`
905
+ {
906
+ "mcpServers": {
907
+ "reactor-mcp": {
908
+ "type": "http",
909
+ "url": "http://localhost:4001/mcp"
910
+ }
911
+ }
912
+ }
913
+ `.raw;
914
+ //#endregion
915
+ //#region src/templates/boilerplate/docker/connect-entrypoint.sh.ts
916
+ const connectEntrypointTemplate = `#!/bin/sh
917
+ set -e
918
+
919
+ # Substitute environment variables in nginx configuration
920
+ envsubst '\${PORT},\${PH_CONNECT_BASE_PATH}' < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
921
+
922
+ echo "Testing nginx configuration..."
923
+ nginx -t
924
+
925
+ if [ $? -eq 0 ]; then
926
+ echo "Connect available at: http://localhost:\${PORT}\${PH_CONNECT_BASE_PATH}"
927
+ exec nginx -g "daemon off;"
928
+ else
929
+ echo "Nginx configuration test failed"
930
+ exit 1
931
+ fi
932
+ `;
933
+ //#endregion
934
+ //#region src/templates/boilerplate/docker/Dockerfile.ts
935
+ const dockerfileTemplate = `# =============================================================================
936
+ # Multi-stage Dockerfile for Powerhouse Document Model Packages
937
+ # Produces two images: connect (frontend) and switchboard (backend)
938
+ #
939
+ # Build commands:
940
+ # docker build --target connect -t <registry>/<project>/connect:<tag> .
941
+ # docker build --target switchboard -t <registry>/<project>/switchboard:<tag> .
942
+ # =============================================================================
943
+
944
+ # -----------------------------------------------------------------------------
945
+ # Base stage: Common setup for building
946
+ # -----------------------------------------------------------------------------
947
+ FROM node:24-alpine AS base
948
+
949
+ WORKDIR /app
950
+
951
+ # Install build dependencies
952
+ RUN apk add --no-cache python3 make g++ git bash \\
953
+ && ln -sf /usr/bin/python3 /usr/bin/python
954
+
955
+ # Setup pnpm
956
+ ENV PNPM_HOME="/pnpm"
957
+ ENV PATH="$PNPM_HOME:$PATH"
958
+ RUN corepack enable && corepack prepare pnpm@latest --activate
959
+
960
+ # Configure JSR registry
961
+ RUN pnpm config set @jsr:registry https://npm.jsr.io
962
+
963
+ # Build arguments
964
+ ARG TAG=latest
965
+ ARG PH_CONNECT_BASE_PATH="/"
966
+
967
+ # Install ph-cmd, prisma, and prettier globally
968
+ RUN pnpm add -g ph-cmd@$TAG prisma@5.17.0 prettier
969
+
970
+ # Initialize project based on tag (dev/staging/latest)
971
+ RUN case "$TAG" in \\
972
+ *dev*) ph init project --dev --package-manager pnpm ;; \\
973
+ *staging*) ph init project --staging --package-manager pnpm ;; \\
974
+ *) ph init project --package-manager pnpm ;; \\
975
+ esac
976
+
977
+ WORKDIR /app/project
978
+
979
+ # Copy package files for the current package
980
+ COPY package.json pnpm-lock.yaml ./
981
+
982
+ # Install the current package (this package)
983
+ ARG PACKAGE_NAME
984
+ RUN if [ -n "$PACKAGE_NAME" ]; then \\
985
+ echo "Installing package: $PACKAGE_NAME"; \\
986
+ ph install "$PACKAGE_NAME"; \\
987
+ else \\
988
+ echo "Warning: PACKAGE_NAME not provided, using local build"; \\
989
+ pnpm install; \\
990
+ fi
991
+
992
+ # Regenerate Prisma client for Alpine Linux
993
+ RUN prisma generate --schema node_modules/document-drive/dist/prisma/schema.prisma || true
994
+
995
+ # -----------------------------------------------------------------------------
996
+ # Connect build stage
997
+ # -----------------------------------------------------------------------------
998
+ FROM base AS connect-builder
999
+
1000
+ ARG PH_CONNECT_BASE_PATH="/"
1001
+
1002
+ # Build connect
1003
+ RUN ph connect build --base \${PH_CONNECT_BASE_PATH}
1004
+
1005
+ # -----------------------------------------------------------------------------
1006
+ # Connect final stage - nginx
1007
+ # -----------------------------------------------------------------------------
1008
+ FROM nginx:alpine AS connect
1009
+
1010
+ # Install envsubst for config templating
1011
+ RUN apk add --no-cache gettext
1012
+
1013
+ # Copy nginx config template
1014
+ COPY docker/nginx.conf /etc/nginx/nginx.conf.template
1015
+
1016
+ # Copy built static files from build stage
1017
+ COPY --from=connect-builder /app/project/.ph/connect-build/dist /var/www/html/project
1018
+
1019
+ # Environment variables for nginx config
1020
+ ENV PORT=3001
1021
+ ENV PH_CONNECT_BASE_PATH="/"
1022
+
1023
+ # Copy and setup entrypoint
1024
+ COPY docker/connect-entrypoint.sh /docker-entrypoint.sh
1025
+ RUN chmod +x /docker-entrypoint.sh
1026
+
1027
+ EXPOSE \${PORT}
1028
+
1029
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \\
1030
+ CMD wget -q --spider http://localhost:\${PORT}/health || exit 1
1031
+
1032
+ ENTRYPOINT ["/docker-entrypoint.sh"]
1033
+
1034
+ # -----------------------------------------------------------------------------
1035
+ # Switchboard final stage - node runtime
1036
+ # -----------------------------------------------------------------------------
1037
+ FROM node:24-alpine AS switchboard
1038
+
1039
+ WORKDIR /app
1040
+
1041
+ # Install runtime dependencies
1042
+ RUN apk add --no-cache curl openssl
1043
+
1044
+ # Setup pnpm
1045
+ ENV PNPM_HOME="/pnpm"
1046
+ ENV PATH="$PNPM_HOME:$PATH"
1047
+ RUN corepack enable && corepack prepare pnpm@latest --activate
1048
+
1049
+ # Configure JSR registry
1050
+ RUN pnpm config set @jsr:registry https://npm.jsr.io
1051
+
1052
+ # Install ph-cmd and prisma globally (needed at runtime)
1053
+ ARG TAG=latest
1054
+ RUN pnpm add -g ph-cmd@$TAG prisma@5.17.0
1055
+
1056
+ # Copy built project from build stage
1057
+ COPY --from=base /app/project /app/project
1058
+
1059
+ WORKDIR /app/project
1060
+
1061
+ # Copy entrypoint
1062
+ COPY docker/switchboard-entrypoint.sh /app/entrypoint.sh
1063
+ RUN chmod +x /app/entrypoint.sh
1064
+
1065
+ # Environment variables
1066
+ ENV NODE_ENV=production
1067
+ ENV PORT=3000
1068
+ ENV DATABASE_URL=""
1069
+ ENV SKIP_DB_MIGRATIONS="false"
1070
+
1071
+ EXPOSE \${PORT}
1072
+
1073
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \\
1074
+ CMD curl -f http://localhost:\${PORT}/health || exit 1
1075
+
1076
+ ENTRYPOINT ["/app/entrypoint.sh"]
1077
+ `;
1078
+ //#endregion
1079
+ //#region src/templates/boilerplate/docker/nginx.conf.ts
1080
+ const nginxConfTemplate = `user nginx;
1081
+ worker_processes auto;
1082
+ error_log /var/log/nginx/error.log warn;
1083
+ pid /var/run/nginx.pid;
1084
+
1085
+ events {
1086
+ worker_connections 1024;
1087
+ }
1088
+
1089
+ http {
1090
+ include /etc/nginx/mime.types;
1091
+ default_type application/octet-stream;
1092
+
1093
+ # Gzip compression
1094
+ gzip on;
1095
+ gzip_vary on;
1096
+ gzip_proxied any;
1097
+ gzip_comp_level 6;
1098
+ gzip_buffers 16 8k;
1099
+ gzip_http_version 1.1;
1100
+ gzip_types text/plain text/css application/javascript application/json image/svg+xml application/xml+rss image/avif;
1101
+
1102
+ server {
1103
+ listen 0.0.0.0:\${PORT};
1104
+ server_name _;
1105
+ root /var/www/html/project;
1106
+
1107
+ # Health check endpoint
1108
+ location /health {
1109
+ access_log off;
1110
+ add_header Content-Type text/plain;
1111
+ return 200 'OK';
1112
+ }
1113
+
1114
+ location \${PH_CONNECT_BASE_PATH}/assets/ {
1115
+ alias /var/www/html/project/assets/;
1116
+ access_log off;
1117
+ log_not_found off;
1118
+ etag off;
1119
+ expires max;
1120
+ add_header Cache-Control "public, max-age=31536000, immutable";
1121
+ }
1122
+
1123
+ location \${PH_CONNECT_BASE_PATH}/fonts/ {
1124
+ alias /var/www/html/project/fonts/;
1125
+ access_log off;
1126
+ log_not_found off;
1127
+ expires max;
1128
+ add_header Cache-Control "public, max-age=31536000, immutable";
1129
+ }
1130
+
1131
+ location = \${PH_CONNECT_BASE_PATH}/service-worker.js {
1132
+ alias /var/www/html/project/service-worker.js;
1133
+
1134
+ access_log off;
1135
+ log_not_found off;
1136
+ etag off;
1137
+
1138
+ add_header Cache-Control "no-cache, no-store, must-revalidate";
1139
+ add_header Pragma "no-cache";
1140
+ add_header Expires "0";
1141
+ }
1142
+
1143
+ # match any file in the root folder, except index.html
1144
+ location ~ \${PH_CONNECT_BASE_PATH}/(?!index\\.html$)([^/]+\\.[a-zA-Z0-9]+)$ {
1145
+ alias /var/www/html/project/$1;
1146
+ access_log off;
1147
+ log_not_found off;
1148
+ etag on;
1149
+ add_header Cache-Control "public, must-revalidate";
1150
+ }
1151
+
1152
+ location \${PH_CONNECT_BASE_PATH} {
1153
+ try_files $uri $uri/ /index.html;
1154
+ }
1155
+ }
1156
+ }
1157
+ `;
1158
+ //#endregion
1159
+ //#region src/templates/boilerplate/docker/switchboard-entrypoint.sh.ts
1160
+ const switchboardEntrypointTemplate = `#!/bin/sh
1161
+ set -e
1162
+
1163
+ # Regenerate Prisma client for current platform (fixes darwin-arm64 vs linux-musl-openssl mismatch)
1164
+ echo "[entrypoint] Regenerating Prisma client for current platform..."
1165
+ prisma generate --schema node_modules/document-drive/dist/prisma/schema.prisma
1166
+
1167
+ # Run migrations if DATABASE_URL is postgres and migrations not skipped
1168
+ if [ -n "$DATABASE_URL" ] && echo "$DATABASE_URL" | grep -q "^postgres" && [ "$SKIP_DB_MIGRATIONS" != "true" ]; then
1169
+ echo "[entrypoint] Running Prisma db push..."
1170
+ prisma db push --schema node_modules/document-drive/dist/prisma/schema.prisma --skip-generate
1171
+ echo "[entrypoint] Running migrations..."
1172
+ ph switchboard --migrate
1173
+ fi
1174
+
1175
+ echo "[entrypoint] Starting switchboard on port \${PORT:-3000}..."
1176
+ exec ph switchboard --port \${PORT:-3000}
1177
+ `;
1178
+ //#endregion
1179
+ //#region src/templates/boilerplate/document-models/document-models.ts
1180
+ const documentModelsTemplate = ts`
1181
+ import type { DocumentModelModule } from "document-model";
1182
+
1183
+ export const documentModels: DocumentModelModule[] = [];
1184
+ `.raw;
1185
+ //#endregion
1186
+ //#region src/templates/boilerplate/document-models/index.ts
1187
+ const documentModelsIndexTemplate = "";
1188
+ //#endregion
1189
+ //#region src/templates/boilerplate/editors/editors.ts
1190
+ const editorsTemplate = ts`
1191
+ import type { EditorModule } from "document-model";
1192
+
1193
+ export const editors: EditorModule[] = [];
1194
+ `.raw;
1195
+ //#endregion
1196
+ //#region src/templates/boilerplate/editors/index.ts
1197
+ const editorsIndexTemplate = "";
1198
+ //#endregion
1199
+ //#region src/templates/boilerplate/eslint.config.js.ts
1200
+ const eslintConfigTemplate = js`
1201
+ // @ts-check
1202
+ import { default as eslint } from "@eslint/js";
1203
+ import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended";
1204
+ import reactPlugin from "eslint-plugin-react";
1205
+ import reactHooksPlugin from "eslint-plugin-react-hooks";
1206
+ import { defineConfig, globalIgnores } from "eslint/config";
1207
+ import globals from "globals";
1208
+ import tseslint from "typescript-eslint";
1209
+
1210
+ /** These files are typically ignored by eslint by default, so there is no need to investigate why they are ignored. */
1211
+ const ignoredFiles = [
1212
+ "**/node_modules/",
1213
+ "**/dist/",
1214
+ "**/.ph/",
1215
+ "**/storybook-static/",
1216
+ "**/.vite/",
1217
+ ];
1218
+
1219
+ /** Global configs for eslint ignores */
1220
+ const ignored = globalIgnores(ignoredFiles);
1221
+
1222
+ /** Typescript (\`.ts\`) files */
1223
+ const typescriptFiles = ["**/*.ts"];
1224
+
1225
+ /** Typescript React (\`.tsx\`) files */
1226
+ const typescriptReactFiles = ["**/*.tsx"];
1227
+
1228
+ /** Javascript (\`.js\`, \`.cjs\`, \`.mjs\`) files */
1229
+ const javascriptFiles = ["**/*.js", "**/*.cjs", "**/*.mjs"];
1230
+
1231
+ /** Typescript rules that we have chosen to opt out of in general */
1232
+ /** @type {import("eslint").Linter.RulesRecord} */
1233
+ const typescriptRules = {
1234
+ "@typescript-eslint/consistent-type-imports": [
1235
+ "error",
1236
+ {
1237
+ prefer: "type-imports",
1238
+ disallowTypeAnnotations: true,
1239
+ fixStyle: "separate-type-imports",
1240
+ },
1241
+ ],
1242
+ "@typescript-eslint/no-explicit-any": "off",
1243
+ "@typescript-eslint/no-unused-vars": [
1244
+ "warn",
1245
+ {
1246
+ argsIgnorePattern: "^_",
1247
+ varsIgnorePattern: "^_",
1248
+ caughtErrorsIgnorePattern: "^_",
1249
+ },
1250
+ ],
1251
+ "@typescript-eslint/no-unnecessary-condition": "warn",
1252
+ "@typescript-eslint/require-await": "warn",
1253
+ "@typescript-eslint/no-misused-promises": "warn",
1254
+ "@typescript-eslint/no-floating-promises": "warn",
1255
+ "@typescript-eslint/no-empty-object-type": "warn",
1256
+ "@typescript-eslint/no-duplicate-type-constituents": "warn",
1257
+ "@typescript-eslint/restrict-template-expressions": [
1258
+ "warn",
1259
+ {
1260
+ allowNumber: true,
1261
+ },
1262
+ ],
1263
+ };
1264
+
1265
+ /** Language options for typescript files
1266
+ @type {import("eslint").Linter.LanguageOptions} */
1267
+ const typescriptLanguageOptions = {
1268
+ sourceType: "module",
1269
+ ecmaVersion: "latest",
1270
+ globals: {
1271
+ ...globals.browser,
1272
+ ...globals.node,
1273
+ },
1274
+ parserOptions: {
1275
+ projectService: {
1276
+ allowDefaultProject: ["eslint.config.js", "vitest.config.ts"],
1277
+ },
1278
+ tsconfigRootDir: import.meta.dirname,
1279
+ ecmaFeatures: {
1280
+ jsx: true,
1281
+ },
1282
+ },
1283
+ };
1284
+
1285
+ /** React plugins */
1286
+ const reactPlugins = {
1287
+ react: reactPlugin,
1288
+ "react-hooks": reactHooksPlugin,
1289
+ };
1290
+
1291
+ /** React settings */
1292
+ const reactSettings = {
1293
+ react: {
1294
+ version: "detect",
1295
+ },
1296
+ };
1297
+
1298
+ /** Typescript config for both \`.ts\` and \`.tsx\` files */
1299
+ const typescriptConfig = {
1300
+ files: [...typescriptFiles, ...typescriptReactFiles],
1301
+ languageOptions: typescriptLanguageOptions,
1302
+ rules: typescriptRules,
1303
+ };
1304
+
1305
+ /** React config for \`.tsx\` files */
1306
+ const reactConfig = {
1307
+ files: typescriptReactFiles,
1308
+ settings: reactSettings,
1309
+ plugins: reactPlugins,
1310
+ };
1311
+
1312
+ /** Config for javascript files */
1313
+ const javascriptConfig = {
1314
+ // disable type aware linting for js files
1315
+ files: javascriptFiles,
1316
+ extends: [tseslint.configs.disableTypeChecked],
1317
+ };
1318
+
1319
+ /** Recommended config from eslint */
1320
+ const eslintRecommendedConfig = eslint.configs.recommended;
1321
+
1322
+ /** Recommended config from typescript-eslint */
1323
+ const typescriptEsLintRecommendedConfig = [
1324
+ ...tseslint.configs.recommendedTypeChecked,
1325
+ ];
1326
+
1327
+ /** Main config */
1328
+ export default defineConfig(
1329
+ ignored,
1330
+ eslintRecommendedConfig,
1331
+ typescriptEsLintRecommendedConfig,
1332
+ typescriptConfig,
1333
+ reactConfig,
1334
+ javascriptConfig,
1335
+ eslintPluginPrettierRecommended,
1336
+ );
1337
+ `.raw;
1338
+ //#endregion
1339
+ //#region src/templates/boilerplate/gemini/settings.json.ts
1340
+ const geminiSettingsTemplate = json`
1341
+ {
1342
+ "mcpServers": {
1343
+ "reactor-mcp": {
1344
+ "type": "http",
1345
+ "url": "http://localhost:4001/mcp"
1346
+ }
1347
+ }
1348
+ }
1349
+ `.raw;
1350
+ //#endregion
1351
+ //#region src/templates/boilerplate/github/sync-and-publish.yml.ts
1352
+ const syncAndPublishWorkflowTemplate = yaml`
1353
+ name: Sync and Publish
1354
+
1355
+ on:
1356
+ # Triggered by powerhouse monorepo after release
1357
+ repository_dispatch:
1358
+ types: [powerhouse-release]
1359
+
1360
+ # Manual trigger
1361
+ workflow_dispatch:
1362
+ inputs:
1363
+ channel:
1364
+ description: 'Release channel'
1365
+ required: true
1366
+ type: choice
1367
+ options:
1368
+ - dev
1369
+ - staging
1370
+ - latest
1371
+ default: 'staging'
1372
+ version:
1373
+ description: 'Powerhouse version (e.g., 5.3.0-staging.6)'
1374
+ required: false
1375
+ type: string
1376
+ dry-run:
1377
+ description: 'Dry run (skip publishing)'
1378
+ required: false
1379
+ type: boolean
1380
+ default: false
1381
+ skip-docker:
1382
+ description: 'Skip Docker build and push'
1383
+ required: false
1384
+ type: boolean
1385
+ default: false
1386
+
1387
+ env:
1388
+ NODE_VERSION: '24'
1389
+ PNPM_VERSION: '10'
1390
+ DOCKER_REGISTRY: cr.vetra.io
1391
+ GHCR_REGISTRY: ghcr.io
1392
+
1393
+ jobs:
1394
+ # ==========================================================================
1395
+ # Determine release parameters
1396
+ # ==========================================================================
1397
+ prepare:
1398
+ name: Prepare Release
1399
+ runs-on: ubuntu-latest
1400
+ outputs:
1401
+ channel: \${{ steps.params.outputs.channel }}
1402
+ version: \${{ steps.params.outputs.version }}
1403
+ branch: \${{ steps.params.outputs.branch }}
1404
+ project_name: \${{ steps.params.outputs.project_name }}
1405
+ dry_run: \${{ steps.params.outputs.dry_run }}
1406
+ skip_docker: \${{ steps.params.outputs.skip_docker }}
1407
+ steps:
1408
+ - name: Determine parameters
1409
+ id: params
1410
+ run: |
1411
+ # Get channel from dispatch payload or input
1412
+ if [ "\${{ github.event_name }}" = "repository_dispatch" ]; then
1413
+ CHANNEL="\${{ github.event.client_payload.channel }}"
1414
+ VERSION="\${{ github.event.client_payload.version }}"
1415
+ DRY_RUN="false"
1416
+ SKIP_DOCKER="false"
1417
+ else
1418
+ CHANNEL="\${{ inputs.channel }}"
1419
+ VERSION="\${{ inputs.version }}"
1420
+ DRY_RUN="\${{ inputs.dry-run }}"
1421
+ SKIP_DOCKER="\${{ inputs.skip-docker }}"
1422
+ fi
1423
+
1424
+ # Default channel to staging if not set
1425
+ CHANNEL="\${CHANNEL:-staging}"
1426
+
1427
+ # Determine branch from channel
1428
+ case "\$CHANNEL" in
1429
+ dev) BRANCH="dev" ;;
1430
+ staging) BRANCH="staging" ;;
1431
+ latest|main) BRANCH="main" ;;
1432
+ *) BRANCH="staging" ;;
1433
+ esac
1434
+
1435
+ # Use DOCKER_PROJECT secret if set, otherwise extract from repository name
1436
+ if [ -n "\${{ secrets.DOCKER_PROJECT }}" ]; then
1437
+ PROJECT_NAME="\${{ secrets.DOCKER_PROJECT }}"
1438
+ else
1439
+ PROJECT_NAME="\${GITHUB_REPOSITORY#*/}"
1440
+ fi
1441
+
1442
+ echo "channel=\$CHANNEL" >> \$GITHUB_OUTPUT
1443
+ echo "version=\$VERSION" >> \$GITHUB_OUTPUT
1444
+ echo "branch=\$BRANCH" >> \$GITHUB_OUTPUT
1445
+ echo "project_name=\$PROJECT_NAME" >> \$GITHUB_OUTPUT
1446
+ echo "dry_run=\$DRY_RUN" >> \$GITHUB_OUTPUT
1447
+ echo "skip_docker=\$SKIP_DOCKER" >> \$GITHUB_OUTPUT
1448
+
1449
+ echo "Channel: \$CHANNEL"
1450
+ echo "Version: \$VERSION"
1451
+ echo "Branch: \$BRANCH"
1452
+ echo "Project: \$PROJECT_NAME"
1453
+ echo "Dry Run: \$DRY_RUN"
1454
+ echo "Skip Docker: \$SKIP_DOCKER"
1455
+
1456
+ # ==========================================================================
1457
+ # Update dependencies and publish to npm
1458
+ # ==========================================================================
1459
+ update-and-publish:
1460
+ name: Update & Publish NPM
1461
+ needs: prepare
1462
+ runs-on: ubuntu-latest
1463
+ permissions:
1464
+ contents: write
1465
+ id-token: write
1466
+ outputs:
1467
+ new_version: \${{ steps.version.outputs.new_version }}
1468
+ steps:
1469
+ - name: Checkout repository
1470
+ uses: actions/checkout@v4
1471
+ with:
1472
+ ref: \${{ needs.prepare.outputs.branch }}
1473
+ fetch-depth: 0
1474
+ token: \${{ secrets.GITHUB_TOKEN }}
1475
+
1476
+ - name: Install pnpm
1477
+ uses: pnpm/action-setup@v4
1478
+ with:
1479
+ version: \${{ env.PNPM_VERSION }}
1480
+
1481
+ - name: Install Node.js
1482
+ uses: actions/setup-node@v4
1483
+ with:
1484
+ node-version: \${{ env.NODE_VERSION }}
1485
+ cache: 'pnpm'
1486
+
1487
+ - name: Configure git
1488
+ run: |
1489
+ git config user.name "github-actions[bot]"
1490
+ git config user.email "github-actions[bot]@users.noreply.github.com"
1491
+
1492
+ - name: Install ph-cli
1493
+ run: |
1494
+ CHANNEL="\${{ needs.prepare.outputs.channel }}"
1495
+ case "\$CHANNEL" in
1496
+ dev) pnpm add -g @powerhousedao/ph-cli@dev ;;
1497
+ staging) pnpm add -g @powerhousedao/ph-cli@staging ;;
1498
+ *) pnpm add -g @powerhousedao/ph-cli@latest ;;
1499
+ esac
1500
+
1501
+ - name: Update Powerhouse dependencies
1502
+ run: ph update
1503
+
1504
+ - name: Install dependencies
1505
+ run: pnpm install
1506
+
1507
+ - name: Build package
1508
+ run: pnpm build
1509
+
1510
+ - name: Run tests
1511
+ run: pnpm test || true
1512
+ continue-on-error: true
1513
+
1514
+ - name: Bump version
1515
+ id: version
1516
+ run: |
1517
+ CHANNEL="\${{ needs.prepare.outputs.channel }}"
1518
+ CURRENT_VERSION=\$(node -p "require('./package.json').version")
1519
+
1520
+ # Determine new version
1521
+ if [ "\$CHANNEL" = "latest" ] || [ "\$CHANNEL" = "main" ]; then
1522
+ # For production, use patch bump
1523
+ npm version patch --no-git-tag-version
1524
+ else
1525
+ # For dev/staging, use prerelease
1526
+ npm version prerelease --preid=\$CHANNEL --no-git-tag-version
1527
+ fi
1528
+
1529
+ NEW_VERSION=\$(node -p "require('./package.json').version")
1530
+ echo "new_version=\$NEW_VERSION" >> \$GITHUB_OUTPUT
1531
+ echo "Bumped version: \$CURRENT_VERSION -> \$NEW_VERSION"
1532
+
1533
+ - name: Commit changes
1534
+ run: |
1535
+ git add package.json pnpm-lock.yaml
1536
+ git commit -m "chore: sync powerhouse dependencies to \${{ needs.prepare.outputs.version }}
1537
+
1538
+ - Updated to powerhouse \${{ needs.prepare.outputs.version }}
1539
+ - Bumped version to \${{ steps.version.outputs.new_version }}" || echo "No changes to commit"
1540
+
1541
+ - name: Push changes
1542
+ if: needs.prepare.outputs.dry_run != 'true'
1543
+ run: git push
1544
+
1545
+ - name: Setup npm for publishing
1546
+ if: needs.prepare.outputs.dry_run != 'true' && secrets.NPM_ACCESS_TOKEN != ''
1547
+ uses: actions/setup-node@v4
1548
+ with:
1549
+ node-version: \${{ env.NODE_VERSION }}
1550
+ registry-url: 'https://registry.npmjs.org'
1551
+
1552
+ - name: Publish to npm with provenance
1553
+ if: needs.prepare.outputs.dry_run != 'true' && secrets.NPM_ACCESS_TOKEN != ''
1554
+ env:
1555
+ NODE_AUTH_TOKEN: \${{ secrets.NPM_ACCESS_TOKEN }}
1556
+ NPM_CONFIG_PROVENANCE: true
1557
+ run: |
1558
+ CHANNEL="\${{ needs.prepare.outputs.channel }}"
1559
+ if [ "\$CHANNEL" = "latest" ] || [ "\$CHANNEL" = "main" ]; then
1560
+ pnpm publish --access public --tag latest --no-git-checks
1561
+ else
1562
+ pnpm publish --access public --tag \$CHANNEL --no-git-checks
1563
+ fi
1564
+
1565
+ - name: Create git tag
1566
+ if: needs.prepare.outputs.dry_run != 'true'
1567
+ run: |
1568
+ git tag "v\${{ steps.version.outputs.new_version }}"
1569
+ git push origin "v\${{ steps.version.outputs.new_version }}"
1570
+
1571
+ # ==========================================================================
1572
+ # Build and push Docker images
1573
+ # ==========================================================================
1574
+ build-docker:
1575
+ name: Build Docker Images
1576
+ needs: [prepare, update-and-publish]
1577
+ if: |
1578
+ needs.prepare.outputs.skip_docker != 'true' &&
1579
+ needs.prepare.outputs.dry_run != 'true' &&
1580
+ secrets.DOCKER_USERNAME != '' &&
1581
+ secrets.DOCKER_PASSWORD != ''
1582
+ runs-on: ubuntu-latest
1583
+ permissions:
1584
+ contents: read
1585
+ packages: write
1586
+ strategy:
1587
+ matrix:
1588
+ target: [connect, switchboard]
1589
+ steps:
1590
+ - name: Checkout repository
1591
+ uses: actions/checkout@v4
1592
+ with:
1593
+ ref: \${{ needs.prepare.outputs.branch }}
1594
+
1595
+ - name: Pull latest changes
1596
+ run: git pull origin \${{ needs.prepare.outputs.branch }}
1597
+
1598
+ - name: Set up Docker Buildx
1599
+ uses: docker/setup-buildx-action@v3
1600
+
1601
+ - name: Ensure Docker project exists
1602
+ run: |
1603
+ PROJECT_NAME="\${{ needs.prepare.outputs.project_name }}"
1604
+
1605
+ # Check if project exists, create if not
1606
+ STATUS=\$(curl -s -o /dev/null -w "%{http_code}" \\
1607
+ -u "\${{ secrets.DOCKER_USERNAME }}:\${{ secrets.DOCKER_PASSWORD }}" \\
1608
+ "https://\${{ env.DOCKER_REGISTRY }}/api/v2.0/projects?name=\${PROJECT_NAME}")
1609
+
1610
+ if [ "\$STATUS" = "200" ]; then
1611
+ # Check if the project is in the response
1612
+ EXISTS=\$(curl -s \\
1613
+ -u "\${{ secrets.DOCKER_USERNAME }}:\${{ secrets.DOCKER_PASSWORD }}" \\
1614
+ "https://\${{ env.DOCKER_REGISTRY }}/api/v2.0/projects?name=\${PROJECT_NAME}" | \\
1615
+ jq -r ".[] | select(.name==\\"\${PROJECT_NAME}\\") | .name")
1616
+
1617
+ if [ "\$EXISTS" = "\$PROJECT_NAME" ]; then
1618
+ echo "Project \${PROJECT_NAME} already exists"
1619
+ else
1620
+ echo "Creating project \${PROJECT_NAME}..."
1621
+ curl -X POST \\
1622
+ -u "\${{ secrets.DOCKER_USERNAME }}:\${{ secrets.DOCKER_PASSWORD }}" \\
1623
+ -H "Content-Type: application/json" \\
1624
+ -d "{\\"project_name\\": \\"\${PROJECT_NAME}\\", \\"public\\": false}" \\
1625
+ "https://\${{ env.DOCKER_REGISTRY }}/api/v2.0/projects"
1626
+ fi
1627
+ else
1628
+ echo "Creating project \${PROJECT_NAME}..."
1629
+ curl -X POST \\
1630
+ -u "\${{ secrets.DOCKER_USERNAME }}:\${{ secrets.DOCKER_PASSWORD }}" \\
1631
+ -H "Content-Type: application/json" \\
1632
+ -d "{\\"project_name\\": \\"\${PROJECT_NAME}\\", \\"public\\": false}" \\
1633
+ "https://\${{ env.DOCKER_REGISTRY }}/api/v2.0/projects"
1634
+ fi
1635
+
1636
+ - name: Login to GitHub Container Registry
1637
+ uses: docker/login-action@v3
1638
+ with:
1639
+ registry: \${{ env.GHCR_REGISTRY }}
1640
+ username: \${{ github.actor }}
1641
+ password: \${{ secrets.GITHUB_TOKEN }}
1642
+
1643
+ - name: Login to Docker Registry
1644
+ uses: docker/login-action@v3
1645
+ with:
1646
+ registry: \${{ env.DOCKER_REGISTRY }}
1647
+ username: \${{ secrets.DOCKER_USERNAME }}
1648
+ password: \${{ secrets.DOCKER_PASSWORD }}
1649
+
1650
+ - name: Extract package name
1651
+ id: package
1652
+ run: |
1653
+ PACKAGE_NAME=\$(node -p "require('./package.json').name")
1654
+ echo "name=\$PACKAGE_NAME" >> \$GITHUB_OUTPUT
1655
+
1656
+ - name: Determine image tags
1657
+ id: tags
1658
+ run: |
1659
+ VERSION="\${{ needs.update-and-publish.outputs.new_version }}"
1660
+ CHANNEL="\${{ needs.prepare.outputs.channel }}"
1661
+ PROJECT="\${{ needs.prepare.outputs.project_name }}"
1662
+ TARGET="\${{ matrix.target }}"
1663
+
1664
+ # GHCR tags
1665
+ GHCR_BASE="\${{ env.GHCR_REGISTRY }}/\${{ github.repository_owner }}/\${PROJECT}/\${TARGET}"
1666
+
1667
+ # Docker registry tags
1668
+ DOCKER_BASE="\${{ env.DOCKER_REGISTRY }}/\${PROJECT}/\${TARGET}"
1669
+
1670
+ # Build tag list
1671
+ TAGS="\${GHCR_BASE}:v\${VERSION}"
1672
+ TAGS="\${TAGS},\${DOCKER_BASE}:v\${VERSION}"
1673
+
1674
+ # Add channel tag
1675
+ if [ "\$CHANNEL" = "latest" ] || [ "\$CHANNEL" = "main" ]; then
1676
+ TAGS="\${TAGS},\${GHCR_BASE}:latest"
1677
+ TAGS="\${TAGS},\${DOCKER_BASE}:latest"
1678
+ else
1679
+ TAGS="\${TAGS},\${GHCR_BASE}:\${CHANNEL}"
1680
+ TAGS="\${TAGS},\${DOCKER_BASE}:\${CHANNEL}"
1681
+ fi
1682
+
1683
+ echo "tags=\$TAGS" >> \$GITHUB_OUTPUT
1684
+ echo "Image tags: \$TAGS"
1685
+
1686
+ - name: Build and push \${{ matrix.target }}
1687
+ uses: docker/build-push-action@v5
1688
+ with:
1689
+ context: .
1690
+ file: ./Dockerfile
1691
+ target: \${{ matrix.target }}
1692
+ push: true
1693
+ tags: \${{ steps.tags.outputs.tags }}
1694
+ build-args: |
1695
+ TAG=\${{ needs.prepare.outputs.channel == 'latest' && 'latest' || needs.prepare.outputs.version }}
1696
+ PACKAGE_NAME=\${{ steps.package.outputs.name }}
1697
+ PH_CONNECT_BASE_PATH=/
1698
+ cache-from: type=gha
1699
+ cache-to: type=gha,mode=max
1700
+
1701
+ # ==========================================================================
1702
+ # Summary
1703
+ # ==========================================================================
1704
+ summary:
1705
+ name: Release Summary
1706
+ needs: [prepare, update-and-publish, build-docker]
1707
+ if: always()
1708
+ runs-on: ubuntu-latest
1709
+ steps:
1710
+ - name: Summary
1711
+ run: |
1712
+ echo "## Release Summary" >> \$GITHUB_STEP_SUMMARY
1713
+ echo "" >> \$GITHUB_STEP_SUMMARY
1714
+ echo "| Parameter | Value |" >> \$GITHUB_STEP_SUMMARY
1715
+ echo "|-----------|-------|" >> \$GITHUB_STEP_SUMMARY
1716
+ echo "| Channel | \${{ needs.prepare.outputs.channel }} |" >> \$GITHUB_STEP_SUMMARY
1717
+ echo "| Branch | \${{ needs.prepare.outputs.branch }} |" >> \$GITHUB_STEP_SUMMARY
1718
+ echo "| Powerhouse Version | \${{ needs.prepare.outputs.version }} |" >> \$GITHUB_STEP_SUMMARY
1719
+ echo "| Package Version | \${{ needs.update-and-publish.outputs.new_version }} |" >> \$GITHUB_STEP_SUMMARY
1720
+ echo "| Dry Run | \${{ needs.prepare.outputs.dry_run }} |" >> \$GITHUB_STEP_SUMMARY
1721
+ echo "" >> \$GITHUB_STEP_SUMMARY
1722
+ echo "### Docker Images" >> \$GITHUB_STEP_SUMMARY
1723
+ echo "- \\\`\${{ env.DOCKER_REGISTRY }}/\${{ needs.prepare.outputs.project_name }}/connect:v\${{ needs.update-and-publish.outputs.new_version }}\\\`" >> \$GITHUB_STEP_SUMMARY
1724
+ echo "- \\\`\${{ env.DOCKER_REGISTRY }}/\${{ needs.prepare.outputs.project_name }}/switchboard:v\${{ needs.update-and-publish.outputs.new_version }}\\\`" >> \$GITHUB_STEP_SUMMARY
1725
+ `.raw;
1726
+ //#endregion
1727
+ //#region src/templates/boilerplate/gitignore.ts
1728
+ const gitIgnoreTemplate = `
1729
+ dist
1730
+ coverage
1731
+ node_modules
1732
+ .eslintcache
1733
+ .env.local
1734
+
1735
+ .ph
1736
+ projects-import.js
1737
+ `;
1738
+ //#endregion
1739
+ //#region \0@oxc-project+runtime@0.115.0/helpers/taggedTemplateLiteral.js
1740
+ function _taggedTemplateLiteral(e, t) {
1741
+ return t || (t = e.slice(0)), Object.freeze(Object.defineProperties(e, { raw: { value: Object.freeze(t) } }));
1742
+ }
1743
+ //#endregion
1744
+ //#region src/templates/boilerplate/index.html.ts
1745
+ var _templateObject$1;
1746
+ const indexHtmlTemplate = html(_templateObject$1 || (_templateObject$1 = _taggedTemplateLiteral(["<!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta\n name=\"description\"\n content=\"Connect is a hub for your most important documents and processes, translated into software. Easily capture data in a structured way with dedicated business process packages. Collaborate on shared documents with ease while using your preferred storage solution (decentralized, centralized, or local).\"\n />\n <title>Powerhouse Connect</title>\n <link rel=\"icon\" href=\"/icon.ico\" />\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link\n href=\"https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap\"\n rel=\"stylesheet\"\n />\n </head>\n <body>\n <div id=\"root\"></div>\n <link href=\"/style.css\" rel=\"stylesheet\" />\n <script type=\"module\" src=\"/main.tsx\"><\/script>\n </body>\n </html> "]))).raw;
1747
+ //#endregion
1748
+ //#region src/templates/boilerplate/index.html.legacy.ts
1749
+ var _templateObject;
1750
+ const legacyIndexHtmlTemplate = html(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta\n name=\"description\"\n content=\"Connect is a hub for your most important documents and processes, translated into software. Easily capture data in a structured way with dedicated business process packages. Collaborate on shared documents with ease while using your preferred storage solution (decentralized, centralized, or local).\"\n />\n <title>Powerhouse Connect</title>\n <link rel=\"icon\" href=\"/icon.ico\" />\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\" />\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n <link\n href=\"https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap\"\n rel=\"stylesheet\"\n />\n <style>\n @import \"tailwindcss\";\n @import \"@powerhousedao/design-system/style.css\";\n @import \"@powerhousedao/document-engineering/style.css\";\n @source \"./node_modules/@powerhousedao/connect\";\n </style>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\">\n // initializes Connect on '<div id=\"root\"></div>'\n import \"@powerhousedao/connect/main.js\";\n <\/script>\n </body>\n </html>\n"]))).raw;
1751
+ //#endregion
1752
+ //#region src/templates/boilerplate/index.ts
1753
+ const indexTsTemplate = ts`
1754
+ import type { Manifest } from "document-model";
1755
+ import manifestJson from "./powerhouse.manifest.json" with { type: "json" };
1756
+ export { documentModels } from "./document-models/document-models.js";
1757
+ export { upgradeManifests } from "./document-models/upgrade-manifests.js";
1758
+ export { editors } from "./editors/editors.js";
1759
+ export { processorFactory } from "./processors/factory.js";
1760
+ export const manifest: Manifest = manifestJson;
1761
+ `.raw;
1762
+ //#endregion
1763
+ //#region src/templates/boilerplate/LICENSE.ts
1764
+ const licenseTemplate = `
1765
+ GNU AFFERO GENERAL PUBLIC LICENSE
1766
+ Version 3, 19 November 2007
1767
+
1768
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
1769
+ Everyone is permitted to copy and distribute verbatim copies
1770
+ of this license document, but changing it is not allowed.
1771
+
1772
+ Preamble
1773
+
1774
+ The GNU Affero General Public License is a free, copyleft license for
1775
+ software and other kinds of works, specifically designed to ensure
1776
+ cooperation with the community in the case of network server software.
1777
+
1778
+ The licenses for most software and other practical works are designed
1779
+ to take away your freedom to share and change the works. By contrast,
1780
+ our General Public Licenses are intended to guarantee your freedom to
1781
+ share and change all versions of a program--to make sure it remains free
1782
+ software for all its users.
1783
+
1784
+ When we speak of free software, we are referring to freedom, not
1785
+ price. Our General Public Licenses are designed to make sure that you
1786
+ have the freedom to distribute copies of free software (and charge for
1787
+ them if you wish), that you receive source code or can get it if you
1788
+ want it, that you can change the software or use pieces of it in new
1789
+ free programs, and that you know you can do these things.
1790
+
1791
+ Developers that use our General Public Licenses protect your rights
1792
+ with two steps: (1) assert copyright on the software, and (2) offer
1793
+ you this License which gives you legal permission to copy, distribute
1794
+ and/or modify the software.
1795
+
1796
+ A secondary benefit of defending all users' freedom is that
1797
+ improvements made in alternate versions of the program, if they
1798
+ receive widespread use, become available for other developers to
1799
+ incorporate. Many developers of free software are heartened and
1800
+ encouraged by the resulting cooperation. However, in the case of
1801
+ software used on network servers, this result may fail to come about.
1802
+ The GNU General Public License permits making a modified version and
1803
+ letting the public access it on a server without ever releasing its
1804
+ source code to the public.
1805
+
1806
+ The GNU Affero General Public License is designed specifically to
1807
+ ensure that, in such cases, the modified source code becomes available
1808
+ to the community. It requires the operator of a network server to
1809
+ provide the source code of the modified version running there to the
1810
+ users of that server. Therefore, public use of a modified version, on
1811
+ a publicly accessible server, gives the public access to the source
1812
+ code of the modified version.
1813
+
1814
+ An older license, called the Affero General Public License and
1815
+ published by Affero, was designed to accomplish similar goals. This is
1816
+ a different license, not a version of the Affero GPL, but Affero has
1817
+ released a new version of the Affero GPL which permits relicensing under
1818
+ this license.
1819
+
1820
+ The precise terms and conditions for copying, distribution and
1821
+ modification follow.
1822
+
1823
+ TERMS AND CONDITIONS
1824
+
1825
+ 0. Definitions.
1826
+
1827
+ "This License" refers to version 3 of the GNU Affero General Public License.
1828
+
1829
+ "Copyright" also means copyright-like laws that apply to other kinds of
1830
+ works, such as semiconductor masks.
1831
+
1832
+ "The Program" refers to any copyrightable work licensed under this
1833
+ License. Each licensee is addressed as "you". "Licensees" and
1834
+ "recipients" may be individuals or organizations.
1835
+
1836
+ To "modify" a work means to copy from or adapt all or part of the work
1837
+ in a fashion requiring copyright permission, other than the making of an
1838
+ exact copy. The resulting work is called a "modified version" of the
1839
+ earlier work or a work "based on" the earlier work.
1840
+
1841
+ A "covered work" means either the unmodified Program or a work based
1842
+ on the Program.
1843
+
1844
+ To "propagate" a work means to do anything with it that, without
1845
+ permission, would make you directly or secondarily liable for
1846
+ infringement under applicable copyright law, except executing it on a
1847
+ computer or modifying a private copy. Propagation includes copying,
1848
+ distribution (with or without modification), making available to the
1849
+ public, and in some countries other activities as well.
1850
+
1851
+ To "convey" a work means any kind of propagation that enables other
1852
+ parties to make or receive copies. Mere interaction with a user through
1853
+ a computer network, with no transfer of a copy, is not conveying.
1854
+
1855
+ An interactive user interface displays "Appropriate Legal Notices"
1856
+ to the extent that it includes a convenient and prominently visible
1857
+ feature that (1) displays an appropriate copyright notice, and (2)
1858
+ tells the user that there is no warranty for the work (except to the
1859
+ extent that warranties are provided), that licensees may convey the
1860
+ work under this License, and how to view a copy of this License. If
1861
+ the interface presents a list of user commands or options, such as a
1862
+ menu, a prominent item in the list meets this criterion.
1863
+
1864
+ 1. Source Code.
1865
+
1866
+ The "source code" for a work means the preferred form of the work
1867
+ for making modifications to it. "Object code" means any non-source
1868
+ form of a work.
1869
+
1870
+ A "Standard Interface" means an interface that either is an official
1871
+ standard defined by a recognized standards body, or, in the case of
1872
+ interfaces specified for a particular programming language, one that
1873
+ is widely used among developers working in that language.
1874
+
1875
+ The "System Libraries" of an executable work include anything, other
1876
+ than the work as a whole, that (a) is included in the normal form of
1877
+ packaging a Major Component, but which is not part of that Major
1878
+ Component, and (b) serves only to enable use of the work with that
1879
+ Major Component, or to implement a Standard Interface for which an
1880
+ implementation is available to the public in source code form. A
1881
+ "Major Component", in this context, means a major essential component
1882
+ (kernel, window system, and so on) of the specific operating system
1883
+ (if any) on which the executable work runs, or a compiler used to
1884
+ produce the work, or an object code interpreter used to run it.
1885
+
1886
+ The "Corresponding Source" for a work in object code form means all
1887
+ the source code needed to generate, install, and (for an executable
1888
+ work) run the object code and to modify the work, including scripts to
1889
+ control those activities. However, it does not include the work's
1890
+ System Libraries, or general-purpose tools or generally available free
1891
+ programs which are used unmodified in performing those activities but
1892
+ which are not part of the work. For example, Corresponding Source
1893
+ includes interface definition files associated with source files for
1894
+ the work, and the source code for shared libraries and dynamically
1895
+ linked subprograms that the work is specifically designed to require,
1896
+ such as by intimate data communication or control flow between those
1897
+ subprograms and other parts of the work.
1898
+
1899
+ The Corresponding Source need not include anything that users
1900
+ can regenerate automatically from other parts of the Corresponding
1901
+ Source.
1902
+
1903
+ The Corresponding Source for a work in source code form is that
1904
+ same work.
1905
+
1906
+ 2. Basic Permissions.
1907
+
1908
+ All rights granted under this License are granted for the term of
1909
+ copyright on the Program, and are irrevocable provided the stated
1910
+ conditions are met. This License explicitly affirms your unlimited
1911
+ permission to run the unmodified Program. The output from running a
1912
+ covered work is covered by this License only if the output, given its
1913
+ content, constitutes a covered work. This License acknowledges your
1914
+ rights of fair use or other equivalent, as provided by copyright law.
1915
+
1916
+ You may make, run and propagate covered works that you do not
1917
+ convey, without conditions so long as your license otherwise remains
1918
+ in force. You may convey covered works to others for the sole purpose
1919
+ of having them make modifications exclusively for you, or provide you
1920
+ with facilities for running those works, provided that you comply with
1921
+ the terms of this License in conveying all material for which you do
1922
+ not control copyright. Those thus making or running the covered works
1923
+ for you must do so exclusively on your behalf, under your direction
1924
+ and control, on terms that prohibit them from making any copies of
1925
+ your copyrighted material outside their relationship with you.
1926
+
1927
+ Conveying under any other circumstances is permitted solely under
1928
+ the conditions stated below. Sublicensing is not allowed; section 10
1929
+ makes it unnecessary.
1930
+
1931
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
1932
+
1933
+ No covered work shall be deemed part of an effective technological
1934
+ measure under any applicable law fulfilling obligations under article
1935
+ 11 of the WIPO copyright treaty adopted on 20 December 1996, or
1936
+ similar laws prohibiting or restricting circumvention of such
1937
+ measures.
1938
+
1939
+ When you convey a covered work, you waive any legal power to forbid
1940
+ circumvention of technological measures to the extent such circumvention
1941
+ is effected by exercising rights under this License with respect to
1942
+ the covered work, and you disclaim any intention to limit operation or
1943
+ modification of the work as a means of enforcing, against the work's
1944
+ users, your or third parties' legal rights to forbid circumvention of
1945
+ technological measures.
1946
+
1947
+ 4. Conveying Verbatim Copies.
1948
+
1949
+ You may convey verbatim copies of the Program's source code as you
1950
+ receive it, in any medium, provided that you conspicuously and
1951
+ appropriately publish on each copy an appropriate copyright notice;
1952
+ keep intact all notices stating that this License and any
1953
+ non-permissive terms added in accord with section 7 apply to the code;
1954
+ keep intact all notices of the absence of any warranty; and give all
1955
+ recipients a copy of this License along with the Program.
1956
+
1957
+ You may charge any price or no price for each copy that you convey,
1958
+ and you may offer support or warranty protection for a fee.
1959
+
1960
+ 5. Conveying Modified Source Versions.
1961
+
1962
+ You may convey a work based on the Program, or the modifications to
1963
+ produce it from the Program, in the form of source code under the
1964
+ terms of section 4, provided that you also meet all of these conditions:
1965
+
1966
+ a) The work must carry prominent notices stating that you modified
1967
+ it, and giving a relevant date.
1968
+
1969
+ b) The work must carry prominent notices stating that it is
1970
+ released under this License and any conditions added under section
1971
+ 7. This requirement modifies the requirement in section 4 to
1972
+ "keep intact all notices".
1973
+
1974
+ c) You must license the entire work, as a whole, under this
1975
+ License to anyone who comes into possession of a copy. This
1976
+ License will therefore apply, along with any applicable section 7
1977
+ additional terms, to the whole of the work, and all its parts,
1978
+ regardless of how they are packaged. This License gives no
1979
+ permission to license the work in any other way, but it does not
1980
+ invalidate such permission if you have separately received it.
1981
+
1982
+ d) If the work has interactive user interfaces, each must display
1983
+ Appropriate Legal Notices; however, if the Program has interactive
1984
+ interfaces that do not display Appropriate Legal Notices, your
1985
+ work need not make them do so.
1986
+
1987
+ A compilation of a covered work with other separate and independent
1988
+ works, which are not by their nature extensions of the covered work,
1989
+ and which are not combined with it such as to form a larger program,
1990
+ in or on a volume of a storage or distribution medium, is called an
1991
+ "aggregate" if the compilation and its resulting copyright are not
1992
+ used to limit the access or legal rights of the compilation's users
1993
+ beyond what the individual works permit. Inclusion of a covered work
1994
+ in an aggregate does not cause this License to apply to the other
1995
+ parts of the aggregate.
1996
+
1997
+ 6. Conveying Non-Source Forms.
1998
+
1999
+ You may convey a covered work in object code form under the terms
2000
+ of sections 4 and 5, provided that you also convey the
2001
+ machine-readable Corresponding Source under the terms of this License,
2002
+ in one of these ways:
2003
+
2004
+ a) Convey the object code in, or embodied in, a physical product
2005
+ (including a physical distribution medium), accompanied by the
2006
+ Corresponding Source fixed on a durable physical medium
2007
+ customarily used for software interchange.
2008
+
2009
+ b) Convey the object code in, or embodied in, a physical product
2010
+ (including a physical distribution medium), accompanied by a
2011
+ written offer, valid for at least three years and valid for as
2012
+ long as you offer spare parts or customer support for that product
2013
+ model, to give anyone who possesses the object code either (1) a
2014
+ copy of the Corresponding Source for all the software in the
2015
+ product that is covered by this License, on a durable physical
2016
+ medium customarily used for software interchange, for a price no
2017
+ more than your reasonable cost of physically performing this
2018
+ conveying of source, or (2) access to copy the
2019
+ Corresponding Source from a network server at no charge.
2020
+
2021
+ c) Convey individual copies of the object code with a copy of the
2022
+ written offer to provide the Corresponding Source. This
2023
+ alternative is allowed only occasionally and noncommercially, and
2024
+ only if you received the object code with such an offer, in accord
2025
+ with subsection 6b.
2026
+
2027
+ d) Convey the object code by offering access from a designated
2028
+ place (gratis or for a charge), and offer equivalent access to the
2029
+ Corresponding Source in the same way through the same place at no
2030
+ further charge. You need not require recipients to copy the
2031
+ Corresponding Source along with the object code. If the place to
2032
+ copy the object code is a network server, the Corresponding Source
2033
+ may be on a different server (operated by you or a third party)
2034
+ that supports equivalent copying facilities, provided you maintain
2035
+ clear directions next to the object code saying where to find the
2036
+ Corresponding Source. Regardless of what server hosts the
2037
+ Corresponding Source, you remain obligated to ensure that it is
2038
+ available for as long as needed to satisfy these requirements.
2039
+
2040
+ e) Convey the object code using peer-to-peer transmission, provided
2041
+ you inform other peers where the object code and Corresponding
2042
+ Source of the work are being offered to the general public at no
2043
+ charge under subsection 6d.
2044
+
2045
+ A separable portion of the object code, whose source code is excluded
2046
+ from the Corresponding Source as a System Library, need not be
2047
+ included in conveying the object code work.
2048
+
2049
+ A "User Product" is either (1) a "consumer product", which means any
2050
+ tangible personal property which is normally used for personal, family,
2051
+ or household purposes, or (2) anything designed or sold for incorporation
2052
+ into a dwelling. In determining whether a product is a consumer product,
2053
+ doubtful cases shall be resolved in favor of coverage. For a particular
2054
+ product received by a particular user, "normally used" refers to a
2055
+ typical or common use of that class of product, regardless of the status
2056
+ of the particular user or of the way in which the particular user
2057
+ actually uses, or expects or is expected to use, the product. A product
2058
+ is a consumer product regardless of whether the product has substantial
2059
+ commercial, industrial or non-consumer uses, unless such uses represent
2060
+ the only significant mode of use of the product.
2061
+
2062
+ "Installation Information" for a User Product means any methods,
2063
+ procedures, authorization keys, or other information required to install
2064
+ and execute modified versions of a covered work in that User Product from
2065
+ a modified version of its Corresponding Source. The information must
2066
+ suffice to ensure that the continued functioning of the modified object
2067
+ code is in no case prevented or interfered with solely because
2068
+ modification has been made.
2069
+
2070
+ If you convey an object code work under this section in, or with, or
2071
+ specifically for use in, a User Product, and the conveying occurs as
2072
+ part of a transaction in which the right of possession and use of the
2073
+ User Product is transferred to the recipient in perpetuity or for a
2074
+ fixed term (regardless of how the transaction is characterized), the
2075
+ Corresponding Source conveyed under this section must be accompanied
2076
+ by the Installation Information. But this requirement does not apply
2077
+ if neither you nor any third party retains the ability to install
2078
+ modified object code on the User Product (for example, the work has
2079
+ been installed in ROM).
2080
+
2081
+ The requirement to provide Installation Information does not include a
2082
+ requirement to continue to provide support service, warranty, or updates
2083
+ for a work that has been modified or installed by the recipient, or for
2084
+ the User Product in which it has been modified or installed. Access to a
2085
+ network may be denied when the modification itself materially and
2086
+ adversely affects the operation of the network or violates the rules and
2087
+ protocols for communication across the network.
2088
+
2089
+ Corresponding Source conveyed, and Installation Information provided,
2090
+ in accord with this section must be in a format that is publicly
2091
+ documented (and with an implementation available to the public in
2092
+ source code form), and must require no special password or key for
2093
+ unpacking, reading or copying.
2094
+
2095
+ 7. Additional Terms.
2096
+
2097
+ "Additional permissions" are terms that supplement the terms of this
2098
+ License by making exceptions from one or more of its conditions.
2099
+ Additional permissions that are applicable to the entire Program shall
2100
+ be treated as though they were included in this License, to the extent
2101
+ that they are valid under applicable law. If additional permissions
2102
+ apply only to part of the Program, that part may be used separately
2103
+ under those permissions, but the entire Program remains governed by
2104
+ this License without regard to the additional permissions.
2105
+
2106
+ When you convey a copy of a covered work, you may at your option
2107
+ remove any additional permissions from that copy, or from any part of
2108
+ it. (Additional permissions may be written to require their own
2109
+ removal in certain cases when you modify the work.) You may place
2110
+ additional permissions on material, added by you to a covered work,
2111
+ for which you have or can give appropriate copyright permission.
2112
+
2113
+ Notwithstanding any other provision of this License, for material you
2114
+ add to a covered work, you may (if authorized by the copyright holders of
2115
+ that material) supplement the terms of this License with terms:
2116
+
2117
+ a) Disclaiming warranty or limiting liability differently from the
2118
+ terms of sections 15 and 16 of this License; or
2119
+
2120
+ b) Requiring preservation of specified reasonable legal notices or
2121
+ author attributions in that material or in the Appropriate Legal
2122
+ Notices displayed by works containing it; or
2123
+
2124
+ c) Prohibiting misrepresentation of the origin of that material, or
2125
+ requiring that modified versions of such material be marked in
2126
+ reasonable ways as different from the original version; or
2127
+
2128
+ d) Limiting the use for publicity purposes of names of licensors or
2129
+ authors of the material; or
2130
+
2131
+ e) Declining to grant rights under trademark law for use of some
2132
+ trade names, trademarks, or service marks; or
2133
+
2134
+ f) Requiring indemnification of licensors and authors of that
2135
+ material by anyone who conveys the material (or modified versions of
2136
+ it) with contractual assumptions of liability to the recipient, for
2137
+ any liability that these contractual assumptions directly impose on
2138
+ those licensors and authors.
2139
+
2140
+ All other non-permissive additional terms are considered "further
2141
+ restrictions" within the meaning of section 10. If the Program as you
2142
+ received it, or any part of it, contains a notice stating that it is
2143
+ governed by this License along with a term that is a further
2144
+ restriction, you may remove that term. If a license document contains
2145
+ a further restriction but permits relicensing or conveying under this
2146
+ License, you may add to a covered work material governed by the terms
2147
+ of that license document, provided that the further restriction does
2148
+ not survive such relicensing or conveying.
2149
+
2150
+ If you add terms to a covered work in accord with this section, you
2151
+ must place, in the relevant source files, a statement of the
2152
+ additional terms that apply to those files, or a notice indicating
2153
+ where to find the applicable terms.
2154
+
2155
+ Additional terms, permissive or non-permissive, may be stated in the
2156
+ form of a separately written license, or stated as exceptions;
2157
+ the above requirements apply either way.
2158
+
2159
+ 8. Termination.
2160
+
2161
+ You may not propagate or modify a covered work except as expressly
2162
+ provided under this License. Any attempt otherwise to propagate or
2163
+ modify it is void, and will automatically terminate your rights under
2164
+ this License (including any patent licenses granted under the third
2165
+ paragraph of section 11).
2166
+
2167
+ However, if you cease all violation of this License, then your
2168
+ license from a particular copyright holder is reinstated (a)
2169
+ provisionally, unless and until the copyright holder explicitly and
2170
+ finally terminates your license, and (b) permanently, if the copyright
2171
+ holder fails to notify you of the violation by some reasonable means
2172
+ prior to 60 days after the cessation.
2173
+
2174
+ Moreover, your license from a particular copyright holder is
2175
+ reinstated permanently if the copyright holder notifies you of the
2176
+ violation by some reasonable means, this is the first time you have
2177
+ received notice of violation of this License (for any work) from that
2178
+ copyright holder, and you cure the violation prior to 30 days after
2179
+ your receipt of the notice.
2180
+
2181
+ Termination of your rights under this section does not terminate the
2182
+ licenses of parties who have received copies or rights from you under
2183
+ this License. If your rights have been terminated and not permanently
2184
+ reinstated, you do not qualify to receive new licenses for the same
2185
+ material under section 10.
2186
+
2187
+ 9. Acceptance Not Required for Having Copies.
2188
+
2189
+ You are not required to accept this License in order to receive or
2190
+ run a copy of the Program. Ancillary propagation of a covered work
2191
+ occurring solely as a consequence of using peer-to-peer transmission
2192
+ to receive a copy likewise does not require acceptance. However,
2193
+ nothing other than this License grants you permission to propagate or
2194
+ modify any covered work. These actions infringe copyright if you do
2195
+ not accept this License. Therefore, by modifying or propagating a
2196
+ covered work, you indicate your acceptance of this License to do so.
2197
+
2198
+ 10. Automatic Licensing of Downstream Recipients.
2199
+
2200
+ Each time you convey a covered work, the recipient automatically
2201
+ receives a license from the original licensors, to run, modify and
2202
+ propagate that work, subject to this License. You are not responsible
2203
+ for enforcing compliance by third parties with this License.
2204
+
2205
+ An "entity transaction" is a transaction transferring control of an
2206
+ organization, or substantially all assets of one, or subdividing an
2207
+ organization, or merging organizations. If propagation of a covered
2208
+ work results from an entity transaction, each party to that
2209
+ transaction who receives a copy of the work also receives whatever
2210
+ licenses to the work the party's predecessor in interest had or could
2211
+ give under the previous paragraph, plus a right to possession of the
2212
+ Corresponding Source of the work from the predecessor in interest, if
2213
+ the predecessor has it or can get it with reasonable efforts.
2214
+
2215
+ You may not impose any further restrictions on the exercise of the
2216
+ rights granted or affirmed under this License. For example, you may
2217
+ not impose a license fee, royalty, or other charge for exercise of
2218
+ rights granted under this License, and you may not initiate litigation
2219
+ (including a cross-claim or counterclaim in a lawsuit) alleging that
2220
+ any patent claim is infringed by making, using, selling, offering for
2221
+ sale, or importing the Program or any portion of it.
2222
+
2223
+ 11. Patents.
2224
+
2225
+ A "contributor" is a copyright holder who authorizes use under this
2226
+ License of the Program or a work on which the Program is based. The
2227
+ work thus licensed is called the contributor's "contributor version".
2228
+
2229
+ A contributor's "essential patent claims" are all patent claims
2230
+ owned or controlled by the contributor, whether already acquired or
2231
+ hereafter acquired, that would be infringed by some manner, permitted
2232
+ by this License, of making, using, or selling its contributor version,
2233
+ but do not include claims that would be infringed only as a
2234
+ consequence of further modification of the contributor version. For
2235
+ purposes of this definition, "control" includes the right to grant
2236
+ patent sublicenses in a manner consistent with the requirements of
2237
+ this License.
2238
+
2239
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
2240
+ patent license under the contributor's essential patent claims, to
2241
+ make, use, sell, offer for sale, import and otherwise run, modify and
2242
+ propagate the contents of its contributor version.
2243
+
2244
+ In the following three paragraphs, a "patent license" is any express
2245
+ agreement or commitment, however denominated, not to enforce a patent
2246
+ (such as an express permission to practice a patent or covenant not to
2247
+ sue for patent infringement). To "grant" such a patent license to a
2248
+ party means to make such an agreement or commitment not to enforce a
2249
+ patent against the party.
2250
+
2251
+ If you convey a covered work, knowingly relying on a patent license,
2252
+ and the Corresponding Source of the work is not available for anyone
2253
+ to copy, free of charge and under the terms of this License, through a
2254
+ publicly available network server or other readily accessible means,
2255
+ then you must either (1) cause the Corresponding Source to be so
2256
+ available, or (2) arrange to deprive yourself of the benefit of the
2257
+ patent license for this particular work, or (3) arrange, in a manner
2258
+ consistent with the requirements of this License, to extend the patent
2259
+ license to downstream recipients. "Knowingly relying" means you have
2260
+ actual knowledge that, but for the patent license, your conveying the
2261
+ covered work in a country, or your recipient's use of the covered work
2262
+ in a country, would infringe one or more identifiable patents in that
2263
+ country that you have reason to believe are valid.
2264
+
2265
+ If, pursuant to or in connection with a single transaction or
2266
+ arrangement, you convey, or propagate by procuring conveyance of, a
2267
+ covered work, and grant a patent license to some of the parties
2268
+ receiving the covered work authorizing them to use, propagate, modify
2269
+ or convey a specific copy of the covered work, then the patent license
2270
+ you grant is automatically extended to all recipients of the covered
2271
+ work and works based on it.
2272
+
2273
+ A patent license is "discriminatory" if it does not include within
2274
+ the scope of its coverage, prohibits the exercise of, or is
2275
+ conditioned on the non-exercise of one or more of the rights that are
2276
+ specifically granted under this License. You may not convey a covered
2277
+ work if you are a party to an arrangement with a third party that is
2278
+ in the business of distributing software, under which you make payment
2279
+ to the third party based on the extent of your activity of conveying
2280
+ the work, and under which the third party grants, to any of the
2281
+ parties who would receive the covered work from you, a discriminatory
2282
+ patent license (a) in connection with copies of the covered work
2283
+ conveyed by you (or copies made from those copies), or (b) primarily
2284
+ for and in connection with specific products or compilations that
2285
+ contain the covered work, unless you entered into that arrangement,
2286
+ or that patent license was granted, prior to 28 March 2007.
2287
+
2288
+ Nothing in this License shall be construed as excluding or limiting
2289
+ any implied license or other defenses to infringement that may
2290
+ otherwise be available to you under applicable patent law.
2291
+
2292
+ 12. No Surrender of Others' Freedom.
2293
+
2294
+ If conditions are imposed on you (whether by court order, agreement or
2295
+ otherwise) that contradict the conditions of this License, they do not
2296
+ excuse you from the conditions of this License. If you cannot convey a
2297
+ covered work so as to satisfy simultaneously your obligations under this
2298
+ License and any other pertinent obligations, then as a consequence you may
2299
+ not convey it at all. For example, if you agree to terms that obligate you
2300
+ to collect a royalty for further conveying from those to whom you convey
2301
+ the Program, the only way you could satisfy both those terms and this
2302
+ License would be to refrain entirely from conveying the Program.
2303
+
2304
+ 13. Remote Network Interaction; Use with the GNU General Public License.
2305
+
2306
+ Notwithstanding any other provision of this License, if you modify the
2307
+ Program, your modified version must prominently offer all users
2308
+ interacting with it remotely through a computer network (if your version
2309
+ supports such interaction) an opportunity to receive the Corresponding
2310
+ Source of your version by providing access to the Corresponding Source
2311
+ from a network server at no charge, through some standard or customary
2312
+ means of facilitating copying of software. This Corresponding Source
2313
+ shall include the Corresponding Source for any work covered by version 3
2314
+ of the GNU General Public License that is incorporated pursuant to the
2315
+ following paragraph.
2316
+
2317
+ Notwithstanding any other provision of this License, you have
2318
+ permission to link or combine any covered work with a work licensed
2319
+ under version 3 of the GNU General Public License into a single
2320
+ combined work, and to convey the resulting work. The terms of this
2321
+ License will continue to apply to the part which is the covered work,
2322
+ but the work with which it is combined will remain governed by version
2323
+ 3 of the GNU General Public License.
2324
+
2325
+ 14. Revised Versions of this License.
2326
+
2327
+ The Free Software Foundation may publish revised and/or new versions of
2328
+ the GNU Affero General Public License from time to time. Such new versions
2329
+ will be similar in spirit to the present version, but may differ in detail to
2330
+ address new problems or concerns.
2331
+
2332
+ Each version is given a distinguishing version number. If the
2333
+ Program specifies that a certain numbered version of the GNU Affero General
2334
+ Public License "or any later version" applies to it, you have the
2335
+ option of following the terms and conditions either of that numbered
2336
+ version or of any later version published by the Free Software
2337
+ Foundation. If the Program does not specify a version number of the
2338
+ GNU Affero General Public License, you may choose any version ever published
2339
+ by the Free Software Foundation.
2340
+
2341
+ If the Program specifies that a proxy can decide which future
2342
+ versions of the GNU Affero General Public License can be used, that proxy's
2343
+ public statement of acceptance of a version permanently authorizes you
2344
+ to choose that version for the Program.
2345
+
2346
+ Later license versions may give you additional or different
2347
+ permissions. However, no additional obligations are imposed on any
2348
+ author or copyright holder as a result of your choosing to follow a
2349
+ later version.
2350
+
2351
+ 15. Disclaimer of Warranty.
2352
+
2353
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
2354
+ APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
2355
+ HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
2356
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
2357
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2358
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
2359
+ IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
2360
+ ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
2361
+
2362
+ 16. Limitation of Liability.
2363
+
2364
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
2365
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
2366
+ THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
2367
+ GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
2368
+ USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
2369
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
2370
+ PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
2371
+ EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
2372
+ SUCH DAMAGES.
2373
+
2374
+ 17. Interpretation of Sections 15 and 16.
2375
+
2376
+ If the disclaimer of warranty and limitation of liability provided
2377
+ above cannot be given local legal effect according to their terms,
2378
+ reviewing courts shall apply local law that most closely approximates
2379
+ an absolute waiver of all civil liability in connection with the
2380
+ Program, unless a warranty or assumption of liability accompanies a
2381
+ copy of the Program in return for a fee.
2382
+
2383
+ END OF TERMS AND CONDITIONS
2384
+
2385
+ How to Apply These Terms to Your New Programs
2386
+
2387
+ If you develop a new program, and you want it to be of the greatest
2388
+ possible use to the public, the best way to achieve this is to make it
2389
+ free software which everyone can redistribute and change under these terms.
2390
+
2391
+ To do so, attach the following notices to the program. It is safest
2392
+ to attach them to the start of each source file to most effectively
2393
+ state the exclusion of warranty; and each file should have at least
2394
+ the "copyright" line and a pointer to where the full notice is found.
2395
+
2396
+ <one line to give the program's name and a brief idea of what it does.>
2397
+ Copyright (C) <year> <name of author>
2398
+
2399
+ This program is free software: you can redistribute it and/or modify
2400
+ it under the terms of the GNU Affero General Public License as published
2401
+ by the Free Software Foundation, either version 3 of the License, or
2402
+ (at your option) any later version.
2403
+
2404
+ This program is distributed in the hope that it will be useful,
2405
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2406
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2407
+ GNU Affero General Public License for more details.
2408
+
2409
+ You should have received a copy of the GNU Affero General Public License
2410
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
2411
+
2412
+ Also add information on how to contact you by electronic and paper mail.
2413
+
2414
+ If your software can interact with users remotely through a computer
2415
+ network, you should also make sure that it provides a way for users to
2416
+ get its source. For example, if your program is a web application, its
2417
+ interface could display a "Source" link that leads users to an archive
2418
+ of the code. There are many ways you could offer source, and different
2419
+ solutions will be better for different programs; see section 13 for the
2420
+ specific requirements.
2421
+
2422
+ You should also get your employer (if you work as a programmer) or school,
2423
+ if any, to sign a "copyright disclaimer" for the program, if necessary.
2424
+ For more information on this, and how to apply and follow the GNU AGPL, see
2425
+ <https://www.gnu.org/licenses/>.
2426
+ `;
2427
+ //#endregion
2428
+ //#region src/templates/boilerplate/main.tsx.ts
2429
+ const mainTsxTemplate = tsx`
2430
+ import { startConnect } from "@powerhousedao/connect";
2431
+ import * as localPackage from "./index.js";
2432
+
2433
+ startConnect(localPackage);
2434
+ `.raw;
2435
+ //#endregion
2436
+ //#region src/templates/boilerplate/mcp.json.ts
2437
+ const mcpTemplate = json`
2438
+ {
2439
+ "mcpServers": {
2440
+ "reactor-mcp": {
2441
+ "type": "http",
2442
+ "url": "http://localhost:4001/mcp"
2443
+ }
2444
+ }
2445
+ }
2446
+ `.raw;
2447
+ //#endregion
2448
+ //#region src/templates/boilerplate/npmrc.ts
2449
+ const npmrcTemplate = `@jsr:registry=https://npm.jsr.io`;
2450
+ //#endregion
2451
+ //#region src/templates/boilerplate/package.json.ts
2452
+ const exportsTemplate = json`
2453
+ ".": {
2454
+ "types": "./dist/index.d.ts",
2455
+ "browser": "./dist/browser/index.js",
2456
+ "node": "./dist/node/index.mjs"
2457
+ },
2458
+ "./document-models": {
2459
+ "types": "./dist/document-models/index.d.ts",
2460
+ "browser": "./dist/browser/document-models/index.js",
2461
+ "node": "./dist/node/document-models/index.mjs"
2462
+ },
2463
+ "./document-models/*": {
2464
+ "types": "./dist/document-models/*/index.d.ts",
2465
+ "browser": "./dist/browser/document-models/*/index.js",
2466
+ "node": "./dist/node/document-models/*/index.mjs"
2467
+ },
2468
+ "./editors": {
2469
+ "types": "./dist/editors/index.d.ts",
2470
+ "browser": "./dist/browser/editors/index.js",
2471
+ "node": "./dist/node/editors/index.mjs"
2472
+ },
2473
+ "./editors/*": {
2474
+ "types": "./dist/editors/*/index.d.ts",
2475
+ "browser": "./dist/browser/editors/*/index.js",
2476
+ "node": "./dist/node/editors/*/index.mjs"
2477
+ },
2478
+ "./subgraphs": {
2479
+ "types": "./dist/subgraphs/index.d.ts",
2480
+ "browser": "./dist/browser/subgraphs/index.js",
2481
+ "node": "./dist/node/subgraphs/index.mjs"
2482
+ },
2483
+ "./processors": {
2484
+ "types": "./dist/processors/index.d.ts",
2485
+ "browser": "./dist/browser/processors/index.js",
2486
+ "node": "./dist/node/processors/index.mjs"
2487
+ },
2488
+ "./manifest": "./dist/powerhouse.manifest.json",
2489
+ "./style.css": "./dist/style.css"
2490
+ `.raw;
2491
+ const scriptsTemplate = json`
2492
+ "test": "vitest run",
2493
+ "test:watch": "vitest",
2494
+ "lint": "eslint --config eslint.config.js --cache --cache-strategy content",
2495
+ "lint:fix": "npm run lint -- --fix",
2496
+ "tsc": "tsc",
2497
+ "tsc:watch": "tsc --watch",
2498
+ "check-circular-imports": "npx dpdm -T ./index.ts",
2499
+ "generate": "ph-cli generate",
2500
+ "connect": "ph-cli connect",
2501
+ "build": "ph-cli build",
2502
+ "reactor": "ph-cli reactor",
2503
+ "service": "ph-cli service",
2504
+ "vetra": "ph-cli vetra",
2505
+ "service-startup": "bash ./node_modules/@powerhousedao/ph-cli/dist/scripts/service-startup.sh",
2506
+ "service-unstartup": "bash ./node_modules/@powerhousedao/ph-cli/dist/scripts/service-unstartup.sh"
2507
+ `.raw;
2508
+ const dependenciesTemplate = (versionedDependencies) => json`
2509
+ ${versionedDependencies.join(",\n")},
2510
+ "@powerhousedao/document-engineering": "1.40.1",
2511
+ "graphql": "^16.10.0",
2512
+ "graphql-tag": "^2.12.6",
2513
+ "zod": "^4.3.5",
2514
+ "react": "^19.2.3",
2515
+ "react-dom": "^19.2.3"
2516
+ `.raw;
2517
+ const devDependenciesTemplate = (versionedDevDependencies) => json`
2518
+ ${versionedDevDependencies.join(",\n")},
2519
+ "@electric-sql/pglite": "0.3.15",
2520
+ "@electric-sql/pglite-tools": "0.2.20",
2521
+ "@eslint/js": "^9.38.0",
2522
+ "@tailwindcss/cli": "^4.1.18",
2523
+ "@types/node": "^24.9.2",
2524
+ "@types/react": "^19.2.3",
2525
+ "eslint": "^9.38.0",
2526
+ "eslint-plugin-react": "^7.37.5",
2527
+ "eslint-plugin-react-hooks": "^7.0.1",
2528
+ "eslint-config-prettier": "^10.1.8",
2529
+ "eslint-plugin-prettier": "^5.5.4",
2530
+ "globals": "^16.4.0",
2531
+ "tailwindcss": "^4.1.16",
2532
+ "typescript": "^5.9.3",
2533
+ "typescript-eslint": "^8.46.2",
2534
+ "vitest": "4.1.1",
2535
+ "@vitejs/plugin-react": "6.0.1",
2536
+ "vite-tsconfig-paths": "6.1.1"
2537
+ `.raw;
2538
+ const packageJsonTemplate = (projectName, versionedDependencies, versionedDevDependencies) => json`
2539
+ {
2540
+ "name": "${projectName}",
2541
+ "version": "1.0.0",
2542
+ "license": "AGPL-3.0-only",
2543
+ "type": "module",
2544
+ "files": [
2545
+ "/dist"
2546
+ ],
2547
+ "exports": {
2548
+ ${exportsTemplate}
2549
+ },
2550
+ "scripts": {
2551
+ ${scriptsTemplate}
2552
+ },
2553
+ "dependencies": {
2554
+ ${dependenciesTemplate(versionedDependencies)}
2555
+ },
2556
+ "devDependencies": {
2557
+ ${devDependenciesTemplate(versionedDevDependencies)}
2558
+ }
2559
+ }
2560
+ `.raw;
2561
+ //#endregion
2562
+ //#region src/templates/boilerplate/package.json.legacy.ts
2563
+ const packageJsonScriptsTemplate = {
2564
+ build: "npm run tsc && npm run tailwind",
2565
+ test: "vitest run",
2566
+ "test:watch": "vitest",
2567
+ lint: "eslint --config eslint.config.js --cache --cache-strategy content",
2568
+ "lint:fix": "npm run lint -- --fix",
2569
+ tsc: "tsc",
2570
+ "tsc:watch": "tsc --watch",
2571
+ tailwind: "pnpm exec tailwindcss -i ./style.css -o ./dist/style.css",
2572
+ prepublishOnly: "npm run build",
2573
+ "check-circular-imports": "npx dpdm -T ./index.ts",
2574
+ generate: "ph-cli generate",
2575
+ connect: "ph-cli connect",
2576
+ reactor: "ph-cli reactor",
2577
+ service: "ph-cli service",
2578
+ vetra: "ph-cli vetra",
2579
+ migrate: "ph-cli migrate",
2580
+ "service-startup": "bash ./node_modules/@powerhousedao/ph-cli/dist/scripts/service-startup.sh",
2581
+ "service-unstartup": "bash ./node_modules/@powerhousedao/ph-cli/dist/scripts/service-unstartup.sh"
2582
+ };
2583
+ const packageJsonExportsTemplate = {
2584
+ ".": {
2585
+ types: "./dist/index.d.ts",
2586
+ default: "./dist/index.js"
2587
+ },
2588
+ "./document-models": {
2589
+ types: "./dist/document-models/index.d.ts",
2590
+ default: "./dist/document-models/index.js"
2591
+ },
2592
+ "./editors": {
2593
+ types: "./dist/editors/index.d.ts",
2594
+ default: "./dist/editors/index.js"
2595
+ },
2596
+ "./document-models/*": {
2597
+ types: "./dist/document-models/*/index.d.ts",
2598
+ default: "./dist/document-models/*/index.js"
2599
+ },
2600
+ "./editors/*": {
2601
+ types: "./dist/editors/*/index.d.ts",
2602
+ default: "./dist/editors/*/index.js"
2603
+ },
2604
+ "./subgraphs": {
2605
+ types: "./dist/subgraphs/index.d.ts",
2606
+ default: "./dist/subgraphs/index.js"
2607
+ },
2608
+ "./processors": {
2609
+ types: "./dist/processors/index.d.ts",
2610
+ default: "./dist/processors/index.js"
2611
+ },
2612
+ "./manifest": { default: "./dist/powerhouse.manifest.json" },
2613
+ "./style.css": "./dist/style.css"
2614
+ };
2615
+ //#endregion
2616
+ //#region src/templates/boilerplate/powerhouse.config.json.ts
2617
+ function makeVetraConfigField(vetraDriveUrl) {
2618
+ if (!vetraDriveUrl) return "";
2619
+ return json`
2620
+ ,
2621
+ "vetra": {
2622
+ "driveId": "${vetraDriveUrl.split("/").pop() ?? ""}",
2623
+ "driveUrl": "${vetraDriveUrl}"
2624
+ }
2625
+ `.raw;
2626
+ }
2627
+ async function buildPowerhouseConfigTemplate(args) {
2628
+ return json`
2629
+ {
2630
+ "documentModelsDir": "./document-models",
2631
+ "editorsDir": "./editors",
2632
+ "processorsDir": "./processors",
2633
+ "subgraphsDir": "./subgraphs",
2634
+ "studio": {
2635
+ "port": 3000
2636
+ },
2637
+ "reactor": {
2638
+ "port": 4001
2639
+ },
2640
+ "packages": [
2641
+ ]${makeVetraConfigField(args.remoteDrive)}
2642
+ }
2643
+ `.raw;
2644
+ }
2645
+ //#endregion
2646
+ //#region src/templates/boilerplate/powerhouse.manifest.json.ts
2647
+ const ManifestTemplate = (projectName) => json`
2648
+ {
2649
+ "name": "${projectName}",
2650
+ "description": "",
2651
+ "category": "",
2652
+ "publisher": {
2653
+ "name": "",
2654
+ "url": ""
2655
+ },
2656
+ "documentModels": [],
2657
+ "editors": [],
2658
+ "apps": [],
2659
+ "subgraphs": [],
2660
+ "importScripts": []
2661
+ }
2662
+
2663
+ `.raw;
2664
+ //#endregion
2665
+ //#region src/templates/boilerplate/README.md.ts
2666
+ const readmeTemplate = md`
2667
+ # Document Model Boilerplate
2668
+
2669
+ This Document Model Boilerplate provides code generation for scaffolding editors and models.
2670
+ It ensures compatibility with host applications like Connect and the Reactors for seamless document model and editor integration.
2671
+
2672
+ ## Standard Document Model Workflow with help of the boilerplate.
2673
+
2674
+ This tutorial will guide you through the process of creating a new document model using the Document Model Editor in the Connect app.
2675
+
2676
+ <details>
2677
+ <summary>Available NPM commands</summary>
2678
+
2679
+ - \`generate\`: Updates the generated code according to the JSON spec and GraphQL schema of your document model, made in Connect.
2680
+ - \`lint\`: Checks for errors with ESLint and TypeScript checking.
2681
+ - \`format\`: Formats the code using Prettier.
2682
+ - \`build\`: Builds the library project using Vite.
2683
+ - \`storybook\`: Starts Storybook in development mode.
2684
+ - \`build-storybook\`: Builds Storybook.
2685
+ - \`test\`: Runs Jest for testing.
2686
+
2687
+ </details>
2688
+
2689
+ ### 1. Defining Your Document Model GraphQL Schema
2690
+
2691
+ Start by creating your own 'Powerhouse Project' (Document model + editor).
2692
+
2693
+ Step 1: Run the following command to set up your project inside this directory:
2694
+
2695
+ ~~~bash
2696
+ npm create document-model-lib
2697
+ ~~~
2698
+
2699
+ Step 2: Use the Document Model Editor in the Connect app
2700
+
2701
+ The following command gives you access to all the powerhouse CLI tools available, install it globally if you are a poweruser.
2702
+
2703
+ ~~~bash
2704
+ npm install ph-cmd
2705
+ ~~~
2706
+
2707
+ Now you are able to launch Connect in Studio Mode (Locally):
2708
+
2709
+ ~~~bash
2710
+ npm run connect
2711
+ ~~~
2712
+
2713
+ Open the 'Document Model' creator at the bottom of connect to define your document mode with it's GraphQL Schema Definition.
2714
+ This schema will define the structure and fields for your document model using GraphQL.
2715
+ Follow one of our tutorials on Academy to get familiar with the process.
2716
+
2717
+ ### 2. Defining Document Model Operations
2718
+
2719
+ Using the Document Model Operations Editor, define the operations for your document model and their GraphQL counterparts.
2720
+ These operations will handle state changes within your document model.
2721
+
2722
+ **Best Practices:**
2723
+
2724
+ - Clearly define CRUD operations (Create, Read, Update, Delete).
2725
+ - Use GraphQL input types to specify the parameters for each operation.
2726
+ - Ensure that operations align with user intent to maintain a clean and understandable API.
2727
+
2728
+ ### 3. Generating Scaffolding Code
2729
+
2730
+ Export your document model as a .zip file from Connect.
2731
+ Import the .zip file into your project directory created in Step 1.
2732
+ Run the following command to generate the scaffolding code:
2733
+
2734
+ ~~~bash
2735
+ npm run generate YourModelName.phdm.zip
2736
+ ~~~
2737
+
2738
+ This will create a new directory under /document-models containing:
2739
+
2740
+ JSON file with the document model specification.
2741
+ GraphQL file with state and operation schemas.
2742
+ A gen/ folder with autogenerated code.
2743
+ A src/ folder for your custom code implementation.
2744
+
2745
+ ### 4. Implementing Reducer Code and Unit Tests
2746
+
2747
+ Navigate to the reducer directory:
2748
+
2749
+ ~~~bash
2750
+ cd document-models/"YourModelName"/src/reducers
2751
+ ~~~
2752
+
2753
+ Implement the reducer functions for each document model operation. These functions will handle state transitions.
2754
+
2755
+ Add utility functions in:
2756
+
2757
+ ~~~bash
2758
+ document-models/"YourModelName"/src/utils.ts
2759
+ ~~~
2760
+
2761
+ Write unit tests to ensure the correctness of your reducers:
2762
+
2763
+ Test files should be located in:
2764
+
2765
+ ~~~bash
2766
+ document-models/"YourModelName"/src/reducers/tests
2767
+ ~~~
2768
+
2769
+ Run the tests:
2770
+
2771
+ ~~~bash
2772
+ npm test
2773
+ ~~~
2774
+
2775
+ Test the editor functionality:
2776
+
2777
+ ~~~bash
2778
+ npm run connect
2779
+ ~~~
2780
+
2781
+ ### 5. Implementing Document Editors
2782
+
2783
+ Generate the editor template for your document model:
2784
+
2785
+ ~~~bash
2786
+ npm run generate -- --editor YourModelName --document-types powerhouse/YourModelName
2787
+ ~~~
2788
+
2789
+ The --editor flag specifies the name of your document model.
2790
+ The --document-types flag links the editor to your document model type.
2791
+ After generation:
2792
+
2793
+ Open the editor template:
2794
+
2795
+ ~~~bash
2796
+ editors/YourModelName/editor.tsx
2797
+ ~~~
2798
+
2799
+ Customize the editor interface to suit your document model.
2800
+
2801
+ ### 6. Testing the Document Editor
2802
+
2803
+ Run the Connect app to test your document editor:
2804
+
2805
+ ~~~bash
2806
+ npm run connect
2807
+ ~~~
2808
+
2809
+ Verify that the editor functions as expected.
2810
+ Perform end-to-end testing to ensure smooth integration between the document model and its editor.
2811
+
2812
+ ### 7. Adding a Manifest File
2813
+
2814
+ Create a manifest file to describe your document model and editor. This enables proper integration with the host application.
2815
+
2816
+ **Example manifest.json:**
2817
+
2818
+ ~~~json
2819
+ {
2820
+ "name": "your-model-name",
2821
+ "description": "A brief description of your document model.",
2822
+ "category": "your-category", // e.g., "Finance", "People Ops", "Legal"
2823
+ "publisher": {
2824
+ "name": "your-publisher-name",
2825
+ "url": "your-publisher-url"
2826
+ },
2827
+ "documentModels": [
2828
+ {
2829
+ "id": "your-model-id",
2830
+ "name": "your-model-name"
2831
+ }
2832
+ ],
2833
+ "editors": [
2834
+ {
2835
+ "id": "your-editor-id",
2836
+ "name": "your-editor-name",
2837
+ "documentTypes": ["your-model-id"]
2838
+ }
2839
+ ]
2840
+ }
2841
+ ~~~
2842
+
2843
+ ### Steps to finalize:
2844
+
2845
+ Place the manifest file at your project root.
2846
+ Update your index.js to export your modules and include the new document model and editor.
2847
+
2848
+ ### Final Thoughts
2849
+
2850
+ You've now successfully created a Document Model and its corresponding Editor using the Connect app!
2851
+
2852
+ Next Steps:
2853
+
2854
+ - Expand functionality: Add more operations or complex logic to your document model.
2855
+ - Improve UX: Enhance the document editor for a smoother user experience.
2856
+ - Integrate with other systems: Use APIs or GraphQL to connect your document model with external services.
2857
+ `.raw;
2858
+ //#endregion
2859
+ //#region src/templates/boilerplate/style.css.ts
2860
+ const styleTemplate = css`
2861
+ @import "tailwindcss";
2862
+ @import "@powerhousedao/design-system/theme.css";
2863
+ @import "@powerhousedao/connect/style.css";
2864
+
2865
+ @theme {
2866
+ /* You can customize the theme by overriding the theme variables here */
2867
+ /* See https://tailwindcss.com/docs/theme#using-a-custom-theme for details */
2868
+
2869
+ /* If you would prefer to use plain css, add your styles below this @theme tag as you normally would */
2870
+
2871
+ /* A sensible CSS reset is applied by default. If you would prefer to use a different reset or none at all, uncomment the following line */
2872
+
2873
+ /* --*: initial; */
2874
+ }
2875
+ `.raw;
2876
+ //#endregion
2877
+ //#region src/templates/boilerplate/subgraphs/index.ts
2878
+ const subgraphsIndexTemplate = "";
2879
+ //#endregion
2880
+ //#region src/templates/boilerplate/tsconfig.json.ts
2881
+ const tsconfigPathsTemplate = json`
2882
+ "document-models": [
2883
+ "./document-models/index.ts"
2884
+ ],
2885
+ "document-models/*": [
2886
+ "./document-models/*/index.ts"
2887
+ ],
2888
+ "editors": [
2889
+ "./editors/index.ts"
2890
+ ],
2891
+ "editors/*": [
2892
+ "./editors/*/index.ts"
2893
+ ],
2894
+ "processors/*": [
2895
+ "./processors/*/index.ts"
2896
+ ],
2897
+ "subgraphs": [
2898
+ "./subgraphs/index.ts"
2899
+ ],
2900
+ "subgraphs/*": [
2901
+ "./subgraphs/*/index.ts"
2902
+ ]`.raw;
2903
+ const tsConfigTemplate = json`
2904
+ {
2905
+ "compilerOptions": {
2906
+ "outDir": "./dist",
2907
+ "rootDir": ".",
2908
+ // paths for easy access to project modules
2909
+ "paths": {
2910
+ ${tsconfigPathsTemplate}
2911
+ },
2912
+ "module": "nodenext",
2913
+ "moduleDetection": "force",
2914
+ "target": "esnext",
2915
+ "jsx": "react-jsx",
2916
+ "types": ["node", "vitest/globals"],
2917
+ "lib": ["ESNext", "dom", "dom.iterable"],
2918
+ "declaration": true,
2919
+ "declarationMap": true,
2920
+ "emitDeclarationOnly": true,
2921
+ "strict": true,
2922
+ "verbatimModuleSyntax": true,
2923
+ "isolatedModules": true,
2924
+ "noUncheckedSideEffectImports": true,
2925
+ "skipLibCheck": true
2926
+ },
2927
+ "include": ["**/*", "./powerhouse.manifest.json"],
2928
+ "exclude": ["dist", "node_modules", ".ph"]
2929
+ }
2930
+ `.raw;
2931
+ //#endregion
2932
+ //#region src/templates/boilerplate/vite.config.ts.ts
2933
+ const viteConfigTemplate = ts`
2934
+ import { getConnectBaseViteConfig } from "@powerhousedao/builder-tools";
2935
+ import { defineConfig, mergeConfig, type UserConfig } from "vite";
2936
+
2937
+ export default defineConfig(({ mode }) => {
2938
+ const baseConnectViteConfig = getConnectBaseViteConfig({
2939
+ mode,
2940
+ dirname: import.meta.dirname,
2941
+ });
2942
+
2943
+ const additionalViteConfig: UserConfig = {
2944
+ // add your own vite config here
2945
+ };
2946
+
2947
+ const config = mergeConfig(baseConnectViteConfig, additionalViteConfig);
2948
+
2949
+ return config;
2950
+ });
2951
+ `;
2952
+ //#endregion
2953
+ //#region src/templates/boilerplate/vitest.config.ts.ts
2954
+ const vitestConfigTemplate = ts`
2955
+ import { defineConfig } from "vitest/config";
2956
+ import react from "@vitejs/plugin-react";
2957
+ import tsconfigPaths from "vite-tsconfig-paths";
2958
+
2959
+ export default defineConfig({
2960
+ test: {
2961
+ globals: true,
2962
+ },
2963
+ plugins: [tsconfigPaths(), react()],
2964
+ });
2965
+
2966
+ `;
2967
+ //#endregion
2968
+ //#region src/templates/cli-docs/docs-from-cli-help.ts
2969
+ function groupHelpTopicsByCategory(helpTopics) {
2970
+ const helpTopicsByCategory = {};
2971
+ for (const helpTopic of helpTopics) if (!helpTopicsByCategory[helpTopic.category]) helpTopicsByCategory[helpTopic.category] = [helpTopic];
2972
+ else helpTopicsByCategory[helpTopic.category]?.push(helpTopic);
2973
+ return helpTopicsByCategory;
2974
+ }
2975
+ function makeTableOfContents(commandsHelpInfo) {
2976
+ const commandNames = commandsHelpInfo.map(({ name }) => name);
2977
+ const tableOfContentsEntries = [];
2978
+ for (const name of commandNames) tableOfContentsEntries.push(`- [${capitalCase(name)}](#${kebabCase(name)})\n`);
2979
+ return tableOfContentsEntries.join("");
2980
+ }
2981
+ function makeDefaultsDescriptors(defaults) {
2982
+ return defaults.filter((d) => d !== "optional" && d !== "[...optional]").map((d) => {
2983
+ const [label, ...rest] = d.split(":").map((s) => s.trim());
2984
+ return `**${label}**: \`${rest.join("")}\``;
2985
+ });
2986
+ }
2987
+ function makeRequiredDescriptor(defaults) {
2988
+ if (defaults.includes("optional") || defaults.includes("[...optional]") || defaults.some((d) => d.includes("default"))) return "";
2989
+ return "*[required]*";
2990
+ }
2991
+ function makeHeadingFromUsage(usage) {
2992
+ if (usage.includes("--")) return `#### ${capitalCase(usage.split(" ")[0].replace("--", ""))}`;
2993
+ return `#### ${capitalCase(usage.replace("[", "").replace("]", ""))}`;
2994
+ }
2995
+ function makeCommandHelpTopicDocs(helpTopic) {
2996
+ const { defaults, description, usage } = helpTopic;
2997
+ return `${makeHeadingFromUsage(usage)} ${makeRequiredDescriptor(defaults)}<br>
2998
+ ${description}<br><br>
2999
+ **usage:** \`${usage}\`<br>
3000
+ ${makeDefaultsDescriptors(defaults).join("<br>")}
3001
+ `;
3002
+ }
3003
+ function makeCommandHelpTopicsDocs(helpTopics) {
3004
+ return helpTopics.map(makeCommandHelpTopicDocs).join("");
3005
+ }
3006
+ function makeCommandHelpTopicsDocsForCategories(helpTopics) {
3007
+ const helpTopicsByCategory = groupHelpTopicsByCategory(helpTopics);
3008
+ const helpTopicsDocs = [];
3009
+ for (const [category, helpTopics] of Object.entries(helpTopicsByCategory)) {
3010
+ const helpTopicDocs = makeCommandHelpTopicsDocs(helpTopics ?? []);
3011
+ helpTopicsDocs.push(`### ${category}
3012
+ ${helpTopicDocs}
3013
+ `);
3014
+ }
3015
+ return helpTopicsDocs.join("");
3016
+ }
3017
+ function makeCommandDoc(commandHelpInfo) {
3018
+ const { name, description, helpTopics } = commandHelpInfo;
3019
+ return `## ${capitalCase(name)}
3020
+ ${description}
3021
+ ${makeCommandHelpTopicsDocsForCategories(helpTopics)}`;
3022
+ }
3023
+ function makeCommandDocs(commandsHelpInfo) {
3024
+ return commandsHelpInfo.map(makeCommandDoc).join("");
3025
+ }
3026
+ const docsFromCliHelpTemplate = (v) => `# ${v.docsTitle}<br>
3027
+ ${v.docsIntroduction}<br><br>
3028
+ ${v.cliDescription}<br>
3029
+ ## Table of Contents
3030
+ ${makeTableOfContents(v.commandsHelpInfo)}<br>
3031
+ ${makeCommandDocs(v.commandsHelpInfo)}
3032
+ `;
3033
+ //#endregion
3034
+ //#region src/templates/document-editor/editor.ts
3035
+ const documentEditorEditorFileTemplate = (v) => tsx`
3036
+ import { DocumentStateViewer, DocumentToolbar } from "@powerhousedao/design-system/connect";
3037
+ import { ${v.useSelectedDocumentHookName}, actions } from "${v.documentModelImportPath}";
3038
+
3039
+ export default function Editor() {
3040
+ const [document, dispatch] = ${v.useSelectedDocumentHookName}();
3041
+
3042
+ const handleSetName = (name: string) => {
3043
+ // 'actions' contains all available actions for this document type
3044
+ dispatch(actions.setName(name));
3045
+ };
3046
+
3047
+ return (
3048
+ <div className="mx-auto max-w-4xl bg-gray-50 p-6">
3049
+ <DocumentToolbar />
3050
+
3051
+ {/* "ph-default-styles" sets default styles for basic UI elements */}
3052
+ <div className="ph-default-styles">
3053
+ {/* Edit document name */}
3054
+ <label className="my-6">
3055
+ <h3>Document Name</h3>
3056
+ <input
3057
+ type="text"
3058
+ defaultValue={document.header.name}
3059
+ placeholder="Enter document name..."
3060
+ title="Edit document name and click outside to save."
3061
+ autoFocus
3062
+ onBlur={(e) => handleSetName(e.target.value.trim())}
3063
+ onKeyDown={(e) => {
3064
+ if (e.key === "Enter") {
3065
+ e.currentTarget.blur();
3066
+ }
3067
+ }}
3068
+ className="font-semibold"
3069
+ />
3070
+ </label>
3071
+ <hr />
3072
+
3073
+ {/* Document header info */}
3074
+ <div className="mb-6 grid grid-cols-2 gap-x-8">
3075
+ <label>
3076
+ <h3 className="text-base">ID</h3>
3077
+ <input
3078
+ type="text"
3079
+ value={document.header.id}
3080
+ readOnly
3081
+ className="font-mono"
3082
+ />
3083
+ </label>
3084
+ <label>
3085
+ <h3 className="text-base">Created</h3>
3086
+ <input
3087
+ type="text"
3088
+ value={new Date(document.header.createdAtUtcIso).toLocaleString()}
3089
+ readOnly
3090
+ />
3091
+ </label>
3092
+ <label>
3093
+ <h3 className="text-base">Type</h3>
3094
+ <input type="text" value={document.header.documentType} readOnly />
3095
+ </label>
3096
+ <label>
3097
+ <h3 className="text-base">Last Modified</h3>
3098
+ <input
3099
+ type="text"
3100
+ value={new Date(
3101
+ document.header.lastModifiedAtUtcIso,
3102
+ ).toLocaleString()}
3103
+ readOnly
3104
+ />
3105
+ </label>
3106
+ </div>
3107
+
3108
+ {/* Document state */}
3109
+ <div className="mt-6">
3110
+ <h3 className="text-base">Document State</h3>
3111
+ <DocumentStateViewer state={document.state} />
3112
+ </div>
3113
+ </div>
3114
+ </div>
3115
+ );
3116
+ }
3117
+ `.raw;
3118
+ //#endregion
3119
+ //#region src/templates/document-editor/module.ts
3120
+ const documentEditorModuleFileTemplate = (v) => tsx`
3121
+ import type { EditorModule } from "document-model";
3122
+ import { lazy } from "react";
3123
+
3124
+ /** Document editor module for the "${v.documentTypes}" document type */
3125
+ export const ${v.pascalCaseEditorName}: EditorModule = {
3126
+ Component: lazy(() => import("./editor.js")),
3127
+ documentTypes: ${v.documentTypes},
3128
+ config: {
3129
+ id: "${v.editorId}",
3130
+ name: "${v.editorName}",
3131
+ },
3132
+ };
3133
+ `.raw;
3134
+ //#endregion
3135
+ //#region src/templates/document-model/actions.ts
3136
+ function buildModuleActionsName(module, camelCaseDocumentType) {
3137
+ const camelCaseModuleName = camelCase(module.name);
3138
+ return `${camelCaseDocumentType}${camelCaseModuleName.charAt(0).toUpperCase()}${camelCaseModuleName.slice(1)}Actions`;
3139
+ }
3140
+ function buildModuleActionsNames(modules, camelCaseDocumentType) {
3141
+ return modules.map((m) => buildModuleActionsName(m, camelCaseDocumentType));
3142
+ }
3143
+ function buildModuleActionsImports(modules, camelCaseDocumentType) {
3144
+ return `import { ${buildModuleActionsNames(modules, camelCaseDocumentType).join(",\n")} } from "./gen/creators.js";`;
3145
+ }
3146
+ function buildModuleActionsSpreadExport(modules, camelCaseDocumentType) {
3147
+ return `
3148
+ export const actions = { ...baseActions, ${buildModuleActionsNames(modules, camelCaseDocumentType).map((n) => `...${n}`).join(",\n")} }`;
3149
+ }
3150
+ const documentModelRootActionsFileTemplate = (v) => ts`
3151
+ import { baseActions } from "document-model";
3152
+ ${buildModuleActionsImports(v.modules, v.camelCaseDocumentType)}
3153
+
3154
+ /** Actions for the ${v.pascalCaseDocumentType} document model */
3155
+ ${buildModuleActionsSpreadExport(v.modules, v.camelCaseDocumentType)}
3156
+ `.raw;
3157
+ //#endregion
3158
+ //#region src/templates/document-model/gen/actions.ts
3159
+ function makeModuleActionsTypeImport(module, pascalCaseDocumentType) {
3160
+ return `import type { ${pascalCaseDocumentType}${pascalCase(module.name)}Action } from "./${kebabCase(module.name)}/actions.js";`;
3161
+ }
3162
+ function makeModuleActionsTypeImports(modules, pascalCaseDocumentType) {
3163
+ return modules.map((module) => makeModuleActionsTypeImport(module, pascalCaseDocumentType)).join("\n");
3164
+ }
3165
+ function makeModuleActionsTypeExport(module) {
3166
+ return `export * from "./${kebabCase(module.name)}/actions.js";`;
3167
+ }
3168
+ function makeModuleActionsTypeExports(modules) {
3169
+ return modules.map(makeModuleActionsTypeExport).join("\n");
3170
+ }
3171
+ function makeModuleActionTypeName(module, pascalCaseDocumentType) {
3172
+ return `${pascalCaseDocumentType}${pascalCase(module.name)}Action`;
3173
+ }
3174
+ function makeModuleActionTypesUnion(modules, pascalCaseDocumentType) {
3175
+ return modules.map((module) => makeModuleActionTypeName(module, pascalCaseDocumentType)).join("|\n");
3176
+ }
3177
+ function makeDocumentActionType(modules, pascalCaseDocumentType) {
3178
+ return `export type ${pascalCaseDocumentType}Action = ${makeModuleActionTypesUnion(modules, pascalCaseDocumentType)};`;
3179
+ }
3180
+ const documentModelGenActionsFileTemplate = (v) => ts`
3181
+ ${makeModuleActionsTypeImports(v.modules, v.pascalCaseDocumentType)}
3182
+
3183
+ ${makeModuleActionsTypeExports(v.modules)}
3184
+
3185
+ ${makeDocumentActionType(v.modules, v.pascalCaseDocumentType)}
3186
+ `.raw;
3187
+ //#endregion
3188
+ //#region src/templates/document-model/gen/controller.ts
3189
+ const documentModelGenControllerFileTemplate = (v) => ts`
3190
+ import { PHDocumentController } from "document-model";
3191
+ import { ${v.pascalCaseDocumentType} } from "../module.js";
3192
+ import type { ${v.actionTypeName}, ${v.phStateName} } from "./types.js";
3193
+
3194
+ export const ${v.pascalCaseDocumentType}Controller = PHDocumentController.forDocumentModel<
3195
+ ${v.phStateName},
3196
+ ${v.actionTypeName}
3197
+ >(${v.pascalCaseDocumentType});
3198
+ `.raw;
3199
+ //#endregion
3200
+ //#region src/templates/document-model/gen/creators.ts
3201
+ function buildModuleCreatorsExport(module, camelCaseDocumentType) {
3202
+ const kebabCaseModuleName = kebabCase(module.name);
3203
+ const camelCaseModuleName = camelCase(module.name);
3204
+ const namespaceName = `${camelCaseDocumentType}${camelCaseModuleName.charAt(0).toUpperCase()}${camelCaseModuleName.slice(1)}Actions`;
3205
+ return [`export * from "./${kebabCaseModuleName}/creators.js";`, `export * as ${namespaceName} from "./${kebabCaseModuleName}/creators.js";`];
3206
+ }
3207
+ function buildCreatorsExports(modules, camelCaseDocumentType) {
3208
+ return modules.flatMap((module) => buildModuleCreatorsExport(module, camelCaseDocumentType)).join("\n");
3209
+ }
3210
+ const documentModelGenCreatorsFileTemplate = (v) => ts`
3211
+ ${buildCreatorsExports(v.modules, v.camelCaseDocumentType)}
3212
+ `.raw;
3213
+ //#endregion
3214
+ //#region src/templates/document-model/gen/document-schema.ts
3215
+ const documentModelDocumentSchemaFileTemplate = (v) => ts`
3216
+ import {
3217
+ BaseDocumentHeaderSchema,
3218
+ BaseDocumentStateSchema,
3219
+ } from "document-model";
3220
+ import { z } from "zod";
3221
+ import { ${v.documentTypeVariableName} } from "./document-type.js";
3222
+ import { ${v.stateSchemaName} } from "./schema/zod.js";
3223
+ import type { ${v.phDocumentTypeName}, ${v.phStateName} } from "./types.js";
3224
+
3225
+ /** Schema for validating the header object of a ${v.pascalCaseDocumentType} document */
3226
+ export const ${v.phDocumentTypeName}HeaderSchema = BaseDocumentHeaderSchema.extend({
3227
+ documentType: z.literal(${v.documentTypeVariableName}),
3228
+ });
3229
+
3230
+ /** Schema for validating the state object of a ${v.pascalCaseDocumentType} document */
3231
+ export const ${v.phStateName}Schema = BaseDocumentStateSchema.extend({
3232
+ global: ${v.stateSchemaName}(),
3233
+ });
3234
+
3235
+ export const ${v.phDocumentSchemaName} = z.object({
3236
+ header: ${v.phDocumentTypeName}HeaderSchema,
3237
+ state: ${v.phStateName}Schema,
3238
+ initialState: ${v.phStateName}Schema,
3239
+ });
3240
+
3241
+ /** Simple helper function to check if a state object is a ${v.pascalCaseDocumentType} document state object */
3242
+ export function ${v.isPhStateOfTypeFunctionName}(
3243
+ state: unknown,
3244
+ ): state is ${v.phStateName} {
3245
+ return ${v.phStateName}Schema.safeParse(state).success;
3246
+ }
3247
+
3248
+ /** Simple helper function to assert that a document state object is a ${v.pascalCaseDocumentType} document state object */
3249
+ export function ${v.assertIsPhStateOfTypeFunctionName}(
3250
+ state: unknown,
3251
+ ): asserts state is ${v.phStateName} {
3252
+ ${v.phStateName}Schema.parse(state);
3253
+ }
3254
+
3255
+ /** Simple helper function to check if a document is a ${v.pascalCaseDocumentType} document */
3256
+ export function ${v.isPhDocumentOfTypeFunctionName}(
3257
+ document: unknown,
3258
+ ): document is ${v.phDocumentTypeName} {
3259
+ return ${v.phDocumentSchemaName}.safeParse(document).success;
3260
+ }
3261
+
3262
+ /** Simple helper function to assert that a document is a ${v.pascalCaseDocumentType} document */
3263
+ export function ${v.assertIsPhDocumentOfTypeFunctionName}(
3264
+ document: unknown,
3265
+ ): asserts document is ${v.phDocumentTypeName} {
3266
+ ${v.phDocumentSchemaName}.parse(document);
3267
+ }
3268
+ `.raw;
3269
+ //#endregion
3270
+ //#region src/templates/document-model/gen/document-type.ts
3271
+ const documentModelDocumentTypeTemplate = (v) => ts`
3272
+ export const ${v.documentTypeVariableName} = "${v.documentTypeId}";
3273
+ `.raw;
3274
+ //#endregion
3275
+ //#region src/templates/document-model/gen/index.ts
3276
+ function buildModuleOperationsExports(module) {
3277
+ return `export * from "./${kebabCase(module.name)}/operations.js";`;
3278
+ }
3279
+ function buildModulesOperationsExports(modules) {
3280
+ return modules.map(buildModuleOperationsExports).join("\n");
3281
+ }
3282
+ const documentModelGenIndexFileTemplate = (v) => ts`
3283
+ export * from './actions.js';
3284
+ export * from './document-model.js';
3285
+ export * from './types.js';
3286
+ export * from './creators.js';
3287
+ export {
3288
+ create${v.phDocumentTypeName},
3289
+ createState,
3290
+ defaultPHState,
3291
+ defaultGlobalState,
3292
+ defaultLocalState,
3293
+ } from './ph-factories.js';
3294
+ export * from "./utils.js";
3295
+ export * from "./reducer.js";
3296
+ export * from "./controller.js";
3297
+ export * from "./schema/index.js";
3298
+ export * from "./document-type.js";
3299
+ export * from "./document-schema.js";
3300
+ ${buildModulesOperationsExports(v.modules)}
3301
+ `.raw;
3302
+ //#endregion
3303
+ //#region src/templates/document-model/gen/modules/actions.ts
3304
+ function getActionTypeExport(action) {
3305
+ const baseActionTypeName = action.hasAttachment ? "ActionWithAttachment" : "Action";
3306
+ const actionTypeName = getActionTypeName(action);
3307
+ const actionInputName = getActionInputName(action) ?? `"{}"`;
3308
+ return ts`export type ${actionTypeName} = ${baseActionTypeName} & { type: "${getActionType(action)}"; input: ${actionInputName} };`.raw;
3309
+ }
3310
+ function getActionTypeExports(actions) {
3311
+ return actions.map(getActionTypeExport).join("\n");
3312
+ }
3313
+ function getModuleExportType(actions, pascalCaseDocumentName, pascalCaseModuleName) {
3314
+ return ts`export type ${pascalCaseDocumentName}${pascalCaseModuleName}Action = ${actions.map(getActionTypeName).join(" |\n")};`.raw;
3315
+ }
3316
+ function getDocumentModelActionTypeImportNames(actions) {
3317
+ const actionTypeImports = ["Action"];
3318
+ if (actions.some((a) => a.hasAttachment)) actionTypeImports.push("ActionWithAttachment");
3319
+ return actionTypeImports.join(",\n");
3320
+ }
3321
+ const documentModelOperationModuleActionsFileTemplate = (v) => ts`
3322
+ import type { ${getDocumentModelActionTypeImportNames(v.actions)} } from 'document-model';
3323
+ import type {
3324
+ ${getActionInputTypeNames(v.actions)}
3325
+ } from '../types.js';
3326
+
3327
+ ${getActionTypeExports(v.actions)}
3328
+
3329
+ ${getModuleExportType(v.actions, v.pascalCaseDocumentType, v.pascalCaseModuleName)}
3330
+ `.raw;
3331
+ //#endregion
3332
+ //#region src/templates/document-model/gen/modules/creators.ts
3333
+ function makeDocumentModelTypeImports(actions) {
3334
+ const actionTypeImports = ["createAction"];
3335
+ if (actions.some((a) => a.hasAttachment)) actionTypeImports.push("AttachmentInput");
3336
+ return actionTypeImports.join(",\n");
3337
+ }
3338
+ function makeActionInputSchemaName(action) {
3339
+ if (!action.hasInput) return;
3340
+ return `${pascalCase(action.name)}InputSchema`;
3341
+ }
3342
+ function makeActionInputTypeName(action) {
3343
+ if (!action.hasInput) return;
3344
+ return `${pascalCase(action.name)}Input`;
3345
+ }
3346
+ function makeActionTypeName(action) {
3347
+ return `${pascalCase(action.name)}Action`;
3348
+ }
3349
+ function makeActionInputSchemaImports(actions) {
3350
+ return actions.map(makeActionInputSchemaName).filter(Boolean).join(",\n");
3351
+ }
3352
+ function makeActionInputTypeImports(actions) {
3353
+ return actions.map(makeActionInputTypeName).filter(Boolean).join(",\n");
3354
+ }
3355
+ function makeActionTypeImports(actions) {
3356
+ return actions.map(makeActionTypeName).join(",\n");
3357
+ }
3358
+ function makeActionCreatorWithInput(actionWithInput) {
3359
+ if (!actionWithInput.hasInput) return;
3360
+ const camelCaseActionName = camelCase(actionWithInput.name);
3361
+ const constantCaseActionName = constantCase(actionWithInput.name);
3362
+ const actionTypeName = makeActionTypeName(actionWithInput);
3363
+ const inputSchemaName = makeActionInputSchemaName(actionWithInput);
3364
+ const inputTypeName = makeActionInputTypeName(actionWithInput);
3365
+ const argsArray = [actionWithInput.isEmptyInput ? `input: ${inputTypeName} = {}` : `input: ${inputTypeName}`];
3366
+ if (actionWithInput.hasAttachment) argsArray.push(`attachments: AttachmentInput[]`);
3367
+ return ts`
3368
+ export const ${camelCaseActionName} = (${argsArray.join(", ")}) =>
3369
+ createAction<${actionTypeName}>(
3370
+ "${constantCaseActionName}",
3371
+ {...input},
3372
+ ${actionWithInput.hasAttachment ? "attachments" : "undefined"},
3373
+ ${inputSchemaName},
3374
+ "${actionWithInput.scope}"
3375
+ );`.raw;
3376
+ }
3377
+ function makeActionCreatorWithoutInput(actionWithoutInput) {
3378
+ if (actionWithoutInput.hasInput) return;
3379
+ const camelCaseActionName = camelCase(actionWithoutInput.name);
3380
+ const constantCaseActionName = constantCase(actionWithoutInput.name);
3381
+ return ts`
3382
+ export const ${camelCaseActionName} = () =>
3383
+ createAction<${makeActionTypeName(actionWithoutInput)}>("${constantCaseActionName}");`.raw;
3384
+ }
3385
+ function makeCreatorsForActionsWithInput(actions) {
3386
+ return actions.filter((a) => a.hasInput).map(makeActionCreatorWithInput).join("\n\n");
3387
+ }
3388
+ function makeActionCreatorsWithoutInput(actions) {
3389
+ return actions.filter((a) => !a.hasInput).map(makeActionCreatorWithoutInput).join("\n\n");
3390
+ }
3391
+ const documentModelOperationsModuleCreatorsFileTemplate = (v) => ts`
3392
+
3393
+ import { ${makeDocumentModelTypeImports(v.actions)} } from "document-model";
3394
+ import {
3395
+ ${makeActionInputSchemaImports(v.actions)}
3396
+ } from '../schema/zod.js';
3397
+ import type {
3398
+ ${makeActionInputTypeImports(v.actions)}
3399
+ } from '../types.js';
3400
+ import type {
3401
+ ${makeActionTypeImports(v.actions)}
3402
+ } from './actions.js';
3403
+
3404
+ ${makeCreatorsForActionsWithInput(v.actions)}
3405
+
3406
+ ${makeActionCreatorsWithoutInput(v.actions)}
3407
+ `.raw;
3408
+ //#endregion
3409
+ //#region src/templates/document-model/gen/modules/error.ts
3410
+ function getErrorName(error) {
3411
+ if (!error.name) return;
3412
+ return pascalCase(error.name);
3413
+ }
3414
+ function getErrorNames(errors) {
3415
+ return errors.map(getErrorName).filter((name) => name !== void 0);
3416
+ }
3417
+ function getErrorCodeType(errors) {
3418
+ return ts`export type ErrorCode = ${getErrorNames(errors).map((name) => `"${name}"`).join(" |\n")};`.raw;
3419
+ }
3420
+ function errorClassTemplate(error) {
3421
+ const errorName = getErrorName(error);
3422
+ if (!errorName) return;
3423
+ return ts`
3424
+ export class ${errorName} extends Error implements ReducerError {
3425
+ errorCode = "${errorName}" as ErrorCode;
3426
+ constructor(message = "${errorName}") {
3427
+ super(message);
3428
+ }
3429
+ }
3430
+ `.raw;
3431
+ }
3432
+ function getErrorClassImplementations(errors) {
3433
+ return errors.map((error) => errorClassTemplate(error)).filter(Boolean).join("\n\n");
3434
+ }
3435
+ function getErrorsImplementations(errors) {
3436
+ if (!errors.length) return "";
3437
+ const deduplicatedErrors = errors.reduce((acc, error) => {
3438
+ if (!acc.some((e) => getErrorName(e) === getErrorName(error))) acc.push(error);
3439
+ return acc;
3440
+ }, new Array());
3441
+ return ts`
3442
+ ${getErrorCodeType(deduplicatedErrors)}
3443
+
3444
+ export interface ReducerError {
3445
+ errorCode: ErrorCode;
3446
+ }
3447
+
3448
+ ${getErrorClassImplementations(deduplicatedErrors)}
3449
+ `.raw;
3450
+ }
3451
+ function getActionErrorsExport(action) {
3452
+ const errors = action.errors;
3453
+ if (errors.length === 0) return;
3454
+ return ts`
3455
+ ${pascalCase(action.name)}: { ${getErrorNames(errors).filter(Boolean).join(",\n")} }
3456
+ `.raw;
3457
+ }
3458
+ function getErrorsExport(actions) {
3459
+ return ts`
3460
+ export const errors = { ${actions.map(getActionErrorsExport).filter(Boolean).join(",\n")} };
3461
+ `.raw;
3462
+ }
3463
+ const documentModelOperationsModuleErrorFileTemplate = (v) => ts`
3464
+ ${getErrorsImplementations(v.errors)}
3465
+ ${getErrorsExport(v.actions)}
3466
+ `.raw;
3467
+ //#endregion
3468
+ //#region src/templates/document-model/gen/modules/operations.ts
3469
+ function getActionTypeNames(actions) {
3470
+ return actions.map(getActionTypeName);
3471
+ }
3472
+ function getActionTypeImports(actions) {
3473
+ return getActionTypeNames(actions).join(",\n");
3474
+ }
3475
+ function getOperationsInterfaceName(pascalCaseDocumentType, module) {
3476
+ return `${pascalCaseDocumentType}${pascalCase(module.name)}Operations`;
3477
+ }
3478
+ function getActionOperationFieldName(action) {
3479
+ return `${camelCase(action.name)}Operation`;
3480
+ }
3481
+ function getActionOperationStateTypeName(action, pascalCaseDocumentType) {
3482
+ if (!action.state) return `${pascalCaseDocumentType}State`;
3483
+ return `${pascalCaseDocumentType}_${pascalCase(action.state)}_State`;
3484
+ }
3485
+ function getActionOperationStateTypeImports(actions, pascalCaseDocumentType) {
3486
+ const stateTypeNames = actions.map((action) => getActionOperationStateTypeName(action, pascalCaseDocumentType));
3487
+ return Array.from(new Set(stateTypeNames)).join(",\n");
3488
+ }
3489
+ function getActionOperationFunction(action, pascalCaseDocumentType) {
3490
+ return ts`
3491
+ (state: ${getActionOperationStateTypeName(action, pascalCaseDocumentType)}, action: ${getActionTypeName(action)}, dispatch?: SignalDispatch) => void
3492
+ `.raw;
3493
+ }
3494
+ function getOperationsInterfaceField(action, pascalCaseDocumentType) {
3495
+ return ts`
3496
+ ${getActionOperationFieldName(action)}: ${getActionOperationFunction(action, pascalCaseDocumentType)}
3497
+ `.raw;
3498
+ }
3499
+ function getOperationsInterfaceFields(actions, pascalCaseDocumentType) {
3500
+ return actions.map((action) => getOperationsInterfaceField(action, pascalCaseDocumentType)).join(",");
3501
+ }
3502
+ const documentModelOperationsModuleOperationsFileTemplate = (v) => ts`
3503
+ import { type SignalDispatch } from 'document-model';
3504
+ import type {
3505
+ ${getActionTypeImports(v.actions)}
3506
+ } from './actions.js';
3507
+ import type {
3508
+ ${getActionOperationStateTypeImports(v.actions, v.pascalCaseDocumentType)}
3509
+ } from "../types.js";
3510
+
3511
+ export interface ${getOperationsInterfaceName(v.pascalCaseDocumentType, v.module)} {
3512
+ ${getOperationsInterfaceFields(v.actions, v.pascalCaseDocumentType)}
3513
+ }
3514
+ `.raw;
3515
+ //#endregion
3516
+ //#region src/templates/document-model/gen/ph-factories.ts
3517
+ const documentModelPhFactoriesFileTemplate = (v) => ts`
3518
+ /**
3519
+ * Factory methods for creating ${v.phDocumentTypeName} instances
3520
+ */
3521
+ import type {
3522
+ PHAuthState,
3523
+ PHDocumentState,
3524
+ PHBaseState,
3525
+ } from "document-model";
3526
+ import {
3527
+ createBaseState,
3528
+ defaultBaseState,
3529
+ } from "document-model";
3530
+ import type {
3531
+ ${v.phDocumentTypeName},
3532
+ ${v.globalStateName},
3533
+ ${v.localStateName},
3534
+ ${v.phStateName},
3535
+ } from "./types.js";
3536
+ import { utils } from "./utils.js";
3537
+
3538
+ export function defaultGlobalState(): ${v.globalStateName} {
3539
+ return ${v.initialGlobalState};
3540
+ }
3541
+
3542
+ export function defaultLocalState(): ${v.localStateName} {
3543
+ return ${v.initialLocalState};
3544
+ }
3545
+
3546
+ export function defaultPHState(): ${v.phStateName} {
3547
+ return {
3548
+ ...defaultBaseState(),
3549
+ global: defaultGlobalState(),
3550
+ local: defaultLocalState(),
3551
+ };
3552
+ }
3553
+
3554
+ export function createGlobalState(
3555
+ state?: Partial<${v.globalStateName}>,
3556
+ ): ${v.globalStateName} {
3557
+ return {
3558
+ ...defaultGlobalState(),
3559
+ ...(state || {}),
3560
+ } as ${v.globalStateName};
3561
+ }
3562
+
3563
+ export function createLocalState(
3564
+ state?: Partial<${v.localStateName}>,
3565
+ ): ${v.localStateName} {
3566
+ return {
3567
+ ...defaultLocalState(),
3568
+ ...(state || {}),
3569
+ } as ${v.localStateName};
3570
+ }
3571
+
3572
+ export function createState(
3573
+ baseState?: Partial<PHBaseState>,
3574
+ globalState?: Partial<${v.globalStateName}>,
3575
+ localState?: Partial<${v.localStateName}>,
3576
+ ): ${v.phStateName} {
3577
+ return {
3578
+ ...createBaseState(baseState?.auth, baseState?.document),
3579
+ global: createGlobalState(globalState),
3580
+ local: createLocalState(localState),
3581
+ };
3582
+ }
3583
+
3584
+ /**
3585
+ * Creates a ${v.phDocumentTypeName} with custom global and local state
3586
+ * This properly handles the PHBaseState requirements while allowing
3587
+ * document-specific state to be set.
3588
+ */
3589
+ export function create${v.phDocumentTypeName}(
3590
+ state?: Partial<{
3591
+ auth?: Partial<PHAuthState>;
3592
+ document?: Partial<PHDocumentState>;
3593
+ global?: Partial<${v.globalStateName}>;
3594
+ local?: Partial<${v.localStateName}>;
3595
+ }>,
3596
+ ): ${v.phDocumentTypeName} {
3597
+ const document = utils.createDocument(
3598
+ state ? createState(
3599
+ createBaseState(state.auth, state.document),
3600
+ state.global,
3601
+ state.local,
3602
+ ) : undefined
3603
+ );
3604
+
3605
+ return document;
3606
+ }
3607
+ `.raw;
3608
+ //#endregion
3609
+ //#region src/templates/document-model/gen/reducer.ts
3610
+ function makePascalCaseOperationName(operation) {
3611
+ if (!operation.name) throw new Error("Operation is missing name");
3612
+ return pascalCase(operation.name);
3613
+ }
3614
+ function makeCamelCaseOperationName(operation) {
3615
+ if (!operation.name) throw new Error("Operation is missing name");
3616
+ return camelCase(operation.name);
3617
+ }
3618
+ function makeConstantCaseOperationName(operation) {
3619
+ if (!operation.name) throw new Error("Operation is missing name");
3620
+ return constantCase(operation.name);
3621
+ }
3622
+ function makeOperationInputSchema(operation) {
3623
+ return `${makePascalCaseOperationName(operation)}InputSchema`;
3624
+ }
3625
+ function makeOperationInputSchemaImports(modules) {
3626
+ return `import { ${modules.flatMap((module) => module.operations.map(makeOperationInputSchema)).join(",\n")} } from "./schema/zod.js";`;
3627
+ }
3628
+ function makeModuleOperationsImport(module, camelCaseDocumentType) {
3629
+ return `import { ${camelCaseDocumentType}${pascalCase(module.name)}Operations } from "../src/reducers/${kebabCase(module.name)}.js";`;
3630
+ }
3631
+ function makeModulesOperationsImports(modules, camelCaseDocumentType) {
3632
+ return modules.map((module) => makeModuleOperationsImport(module, camelCaseDocumentType)).join("\n");
3633
+ }
3634
+ function makeOperationInputSchemaInvocation(operation) {
3635
+ const operationInputSchema = makeOperationInputSchema(operation);
3636
+ const constantCaseOperationName = makeConstantCaseOperationName(operation);
3637
+ if (operation.schema === null) return ts`
3638
+ if (Object.keys(action.input).length > 0) throw new Error("Expected empty input for action ${constantCaseOperationName}");
3639
+ `.raw;
3640
+ return ts`${operationInputSchema}().parse(action.input);`.raw;
3641
+ }
3642
+ function makeOperationsObjectName(module, camelCaseDocumentType) {
3643
+ return `${camelCaseDocumentType}${pascalCase(module.name)}Operations`;
3644
+ }
3645
+ function makeOperationName(operation) {
3646
+ return `${makeCamelCaseOperationName(operation)}Operation`;
3647
+ }
3648
+ function makeOperationInvocation(module, operation, camelCaseDocumentType) {
3649
+ return ts`
3650
+ ${makeOperationsObjectName(module, camelCaseDocumentType)}.${makeOperationName(operation)}((state as any)[action.scope], action as any, dispatch);
3651
+ `.raw;
3652
+ }
3653
+ function makeModuleOperationCaseStatement(module, camelCaseDocumentType) {
3654
+ return module.operations.map((operation) => ts`
3655
+ case "${makeConstantCaseOperationName(operation)}": {
3656
+ ${makeOperationInputSchemaInvocation(operation)}
3657
+ ${makeOperationInvocation(module, operation, camelCaseDocumentType)}
3658
+ break;
3659
+ }
3660
+ `.raw);
3661
+ }
3662
+ function makeModuleOperationsCaseStatements(modules, camelCaseDocumentType) {
3663
+ return modules.map((module) => makeModuleOperationCaseStatement(module, camelCaseDocumentType).join("\n")).join("\n");
3664
+ }
3665
+ const documentModelGenReducerFileTemplate = (v) => ts`
3666
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
3667
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
3668
+ import type { Reducer, StateReducer } from "document-model";
3669
+ import { isDocumentAction, createReducer } from "document-model";
3670
+ import type { ${v.phStateName} } from "${v.versionedDocumentModelPackageImportPath}";
3671
+
3672
+ ${makeModulesOperationsImports(v.modules, v.camelCaseDocumentType)}
3673
+
3674
+ ${makeOperationInputSchemaImports(v.modules)}
3675
+
3676
+ const stateReducer: StateReducer<${v.phStateName}> =
3677
+ (state, action, dispatch) => {
3678
+ if (isDocumentAction(action)) {
3679
+ return state;
3680
+ }
3681
+ switch (action.type) {
3682
+ ${makeModuleOperationsCaseStatements(v.modules, v.camelCaseDocumentType)}
3683
+ default:
3684
+ return state;
3685
+ }
3686
+ }
3687
+
3688
+ export const reducer: Reducer<${v.phStateName}> = createReducer(stateReducer);
3689
+ `.raw;
3690
+ //#endregion
3691
+ //#region src/templates/document-model/gen/schema/index.ts
3692
+ const documentModelSchemaIndexTemplate = ts`
3693
+ export * from "./types.js";
3694
+ export * from "./zod.js";
3695
+ `.raw;
3696
+ //#endregion
3697
+ //#region src/templates/document-model/gen/types.ts
3698
+ function buildEmptyLocalStateType(hasLocalSchema, localStateName) {
3699
+ if (hasLocalSchema) return "";
3700
+ return `type ${localStateName} = Record<PropertyKey, never>;`;
3701
+ }
3702
+ function buildLocalStateTypeImport(hasLocalSchema, localStateName) {
3703
+ if (!hasLocalSchema) return "";
3704
+ return localStateName;
3705
+ }
3706
+ const documentModelGenTypesTemplate = (v) => ts`
3707
+ import type { PHDocument, PHBaseState } from 'document-model';
3708
+ import type { ${v.actionTypeName} } from './actions.js';
3709
+ import type {
3710
+ ${v.stateName} as ${v.globalStateName},
3711
+ ${buildLocalStateTypeImport(v.hasLocalSchema, v.localStateName)}
3712
+ } from './schema/types.js';
3713
+
3714
+ ${buildEmptyLocalStateType(v.hasLocalSchema, v.localStateName)}
3715
+
3716
+ type ${v.phStateName} = PHBaseState & {
3717
+ global: ${v.globalStateName};
3718
+ local: ${v.localStateName};
3719
+ };
3720
+ type ${v.phDocumentTypeName} = PHDocument<${v.phStateName}>;
3721
+
3722
+ export * from './schema/types.js';
3723
+
3724
+ export type {
3725
+ ${v.globalStateName},
3726
+ ${v.localStateName},
3727
+ ${v.phStateName},
3728
+ ${v.actionTypeName},
3729
+ ${v.phDocumentTypeName},
3730
+ };
3731
+ `.raw;
3732
+ //#endregion
3733
+ //#region src/templates/document-model/gen/utils.ts
3734
+ const documentModelGenUtilsTemplate = (v) => ts`
3735
+ import type {
3736
+ DocumentModelUtils,
3737
+ } from "document-model";
3738
+ import {
3739
+ baseCreateDocument,
3740
+ baseSaveToFileHandle,
3741
+ baseLoadFromInput,
3742
+ defaultBaseState,
3743
+ generateId,
3744
+ } from "document-model";
3745
+ import { reducer } from './reducer.js';
3746
+ import { ${v.documentTypeVariableName} } from "./document-type.js";
3747
+ import {
3748
+ ${v.assertIsPhDocumentOfTypeFunctionName},
3749
+ ${v.assertIsPhStateOfTypeFunctionName},
3750
+ ${v.isPhDocumentOfTypeFunctionName},
3751
+ ${v.isPhStateOfTypeFunctionName},
3752
+ } from "./document-schema.js";
3753
+ import type { ${v.globalStateName}, ${v.localStateName}, ${v.phStateName} } from './types.js';
3754
+
3755
+ export const initialGlobalState: ${v.globalStateName} = ${v.initialGlobalState};
3756
+ export const initialLocalState: ${v.localStateName} = ${v.initialLocalState};
3757
+
3758
+ export const utils: DocumentModelUtils<${v.phStateName}> = {
3759
+ fileExtension: "${v.fileExtension}",
3760
+ createState(state) {
3761
+ return { ...defaultBaseState(), global: { ...initialGlobalState, ...state?.global }, local: { ...initialLocalState, ...state?.local } };
3762
+ },
3763
+ createDocument(state) {
3764
+ const document = baseCreateDocument(
3765
+ utils.createState,
3766
+ state
3767
+ );
3768
+
3769
+ document.header.documentType = ${v.documentTypeVariableName};
3770
+
3771
+ // for backwards compatibility, but this is NOT a valid signed document id
3772
+ document.header.id = generateId();
3773
+
3774
+ return document;
3775
+ },
3776
+ saveToFileHandle(document, input) {
3777
+ return baseSaveToFileHandle(document, input);
3778
+ },
3779
+ loadFromInput(input) {
3780
+ return baseLoadFromInput(input, reducer);
3781
+ },
3782
+ isStateOfType(state) {
3783
+ return ${v.isPhStateOfTypeFunctionName}(state);
3784
+ },
3785
+ assertIsStateOfType(state) {
3786
+ return ${v.assertIsPhStateOfTypeFunctionName}(state);
3787
+ },
3788
+ isDocumentOfType(document) {
3789
+ return ${v.isPhDocumentOfTypeFunctionName}(document);
3790
+ },
3791
+ assertIsDocumentOfType(document) {
3792
+ return ${v.assertIsPhDocumentOfTypeFunctionName}(document);
3793
+ },
3794
+ };
3795
+ `.raw;
3796
+ //#endregion
3797
+ //#region src/templates/document-model/hooks.ts
3798
+ const documentModelHooksFileTemplate = (v) => ts`
3799
+
3800
+ import type { DocumentDispatch } from "@powerhousedao/reactor-browser";
3801
+ import {
3802
+ useDocumentById,
3803
+ useDocumentsInSelectedDrive,
3804
+ useDocumentsInSelectedFolder,
3805
+ useSelectedDocument,
3806
+ } from "@powerhousedao/reactor-browser";
3807
+ import type {
3808
+ ${v.actionTypeName},
3809
+ ${v.phDocumentTypeName},
3810
+ } from "${v.versionedDocumentModelPackageImportPath}";
3811
+ import {
3812
+ ${v.assertIsPhDocumentOfTypeFunctionName},
3813
+ ${v.isPhDocumentOfTypeFunctionName}
3814
+ } from "./gen/document-schema.js";
3815
+
3816
+ /** Hook to get a ${v.pascalCaseDocumentType} document by its id */
3817
+ export function ${v.useByIdHookName}(
3818
+ documentId: string | null | undefined,
3819
+ ):
3820
+ | [${v.phDocumentTypeName}, DocumentDispatch<${v.actionTypeName}>]
3821
+ | [undefined, undefined] {
3822
+ const [document, dispatch] = useDocumentById(documentId);
3823
+ if (!${v.isPhDocumentOfTypeFunctionName}(document)) return [undefined, undefined];
3824
+ return [document, dispatch];
3825
+ }
3826
+
3827
+ /** Hook to get the selected ${v.pascalCaseDocumentType} document */
3828
+ export function ${v.useSelectedHookName}():
3829
+ | [${v.phDocumentTypeName}, DocumentDispatch<${v.actionTypeName}>] {
3830
+ const [document, dispatch] = useSelectedDocument();
3831
+
3832
+ ${v.assertIsPhDocumentOfTypeFunctionName}(document);
3833
+ return [document, dispatch] as const;
3834
+ }
3835
+
3836
+ /** Hook to get all ${v.pascalCaseDocumentType} documents in the selected drive */
3837
+ export function ${v.useInSelectedDriveHookName}() {
3838
+ const documentsInSelectedDrive = useDocumentsInSelectedDrive();
3839
+ return documentsInSelectedDrive?.filter(${v.isPhDocumentOfTypeFunctionName});
3840
+ }
3841
+
3842
+ /** Hook to get all ${v.pascalCaseDocumentType} documents in the selected folder */
3843
+ export function ${v.useInSelectedFolderHookName}() {
3844
+ const documentsInSelectedFolder = useDocumentsInSelectedFolder();
3845
+ return documentsInSelectedFolder?.filter(${v.isPhDocumentOfTypeFunctionName});
3846
+ }
3847
+ `.raw;
3848
+ //#endregion
3849
+ //#region src/templates/document-model/index.ts
3850
+ const documentModelIndexTemplate = ts`
3851
+ export * from "./gen/index.js";
3852
+ export * from "./src/index.js";
3853
+ export * from "./hooks.js";
3854
+ export { actions } from "./actions.js";
3855
+ export { utils } from "./utils.js";
3856
+ `.raw;
3857
+ //#endregion
3858
+ //#region src/templates/document-model/module.ts
3859
+ function documentModelModuleFileTemplate({ phStateName, pascalCaseDocumentType, version }) {
3860
+ return ts`
3861
+ import type { DocumentModelModule } from "document-model";
3862
+ import { createState, defaultBaseState } from "document-model";
3863
+ import type { ${phStateName} } from "./gen/types.js";
3864
+ import { documentModel } from "./gen/document-model.js";
3865
+ import { reducer } from "./gen/reducer.js";
3866
+ import { actions } from "./actions.js";
3867
+ import { utils } from "./utils.js";
3868
+
3869
+ /** Document model module for the ${pascalCaseDocumentType} document type */
3870
+ export const ${pascalCaseDocumentType}: DocumentModelModule<${phStateName}> = {
3871
+ version: ${version},
3872
+ reducer,
3873
+ actions,
3874
+ utils,
3875
+ documentModel: createState(defaultBaseState(), documentModel),
3876
+ };
3877
+ `.raw;
3878
+ }
3879
+ //#endregion
3880
+ //#region src/templates/document-model/src/index.ts
3881
+ const documentModelSrcIndexFileTemplate = ts`
3882
+ export * from "./utils.js";
3883
+ `.raw;
3884
+ //#endregion
3885
+ //#region src/templates/document-model/src/utils.ts
3886
+ const documentModelSrcUtilsTemplate = ts`
3887
+ export {};
3888
+ `.raw;
3889
+ //#endregion
3890
+ //#region src/templates/document-model/tests/document-model.test.ts
3891
+ const documentModelTestFileTemplate = (v) => ts`
3892
+ /**
3893
+ * This is a scaffold file meant for customization:
3894
+ * - change it by adding new tests or modifying the existing ones
3895
+ */
3896
+ /**
3897
+ * This is a scaffold file meant for customization:
3898
+ * - change it by adding new tests or modifying the existing ones
3899
+ */
3900
+
3901
+ import { describe, it, expect } from "vitest";
3902
+ import {
3903
+ utils,
3904
+ initialGlobalState,
3905
+ initialLocalState,
3906
+ ${v.documentTypeVariableName},
3907
+ ${v.isPhDocumentOfTypeFunctionName},
3908
+ ${v.assertIsPhDocumentOfTypeFunctionName},
3909
+ ${v.isPhStateOfTypeFunctionName},
3910
+ ${v.assertIsPhStateOfTypeFunctionName},
3911
+ } from "${v.versionedDocumentModelPackageImportPath}";
3912
+ import { ZodError } from "zod";
3913
+
3914
+ describe("${v.pascalCaseDocumentType} Document Model", () => {
3915
+ it("should create a new ${v.pascalCaseDocumentType} document", () => {
3916
+ const document = utils.createDocument();
3917
+
3918
+ expect(document).toBeDefined();
3919
+ expect(document.header.documentType).toBe(${v.documentTypeVariableName});
3920
+ });
3921
+
3922
+ it("should create a new ${v.pascalCaseDocumentType} document with a valid initial state", () => {
3923
+ const document = utils.createDocument();
3924
+ expect(document.state.global).toStrictEqual(initialGlobalState);
3925
+ expect(document.state.local).toStrictEqual(initialLocalState);
3926
+ expect(${v.isPhDocumentOfTypeFunctionName}(document)).toBe(true);
3927
+ expect(${v.isPhStateOfTypeFunctionName}(document.state)).toBe(true);
3928
+ });
3929
+ it("should reject a document that is not a ${v.pascalCaseDocumentType} document", () => {
3930
+ const wrongDocumentType = utils.createDocument();
3931
+ wrongDocumentType.header.documentType = "the-wrong-thing-1234";
3932
+ try {
3933
+ expect(${v.assertIsPhDocumentOfTypeFunctionName}(wrongDocumentType)).toThrow();
3934
+ expect(${v.isPhDocumentOfTypeFunctionName}(wrongDocumentType)).toBe(false);
3935
+ } catch (error) {
3936
+ expect(error).toBeInstanceOf(ZodError);
3937
+ }
3938
+ });
3939
+ const wrongState = utils.createDocument();
3940
+ // @ts-expect-error - we are testing the error case
3941
+ wrongState.state.global = {
3942
+ ...{ notWhat: "you want" },
3943
+ };
3944
+ try {
3945
+ expect(${v.isPhStateOfTypeFunctionName}(wrongState.state)).toBe(false);
3946
+ expect(${v.assertIsPhStateOfTypeFunctionName}(wrongState.state)).toThrow();
3947
+ expect(${v.isPhDocumentOfTypeFunctionName}(wrongState)).toBe(false);
3948
+ expect(${v.assertIsPhDocumentOfTypeFunctionName}(wrongState)).toThrow();
3949
+ } catch (error) {
3950
+ expect(error).toBeInstanceOf(ZodError);
3951
+ }
3952
+
3953
+ const wrongInitialState = utils.createDocument();
3954
+ // @ts-expect-error - we are testing the error case
3955
+ wrongInitialState.initialState.global = {
3956
+ ...{ notWhat: "you want" },
3957
+ };
3958
+ try {
3959
+ expect(${v.isPhStateOfTypeFunctionName}(wrongInitialState.state)).toBe(false);
3960
+ expect(${v.assertIsPhStateOfTypeFunctionName}(wrongInitialState.state)).toThrow();
3961
+ expect(${v.isPhDocumentOfTypeFunctionName}(wrongInitialState)).toBe(false);
3962
+ expect(${v.assertIsPhDocumentOfTypeFunctionName}(wrongInitialState)).toThrow();
3963
+ } catch (error) {
3964
+ expect(error).toBeInstanceOf(ZodError);
3965
+ }
3966
+
3967
+ const missingIdInHeader = utils.createDocument();
3968
+ // @ts-expect-error - we are testing the error case
3969
+ delete missingIdInHeader.header.id;
3970
+ try {
3971
+ expect(${v.isPhDocumentOfTypeFunctionName}(missingIdInHeader)).toBe(false);
3972
+ expect(${v.assertIsPhDocumentOfTypeFunctionName}(missingIdInHeader)).toThrow();
3973
+ } catch (error) {
3974
+ expect(error).toBeInstanceOf(ZodError);
3975
+ }
3976
+
3977
+ const missingNameInHeader = utils.createDocument();
3978
+ // @ts-expect-error - we are testing the error case
3979
+ delete missingNameInHeader.header.name;
3980
+ try {
3981
+ expect(${v.isPhDocumentOfTypeFunctionName}(missingNameInHeader)).toBe(false);
3982
+ expect(${v.assertIsPhDocumentOfTypeFunctionName}(missingNameInHeader)).toThrow();
3983
+ } catch (error) {
3984
+ expect(error).toBeInstanceOf(ZodError);
3985
+ }
3986
+
3987
+ const missingCreatedAtUtcIsoInHeader = utils.createDocument();
3988
+ // @ts-expect-error - we are testing the error case
3989
+ delete missingCreatedAtUtcIsoInHeader.header.createdAtUtcIso;
3990
+ try {
3991
+ expect(${v.isPhDocumentOfTypeFunctionName}(missingCreatedAtUtcIsoInHeader)).toBe(false);
3992
+ expect(${v.assertIsPhDocumentOfTypeFunctionName}(missingCreatedAtUtcIsoInHeader)).toThrow();
3993
+ } catch (error) {
3994
+ expect(error).toBeInstanceOf(ZodError);
3995
+ }
3996
+
3997
+ const missingLastModifiedAtUtcIsoInHeader = utils.createDocument();
3998
+ // @ts-expect-error - we are testing the error case
3999
+ delete missingLastModifiedAtUtcIsoInHeader.header.lastModifiedAtUtcIso;
4000
+ try {
4001
+ expect(${v.isPhDocumentOfTypeFunctionName}(missingLastModifiedAtUtcIsoInHeader)).toBe(false);
4002
+ expect(
4003
+ ${v.assertIsPhDocumentOfTypeFunctionName}(missingLastModifiedAtUtcIsoInHeader),
4004
+ ).toThrow();
4005
+ } catch (error) {
4006
+ expect(error).toBeInstanceOf(ZodError);
4007
+ }
4008
+ });
4009
+ `.raw;
4010
+ //#endregion
4011
+ //#region src/templates/document-model/tests/module.test.ts
4012
+ function makeModuleOperationsTypeName(module) {
4013
+ return `${pascalCase(module.name)}Operations`;
4014
+ }
4015
+ function makeCamelCaseActionNamesForImport(actions) {
4016
+ return actions.map((a) => camelCase(a.name));
4017
+ }
4018
+ function makeActionInputSchemasForImport(actions) {
4019
+ return actions.map((a) => `${pascalCase(a.name)}InputSchema`);
4020
+ }
4021
+ function makeTestCaseForAction(action, isPhDocumentOfTypeFunctionName) {
4022
+ const camelCaseActionName = camelCase(action.name);
4023
+ const pascalCaseActionName = pascalCase(action.name);
4024
+ const constantCaseActionName = constantCase(action.name);
4025
+ const actionInputSchemaName = `${pascalCaseActionName}InputSchema`;
4026
+ const scope = action.scope;
4027
+ return ts`
4028
+ it('should handle ${camelCaseActionName} operation', () => {
4029
+ const document = utils.createDocument();
4030
+ const input = generateMock(
4031
+ ${actionInputSchemaName}(),
4032
+ );
4033
+
4034
+ const updatedDocument = reducer(
4035
+ document,
4036
+ ${camelCaseActionName}(input),
4037
+ );
4038
+
4039
+ expect(${isPhDocumentOfTypeFunctionName}(updatedDocument)).toBe(true);
4040
+ expect(updatedDocument.operations.${scope}).toHaveLength(1);
4041
+ expect(updatedDocument.operations.${scope}[0].action.type).toBe(
4042
+ "${constantCaseActionName}",
4043
+ );
4044
+ expect(updatedDocument.operations.${scope}[0].action.input).toStrictEqual(input);
4045
+ expect(updatedDocument.operations.${scope}[0].index).toEqual(0);
4046
+ });
4047
+ `.raw;
4048
+ }
4049
+ function makeActionImportNames(v) {
4050
+ const actionNames = makeCamelCaseActionNamesForImport(v.actions);
4051
+ const inputSchemaNames = makeActionInputSchemasForImport(v.actions);
4052
+ return [
4053
+ "reducer",
4054
+ "utils",
4055
+ v.isPhDocumentOfTypeFunctionName,
4056
+ ...actionNames,
4057
+ ...inputSchemaNames
4058
+ ];
4059
+ }
4060
+ function makeActionsImports(v) {
4061
+ return ts`
4062
+ import {
4063
+ ${makeActionImportNames(v).join("\n")}
4064
+ } from "${v.versionedDocumentModelPackageImportPath}";
4065
+ `.raw;
4066
+ }
4067
+ function makeTestCasesForActions(actions, isPhDocumentOfTypeFunctionName) {
4068
+ return actions.map((action) => makeTestCaseForAction(action, isPhDocumentOfTypeFunctionName)).join("\n\n");
4069
+ }
4070
+ const documentModelOperationsModuleTestFileTemplate = (v) => ts`
4071
+ /**
4072
+ * This is a scaffold file meant for customization:
4073
+ * - change it by adding new tests or modifying the existing ones
4074
+ */
4075
+
4076
+ import { describe, it, expect } from 'vitest';
4077
+ import { generateMock } from '@powerhousedao/common';
4078
+ import {
4079
+ reducer,
4080
+ utils,
4081
+ ${v.isPhDocumentOfTypeFunctionName},
4082
+ ${makeCamelCaseActionNamesForImport(v.actions)},
4083
+ ${makeActionInputSchemasForImport(v.actions)},
4084
+ } from "${v.versionedDocumentModelPackageImportPath}";
4085
+
4086
+ describe("${makeModuleOperationsTypeName(v.module)}", () => {
4087
+ ${makeTestCasesForActions(v.actions, v.isPhDocumentOfTypeFunctionName)}
4088
+ });
4089
+
4090
+ `.raw;
4091
+ //#endregion
4092
+ //#region src/templates/document-model/upgrades/upgrade-manifest.ts
4093
+ const upgradeManifestTemplate = (v) => ts`
4094
+ import type { UpgradeManifest } from "document-model";
4095
+ import { latestVersion, supportedVersions } from "./versions.js";
4096
+
4097
+ export const ${v.upgradeManifestName}: UpgradeManifest<typeof supportedVersions> = {
4098
+ documentType: "${v.documentModelId}",
4099
+ latestVersion,
4100
+ supportedVersions,
4101
+ upgrades: {},
4102
+ };
4103
+ `.raw;
4104
+ //#endregion
4105
+ //#region src/templates/document-model/upgrades/upgrade-transition.ts
4106
+ const upgradeTransitionTemplate = (v) => ts`
4107
+ import type { Action, PHDocument, UpgradeTransition } from "document-model";
4108
+ import type { ${v.phStateName} as StateV${v.previousVersion} } from "${v.documentModelPackageImportPath}/v${v.previousVersion}";
4109
+ import type { ${v.phStateName} as StateV${v.version} } from "${v.documentModelPackageImportPath}/v${v.version}";
4110
+
4111
+ function upgradeReducer(
4112
+ document: PHDocument<StateV${v.previousVersion}>,
4113
+ action: Action,
4114
+ ): PHDocument<StateV${v.version}> {
4115
+ return {
4116
+ ...document,
4117
+ };
4118
+ }
4119
+
4120
+ export const v${v.version}: UpgradeTransition = {
4121
+ toVersion: ${v.version},
4122
+ upgradeReducer,
4123
+ description: "",
4124
+ };
4125
+ `.raw;
4126
+ //#endregion
4127
+ //#region src/templates/document-model/utils.ts
4128
+ const documentModelUtilsTemplate = ({ phStateName, pascalCaseDocumentType }) => ts`
4129
+ import type { DocumentModelUtils } from "document-model";
4130
+ import type { ${phStateName} } from "./gen/types.js";
4131
+ import { utils as genUtils } from "./gen/utils.js";
4132
+ import * as customUtils from "./src/utils.js";
4133
+
4134
+ /** Utils for the ${pascalCaseDocumentType} document model */
4135
+ export const utils: DocumentModelUtils<${phStateName}> = { ...genUtils, ...customUtils };
4136
+ `.raw;
4137
+ //#endregion
4138
+ //#region src/templates/processors/utils.ts
4139
+ function getDocumentType(documentTypes) {
4140
+ if (!documentTypes.length) return `"*"`;
4141
+ return documentTypes.map((type) => `"${type}"`).join(", ");
4142
+ }
4143
+ //#endregion
4144
+ //#region src/templates/processors/analytics/factory.ts
4145
+ const analyticsFactoryTemplate = (v) => ts`
4146
+ import type {
4147
+ ProcessorApp,
4148
+ ProcessorFactoryBuilder,
4149
+ ProcessorRecord,
4150
+ IProcessorHostModule,
4151
+ } from "@powerhousedao/reactor-browser";
4152
+ import { type PHDocumentHeader } from "document-model";
4153
+ import { ${v.pascalCaseName} } from "./processor.js";
4154
+
4155
+ export const ${v.camelCaseName}FactoryBuilder: ProcessorFactoryBuilder = (module: IProcessorHostModule) => async (driveHeader: PHDocumentHeader, processorApp?: ProcessorApp) => {
4156
+ return [
4157
+ {
4158
+ processor: new ${v.pascalCaseName}(module.analyticsStore),
4159
+ filter: {
4160
+ branch: ["main"],
4161
+ documentId: ["*"],
4162
+ scope: ["*"],
4163
+ documentType: [${getDocumentType(v.documentTypes)}],
4164
+ },
4165
+ },
4166
+ ];
4167
+ }
4168
+ `.raw;
4169
+ //#endregion
4170
+ //#region src/templates/processors/analytics/index.ts
4171
+ const analyticsIndexTemplate = ts`
4172
+ export * from "./factory.js";
4173
+ export * from "./processor.js";
4174
+ `.raw;
4175
+ //#endregion
4176
+ //#region src/templates/processors/analytics/processor.ts
4177
+ const analyticsProcessorTemplate = (v) => ts`
4178
+ import type { AnalyticsSeriesInput, AnalyticsPath, IAnalyticsStore } from "@powerhousedao/analytics-engine-core";
4179
+ import type { OperationWithContext, IProcessor } from "@powerhousedao/reactor-browser";
4180
+
4181
+ export class ${v.pascalCaseName} implements IProcessor {
4182
+ private readonly NAMESPACE = "${v.pascalCaseName}";
4183
+
4184
+ private readonly inputs: AnalyticsSeriesInput[] = [];
4185
+
4186
+ constructor(private readonly analyticsStore: IAnalyticsStore) {
4187
+ //
4188
+ }
4189
+
4190
+ onOperations(operations: OperationWithContext[]): Promise<void> {
4191
+ return Promise.resolve();
4192
+ }
4193
+
4194
+ onDisconnect(): Promise<void> {
4195
+ return Promise.resolve();
4196
+ }
4197
+
4198
+ private async clearSource(source: AnalyticsPath) {
4199
+ try {
4200
+ await this.analyticsStore.clearSeriesBySource(source, true);
4201
+ } catch (e) {
4202
+ console.error(e);
4203
+ }
4204
+ }
4205
+ }
4206
+ `.raw;
4207
+ //#endregion
4208
+ //#region src/templates/processors/factory-builders.ts
4209
+ const factoryBuildersTemplate = ts`
4210
+ import type { ProcessorFactoryBuilder } from "@powerhousedao/reactor";
4211
+
4212
+ export const processorFactoryBuilders: ProcessorFactoryBuilder[] = [];
4213
+ `.raw;
4214
+ //#endregion
4215
+ //#region src/templates/processors/factory.ts
4216
+ const processorsFactoryTemplate = ts`
4217
+ /**
4218
+ * This file aggregates all processor factories
4219
+ * Auto-generated by codegen - DO NOT EDIT MANUALLY
4220
+ */
4221
+
4222
+ import type {
4223
+ IProcessorHostModule,
4224
+ ProcessorRecord,
4225
+ } from "@powerhousedao/reactor-browser";
4226
+ import type { PHDocumentHeader } from "document-model";
4227
+
4228
+ export const processorFactory = async (module: IProcessorHostModule) => {
4229
+ const { processorFactoryBuilders } =
4230
+ module.processorApp === "connect"
4231
+ ? await import("./connect.js")
4232
+ : await import("./switchboard.js");
4233
+
4234
+ const factories = await Promise.all(
4235
+ processorFactoryBuilders.map(
4236
+ async (buildFactory) => await buildFactory(module),
4237
+ ),
4238
+ );
4239
+
4240
+ // Return the inner function that will be called for each drive
4241
+ return async (driveHeader: PHDocumentHeader): Promise<ProcessorRecord[]> => {
4242
+ const processors: ProcessorRecord[] = [];
4243
+
4244
+ // Call each cached factory with the driveHeader
4245
+ for (const factory of factories) {
4246
+ const factoryProcessors = await factory(driveHeader, module.processorApp);
4247
+ processors.push(...factoryProcessors);
4248
+ }
4249
+
4250
+ return processors;
4251
+ };
4252
+ };
4253
+ `.raw;
4254
+ //#endregion
4255
+ //#region src/templates/processors/index.ts
4256
+ const processorsIndexTemplate = ts`
4257
+ /**
4258
+ * Processor exports
4259
+ * This file is auto-generated and updated by codegen
4260
+ */
4261
+
4262
+ export { processorFactory } from "./factory.js";
4263
+ `.raw;
4264
+ //#endregion
4265
+ //#region src/templates/processors/relational-db/factory.ts
4266
+ const relationalDbFactoryTemplate = (v) => ts`
4267
+ import type {
4268
+ IProcessorHostModule,
4269
+ ProcessorApp,
4270
+ ProcessorFactoryBuilder,
4271
+ ProcessorFilter,
4272
+ ProcessorRecord,
4273
+ } from "@powerhousedao/reactor-browser"
4274
+ import type { PHDocumentHeader } from "document-model";
4275
+ import { ${v.pascalCaseName} } from "./processor.js";
4276
+
4277
+ export const ${v.camelCaseName}FactoryBuilder: ProcessorFactoryBuilder = (module: IProcessorHostModule) => async (driveHeader: PHDocumentHeader, processorApp?: ProcessorApp) => {
4278
+ // Create a namespace for the processor and the provided drive id
4279
+ const namespace = ${v.pascalCaseName}.getNamespace(driveHeader.id);
4280
+
4281
+ // Create a namespaced db for the processor
4282
+ const store = await module.relationalDb.createNamespace<${v.pascalCaseName}>(
4283
+ namespace,
4284
+ );
4285
+
4286
+ // Create a filter for the processor
4287
+ const filter: ProcessorFilter = {
4288
+ branch: ["main"],
4289
+ documentId: ["*"],
4290
+ documentType: [${getDocumentType(v.documentTypes)}],
4291
+ scope: ["global"],
4292
+ };
4293
+
4294
+ // Create the processor
4295
+ const processor = new ${v.pascalCaseName}(namespace, filter, store);
4296
+ return [
4297
+ {
4298
+ processor,
4299
+ filter,
4300
+ },
4301
+ ];
4302
+ }
4303
+ `.raw;
4304
+ //#endregion
4305
+ //#region src/templates/processors/relational-db/index.ts
4306
+ const relationalDbIndexTemplate = ts`
4307
+ export * from "./factory.js";
4308
+ export * from "./processor.js";
4309
+ `.raw;
4310
+ //#endregion
4311
+ //#region src/templates/processors/relational-db/migrations.ts
4312
+ const relationalDbMigrationsTemplate = () => ts`
4313
+ import type { IRelationalDb } from "@powerhousedao/reactor-browser"
4314
+
4315
+ export async function up(db: IRelationalDb<any>): Promise<void> {
4316
+ // Create table
4317
+ await db.schema
4318
+ .createTable("todo")
4319
+ .addColumn("task", "varchar(255)")
4320
+ .addColumn("status", "boolean")
4321
+ .addPrimaryKeyConstraint("todo_pkey", [
4322
+ "task"
4323
+ ])
4324
+ .ifNotExists()
4325
+ .execute();
4326
+ }
4327
+
4328
+ export async function down(db: IRelationalDb<any>): Promise<void> {
4329
+ // drop table
4330
+ await db.schema.dropTable("todo").execute();
4331
+ }
4332
+ `.raw;
4333
+ //#endregion
4334
+ //#region src/templates/processors/relational-db/processor.ts
4335
+ const defaultNamespaceComment = "// Default namespace: `${this.name}_${driveId.replaceAll(\"-\", \"_\")}`";
4336
+ const relationalDbProcessorTemplate = (v) => ts`
4337
+ import { RelationalDbProcessor } from "@powerhousedao/reactor-browser";
4338
+ import type { OperationWithContext } from "document-model";
4339
+ import { up } from "./migrations.js";
4340
+ import type { DB } from "./schema.js";
4341
+
4342
+ export class ${v.pascalCaseName} extends RelationalDbProcessor<DB> {
4343
+ onOperations(operations: OperationWithContext[]): Promise<void> {
4344
+ return Promise.resolve();
4345
+ }
4346
+
4347
+ onDisconnect(): Promise<void> {
4348
+ return Promise.resolve();
4349
+ }
4350
+
4351
+ static override getNamespace(driveId: string): string {
4352
+ ${defaultNamespaceComment}
4353
+ return super.getNamespace(driveId);
4354
+ }
4355
+
4356
+ override async initAndUpgrade(): Promise<void> {
4357
+ await up(this.relationalDb);
4358
+ }
4359
+ }
4360
+ `.raw;
4361
+ //#endregion
4362
+ //#region src/templates/processors/relational-db/schema.ts
4363
+ const relationalDbSchemaTemplate = () => ts`
4364
+ export interface Todo {
4365
+ status: boolean | null;
4366
+ task: string;
4367
+ }
4368
+
4369
+ export interface DB {
4370
+ todo: Todo;
4371
+ }
4372
+ `.raw;
4373
+ //#endregion
4374
+ //#region src/templates/subgraphs/index-file.ts
4375
+ const subgraphIndexFileTemplate = (v) => ts`
4376
+ import { BaseSubgraph } from "@powerhousedao/reactor-api";
4377
+ import type { DocumentNode } from "graphql";
4378
+ import { schema } from "./schema.js";
4379
+ import { getResolvers } from "./resolvers.js";
4380
+
4381
+ export class ${v.pascalCaseName}Subgraph extends BaseSubgraph {
4382
+ name = "${v.kebabCaseName}";
4383
+ typeDefs: DocumentNode = schema;
4384
+ resolvers = getResolvers(this);
4385
+ additionalContextFields = {};
4386
+ async onSetup() {}
4387
+ async onDisconnect() {}
4388
+ }
4389
+ `.raw;
4390
+ //#endregion
4391
+ //#region src/templates/subgraphs/lib-file.ts
4392
+ const subgraphLibFileTemplate = () => ts`
4393
+ /**
4394
+ * This is a scaffold file meant for customization.
4395
+ * Delete the file and run the code generator again to have it reset
4396
+ */
4397
+ `.raw;
4398
+ //#endregion
4399
+ //#region src/templates/subgraphs/custom-schema.ts
4400
+ const customSubgraphSchemaTemplate = (v) => ts`
4401
+ import { gql } from "graphql-tag";
4402
+ import type { DocumentNode } from "graphql";
4403
+
4404
+ export const schema: DocumentNode = gql\`
4405
+ """
4406
+ ${v.pascalCaseName} Queries
4407
+ """
4408
+ type ${v.pascalCaseName}Queries {
4409
+ example(driveId: String!): String
4410
+ }
4411
+
4412
+ type Query {
4413
+ ${v.camelCaseName}: ${v.pascalCaseName}Queries!
4414
+ }
4415
+
4416
+ \`
4417
+ `.raw;
4418
+ //#endregion
4419
+ //#region src/templates/subgraphs/custom-resolvers.ts
4420
+ const customSubgraphResolversTemplate = (v) => ts`
4421
+ import { type ISubgraph } from "@powerhousedao/reactor-api";
4422
+
4423
+ export const getResolvers = (subgraph: ISubgraph): Record<string, unknown> => {
4424
+ const reactor = subgraph.reactorClient;
4425
+
4426
+ return ({
4427
+ Query: {
4428
+ ${v.camelCaseName}: () => ({}), // namespace resolver for nested queries
4429
+ },
4430
+ ${v.pascalCaseName}Queries: {
4431
+ example: async (parent: unknown, args: { driveId: string }) => {
4432
+ return "example";
4433
+ },
4434
+ },
4435
+ });
4436
+ };
4437
+ `.raw;
4438
+ //#endregion
4439
+ //#region src/templates/subgraphs/document-model-schema.ts
4440
+ const documentModelSubgraphSchemaTemplate = (v) => {
4441
+ const mutationFields = v.modules.flatMap((module) => module.operations.map((op) => ` ${v.pascalCaseDocumentType}_${camel$1(op.name)}(driveId:String, docId:PHID, input:${v.pascalCaseDocumentType}_${pascal$1(op.name)}Input): Int`)).join("\n");
4442
+ const moduleSchemas = v.modules.map((module) => {
4443
+ return `${`\n"""\nModule: ${pascal$1(module.name)}\n"""`}\n${module.operations.map((op) => op.schema).join("\n")}`;
4444
+ }).join("\n");
4445
+ return `import { gql } from "graphql-tag";
4446
+ import type { DocumentNode } from "graphql";
4447
+
4448
+ export const schema: DocumentNode = gql\`
4449
+ """
4450
+ Queries: ${v.pascalCaseDocumentType} Document
4451
+ """
4452
+
4453
+ type ${v.pascalCaseDocumentType}Queries {
4454
+ getDocument(docId: PHID!, driveId: PHID): ${v.pascalCaseDocumentType}
4455
+ getDocuments(driveId: String): [${v.pascalCaseDocumentType}!]
4456
+ }
4457
+
4458
+ type Query {
4459
+ ${v.pascalCaseDocumentType}: ${v.pascalCaseDocumentType}Queries
4460
+ }
4461
+
4462
+ """
4463
+ Mutations: ${v.pascalCaseDocumentType}
4464
+ """
4465
+ type Mutation {
4466
+
4467
+ ${v.pascalCaseDocumentType}_createDocument(name:String!, driveId:String): String
4468
+
4469
+ ${mutationFields}
4470
+ }
4471
+
4472
+ ${moduleSchemas}
4473
+ \`
4474
+ `;
4475
+ };
4476
+ function pascal$1(name) {
4477
+ return name.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
4478
+ }
4479
+ function camel$1(name) {
4480
+ const p = pascal$1(name);
4481
+ return p.charAt(0).toLowerCase() + p.slice(1);
4482
+ }
4483
+ //#endregion
4484
+ //#region src/templates/subgraphs/document-model-resolvers.ts
4485
+ const documentModelSubgraphResolversTemplate = (v) => {
4486
+ const inputTypeImports = v.modules.flatMap((m) => m.operations.map((o) => `${pascal(o.name)}Input`)).join(",\n ");
4487
+ const operationMutations = v.modules.flatMap((module) => module.operations.map((op) => ` ${v.pascalCaseDocumentType}_${camel(op.name)}: async (_: unknown, args: { docId: string, input: ${pascal(op.name)}Input}) => {
4488
+ const { docId, input } = args;
4489
+ const doc = await reactorClient.get<${v.pascalCaseDocumentType}Document>(docId);
4490
+ if(!doc) {
4491
+ throw new Error("Document not found");
4492
+ }
4493
+
4494
+ await reactorClient.execute(
4495
+ docId,
4496
+ "main",
4497
+ [actions.${camel(op.name)}(input)]
4498
+ );
4499
+
4500
+ return true;
4501
+ },
4502
+ `)).join("\n");
4503
+ return `import type { BaseSubgraph } from "@powerhousedao/reactor-api";
4504
+ import { addFile } from "@powerhousedao/shared/document-drive";
4505
+ import { setName } from "document-model";
4506
+ import {
4507
+ actions,
4508
+ ${v.documentTypeVariableName},
4509
+ } from "${v.documentModelDir}";
4510
+ import type {
4511
+ ${v.phDocumentTypeName},
4512
+ ${inputTypeImports}
4513
+ } from "${v.documentModelDir}";
4514
+
4515
+ export const getResolvers = (subgraph: BaseSubgraph): Record<string, unknown> => {
4516
+ const reactorClient = subgraph.reactorClient;
4517
+
4518
+ return ({
4519
+ Query: {
4520
+ ${v.pascalCaseDocumentType}: async () => {
4521
+ return {
4522
+ getDocument: async (args: { docId: string, driveId: string }) => {
4523
+ const { docId, driveId } = args;
4524
+
4525
+ if(!docId) {
4526
+ throw new Error("Document id is required");
4527
+ }
4528
+
4529
+ if(driveId) {
4530
+ const children = await reactorClient.getChildren(driveId);
4531
+ const childIds = children.results.map(d => d.header.id);
4532
+ if(!childIds.includes(docId)) {
4533
+ throw new Error(\`Document with id \${docId} is not part of \${driveId}\`);
4534
+ }
4535
+ }
4536
+
4537
+ const doc = await reactorClient.get<${v.phDocumentTypeName}>(docId);
4538
+ return {
4539
+ driveId: driveId,
4540
+ ...doc,
4541
+ ...doc.header,
4542
+ created: doc.header.createdAtUtcIso,
4543
+ lastModified: doc.header.lastModifiedAtUtcIso,
4544
+ state: doc.state.global,
4545
+ stateJSON: doc.state.global,
4546
+ revision: doc.header?.revision?.global ?? 0,
4547
+ };
4548
+ },
4549
+ getDocuments: async (args: { driveId?: string }) => {
4550
+ const { driveId } = args;
4551
+ const result = await reactorClient.find({ type: ${v.documentTypeVariableName}, ...(driveId ? { parentId: driveId } : {}) });
4552
+ return result.results.map((_doc) => {
4553
+ const doc = _doc as ${v.phDocumentTypeName};
4554
+ return {
4555
+ driveId: driveId,
4556
+ ...doc,
4557
+ ...doc.header,
4558
+ created: doc.header.createdAtUtcIso,
4559
+ lastModified: doc.header.lastModifiedAtUtcIso,
4560
+ state: doc.state.global,
4561
+ stateJSON: doc.state.global,
4562
+ revision: doc.header?.revision?.global ?? 0,
4563
+ };
4564
+ });
4565
+ },
4566
+ };
4567
+ },
4568
+ },
4569
+ Mutation: {
4570
+ ${v.pascalCaseDocumentType}_createDocument: async (_: unknown, args: { name: string, driveId?: string }) => {
4571
+ const { driveId, name } = args;
4572
+ const document = await reactorClient.createEmpty(${v.documentTypeVariableName});
4573
+
4574
+ if(driveId) {
4575
+ await reactorClient.execute(
4576
+ driveId,
4577
+ "main",
4578
+ [addFile({
4579
+ name,
4580
+ id: document.header.id,
4581
+ documentType: ${v.documentTypeVariableName},
4582
+ })],
4583
+ );
4584
+ }
4585
+
4586
+ if(name) {
4587
+ await reactorClient.execute(
4588
+ document.header.id,
4589
+ "main",
4590
+ [setName(name)],
4591
+ );
4592
+ }
4593
+
4594
+ return document.header.id;
4595
+ },
4596
+
4597
+ ${operationMutations}
4598
+ },
4599
+ });
4600
+ };
4601
+ `;
4602
+ };
4603
+ function pascal(name) {
4604
+ return name.split(/[-_\s]+/).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join("");
4605
+ }
4606
+ function camel(name) {
4607
+ const p = pascal(name);
4608
+ return p.charAt(0).toLowerCase() + p.slice(1);
4609
+ }
4610
+ //#endregion
4611
+ export { tsConfigTemplate as $, documentModelHooksFileTemplate as A, claudeSettingsLocalTemplate as At, getModuleExportType as B, appDriveContentsFileTemplate as Bt, makeActionsImports as C, documentModelsIndexTemplate as Ct, documentModelSrcIndexFileTemplate as D, dockerfileTemplate as Dt, documentModelSrcUtilsTemplate as E, nginxConfTemplate as Et, documentModelPhFactoriesFileTemplate as F, folderTreeFileTemplate as Ft, documentModelGenControllerFileTemplate as G, documentModelDocumentTypeTemplate as H, documentModelOperationsModuleOperationsFileTemplate as I, appFoldersFileTemplate as It, documentEditorModuleFileTemplate as J, documentModelGenActionsFileTemplate as K, documentModelOperationsModuleErrorFileTemplate as L, appFilesFileTemplate as Lt, documentModelGenTypesTemplate as M, appEditorFileTemplate as Mt, documentModelSchemaIndexTemplate as N, appConfigFileTemplate as Nt, documentModelModuleFileTemplate as O, connectEntrypointTemplate as Ot, documentModelGenReducerFileTemplate as P, driveExplorerNavigationBreadcrumbsFileTemplate as Pt, viteConfigTemplate as Q, documentModelOperationsModuleCreatorsFileTemplate as R, emptyStateFileTemplate as Rt, makeActionImportNames as S, editorsTemplate as St, documentModelTestFileTemplate as T, switchboardEntrypointTemplate as Tt, documentModelDocumentSchemaFileTemplate as U, documentModelGenIndexFileTemplate as V, createDocumentFileTemplate as Vt, documentModelGenCreatorsFileTemplate as W, docsFromCliHelpTemplate as X, documentEditorEditorFileTemplate as Y, vitestConfigTemplate as Z, analyticsFactoryTemplate as _, gitIgnoreTemplate as _t, subgraphLibFileTemplate as a, buildPowerhouseConfigTemplate as at, upgradeManifestTemplate as b, eslintConfigTemplate as bt, relationalDbProcessorTemplate as c, exportsTemplate as ct, relationalDbFactoryTemplate as d, mcpTemplate as dt, tsconfigPathsTemplate as et, processorsIndexTemplate as f, mainTsxTemplate as ft, analyticsIndexTemplate as g, indexHtmlTemplate as gt, analyticsProcessorTemplate as h, legacyIndexHtmlTemplate as ht, customSubgraphSchemaTemplate as i, ManifestTemplate as it, documentModelGenUtilsTemplate as j, agentsTemplate as jt, documentModelIndexTemplate as k, cursorMcpTemplate as kt, relationalDbMigrationsTemplate as l, packageJsonTemplate as lt, factoryBuildersTemplate as m, indexTsTemplate as mt, documentModelSubgraphSchemaTemplate as n, styleTemplate as nt, subgraphIndexFileTemplate as o, packageJsonExportsTemplate as ot, processorsFactoryTemplate as p, licenseTemplate as pt, documentModelRootActionsFileTemplate as q, customSubgraphResolversTemplate as r, readmeTemplate as rt, relationalDbSchemaTemplate as s, packageJsonScriptsTemplate as st, documentModelSubgraphResolversTemplate as t, subgraphsIndexTemplate as tt, relationalDbIndexTemplate as u, npmrcTemplate as ut, documentModelUtilsTemplate as v, syncAndPublishWorkflowTemplate as vt, makeTestCaseForAction as w, documentModelsTemplate as wt, documentModelOperationsModuleTestFileTemplate as x, editorsIndexTemplate as xt, upgradeTransitionTemplate as y, geminiSettingsTemplate as yt, documentModelOperationModuleActionsFileTemplate as z, driveExplorerFileTemplate as zt };
4612
+
4613
+ //# sourceMappingURL=templates-Bn7kq5sb.mjs.map