@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,21 @@
1
+ import { Effect } from 'effect'
2
+ import type { AppContext } from '@voltro/runtime'
3
+ import { StorageService } from '@voltro/plugin-storage'
4
+
5
+ const execute = (input: { bytesBase64: string; contentType: string; filename: string }, ctx: AppContext) =>
6
+ Effect.gen(function* () {
7
+ const storage = yield* StorageService
8
+ const bytes = new Uint8Array(Buffer.from(input.bytesBase64, 'base64'))
9
+ const ref = yield* storage.put({
10
+ bytes,
11
+ contentType: input.contentType,
12
+ visibility: 'private',
13
+ ownerId: ctx.request.subject.id,
14
+ tenantId: ctx.request.subject.tenantId,
15
+ key: `documents/${ctx.request.subject.id ?? 'anon'}/${input.filename}`,
16
+ access: [{ roles: ['admin'] }, { tenant: true }],
17
+ })
18
+ return { id: ref.id }
19
+ })
20
+
21
+ export default execute
@@ -0,0 +1,20 @@
1
+ // `storage.uploadDocument` — stores a PRIVATE document. The owner is
2
+ // always allowed; this policy additionally grants the `admin` role and
3
+ // same-tenant subjects. Fetch the bytes via the plugin's access-checked
4
+ // `storage.mintUrl` route, or grant a specific user/group from the
5
+ // dashboard's Storage tab.
6
+
7
+ import { Schema } from 'effect'
8
+ import { defineAction } from '@voltro/protocol'
9
+
10
+ export const uploadDocument = defineAction({
11
+ name: 'storage.uploadDocument',
12
+ input: Schema.Struct({
13
+ bytesBase64: Schema.String,
14
+ contentType: Schema.String,
15
+ filename: Schema.String,
16
+ }),
17
+ output: Schema.Struct({
18
+ id: Schema.String,
19
+ }),
20
+ })
@@ -0,0 +1,38 @@
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 (file metadata + grants persist there).
6
+ //
7
+ // This variant ships file storage out of the box via
8
+ // `@voltro/plugin-storage`. The `memory` provider keeps blobs in-process
9
+ // (zero-config, dev only) — swap to `'s3'` / `'minio'` (+ S3_* env) for
10
+ // real object storage, or `'filesystem'` for on-disk dev.
11
+ //
12
+ // - PUBLIC objects are served direct from the bucket/CDN (set
13
+ // `cdnBaseUrl`); the app's serve route is only a dev fallback.
14
+ // - PRIVATE objects are gated by an access policy (owner / roles /
15
+ // groups / scopes / tenant / api-key / password / custom guard) PLUS
16
+ // per-object grants you manage from the dashboard's Storage tab.
17
+ import { defineEnv, envVar } from '@voltro/env'
18
+ import { storagePlugin } from '@voltro/plugin-storage'
19
+
20
+ // Typed environment — declare your env once; it's validated at boot (fail-fast)
21
+ // and read on the server via `serverEnv` / `getSecret` from '@voltro/env/server'.
22
+ // `access` is required: 'public' (browser-safe) or 'secret' (server-only, never
23
+ // bundled). Run `voltro env` to see the manifest. See the Environment docs.
24
+ export const env = defineEnv({
25
+ LOG_LEVEL: envVar.enum(['debug', 'info', 'warn', 'error'], { access: 'public', default: 'info' }),
26
+ // Add your own, e.g.:
27
+ // STRIPE_KEY: envVar.string({ access: 'secret' }),
28
+ })
29
+
30
+ export default {
31
+ type: 'api' as const,
32
+ name: '{{projectNamePascal}}{{appNamePascal}}',
33
+ store: 'memory' as const,
34
+ env,
35
+ plugins: [
36
+ storagePlugin({ provider: 'memory' }),
37
+ ],
38
+ }
@@ -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,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
+ })
@@ -0,0 +1,27 @@
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
+ "typecheck": "tsc --noEmit",
10
+ "test": "voltro test"
11
+ },
12
+ "dependencies": {
13
+ "@voltro/cli": "0.1.0",
14
+ "@voltro/database": "0.1.0",
15
+ "@voltro/env": "0.1.0",
16
+ "@voltro/plugin-multitenancy": "0.1.0",
17
+ "@voltro/plugin-storage": "0.1.0",
18
+ "@voltro/protocol": "0.1.0",
19
+ "@voltro/runtime": "0.1.0",
20
+ "effect": "^3.21.2"
21
+ },
22
+ "devDependencies": {
23
+ "@voltro/testing": "0.1.0",
24
+ "typescript": "^5.7.0",
25
+ "vitest": "^3.0.0"
26
+ }
27
+ }
@@ -0,0 +1,14 @@
1
+ import type { AppContext } from '@voltro/runtime'
2
+
3
+ const execute = (_input: Record<string, never>, _ctx: AppContext) => ({
4
+ descriptor: {
5
+ table: 'notes' as const,
6
+ predicate: undefined,
7
+ order: [{ column: 'createdAt' as const, direction: 'desc' as const }],
8
+ take: 100,
9
+ skip: undefined,
10
+ projection: undefined,
11
+ },
12
+ })
13
+
14
+ export default execute
@@ -0,0 +1,20 @@
1
+ // Streaming subscription: every change to `notes` for the caller's
2
+ // tenant lands as a delta. The runtime AND-merges tenant scope into
3
+ // the predicate via the `tenant()` mixin on the table — no manual
4
+ // `eq('tenantId', ...)` needed in the handler.
5
+
6
+ import { defineQuery } from '@voltro/protocol'
7
+ import { Schema } from 'effect'
8
+
9
+ export const listNotes = defineQuery({
10
+ name: 'notes.list',
11
+ input: Schema.Struct({}),
12
+ output: Schema.Struct({
13
+ id: Schema.String,
14
+ title: Schema.String,
15
+ body: Schema.String,
16
+ done: Schema.Boolean,
17
+ tenantId: Schema.String,
18
+ createdAt: Schema.Date,
19
+ }),
20
+ })
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "api-backend-storage",
3
+ "kind": "api",
4
+ "summary": "Voltro backend with file storage wired: @voltro/plugin-storage with public (CDN-direct) + private (policy + per-object grants) objects, plus upload examples you browse/share from the dashboard. Same minimal base as api-backend.",
5
+ "tags": ["api", "backend", "storage", "files", "uploads", "starter"]
6
+ }
@@ -0,0 +1,50 @@
1
+ // Unit test with `@voltro/testing` — no database, no running server. Importing
2
+ // `../database/schema` registers the `notes` / `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 handler gets in production,
5
+ // so tenant auto-scoping + audit auto-fill behave exactly as at runtime.
6
+ // 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 notes / actors / tenants
11
+ import { TenantMismatch } from '@voltro/plugin-multitenancy/guard'
12
+ import createNote from '../mutations/notes.create.mutation.server'
13
+
14
+ describe('notes.create', () => {
15
+ it('inserts a note stamped to the caller tenant', async () => {
16
+ const ctx = makeTestContext({
17
+ subject: { type: 'user', id: 'user_1', tenantId: 'acme' },
18
+ store: mockStore({ notes: [] }),
19
+ })
20
+ const row = await createNote({ tenantId: 'acme', title: 'Hello', body: 'World' }, ctx)
21
+
22
+ expect(row['title']).toBe('Hello')
23
+ expect(row['tenantId']).toBe('acme') // assertOwnTenant let it through + stamped
24
+ expect(row['done']).toBe(false)
25
+ expect(String(row['id'])).toMatch(/^note_/) // TypeID auto-injected from id()
26
+ })
27
+
28
+ it('rejects a cross-tenant spoof — input.tenantId must match the subject', async () => {
29
+ const ctx = makeTestContext({
30
+ subject: { type: 'user', id: 'user_1', tenantId: 'acme' },
31
+ store: mockStore({ notes: [] }),
32
+ })
33
+ await expect(
34
+ createNote({ tenantId: 'other-tenant', title: 'spoof', body: '' }, ctx),
35
+ ).rejects.toBeInstanceOf(TenantMismatch)
36
+ })
37
+
38
+ it('isolates tenants — t2 never sees t1 rows (REAL tenant scoping)', async () => {
39
+ const ctx = makeTestContext({
40
+ subject: { type: 'user', id: 'u1', tenantId: 't1' },
41
+ store: mockStore({ notes: [] }),
42
+ })
43
+ await createNote({ tenantId: 't1', title: 'secret', body: '' }, ctx)
44
+
45
+ // Re-scope the SAME store to a different tenant — the real WHERE filter
46
+ // (eq tenantId) hides t1's row from t2.
47
+ const seenByT2 = await ctx.withTenant('t2', (c) => c.store.query(database.notes.descriptor))
48
+ expect(seenByT2).toHaveLength(0)
49
+ })
50
+ })
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../../tsconfig.base.json",
3
+ "include": ["**/*.ts", "**/*.tsx"],
4
+ "exclude": ["node_modules", "dist"]
5
+ }
@@ -0,0 +1,17 @@
1
+ # DEV-ONLY environment for the {{projectName}} api.
2
+ #
3
+ # `voltro dev` loads this file into the process environment at boot, BEFORE the
4
+ # env-validation gate and BEFORE plugins activate. That's how the governance
5
+ # plugin's field-encryption cipher resolves its key (it reads the Secrets-
6
+ # Resolver, i.e. process.env — a typed-env `default` would NOT reach it).
7
+ #
8
+ # ⚠️ The key below is a PUBLIC, DEV-ONLY placeholder shipped with the template.
9
+ # NEVER use it in production. Generate a real one and set it in your
10
+ # deployment's environment / secrets manager:
11
+ #
12
+ # openssl rand -hex 32
13
+ #
14
+ # Lose the key → lose the data (AES-256-GCM fails closed, never silent
15
+ # corruption). Rotating it makes every existing `.encrypted()` value
16
+ # unreadable.
17
+ VOLTRO_FIELD_ENCRYPTION_KEY=00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff
@@ -0,0 +1,88 @@
1
+ # {{projectName}} / {{appName}}
2
+
3
+ Voltro backend scaffold (template: **api-data-advanced**).
4
+
5
+ A small **library/catalog** (authors + books) that closes the advanced
6
+ schema-DSL gaps — features that are documented but shown in no other
7
+ template: the `*.entity.ts` / `*.relations.ts` split with eager loading,
8
+ full-text search, `dbEnum`, array / generated / encrypted columns, and
9
+ declarative query caching.
10
+
11
+ ## Boot
12
+
13
+ ```bash
14
+ pnpm install # at the repo root
15
+ pnpm --filter @{{projectName}}/{{appName}} dev
16
+ # → http://localhost:4000
17
+ # → ws://localhost:4000/ws
18
+ ```
19
+
20
+ Boots with **zero setup**: the `.encrypted()` `authors.bio` column needs an
21
+ AES-256-GCM key, and the shipped `.env` supplies a **DEV-ONLY** placeholder so
22
+ `voltro dev` comes up immediately. `voltro dev` then auto-migrates the schema
23
+ and runs the boot seed, so the catalog has two authors + three books right away.
24
+
25
+ > ⚠️ **Before production**, replace the key in `.env` with a real one and move
26
+ > it into your deployment's secret store — never ship the placeholder. Generate
27
+ > one with `openssl rand -hex 32`. **Lose the key → lose the ciphertext** (GCM
28
+ > fails closed); **rotating it** makes every existing `.encrypted()` value
29
+ > unreadable.
30
+
31
+ ## Environment
32
+
33
+ | Var | Access | Why |
34
+ |---|---|---|
35
+ | `VOLTRO_FIELD_ENCRYPTION_KEY` | secret | AES-256-GCM key for the `.encrypted()` `authors.bio` column (32-byte hex). `governancePlugin({ fieldEncryption: true })` resolves it through the **Secrets-Resolver** — i.e. the process environment, which the shipped `.env` populates (a `defineEnv` `default` would NOT reach the cipher). Boot fails loud if an `.encrypted()` column exists but the cipher can't resolve a key. |
36
+ | `LOG_LEVEL` | public | `debug \| info \| warn \| error` (default `info`). |
37
+
38
+ ## What this demonstrates
39
+
40
+ | Feature | Where | Notes |
41
+ |---|---|---|
42
+ | `*.entity.ts` / `*.relations.ts` split | `database/*.entity.ts`, `database/*.relations.ts` | One table per file; relations declared OUTSIDE the table descriptor. |
43
+ | `relations()` + eager `.with()` | `authors.relations.ts`, `books.relations.ts`, `queries/authors.withBooks.query.server.ts` | `database.authors.with({ books: true })` → each author carries a `books[]` array in ONE SQL roundtrip. |
44
+ | Full-text search | `books.entity.ts` (`.fullTextIndex('bookSearch', ['title','summary'])`) + `queries/books.search.query.server.ts` (`.matching('bookSearch', q)`) | One declaration, three backends (postgres tsvector, mysql/mariadb FULLTEXT, sqlite FTS5, mssql ranked-LIKE). |
45
+ | `dbEnum(...)` | `books.entity.ts` (`bookGenre`) | Native `CREATE TYPE … ENUM` on postgres; native `ENUM(...)` on mysql/mariadb; CHECK fallback elsewhere. |
46
+ | `array(text())` | `books.entity.ts` (`tags`) | Native `text[]` on postgres; JSON-string codec on other dialects — the API stays "a JS array". |
47
+ | `.generatedAs(expr, { stored })` | `books.entity.ts` (`slug`) | DB-computed, persisted, indexable column derived from `title`. Don't write it — the engine fills it. |
48
+ | `.encrypted()` | `authors.entity.ts` (`bio`) | Transparent AES-256-GCM at rest via `governancePlugin({ fieldEncryption: true })` in `app.config.ts`. |
49
+ | Declarative query caching | `queries/books.search.query.ts` (`cache: { ttl, swr, scope }`) | Server snapshot cache with auto-invalidation on writes to `books`; `scope: 'subject'` because the query is tenant-filtered. |
50
+ | Boot seed | `seeds/catalog.seed.ts` | Idempotent `upsertByUnique` authors + books. |
51
+
52
+ ## Files
53
+
54
+ ```
55
+ app.config.ts governancePlugin({ fieldEncryption: true })
56
+ database/
57
+ actors.entity.ts core audit-subject table
58
+ tenants.entity.ts core tenant boundary
59
+ authors.entity.ts name + .encrypted() bio
60
+ books.entity.ts dbEnum genre, array tags, generated slug, FTS index
61
+ authors.relations.ts author → many books
62
+ books.relations.ts book → one author
63
+ index.ts databaseHandle({...}) + relation registration
64
+ queries/
65
+ books.search.query.ts(.server) FTS via .matching(...) + cache
66
+ authors.withBooks.query.ts(.server) eager-load via .with({ books: true })
67
+ seeds/
68
+ catalog.seed.ts demo authors + books
69
+ ```
70
+
71
+ ## Try it
72
+
73
+ The dev AuthMiddleware resolves the `acme` tenant from the `x-tenant`
74
+ header (the seed writes under `acme`). Subscribe to the queries from a
75
+ web app via `useSubscription('app', 'books.search', { q: 'magic' })` and
76
+ `useSubscription('app', 'authors.withBooks')`, or invoke them over HTTP
77
+ through `POST /_voltro/inspect/invoke` for a one-shot snapshot.
78
+
79
+ ## Switching to a real SQL store
80
+
81
+ `store: 'memory'` keeps boot zero-infra. Switch `app.config.ts` to
82
+ `store: 'postgres'` (and `docker compose up` a postgres) to see the
83
+ native DDL the migrator emits for each feature — `CREATE TYPE`,
84
+ `text[]`, the STORED generated column, and the tsvector + GIN FTS index.
85
+ The handler code is unchanged across every dialect.
86
+
87
+ Drop more `*.entity.ts` / `*.query.ts` / `*.mutation.ts` / `*.action.ts`
88
+ files anywhere in this tree — discovery is by file convention.
@@ -0,0 +1,56 @@
1
+ // Backend app for the {{projectName}} project. Read by `voltro dev`.
2
+ //
3
+ // This template demonstrates the framework's ADVANCED schema-DSL surface
4
+ // on a small library/catalog domain (authors + books):
5
+ // - the *.entity.ts / *.relations.ts split (one table per file),
6
+ // - relations() + eager `.with({ books: true })` loading,
7
+ // - full-text search via `.fullTextIndex(...)` + `.matching(...)`,
8
+ // - `dbEnum(...)` native enum columns,
9
+ // - `array(text())` columns + a stored `.generatedAs(...)` column,
10
+ // - `.encrypted()` field encryption (AES-256-GCM at rest),
11
+ // - declarative query result caching (`cache` on `defineQuery`).
12
+ //
13
+ // `store: 'memory'` keeps boot zero-infra (no docker). The schema DSL is
14
+ // identical across every SQL backend — switch to `'postgres'` to see the
15
+ // native ENUM / tsvector-FTS / text[] DDL the migrator emits. On `memory`
16
+ // the same features run through the in-process store (FTS degrades to a
17
+ // substring scan, arrays round-trip as JS arrays, encryption still applies).
18
+ //
19
+ // `governancePlugin({ fieldEncryption: true })` registers the AES-256-GCM
20
+ // cipher that makes the `authors.bio` `.encrypted()` column work — without
21
+ // it, boot fails loud ("an `.encrypted()` column exists but no cipher is
22
+ // registered"). The key is read from the secret `VOLTRO_FIELD_ENCRYPTION_KEY`
23
+ // via the Secrets-Resolver (which reads the process environment). The shipped
24
+ // `.env` carries a DEV-ONLY key so the template boots out of the box — see the
25
+ // README to generate a real one for production. Lose the key → lose the
26
+ // ciphertext (GCM fails closed).
27
+ import { defineEnv, envVar } from '@voltro/env'
28
+ import { governancePlugin } from '@voltro/plugin-governance'
29
+
30
+ // Typed environment — declare your env once; it's validated at boot (fail-fast)
31
+ // and read on the server via `serverEnv` / `getSecret` from '@voltro/env/server'.
32
+ // `access` is required: 'public' (browser-safe) or 'secret' (server-only, never
33
+ // bundled). Run `voltro env` to see the manifest. See the Environment docs.
34
+ export const env = defineEnv({
35
+ LOG_LEVEL: envVar.enum(['debug', 'info', 'warn', 'error'], { access: 'public', default: 'info' }),
36
+ // The 32-byte hex key the field-encryption cipher uses. NO `default` here on
37
+ // purpose: governancePlugin resolves it through the Secrets-Resolver (which
38
+ // reads `process.env`), NOT this typed-env default — a default would satisfy
39
+ // the boot gate while the cipher still failed to resolve. The shipped `.env`
40
+ // supplies a DEV-ONLY value so `voltro dev` boots; for production generate a
41
+ // real key (`openssl rand -hex 32`) and set VOLTRO_FIELD_ENCRYPTION_KEY in
42
+ // the environment. Lose the key → lose the ciphertext (GCM fails closed).
43
+ VOLTRO_FIELD_ENCRYPTION_KEY: envVar.string({ access: 'secret' }),
44
+ })
45
+
46
+ export default {
47
+ type: 'api' as const,
48
+ name: '{{capProjectName}}{{capAppName}}',
49
+ store: 'memory' as const,
50
+ env,
51
+ plugins: [
52
+ // Registers the cipher for `.encrypted()` columns. Key from the secret
53
+ // VOLTRO_FIELD_ENCRYPTION_KEY (or pass { fieldEncryption: { secretKey } }).
54
+ governancePlugin({ fieldEncryption: true }),
55
+ ],
56
+ }
@@ -0,0 +1,14 @@
1
+ // Core table — the universal audit subject (whoever/whatever initiated a
2
+ // write: a user, a service account, an API key, or the system). Every
3
+ // `createdBy` / `updatedBy` / `deletedBy` references it, so the `audit()` /
4
+ // `tenant()` / `softDelete()` mixins require it to exist. Declared one-per-
5
+ // file with the `*.entity.ts` convention — the CLI auto-discovers it.
6
+
7
+ import { id, table, text, timestamp } from '@voltro/database'
8
+
9
+ export const actors = table('actors', {
10
+ id: id(),
11
+ kind: text().oneOf(['user', 'serviceAccount', 'apiKey', 'system']),
12
+ displayName: text().nullable(),
13
+ createdAt: timestamp().default('now'),
14
+ })
@@ -0,0 +1,30 @@
1
+ // Authors — demonstrates `.encrypted()` field encryption.
2
+ //
3
+ // `bio` is flagged `.encrypted()`: the store middleware transparently
4
+ // encrypts it on write (AES-256-GCM) and decrypts on read, so handlers
5
+ // always see plaintext while the column stores an opaque `enc:v1:…` string
6
+ // on disk on every dialect.
7
+ //
8
+ // ‼️ This column ONLY works because `app.config.ts` wires
9
+ // `governancePlugin({ fieldEncryption: true })`, which registers the
10
+ // cipher (key from the secret VOLTRO_FIELD_ENCRYPTION_KEY). Boot fails
11
+ // loud if an `.encrypted()` column exists but no cipher is registered.
12
+ //
13
+ // An `.encrypted()` column is ciphertext on disk — you CANNOT filter or
14
+ // sort by its plaintext in SQL. Encrypt only what you read back whole
15
+ // (PII, tokens, notes). A book search never touches `bio`, so this is safe.
16
+
17
+ import { id, table, text } from '@voltro/database'
18
+ import { tenant } from '@voltro/plugin-multitenancy/mixin'
19
+
20
+ export const authors = table('authors', {
21
+ id: id({ prefix: 'author' }),
22
+ name: text(),
23
+ // Encrypted at rest. Requires governancePlugin({ fieldEncryption: true }).
24
+ bio: text().encrypted().nullable(),
25
+ })
26
+ // tenant() pulls audit() transitively → adds tenantId + createdAt /
27
+ // updatedAt / createdBy / updatedBy (auto-stamped by the runtime).
28
+ .with(tenant())
29
+ // Opt into the matcher engine so subscriptions react to writes.
30
+ .reactive()
@@ -0,0 +1,15 @@
1
+ // Relations are declared OUTSIDE the table descriptor, in a `*.relations.ts`
2
+ // file (convention). The framework registers them at boot; the query
3
+ // builder's `.with({ books: true })` chain uses them to eager-load.
4
+ //
5
+ // An author has MANY books. The `foreignKey` auto-derives because exactly
6
+ // one `reference()` column on `books` (`authorId`) points back at `authors`
7
+ // — no explicit override needed.
8
+
9
+ import { relations } from '@voltro/database'
10
+ import { authors } from './authors.entity'
11
+ import { books } from './books.entity'
12
+
13
+ export const authorsRelations = relations(authors, ({ many }) => ({
14
+ books: many(books),
15
+ }))
@@ -0,0 +1,59 @@
1
+ // Books — the centrepiece of the advanced schema-DSL tour. One table,
2
+ // five specialized column features:
3
+ //
4
+ // - `authorId` → reference(() => authors) (FK + auto B-tree index)
5
+ // - `genre` → dbEnum(...).column() (native ENUM type)
6
+ // - `tags` → array(text()) (native text[] on postgres,
7
+ // JSON fallback elsewhere)
8
+ // - `slug` → text().generatedAs(..., { stored: true })
9
+ // (DB-computed, persisted, indexable)
10
+ // - `.fullTextIndex('bookSearch', [...])` (FTS over title + summary;
11
+ // query with `.matching(...)`)
12
+
13
+ import { array, dbEnum, id, reference, table, text } from '@voltro/database'
14
+ import { tenant } from '@voltro/plugin-multitenancy/mixin'
15
+ import { authors } from './authors.entity'
16
+
17
+ // A native ENUM type. Declared once (module-level) so it's a reusable handle:
18
+ // - postgres → CREATE TYPE book_genre AS ENUM (...). ADD VALUE is O(1).
19
+ // - mysql / mariadb → native ENUM('fiction', ...) column.
20
+ // - mssql / sqlite → NVARCHAR / TEXT + CHECK fallback.
21
+ // Distinct from `text().oneOf([...])`, which is a CROSS-DIALECT CHECK on every
22
+ // backend — reach for `dbEnum` on postgres-primary apps for the cheap
23
+ // ADD-VALUE migration. The `as const` is required for the literal-union type.
24
+ export const bookGenre = dbEnum('book_genre', [
25
+ 'fiction',
26
+ 'nonfiction',
27
+ 'fantasy',
28
+ 'sciFi',
29
+ 'mystery',
30
+ 'biography',
31
+ ] as const)
32
+
33
+ export const books = table('books', {
34
+ id: id({ prefix: 'book' }),
35
+ authorId: reference(() => authors), // FK → authors, auto-indexed
36
+ title: text(),
37
+ summary: text(),
38
+ // Native ENUM column, defaulting to 'fiction'.
39
+ genre: bookGenre.column().default('fiction'),
40
+ // Array column → `text[]` on postgres; JSON-string codec elsewhere. The
41
+ // user-facing API stays "I get back a JS string array" on every dialect.
42
+ tags: array(text()).default([]),
43
+ // DB-computed STORED column — a URL-friendly slug derived from `title` in
44
+ // the DB engine on INSERT + UPDATE. `stored: true` persists it on disk so
45
+ // it's indexable. Same-row columns only (it can't see subject/tenant —
46
+ // that's what `.computed(row => ...)` is for). The expression is raw SQL
47
+ // emitted verbatim, so it must stay portable (double-quoted identifier).
48
+ slug: text().generatedAs(`lower("title")`, { stored: true }),
49
+ })
50
+ // Full-text search index over title + summary. One declaration, three
51
+ // backends (postgres tsvector+GIN, mysql/mariadb FULLTEXT, sqlite FTS5;
52
+ // mssql ranked-LIKE fallback). Query it with `.matching('bookSearch', q)`.
53
+ .fullTextIndex('bookSearch', ['title', 'summary'], {
54
+ config: 'english',
55
+ weights: { title: 'A', summary: 'B' },
56
+ })
57
+ // tenant() pulls audit() transitively (tenantId + audit columns).
58
+ .with(tenant())
59
+ .reactive()
@@ -0,0 +1,10 @@
1
+ // A book belongs to ONE author. The inverse of authors→books.
2
+ // `one(authors)` resolves the `authorId` FK automatically.
3
+
4
+ import { relations } from '@voltro/database'
5
+ import { authors } from './authors.entity'
6
+ import { books } from './books.entity'
7
+
8
+ export const booksRelations = relations(books, ({ one }) => ({
9
+ author: one(authors),
10
+ }))
@@ -0,0 +1,23 @@
1
+ // The database handle + barrel. Imports every entity + exports
2
+ // `databaseHandle({...})`. Tables are auto-discovered by the CLI from the
3
+ // `*.entity.ts` files; the handle is what server code queries through
4
+ // (`database.books.matching(...)`, `database.authors.with({ books: true })`).
5
+ //
6
+ // Importing the `*.relations.ts` files here is what registers the relations
7
+ // at boot so the eager-load `.with(...)` walker can resolve them.
8
+
9
+ import { databaseHandle, type InferRow } from '@voltro/database'
10
+ import { actors } from './actors.entity'
11
+ import { tenants } from './tenants.entity'
12
+ import { authors } from './authors.entity'
13
+ import { books } from './books.entity'
14
+
15
+ // Register relations (side-effecting imports).
16
+ import './authors.relations'
17
+ import './books.relations'
18
+
19
+ export { actors, tenants, authors, books }
20
+ export type Author = InferRow<typeof authors>
21
+ export type Book = InferRow<typeof books>
22
+
23
+ export const database = databaseHandle({ actors, tenants, authors, books })