@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,49 @@
1
+ # {{projectName}} / {{appName}}
2
+
3
+ Voltro API scaffold (template: **api-backend-deactivation**) — the
4
+ `deactivation()` schema mixin: lock a user out without hiding their data.
5
+
6
+ ## Boot
7
+
8
+ ```bash
9
+ pnpm install
10
+ pnpm --filter @{{projectName}}/{{appName}} dev
11
+ # → http://localhost:4000 (store: memory — zero infra)
12
+ ```
13
+
14
+ ## What this shows
15
+
16
+ - **`deactivation()` mixin** — `users.with(deactivation())` adds
17
+ `deactivatedAt` + `deactivatedBy` (→ `actors`) and pulls `audit()`
18
+ transitively. It's a pure schema mixin — no `plugins[]` entry.
19
+ - **Visible-but-locked-out** — set `deactivatedAt` with a normal
20
+ `ctx.store.update`. The row STAYS in the table and remains queryable; the
21
+ convention is that your auth layer refuses to authenticate a subject whose
22
+ `deactivatedAt` is set. This is the deliberate **opposite of
23
+ `softDelete()`**, which hides + anonymises the row (its `defaultWhere`
24
+ filters deleted rows out of every read).
25
+
26
+ ## Try it
27
+
28
+ ```bash
29
+ # create a user, then read it (deactivatedAt is null):
30
+ ID=$(curl -s localhost:4000/_voltro/inspect/invoke -H 'content-type: application/json' \
31
+ -d '{"tag":"users.create","input":{"email":"ada@acme.com","name":"Ada"}}' | python3 -c 'import sys,json;print(json.load(sys.stdin)["result"]["id"])')
32
+ curl -s localhost:4000/_voltro/inspect/invoke -H 'content-type: application/json' \
33
+ -d "{\"tag\":\"users.get\",\"input\":{\"id\":\"$ID\"}}"
34
+ # → { ok:true, result:{ …, deactivatedAt:null } }
35
+
36
+ # deactivate, then read AGAIN — still there, now stamped:
37
+ curl -s localhost:4000/_voltro/inspect/invoke -H 'content-type: application/json' \
38
+ -d "{\"tag\":\"users.deactivate\",\"input\":{\"id\":\"$ID\"}}" >/dev/null
39
+ curl -s localhost:4000/_voltro/inspect/invoke -H 'content-type: application/json' \
40
+ -d "{\"tag\":\"users.get\",\"input\":{\"id\":\"$ID\"}}"
41
+ # → { ok:true, result:{ …, deactivatedAt:"2026-…" } } (NOT null → still visible)
42
+ ```
43
+
44
+ ## Full user lifecycle
45
+
46
+ Compose the lifecycle mixins for the complete column set:
47
+ `users.with(audit(), softDelete(), deactivation())` — who/when (audit),
48
+ hidden+anonymised on delete (softDelete), and visible-but-locked-out
49
+ (deactivation).
@@ -0,0 +1,17 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+ import { eq } from '@voltro/database'
3
+ import { database } from '../database/schema'
4
+
5
+ const execute = async (input: { id: string }, ctx: AppContext) => {
6
+ const rows = await ctx.store.query(database.users.where(eq('id', input.id)).descriptor)
7
+ const u = rows[0]
8
+ if (!u) return null
9
+ return {
10
+ id: u['id'] as string,
11
+ email: u['email'] as string,
12
+ name: u['name'] as string,
13
+ deactivatedAt: (u['deactivatedAt'] as Date | null) ?? null,
14
+ }
15
+ }
16
+
17
+ export default execute
@@ -0,0 +1,18 @@
1
+ // Reads one user by id — including a deactivated one. This is the whole point
2
+ // of deactivation() vs softDelete(): after deactivation the row is STILL here
3
+ // and readable, just stamped with `deactivatedAt`. (softDelete() would make
4
+ // this return null.)
5
+
6
+ import { defineAction } from '@voltro/protocol'
7
+ import { Schema } from 'effect'
8
+
9
+ export const getUser = defineAction({
10
+ name: 'users.get',
11
+ input: Schema.Struct({ id: Schema.String }),
12
+ output: Schema.NullOr(Schema.Struct({
13
+ id: Schema.String,
14
+ email: Schema.String,
15
+ name: Schema.String,
16
+ deactivatedAt: Schema.NullOr(Schema.Date),
17
+ })),
18
+ })
@@ -0,0 +1,20 @@
1
+ // Backend for the {{projectName}} project demonstrating the `deactivation()`
2
+ // schema mixin.
3
+ //
4
+ // deactivation() is a pure SCHEMA mixin (no plugins[] entry) — it adds
5
+ // `deactivatedAt` + `deactivatedBy` columns. A deactivated subject can't
6
+ // authenticate, but its row stays VISIBLE and queryable: no read-scoping, no
7
+ // delete interception. That's the deliberate opposite of softDelete(), which
8
+ // HIDES + anonymises. Set `deactivatedAt` with a normal `ctx.store.update`.
9
+ import { defineEnv, envVar } from '@voltro/env'
10
+
11
+ export const env = defineEnv({
12
+ LOG_LEVEL: envVar.enum(['debug', 'info', 'warn', 'error'], { access: 'public', default: 'info' }),
13
+ })
14
+
15
+ export default {
16
+ type: 'api' as const,
17
+ name: '{{capProjectName}}{{capAppName}}',
18
+ store: 'memory' as const,
19
+ env,
20
+ }
@@ -0,0 +1,41 @@
1
+ // Schema for the {{projectName}} backend — a `users` table with the
2
+ // `deactivation()` mixin. `actors` + `tenants` are the framework core tables.
3
+
4
+ import {
5
+ databaseHandle,
6
+ id,
7
+ table,
8
+ text,
9
+ timestamp,
10
+ type InferRow,
11
+ } from '@voltro/database'
12
+ import { deactivation } from '@voltro/plugin-deactivation'
13
+
14
+ export const actors = table('actors', {
15
+ id: id(),
16
+ kind: text().oneOf(['user', 'serviceAccount', 'apiKey', 'system']),
17
+ displayName: text().nullable(),
18
+ createdAt: timestamp().default('now'),
19
+ })
20
+
21
+ export const tenants = table('tenants', {
22
+ id: id(),
23
+ name: text(),
24
+ createdAt: timestamp().default('now'),
25
+ })
26
+
27
+ export const users = table('users', {
28
+ id: id(),
29
+ email: text().unique(),
30
+ name: text(),
31
+ })
32
+ // deactivation() adds deactivatedAt + deactivatedBy (→ actors) and pulls
33
+ // audit() transitively (createdAt/updatedAt/createdBy/updatedBy). NOTE: no
34
+ // defaultWhere — a deactivated user still shows up in queries, unlike
35
+ // softDelete() which would hide it.
36
+ .with(deactivation())
37
+ .reactive()
38
+
39
+ export type User = InferRow<typeof users>
40
+
41
+ export const database = databaseHandle({ actors, tenants, users })
@@ -0,0 +1,6 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+
3
+ const execute = async (input: { email: string; name: string }, ctx: AppContext) =>
4
+ ctx.store.insert('users', { email: input.email, name: input.name })
5
+
6
+ export default execute
@@ -0,0 +1,16 @@
1
+ import { defineMutation } from '@voltro/protocol'
2
+ import { Schema } from 'effect'
3
+
4
+ export const createUser = defineMutation({
5
+ name: 'users.create',
6
+ target: { table: 'users', op: 'insert' },
7
+ input: Schema.Struct({
8
+ email: Schema.NonEmptyString,
9
+ name: Schema.String,
10
+ }),
11
+ output: Schema.Struct({
12
+ id: Schema.String,
13
+ email: Schema.String,
14
+ name: Schema.String,
15
+ }),
16
+ })
@@ -0,0 +1,10 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+
3
+ const execute = async (input: { id: string }, ctx: AppContext) => {
4
+ // A plain update — set the timestamp. audit() stamps updatedAt/updatedBy.
5
+ const row = await ctx.store.update('users', input.id, { deactivatedAt: new Date() })
6
+ if (row === null) throw { status: 404, message: `user ${input.id} not found` }
7
+ return row
8
+ }
9
+
10
+ export default execute
@@ -0,0 +1,19 @@
1
+ // Deactivates a user — sets `deactivatedAt` with a normal update. The user's
2
+ // row stays in the table and remains visible to queries; the convention is
3
+ // that your auth layer refuses to authenticate a subject whose `deactivatedAt`
4
+ // is set. (Contrast softDelete(), which hides + anonymises the row.)
5
+
6
+ import { defineMutation } from '@voltro/protocol'
7
+ import { Schema } from 'effect'
8
+
9
+ export const deactivateUser = defineMutation({
10
+ name: 'users.deactivate',
11
+ target: { table: 'users', op: 'update' },
12
+ input: Schema.Struct({ id: Schema.String }),
13
+ output: Schema.Struct({
14
+ id: Schema.String,
15
+ email: Schema.String,
16
+ name: Schema.String,
17
+ deactivatedAt: Schema.NullOr(Schema.Date),
18
+ }),
19
+ })
@@ -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/env": "0.1.0",
18
+ "@voltro/plugin-deactivation": "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,6 @@
1
+ {
2
+ "id": "api-backend-deactivation",
3
+ "kind": "api",
4
+ "summary": "The deactivation() schema mixin — adds deactivatedAt/deactivatedBy so a user can be locked out (your auth refuses a deactivated subject) while its row stays VISIBLE and queryable. The deliberate opposite of softDelete(), which hides + anonymises. Pure schema, zero infra.",
5
+ "tags": ["api", "deactivation", "user-lifecycle", "schema-mixin", "soft-delete"]
6
+ }
@@ -0,0 +1,47 @@
1
+ // Unit test with `@voltro/testing` — no database, no running server. Importing
2
+ // `../database/schema` registers the `users` / `actors` / `tenants` tables
3
+ // globally, so `makeTestContext` auto-wires them into the in-memory store.
4
+ // `ctx.store` is the SAME mixin-wrapped store the handlers get in production,
5
+ // so the `deactivation()` mixin columns behave exactly as at runtime.
6
+ //
7
+ // The POINT of this template: `deactivation()` is a columns-only mixin (adds
8
+ // `deactivatedAt` / `deactivatedBy`) with NO read scoping — a deactivated row
9
+ // stays fully VISIBLE, the deliberate opposite of `softDelete()`. These tests
10
+ // assert exactly that. Run with `voltro test` (vitest).
11
+
12
+ import { describe, it, expect } from 'vitest'
13
+ import { makeTestContext, mockStore } from '@voltro/testing'
14
+ import { database } from '../database/schema' // registers users / actors / tenants
15
+ import createUser from '../mutations/users.create.mutation.server'
16
+ import deactivateUser from '../mutations/users.deactivate.mutation.server'
17
+
18
+ const subject = { type: 'user' as const, id: 'user_1', tenantId: null }
19
+
20
+ describe('users.create', () => {
21
+ it('inserts a user with an auto-injected id and no deactivation timestamp', async () => {
22
+ const ctx = makeTestContext({ subject, store: mockStore({ users: [] }) })
23
+ const row = await createUser({ email: 'ada@example.com', name: 'Ada' }, ctx)
24
+
25
+ expect(row['email']).toBe('ada@example.com')
26
+ expect(row['name']).toBe('Ada')
27
+ expect(row['id']).toBeTruthy() // TypeID auto-injected from id()
28
+ expect(row['deactivatedAt'] ?? null).toBeNull() // active on creation
29
+ })
30
+ })
31
+
32
+ describe('users.deactivate', () => {
33
+ it('stamps deactivatedAt — and the row STAYS visible (unlike softDelete)', async () => {
34
+ const ctx = makeTestContext({ subject, store: mockStore({ users: [] }) })
35
+ const created = await createUser({ email: 'grace@example.com', name: 'Grace' }, ctx)
36
+
37
+ const updated = await deactivateUser({ id: String(created['id']) }, ctx)
38
+ expect(updated['deactivatedAt']).toBeInstanceOf(Date)
39
+
40
+ // deactivation() adds no defaultWhere, so a plain query still returns the
41
+ // deactivated row — this is the mixin's whole contract.
42
+ const rows = await ctx.store.query(database.users.descriptor)
43
+ expect(rows).toHaveLength(1)
44
+ expect(String(rows[0]!['id'])).toBe(String(created['id']))
45
+ expect(rows[0]!['deactivatedAt']).toBeInstanceOf(Date)
46
+ })
47
+ })
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../../tsconfig.base.json",
3
+ "include": ["**/*.ts", "**/*.tsx"],
4
+ "exclude": ["node_modules", "dist"]
5
+ }
@@ -0,0 +1,39 @@
1
+ # {{projectName}} / {{appName}}
2
+
3
+ Voltro backend scaffold (template: **api-backend-mail**).
4
+
5
+ ## Boot
6
+
7
+ ```bash
8
+ pnpm install # at the repo root
9
+ pnpm --filter @{{projectName}}/{{appName}} dev
10
+ # → http://localhost:4000
11
+ # → ws://localhost:4000/ws
12
+ ```
13
+
14
+ ## What's in here
15
+
16
+ | File | Role |
17
+ |---|---|
18
+ | `app.config.ts` | App declaration + `mailPlugin` wired (`console` provider). |
19
+ | `database/schema.ts` | One example table (`notes`) with the `tenant()` mixin. |
20
+ | `queries/` + `mutations/` | Streaming subscription + tenant-guarded mutation examples. |
21
+ | `emails/welcome.email.tsx` | A React-Email welcome template (edit/replace freely). |
22
+ | `actions/sendWelcome.{rpc,handler}.ts` | `mail.sendWelcome` — sends the welcome template. |
23
+
24
+ ## Mail
25
+
26
+ Transactional email is wired out of the box via `@voltro/plugin-mail`:
27
+
28
+ - **Preview** templates in the dashboard's **Mail** tab (props box
29
+ pre-fills from each template's `preview`).
30
+ - **Send** with the `mail.sendWelcome` action, or `yield* MailService`
31
+ + `mail.send({ template: 'welcome', props })` from any handler.
32
+ - The default `console` provider just **logs** the mail (zero-config, no
33
+ API key) and captures it in the dashboard outbox. For real delivery,
34
+ switch `provider` in `app.config.ts` to `'resend'` / `'postmark'` /
35
+ `'sendgrid'` / `'smtp'` and set the matching env var (e.g.
36
+ `RESEND_API_KEY`).
37
+
38
+ Drop more `*.email.tsx`, `*.query.ts` + `*.query.server.ts`, `*.mutation.ts` + `*.mutation.server.ts`, `*.action.ts` + `*.action.server.ts`, or `*.stream.ts` + `*.stream.server.ts`, or `*.workflow.tsx`
39
+ files anywhere in this tree — discovery is by file convention.
@@ -0,0 +1,15 @@
1
+ import { Effect } from 'effect'
2
+ import { MailService } from '@voltro/plugin-mail'
3
+
4
+ const execute = (input: { email: string; name: string }) =>
5
+ Effect.gen(function* () {
6
+ const mail = yield* MailService
7
+ const res = yield* mail.send({
8
+ to: input.email,
9
+ template: 'welcome',
10
+ props: { name: input.name },
11
+ })
12
+ return { id: res.id, provider: res.provider }
13
+ })
14
+
15
+ export default execute
@@ -0,0 +1,21 @@
1
+ // `mail.sendWelcome` — example action that sends the `welcome` template
2
+ // via @voltro/plugin-mail. With the `console` provider nothing leaves the
3
+ // process — the send is logged + captured in the dev outbox (dashboard
4
+ // Mail panel). Swap the provider in app.config.ts for real delivery.
5
+ //
6
+ // Email is external I/O → an action, not a mutation.
7
+
8
+ import { Schema } from 'effect'
9
+ import { defineAction } from '@voltro/protocol'
10
+
11
+ export const sendWelcome = defineAction({
12
+ name: 'mail.sendWelcome',
13
+ input: Schema.Struct({
14
+ email: Schema.String,
15
+ name: Schema.String,
16
+ }),
17
+ output: Schema.Struct({
18
+ id: Schema.String,
19
+ provider: Schema.String,
20
+ }),
21
+ })
@@ -0,0 +1,34 @@
1
+ // Backend app for the {{projectName}} project. Read by `voltro dev`.
2
+ //
3
+ // `store: 'memory'` is the dev-friendly default — fast startup, no
4
+ // docker. Switch to `'postgres'` when you wire `docker compose up`
5
+ // from the repo root.
6
+ //
7
+ // This variant ships transactional email out of the box via
8
+ // `@voltro/plugin-mail`. The `console` provider just logs what would be
9
+ // sent (zero-config, no API key) — swap to `'resend'` / `'postmark'` /
10
+ // `'sendgrid'` / `'smtp'` (+ the matching env var, e.g. RESEND_API_KEY)
11
+ // for real delivery. Templates live in `emails/*.email.tsx`; preview +
12
+ // send them from the dashboard's Mail tab.
13
+ import { defineEnv, envVar } from '@voltro/env'
14
+ import { mailPlugin } from '@voltro/plugin-mail'
15
+
16
+ // Typed environment — declare your env once; it's validated at boot (fail-fast)
17
+ // and read on the server via `serverEnv` / `getSecret` from '@voltro/env/server'.
18
+ // `access` is required: 'public' (browser-safe) or 'secret' (server-only, never
19
+ // bundled). Run `voltro env` to see the manifest. See the Environment docs.
20
+ export const env = defineEnv({
21
+ LOG_LEVEL: envVar.enum(['debug', 'info', 'warn', 'error'], { access: 'public', default: 'info' }),
22
+ // Add your own, e.g.:
23
+ // STRIPE_KEY: envVar.string({ access: 'secret' }),
24
+ })
25
+
26
+ export default {
27
+ type: 'api' as const,
28
+ name: '{{projectNamePascal}}{{appNamePascal}}',
29
+ store: 'memory' as const,
30
+ env,
31
+ plugins: [
32
+ mailPlugin({ provider: 'console', from: '{{projectNamePascal}} <hello@example.com>' }),
33
+ ],
34
+ }
@@ -0,0 +1,57 @@
1
+ // Schema for the {{projectName}} backend.
2
+ //
3
+ // Tables are auto-discovered: every exported `table(...)` in this file
4
+ // (or any `*.entity.ts` / `*.schema.ts` file) is registered by
5
+ // `voltro dev` — no manual barrel. `actors` + `tenants` are the
6
+ // framework's core tables: the built-in `audit()` / `tenant()` /
7
+ // `softDelete()` mixins reference them, so they must be declared (the
8
+ // CLI wires them into the mixin registry once it finds them).
9
+ //
10
+ // Add the `tenant()` mixin to a table to make it tenant-scoped — the
11
+ // runtime AND-merges `eq('tenantId', subject.tenantId)` into every
12
+ // subscription predicate, so cross-tenant reads can't leak.
13
+
14
+ import {
15
+ boolean,
16
+ databaseHandle,
17
+ id,
18
+ table,
19
+ text,
20
+ timestamp,
21
+ type InferRow,
22
+ } from '@voltro/database'
23
+ import { tenant } from '@voltro/plugin-multitenancy'
24
+
25
+ // ---------- Core tables (required by the audit / tenant mixins) ----------
26
+
27
+ export const actors = table('actors', {
28
+ id: id(),
29
+ kind: text().oneOf(['user', 'serviceAccount', 'apiKey', 'system']),
30
+ displayName: text().nullable(),
31
+ createdAt: timestamp().default('now'),
32
+ })
33
+
34
+ export const tenants = table('tenants', {
35
+ id: id(),
36
+ name: text(),
37
+ createdAt: timestamp().default('now'),
38
+ })
39
+
40
+ // ---------- Application tables — rename / replace with your own ----------
41
+
42
+ export const notes = table('notes', {
43
+ id: id({ prefix: 'note' }),
44
+ title: text(),
45
+ body: text(),
46
+ done: boolean().default(false),
47
+ })
48
+ // tenant() pulls audit() transitively → adds tenantId + createdAt /
49
+ // updatedAt / createdBy / updatedBy (auto-stamped by the runtime).
50
+ .with(tenant())
51
+ // Opt into the matcher engine: subscriptions against `notes` get a
52
+ // fresh snapshot/delta whenever a mutation writes the table.
53
+ .reactive()
54
+
55
+ export type Note = InferRow<typeof notes>
56
+
57
+ export const database = databaseHandle({ actors, tenants, notes })
@@ -0,0 +1,106 @@
1
+ // Default transactional email — a clean, ready-to-send welcome built with
2
+ // @react-email/components. Auto-discovered by `voltro dev` and registered
3
+ // with @voltro/plugin-mail, so `mail.send({ template: 'welcome', props })`
4
+ // works + the dashboard Mail panel previews it.
5
+ //
6
+ // This is a STARTER you replace: swap the copy, colours, and layout for
7
+ // your brand. The component kit (Container / Section / Button / …) handles
8
+ // the email-client quirks so it renders consistently across Gmail/Outlook/
9
+ // Apple Mail. Plain JSX tags also work if you'd rather not use the kit.
10
+ //
11
+ // Light + dark: inline styles are the LIGHT defaults; the <style> block in
12
+ // <Head> overrides colours when the client is in dark mode
13
+ // (`prefers-color-scheme`) — and, for the dashboard preview's Light/Dark
14
+ // switch, when an ancestor carries `[data-theme="dark"]`. `!important`
15
+ // beats the inline light values. Clients that strip <style> (older Outlook)
16
+ // just stay light.
17
+
18
+ import { defineEmail } from '@voltro/plugin-mail'
19
+ import {
20
+ Body,
21
+ Button,
22
+ Container,
23
+ Head,
24
+ Heading,
25
+ Hr,
26
+ Html,
27
+ Preview,
28
+ Section,
29
+ Text,
30
+ } from '@react-email/components'
31
+ import { Schema } from 'effect'
32
+
33
+ // Your product/brand name. Defaults to the project name; edit freely.
34
+ const BRAND = '{{projectNamePascal}}'
35
+
36
+ const darkCss = `
37
+ .e-body { background-color: #f4f4f5; }
38
+ @media (prefers-color-scheme: dark) {
39
+ .e-body { background-color: #0a0a0a !important; }
40
+ .e-card { background-color: #18181b !important; border-color: #27272a !important; }
41
+ .e-heading { color: #fafafa !important; }
42
+ .e-text { color: #d4d4d8 !important; }
43
+ .e-footer { color: #a1a1aa !important; }
44
+ }
45
+ [data-theme="dark"] .e-body { background-color: #0a0a0a !important; }
46
+ [data-theme="dark"] .e-card { background-color: #18181b !important; border-color: #27272a !important; }
47
+ [data-theme="dark"] .e-heading { color: #fafafa !important; }
48
+ [data-theme="dark"] .e-text { color: #d4d4d8 !important; }
49
+ [data-theme="dark"] .e-footer { color: #a1a1aa !important; }
50
+ [data-theme="light"] .e-body { background-color: #f4f4f5 !important; }
51
+ [data-theme="light"] .e-card { background-color: #ffffff !important; border-color: #e4e4e7 !important; }
52
+ [data-theme="light"] .e-heading { color: #18181b !important; }
53
+ [data-theme="light"] .e-text { color: #3f3f46 !important; }
54
+ [data-theme="light"] .e-footer { color: #a1a1aa !important; }
55
+ `
56
+
57
+ const styles = {
58
+ // No backgroundColor here on purpose — react-email copies the Body inline
59
+ // style onto an inner wrapper <td>, which would then keep the light bg even
60
+ // in dark mode. The body bg lives in the `.e-body` class (light + dark) so
61
+ // a single rule controls it. (margin/padding/font stay inline.)
62
+ body: { fontFamily: 'ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif', margin: 0, padding: '32px 0' },
63
+ container: { backgroundColor: '#ffffff', borderRadius: '12px', maxWidth: '480px', margin: '0 auto', padding: '40px', border: '1px solid #e4e4e7' },
64
+ heading: { fontSize: '22px', fontWeight: 700, color: '#18181b', margin: '0 0 16px' },
65
+ text: { fontSize: '15px', lineHeight: '24px', color: '#3f3f46', margin: '0 0 16px' },
66
+ button: { backgroundColor: '#6d28d9', color: '#ffffff', borderRadius: '8px', fontSize: '15px', fontWeight: 600, textDecoration: 'none', padding: '12px 20px', display: 'inline-block' },
67
+ hr: { borderColor: '#e4e4e7', margin: '28px 0' },
68
+ footer: { fontSize: '13px', lineHeight: '20px', color: '#a1a1aa', margin: 0 },
69
+ } as const
70
+
71
+ export const welcome = defineEmail({
72
+ name: 'welcome',
73
+ props: Schema.Struct({ name: Schema.String }),
74
+ // Realistic example props — the dashboard preview box pre-fills with this.
75
+ preview: { name: 'Mario' },
76
+ subject: (p) => `Welcome to ${BRAND}, ${p.name}!`,
77
+ render: (p) => (
78
+ <Html>
79
+ <Head>
80
+ <meta name="color-scheme" content="light dark" />
81
+ <meta name="supported-color-schemes" content="light dark" />
82
+ <style dangerouslySetInnerHTML={{ __html: darkCss }} />
83
+ </Head>
84
+ <Preview>Your {BRAND} account is ready — let's get you started.</Preview>
85
+ <Body className="e-body" style={styles.body}>
86
+ <Container className="e-card" style={styles.container}>
87
+ <Heading className="e-heading" style={styles.heading}>Welcome, {p.name} 👋</Heading>
88
+ <Text className="e-text" style={styles.text}>
89
+ Thanks for joining {BRAND}. Your workspace is ready — jump in and
90
+ create your first project whenever you're set.
91
+ </Text>
92
+ <Section>
93
+ <Button href="https://example.com/dashboard" style={styles.button}>
94
+ Open your dashboard
95
+ </Button>
96
+ </Section>
97
+ <Hr style={styles.hr} />
98
+ <Text className="e-footer" style={styles.footer}>
99
+ You're receiving this because you signed up for {BRAND}. If this
100
+ wasn't you, just ignore this email.
101
+ </Text>
102
+ </Container>
103
+ </Body>
104
+ </Html>
105
+ ),
106
+ })
@@ -0,0 +1,19 @@
1
+ import { assertOwnTenant } from '@voltro/plugin-multitenancy/guard'
2
+ import type { AppContext } from '@voltro/runtime'
3
+
4
+ const execute = async (
5
+ input: { tenantId: string; title: string; body: string },
6
+ ctx: AppContext,
7
+ ) => {
8
+ assertOwnTenant(input.tenantId, ctx.request.subject)
9
+ // Framework auto-injects a `note_…` id from the table's id() decl.
10
+ return ctx.store.insert('notes', {
11
+ title: input.title,
12
+ body: input.body,
13
+ done: false,
14
+ tenantId: input.tenantId,
15
+ createdAt: new Date(),
16
+ })
17
+ }
18
+
19
+ export default execute
@@ -0,0 +1,37 @@
1
+ // Creates a note. The handler's `assertOwnTenant` guard rejects
2
+ // cross-tenant spoofing — input.tenantId MUST match the resolved
3
+ // subject's tenantId, else the rpc layer surfaces a typed
4
+ // `TenantMismatch` error.
5
+
6
+ import { defineMutation } from '@voltro/protocol'
7
+ import { TenantMismatch } from '@voltro/plugin-multitenancy/guard'
8
+ import { Schema } from 'effect'
9
+
10
+ export const createNote = defineMutation({
11
+ name: 'notes.create',
12
+ target: {
13
+ table: 'notes',
14
+ op: 'insert',
15
+ shape: (input: { tenantId: string; title: string; body: string }) => ({
16
+ title: input.title,
17
+ body: input.body,
18
+ done: false,
19
+ tenantId: input.tenantId,
20
+ createdAt: new Date(),
21
+ }),
22
+ },
23
+ input: Schema.Struct({
24
+ tenantId: Schema.String,
25
+ title: Schema.NonEmptyString,
26
+ body: Schema.String,
27
+ }),
28
+ output: Schema.Struct({
29
+ id: Schema.String,
30
+ title: Schema.String,
31
+ body: Schema.String,
32
+ done: Schema.Boolean,
33
+ tenantId: Schema.String,
34
+ createdAt: Schema.Date,
35
+ }),
36
+ error: TenantMismatch,
37
+ })