alepha 0.18.2 → 0.18.3

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 (397) hide show
  1. package/assets/devtools-ui/200.html +2 -2
  2. package/assets/devtools-ui/200.html.br +0 -0
  3. package/assets/devtools-ui/404.html +2 -2
  4. package/assets/devtools-ui/404.html.br +0 -0
  5. package/assets/devtools-ui/{asset.BfSBZ5Dd.css → asset.hG_f8HuK.css} +1 -1
  6. package/assets/devtools-ui/asset.hG_f8HuK.css.br +0 -0
  7. package/assets/devtools-ui/chunk.B3au4Lhg.js +1 -0
  8. package/assets/devtools-ui/chunk.B3au4Lhg.js.br +0 -0
  9. package/assets/devtools-ui/chunk.BLOrlnMB.js +1 -0
  10. package/assets/devtools-ui/chunk.BLOrlnMB.js.br +0 -0
  11. package/assets/devtools-ui/chunk.BLR01ljW.js +1 -0
  12. package/assets/devtools-ui/chunk.BLR01ljW.js.br +0 -0
  13. package/assets/devtools-ui/chunk.BTXaIUlA.js +1 -0
  14. package/assets/devtools-ui/chunk.BTXaIUlA.js.br +0 -0
  15. package/assets/devtools-ui/{chunk.lJL-lgnW.js → chunk.BhJaxmm8.js} +1 -1
  16. package/assets/devtools-ui/chunk.BhJaxmm8.js.br +0 -0
  17. package/assets/devtools-ui/chunk.BtoNxFuL.js +1 -0
  18. package/assets/devtools-ui/chunk.BtoNxFuL.js.br +0 -0
  19. package/assets/devtools-ui/chunk.C8YUV2Wd.js +1 -0
  20. package/assets/devtools-ui/chunk.C8YUV2Wd.js.br +0 -0
  21. package/assets/devtools-ui/{chunk.M6wyKO_3.js → chunk.CBbIgDzE.js} +2 -2
  22. package/assets/devtools-ui/chunk.CBbIgDzE.js.br +0 -0
  23. package/assets/devtools-ui/chunk.CFqIniwA.js +1 -0
  24. package/assets/devtools-ui/chunk.CFqIniwA.js.br +0 -0
  25. package/assets/devtools-ui/chunk.CLFF7f7-.js +1 -0
  26. package/assets/devtools-ui/chunk.CLFF7f7-.js.br +0 -0
  27. package/assets/devtools-ui/chunk.CRsBbA10.js +1 -0
  28. package/assets/devtools-ui/chunk.CRsBbA10.js.br +0 -0
  29. package/assets/devtools-ui/{chunk.DbEH1oOB.js → chunk.CZPo6v95.js} +1 -1
  30. package/assets/devtools-ui/chunk.CZPo6v95.js.br +0 -0
  31. package/assets/devtools-ui/chunk.D0fWgNos.js +1 -0
  32. package/assets/devtools-ui/chunk.D0fWgNos.js.br +1 -0
  33. package/assets/devtools-ui/chunk.D7-0ziQ6.js +1 -0
  34. package/assets/devtools-ui/chunk.D7-0ziQ6.js.br +0 -0
  35. package/assets/devtools-ui/chunk.DAewe0vm.js +1 -0
  36. package/assets/devtools-ui/chunk.DAewe0vm.js.br +0 -0
  37. package/assets/devtools-ui/chunk.DJRQEYqK.js +1 -0
  38. package/assets/devtools-ui/chunk.DJRQEYqK.js.br +0 -0
  39. package/assets/devtools-ui/{chunk.CZl6J9DF.js → chunk.DMAxv14p.js} +1 -1
  40. package/assets/devtools-ui/chunk.DMAxv14p.js.br +0 -0
  41. package/assets/devtools-ui/{chunk.BT2IiBkZ.js → chunk.DMImnNjU.js} +1 -1
  42. package/assets/devtools-ui/chunk.DMImnNjU.js.br +0 -0
  43. package/assets/devtools-ui/chunk.DeeQsidk.js +9 -0
  44. package/assets/devtools-ui/chunk.DeeQsidk.js.br +0 -0
  45. package/assets/devtools-ui/chunk.DqEwn9Vj.js +7 -0
  46. package/assets/devtools-ui/chunk.DqEwn9Vj.js.br +0 -0
  47. package/assets/devtools-ui/chunk.Dt8OsQey.js +1 -0
  48. package/assets/devtools-ui/chunk.Dt8OsQey.js.br +0 -0
  49. package/assets/devtools-ui/{chunk.B9pX3zit.js → chunk.Dtp8oa_f.js} +1 -1
  50. package/assets/devtools-ui/chunk.Dtp8oa_f.js.br +0 -0
  51. package/assets/devtools-ui/chunk.Dx3JzAYM.js +1 -0
  52. package/assets/devtools-ui/chunk.Dx3JzAYM.js.br +0 -0
  53. package/assets/devtools-ui/chunk.GCOj1-5E.js +1 -0
  54. package/assets/devtools-ui/chunk.GCOj1-5E.js.br +0 -0
  55. package/assets/devtools-ui/chunk.IC1LD8BH.js +1 -0
  56. package/assets/devtools-ui/chunk.IC1LD8BH.js.br +0 -0
  57. package/assets/devtools-ui/chunk.IwuB_TqW.js +1 -0
  58. package/assets/devtools-ui/chunk.IwuB_TqW.js.br +0 -0
  59. package/assets/devtools-ui/chunk.Qqapj2zq.js +1 -0
  60. package/assets/devtools-ui/chunk.Qqapj2zq.js.br +0 -0
  61. package/assets/devtools-ui/{chunk.C79YouPp.js → chunk.TKKKndOy.js} +1 -1
  62. package/assets/devtools-ui/chunk.TKKKndOy.js.br +0 -0
  63. package/assets/devtools-ui/chunk.YHTVhFQT.js +1 -0
  64. package/assets/devtools-ui/chunk.YHTVhFQT.js.br +0 -0
  65. package/assets/devtools-ui/chunk.fnod6uEi.js +1 -0
  66. package/assets/devtools-ui/chunk.fnod6uEi.js.br +0 -0
  67. package/assets/devtools-ui/chunk.mOCRmXjo.js +1 -0
  68. package/assets/devtools-ui/chunk.mOCRmXjo.js.br +0 -0
  69. package/assets/devtools-ui/chunk.qZTNEAK0.js +1 -0
  70. package/assets/devtools-ui/chunk.qZTNEAK0.js.br +0 -0
  71. package/assets/devtools-ui/chunk.rc9m0y4-.js +1 -0
  72. package/assets/devtools-ui/chunk.rc9m0y4-.js.br +0 -0
  73. package/assets/devtools-ui/entry.Cxc5QLCU.js +80 -0
  74. package/assets/devtools-ui/entry.Cxc5QLCU.js.br +0 -0
  75. package/assets/devtools-ui/index.html +2 -2
  76. package/assets/devtools-ui/index.html.br +0 -0
  77. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  78. package/assets/swagger-ui/swagger-ui.css +1 -1
  79. package/dist/api/audits/index.d.ts +61 -5
  80. package/dist/api/audits/index.d.ts.map +1 -1
  81. package/dist/api/files/index.d.ts +61 -5
  82. package/dist/api/files/index.d.ts.map +1 -1
  83. package/dist/api/jobs/index.d.ts +61 -5
  84. package/dist/api/jobs/index.d.ts.map +1 -1
  85. package/dist/api/jobs/index.js +4 -2
  86. package/dist/api/jobs/index.js.map +1 -1
  87. package/dist/api/keys/index.d.ts +5 -5
  88. package/dist/api/notifications/index.browser.js +44 -1
  89. package/dist/api/notifications/index.browser.js.map +1 -1
  90. package/dist/api/notifications/index.d.ts +187 -2
  91. package/dist/api/notifications/index.d.ts.map +1 -1
  92. package/dist/api/notifications/index.js +143 -8
  93. package/dist/api/notifications/index.js.map +1 -1
  94. package/dist/api/parameters/index.d.ts +61 -5
  95. package/dist/api/parameters/index.d.ts.map +1 -1
  96. package/dist/api/users/index.d.ts +330 -93
  97. package/dist/api/users/index.d.ts.map +1 -1
  98. package/dist/api/users/index.js +27 -36
  99. package/dist/api/users/index.js.map +1 -1
  100. package/dist/cli/config/index.d.ts +46 -0
  101. package/dist/cli/config/index.d.ts.map +1 -0
  102. package/dist/cli/config/index.js +20 -0
  103. package/dist/cli/config/index.js.map +1 -0
  104. package/dist/cli/core/index.d.ts +69 -66
  105. package/dist/cli/core/index.d.ts.map +1 -1
  106. package/dist/cli/core/index.js +329 -196
  107. package/dist/cli/core/index.js.map +1 -1
  108. package/dist/cli/platform/index.d.ts +302 -63
  109. package/dist/cli/platform/index.d.ts.map +1 -1
  110. package/dist/cli/platform/index.js +455 -25
  111. package/dist/cli/platform/index.js.map +1 -1
  112. package/dist/core/index.browser.js +125 -87
  113. package/dist/core/index.browser.js.map +1 -1
  114. package/dist/core/index.d.ts +62 -53
  115. package/dist/core/index.d.ts.map +1 -1
  116. package/dist/core/index.js +125 -87
  117. package/dist/core/index.js.map +1 -1
  118. package/dist/core/index.native.js +125 -87
  119. package/dist/core/index.native.js.map +1 -1
  120. package/dist/core/index.workerd.js +125 -87
  121. package/dist/core/index.workerd.js.map +1 -1
  122. package/dist/crypto/index.d.ts +18 -1
  123. package/dist/crypto/index.d.ts.map +1 -1
  124. package/dist/crypto/index.js +29 -3
  125. package/dist/crypto/index.js.map +1 -1
  126. package/dist/devtools/index.js +3 -12
  127. package/dist/devtools/index.js.map +1 -1
  128. package/dist/logger/index.d.ts +10 -1
  129. package/dist/logger/index.d.ts.map +1 -1
  130. package/dist/logger/index.js +19 -9
  131. package/dist/logger/index.js.map +1 -1
  132. package/dist/orm/core/index.browser.js +57 -1
  133. package/dist/orm/core/index.browser.js.map +1 -1
  134. package/dist/orm/core/index.bun.js +378 -19
  135. package/dist/orm/core/index.bun.js.map +1 -1
  136. package/dist/orm/core/index.d.ts +328 -9
  137. package/dist/orm/core/index.d.ts.map +1 -1
  138. package/dist/orm/core/index.js +384 -21
  139. package/dist/orm/core/index.js.map +1 -1
  140. package/dist/orm/postgres/index.bun.js +49 -17
  141. package/dist/orm/postgres/index.bun.js.map +1 -1
  142. package/dist/orm/postgres/index.d.ts +47 -21
  143. package/dist/orm/postgres/index.d.ts.map +1 -1
  144. package/dist/orm/postgres/index.js +52 -17
  145. package/dist/orm/postgres/index.js.map +1 -1
  146. package/dist/react/core/index.d.ts +1 -1
  147. package/dist/react/core/index.d.ts.map +1 -1
  148. package/dist/react/core/index.js +6 -1
  149. package/dist/react/core/index.js.map +1 -1
  150. package/dist/react/form/index.d.ts +28 -18
  151. package/dist/react/form/index.d.ts.map +1 -1
  152. package/dist/react/form/index.js +92 -56
  153. package/dist/react/form/index.js.map +1 -1
  154. package/dist/react/router/index.browser.js +448 -116
  155. package/dist/react/router/index.browser.js.map +1 -1
  156. package/dist/react/router/index.d.ts +102 -40
  157. package/dist/react/router/index.d.ts.map +1 -1
  158. package/dist/react/router/index.js +453 -92
  159. package/dist/react/router/index.js.map +1 -1
  160. package/dist/security/index.d.ts +3 -11
  161. package/dist/security/index.d.ts.map +1 -1
  162. package/dist/security/index.js +6 -11
  163. package/dist/security/index.js.map +1 -1
  164. package/dist/server/auth/index.d.ts +22 -24
  165. package/dist/server/auth/index.d.ts.map +1 -1
  166. package/dist/server/auth/index.js +102 -82
  167. package/dist/server/auth/index.js.map +1 -1
  168. package/dist/server/cookies/index.d.ts +7 -4
  169. package/dist/server/cookies/index.d.ts.map +1 -1
  170. package/dist/server/cookies/index.js +13 -12
  171. package/dist/server/cookies/index.js.map +1 -1
  172. package/dist/server/core/index.d.ts +288 -4
  173. package/dist/server/core/index.d.ts.map +1 -1
  174. package/dist/server/core/index.js +375 -2
  175. package/dist/server/core/index.js.map +1 -1
  176. package/dist/server/links/index.browser.js +10 -71
  177. package/dist/server/links/index.browser.js.map +1 -1
  178. package/dist/server/links/index.d.ts +32 -49
  179. package/dist/server/links/index.d.ts.map +1 -1
  180. package/dist/server/links/index.js +73 -100
  181. package/dist/server/links/index.js.map +1 -1
  182. package/dist/system/index.browser.js +221 -2
  183. package/dist/system/index.browser.js.map +1 -1
  184. package/dist/system/index.d.ts +63 -1
  185. package/dist/system/index.d.ts.map +1 -1
  186. package/dist/system/index.js +221 -1
  187. package/dist/system/index.js.map +1 -1
  188. package/dist/system/index.workerd.js +224 -4
  189. package/dist/system/index.workerd.js.map +1 -1
  190. package/package.json +10 -5
  191. package/src/api/jobs/providers/JobProvider.ts +6 -3
  192. package/src/api/notifications/controllers/AdminNotificationController.ts +83 -0
  193. package/src/api/notifications/index.browser.ts +3 -0
  194. package/src/api/notifications/index.ts +14 -2
  195. package/src/api/notifications/jobs/NotificationJobs.ts +11 -2
  196. package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +20 -0
  197. package/src/api/notifications/schemas/notificationQuerySchema.ts +19 -0
  198. package/src/api/notifications/schemas/notificationResourceSchema.ts +18 -0
  199. package/src/api/notifications/services/NotificationSenderService.ts +15 -2
  200. package/src/api/users/atoms/realmAuthSettingsAtom.ts +28 -32
  201. package/src/api/users/buckets/UserBuckets.ts +1 -1
  202. package/src/api/users/jobs/UserJobs.ts +1 -1
  203. package/src/api/users/primitives/$realm.ts +8 -49
  204. package/src/api/users/providers/RealmProvider.ts +2 -3
  205. package/src/api/users/services/RegistrationService.spec.ts +7 -7
  206. package/src/api/users/services/RegistrationService.ts +3 -3
  207. package/src/api/users/services/SessionService.spec.ts +4 -4
  208. package/src/api/users/services/SessionService.ts +3 -3
  209. package/src/cli/{core → config}/defineConfig.ts +14 -20
  210. package/src/cli/config/index.ts +1 -0
  211. package/src/cli/core/commands/db.ts +65 -1
  212. package/src/cli/core/commands/dev.ts +1 -0
  213. package/src/cli/core/commands/init.ts +2 -192
  214. package/src/cli/core/index.ts +34 -11
  215. package/src/cli/core/providers/ViteDevServerProvider.ts +52 -13
  216. package/src/cli/core/services/PackageManagerUtils.ts +43 -21
  217. package/src/cli/core/services/ProjectScaffolder.ts +214 -2
  218. package/src/cli/core/services/ViteUtils.ts +57 -0
  219. package/src/cli/core/tasks/BuildClientTask.ts +7 -2
  220. package/src/cli/core/tasks/BuildCloudflareTask.ts +4 -12
  221. package/src/cli/core/tasks/BuildServerTask.ts +2 -0
  222. package/src/cli/core/tasks/BuildVercelTask.ts +165 -168
  223. package/src/cli/core/templates/alephaConfigTs.ts +1 -1
  224. package/src/cli/core/templates/apiAppSecurityTs.ts +5 -8
  225. package/src/cli/core/templates/tsconfigJson.ts +6 -1
  226. package/src/cli/platform/adapters/CloudflareAdapter.spec.ts +1 -1
  227. package/src/cli/platform/adapters/CloudflareAdapter.ts +30 -29
  228. package/src/cli/platform/atoms/platformOptions.ts +21 -0
  229. package/src/cli/platform/commands/SecretsCommand.spec.ts +298 -0
  230. package/src/cli/platform/commands/SecretsCommand.ts +283 -0
  231. package/src/cli/platform/commands/platform.ts +12 -0
  232. package/src/cli/platform/index.ts +14 -28
  233. package/src/cli/platform/providers/GitHubSecretStore.spec.ts +153 -0
  234. package/src/cli/platform/providers/GitHubSecretStore.ts +112 -0
  235. package/src/cli/platform/providers/MemorySecretStore.ts +114 -0
  236. package/src/cli/platform/providers/SecretStoreProvider.ts +39 -0
  237. package/src/cli/platform/schemas/cloudflare.ts +2 -0
  238. package/src/cli/platform/services/CloudflareApi.ts +5 -2
  239. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +115 -0
  240. package/src/cli/platform/services/DockerComposeGenerator.ts +46 -1
  241. package/src/cli/platform/services/SecretFilterService.spec.ts +111 -0
  242. package/src/cli/platform/services/SecretFilterService.ts +54 -0
  243. package/src/core/Alepha.ts +94 -25
  244. package/src/core/__tests__/Alepha-parseEnv.spec.ts +20 -0
  245. package/src/core/primitives/$memoize.ts +38 -26
  246. package/src/core/providers/AlsProvider.ts +2 -0
  247. package/src/core/providers/EventManager.ts +4 -0
  248. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +1 -4
  249. package/src/core/providers/KeylessJsonSchemaCodec.ts +19 -125
  250. package/src/core/providers/SchemaValidator.spec.ts +36 -0
  251. package/src/core/providers/SchemaValidator.ts +9 -0
  252. package/src/crypto/index.ts +6 -1
  253. package/src/crypto/providers/SecretProvider.ts +36 -0
  254. package/src/devtools/providers/DevToolsProvider.ts +3 -12
  255. package/src/logger/index.ts +33 -6
  256. package/src/logger/providers/PrettyFormatterProvider.ts +5 -3
  257. package/src/orm/__tests__/orm-next-tests.ts +492 -0
  258. package/src/orm/__tests__/orm-next.spec.ts +140 -0
  259. package/src/orm/core/constants/PG_SYMBOLS.ts +17 -0
  260. package/src/orm/core/index.bun.ts +3 -6
  261. package/src/orm/core/index.shared-server.ts +2 -0
  262. package/src/orm/core/index.shared.ts +2 -0
  263. package/src/orm/core/index.ts +5 -7
  264. package/src/orm/core/interfaces/AggregateQuery.ts +103 -0
  265. package/src/orm/core/interfaces/PgQueryWhere.ts +7 -0
  266. package/src/orm/core/primitives/$entity.ts +8 -0
  267. package/src/orm/core/primitives/$repository.ts +6 -3
  268. package/src/orm/core/primitives/$view.ts +88 -0
  269. package/src/orm/core/providers/DbCacheProvider.ts +66 -0
  270. package/src/orm/core/providers/DrizzleKitProvider.ts +42 -0
  271. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -3
  272. package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +12 -0
  273. package/src/orm/core/providers/drivers/DatabaseProvider.ts +39 -0
  274. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +2 -3
  275. package/src/orm/core/schemas/databaseEnvSchema.ts +31 -0
  276. package/src/orm/core/schemas/insertSchema.ts +13 -3
  277. package/src/orm/core/schemas/updateSchema.ts +14 -3
  278. package/src/orm/core/services/ModelBuilder.ts +26 -14
  279. package/src/orm/core/services/QueryManager.ts +13 -0
  280. package/src/orm/core/services/Repository.ts +307 -5
  281. package/src/orm/core/services/SqliteModelBuilder.ts +38 -0
  282. package/src/orm/postgres/index.bun.ts +4 -7
  283. package/src/orm/postgres/index.ts +4 -7
  284. package/src/orm/postgres/providers/BunPostgresProvider.ts +12 -2
  285. package/src/orm/postgres/providers/NodePostgresProvider.ts +7 -0
  286. package/src/orm/postgres/providers/PglitePostgresProvider.ts +10 -17
  287. package/src/orm/postgres/providers/PostgresProvider.ts +7 -36
  288. package/src/orm/postgres/schemas/postgresEnvSchema.ts +32 -0
  289. package/src/orm/postgres/services/PostgresModelBuilder.ts +40 -0
  290. package/src/react/core/components/ErrorBoundary.tsx +5 -2
  291. package/src/react/form/hooks/useFieldValue.ts +34 -0
  292. package/src/react/form/hooks/useForm.browser.spec.tsx +94 -9
  293. package/src/react/form/hooks/useForm.ts +14 -2
  294. package/src/react/form/hooks/useFormState.ts +10 -10
  295. package/src/react/form/hooks/useFormValues.ts +29 -0
  296. package/src/react/form/index.ts +3 -1
  297. package/src/react/form/services/FormModel.ts +53 -122
  298. package/src/react/router/components/ErrorViewer.tsx +333 -34
  299. package/src/react/router/components/NestedView.tsx +10 -3
  300. package/src/react/router/primitives/$page.browser.spec.tsx +34 -0
  301. package/src/react/router/primitives/$page.spec.tsx +20 -0
  302. package/src/react/router/primitives/$page.ts +24 -0
  303. package/src/react/router/providers/ReactBrowserRouterProvider.ts +14 -2
  304. package/src/react/router/providers/ReactPageProvider.ts +156 -73
  305. package/src/react/router/providers/ReactServerProvider.ts +40 -2
  306. package/src/react/router/providers/ReactServerTemplateProvider.ts +13 -1
  307. package/src/security/providers/SecurityProvider.ts +5 -27
  308. package/src/server/auth/primitives/$auth.ts +52 -19
  309. package/src/server/auth/providers/ServerAuthProvider.ts +145 -139
  310. package/src/server/cookies/providers/ServerCookiesProvider.ts +12 -24
  311. package/src/server/core/index.ts +3 -1
  312. package/src/server/core/primitives/$sse.spec.ts +315 -0
  313. package/src/server/core/primitives/$sse.ts +715 -0
  314. package/src/server/links/index.browser.ts +1 -3
  315. package/src/server/links/index.ts +0 -3
  316. package/src/server/links/providers/LinkProvider.spec.ts +12 -21
  317. package/src/server/links/providers/LinkProvider.ts +20 -52
  318. package/src/server/links/providers/ServerLinksProvider.spec.ts +106 -0
  319. package/src/server/links/providers/ServerLinksProvider.ts +113 -73
  320. package/src/server/links/schemas/apiLinksResponseSchema.ts +4 -21
  321. package/src/server/links/services/BatchCollector.ts +5 -3
  322. package/src/system/index.browser.ts +1 -0
  323. package/src/system/index.ts +3 -0
  324. package/src/system/index.workerd.ts +39 -1
  325. package/src/system/providers/WorkerdFileSystemProvider.ts +365 -0
  326. package/assets/devtools-ui/asset.BfSBZ5Dd.css.br +0 -0
  327. package/assets/devtools-ui/chunk.2NYaoqWt.js +0 -1
  328. package/assets/devtools-ui/chunk.2NYaoqWt.js.br +0 -0
  329. package/assets/devtools-ui/chunk.B052Z_xQ.js +0 -1
  330. package/assets/devtools-ui/chunk.B052Z_xQ.js.br +0 -0
  331. package/assets/devtools-ui/chunk.B4kVY90C.js +0 -1
  332. package/assets/devtools-ui/chunk.B4kVY90C.js.br +0 -0
  333. package/assets/devtools-ui/chunk.B7QJXctB.js +0 -1
  334. package/assets/devtools-ui/chunk.B7QJXctB.js.br +0 -0
  335. package/assets/devtools-ui/chunk.B9pX3zit.js.br +0 -0
  336. package/assets/devtools-ui/chunk.BKF9JxIo.js +0 -1
  337. package/assets/devtools-ui/chunk.BKF9JxIo.js.br +0 -0
  338. package/assets/devtools-ui/chunk.BOHgdTP-.js +0 -1
  339. package/assets/devtools-ui/chunk.BOHgdTP-.js.br +0 -0
  340. package/assets/devtools-ui/chunk.BOVFxkYC.js +0 -1
  341. package/assets/devtools-ui/chunk.BOVFxkYC.js.br +0 -0
  342. package/assets/devtools-ui/chunk.BR842zj5.js +0 -1
  343. package/assets/devtools-ui/chunk.BR842zj5.js.br +0 -0
  344. package/assets/devtools-ui/chunk.BT2IiBkZ.js.br +0 -0
  345. package/assets/devtools-ui/chunk.C79YouPp.js.br +0 -0
  346. package/assets/devtools-ui/chunk.C8mlBrjW.js +0 -9
  347. package/assets/devtools-ui/chunk.C8mlBrjW.js.br +0 -0
  348. package/assets/devtools-ui/chunk.CK0ow3AZ.js +0 -1
  349. package/assets/devtools-ui/chunk.CK0ow3AZ.js.br +0 -0
  350. package/assets/devtools-ui/chunk.CZl6J9DF.js.br +0 -0
  351. package/assets/devtools-ui/chunk.CdNr0YzS.js +0 -1
  352. package/assets/devtools-ui/chunk.CdNr0YzS.js.br +0 -0
  353. package/assets/devtools-ui/chunk.Ce6_6iIF.js +0 -1
  354. package/assets/devtools-ui/chunk.Ce6_6iIF.js.br +0 -0
  355. package/assets/devtools-ui/chunk.CpyDMr6O.js +0 -1
  356. package/assets/devtools-ui/chunk.CpyDMr6O.js.br +0 -0
  357. package/assets/devtools-ui/chunk.CyPmvPnY.js +0 -1
  358. package/assets/devtools-ui/chunk.CyPmvPnY.js.br +0 -0
  359. package/assets/devtools-ui/chunk.DTI_geWu.js +0 -1
  360. package/assets/devtools-ui/chunk.DTI_geWu.js.br +0 -0
  361. package/assets/devtools-ui/chunk.DbEH1oOB.js.br +0 -0
  362. package/assets/devtools-ui/chunk.Ddeqj5gv.js +0 -1
  363. package/assets/devtools-ui/chunk.Ddeqj5gv.js.br +0 -0
  364. package/assets/devtools-ui/chunk.DpRnB4vJ.js +0 -1
  365. package/assets/devtools-ui/chunk.DpRnB4vJ.js.br +0 -0
  366. package/assets/devtools-ui/chunk.DxPGTlsg.js +0 -1
  367. package/assets/devtools-ui/chunk.DxPGTlsg.js.br +0 -0
  368. package/assets/devtools-ui/chunk.G7_MMBJS.js +0 -1
  369. package/assets/devtools-ui/chunk.G7_MMBJS.js.br +0 -0
  370. package/assets/devtools-ui/chunk.M6wyKO_3.js.br +0 -0
  371. package/assets/devtools-ui/chunk.OUxNGmQ6.js +0 -1
  372. package/assets/devtools-ui/chunk.OUxNGmQ6.js.br +0 -0
  373. package/assets/devtools-ui/chunk.T1kle-fF.js +0 -1
  374. package/assets/devtools-ui/chunk.T1kle-fF.js.br +0 -0
  375. package/assets/devtools-ui/chunk.WjpsbQAv.js +0 -1
  376. package/assets/devtools-ui/chunk.WjpsbQAv.js.br +0 -0
  377. package/assets/devtools-ui/chunk.c6YgVx86.js +0 -1
  378. package/assets/devtools-ui/chunk.c6YgVx86.js.br +0 -0
  379. package/assets/devtools-ui/chunk.dwU3E_MU.js +0 -1
  380. package/assets/devtools-ui/chunk.dwU3E_MU.js.br +0 -0
  381. package/assets/devtools-ui/chunk.lJL-lgnW.js.br +0 -0
  382. package/assets/devtools-ui/chunk.lPWRmvA-.js +0 -7
  383. package/assets/devtools-ui/chunk.lPWRmvA-.js.br +0 -0
  384. package/assets/devtools-ui/chunk.p3HJvugM.js +0 -1
  385. package/assets/devtools-ui/chunk.p3HJvugM.js.br +0 -0
  386. package/assets/devtools-ui/chunk.r_Xoa_CI.js +0 -1
  387. package/assets/devtools-ui/chunk.r_Xoa_CI.js.br +0 -0
  388. package/assets/devtools-ui/chunk.sRNuTYXb.js +0 -1
  389. package/assets/devtools-ui/chunk.sRNuTYXb.js.br +0 -0
  390. package/assets/devtools-ui/chunk.tUjcyX5C.js +0 -1
  391. package/assets/devtools-ui/chunk.tUjcyX5C.js.br +0 -0
  392. package/assets/devtools-ui/chunk.thjBxvCA.js +0 -1
  393. package/assets/devtools-ui/chunk.thjBxvCA.js.br +0 -0
  394. package/assets/devtools-ui/entry.GYhBVRpC.js +0 -78
  395. package/assets/devtools-ui/entry.GYhBVRpC.js.br +0 -0
  396. package/src/server/links/services/DefinitionsPool.spec.ts +0 -86
  397. package/src/server/links/services/DefinitionsPool.ts +0 -43
@@ -0,0 +1,298 @@
1
+ import { Alepha } from "alepha";
2
+ import { CliProvider } from "alepha/command";
3
+ import { FileSystemProvider, MemoryFileSystemProvider } from "alepha/system";
4
+ import { describe, test } from "vitest";
5
+ import { platformOptions } from "../atoms/platformOptions.ts";
6
+ import { MemorySecretStore } from "../providers/MemorySecretStore.ts";
7
+ import type { SecretStoreProvider } from "../providers/SecretStoreProvider.ts";
8
+ import { SecretsCommand } from "./SecretsCommand.ts";
9
+
10
+ class TestSecretsCommand extends SecretsCommand {
11
+ public readonly testList = this.list;
12
+ public readonly testDiff = this.diff;
13
+ public readonly testApply = this.apply;
14
+ public testStore: MemorySecretStore | null = null;
15
+
16
+ public override resolveStore(): SecretStoreProvider {
17
+ if (this.testStore) return this.testStore;
18
+ return super.resolveStore();
19
+ }
20
+ }
21
+
22
+ describe("SecretsCommand", () => {
23
+ const createTestEnv = (
24
+ config: Record<string, any> = {},
25
+ storeSecrets: Record<string, Record<string, string>> = {},
26
+ ) => {
27
+ const alepha = Alepha.create().with({
28
+ provide: FileSystemProvider,
29
+ use: MemoryFileSystemProvider,
30
+ });
31
+
32
+ const fs = alepha.inject(MemoryFileSystemProvider);
33
+ const store = new MemorySecretStore();
34
+ const cli = alepha.inject(CliProvider);
35
+ const cmd = alepha.inject(TestSecretsCommand);
36
+ cmd.testStore = store;
37
+
38
+ alepha.set(platformOptions, {
39
+ name: "my-app",
40
+ environments: { production: { adapter: "cloudflare" } },
41
+ ...config,
42
+ } as any);
43
+
44
+ // Seed package.json
45
+ fs.writeFile("/project/package.json", JSON.stringify({ name: "my-app" }));
46
+
47
+ // Seed store with pre-existing secrets
48
+ for (const [env, secrets] of Object.entries(storeSecrets)) {
49
+ const envMap = new Map<string, string>();
50
+ for (const [k, v] of Object.entries(secrets)) {
51
+ envMap.set(k, v);
52
+ }
53
+ store.secrets.set(env, envMap);
54
+ }
55
+
56
+ return { alepha, fs, store, cli, cmd };
57
+ };
58
+
59
+ // -----------------------------------------------------------------------
60
+ // apply
61
+ // -----------------------------------------------------------------------
62
+
63
+ describe("apply", () => {
64
+ test("filters and pushes secrets to store", async ({ expect }) => {
65
+ const { fs, store, cli, cmd } = createTestEnv();
66
+
67
+ await fs.writeFile(
68
+ "/project/.env.production",
69
+ "DATABASE_URL=postgres://localhost/db\nAPI_KEY=abc123\nNODE_ENV=production\nVITE_APP=hello\nEMPTY=",
70
+ );
71
+
72
+ await cli.run(cmd.testApply, {
73
+ root: "/project",
74
+ argv: "--env production",
75
+ });
76
+
77
+ expect(store.wasSet("my-app-production", "DATABASE_URL")).toBe(true);
78
+ expect(store.wasSet("my-app-production", "API_KEY")).toBe(true);
79
+ expect(store.wasSet("my-app-production", "NODE_ENV")).toBe(false);
80
+ expect(store.wasSet("my-app-production", "VITE_APP")).toBe(false);
81
+ expect(store.wasSet("my-app-production", "EMPTY")).toBe(false);
82
+ });
83
+
84
+ test("renames GITHUB_ keys with APP_ prefix", async ({ expect }) => {
85
+ const { fs, store, cli, cmd } = createTestEnv();
86
+
87
+ await fs.writeFile(
88
+ "/project/.env.production",
89
+ "GITHUB_CLIENT_ID=id123\nGITHUB_CLIENT_SECRET=secret456",
90
+ );
91
+
92
+ await cli.run(cmd.testApply, {
93
+ root: "/project",
94
+ argv: "--env production",
95
+ });
96
+
97
+ expect(store.wasSet("my-app-production", "APP_GITHUB_CLIENT_ID")).toBe(
98
+ true,
99
+ );
100
+ expect(
101
+ store.wasSet("my-app-production", "APP_GITHUB_CLIENT_SECRET"),
102
+ ).toBe(true);
103
+ expect(store.wasSet("my-app-production", "GITHUB_CLIENT_ID")).toBe(false);
104
+ });
105
+
106
+ test("dry run does not call store", async ({ expect }) => {
107
+ const { fs, store, cli, cmd } = createTestEnv();
108
+
109
+ await fs.writeFile(
110
+ "/project/.env.production",
111
+ "API_KEY=abc123\nSECRET=xyz",
112
+ );
113
+
114
+ await cli.run(cmd.testApply, {
115
+ root: "/project",
116
+ argv: "--env production --dry-run",
117
+ });
118
+
119
+ expect(store.calls.filter((c) => c.method === "set")).toHaveLength(0);
120
+ });
121
+
122
+ test("uses custom environment pattern", async ({ expect }) => {
123
+ const { fs, store, cli, cmd } = createTestEnv({
124
+ secrets: {
125
+ store: "github",
126
+ environmentPattern: "{env}",
127
+ },
128
+ });
129
+
130
+ await fs.writeFile("/project/.env.production", "API_KEY=abc123");
131
+
132
+ await cli.run(cmd.testApply, {
133
+ root: "/project",
134
+ argv: "--env production",
135
+ });
136
+
137
+ expect(store.wasSet("production", "API_KEY")).toBe(true);
138
+ });
139
+ });
140
+
141
+ // -----------------------------------------------------------------------
142
+ // diff
143
+ // -----------------------------------------------------------------------
144
+
145
+ describe("diff", () => {
146
+ test("detects only-local, only-remote, and in-both keys", async ({
147
+ expect,
148
+ }) => {
149
+ const { fs, cli, cmd } = createTestEnv(
150
+ {},
151
+ {
152
+ "my-app-production": {
153
+ API_KEY: "remote-value",
154
+ OLD_SECRET: "stale",
155
+ },
156
+ },
157
+ );
158
+
159
+ await fs.writeFile(
160
+ "/project/.env.production",
161
+ "API_KEY=local-value\nNEW_SECRET=fresh",
162
+ );
163
+
164
+ // Capture stdout
165
+ const writes: string[] = [];
166
+ const originalWrite = process.stdout.write;
167
+ process.stdout.write = ((chunk: string) => {
168
+ writes.push(chunk);
169
+ return true;
170
+ }) as any;
171
+
172
+ try {
173
+ await cli.run(cmd.testDiff, {
174
+ root: "/project",
175
+ argv: "--env production",
176
+ });
177
+ } finally {
178
+ process.stdout.write = originalWrite;
179
+ }
180
+
181
+ // biome-ignore lint/suspicious/noControlCharactersInRegex: stripping ANSI codes
182
+ const output = writes.join("").replace(/\x1B\[[0-9;]*m/g, "");
183
+ expect(output).toContain("+ NEW_SECRET");
184
+ expect(output).toContain("- OLD_SECRET");
185
+ expect(output).toContain("= API_KEY");
186
+ });
187
+ });
188
+
189
+ // -----------------------------------------------------------------------
190
+ // list
191
+ // -----------------------------------------------------------------------
192
+
193
+ describe("list", () => {
194
+ test("shows table format by default", async ({ expect }) => {
195
+ const { cli, cmd } = createTestEnv(
196
+ {},
197
+ {
198
+ "my-app-production": {
199
+ API_KEY: "value1",
200
+ DATABASE_URL: "value2",
201
+ },
202
+ },
203
+ );
204
+
205
+ const writes: string[] = [];
206
+ const originalWrite = process.stdout.write;
207
+ process.stdout.write = ((chunk: string) => {
208
+ writes.push(chunk);
209
+ return true;
210
+ }) as any;
211
+
212
+ try {
213
+ await cli.run(cmd.testList, {
214
+ root: "/project",
215
+ argv: "--env production",
216
+ });
217
+ } finally {
218
+ process.stdout.write = originalWrite;
219
+ }
220
+
221
+ const output = writes.join("");
222
+ expect(output).toContain("API_KEY");
223
+ expect(output).toContain("DATABASE_URL");
224
+ });
225
+
226
+ test("shows GHA format", async ({ expect }) => {
227
+ const { cli, cmd } = createTestEnv(
228
+ {},
229
+ {
230
+ "my-app-production": {
231
+ API_KEY: "value1",
232
+ APP_GITHUB_CLIENT_ID: "value2",
233
+ },
234
+ },
235
+ );
236
+
237
+ const writes: string[] = [];
238
+ const originalWrite = process.stdout.write;
239
+ process.stdout.write = ((chunk: string) => {
240
+ writes.push(chunk);
241
+ return true;
242
+ }) as any;
243
+
244
+ try {
245
+ await cli.run(cmd.testList, {
246
+ root: "/project",
247
+ argv: "--env production --format gha",
248
+ });
249
+ } finally {
250
+ process.stdout.write = originalWrite;
251
+ }
252
+
253
+ const output = writes.join("");
254
+ expect(output).toContain("env:");
255
+ expect(output).toContain("API_KEY: ${{ secrets.API_KEY }}");
256
+ expect(output).toContain(
257
+ "GITHUB_CLIENT_ID: ${{ secrets.APP_GITHUB_CLIENT_ID }}",
258
+ );
259
+ });
260
+ });
261
+
262
+ // -----------------------------------------------------------------------
263
+ // environment name resolution
264
+ // -----------------------------------------------------------------------
265
+
266
+ describe("environment name resolution", () => {
267
+ test("uses default pattern {project}-{env}", async ({ expect }) => {
268
+ const { fs, store, cli, cmd } = createTestEnv();
269
+
270
+ await fs.writeFile("/project/.env.production", "KEY=val");
271
+
272
+ await cli.run(cmd.testApply, {
273
+ root: "/project",
274
+ argv: "--env production",
275
+ });
276
+
277
+ expect(store.wasSet("my-app-production", "KEY")).toBe(true);
278
+ });
279
+
280
+ test("uses custom pattern", async ({ expect }) => {
281
+ const { fs, store, cli, cmd } = createTestEnv({
282
+ secrets: {
283
+ store: "github",
284
+ environmentPattern: "deploy-{project}-{env}",
285
+ },
286
+ });
287
+
288
+ await fs.writeFile("/project/.env.production", "KEY=val");
289
+
290
+ await cli.run(cmd.testApply, {
291
+ root: "/project",
292
+ argv: "--env production",
293
+ });
294
+
295
+ expect(store.wasSet("deploy-my-app-production", "KEY")).toBe(true);
296
+ });
297
+ });
298
+ });
@@ -0,0 +1,283 @@
1
+ import { $inject, $use, AlephaError, t } from "alepha";
2
+ import { $command, EnvUtils } from "alepha/command";
3
+ import { $logger, ConsoleColorProvider } from "alepha/logger";
4
+ import { platformOptions } from "../atoms/platformOptions.ts";
5
+ import { GitHubSecretStore } from "../providers/GitHubSecretStore.ts";
6
+ import type { SecretStoreProvider } from "../providers/SecretStoreProvider.ts";
7
+ import { NamingService } from "../services/NamingService.ts";
8
+ import { PlatformInspector } from "../services/PlatformInspector.ts";
9
+ import { SecretFilterService } from "../services/SecretFilterService.ts";
10
+
11
+ export class SecretsCommand {
12
+ protected readonly log = $logger();
13
+ protected readonly options = $use(platformOptions);
14
+ protected readonly inspector = $inject(PlatformInspector);
15
+ protected readonly naming = $inject(NamingService);
16
+ protected readonly envUtils = $inject(EnvUtils);
17
+ protected readonly githubStore = $inject(GitHubSecretStore);
18
+ protected readonly filter = $inject(SecretFilterService);
19
+ protected readonly color = $inject(ConsoleColorProvider);
20
+
21
+ protected readonly envFlags = t.object({
22
+ env: t.optional(
23
+ t.text({
24
+ aliases: ["e"],
25
+ description: "Target environment",
26
+ }),
27
+ ),
28
+ });
29
+
30
+ // -----------------------------------------------------------------------
31
+ // alepha p secrets list
32
+ // -----------------------------------------------------------------------
33
+
34
+ protected readonly list = $command({
35
+ name: "list",
36
+ aliases: ["ls"],
37
+ description: "List secrets in the remote store",
38
+ flags: t.object({
39
+ env: t.optional(
40
+ t.text({
41
+ aliases: ["e"],
42
+ description: "Target environment",
43
+ }),
44
+ ),
45
+ format: t.optional(
46
+ t.text({
47
+ aliases: ["f"],
48
+ description: "Output format: table (default), gha",
49
+ }),
50
+ ),
51
+ }),
52
+ handler: async ({ flags, root, run }) => {
53
+ const config = await this.inspector.resolveConfig(root);
54
+ const env = flags.env ?? config.defaultEnv;
55
+ const envName = this.resolveEnvironmentName(config.project, env);
56
+ const format = flags.format ?? "table";
57
+
58
+ const store = this.resolveStore();
59
+ await store.ensureAvailable();
60
+ const remoteSecrets = await store.list(envName);
61
+
62
+ run.end();
63
+
64
+ if (format === "gha") {
65
+ process.stdout.write(
66
+ `# Generated by alepha — environment: ${envName}\n`,
67
+ );
68
+ process.stdout.write("env:\n");
69
+ for (const secret of remoteSecrets) {
70
+ const localName = this.filter.toLocalName(secret.name);
71
+ process.stdout.write(
72
+ ` ${localName}: \${{ secrets.${secret.name} }}\n`,
73
+ );
74
+ }
75
+ return;
76
+ }
77
+
78
+ // table format
79
+ const c = this.color;
80
+
81
+ if (remoteSecrets.length === 0) {
82
+ process.stdout.write(
83
+ `\nNo secrets in environment ${c.set("CYAN", envName)}.\n\n`,
84
+ );
85
+ return;
86
+ }
87
+
88
+ process.stdout.write(
89
+ `\n${c.set("GREY_LIGHT", "Environment:")} ${c.set("CYAN", envName)}\n\n`,
90
+ );
91
+
92
+ const maxNameLen = Math.max(
93
+ ...remoteSecrets.map((s) => s.name.length),
94
+ 4,
95
+ );
96
+
97
+ process.stdout.write(
98
+ ` ${c.set("GREY_LIGHT", "NAME".padEnd(maxNameLen + 2))}${c.set("GREY_LIGHT", "UPDATED")}\n`,
99
+ );
100
+
101
+ for (const secret of remoteSecrets) {
102
+ const updated = secret.updatedAt
103
+ ? new Date(secret.updatedAt).toLocaleString()
104
+ : "-";
105
+ process.stdout.write(
106
+ ` ${c.set("CYAN", secret.name.padEnd(maxNameLen + 2))}${c.set("GREY_DARK", updated)}\n`,
107
+ );
108
+ }
109
+
110
+ process.stdout.write("\n");
111
+ },
112
+ });
113
+
114
+ // -----------------------------------------------------------------------
115
+ // alepha p secrets diff
116
+ // -----------------------------------------------------------------------
117
+
118
+ protected readonly diff = $command({
119
+ name: "diff",
120
+ description: "Compare local .env keys with remote store",
121
+ flags: this.envFlags,
122
+ handler: async ({ flags, root, run }) => {
123
+ const config = await this.inspector.resolveConfig(root);
124
+ const env = flags.env ?? config.defaultEnv;
125
+ const envName = this.resolveEnvironmentName(config.project, env);
126
+
127
+ const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);
128
+ const filtered = this.filter.filter(envVars);
129
+ const localKeys = new Set(
130
+ Object.keys(filtered).map((k) => this.filter.toRemoteName(k)),
131
+ );
132
+
133
+ const store = this.resolveStore();
134
+ await store.ensureAvailable();
135
+ const remoteSecrets = await store.list(envName);
136
+ const remoteKeys = new Set(remoteSecrets.map((s) => s.name));
137
+
138
+ run.end();
139
+
140
+ const c = this.color;
141
+ const allKeys = [...new Set([...localKeys, ...remoteKeys])].sort();
142
+
143
+ process.stdout.write(
144
+ `\n${c.set("GREY_LIGHT", "Environment:")} ${c.set("CYAN", envName)}\n\n`,
145
+ );
146
+
147
+ let hasChanges = false;
148
+ for (const key of allKeys) {
149
+ const inLocal = localKeys.has(key);
150
+ const inRemote = remoteKeys.has(key);
151
+
152
+ if (inLocal && !inRemote) {
153
+ process.stdout.write(` ${c.set("GREEN", "+")} ${key}\n`);
154
+ hasChanges = true;
155
+ } else if (!inLocal && inRemote) {
156
+ process.stdout.write(` ${c.set("RED", "-")} ${key}\n`);
157
+ hasChanges = true;
158
+ } else {
159
+ process.stdout.write(` ${c.set("GREY_DARK", "=")} ${key}\n`);
160
+ }
161
+ }
162
+
163
+ if (!hasChanges) {
164
+ process.stdout.write(
165
+ ` ${c.set("GREEN", "Local and remote are in sync.")}\n`,
166
+ );
167
+ }
168
+
169
+ process.stdout.write("\n");
170
+ },
171
+ });
172
+
173
+ // -----------------------------------------------------------------------
174
+ // alepha p secrets apply
175
+ // -----------------------------------------------------------------------
176
+
177
+ protected readonly apply = $command({
178
+ name: "apply",
179
+ description: "Push local .env secrets to the remote store",
180
+ flags: t.object({
181
+ env: t.optional(
182
+ t.text({
183
+ aliases: ["e"],
184
+ description: "Target environment",
185
+ }),
186
+ ),
187
+ "dry-run": t.optional(
188
+ t.boolean({
189
+ description: "Preview changes without pushing",
190
+ }),
191
+ ),
192
+ }),
193
+ handler: async ({ flags, root, run }) => {
194
+ const config = await this.inspector.resolveConfig(root);
195
+ const env = flags.env ?? config.defaultEnv;
196
+ const envName = this.resolveEnvironmentName(config.project, env);
197
+ const dryRun = flags["dry-run"] ?? false;
198
+
199
+ const envVars = await this.envUtils.parseEnv(root, [`.env.${env}`]);
200
+ const filtered = this.filter.filter(envVars);
201
+ const keys = Object.keys(filtered);
202
+
203
+ if (keys.length === 0) {
204
+ run.end();
205
+ process.stdout.write("\nNo secrets to push.\n\n");
206
+ return;
207
+ }
208
+
209
+ if (dryRun) {
210
+ run.end();
211
+ const c = this.color;
212
+ process.stdout.write(
213
+ `\n${c.set("GREY_LIGHT", "Dry run — environment:")} ${c.set("CYAN", envName)}\n\n`,
214
+ );
215
+ for (const key of keys) {
216
+ process.stdout.write(` ${c.set("GREEN", "+")} ${key}\n`);
217
+ }
218
+ process.stdout.write(
219
+ `\n ${keys.length} secret(s) would be pushed.\n\n`,
220
+ );
221
+ return;
222
+ }
223
+
224
+ const store = this.resolveStore();
225
+ await store.ensureAvailable();
226
+ await store.ensureEnvironment(envName);
227
+
228
+ for (const key of keys) {
229
+ const remoteName = this.filter.toRemoteName(key);
230
+ await run({
231
+ name: `push ${remoteName}`,
232
+ handler: async () => {
233
+ await store.set(envName, remoteName, filtered[key]);
234
+ },
235
+ });
236
+ }
237
+
238
+ run.end();
239
+ process.stdout.write(
240
+ `\n${keys.length} secret(s) pushed to ${envName}.\n`,
241
+ );
242
+ },
243
+ });
244
+
245
+ // -----------------------------------------------------------------------
246
+ // Parent command
247
+ // -----------------------------------------------------------------------
248
+
249
+ public readonly secrets = $command({
250
+ name: "secrets",
251
+ aliases: ["sec"],
252
+ description: "Manage secrets in external stores",
253
+ children: [this.list, this.diff, this.apply],
254
+ handler: async ({ help }) => {
255
+ help();
256
+ },
257
+ });
258
+
259
+ // -----------------------------------------------------------------------
260
+ // Helpers
261
+ // -----------------------------------------------------------------------
262
+
263
+ public resolveStore(): SecretStoreProvider {
264
+ const storeName = this.options?.secrets?.store ?? "github";
265
+ switch (storeName) {
266
+ case "github":
267
+ return this.githubStore;
268
+ default:
269
+ throw new AlephaError(
270
+ `Unknown secret store "${storeName}". Available: github`,
271
+ );
272
+ }
273
+ }
274
+
275
+ protected resolveEnvironmentName(project: string, env: string): string {
276
+ const pattern =
277
+ this.options?.secrets?.environmentPattern ?? "{project}-{env}";
278
+
279
+ return pattern
280
+ .replace("{project}", this.naming.slugify(project))
281
+ .replace("{env}", this.naming.slugify(env));
282
+ }
283
+ }
@@ -19,6 +19,7 @@ import {
19
19
  type ResolvedPlatformConfig,
20
20
  } from "../services/PlatformInspector.ts";
21
21
  import { PlatformOrchestrator } from "../services/PlatformOrchestrator.ts";
22
+ import { SecretsCommand } from "./SecretsCommand.ts";
22
23
 
23
24
  export class PlatformCommand {
24
25
  protected readonly log = $logger();
@@ -30,6 +31,7 @@ export class PlatformCommand {
30
31
  protected readonly viteBuild = $inject(ViteBuildProvider);
31
32
  protected readonly color = $inject(ConsoleColorProvider);
32
33
  protected readonly envUtils = $inject(EnvUtils);
34
+ protected readonly secretsCommand = $inject(SecretsCommand);
33
35
 
34
36
  /**
35
37
  * Common flags for env/app targeting.
@@ -134,6 +136,15 @@ export class PlatformCommand {
134
136
  }
135
137
  }
136
138
 
139
+ if (adapterName === "docker" || adapterName === "docker-compose") {
140
+ if (hasDB && !envVars.DATABASE_URL) {
141
+ resources.push({ label: "Postgres", value: "postgres:17-alpine" });
142
+ }
143
+ if (hasBucket && !envVars.S3_ENDPOINT) {
144
+ resources.push({ label: "RustFS", value: "rustfs/rustfs:latest" });
145
+ }
146
+ }
147
+
137
148
  const excludedKeys =
138
149
  adapterName === "vercel"
139
150
  ? VercelAdapter.EXCLUDED_SECRET_KEYS
@@ -609,6 +620,7 @@ export class PlatformCommand {
609
620
  this.build,
610
621
  this.deploy,
611
622
  this.migrate,
623
+ this.secretsCommand.secrets,
612
624
  ],
613
625
  handler: async ({ help, root }) => {
614
626
  await this.inspector.resolveConfig(root);