@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,95 @@
1
+ // @vitest-environment jsdom
2
+ //
3
+ // The [locale] mirror pages re-export the bare page and add getStaticPaths,
4
+ // which tells `voltro build` which locale-prefixed paths to emit. The default
5
+ // locale (en) is NOT listed — it lives at the bare path — so only /de is
6
+ // produced. The dynamic release mirror emits the CROSS-PRODUCT of non-default
7
+ // locales × release slugs (here: de × every release).
8
+
9
+ import { describe, expect, test, vi } from 'vitest'
10
+
11
+ interface Release {
12
+ version: string
13
+ releasedAt: string
14
+ slug: string
15
+ tags: ReadonlyArray<string>
16
+ title: string
17
+ summary: string
18
+ html: string
19
+ }
20
+
21
+ const releases: ReadonlyArray<Release> = [
22
+ {
23
+ version: '0.2.0',
24
+ releasedAt: '2026-06-21',
25
+ slug: 'v0-2-0',
26
+ tags: ['feature'],
27
+ title: 'Typed env',
28
+ summary: 'Declare your environment once.',
29
+ html: '<p>body</p>',
30
+ },
31
+ {
32
+ version: '0.1.0',
33
+ releasedAt: '2026-01-15',
34
+ slug: 'v0-1-0',
35
+ tags: ['feature'],
36
+ title: 'First release',
37
+ summary: 'The initial cut.',
38
+ html: '<p>body</p>',
39
+ },
40
+ ]
41
+
42
+ // The real release source reads .mdx via `import.meta.glob` + node-gated shiki;
43
+ // mock it (used by the [slug] mirror's cross-product getStaticPaths and by the
44
+ // transitively-imported base pages).
45
+ const releaseBySlug = (slug: string): Release | undefined => releases.find((r) => r.slug === slug)
46
+ vi.mock('../../lib/releases', () => ({ releases, releaseBySlug }))
47
+ vi.mock('@voltro/changelog', () => ({
48
+ highlightRelease: async (r: Release) => r,
49
+ }))
50
+ vi.mock('@voltro/web', () => ({
51
+ useLoaderData: () => ({ release: releases[0] }),
52
+ notFound: (detail?: string) => {
53
+ throw new Error(detail)
54
+ },
55
+ useLocation: () => '/',
56
+ }))
57
+ vi.mock('@voltro/i18n', () => ({
58
+ defineCatalog: <T,>(c: T): T => c,
59
+ defineLocale:
60
+ () =>
61
+ <T,>(c: T): T =>
62
+ c,
63
+ useLocale: () => 'en',
64
+ useT: (id: string) => id,
65
+ T: ({ id }: { id: string }) => id,
66
+ }))
67
+
68
+ const indexMirror = await import('./index')
69
+ const releaseMirror = await import('./[slug]')
70
+
71
+ describe('index mirror — getStaticPaths', () => {
72
+ test('emits only non-default locales (just /de)', async () => {
73
+ const paths = await indexMirror.getStaticPaths()
74
+ expect(paths).toEqual([{ params: { locale: 'de' } }])
75
+ })
76
+
77
+ test('re-exports the base page component + its meta function', () => {
78
+ expect(typeof indexMirror.default).toBe('function')
79
+ expect(indexMirror.meta({ locale: 'de' }).title).toContain('Changelog')
80
+ })
81
+ })
82
+
83
+ describe('release mirror — getStaticPaths (locale × slug cross-product)', () => {
84
+ test('emits one path per non-default locale × release slug', async () => {
85
+ const paths = await releaseMirror.getStaticPaths()
86
+ expect(paths).toEqual(releases.map((r) => ({ params: { locale: 'de', slug: r.slug } })))
87
+ })
88
+
89
+ test('re-exports the base release page + its config exports', () => {
90
+ expect(typeof releaseMirror.default).toBe('function')
91
+ expect(releaseMirror.renderMode).toBe('static')
92
+ expect(releaseMirror.interactive).toBe('none')
93
+ expect(typeof releaseMirror.loader).toBe('function')
94
+ })
95
+ })
@@ -0,0 +1,127 @@
1
+ // @vitest-environment jsdom
2
+ //
3
+ // `/[slug]` per-release page — `getStaticPaths` (one path per release),
4
+ // `loader` (look up the release, shiki-highlight it, `notFound()` on a miss),
5
+ // `meta(loaderData)`, and the render (which injects the highlighted HTML). We
6
+ // mock `../lib/releases` (avoids the node-only glob) and `@voltro/changelog`
7
+ // (`highlightRelease` pulls in shiki) and `@voltro/web` (`notFound`).
8
+
9
+ import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
10
+ import { act, createElement, type ReactNode } from 'react'
11
+ import { createRoot, type Root } from 'react-dom/client'
12
+ // Type-only import — erased at runtime, so it does NOT pull @voltro/changelog's
13
+ // node-only glob (the value module stays mocked below). Using the real Release
14
+ // type keeps the mock in lockstep with the framework's shape (tags: ReleaseTag[],
15
+ // draft, body, …) so the test typechecks against what the page actually consumes.
16
+ import type { Release } from '@voltro/changelog'
17
+
18
+ const releases: ReadonlyArray<Release> = [
19
+ {
20
+ version: '0.1.0',
21
+ releasedAt: '2026-01-15',
22
+ slug: 'v0-1-0',
23
+ tags: ['feature'],
24
+ title: 'First release',
25
+ summary: 'The initial cut.',
26
+ draft: false,
27
+ body: 'The initial cut.',
28
+ html: '<p>plain</p>',
29
+ },
30
+ ]
31
+
32
+ const releaseBySlug = (slug: string): Release | undefined => releases.find((r) => r.slug === slug)
33
+
34
+ vi.mock('../lib/releases', () => ({ releases, releaseBySlug }))
35
+ // `highlightRelease` runs shiki in node; the page only needs it to return a
36
+ // (possibly re-rendered) release — the identity, tagged so we can assert it ran.
37
+ vi.mock('@voltro/changelog', () => ({
38
+ highlightRelease: async (r: Release) => ({ ...r, html: `<pre>${r.title}</pre>` }),
39
+ }))
40
+
41
+ const loaderData = vi.fn<() => { release: Release }>()
42
+ class NotFoundError extends Error {}
43
+ vi.mock('@voltro/web', () => ({
44
+ useLoaderData: () => loaderData(),
45
+ notFound: (detail?: string) => {
46
+ throw new NotFoundError(detail)
47
+ },
48
+ // `withLocalePrefix` (lib/locale) reads useLocation; the page pins the locale
49
+ // via useLocale, so any bare path is fine here.
50
+ useLocation: () => '/',
51
+ }))
52
+ // The back-link chrome comes from @voltro/i18n; stub it (useLocale → en,
53
+ // <T> passes children through).
54
+ vi.mock('@voltro/i18n', () => ({
55
+ defineCatalog: <T,>(c: T): T => c,
56
+ defineLocale:
57
+ () =>
58
+ <T,>(c: T): T =>
59
+ c,
60
+ useLocale: () => 'en',
61
+ T: ({ id }: { id: string }) => id,
62
+ }))
63
+
64
+ const { default: ReleasePage, getStaticPaths, loader, meta } = await import('./[slug]')
65
+
66
+ ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
67
+
68
+ let container: HTMLDivElement
69
+ let root: Root
70
+
71
+ const render = (node: ReactNode): void => {
72
+ container = document.createElement('div')
73
+ document.body.appendChild(container)
74
+ act(() => {
75
+ root = createRoot(container)
76
+ root.render(node)
77
+ })
78
+ }
79
+
80
+ beforeEach(() => {
81
+ loaderData.mockReset()
82
+ })
83
+
84
+ afterEach(() => {
85
+ if (root) act(() => root.unmount())
86
+ container?.remove()
87
+ document.body.innerHTML = ''
88
+ })
89
+
90
+ describe('changelog [slug] — getStaticPaths', () => {
91
+ test('enumerates one path per release slug', async () => {
92
+ const paths = await getStaticPaths()
93
+ expect(paths.map((p) => p.params.slug)).toEqual(['v0-1-0'])
94
+ })
95
+ })
96
+
97
+ describe('changelog [slug] — loader', () => {
98
+ test('resolves the release and runs it through highlightRelease', async () => {
99
+ const { release } = await loader({ params: { slug: 'v0-1-0' } } as never)
100
+ expect(release.slug).toBe('v0-1-0')
101
+ expect(release.html).toBe('<pre>First release</pre>')
102
+ })
103
+
104
+ test('throws notFound for an unknown slug', async () => {
105
+ await expect(loader({ params: { slug: 'nope' } } as never)).rejects.toBeInstanceOf(
106
+ NotFoundError,
107
+ )
108
+ })
109
+ })
110
+
111
+ describe('changelog [slug] — meta', () => {
112
+ test('builds the per-release title + description from the loader data', () => {
113
+ const m = meta({ loaderData: { release: releases[0]! } })
114
+ expect(m.title).toContain('First release')
115
+ expect(m.description).toBe('The initial cut.')
116
+ })
117
+ })
118
+
119
+ describe('changelog [slug] — render', () => {
120
+ test('renders the title, version, and injects the highlighted HTML body', () => {
121
+ loaderData.mockReturnValue({ release: { ...releases[0]!, html: '<p>the body html</p>' } })
122
+ render(createElement(ReleasePage))
123
+ expect(container.querySelector('h1')?.textContent).toBe('First release')
124
+ expect(container.textContent).toContain('v0.1.0')
125
+ expect(container.innerHTML).toContain('the body html')
126
+ })
127
+ })
@@ -0,0 +1,52 @@
1
+ // Per-release page. `getStaticPaths` enumerates every release slug so
2
+ // `voltro build` pre-renders one HTML file per release. The loader runs at
3
+ // build time (Node) where `highlightRelease` shiki-highlights the code
4
+ // fences; in the browser it's a no-op and the plain marked HTML is used.
5
+
6
+ import type { ReactNode } from 'react'
7
+ import { useLoaderData, notFound, type LoaderFn } from '@voltro/web'
8
+ import { highlightRelease } from '@voltro/changelog'
9
+ import { T, useLocale } from '@voltro/i18n'
10
+ import { releases, releaseBySlug, type Release } from '../lib/releases'
11
+ import { withLocalePrefix } from '../lib/locale'
12
+
13
+ export const renderMode = 'static' as const
14
+ export const interactive = 'none' as const
15
+
16
+ export const getStaticPaths = async (): Promise<Array<{ params: { slug: string } }>> =>
17
+ releases.map((release) => ({ params: { slug: release.slug } }))
18
+
19
+ export const loader: LoaderFn<{ release: Release }> = async ({ params }) => {
20
+ const release = params.slug ? releaseBySlug(params.slug) : undefined
21
+ if (!release) return notFound(`release ${params.slug ?? ''}`)
22
+ return { release: await highlightRelease(release) }
23
+ }
24
+
25
+ export const meta = ({ loaderData }: { loaderData: { release: Release } }) => ({
26
+ title: `${loaderData.release.title} — Changelog`,
27
+ description: loaderData.release.summary,
28
+ })
29
+
30
+ export default function ReleasePage(): ReactNode {
31
+ const { release } = useLoaderData<{ release: Release }>()
32
+ // The active locale (from the layout's URL provider) keeps the back-link on
33
+ // the current language.
34
+ const locale = useLocale()
35
+ return (
36
+ <article className="changelog-prose">
37
+ <p className="changelog-meta">
38
+ <a href={withLocalePrefix('/', locale)}>
39
+ <T id="post.backToList" />
40
+ </a>
41
+ </p>
42
+ <h1>{release.title}</h1>
43
+ <p className="changelog-meta">
44
+ <time dateTime={release.releasedAt}>{release.releasedAt}</time> · v{release.version}
45
+ {release.tags.map((tag) => (
46
+ <span key={tag} className="changelog-tag">{tag}</span>
47
+ ))}
48
+ </p>
49
+ <div dangerouslySetInnerHTML={{ __html: release.html }} />
50
+ </article>
51
+ )
52
+ }
@@ -0,0 +1,112 @@
1
+ // @vitest-environment jsdom
2
+ //
3
+ // `/` changelog index — lists every release, newest first. The real release
4
+ // source (`../lib/releases`) reads .mdx via `import.meta.glob` + node-gated
5
+ // shiki, so we mock it with canned releases and assert the observable render:
6
+ // config exports, meta, one entry per release, and its tags + link.
7
+
8
+ import { afterEach, describe, expect, test, vi } from 'vitest'
9
+ import { act, createElement, type ReactNode } from 'react'
10
+ import { createRoot, type Root } from 'react-dom/client'
11
+
12
+ interface Release {
13
+ version: string
14
+ releasedAt: string
15
+ slug: string
16
+ tags: ReadonlyArray<string>
17
+ title: string
18
+ summary: string
19
+ html: string
20
+ }
21
+
22
+ const releases: ReadonlyArray<Release> = [
23
+ {
24
+ version: '0.2.0',
25
+ releasedAt: '2026-06-21',
26
+ slug: 'v0-2-0',
27
+ tags: ['feature', 'performance'],
28
+ title: 'Typed env + faster boot',
29
+ summary: 'Declare your environment once.',
30
+ html: '<p>body</p>',
31
+ },
32
+ {
33
+ version: '0.1.0',
34
+ releasedAt: '2026-01-15',
35
+ slug: 'v0-1-0',
36
+ tags: ['feature'],
37
+ title: 'First release',
38
+ summary: 'The initial cut.',
39
+ html: '<p>body</p>',
40
+ },
41
+ ]
42
+
43
+ vi.mock('../lib/releases', () => ({ releases }))
44
+ // `withLocalePrefix` (lib/locale) reads useLocation; the page pins the locale
45
+ // via useLocale, so any bare path is fine here.
46
+ vi.mock('@voltro/web', () => ({ useLocation: () => '/' }))
47
+ // Chrome (meta via getCatalog + the empty state) comes from @voltro/i18n;
48
+ // stub it (identity catalog defs, useLocale → en, <T> passes children through).
49
+ vi.mock('@voltro/i18n', () => ({
50
+ defineCatalog: <T,>(c: T): T => c,
51
+ defineLocale:
52
+ () =>
53
+ <T,>(c: T): T =>
54
+ c,
55
+ useLocale: () => 'en',
56
+ useT: (id: string) => id,
57
+ T: ({ id }: { id: string }) => id,
58
+ }))
59
+
60
+ const { default: ChangelogIndex, meta, renderMode, interactive } = await import('./index')
61
+
62
+ ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true
63
+
64
+ let container: HTMLDivElement
65
+ let root: Root
66
+
67
+ const render = (node: ReactNode): void => {
68
+ container = document.createElement('div')
69
+ document.body.appendChild(container)
70
+ act(() => {
71
+ root = createRoot(container)
72
+ root.render(node)
73
+ })
74
+ }
75
+
76
+ afterEach(() => {
77
+ if (root) act(() => root.unmount())
78
+ container?.remove()
79
+ document.body.innerHTML = ''
80
+ })
81
+
82
+ describe('changelog index — config + localized meta', () => {
83
+ test('is a static page with zero client JS', () => {
84
+ expect(renderMode).toBe('static')
85
+ expect(interactive).toBe('none')
86
+ })
87
+
88
+ test('meta() returns a localized title + description per locale', () => {
89
+ expect(meta({ locale: 'en' }).title).toContain('Changelog')
90
+ expect(meta({ locale: 'en' }).description).toContain('release notes')
91
+ expect(meta({ locale: 'de' }).description).toContain('Release-Notes')
92
+ })
93
+ })
94
+
95
+ describe('changelog index — render', () => {
96
+ test('renders one entry per release, each linking to /<slug> with its tags', () => {
97
+ render(createElement(ChangelogIndex))
98
+ const entries = Array.from(container.querySelectorAll('.changelog-entry'))
99
+ expect(entries).toHaveLength(2)
100
+
101
+ const links = Array.from(container.querySelectorAll('.changelog-entry h2 a'))
102
+ expect(links.map((a) => a.getAttribute('href'))).toEqual(['/v0-2-0', '/v0-1-0'])
103
+ expect(links[0]!.textContent).toBe('Typed env + faster boot')
104
+
105
+ // The first entry surfaces both of its tags.
106
+ const firstTags = Array.from(entries[0]!.querySelectorAll('.changelog-tag')).map(
107
+ (t) => t.textContent,
108
+ )
109
+ expect(firstTags).toEqual(['feature', 'performance'])
110
+ expect(container.textContent).toContain('v0.2.0')
111
+ })
112
+ })
@@ -0,0 +1,55 @@
1
+ // Changelog index — every release, newest first, mounted at `/` (default
2
+ // locale) and mirrored at `/de` by src/pages/[locale]/index.tsx. Pure static
3
+ // render with no client JS (`interactive: 'none'`).
4
+ //
5
+ // `meta` is a FUNCTION of `{ locale }` so each variant's <title>/<description>
6
+ // is localised in the pre-rendered HTML. The release list itself is CONTENT
7
+ // (the .mdx files) and is NOT translated — only the chrome (page meta, the
8
+ // empty state) comes from the catalogs. Entry links are locale-prefixed via
9
+ // `withLocalePrefix` so /de stays on /de.
10
+
11
+ import type { ReactNode } from 'react'
12
+ import type { PageMeta } from '@voltro/web'
13
+ import { T, useLocale } from '@voltro/i18n'
14
+ import { releases } from '../lib/releases'
15
+ import { getCatalog, withLocalePrefix } from '../lib/locale'
16
+
17
+ export const renderMode = 'static' as const
18
+ export const interactive = 'none' as const
19
+
20
+ export const meta = ({ locale }: { locale: string }): PageMeta => {
21
+ const c = getCatalog(locale)
22
+ return {
23
+ title: c['meta.home.title'],
24
+ description: c['meta.home.description'],
25
+ }
26
+ }
27
+
28
+ export default function ChangelogIndex(): ReactNode {
29
+ const locale = useLocale()
30
+ if (releases.length === 0) {
31
+ return (
32
+ <p>
33
+ <T id="empty.body" values={{ code: (chunks: ReactNode) => <code>{chunks}</code> }} />
34
+ </p>
35
+ )
36
+ }
37
+ return (
38
+ <div>
39
+ {releases.map((release) => (
40
+ <article key={release.slug} className="changelog-entry">
41
+ <p className="changelog-meta">
42
+ <time dateTime={release.releasedAt}>{release.releasedAt}</time> · v{release.version}
43
+ {release.tags.map((tag) => (
44
+ <span key={tag} className="changelog-tag">{tag}</span>
45
+ ))}
46
+ </p>
47
+ <h2>
48
+ <a href={withLocalePrefix(`/${release.slug}`, locale)}>{release.title}</a>
49
+ </h2>
50
+ <p>{release.summary}</p>
51
+ </article>
52
+ ))}
53
+ </div>
54
+ )
55
+ }
@@ -0,0 +1,84 @@
1
+ // Root layout — wraps every page in the framework's BlogLayout shell inside a
2
+ // URL-driven <I18nProvider> (Strategy B: en at the bare path, de under /de).
3
+ // `voltro build` pre-renders each page once per locale with the right catalog
4
+ // baked in. The language switcher goes in BlogLayout's `headerRight` slot as a
5
+ // plain <a> per locale — a real navigation to that locale's crawlable URL,
6
+ // which is correct for a zero-JS static content site.
7
+ //
8
+ // BlogLayout carries its own inline styles; globals.css only styles the
9
+ // markdown body + the list.
10
+
11
+ import type { ReactNode } from 'react'
12
+ import { BlogLayout, useLocation } from '@voltro/web'
13
+ import { I18nProvider, T, useLocale, useT } from '@voltro/i18n'
14
+ import {
15
+ CATALOGS,
16
+ DEFAULT_LOCALE,
17
+ SUPPORTED_LOCALES,
18
+ stripLocalePrefix,
19
+ useUrlLocale,
20
+ withLocalePrefix,
21
+ } from '../lib/locale'
22
+ import '../globals.css'
23
+
24
+ interface LayoutProps {
25
+ readonly children: ReactNode
26
+ }
27
+
28
+ // Rendered INSIDE the provider so <T> / useT resolve against the active
29
+ // catalog. topNav labels must be plain strings, so they come from useT.
30
+ function ChangelogShell({ children }: LayoutProps): ReactNode {
31
+ const locale = useLocale()
32
+ const pathname = useLocation()
33
+ const barePath = stripLocalePrefix(pathname)
34
+ const releasesLabel = useT('nav.releases')
35
+ const rssLabel = useT('nav.rss')
36
+
37
+ return (
38
+ <BlogLayout
39
+ brand={
40
+ <>
41
+ {{capProjectName}} <T id="nav.changelog" />
42
+ </>
43
+ }
44
+ pathname={pathname}
45
+ topNav={[
46
+ { label: releasesLabel, href: withLocalePrefix('/', locale) },
47
+ // One shared feed for every locale — never locale-prefixed.
48
+ { label: rssLabel, href: '/rss.xml' },
49
+ ]}
50
+ headerRight={
51
+ <span className="cl-lang">
52
+ <span className="cl-lang-label">
53
+ <T id="nav.language" />:
54
+ </span>
55
+ {SUPPORTED_LOCALES.map((code) => (
56
+ <a
57
+ key={code}
58
+ href={withLocalePrefix(barePath, code)}
59
+ aria-current={code === locale ? 'true' : undefined}
60
+ >
61
+ {code.toUpperCase()}
62
+ </a>
63
+ ))}
64
+ </span>
65
+ }
66
+ footer={
67
+ <span>
68
+ <T id="footer.builtWith" />
69
+ </span>
70
+ }
71
+ >
72
+ {children}
73
+ </BlogLayout>
74
+ )
75
+ }
76
+
77
+ export default function Layout({ children }: LayoutProps): ReactNode {
78
+ const locale = useUrlLocale()
79
+ return (
80
+ <I18nProvider locale={locale} messages={CATALOGS[locale]} defaultLocale={DEFAULT_LOCALE}>
81
+ <ChangelogShell>{children}</ChangelogShell>
82
+ </I18nProvider>
83
+ )
84
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "id": "changelog",
3
+ "kind": "web",
4
+ "summary": "Changelog / release-notes site: MDX releases in content/releases/, a rendered list + per-release pages (shiki-highlighted code), and an RSS feed — powered by @voltro/changelog.",
5
+ "tags": ["web", "frontend", "changelog", "releases", "rss", "static"]
6
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "../../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "lib": ["ES2024", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "moduleResolution": "Bundler"
8
+ },
9
+ "include": ["src/**/*"],
10
+ "exclude": ["node_modules", "dist", ".framework"]
11
+ }
@@ -0,0 +1,55 @@
1
+ # {{projectName}} / {{appName}}
2
+
3
+ A library of standalone serverless functions (template: **edge-functions**).
4
+ Each `functions/*.serverless.ts` is bundled + deployed on its own — there is
5
+ no long-running server here and no dev port.
6
+
7
+ ## The functions
8
+
9
+ | File | Method | Demonstrates |
10
+ |---|---|---|
11
+ | `health.serverless.ts` | GET | simplest diagnostic; `ctx.env`; pure `Effect.sync` |
12
+ | `shareLink.serverless.ts` | POST | pure compute; runtime hints (memory/timeout/region) |
13
+ | `geoGreeting.serverless.ts` | GET | reading `ctx.request.headers` (edge geo) |
14
+ | `slackNotify.serverless.ts` | POST | `ctx.waitUntil` — background work after the response |
15
+ | `currencyConvert.serverless.ts` | POST | outbound HTTP via `HttpClient`; read + transform JSON |
16
+ | `verifySignature.serverless.ts` | POST | Web Crypto HMAC; `ServerlessHttpError` 401 |
17
+ | `aiComplete.serverless.ts` | POST | a third-party API needing a secret (`ctx.env`); 502 mapping |
18
+ | `resolveLink.serverless.ts` | GET | a lookup; 404 via `ServerlessHttpError` |
19
+
20
+ Every function is **edge-safe** (no `node:*`), so the same code runs on
21
+ Cloudflare Workers, Scaleway Functions, and your own node box.
22
+
23
+ ## Run one locally
24
+
25
+ ```bash
26
+ pnpm install
27
+ voltro serverless list . # what's here
28
+ voltro serverless dev functions/health.serverless.ts # one function on :8910
29
+ curl http://localhost:8910/
30
+
31
+ # functions that need config read it from the env:
32
+ SLACK_WEBHOOK_URL=https://hooks.slack.com/... \
33
+ voltro serverless dev functions/slackNotify.serverless.ts
34
+ ```
35
+
36
+ `voltro serverless serve .` runs ALL of them at once (each mounted at
37
+ `/<name>`) — handy as a single self-hosted sidecar.
38
+
39
+ ## Deploy
40
+
41
+ ```bash
42
+ voltro serverless build . # bundle all → inspect
43
+ voltro serverless deploy --target node # self-host kit (Dockerfile + README)
44
+ voltro serverless deploy --target cloudflare # Cloudflare Workers
45
+ voltro serverless deploy --target scaleway --namespace-id <id> # Scaleway Functions
46
+ ```
47
+
48
+ Set each function's secrets at deploy time (the host's env / secret store):
49
+ `SLACK_WEBHOOK_URL`, `SIGNING_SECRET`, `OPENAI_API_KEY`, `SHARE_BASE_URL`, …
50
+
51
+ ## Add your own
52
+
53
+ Drop a new `functions/<name>.serverless.ts` exporting
54
+ `export default defineServerless({ … })`. It's discovered automatically — no
55
+ registry, no config.
@@ -0,0 +1,58 @@
1
+ // aiComplete — a one-shot LLM completion at the edge.
2
+ //
3
+ // Demonstrates: calling a third-party API that needs a SECRET (the key lives in
4
+ // `ctx.env`, never in the bundle), an optional input field, reading the JSON
5
+ // response, and mapping an upstream failure to a 502. Uses the OpenAI
6
+ // chat-completions shape; point it at any compatible endpoint via OPENAI_BASE_URL.
7
+ //
8
+ // OPENAI_API_KEY=sk-... voltro serverless dev functions/aiComplete.serverless.ts
9
+ // curl -X POST http://localhost:8910/ -d '{"prompt":"Name three primary colors."}'
10
+
11
+ import { Effect, Schema } from 'effect'
12
+ import { HttpClient, HttpClientRequest } from '@effect/platform'
13
+ import { defineServerless, ServerlessHttpError } from '@voltro/serverless'
14
+
15
+ export default defineServerless({
16
+ name: 'ai-complete',
17
+ method: 'POST',
18
+ input: Schema.Struct({
19
+ prompt: Schema.String.pipe(Schema.minLength(1), Schema.maxLength(4000)),
20
+ system: Schema.optional(Schema.String),
21
+ }),
22
+ output: Schema.Struct({ text: Schema.String }),
23
+ runtime: { memoryMb: 256, timeoutSeconds: 30 },
24
+ handler: ({ prompt, system }, ctx) =>
25
+ Effect.gen(function* () {
26
+ const apiKey = ctx.env.OPENAI_API_KEY
27
+ if (!apiKey) {
28
+ return yield* Effect.fail(
29
+ new ServerlessHttpError({ status: 503, message: 'ai-not-configured', detail: 'Set OPENAI_API_KEY.' }),
30
+ )
31
+ }
32
+ const baseUrl = ctx.env.OPENAI_BASE_URL ?? 'https://api.openai.com'
33
+ const model = ctx.env.OPENAI_MODEL ?? 'gpt-4o-mini'
34
+
35
+ const http = yield* HttpClient.HttpClient
36
+ const request = HttpClientRequest.post(`${baseUrl}/v1/chat/completions`).pipe(
37
+ HttpClientRequest.setHeader('authorization', `Bearer ${apiKey}`),
38
+ HttpClientRequest.bodyUnsafeJson({
39
+ model,
40
+ max_tokens: 400,
41
+ messages: [
42
+ ...(system ? [{ role: 'system', content: system }] : []),
43
+ { role: 'user', content: prompt },
44
+ ],
45
+ }),
46
+ )
47
+
48
+ const response = yield* http.execute(request)
49
+ if (response.status >= 400) {
50
+ const detail = yield* response.text
51
+ return yield* Effect.fail(new ServerlessHttpError({ status: 502, message: 'ai-call-failed', detail }))
52
+ }
53
+ const body = (yield* response.json) as {
54
+ choices?: ReadonlyArray<{ message?: { content?: string } }>
55
+ }
56
+ return { text: body.choices?.[0]?.message?.content ?? '' }
57
+ }),
58
+ })