@voltro/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (626) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +57 -0
  3. package/README.md +26 -0
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +20236 -0
  6. package/bin/voltro.mjs +43 -0
  7. package/dist/bin.d.ts +1 -0
  8. package/dist/bin.js +9 -0
  9. package/dist/commands-CfPH2Wf4.js +18061 -0
  10. package/dist/frameworkInspectState-CX2250XB.js +86 -0
  11. package/dist/index.d.ts +48 -0
  12. package/dist/index.js +5 -0
  13. package/dist/inspectState.d.ts +116 -0
  14. package/dist/inspectState.js +2 -0
  15. package/dist/startup.d.ts +26 -0
  16. package/dist/startup.js +2 -0
  17. package/dist/startupRunner-CRhuUl91.js +71 -0
  18. package/package.json +88 -0
  19. package/templates/AGENTS.core.md +258 -0
  20. package/templates/AGENTS.md +351 -0
  21. package/templates/agent-docs/_index.md +93 -0
  22. package/templates/agent-docs/_manifest.json +655 -0
  23. package/templates/agent-docs/ai.md +1845 -0
  24. package/templates/agent-docs/authentication.md +1788 -0
  25. package/templates/agent-docs/caching.md +624 -0
  26. package/templates/agent-docs/cli.md +1650 -0
  27. package/templates/agent-docs/configuration.md +295 -0
  28. package/templates/agent-docs/data.md +2172 -0
  29. package/templates/agent-docs/database/advancedqueries.md +1583 -0
  30. package/templates/agent-docs/database/columntypes.md +1200 -0
  31. package/templates/agent-docs/database/hosting.md +881 -0
  32. package/templates/agent-docs/database/migrations.md +2938 -0
  33. package/templates/agent-docs/database/misc.md +270 -0
  34. package/templates/agent-docs/database/overview.md +108 -0
  35. package/templates/agent-docs/database/querying.md +1622 -0
  36. package/templates/agent-docs/database/scaling.md +331 -0
  37. package/templates/agent-docs/database/schema.md +1458 -0
  38. package/templates/agent-docs/database/seedsdialects.md +1235 -0
  39. package/templates/agent-docs/database/transactions.md +285 -0
  40. package/templates/agent-docs/deployment.md +999 -0
  41. package/templates/agent-docs/internationalization.md +359 -0
  42. package/templates/agent-docs/introduction.md +438 -0
  43. package/templates/agent-docs/multi-tenancy.md +610 -0
  44. package/templates/agent-docs/observability.md +350 -0
  45. package/templates/agent-docs/plugins.md +1273 -0
  46. package/templates/agent-docs/reference.md +978 -0
  47. package/templates/agent-docs/routing.md +1553 -0
  48. package/templates/agent-docs/scheduling.md +666 -0
  49. package/templates/agent-docs/schema-driven-ui.md +607 -0
  50. package/templates/agent-docs/security.md +42 -0
  51. package/templates/agent-docs/templates/apibackends.md +3214 -0
  52. package/templates/agent-docs/templates/appshells.md +2062 -0
  53. package/templates/agent-docs/templates/custom.md +128 -0
  54. package/templates/agent-docs/templates/overview.md +122 -0
  55. package/templates/agent-docs/templates/serverless.md +315 -0
  56. package/templates/agent-docs/testing.md +376 -0
  57. package/templates/agent-docs/workflows.md +1351 -0
  58. package/templates/apps/api-ai/README.md +105 -0
  59. package/templates/apps/api-ai/actions/summarize.action.server.tsx +32 -0
  60. package/templates/apps/api-ai/actions/summarize.action.ts +33 -0
  61. package/templates/apps/api-ai/agents/support.agent.server.tsx +31 -0
  62. package/templates/apps/api-ai/agents/support.agent.tsx +27 -0
  63. package/templates/apps/api-ai/app.config.ts +57 -0
  64. package/templates/apps/api-ai/database/schema.ts +67 -0
  65. package/templates/apps/api-ai/package.json +27 -0
  66. package/templates/apps/api-ai/seeds/docs.seed.ts +67 -0
  67. package/templates/apps/api-ai/template.json +6 -0
  68. package/templates/apps/api-ai/tests/summarize.test.ts +50 -0
  69. package/templates/apps/api-ai/tools/searchDocs.tool.tsx +60 -0
  70. package/templates/apps/api-ai/tsconfig.json +5 -0
  71. package/templates/apps/api-auth/.env +17 -0
  72. package/templates/apps/api-auth/README.md +109 -0
  73. package/templates/apps/api-auth/actions/me.action.server.ts +20 -0
  74. package/templates/apps/api-auth/actions/me.action.ts +19 -0
  75. package/templates/apps/api-auth/app.config.ts +59 -0
  76. package/templates/apps/api-auth/database/schema.ts +26 -0
  77. package/templates/apps/api-auth/package.json +28 -0
  78. package/templates/apps/api-auth/template.json +6 -0
  79. package/templates/apps/api-auth/tests/me.test.ts +37 -0
  80. package/templates/apps/api-auth/tsconfig.json +5 -0
  81. package/templates/apps/api-backend/README.md +25 -0
  82. package/templates/apps/api-backend/app.config.ts +39 -0
  83. package/templates/apps/api-backend/database/schema.ts +57 -0
  84. package/templates/apps/api-backend/mutations/notes.create.mutation.server.ts +19 -0
  85. package/templates/apps/api-backend/mutations/notes.create.mutation.ts +37 -0
  86. package/templates/apps/api-backend/package.json +28 -0
  87. package/templates/apps/api-backend/queries/notes.query.server.ts +14 -0
  88. package/templates/apps/api-backend/queries/notes.query.ts +20 -0
  89. package/templates/apps/api-backend/template.json +6 -0
  90. package/templates/apps/api-backend/tests/notes.create.test.ts +50 -0
  91. package/templates/apps/api-backend/tsconfig.json +5 -0
  92. package/templates/apps/api-backend-deactivation/README.md +49 -0
  93. package/templates/apps/api-backend-deactivation/actions/users.get.action.server.ts +17 -0
  94. package/templates/apps/api-backend-deactivation/actions/users.get.action.ts +18 -0
  95. package/templates/apps/api-backend-deactivation/app.config.ts +20 -0
  96. package/templates/apps/api-backend-deactivation/database/schema.ts +41 -0
  97. package/templates/apps/api-backend-deactivation/mutations/users.create.mutation.server.ts +6 -0
  98. package/templates/apps/api-backend-deactivation/mutations/users.create.mutation.ts +16 -0
  99. package/templates/apps/api-backend-deactivation/mutations/users.deactivate.mutation.server.ts +10 -0
  100. package/templates/apps/api-backend-deactivation/mutations/users.deactivate.mutation.ts +19 -0
  101. package/templates/apps/api-backend-deactivation/package.json +28 -0
  102. package/templates/apps/api-backend-deactivation/template.json +6 -0
  103. package/templates/apps/api-backend-deactivation/tests/users.deactivate.test.ts +47 -0
  104. package/templates/apps/api-backend-deactivation/tsconfig.json +5 -0
  105. package/templates/apps/api-backend-mail/README.md +39 -0
  106. package/templates/apps/api-backend-mail/actions/sendWelcome.action.server.ts +15 -0
  107. package/templates/apps/api-backend-mail/actions/sendWelcome.action.ts +21 -0
  108. package/templates/apps/api-backend-mail/app.config.ts +34 -0
  109. package/templates/apps/api-backend-mail/database/schema.ts +57 -0
  110. package/templates/apps/api-backend-mail/emails/welcome.email.tsx +106 -0
  111. package/templates/apps/api-backend-mail/mutations/notes.create.mutation.server.ts +19 -0
  112. package/templates/apps/api-backend-mail/mutations/notes.create.mutation.ts +37 -0
  113. package/templates/apps/api-backend-mail/package.json +30 -0
  114. package/templates/apps/api-backend-mail/queries/notes.query.server.ts +14 -0
  115. package/templates/apps/api-backend-mail/queries/notes.query.ts +20 -0
  116. package/templates/apps/api-backend-mail/template.json +6 -0
  117. package/templates/apps/api-backend-mail/tests/notes.create.test.ts +50 -0
  118. package/templates/apps/api-backend-mail/tsconfig.json +5 -0
  119. package/templates/apps/api-backend-mariadb/.env.example +35 -0
  120. package/templates/apps/api-backend-mariadb/README.md +31 -0
  121. package/templates/apps/api-backend-mariadb/app.config.ts +68 -0
  122. package/templates/apps/api-backend-mariadb/database/schema.ts +57 -0
  123. package/templates/apps/api-backend-mariadb/mutations/notes.create.mutation.server.ts +19 -0
  124. package/templates/apps/api-backend-mariadb/mutations/notes.create.mutation.ts +37 -0
  125. package/templates/apps/api-backend-mariadb/package.json +30 -0
  126. package/templates/apps/api-backend-mariadb/queries/notes.query.server.ts +14 -0
  127. package/templates/apps/api-backend-mariadb/queries/notes.query.ts +20 -0
  128. package/templates/apps/api-backend-mariadb/template.json +6 -0
  129. package/templates/apps/api-backend-mariadb/tests/notes.create.test.ts +50 -0
  130. package/templates/apps/api-backend-mariadb/tsconfig.json +5 -0
  131. package/templates/apps/api-backend-storage/README.md +86 -0
  132. package/templates/apps/api-backend-storage/actions/uploadAvatar.action.server.ts +21 -0
  133. package/templates/apps/api-backend-storage/actions/uploadAvatar.action.ts +21 -0
  134. package/templates/apps/api-backend-storage/actions/uploadDocument.action.server.ts +21 -0
  135. package/templates/apps/api-backend-storage/actions/uploadDocument.action.ts +20 -0
  136. package/templates/apps/api-backend-storage/app.config.ts +38 -0
  137. package/templates/apps/api-backend-storage/database/schema.ts +57 -0
  138. package/templates/apps/api-backend-storage/mutations/notes.create.mutation.server.ts +19 -0
  139. package/templates/apps/api-backend-storage/mutations/notes.create.mutation.ts +37 -0
  140. package/templates/apps/api-backend-storage/package.json +27 -0
  141. package/templates/apps/api-backend-storage/queries/notes.query.server.ts +14 -0
  142. package/templates/apps/api-backend-storage/queries/notes.query.ts +20 -0
  143. package/templates/apps/api-backend-storage/template.json +6 -0
  144. package/templates/apps/api-backend-storage/tests/notes.create.test.ts +50 -0
  145. package/templates/apps/api-backend-storage/tsconfig.json +5 -0
  146. package/templates/apps/api-data-advanced/.env +17 -0
  147. package/templates/apps/api-data-advanced/README.md +88 -0
  148. package/templates/apps/api-data-advanced/app.config.ts +56 -0
  149. package/templates/apps/api-data-advanced/database/actors.entity.ts +14 -0
  150. package/templates/apps/api-data-advanced/database/authors.entity.ts +30 -0
  151. package/templates/apps/api-data-advanced/database/authors.relations.ts +15 -0
  152. package/templates/apps/api-data-advanced/database/books.entity.ts +59 -0
  153. package/templates/apps/api-data-advanced/database/books.relations.ts +10 -0
  154. package/templates/apps/api-data-advanced/database/index.ts +23 -0
  155. package/templates/apps/api-data-advanced/database/tenants.entity.ts +11 -0
  156. package/templates/apps/api-data-advanced/package.json +28 -0
  157. package/templates/apps/api-data-advanced/queries/authors.withBooks.query.server.ts +18 -0
  158. package/templates/apps/api-data-advanced/queries/authors.withBooks.query.ts +40 -0
  159. package/templates/apps/api-data-advanced/queries/books.search.query.server.ts +17 -0
  160. package/templates/apps/api-data-advanced/queries/books.search.query.ts +39 -0
  161. package/templates/apps/api-data-advanced/seeds/catalog.seed.ts +101 -0
  162. package/templates/apps/api-data-advanced/template.json +6 -0
  163. package/templates/apps/api-data-advanced/tests/queries.test.ts +124 -0
  164. package/templates/apps/api-data-advanced/tsconfig.json +5 -0
  165. package/templates/apps/api-durable/README.md +81 -0
  166. package/templates/apps/api-durable/aggregates/orderStats.aggregate.ts +49 -0
  167. package/templates/apps/api-durable/app.config.ts +41 -0
  168. package/templates/apps/api-durable/database/schema.ts +65 -0
  169. package/templates/apps/api-durable/mutations/orders.approve.mutation.server.ts +43 -0
  170. package/templates/apps/api-durable/mutations/orders.approve.mutation.ts +23 -0
  171. package/templates/apps/api-durable/mutations/orders.place.mutation.server.ts +45 -0
  172. package/templates/apps/api-durable/mutations/orders.place.mutation.ts +40 -0
  173. package/templates/apps/api-durable/package.json +28 -0
  174. package/templates/apps/api-durable/schedules/nightlyReport.cron.tsx +37 -0
  175. package/templates/apps/api-durable/startup/warm.startup.tsx +33 -0
  176. package/templates/apps/api-durable/subscribers/orderChanges.subscribe.ts +27 -0
  177. package/templates/apps/api-durable/template.json +6 -0
  178. package/templates/apps/api-durable/tests/orders.place.test.ts +91 -0
  179. package/templates/apps/api-durable/triggers/order.placed.trigger.tsx +21 -0
  180. package/templates/apps/api-durable/tsconfig.json +5 -0
  181. package/templates/apps/api-durable/workflows/order.fulfill.workflow.server.tsx +103 -0
  182. package/templates/apps/api-durable/workflows/order.fulfill.workflow.tsx +25 -0
  183. package/templates/apps/api-feature-flags/README.md +63 -0
  184. package/templates/apps/api-feature-flags/actions/notes.export.action.server.ts +11 -0
  185. package/templates/apps/api-feature-flags/actions/notes.export.action.ts +18 -0
  186. package/templates/apps/api-feature-flags/app.config.ts +41 -0
  187. package/templates/apps/api-feature-flags/database/schema.ts +37 -0
  188. package/templates/apps/api-feature-flags/mutations/notes.create.mutation.server.ts +29 -0
  189. package/templates/apps/api-feature-flags/mutations/notes.create.mutation.ts +28 -0
  190. package/templates/apps/api-feature-flags/package.json +29 -0
  191. package/templates/apps/api-feature-flags/template.json +6 -0
  192. package/templates/apps/api-feature-flags/tests/notes.create.test.ts +67 -0
  193. package/templates/apps/api-feature-flags/tsconfig.json +5 -0
  194. package/templates/apps/api-governance/.env +4 -0
  195. package/templates/apps/api-governance/README.md +61 -0
  196. package/templates/apps/api-governance/actions/profiles.get.action.server.ts +17 -0
  197. package/templates/apps/api-governance/actions/profiles.get.action.ts +17 -0
  198. package/templates/apps/api-governance/app.config.ts +35 -0
  199. package/templates/apps/api-governance/database/schema.ts +41 -0
  200. package/templates/apps/api-governance/mutations/profiles.create.mutation.server.ts +17 -0
  201. package/templates/apps/api-governance/mutations/profiles.create.mutation.ts +21 -0
  202. package/templates/apps/api-governance/package.json +29 -0
  203. package/templates/apps/api-governance/template.json +6 -0
  204. package/templates/apps/api-governance/tests/profiles.create.test.ts +59 -0
  205. package/templates/apps/api-governance/tsconfig.json +5 -0
  206. package/templates/apps/api-kv/README.md +100 -0
  207. package/templates/apps/api-kv/actions/sync.pull.action.server.ts +75 -0
  208. package/templates/apps/api-kv/actions/sync.pull.action.ts +25 -0
  209. package/templates/apps/api-kv/actions/sync.reset.action.server.ts +25 -0
  210. package/templates/apps/api-kv/actions/sync.reset.action.ts +22 -0
  211. package/templates/apps/api-kv/actions/sync.status.action.server.ts +28 -0
  212. package/templates/apps/api-kv/actions/sync.status.action.ts +17 -0
  213. package/templates/apps/api-kv/app.config.ts +48 -0
  214. package/templates/apps/api-kv/database/schema.ts +62 -0
  215. package/templates/apps/api-kv/package.json +28 -0
  216. package/templates/apps/api-kv/queries/events.list.query.server.ts +14 -0
  217. package/templates/apps/api-kv/queries/events.list.query.ts +23 -0
  218. package/templates/apps/api-kv/template.json +6 -0
  219. package/templates/apps/api-kv/tests/sync.test.ts +103 -0
  220. package/templates/apps/api-kv/tsconfig.json +5 -0
  221. package/templates/apps/api-moderation/README.md +46 -0
  222. package/templates/apps/api-moderation/app.config.ts +33 -0
  223. package/templates/apps/api-moderation/database/schema.ts +45 -0
  224. package/templates/apps/api-moderation/mutations/comments.create.mutation.server.ts +8 -0
  225. package/templates/apps/api-moderation/mutations/comments.create.mutation.ts +20 -0
  226. package/templates/apps/api-moderation/mutations/posts.create.mutation.server.ts +9 -0
  227. package/templates/apps/api-moderation/mutations/posts.create.mutation.ts +25 -0
  228. package/templates/apps/api-moderation/package.json +29 -0
  229. package/templates/apps/api-moderation/template.json +6 -0
  230. package/templates/apps/api-moderation/tests/posts.create.test.ts +79 -0
  231. package/templates/apps/api-moderation/tsconfig.json +5 -0
  232. package/templates/apps/api-observability/README.md +106 -0
  233. package/templates/apps/api-observability/app.config.ts +32 -0
  234. package/templates/apps/api-observability/database/schema.ts +38 -0
  235. package/templates/apps/api-observability/mutations/notes.create.mutation.server.ts +33 -0
  236. package/templates/apps/api-observability/mutations/notes.create.mutation.ts +15 -0
  237. package/templates/apps/api-observability/package.json +29 -0
  238. package/templates/apps/api-observability/queries/notes.list.query.server.ts +7 -0
  239. package/templates/apps/api-observability/queries/notes.list.query.ts +14 -0
  240. package/templates/apps/api-observability/template.json +6 -0
  241. package/templates/apps/api-observability/tests/notes.create.test.ts +36 -0
  242. package/templates/apps/api-observability/tsconfig.json +5 -0
  243. package/templates/apps/api-ratelimit/README.md +49 -0
  244. package/templates/apps/api-ratelimit/app.config.ts +42 -0
  245. package/templates/apps/api-ratelimit/database/schema.ts +37 -0
  246. package/templates/apps/api-ratelimit/mutations/notes.create.mutation.server.ts +16 -0
  247. package/templates/apps/api-ratelimit/mutations/notes.create.mutation.ts +34 -0
  248. package/templates/apps/api-ratelimit/package.json +29 -0
  249. package/templates/apps/api-ratelimit/template.json +6 -0
  250. package/templates/apps/api-ratelimit/tests/notes.create.test.ts +69 -0
  251. package/templates/apps/api-ratelimit/tsconfig.json +5 -0
  252. package/templates/apps/api-rbac/README.md +59 -0
  253. package/templates/apps/api-rbac/app.config.ts +48 -0
  254. package/templates/apps/api-rbac/database/schema.ts +37 -0
  255. package/templates/apps/api-rbac/mutations/notes.create.mutation.server.ts +22 -0
  256. package/templates/apps/api-rbac/mutations/notes.create.mutation.ts +26 -0
  257. package/templates/apps/api-rbac/package.json +29 -0
  258. package/templates/apps/api-rbac/template.json +6 -0
  259. package/templates/apps/api-rbac/tests/notes.create.test.ts +80 -0
  260. package/templates/apps/api-rbac/tsconfig.json +5 -0
  261. package/templates/apps/api-rest/README.md +85 -0
  262. package/templates/apps/api-rest/app.config.ts +70 -0
  263. package/templates/apps/api-rest/database/schema.ts +52 -0
  264. package/templates/apps/api-rest/lib/product.ts +30 -0
  265. package/templates/apps/api-rest/package.json +27 -0
  266. package/templates/apps/api-rest/routes/v1/products.create.route.tsx +45 -0
  267. package/templates/apps/api-rest/routes/v1/products.delete.route.tsx +25 -0
  268. package/templates/apps/api-rest/routes/v1/products.get.route.tsx +29 -0
  269. package/templates/apps/api-rest/routes/v1/products.list.route.tsx +43 -0
  270. package/templates/apps/api-rest/template.json +6 -0
  271. package/templates/apps/api-rest/tests/products.create.test.ts +53 -0
  272. package/templates/apps/api-rest/tsconfig.json +5 -0
  273. package/templates/apps/api-saas/README.md +106 -0
  274. package/templates/apps/api-saas/app.config.ts +51 -0
  275. package/templates/apps/api-saas/database/schema.ts +50 -0
  276. package/templates/apps/api-saas/mutations/projects.create.mutation.server.ts +52 -0
  277. package/templates/apps/api-saas/mutations/projects.create.mutation.ts +18 -0
  278. package/templates/apps/api-saas/package.json +31 -0
  279. package/templates/apps/api-saas/queries/projects.list.query.server.ts +7 -0
  280. package/templates/apps/api-saas/queries/projects.list.query.ts +18 -0
  281. package/templates/apps/api-saas/template.json +6 -0
  282. package/templates/apps/api-saas/tests/projects.create.test.ts +47 -0
  283. package/templates/apps/api-saas/tsconfig.json +5 -0
  284. package/templates/apps/api-search/README.md +68 -0
  285. package/templates/apps/api-search/app.config.ts +31 -0
  286. package/templates/apps/api-search/database/schema.ts +47 -0
  287. package/templates/apps/api-search/lib/search.ts +27 -0
  288. package/templates/apps/api-search/mutations/articles.create.mutation.server.ts +19 -0
  289. package/templates/apps/api-search/mutations/articles.create.mutation.ts +35 -0
  290. package/templates/apps/api-search/package.json +29 -0
  291. package/templates/apps/api-search/queries/articles.list.query.server.ts +14 -0
  292. package/templates/apps/api-search/queries/articles.list.query.ts +19 -0
  293. package/templates/apps/api-search/seeds/articles.seed.ts +41 -0
  294. package/templates/apps/api-search/startup/searchBackfill.startup.tsx +24 -0
  295. package/templates/apps/api-search/template.json +6 -0
  296. package/templates/apps/api-search/tests/articles.create.test.ts +69 -0
  297. package/templates/apps/api-search/tsconfig.json +5 -0
  298. package/templates/apps/api-versioning/README.md +51 -0
  299. package/templates/apps/api-versioning/actions/documents.asOf.action.server.ts +13 -0
  300. package/templates/apps/api-versioning/actions/documents.asOf.action.ts +14 -0
  301. package/templates/apps/api-versioning/actions/documents.history.action.server.ts +15 -0
  302. package/templates/apps/api-versioning/actions/documents.history.action.ts +17 -0
  303. package/templates/apps/api-versioning/app.config.ts +24 -0
  304. package/templates/apps/api-versioning/database/schema.ts +38 -0
  305. package/templates/apps/api-versioning/mutations/documents.create.mutation.server.ts +8 -0
  306. package/templates/apps/api-versioning/mutations/documents.create.mutation.ts +21 -0
  307. package/templates/apps/api-versioning/mutations/documents.update.mutation.server.ts +9 -0
  308. package/templates/apps/api-versioning/mutations/documents.update.mutation.ts +21 -0
  309. package/templates/apps/api-versioning/package.json +29 -0
  310. package/templates/apps/api-versioning/template.json +6 -0
  311. package/templates/apps/api-versioning/tests/documents.create.test.ts +37 -0
  312. package/templates/apps/api-versioning/tsconfig.json +5 -0
  313. package/templates/apps/api-webhooks/.env +6 -0
  314. package/templates/apps/api-webhooks/README.md +106 -0
  315. package/templates/apps/api-webhooks/app.config.ts +16 -0
  316. package/templates/apps/api-webhooks/database/schema.ts +49 -0
  317. package/templates/apps/api-webhooks/events/order.completed.webhook.tsx +22 -0
  318. package/templates/apps/api-webhooks/mutations/orders.fulfill.mutation.server.ts +37 -0
  319. package/templates/apps/api-webhooks/mutations/orders.fulfill.mutation.ts +15 -0
  320. package/templates/apps/api-webhooks/package.json +28 -0
  321. package/templates/apps/api-webhooks/queries/orders.list.query.server.ts +7 -0
  322. package/templates/apps/api-webhooks/queries/orders.list.query.ts +15 -0
  323. package/templates/apps/api-webhooks/template.json +6 -0
  324. package/templates/apps/api-webhooks/tests/orders.fulfill.test.ts +51 -0
  325. package/templates/apps/api-webhooks/tsconfig.json +5 -0
  326. package/templates/apps/api-webhooks/webhooks/orders.webhook.tsx +35 -0
  327. package/templates/apps/changelog/README.md +77 -0
  328. package/templates/apps/changelog/app.config.ts +27 -0
  329. package/templates/apps/changelog/content/releases/0.1.0.mdx +19 -0
  330. package/templates/apps/changelog/content/releases/0.2.0.mdx +28 -0
  331. package/templates/apps/changelog/package.json +30 -0
  332. package/templates/apps/changelog/scripts/generate-rss.mjs +38 -0
  333. package/templates/apps/changelog/src/globals.css +66 -0
  334. package/templates/apps/changelog/src/globals.d.ts +16 -0
  335. package/templates/apps/changelog/src/lib/locale.test.ts +72 -0
  336. package/templates/apps/changelog/src/lib/locale.ts +55 -0
  337. package/templates/apps/changelog/src/lib/releases.ts +21 -0
  338. package/templates/apps/changelog/src/locales/de.ts +22 -0
  339. package/templates/apps/changelog/src/locales/en.ts +30 -0
  340. package/templates/apps/changelog/src/pages/[locale]/[slug].tsx +24 -0
  341. package/templates/apps/changelog/src/pages/[locale]/index.tsx +13 -0
  342. package/templates/apps/changelog/src/pages/[locale]/mirrors.test.tsx +95 -0
  343. package/templates/apps/changelog/src/pages/[slug].test.tsx +127 -0
  344. package/templates/apps/changelog/src/pages/[slug].tsx +52 -0
  345. package/templates/apps/changelog/src/pages/index.test.tsx +112 -0
  346. package/templates/apps/changelog/src/pages/index.tsx +55 -0
  347. package/templates/apps/changelog/src/pages/layout.tsx +84 -0
  348. package/templates/apps/changelog/template.json +6 -0
  349. package/templates/apps/changelog/tsconfig.json +11 -0
  350. package/templates/apps/edge-functions/README.md +55 -0
  351. package/templates/apps/edge-functions/functions/aiComplete.serverless.ts +58 -0
  352. package/templates/apps/edge-functions/functions/currencyConvert.serverless.ts +47 -0
  353. package/templates/apps/edge-functions/functions/geoGreeting.serverless.ts +44 -0
  354. package/templates/apps/edge-functions/functions/health.serverless.ts +29 -0
  355. package/templates/apps/edge-functions/functions/resolveLink.serverless.ts +32 -0
  356. package/templates/apps/edge-functions/functions/shareLink.serverless.ts +30 -0
  357. package/templates/apps/edge-functions/functions/slackNotify.serverless.ts +40 -0
  358. package/templates/apps/edge-functions/functions/verifySignature.serverless.ts +52 -0
  359. package/templates/apps/edge-functions/package.json +21 -0
  360. package/templates/apps/edge-functions/template.json +6 -0
  361. package/templates/apps/edge-functions/tsconfig.json +10 -0
  362. package/templates/apps/frontend-admin/README.md +40 -0
  363. package/templates/apps/frontend-admin/app.config.ts +37 -0
  364. package/templates/apps/frontend-admin/package.json +30 -0
  365. package/templates/apps/frontend-admin/src/config.ts +8 -0
  366. package/templates/apps/frontend-admin/src/globals.css +76 -0
  367. package/templates/apps/frontend-admin/src/globals.d.ts +6 -0
  368. package/templates/apps/frontend-admin/src/lib/admin.ts +16 -0
  369. package/templates/apps/frontend-admin/src/lib/auth.ts +24 -0
  370. package/templates/apps/frontend-admin/src/locales/de.ts +67 -0
  371. package/templates/apps/frontend-admin/src/locales/en.ts +79 -0
  372. package/templates/apps/frontend-admin/src/locales/index.ts +15 -0
  373. package/templates/apps/frontend-admin/src/pages/(marketing)/index.test.tsx +55 -0
  374. package/templates/apps/frontend-admin/src/pages/(marketing)/index.tsx +32 -0
  375. package/templates/apps/frontend-admin/src/pages/(marketing)/layout.tsx +29 -0
  376. package/templates/apps/frontend-admin/src/pages/(marketing)/login.test.tsx +73 -0
  377. package/templates/apps/frontend-admin/src/pages/(marketing)/login.tsx +35 -0
  378. package/templates/apps/frontend-admin/src/pages/admin/[entity].tsx +121 -0
  379. package/templates/apps/frontend-admin/src/pages/admin/entity.test.tsx +119 -0
  380. package/templates/apps/frontend-admin/src/pages/admin/error.tsx +20 -0
  381. package/templates/apps/frontend-admin/src/pages/admin/fallbacks.test.tsx +68 -0
  382. package/templates/apps/frontend-admin/src/pages/admin/index.test.tsx +88 -0
  383. package/templates/apps/frontend-admin/src/pages/admin/index.tsx +65 -0
  384. package/templates/apps/frontend-admin/src/pages/admin/layout.test.tsx +114 -0
  385. package/templates/apps/frontend-admin/src/pages/admin/layout.tsx +97 -0
  386. package/templates/apps/frontend-admin/src/pages/admin/loading.tsx +15 -0
  387. package/templates/apps/frontend-admin/src/pages/admin/not-found.tsx +15 -0
  388. package/templates/apps/frontend-admin/src/pages/layout.tsx +12 -0
  389. package/templates/apps/frontend-admin/src/pages/layouts.test.tsx +54 -0
  390. package/templates/apps/frontend-admin/template.json +6 -0
  391. package/templates/apps/frontend-admin/tsconfig.json +11 -0
  392. package/templates/apps/frontend-app/README.md +98 -0
  393. package/templates/apps/frontend-app/app.config.ts +43 -0
  394. package/templates/apps/frontend-app/package.json +30 -0
  395. package/templates/apps/frontend-app/src/locales/de.ts +36 -0
  396. package/templates/apps/frontend-app/src/locales/en.ts +43 -0
  397. package/templates/apps/frontend-app/src/locales/index.ts +15 -0
  398. package/templates/apps/frontend-app/src/pages/index.test.tsx +167 -0
  399. package/templates/apps/frontend-app/src/pages/index.tsx +136 -0
  400. package/templates/apps/frontend-app/src/pages/layout.tsx +41 -0
  401. package/templates/apps/frontend-app/src/pages/schema-ui.test.tsx +99 -0
  402. package/templates/apps/frontend-app/src/pages/schema-ui.tsx +74 -0
  403. package/templates/apps/frontend-app/template.json +6 -0
  404. package/templates/apps/frontend-app/tsconfig.json +11 -0
  405. package/templates/apps/frontend-blank/README.md +18 -0
  406. package/templates/apps/frontend-blank/app.config.ts +29 -0
  407. package/templates/apps/frontend-blank/package.json +29 -0
  408. package/templates/apps/frontend-blank/src/locales/de.ts +15 -0
  409. package/templates/apps/frontend-blank/src/locales/en.ts +22 -0
  410. package/templates/apps/frontend-blank/src/locales/index.ts +15 -0
  411. package/templates/apps/frontend-blank/src/pages/index.test.tsx +55 -0
  412. package/templates/apps/frontend-blank/src/pages/index.tsx +27 -0
  413. package/templates/apps/frontend-blank/src/pages/layout.test.tsx +54 -0
  414. package/templates/apps/frontend-blank/src/pages/layout.tsx +35 -0
  415. package/templates/apps/frontend-blank/template.json +6 -0
  416. package/templates/apps/frontend-blank/tsconfig.json +11 -0
  417. package/templates/apps/frontend-contact/README.md +65 -0
  418. package/templates/apps/frontend-contact/app.config.ts +25 -0
  419. package/templates/apps/frontend-contact/functions/sendMessage.serverless.ts +69 -0
  420. package/templates/apps/frontend-contact/package.json +33 -0
  421. package/templates/apps/frontend-contact/src/components/ContactForm.island.test.tsx +142 -0
  422. package/templates/apps/frontend-contact/src/components/ContactForm.island.tsx +104 -0
  423. package/templates/apps/frontend-contact/src/config.ts +12 -0
  424. package/templates/apps/frontend-contact/src/globals.css +84 -0
  425. package/templates/apps/frontend-contact/src/lib/locale.ts +55 -0
  426. package/templates/apps/frontend-contact/src/locales/de.ts +26 -0
  427. package/templates/apps/frontend-contact/src/locales/en.ts +29 -0
  428. package/templates/apps/frontend-contact/src/pages/[locale]/index.tsx +14 -0
  429. package/templates/apps/frontend-contact/src/pages/index.test.tsx +70 -0
  430. package/templates/apps/frontend-contact/src/pages/index.tsx +63 -0
  431. package/templates/apps/frontend-contact/src/pages/layout.tsx +65 -0
  432. package/templates/apps/frontend-contact/template.json +6 -0
  433. package/templates/apps/frontend-contact/tsconfig.json +11 -0
  434. package/templates/apps/frontend-dashboard/README.md +54 -0
  435. package/templates/apps/frontend-dashboard/app.config.ts +39 -0
  436. package/templates/apps/frontend-dashboard/package.json +29 -0
  437. package/templates/apps/frontend-dashboard/src/config.ts +8 -0
  438. package/templates/apps/frontend-dashboard/src/globals.css +72 -0
  439. package/templates/apps/frontend-dashboard/src/globals.d.ts +6 -0
  440. package/templates/apps/frontend-dashboard/src/lib/auth.ts +27 -0
  441. package/templates/apps/frontend-dashboard/src/locales/de.ts +49 -0
  442. package/templates/apps/frontend-dashboard/src/locales/en.ts +60 -0
  443. package/templates/apps/frontend-dashboard/src/locales/index.ts +15 -0
  444. package/templates/apps/frontend-dashboard/src/pages/(marketing)/index.test.tsx +55 -0
  445. package/templates/apps/frontend-dashboard/src/pages/(marketing)/index.tsx +34 -0
  446. package/templates/apps/frontend-dashboard/src/pages/(marketing)/layout.tsx +32 -0
  447. package/templates/apps/frontend-dashboard/src/pages/(marketing)/login.test.tsx +74 -0
  448. package/templates/apps/frontend-dashboard/src/pages/(marketing)/login.tsx +40 -0
  449. package/templates/apps/frontend-dashboard/src/pages/dashboard/error.tsx +21 -0
  450. package/templates/apps/frontend-dashboard/src/pages/dashboard/fallbacks.test.tsx +68 -0
  451. package/templates/apps/frontend-dashboard/src/pages/dashboard/index.test.tsx +55 -0
  452. package/templates/apps/frontend-dashboard/src/pages/dashboard/index.tsx +38 -0
  453. package/templates/apps/frontend-dashboard/src/pages/dashboard/layout.test.tsx +88 -0
  454. package/templates/apps/frontend-dashboard/src/pages/dashboard/layout.tsx +69 -0
  455. package/templates/apps/frontend-dashboard/src/pages/dashboard/loading.tsx +21 -0
  456. package/templates/apps/frontend-dashboard/src/pages/dashboard/not-found.tsx +19 -0
  457. package/templates/apps/frontend-dashboard/src/pages/dashboard/settings.test.tsx +69 -0
  458. package/templates/apps/frontend-dashboard/src/pages/dashboard/settings.tsx +35 -0
  459. package/templates/apps/frontend-dashboard/src/pages/layout.tsx +12 -0
  460. package/templates/apps/frontend-dashboard/src/pages/layouts.test.tsx +54 -0
  461. package/templates/apps/frontend-dashboard/template.json +6 -0
  462. package/templates/apps/frontend-dashboard/tsconfig.json +11 -0
  463. package/templates/apps/frontend-docs/README.md +19 -0
  464. package/templates/apps/frontend-docs/app.config.ts +25 -0
  465. package/templates/apps/frontend-docs/package.json +29 -0
  466. package/templates/apps/frontend-docs/src/globals.css +32 -0
  467. package/templates/apps/frontend-docs/src/lib/locale.test.ts +72 -0
  468. package/templates/apps/frontend-docs/src/lib/locale.ts +56 -0
  469. package/templates/apps/frontend-docs/src/locales/de.ts +24 -0
  470. package/templates/apps/frontend-docs/src/locales/en.ts +28 -0
  471. package/templates/apps/frontend-docs/src/pages/[locale]/docs/[...slug].tsx +18 -0
  472. package/templates/apps/frontend-docs/src/pages/[locale]/index.tsx +13 -0
  473. package/templates/apps/frontend-docs/src/pages/[locale]/mirrors.test.tsx +67 -0
  474. package/templates/apps/frontend-docs/src/pages/docs/[...slug].test.tsx +115 -0
  475. package/templates/apps/frontend-docs/src/pages/docs/[...slug].tsx +82 -0
  476. package/templates/apps/frontend-docs/src/pages/index.test.tsx +90 -0
  477. package/templates/apps/frontend-docs/src/pages/index.tsx +45 -0
  478. package/templates/apps/frontend-docs/src/pages/layout.test.tsx +84 -0
  479. package/templates/apps/frontend-docs/src/pages/layout.tsx +66 -0
  480. package/templates/apps/frontend-docs/template.json +6 -0
  481. package/templates/apps/frontend-docs/tsconfig.json +11 -0
  482. package/templates/apps/frontend-i18n/README.md +61 -0
  483. package/templates/apps/frontend-i18n/app.config.ts +33 -0
  484. package/templates/apps/frontend-i18n/package.json +28 -0
  485. package/templates/apps/frontend-i18n/src/globals.css +46 -0
  486. package/templates/apps/frontend-i18n/src/globals.d.ts +6 -0
  487. package/templates/apps/frontend-i18n/src/lib/locale.test.ts +72 -0
  488. package/templates/apps/frontend-i18n/src/lib/locale.ts +55 -0
  489. package/templates/apps/frontend-i18n/src/locales/de.ts +24 -0
  490. package/templates/apps/frontend-i18n/src/locales/en.ts +25 -0
  491. package/templates/apps/frontend-i18n/src/pages/[locale]/about.tsx +11 -0
  492. package/templates/apps/frontend-i18n/src/pages/[locale]/index.tsx +13 -0
  493. package/templates/apps/frontend-i18n/src/pages/[locale]/mirrors.test.tsx +50 -0
  494. package/templates/apps/frontend-i18n/src/pages/about.test.tsx +75 -0
  495. package/templates/apps/frontend-i18n/src/pages/about.tsx +31 -0
  496. package/templates/apps/frontend-i18n/src/pages/index.test.tsx +102 -0
  497. package/templates/apps/frontend-i18n/src/pages/index.tsx +43 -0
  498. package/templates/apps/frontend-i18n/src/pages/layout.test.tsx +86 -0
  499. package/templates/apps/frontend-i18n/src/pages/layout.tsx +70 -0
  500. package/templates/apps/frontend-i18n/template.json +6 -0
  501. package/templates/apps/frontend-i18n/tsconfig.json +11 -0
  502. package/templates/apps/frontend-landing/README.md +17 -0
  503. package/templates/apps/frontend-landing/app.config.ts +25 -0
  504. package/templates/apps/frontend-landing/package.json +29 -0
  505. package/templates/apps/frontend-landing/src/globals.css +23 -0
  506. package/templates/apps/frontend-landing/src/lib/locale.test.ts +72 -0
  507. package/templates/apps/frontend-landing/src/lib/locale.ts +55 -0
  508. package/templates/apps/frontend-landing/src/locales/de.ts +24 -0
  509. package/templates/apps/frontend-landing/src/locales/en.ts +26 -0
  510. package/templates/apps/frontend-landing/src/pages/[locale]/index.tsx +13 -0
  511. package/templates/apps/frontend-landing/src/pages/[locale]/mirrors.test.tsx +37 -0
  512. package/templates/apps/frontend-landing/src/pages/index.test.tsx +110 -0
  513. package/templates/apps/frontend-landing/src/pages/index.tsx +75 -0
  514. package/templates/apps/frontend-landing/src/pages/layout.test.tsx +84 -0
  515. package/templates/apps/frontend-landing/src/pages/layout.tsx +66 -0
  516. package/templates/apps/frontend-landing/template.json +6 -0
  517. package/templates/apps/frontend-landing/tsconfig.json +11 -0
  518. package/templates/apps/frontend-spa/README.md +45 -0
  519. package/templates/apps/frontend-spa/app.config.ts +27 -0
  520. package/templates/apps/frontend-spa/package.json +29 -0
  521. package/templates/apps/frontend-spa/src/globals.css +84 -0
  522. package/templates/apps/frontend-spa/src/locales/de.ts +22 -0
  523. package/templates/apps/frontend-spa/src/locales/en.ts +29 -0
  524. package/templates/apps/frontend-spa/src/locales/index.ts +15 -0
  525. package/templates/apps/frontend-spa/src/pages/index.test.tsx +137 -0
  526. package/templates/apps/frontend-spa/src/pages/index.tsx +123 -0
  527. package/templates/apps/frontend-spa/src/pages/layout.tsx +27 -0
  528. package/templates/apps/frontend-spa/template.json +6 -0
  529. package/templates/apps/frontend-spa/tsconfig.json +11 -0
  530. package/templates/apps/frontend-ssr/README.md +68 -0
  531. package/templates/apps/frontend-ssr/app.config.ts +32 -0
  532. package/templates/apps/frontend-ssr/package.json +29 -0
  533. package/templates/apps/frontend-ssr/src/globals.css +67 -0
  534. package/templates/apps/frontend-ssr/src/locales/de.ts +41 -0
  535. package/templates/apps/frontend-ssr/src/locales/en.ts +54 -0
  536. package/templates/apps/frontend-ssr/src/locales/index.ts +16 -0
  537. package/templates/apps/frontend-ssr/src/pages/feed-swr.test.tsx +69 -0
  538. package/templates/apps/frontend-ssr/src/pages/feed-swr.tsx +54 -0
  539. package/templates/apps/frontend-ssr/src/pages/feed.test.tsx +73 -0
  540. package/templates/apps/frontend-ssr/src/pages/feed.tsx +64 -0
  541. package/templates/apps/frontend-ssr/src/pages/index.test.tsx +89 -0
  542. package/templates/apps/frontend-ssr/src/pages/index.tsx +72 -0
  543. package/templates/apps/frontend-ssr/src/pages/layout.tsx +37 -0
  544. package/templates/apps/frontend-ssr/template.json +6 -0
  545. package/templates/apps/frontend-ssr/tsconfig.json +11 -0
  546. package/templates/apps/frontend-ssr-api/README.md +50 -0
  547. package/templates/apps/frontend-ssr-api/app.config.ts +43 -0
  548. package/templates/apps/frontend-ssr-api/package.json +30 -0
  549. package/templates/apps/frontend-ssr-api/src/globals.css +38 -0
  550. package/templates/apps/frontend-ssr-api/src/globals.d.ts +6 -0
  551. package/templates/apps/frontend-ssr-api/src/locales/de.ts +20 -0
  552. package/templates/apps/frontend-ssr-api/src/locales/en.ts +31 -0
  553. package/templates/apps/frontend-ssr-api/src/locales/index.ts +16 -0
  554. package/templates/apps/frontend-ssr-api/src/pages/index.test.tsx +105 -0
  555. package/templates/apps/frontend-ssr-api/src/pages/index.tsx +83 -0
  556. package/templates/apps/frontend-ssr-api/src/pages/layout.tsx +28 -0
  557. package/templates/apps/frontend-ssr-api/template.json +6 -0
  558. package/templates/apps/frontend-ssr-api/tsconfig.json +11 -0
  559. package/templates/apps/frontend-static-blog/README.md +49 -0
  560. package/templates/apps/frontend-static-blog/app.config.ts +34 -0
  561. package/templates/apps/frontend-static-blog/package.json +28 -0
  562. package/templates/apps/frontend-static-blog/src/components/ReadingProgress.island.test.tsx +65 -0
  563. package/templates/apps/frontend-static-blog/src/components/ReadingProgress.island.tsx +35 -0
  564. package/templates/apps/frontend-static-blog/src/content/posts.ts +64 -0
  565. package/templates/apps/frontend-static-blog/src/globals.css +75 -0
  566. package/templates/apps/frontend-static-blog/src/lib/locale.test.ts +72 -0
  567. package/templates/apps/frontend-static-blog/src/lib/locale.ts +55 -0
  568. package/templates/apps/frontend-static-blog/src/locales/de.ts +19 -0
  569. package/templates/apps/frontend-static-blog/src/locales/en.ts +26 -0
  570. package/templates/apps/frontend-static-blog/src/pages/[locale]/blog/[slug].tsx +20 -0
  571. package/templates/apps/frontend-static-blog/src/pages/[locale]/index.tsx +13 -0
  572. package/templates/apps/frontend-static-blog/src/pages/[locale]/mirrors.test.tsx +62 -0
  573. package/templates/apps/frontend-static-blog/src/pages/blog/[slug].test.tsx +116 -0
  574. package/templates/apps/frontend-static-blog/src/pages/blog/[slug].tsx +69 -0
  575. package/templates/apps/frontend-static-blog/src/pages/index.test.tsx +100 -0
  576. package/templates/apps/frontend-static-blog/src/pages/index.tsx +58 -0
  577. package/templates/apps/frontend-static-blog/src/pages/layout.tsx +63 -0
  578. package/templates/apps/frontend-static-blog/template.json +6 -0
  579. package/templates/apps/frontend-static-blog/tsconfig.json +11 -0
  580. package/templates/baselines/bare/.env.example +37 -0
  581. package/templates/baselines/bare/README.md +47 -0
  582. package/templates/baselines/bare/baseline.json +31 -0
  583. package/templates/baselines/bare/deploy/README.md +43 -0
  584. package/templates/baselines/bare/deploy/voltro.service.example +36 -0
  585. package/templates/baselines/compose/.env.example +46 -0
  586. package/templates/baselines/compose/README.md +69 -0
  587. package/templates/baselines/compose/baseline.json +51 -0
  588. package/templates/baselines/compose/docker/.dockerignore +38 -0
  589. package/templates/baselines/compose/docker/api.Dockerfile +57 -0
  590. package/templates/baselines/compose/docker/dev.Dockerfile +35 -0
  591. package/templates/baselines/compose/docker/web.Dockerfile +59 -0
  592. package/templates/baselines/compose/docker-compose.dev.yml +89 -0
  593. package/templates/baselines/compose/docker-compose.prod.yml +87 -0
  594. package/templates/baselines/compose/docker-compose.yml +41 -0
  595. package/templates/baselines/compose-mariadb/.env.example +57 -0
  596. package/templates/baselines/compose-mariadb/README.md +78 -0
  597. package/templates/baselines/compose-mariadb/baseline.json +51 -0
  598. package/templates/baselines/compose-mariadb/docker/.dockerignore +38 -0
  599. package/templates/baselines/compose-mariadb/docker/api.Dockerfile +57 -0
  600. package/templates/baselines/compose-mariadb/docker/dev.Dockerfile +35 -0
  601. package/templates/baselines/compose-mariadb/docker/mariadb-init.sql +6 -0
  602. package/templates/baselines/compose-mariadb/docker/web.Dockerfile +59 -0
  603. package/templates/baselines/compose-mariadb/docker-compose.dev.yml +117 -0
  604. package/templates/baselines/compose-mariadb/docker-compose.prod.yml +114 -0
  605. package/templates/baselines/compose-mariadb/docker-compose.yml +79 -0
  606. package/templates/baselines/helm/.env.example +39 -0
  607. package/templates/baselines/helm/README.md +98 -0
  608. package/templates/baselines/helm/baseline.json +53 -0
  609. package/templates/baselines/helm/charts/voltro-app/.helmignore +10 -0
  610. package/templates/baselines/helm/charts/voltro-app/Chart.yaml +10 -0
  611. package/templates/baselines/helm/charts/voltro-app/templates/_helpers.tpl +36 -0
  612. package/templates/baselines/helm/charts/voltro-app/templates/configmap.yaml +13 -0
  613. package/templates/baselines/helm/charts/voltro-app/templates/deployment-api.yaml +120 -0
  614. package/templates/baselines/helm/charts/voltro-app/templates/deployment-web.yaml +45 -0
  615. package/templates/baselines/helm/charts/voltro-app/templates/ingress.yaml +37 -0
  616. package/templates/baselines/helm/charts/voltro-app/templates/postgres-service.yaml +19 -0
  617. package/templates/baselines/helm/charts/voltro-app/templates/postgres-statefulset.yaml +73 -0
  618. package/templates/baselines/helm/charts/voltro-app/templates/secret.yaml +33 -0
  619. package/templates/baselines/helm/charts/voltro-app/templates/service-api.yaml +19 -0
  620. package/templates/baselines/helm/charts/voltro-app/templates/service-web.yaml +19 -0
  621. package/templates/baselines/helm/charts/voltro-app/values-dev.yaml +21 -0
  622. package/templates/baselines/helm/charts/voltro-app/values-prod.yaml +58 -0
  623. package/templates/baselines/helm/charts/voltro-app/values-staging.yaml +25 -0
  624. package/templates/baselines/helm/charts/voltro-app/values.yaml +109 -0
  625. package/templates/baselines/helm/deploy/README.md +94 -0
  626. package/templates/patches/@effect__cluster@0.59.0.patch +262 -0
@@ -0,0 +1,13 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+ import { rowAsOf } from '@voltro/plugin-versioning'
3
+
4
+ const execute = async (input: { id: string; at: number }, ctx: AppContext) => {
5
+ const snapshot = await rowAsOf(ctx.store, 'documents', input.id, ctx.request.subject.tenantId, input.at)
6
+ if (snapshot === null) return null
7
+ return {
8
+ title: snapshot['title'] as string,
9
+ content: snapshot['content'] as string,
10
+ }
11
+ }
12
+
13
+ export default execute
@@ -0,0 +1,14 @@
1
+ // Time-travel: the document's value as of a past instant (`at`, epoch ms).
2
+ // Returns null if it didn't exist (or was deleted) then.
3
+
4
+ import { defineAction } from '@voltro/protocol'
5
+ import { Schema } from 'effect'
6
+
7
+ export const documentAsOf = defineAction({
8
+ name: 'documents.asOf',
9
+ input: Schema.Struct({ id: Schema.String, at: Schema.Number }),
10
+ output: Schema.NullOr(Schema.Struct({
11
+ title: Schema.String,
12
+ content: Schema.String,
13
+ })),
14
+ })
@@ -0,0 +1,15 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+ import { rowHistory } from '@voltro/plugin-versioning'
3
+
4
+ const execute = async (input: { id: string }, ctx: AppContext) => {
5
+ const rows = await rowHistory(ctx.store, 'documents', input.id, ctx.request.subject.tenantId)
6
+ return rows.map((r) => ({
7
+ version: r.version,
8
+ op: r.op,
9
+ title: (r.data?.['title'] as string | undefined) ?? null,
10
+ content: (r.data?.['content'] as string | undefined) ?? null,
11
+ changedAt: r.changedAt,
12
+ }))
13
+ }
14
+
15
+ export default execute
@@ -0,0 +1,17 @@
1
+ // Lists every recorded version of a document — what it looked like after each
2
+ // change. (`audit()` tells you WHO/WHEN; this tells you WHAT it changed to.)
3
+
4
+ import { defineAction } from '@voltro/protocol'
5
+ import { Schema } from 'effect'
6
+
7
+ export const documentHistory = defineAction({
8
+ name: 'documents.history',
9
+ input: Schema.Struct({ id: Schema.String }),
10
+ output: Schema.Array(Schema.Struct({
11
+ version: Schema.Number,
12
+ op: Schema.String,
13
+ title: Schema.NullOr(Schema.String),
14
+ content: Schema.NullOr(Schema.String),
15
+ changedAt: Schema.Number,
16
+ })),
17
+ })
@@ -0,0 +1,24 @@
1
+ // Row-history backend for the {{projectName}} project.
2
+ //
3
+ // `versioningPlugin({ tables })` rides the post-commit ChangeEvent tap and
4
+ // records a FULL snapshot of every insert/update/delete on the listed tables
5
+ // into row history. Read it back with `rowHistory(store, table, id)` (every
6
+ // version) and `rowAsOf(store, table, id, when)` (the value at a past instant
7
+ // — time-travel). This is what-changed-to-what; `audit()` is who/when.
8
+ // Memory history store — zero infra.
9
+ import { defineEnv, envVar } from '@voltro/env'
10
+ import { versioningPlugin } from '@voltro/plugin-versioning'
11
+
12
+ export const env = defineEnv({
13
+ LOG_LEVEL: envVar.enum(['debug', 'info', 'warn', 'error'], { access: 'public', default: 'info' }),
14
+ })
15
+
16
+ export default {
17
+ type: 'api' as const,
18
+ name: '{{capProjectName}}{{capAppName}}',
19
+ store: 'memory' as const,
20
+ plugins: [
21
+ versioningPlugin({ tables: ['documents'] }),
22
+ ],
23
+ env,
24
+ }
@@ -0,0 +1,38 @@
1
+ // Schema for the {{projectName}} versioning backend — a `documents` table whose
2
+ // every change is snapshotted into row history (see app.config.ts).
3
+ // `actors` + `tenants` are the framework core tables.
4
+
5
+ import {
6
+ databaseHandle,
7
+ id,
8
+ table,
9
+ text,
10
+ timestamp,
11
+ type InferRow,
12
+ } from '@voltro/database'
13
+ import { tenant } from '@voltro/plugin-multitenancy'
14
+
15
+ export const actors = table('actors', {
16
+ id: id(),
17
+ kind: text().oneOf(['user', 'serviceAccount', 'apiKey', 'system']),
18
+ displayName: text().nullable(),
19
+ createdAt: timestamp().default('now'),
20
+ })
21
+
22
+ export const tenants = table('tenants', {
23
+ id: id(),
24
+ name: text(),
25
+ createdAt: timestamp().default('now'),
26
+ })
27
+
28
+ export const documents = table('documents', {
29
+ id: id({ prefix: 'doc' }),
30
+ title: text(),
31
+ content: text(),
32
+ })
33
+ .with(tenant())
34
+ .reactive()
35
+
36
+ export type Document = InferRow<typeof documents>
37
+
38
+ export const database = databaseHandle({ actors, tenants, documents })
@@ -0,0 +1,8 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+
3
+ // Plain insert — tenant() auto-fills tenantId. The versioning plugin records
4
+ // version 1 from the post-commit change event.
5
+ const execute = async (input: { title: string; content: string }, ctx: AppContext) =>
6
+ ctx.store.insert('documents', { title: input.title, content: input.content })
7
+
8
+ export default execute
@@ -0,0 +1,21 @@
1
+ // Creates a document — version 1 in its history. The versioning plugin
2
+ // snapshots the insert automatically (no code here); read it back via the
3
+ // documents.history / documents.asOf actions.
4
+
5
+ import { defineMutation } from '@voltro/protocol'
6
+ import { Schema } from 'effect'
7
+
8
+ export const createDocument = defineMutation({
9
+ name: 'documents.create',
10
+ target: { table: 'documents', op: 'insert' },
11
+ input: Schema.Struct({
12
+ title: Schema.NonEmptyString,
13
+ content: Schema.String,
14
+ }),
15
+ output: Schema.Struct({
16
+ id: Schema.String,
17
+ title: Schema.String,
18
+ content: Schema.String,
19
+ tenantId: Schema.String,
20
+ }),
21
+ })
@@ -0,0 +1,9 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+
3
+ const execute = async (input: { id: string; content: string }, ctx: AppContext) => {
4
+ const row = await ctx.store.update('documents', input.id, { content: input.content })
5
+ if (row === null) throw { status: 404, message: `document ${input.id} not found` }
6
+ return row
7
+ }
8
+
9
+ export default execute
@@ -0,0 +1,21 @@
1
+ // Edits a document's content — a new version in its history. Each update is
2
+ // snapshotted, so you can list every version or read the value as of any past
3
+ // instant.
4
+
5
+ import { defineMutation } from '@voltro/protocol'
6
+ import { Schema } from 'effect'
7
+
8
+ export const updateDocument = defineMutation({
9
+ name: 'documents.update',
10
+ target: { table: 'documents', op: 'update' },
11
+ input: Schema.Struct({
12
+ id: Schema.String,
13
+ content: Schema.String,
14
+ }),
15
+ output: Schema.Struct({
16
+ id: Schema.String,
17
+ title: Schema.String,
18
+ content: Schema.String,
19
+ tenantId: Schema.String,
20
+ }),
21
+ })
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@{{projectName}}/{{appName}}",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "voltro dev .",
8
+ "migrate": "voltro migrate",
9
+ "test": "voltro test",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@effect/platform": "^0.96.1",
14
+ "@effect/rpc": "^0.75.1",
15
+ "@voltro/cli": "0.1.0",
16
+ "@voltro/database": "0.1.0",
17
+ "@voltro/env": "0.1.0",
18
+ "@voltro/plugin-multitenancy": "0.1.0",
19
+ "@voltro/plugin-versioning": "0.1.0",
20
+ "@voltro/protocol": "0.1.0",
21
+ "@voltro/runtime": "0.1.0",
22
+ "effect": "^3.21.2"
23
+ },
24
+ "devDependencies": {
25
+ "@voltro/testing": "0.1.0",
26
+ "typescript": "^5.7.0",
27
+ "vitest": "^3.0.0"
28
+ }
29
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "api-versioning",
3
+ "kind": "api",
4
+ "summary": "Row history + time-travel — @voltro/plugin-versioning snapshots every insert/update/delete on the listed tables via the post-commit change tap; read every version with rowHistory() and the value at a past instant with rowAsOf(). audit() is who/when; this is what-changed-to-what. Memory store, zero infra.",
5
+ "tags": ["api", "versioning", "history", "audit-trail", "time-travel", "plugin"]
6
+ }
@@ -0,0 +1,37 @@
1
+ // Unit test with `@voltro/testing` — no database, no running server. The base
2
+ // `documents.create` mutation is a plain tenant()-scoped insert, so it's fully
3
+ // unit-runnable. The row-HISTORY / as-of reads are populated by the versioning
4
+ // plugin's post-commit tap (not wired into the unit store), so those are
5
+ // integration-tested elsewhere; here we cover the write + tenant isolation that
6
+ // every version-1 snapshot is built from. Run with `voltro test` (vitest).
7
+
8
+ import { describe, it, expect } from 'vitest'
9
+ import { makeTestContext, mockStore } from '@voltro/testing'
10
+ import { database } from '../database/schema' // registers documents / actors / tenants
11
+ import createDocument from '../mutations/documents.create.mutation.server'
12
+
13
+ describe('documents.create', () => {
14
+ it('inserts a document, auto-stamped to the caller tenant', async () => {
15
+ const ctx = makeTestContext({
16
+ subject: { type: 'user', id: 'user_1', tenantId: 'acme' },
17
+ store: mockStore({ documents: [] }),
18
+ })
19
+ const row = await createDocument({ title: 'Spec', content: 'v1 body' }, ctx)
20
+
21
+ expect(row['title']).toBe('Spec')
22
+ expect(row['content']).toBe('v1 body')
23
+ expect(row['tenantId']).toBe('acme') // tenant() stamped it
24
+ expect(row['id'] as string).toMatch(/^doc_/) // TypeID auto-injected
25
+ })
26
+
27
+ it('isolates tenants — t2 never sees t1 documents (REAL tenant scoping)', async () => {
28
+ const ctx = makeTestContext({
29
+ subject: { type: 'user', id: 'u1', tenantId: 't1' },
30
+ store: mockStore({ documents: [] }),
31
+ })
32
+ await createDocument({ title: 'secret', content: '' }, ctx)
33
+
34
+ const seenByT2 = await ctx.withTenant('t2', (c) => c.store.query(database.documents.descriptor))
35
+ expect(seenByT2).toHaveLength(0)
36
+ })
37
+ })
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../../tsconfig.base.json",
3
+ "include": ["**/*.ts", "**/*.tsx"],
4
+ "exclude": ["node_modules", "dist"]
5
+ }
@@ -0,0 +1,6 @@
1
+ # DEV-ONLY signing secret for the incoming `orders` webhook. The convention is
2
+ # VOLTRO_WEBHOOK_SECRET_<UPPER_ID> — for `id: 'orders'` that's _ORDERS. The
3
+ # external caller signs `<unix>.<rawBody>` with this and sends
4
+ # `X-Webhook-Signature: t=<ts>,v1=<hmac-sha256-hex>`. Rotate it for production
5
+ # (the partner gets the new value out of band).
6
+ VOLTRO_WEBHOOK_SECRET_ORDERS=devonly-webhook-secret-change-me
@@ -0,0 +1,106 @@
1
+ # {{capProjectName}} {{capAppName}} — first-class webhooks
2
+
3
+ Webhooks **both ways**, wired turnkey: a **signature-verified incoming receiver**
4
+ that rejects forged traffic before your code runs, and an **outgoing event** a
5
+ mutation emits to subscribed targets through a durable, signed, retried delivery
6
+ workflow. Boots **zero-infra** (`store: 'memory'`).
7
+
8
+ Webhooks are **file-convention**, not a `plugins:[]` entry — drop a
9
+ `*.webhook.tsx`, it's auto-discovered.
10
+
11
+ ## What ships
12
+
13
+ ```text
14
+ apps/acme/api/
15
+ ├── .env # VOLTRO_WEBHOOK_SECRET_ORDERS (dev signing secret)
16
+ ├── database/schema.ts # orders + webhookTables() bookkeeping
17
+ ├── webhooks/orders.webhook.tsx # INCOMING — signature-verified receiver
18
+ ├── events/order.completed.webhook.tsx # OUTGOING — defineOutgoingEvent
19
+ ├── mutations/orders.fulfill.mutation.ts # create order + emit (+ .server.ts)
20
+ └── queries/orders.list.query.ts # reactive list (+ .server.ts)
21
+ ```
22
+
23
+ ## Incoming — verified before your handler runs
24
+
25
+ ```tsx
26
+ // webhooks/orders.webhook.tsx → mounts at POST /webhooks/orders
27
+ import { defineIncomingWebhook } from '@voltro/plugin-webhooks'
28
+ import { genericProvider } from '@voltro/plugin-webhooks/providers'
29
+
30
+ export default defineIncomingWebhook({
31
+ id: 'orders', provider: genericProvider(), payload: Schema.Struct({ … }),
32
+ handler: async (ctx) => { /* ctx.body is validated; ctx.idempotencyKey set */ },
33
+ })
34
+ ```
35
+
36
+ The framework's middleware runs **before** `handler`: verify the HMAC over
37
+ `<ts>.<rawBody>` (→ `401`), reject a stale timestamp (→ `401`), decode the body
38
+ against `payload` (→ `422`), claim the `Idempotency-Key` (a replay → `200
39
+ {duplicate:true}`, handler skipped). You never hand-roll a signature check, and
40
+ forged traffic never reaches your code. Built-in provider presets:
41
+ `stripeProvider` / `githubProvider` / `slackProvider` / `genericProvider` (or
42
+ `defineWebhookProvider` for a custom partner).
43
+
44
+ The signing secret comes from `VOLTRO_WEBHOOK_SECRET_<UPPER_ID>` — here
45
+ `VOLTRO_WEBHOOK_SECRET_ORDERS` (shipped DEV-ONLY in `.env`).
46
+
47
+ ### Try it (curl)
48
+
49
+ ```bash
50
+ SECRET='devonly-webhook-secret-change-me'
51
+ BODY='{"event":"order.created","orderId":"o_1","sku":"WIDGET","totalCents":1999}'
52
+ TS=$(date +%s)
53
+ SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.*= //')
54
+
55
+ # valid signature → 200, handler runs
56
+ curl -s -o /dev/null -w '%{http_code}\n' -X POST http://localhost:4000/webhooks/orders \
57
+ -H "X-Webhook-Signature: t=$TS,v1=$SIG" -H 'content-type: application/json' \
58
+ -H 'Idempotency-Key: evt_1' --data "$BODY" # → 200
59
+
60
+ # no signature → 401 ; forged signature → 401 ; valid sig + wrong shape → 422
61
+ curl -s -o /dev/null -w '%{http_code}\n' -X POST http://localhost:4000/webhooks/orders \
62
+ -H 'content-type: application/json' --data "$BODY" # → 401
63
+ ```
64
+
65
+ ## Outgoing — emit to subscribed targets
66
+
67
+ ```ts
68
+ // events/order.completed.webhook.tsx
69
+ export default defineOutgoingEvent({ id: 'order.completed', payload: Schema.Struct({ … }), version: 1 })
70
+
71
+ // mutations/orders.fulfill.mutation.server.ts — after the row commits:
72
+ const { eventId, deliveries } = await useWebhooks(ctx).emit('order.completed', { orderId, tenantId, … })
73
+ ```
74
+
75
+ External systems subscribe at runtime — `ctx.webhooks.subscribe({ event:
76
+ 'order.completed', url })` (one row in `_voltro_webhook_targets`). On `emit`, the
77
+ framework fans out to every matching target through a **durable delivery
78
+ workflow** — HMAC-signing the outbound request, retrying with backoff, honouring
79
+ `Retry-After`; each attempt lands in `_voltro_webhook_deliveries`. The `emit`
80
+ returns immediately (the POSTs run in the background); `deliveries` is one entry
81
+ per matched target (empty until someone subscribes).
82
+
83
+ ```bash
84
+ # Fulfill an order → emits order.completed (0 targets until a subscriber registers)
85
+ curl -s -X POST http://localhost:4000/_voltro/inspect/invoke -H 'content-type: application/json' \
86
+ -d '{"tag":"orders.fulfill","input":{"sku":"WIDGET","totalCents":4999}}'
87
+ ```
88
+
89
+ ## Going to production
90
+
91
+ | Want… | Do |
92
+ |---|---|
93
+ | A real partner (Stripe/GitHub/Slack) | swap `genericProvider()` → `stripeProvider()` etc.; set `VOLTRO_WEBHOOK_SECRET_<ID>` |
94
+ | Durable targets + delivery history | `store: 'postgres'` (the `_voltro_webhook_*` tables survive restarts) |
95
+ | A subscribe API | a mutation calling `ctx.webhooks.subscribe({ event, url, secret?, retry? })` |
96
+ | A custom signature scheme | `defineWebhookProvider({ id, signature, idempotency })` |
97
+
98
+ ## Anti-patterns
99
+
100
+ - **Trusting webhook input without verification.** The framework rejects unsigned
101
+ incoming requests by default — don't set `signature: undefined` unless a
102
+ network trust boundary (IP allow-list, VPC) gates the route.
103
+ - **Mutating domain state synchronously in the outgoing emit path.** Mutate in the
104
+ mutation, THEN emit — delivery is async by design (rollback drops the queued send).
105
+ - **Re-using the idempotency TTL as the provider's retry window.** Pick TTL ≥ 2×
106
+ the provider's max retry window so the dedup catches the slowest retry.
@@ -0,0 +1,16 @@
1
+ // Api app config — first-class webhooks. Read by `voltro dev`.
2
+ //
3
+ // Webhooks are FILE-CONVENTION, not a plugins:[] entry — `*.webhook.tsx` files
4
+ // are auto-discovered (the incoming `orders` receiver + the outgoing
5
+ // `order.completed` event), and the bookkeeping tables come from
6
+ // `webhookTables()` in database/schema.ts. The only wiring is the signing
7
+ // secret in `.env` (VOLTRO_WEBHOOK_SECRET_ORDERS).
8
+ //
9
+ // `store: 'memory'` keeps first-run zero-infra; the durable delivery workflow
10
+ // runs in-process. Swap to `store: 'postgres'` for cross-restart durability.
11
+
12
+ export default {
13
+ type: 'api' as const,
14
+ name: '{{capProjectName}}{{capAppName}}',
15
+ store: 'memory' as const,
16
+ }
@@ -0,0 +1,49 @@
1
+ // Schema for the {{projectName}} webhooks backend.
2
+ //
3
+ // `webhookTables()` contributes the framework's two bookkeeping tables —
4
+ // `_voltro_webhook_targets` (who subscribed to an outgoing event) and
5
+ // `_voltro_webhook_deliveries` (each delivery attempt). They're auto-migrated
6
+ // alongside your own tables; you register them by exporting them here.
7
+
8
+ import {
9
+ databaseHandle,
10
+ id,
11
+ integer,
12
+ table,
13
+ text,
14
+ type InferRow,
15
+ } from '@voltro/database'
16
+ import { tenant } from '@voltro/plugin-multitenancy'
17
+ import { webhookTables } from '@voltro/plugin-webhooks/mixin'
18
+
19
+ // ---------- Core tables ----------
20
+
21
+ export const actors = table('actors', {
22
+ id: id(),
23
+ kind: text().oneOf(['user', 'serviceAccount', 'apiKey', 'system']),
24
+ displayName: text().nullable(),
25
+ })
26
+
27
+ export const tenants = table('tenants', { id: id(), name: text() })
28
+
29
+ // ---------- Application table ----------
30
+
31
+ export const orders = table('orders', {
32
+ id: id({ prefix: 'order' }),
33
+ sku: text(),
34
+ totalCents: integer(),
35
+ status: text().oneOf(['pending', 'fulfilled']).default('pending'),
36
+ })
37
+ .with(tenant())
38
+ .reactive()
39
+
40
+ export type Order = InferRow<typeof orders>
41
+
42
+ // ---------- Webhook bookkeeping (framework-managed) ----------
43
+ const [webhookTargets, webhookDeliveries] = webhookTables()
44
+ export { webhookTargets, webhookDeliveries }
45
+
46
+ export const database = databaseHandle({
47
+ actors, tenants, orders,
48
+ webhookTargets, webhookDeliveries,
49
+ })
@@ -0,0 +1,22 @@
1
+ // OUTGOING event — an event THIS app emits. External systems subscribe at
2
+ // runtime via `ctx.webhooks.subscribe({ event: 'order.completed', url })`;
3
+ // each subscriber is a row in `_voltro_webhook_targets`. When a handler calls
4
+ // `useWebhooks(ctx).emit('order.completed', payload)`, the framework fans out
5
+ // to every matching target through a DURABLE delivery workflow — HMAC-signing
6
+ // the outbound request, retrying with backoff, honouring Retry-After. Each
7
+ // attempt is recorded in `_voltro_webhook_deliveries`.
8
+
9
+ import { defineOutgoingEvent } from '@voltro/plugin-webhooks'
10
+ import { Schema } from 'effect'
11
+
12
+ export default defineOutgoingEvent({
13
+ id: 'order.completed',
14
+ description: 'An order moved to "fulfilled" — payment captured, items shipped.',
15
+ payload: Schema.Struct({
16
+ orderId: Schema.String,
17
+ tenantId: Schema.String,
18
+ sku: Schema.String,
19
+ totalCents: Schema.Number,
20
+ }),
21
+ version: 1,
22
+ })
@@ -0,0 +1,37 @@
1
+ // Create a fulfilled order, THEN emit the outgoing `order.completed` event.
2
+ //
3
+ // `ctx.workflows.start` / emit are post-commit safe inside a mutation: the row
4
+ // commits first, then the event fans out to subscribed targets — so a rollback
5
+ // never ships a webhook for an order that didn't persist. `emit` returns
6
+ // immediately (the HTTP POSTs run in the background delivery workflow); the
7
+ // `deliveries` array is one entry per matched target (empty until someone
8
+ // subscribes via ctx.webhooks.subscribe).
9
+
10
+ import type { AppContext } from '@voltro/runtime'
11
+ import { useWebhooks } from '@voltro/plugin-webhooks'
12
+
13
+ const execute = async (input: { sku: string; totalCents: number }, ctx: AppContext) => {
14
+ // status set explicitly — a column DEFAULT only fills in on a SQL store.
15
+ const row = await ctx.store.insert('orders', {
16
+ sku: input.sku, totalCents: input.totalCents, status: 'fulfilled',
17
+ })
18
+
19
+ const order = {
20
+ id: row['id'] as string,
21
+ sku: row['sku'] as string,
22
+ totalCents: row['totalCents'] as number,
23
+ status: row['status'] as string,
24
+ tenantId: row['tenantId'] as string,
25
+ }
26
+
27
+ // Fan out to every subscribed target (durable, signed, retried in the bg).
28
+ const webhooks = useWebhooks(ctx)
29
+ const { eventId, deliveries } = await webhooks.emit('order.completed', {
30
+ orderId: order.id, tenantId: order.tenantId, sku: order.sku, totalCents: order.totalCents,
31
+ })
32
+ console.log(`[webhook:emit] order.completed event=${eventId} → ${deliveries.length} target(s)`)
33
+
34
+ return order
35
+ }
36
+
37
+ export default execute
@@ -0,0 +1,15 @@
1
+ import { defineMutation } from '@voltro/protocol'
2
+ import { Schema } from 'effect'
3
+
4
+ export const fulfillOrder = defineMutation({
5
+ name: 'orders.fulfill',
6
+ target: { table: 'orders', op: 'insert' },
7
+ input: Schema.Struct({ sku: Schema.NonEmptyString, totalCents: Schema.Number }),
8
+ output: Schema.Struct({
9
+ id: Schema.String,
10
+ sku: Schema.String,
11
+ totalCents: Schema.Number,
12
+ status: Schema.String,
13
+ tenantId: Schema.String,
14
+ }),
15
+ })
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@{{projectName}}/{{appName}}",
3
+ "version": "0.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "voltro dev .",
8
+ "migrate": "voltro migrate",
9
+ "test": "voltro test",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@effect/platform": "^0.96.1",
14
+ "@effect/rpc": "^0.75.1",
15
+ "@voltro/cli": "0.1.0",
16
+ "@voltro/database": "0.1.0",
17
+ "@voltro/plugin-multitenancy": "0.1.0",
18
+ "@voltro/plugin-webhooks": "0.1.0",
19
+ "@voltro/protocol": "0.1.0",
20
+ "@voltro/runtime": "0.1.0",
21
+ "effect": "^3.21.2"
22
+ },
23
+ "devDependencies": {
24
+ "@voltro/testing": "0.1.0",
25
+ "typescript": "^5.7.0",
26
+ "vitest": "^3.0.0"
27
+ }
28
+ }
@@ -0,0 +1,7 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+ import { database } from '../database/schema'
3
+
4
+ const route = (_input: Record<string, never>, _ctx: AppContext) =>
5
+ database.orders.orderBy('createdAt', 'desc').limit(100)
6
+
7
+ export default route
@@ -0,0 +1,15 @@
1
+ import { defineQuery } from '@voltro/protocol'
2
+ import { Schema } from 'effect'
3
+
4
+ export const listOrders = defineQuery({
5
+ name: 'orders.list',
6
+ source: 'orders',
7
+ input: Schema.Struct({}),
8
+ output: Schema.Array(Schema.Struct({
9
+ id: Schema.String,
10
+ sku: Schema.String,
11
+ totalCents: Schema.Number,
12
+ status: Schema.String,
13
+ tenantId: Schema.String,
14
+ })),
15
+ })
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "api-webhooks",
3
+ "kind": "api",
4
+ "summary": "First-class webhooks both ways: a signature-verified INCOMING receiver (*.webhook.tsx, genericProvider HMAC) that rejects unsigned/forged requests before your handler runs, plus an OUTGOING defineOutgoingEvent a mutation emits to subscribed targets via a durable delivery workflow.",
5
+ "tags": ["api", "webhooks", "integrations", "hmac", "signature", "stripe", "events"]
6
+ }
@@ -0,0 +1,51 @@
1
+ // Unit test with `@voltro/testing` — no database, no running server, no webhook
2
+ // delivery. The `orders.fulfill` executor emits an outgoing `order.completed`
3
+ // event via `useWebhooks(ctx).emit(...)` — that fans out through the webhooks
4
+ // plugin's durable delivery workflow (real HTTP POSTs, retries, signing), which
5
+ // is dispatch-time infrastructure the unit harness does NOT wire, so we do not
6
+ // fake it. Instead we PIN the descriptor's wire contract and prove the tenant()
7
+ // scoping on the `orders` table. Run with `voltro test` (vitest).
8
+
9
+ import { describe, it, expect } from 'vitest'
10
+ import { Schema } from 'effect'
11
+ import { makeTestContext, mockStore } from '@voltro/testing'
12
+ import { database } from '../database/schema' // registers orders + webhook tables
13
+ import { fulfillOrder } from '../mutations/orders.fulfill.mutation'
14
+
15
+ describe('orders.fulfill descriptor', () => {
16
+ it('decodes a valid input and rejects a blank sku', () => {
17
+ const decode = Schema.decodeUnknownSync(fulfillOrder.input)
18
+ expect(decode({ sku: 'SKU-1', totalCents: 4200 })).toEqual({ sku: 'SKU-1', totalCents: 4200 })
19
+ // `sku: Schema.NonEmptyString` — an empty string fails the wire decode.
20
+ expect(() => decode({ sku: '', totalCents: 4200 })).toThrow()
21
+ })
22
+
23
+ it('encodes the output shape the client expects', () => {
24
+ const encode = Schema.encodeUnknownSync(fulfillOrder.output)
25
+ const wire = encode({
26
+ id: 'order_1', sku: 'SKU-1', totalCents: 4200, status: 'fulfilled', tenantId: 'acme',
27
+ })
28
+ expect(wire).toEqual({
29
+ id: 'order_1', sku: 'SKU-1', totalCents: 4200, status: 'fulfilled', tenantId: 'acme',
30
+ })
31
+ })
32
+ })
33
+
34
+ describe('orders tenant isolation', () => {
35
+ it('t2 never sees t1 orders (REAL tenant scoping)', async () => {
36
+ const ctx = makeTestContext({
37
+ subject: { type: 'user', id: 'u1', tenantId: 't1' },
38
+ store: mockStore({ orders: [] }),
39
+ })
40
+ // Raw insert through the mixin store — tenant() auto-stamps tenantId=t1.
41
+ // `status` set explicitly (a column DEFAULT only fills on a SQL store).
42
+ const row = await ctx.store.insert('orders', { sku: 'SKU-1', totalCents: 4200, status: 'fulfilled' })
43
+ expect(row['tenantId']).toBe('t1')
44
+ expect(row['id'] as string).toMatch(/^order_/)
45
+
46
+ const seenByT2 = await ctx.withTenant('t2', (c) => c.store.query(database.orders.descriptor))
47
+ expect(seenByT2).toHaveLength(0)
48
+ const seenByT1 = await ctx.store.query(database.orders.descriptor)
49
+ expect(seenByT1).toHaveLength(1)
50
+ })
51
+ })