alepha 0.19.1 → 0.19.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 (531) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +6 -9
  3. package/dist/api/audits/index.d.ts +378 -346
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/files/index.d.ts +216 -184
  6. package/dist/api/files/index.d.ts.map +1 -1
  7. package/dist/api/jobs/index.d.ts +534 -502
  8. package/dist/api/jobs/index.d.ts.map +1 -1
  9. package/dist/api/jobs/index.js +13 -7
  10. package/dist/api/jobs/index.js.map +1 -1
  11. package/dist/api/keys/index.d.ts +202 -202
  12. package/dist/api/keys/index.d.ts.map +1 -1
  13. package/dist/api/notifications/index.d.ts +152 -152
  14. package/dist/api/notifications/index.d.ts.map +1 -1
  15. package/dist/api/organizations/index.browser.js +48 -0
  16. package/dist/api/organizations/index.browser.js.map +1 -0
  17. package/dist/api/organizations/index.d.ts +516 -0
  18. package/dist/api/organizations/index.d.ts.map +1 -0
  19. package/dist/api/organizations/index.js +202 -0
  20. package/dist/api/organizations/index.js.map +1 -0
  21. package/dist/api/parameters/index.d.ts +391 -358
  22. package/dist/api/parameters/index.d.ts.map +1 -1
  23. package/dist/api/parameters/index.js +5 -1
  24. package/dist/api/parameters/index.js.map +1 -1
  25. package/dist/api/users/index.browser.js +7 -5
  26. package/dist/api/users/index.browser.js.map +1 -1
  27. package/dist/api/users/index.d.ts +986 -931
  28. package/dist/api/users/index.d.ts.map +1 -1
  29. package/dist/api/users/index.js +160 -112
  30. package/dist/api/users/index.js.map +1 -1
  31. package/dist/api/verifications/index.d.ts +137 -137
  32. package/dist/api/verifications/index.d.ts.map +1 -1
  33. package/dist/api/verifications/index.js +2 -2
  34. package/dist/api/verifications/index.js.map +1 -1
  35. package/dist/batch/index.d.ts +6 -6
  36. package/dist/batch/index.d.ts.map +1 -1
  37. package/dist/billing/index.d.ts +1048 -0
  38. package/dist/billing/index.d.ts.map +1 -0
  39. package/dist/billing/index.js +713 -0
  40. package/dist/billing/index.js.map +1 -0
  41. package/dist/bin/index.js +0 -2
  42. package/dist/bin/index.js.map +1 -1
  43. package/dist/bucket/index.d.ts +10 -10
  44. package/dist/bucket/index.d.ts.map +1 -1
  45. package/dist/bucket/index.js +2 -2
  46. package/dist/bucket/index.js.map +1 -1
  47. package/dist/cache/core/index.d.ts +9 -9
  48. package/dist/cache/core/index.d.ts.map +1 -1
  49. package/dist/cache/core/index.js +2 -2
  50. package/dist/cache/core/index.js.map +1 -1
  51. package/dist/cache/core/index.workerd.js +2 -2
  52. package/dist/cache/core/index.workerd.js.map +1 -1
  53. package/dist/cache/redis/index.d.ts +6 -6
  54. package/dist/cache/redis/index.d.ts.map +1 -1
  55. package/dist/cache/redis/index.js +2 -2
  56. package/dist/cache/redis/index.js.map +1 -1
  57. package/dist/cli/config/index.d.ts +6 -18
  58. package/dist/cli/config/index.d.ts.map +1 -1
  59. package/dist/cli/config/index.js +5 -6
  60. package/dist/cli/config/index.js.map +1 -1
  61. package/dist/cli/core/index.d.ts +11811 -323
  62. package/dist/cli/core/index.d.ts.map +1 -1
  63. package/dist/cli/core/index.js +324 -98
  64. package/dist/cli/core/index.js.map +1 -1
  65. package/dist/cli/devtools/index.d.ts +50 -0
  66. package/dist/cli/devtools/index.d.ts.map +1 -0
  67. package/dist/cli/devtools/index.js +174 -0
  68. package/dist/cli/devtools/index.js.map +1 -0
  69. package/dist/cli/platform/index.d.ts +438 -542
  70. package/dist/cli/platform/index.d.ts.map +1 -1
  71. package/dist/cli/platform/index.js +46 -511
  72. package/dist/cli/platform/index.js.map +1 -1
  73. package/dist/cli/vendor/index.d.ts +201 -0
  74. package/dist/cli/vendor/index.d.ts.map +1 -0
  75. package/dist/cli/vendor/index.js +388 -0
  76. package/dist/cli/vendor/index.js.map +1 -0
  77. package/dist/command/index.d.ts +18 -18
  78. package/dist/command/index.d.ts.map +1 -1
  79. package/dist/command/index.js +2 -2
  80. package/dist/command/index.js.map +1 -1
  81. package/dist/core/index.browser.js +4 -4
  82. package/dist/core/index.browser.js.map +1 -1
  83. package/dist/core/index.d.ts +10 -10
  84. package/dist/core/index.d.ts.map +1 -1
  85. package/dist/core/index.js +8 -4
  86. package/dist/core/index.js.map +1 -1
  87. package/dist/core/index.native.js +8 -4
  88. package/dist/core/index.native.js.map +1 -1
  89. package/dist/core/index.workerd.js +8 -4
  90. package/dist/core/index.workerd.js.map +1 -1
  91. package/dist/crypto/index.d.ts +7 -7
  92. package/dist/crypto/index.d.ts.map +1 -1
  93. package/dist/datetime/index.d.ts +4 -4
  94. package/dist/datetime/index.d.ts.map +1 -1
  95. package/dist/email/brevo/index.d.ts +4 -4
  96. package/dist/email/brevo/index.d.ts.map +1 -1
  97. package/dist/email/core/index.d.ts +15 -11
  98. package/dist/email/core/index.d.ts.map +1 -1
  99. package/dist/email/core/index.js +12 -35
  100. package/dist/email/core/index.js.map +1 -1
  101. package/dist/email/smtp/index.d.ts +12 -12
  102. package/dist/email/smtp/index.d.ts.map +1 -1
  103. package/dist/email/smtp/index.js +7 -4
  104. package/dist/email/smtp/index.js.map +1 -1
  105. package/dist/fake/index.d.ts +4 -8
  106. package/dist/fake/index.d.ts.map +1 -1
  107. package/dist/fake/index.js +55 -889
  108. package/dist/fake/index.js.map +1 -1
  109. package/dist/lock/core/index.d.ts +13 -13
  110. package/dist/lock/core/index.d.ts.map +1 -1
  111. package/dist/lock/core/index.js +2 -2
  112. package/dist/lock/core/index.js.map +1 -1
  113. package/dist/lock/redis/index.d.ts +4 -4
  114. package/dist/lock/redis/index.d.ts.map +1 -1
  115. package/dist/logger/index.d.ts +16 -15
  116. package/dist/logger/index.d.ts.map +1 -1
  117. package/dist/logger/index.js +6 -3
  118. package/dist/logger/index.js.map +1 -1
  119. package/dist/mcp/index.d.ts +11 -11
  120. package/dist/mcp/index.d.ts.map +1 -1
  121. package/dist/mcp/index.js +2 -2
  122. package/dist/mcp/index.js.map +1 -1
  123. package/dist/orm/core/index.browser.js +11 -1
  124. package/dist/orm/core/index.browser.js.map +1 -1
  125. package/dist/orm/core/index.bun.js +78 -72
  126. package/dist/orm/core/index.bun.js.map +1 -1
  127. package/dist/orm/core/index.d.ts +103 -69
  128. package/dist/orm/core/index.d.ts.map +1 -1
  129. package/dist/orm/core/index.js +80 -70
  130. package/dist/orm/core/index.js.map +1 -1
  131. package/dist/orm/postgres/index.d.ts +19 -17
  132. package/dist/orm/postgres/index.d.ts.map +1 -1
  133. package/dist/queue/core/index.d.ts +14 -14
  134. package/dist/queue/core/index.d.ts.map +1 -1
  135. package/dist/queue/core/index.js +2 -2
  136. package/dist/queue/core/index.js.map +1 -1
  137. package/dist/queue/core/index.workerd.js +2 -2
  138. package/dist/queue/core/index.workerd.js.map +1 -1
  139. package/dist/queue/redis/index.d.ts +4 -4
  140. package/dist/queue/redis/index.d.ts.map +1 -1
  141. package/dist/queue/redis/index.js +2 -2
  142. package/dist/queue/redis/index.js.map +1 -1
  143. package/dist/react/auth/index.d.ts +9 -9
  144. package/dist/react/auth/index.d.ts.map +1 -1
  145. package/dist/react/core/index.d.ts +6 -6
  146. package/dist/react/core/index.d.ts.map +1 -1
  147. package/dist/react/core/index.js +5 -4
  148. package/dist/react/core/index.js.map +1 -1
  149. package/dist/react/form/index.d.ts +4 -4
  150. package/dist/react/form/index.d.ts.map +1 -1
  151. package/dist/react/head/index.d.ts +4 -4
  152. package/dist/react/head/index.d.ts.map +1 -1
  153. package/dist/react/i18n/index.d.ts +9 -9
  154. package/dist/react/i18n/index.d.ts.map +1 -1
  155. package/dist/react/intro/index.d.ts +2 -2
  156. package/dist/react/intro/index.d.ts.map +1 -1
  157. package/dist/react/intro/index.js +1 -1
  158. package/dist/react/intro/index.js.map +1 -1
  159. package/dist/react/router/index.browser.js +4 -5
  160. package/dist/react/router/index.browser.js.map +1 -1
  161. package/dist/react/router/index.d.ts +215 -215
  162. package/dist/react/router/index.d.ts.map +1 -1
  163. package/dist/react/router/index.js +6 -7
  164. package/dist/react/router/index.js.map +1 -1
  165. package/dist/react/testing/index.d.ts +2 -2
  166. package/dist/react/testing/index.d.ts.map +1 -1
  167. package/dist/react/testing/index.js +2 -4
  168. package/dist/react/testing/index.js.map +1 -1
  169. package/dist/redis/index.d.ts +19 -19
  170. package/dist/redis/index.d.ts.map +1 -1
  171. package/dist/retry/index.d.ts +4 -4
  172. package/dist/retry/index.d.ts.map +1 -1
  173. package/dist/scheduler/index.d.ts +13 -13
  174. package/dist/scheduler/index.d.ts.map +1 -1
  175. package/dist/scheduler/index.js +2 -2
  176. package/dist/scheduler/index.js.map +1 -1
  177. package/dist/scheduler/index.workerd.js +2 -2
  178. package/dist/scheduler/index.workerd.js.map +1 -1
  179. package/dist/security/index.browser.js +1 -1
  180. package/dist/security/index.browser.js.map +1 -1
  181. package/dist/security/index.d.ts +47 -47
  182. package/dist/security/index.d.ts.map +1 -1
  183. package/dist/security/index.js +9 -12
  184. package/dist/security/index.js.map +1 -1
  185. package/dist/server/auth/index.d.ts +170 -169
  186. package/dist/server/auth/index.d.ts.map +1 -1
  187. package/dist/server/auth/index.js +16 -2
  188. package/dist/server/auth/index.js.map +1 -1
  189. package/dist/server/cookies/index.d.ts +7 -7
  190. package/dist/server/cookies/index.d.ts.map +1 -1
  191. package/dist/server/core/index.d.ts +76 -76
  192. package/dist/server/core/index.d.ts.map +1 -1
  193. package/dist/server/core/index.js +23 -17
  194. package/dist/server/core/index.js.map +1 -1
  195. package/dist/server/cors/index.d.ts +13 -13
  196. package/dist/server/cors/index.d.ts.map +1 -1
  197. package/dist/server/cors/index.js +2 -2
  198. package/dist/server/cors/index.js.map +1 -1
  199. package/dist/server/etag/index.d.ts +9 -9
  200. package/dist/server/etag/index.d.ts.map +1 -1
  201. package/dist/server/health/index.d.ts +20 -20
  202. package/dist/server/health/index.d.ts.map +1 -1
  203. package/dist/server/links/index.browser.js +2 -2
  204. package/dist/server/links/index.browser.js.map +1 -1
  205. package/dist/server/links/index.d.ts +66 -66
  206. package/dist/server/links/index.d.ts.map +1 -1
  207. package/dist/server/links/index.js +4 -4
  208. package/dist/server/links/index.js.map +1 -1
  209. package/dist/server/metrics/index.d.ts +7 -7
  210. package/dist/server/metrics/index.d.ts.map +1 -1
  211. package/dist/server/proxy/index.d.ts +5 -5
  212. package/dist/server/proxy/index.d.ts.map +1 -1
  213. package/dist/server/rate-limit/index.d.ts +12 -12
  214. package/dist/server/rate-limit/index.d.ts.map +1 -1
  215. package/dist/server/rate-limit/index.js +2 -2
  216. package/dist/server/rate-limit/index.js.map +1 -1
  217. package/dist/server/static/index.d.ts +5 -5
  218. package/dist/server/static/index.d.ts.map +1 -1
  219. package/dist/server/swagger/index.d.ts +7 -7
  220. package/dist/server/swagger/index.d.ts.map +1 -1
  221. package/dist/server/swagger/index.js +2 -2
  222. package/dist/server/swagger/index.js.map +1 -1
  223. package/dist/sms/index.d.ts +11 -7
  224. package/dist/sms/index.d.ts.map +1 -1
  225. package/dist/sms/index.js +9 -15
  226. package/dist/sms/index.js.map +1 -1
  227. package/dist/system/index.d.ts +4 -4
  228. package/dist/system/index.d.ts.map +1 -1
  229. package/dist/topic/core/index.d.ts +6 -6
  230. package/dist/topic/core/index.d.ts.map +1 -1
  231. package/dist/topic/redis/index.d.ts +7 -7
  232. package/dist/topic/redis/index.d.ts.map +1 -1
  233. package/dist/topic/redis/index.js +2 -2
  234. package/dist/topic/redis/index.js.map +1 -1
  235. package/dist/websocket/index.d.ts +36 -36
  236. package/dist/websocket/index.d.ts.map +1 -1
  237. package/dist/websocket/index.js +2 -2
  238. package/dist/websocket/index.js.map +1 -1
  239. package/package.json +37 -15
  240. package/src/api/jobs/{services → __tests__}/JobService.spec.ts +1 -1
  241. package/src/api/jobs/providers/JobProvider.ts +13 -9
  242. package/src/api/keys/{services → __tests__}/ApiKeyService.spec.ts +1 -1
  243. package/src/api/organizations/__tests__/OrganizationService.spec.ts +193 -0
  244. package/src/api/organizations/controllers/AdminOrganizationController.ts +103 -0
  245. package/src/api/organizations/entities/organizations.ts +20 -0
  246. package/src/api/organizations/index.browser.ts +10 -0
  247. package/src/api/organizations/index.ts +31 -0
  248. package/src/api/organizations/schemas/createOrganizationSchema.ts +10 -0
  249. package/src/api/organizations/schemas/organizationQuerySchema.ts +10 -0
  250. package/src/api/organizations/schemas/organizationResourceSchema.ts +6 -0
  251. package/src/api/organizations/schemas/updateOrganizationSchema.ts +7 -0
  252. package/src/api/organizations/services/OrganizationService.ts +75 -0
  253. package/src/api/parameters/services/ParameterProvider.ts +6 -1
  254. package/src/api/users/{services → __tests__}/SessionService.spec.ts +67 -0
  255. package/src/api/users/{jobs → __tests__}/UserJobs.spec.ts +1 -1
  256. package/src/api/users/entities/users.ts +9 -3
  257. package/src/api/users/index.ts +23 -4
  258. package/src/api/users/primitives/$realm.ts +6 -4
  259. package/src/api/users/providers/RealmProvider.ts +1 -1
  260. package/src/api/users/services/RegistrationService.ts +1 -1
  261. package/src/api/users/services/SessionService.ts +92 -5
  262. package/src/api/users/services/UserService.ts +1 -1
  263. package/src/api/verifications/{jobs → __tests__}/VerificationJobs.spec.ts +4 -2
  264. package/src/api/verifications/parameters/VerificationParameters.ts +2 -2
  265. package/src/billing/__tests__/BillingService.spec.ts +136 -0
  266. package/src/billing/__tests__/PaymentMethodService.spec.ts +78 -0
  267. package/src/billing/controllers/AdminBillingController.ts +149 -0
  268. package/src/billing/controllers/BillingController.ts +108 -0
  269. package/src/billing/entities/paymentIntents.ts +34 -0
  270. package/src/billing/entities/paymentMethods.ts +24 -0
  271. package/src/billing/entities/refunds.ts +22 -0
  272. package/src/billing/errors/BillingError.ts +5 -0
  273. package/src/billing/index.ts +76 -0
  274. package/src/billing/providers/BillingProvider.ts +79 -0
  275. package/src/billing/providers/MemoryBillingProvider.ts +139 -0
  276. package/src/billing/schemas/intentSchemas.ts +60 -0
  277. package/src/billing/schemas/paymentMethodSchemas.ts +13 -0
  278. package/src/billing/schemas/refundSchemas.ts +6 -0
  279. package/src/billing/services/BillingService.ts +325 -0
  280. package/src/billing/services/PaymentMethodService.ts +82 -0
  281. package/src/bin/index.ts +0 -2
  282. package/src/bucket/providers/LocalFileStorageProvider.ts +2 -2
  283. package/src/cache/core/{primitives → __tests__}/$cache.middleware.spec.ts +1 -1
  284. package/src/cache/core/{providers → __tests__}/MemoryCacheProvider.spec.ts +1 -1
  285. package/src/cache/core/primitives/$cache.ts +2 -2
  286. package/src/cache/redis/providers/RedisCacheProvider.ts +2 -2
  287. package/src/cli/config/defineConfig.ts +17 -26
  288. package/src/cli/core/{services → __tests__}/ProjectScaffolder.spec.ts +1 -1
  289. package/src/cli/core/{commands/gen → __tests__}/changelog.spec.ts +1 -1
  290. package/src/cli/core/{commands → __tests__}/init.spec.ts +2 -8
  291. package/src/cli/core/atoms/devOptions.ts +0 -5
  292. package/src/cli/core/commands/build.ts +2 -2
  293. package/src/cli/core/commands/dev.ts +165 -30
  294. package/src/cli/core/commands/gen/changelog.ts +2 -2
  295. package/src/cli/core/commands/init.ts +2 -7
  296. package/src/cli/core/commands/verify.ts +0 -1
  297. package/src/cli/core/providers/AppEntryProvider.ts +2 -2
  298. package/src/cli/core/providers/ViteDevServerProvider.ts +99 -69
  299. package/src/cli/core/services/PackageManagerUtils.ts +8 -1
  300. package/src/cli/core/services/ProjectScaffolder.ts +23 -23
  301. package/src/cli/core/tasks/BuildClientTask.ts +8 -0
  302. package/src/cli/core/tasks/BuildServerTask.ts +17 -4
  303. package/src/cli/core/templates/agentMd.ts +14 -5
  304. package/src/cli/core/templates/alephaConfigTs.ts +0 -6
  305. package/src/cli/core/templates/webAdminDashboardTsx.ts +17 -0
  306. package/src/cli/core/templates/webAppRouterTs.ts +85 -2
  307. package/src/cli/devtools/atoms/devtoolsOptions.ts +26 -0
  308. package/src/cli/devtools/index.ts +214 -0
  309. package/src/cli/platform/{adapters → __tests__}/CloudflareAdapter.spec.ts +2 -2
  310. package/src/cli/platform/{providers → __tests__}/GitHubSecretStore.spec.ts +1 -1
  311. package/src/cli/platform/{services → __tests__}/NamingService.spec.ts +1 -1
  312. package/src/cli/platform/{providers → __tests__}/PlatformCacheProvider.spec.ts +1 -1
  313. package/src/cli/platform/{services → __tests__}/PlatformInspector.spec.ts +1 -1
  314. package/src/cli/platform/{services → __tests__}/PlatformOrchestrator.spec.ts +3 -3
  315. package/src/cli/platform/{services → __tests__}/SecretFilterService.spec.ts +1 -1
  316. package/src/cli/platform/{commands → __tests__}/SecretsCommand.spec.ts +1 -1
  317. package/src/cli/platform/{adapters → __tests__}/VercelAdapter.spec.ts +2 -2
  318. package/src/cli/platform/atoms/platformOptions.ts +2 -10
  319. package/src/cli/platform/commands/SecretsCommand.ts +2 -2
  320. package/src/cli/platform/commands/platform.ts +2 -11
  321. package/src/cli/platform/index.ts +55 -11
  322. package/src/cli/platform/services/PlatformInspector.ts +2 -2
  323. package/src/cli/platform/services/PlatformOrchestrator.ts +0 -9
  324. package/src/cli/vendor/__tests__/VendorService.spec.ts +407 -0
  325. package/src/cli/vendor/atoms/vendorOptions.ts +41 -0
  326. package/src/cli/vendor/commands/VendorCommand.ts +204 -0
  327. package/src/cli/vendor/index.ts +60 -0
  328. package/src/cli/vendor/services/VendorService.ts +338 -0
  329. package/src/command/{providers → __tests__}/CliProvider.spec.ts +1 -1
  330. package/src/command/{helpers → __tests__}/EnvUtils.spec.ts +1 -1
  331. package/src/command/providers/CliProvider.ts +2 -2
  332. package/src/core/Alepha.ts +10 -0
  333. package/src/core/{primitives → __tests__}/$atom.spec.ts +2 -2
  334. package/src/core/{primitives → __tests__}/$memoize.spec.ts +1 -1
  335. package/src/core/{primitives → __tests__}/$mode.spec.ts +1 -1
  336. package/src/core/{primitives → __tests__}/$pipeline.spec.ts +1 -1
  337. package/src/core/{primitives → __tests__}/$scope.spec.ts +2 -2
  338. package/src/core/{providers → __tests__}/KeylessJsonSchemaCodec.spec.ts +1 -1
  339. package/src/core/{providers → __tests__}/SchemaValidator.spec.ts +1 -1
  340. package/src/core/{helpers → __tests__}/jsonSchemaToTypeBox.spec.ts +1 -1
  341. package/src/core/index.shared.ts +1 -1
  342. package/src/core/primitives/{$use.ts → $state.ts} +4 -4
  343. package/src/crypto/{providers → __tests__}/BrowserCryptoProvider.browser.spec.ts +1 -1
  344. package/src/crypto/{providers → __tests__}/CryptoProvider.spec.ts +1 -1
  345. package/src/datetime/{primitives → __tests__}/$debounce.spec.ts +1 -1
  346. package/src/datetime/{primitives → __tests__}/$throttle.spec.ts +1 -1
  347. package/src/datetime/{primitives → __tests__}/$timeout.spec.ts +1 -1
  348. package/src/email/brevo/{providers → __tests__}/BrevoEmailProvider.spec.ts +1 -1
  349. package/src/email/core/{providers → __tests__}/LocalEmailProvider.spec.ts +39 -150
  350. package/src/email/core/providers/LocalEmailProvider.ts +13 -51
  351. package/src/email/smtp/providers/NodemailerEmailProvider.ts +2 -2
  352. package/src/lock/core/{primitives → __tests__}/$lock.middleware.spec.ts +1 -1
  353. package/src/lock/core/primitives/$lock.ts +2 -2
  354. package/src/logger/index.ts +16 -5
  355. package/src/mcp/transports/SseMcpTransport.ts +2 -2
  356. package/src/orm/__tests__/ModelBuilder-tests.ts +53 -0
  357. package/src/orm/__tests__/ModelBuilder.spec.ts +80 -0
  358. package/src/orm/__tests__/organization-tests.ts +200 -0
  359. package/src/orm/__tests__/organization.spec.ts +103 -0
  360. package/src/orm/core/{providers/drivers → __tests__}/BunSqliteProvider.bun.spec.ts +5 -2
  361. package/src/orm/core/constants/PG_SYMBOLS.ts +2 -0
  362. package/src/orm/core/index.shared.ts +1 -0
  363. package/src/orm/core/primitives/$entity.ts +31 -0
  364. package/src/orm/core/providers/DatabaseTypeProvider.ts +11 -0
  365. package/src/orm/core/providers/DrizzleKitProvider.ts +57 -106
  366. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -2
  367. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +3 -3
  368. package/src/orm/core/services/ModelBuilder.ts +11 -0
  369. package/src/orm/core/services/QueryManager.ts +16 -2
  370. package/src/orm/core/services/Repository.ts +70 -10
  371. package/src/orm/postgres/{providers → __tests__}/BunPostgresProvider.bun.spec.ts +1 -1
  372. package/src/queue/core/providers/WorkerProvider.ts +2 -2
  373. package/src/queue/redis/providers/RedisQueueProvider.ts +2 -2
  374. package/src/react/core/{hooks → __tests__}/useAction.browser.spec.tsx +1 -1
  375. package/src/react/core/hooks/useAction.ts +7 -6
  376. package/src/react/head/{providers → __tests__}/BrowserHeadProvider.browser.spec.ts +1 -1
  377. package/src/react/head/{helpers → __tests__}/SeoExpander.spec.ts +1 -1
  378. package/src/react/i18n/{providers → __tests__}/I18nProvider.spec.ts +1 -1
  379. package/src/react/i18n/{hooks → __tests__}/useI18n.browser.spec.tsx +1 -1
  380. package/src/react/intro/components/GettingStartedDevtoolsSlide.tsx +1 -1
  381. package/src/react/router/{providers → __tests__}/ReactBrowserProvider.browser.spec.ts +1 -1
  382. package/src/react/router/providers/ReactBrowserProvider.ts +2 -2
  383. package/src/react/router/providers/ReactPageProvider.ts +2 -2
  384. package/src/react/router/providers/ReactServerProvider.ts +3 -3
  385. package/src/redis/{providers → __tests__}/BunRedisProvider.bun.spec.ts +4 -4
  386. package/src/retry/{primitives → __tests__}/$retry.middleware.spec.ts +1 -1
  387. package/src/router/{TemplatedPathParser.spec.ts → __tests__/TemplatedPathParser.spec.ts} +1 -1
  388. package/src/scheduler/primitives/$scheduler.ts +2 -2
  389. package/src/security/{primitives → __tests__}/$secure-browser.spec.ts +1 -1
  390. package/src/security/{primitives → __tests__}/$secure.spec.ts +1 -1
  391. package/src/security/primitives/$issuer.ts +1 -1
  392. package/src/security/providers/JwtProvider.ts +6 -10
  393. package/src/security/providers/SecurityProvider.ts +6 -11
  394. package/src/security/schemas/userAccountInfoSchema.ts +3 -3
  395. package/src/server/auth/providers/ServerAuthProvider.ts +24 -2
  396. package/src/server/cookies/{services → __tests__}/CookieParser.spec.ts +1 -1
  397. package/src/server/core/{primitives → __tests__}/$circuit.spec.ts +1 -1
  398. package/src/server/core/{providers → __tests__}/NodeHttpServerProvider.spec.ts +1 -1
  399. package/src/server/core/{providers → __tests__}/ServerBodyParserProvider.spec.ts +31 -1
  400. package/src/server/core/{providers → __tests__}/ServerCompressProvider.spec.ts +1 -1
  401. package/src/server/core/{providers → __tests__}/ServerHelmetProvider.spec.ts +4 -1
  402. package/src/server/core/{providers → __tests__}/ServerMultipartProvider.spec.ts +1 -1
  403. package/src/server/core/{services → __tests__}/ServerRequestParser.spec.ts +1 -1
  404. package/src/server/core/primitives/$action.ts +2 -2
  405. package/src/server/core/primitives/$sse.ts +2 -2
  406. package/src/server/core/providers/ServerBodyParserProvider.ts +21 -12
  407. package/src/server/core/providers/ServerCompressProvider.ts +2 -2
  408. package/src/server/core/providers/ServerHelmetProvider.ts +2 -2
  409. package/src/server/core/providers/ServerMultipartProvider.ts +2 -2
  410. package/src/server/core/providers/ServerRouterProvider.ts +1 -5
  411. package/src/server/cors/{primitives → __tests__}/$cors.spec.ts +1 -1
  412. package/src/server/cors/providers/ServerCorsProvider.ts +2 -2
  413. package/src/server/links/{services → __tests__}/BatchCollector.spec.ts +1 -1
  414. package/src/server/links/providers/LinkProvider.ts +2 -2
  415. package/src/server/links/providers/RemotePrimitiveProvider.ts +2 -2
  416. package/src/server/links/providers/ServerLinksProvider.ts +2 -2
  417. package/src/server/rate-limit/{primitives → __tests__}/$rateLimit.spec.ts +1 -1
  418. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +2 -2
  419. package/src/server/swagger/providers/ServerSwaggerProvider.ts +2 -2
  420. package/src/sms/{providers → __tests__}/LocalSmsProvider.spec.ts +35 -29
  421. package/src/sms/providers/LocalSmsProvider.ts +13 -24
  422. package/src/system/{providers → __tests__}/MemoryFileSystemProvider.spec.ts +1 -1
  423. package/src/system/{providers → __tests__}/MemoryShellProvider.spec.ts +1 -1
  424. package/src/topic/redis/providers/RedisTopicProvider.ts +2 -2
  425. package/src/websocket/{services → __tests__}/RoomManager.spec.ts +1 -1
  426. package/src/websocket/providers/NodeWebSocketServerProvider.ts +2 -2
  427. package/src/cli/platform/adapters/DockerAdapter.spec.ts +0 -378
  428. package/src/cli/platform/adapters/DockerAdapter.ts +0 -417
  429. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +0 -490
  430. package/src/cli/platform/services/DockerComposeGenerator.ts +0 -353
  431. package/src/cli/platform/services/DockerSshService.spec.ts +0 -47
  432. package/src/cli/platform/services/DockerSshService.ts +0 -61
  433. /package/src/api/audits/{primitives → __tests__}/$audit.spec.ts +0 -0
  434. /package/src/api/audits/{services → __tests__}/AuditService.spec.ts +0 -0
  435. /package/src/api/files/{controllers → __tests__}/AdminFileStatsController.spec.ts +0 -0
  436. /package/src/api/files/{controllers → __tests__}/FileController.spec.ts +0 -0
  437. /package/src/api/files/{jobs → __tests__}/FileJobs.spec.ts +0 -0
  438. /package/src/api/files/{services → __tests__}/FileService.spec.ts +0 -0
  439. /package/src/api/jobs/{primitives → __tests__}/$job-middleware.spec.ts +0 -0
  440. /package/src/api/parameters/{primitives → __tests__}/$parameter.spec.ts +0 -0
  441. /package/src/api/users/{primitives → __tests__}/$realm.spec.ts +0 -0
  442. /package/src/api/users/{controllers → __tests__}/AdminIdentityController.spec.ts +0 -0
  443. /package/src/api/users/{controllers → __tests__}/AdminSessionController.spec.ts +0 -0
  444. /package/src/api/users/{controllers → __tests__}/AdminUserController.spec.ts +0 -0
  445. /package/src/api/users/{services → __tests__}/CredentialService.spec.ts +0 -0
  446. /package/src/api/users/{providers → __tests__}/RealmProvider.spec.ts +0 -0
  447. /package/src/api/users/{services → __tests__}/RegistrationService.spec.ts +0 -0
  448. /package/src/batch/{primitives → __tests__}/$batch.spec.ts +0 -0
  449. /package/src/batch/{providers → __tests__}/BatchProvider.spec.ts +0 -0
  450. /package/src/bucket/{primitives → __tests__}/$bucket.spec.ts +0 -0
  451. /package/src/bucket/{providers → __tests__}/FileStorageProvider.spec.ts +0 -0
  452. /package/src/bucket/{providers → __tests__}/LocalFileStorageProvider.spec.ts +0 -0
  453. /package/src/bucket/{providers → __tests__}/MemoryFileStorageProvider.spec.ts +0 -0
  454. /package/src/cache/core/{primitives → __tests__}/$cache.spec.ts +0 -0
  455. /package/src/cache/redis/{providers → __tests__}/RedisCacheProvider.spec.ts +0 -0
  456. /package/src/command/{primitives → __tests__}/$command.spec.ts +0 -0
  457. /package/src/command/{helpers → __tests__}/Asker.spec.ts +0 -0
  458. /package/src/command/{helpers → __tests__}/Runner.spec.ts +0 -0
  459. /package/src/core/{primitives → __tests__}/$context.spec.ts +0 -0
  460. /package/src/core/{primitives → __tests__}/$env.spec.ts +0 -0
  461. /package/src/core/{primitives → __tests__}/$hook.spec.ts +0 -0
  462. /package/src/core/{primitives → __tests__}/$inject.spec.ts +0 -0
  463. /package/src/core/{primitives → __tests__}/$module.spec.ts +0 -0
  464. /package/src/core/{providers → __tests__}/CodecManager.spec.ts +0 -0
  465. /package/src/core/{providers → __tests__}/EventManager.spec.ts +0 -0
  466. /package/src/core/{providers → __tests__}/StateManager.spec.ts +0 -0
  467. /package/src/core/{providers → __tests__}/TypeProvider.spec.ts +0 -0
  468. /package/src/datetime/{primitives → __tests__}/$interval.spec.ts +0 -0
  469. /package/src/datetime/{providers → __tests__}/DateTimeProvider.spec.ts +0 -0
  470. /package/src/email/core/{primitives → __tests__}/$email.spec.ts +0 -0
  471. /package/src/fake/{providers → __tests__}/FakeProvider.spec.ts +0 -0
  472. /package/src/lock/core/{providers → __tests__}/MemoryLockProvider.spec.ts +0 -0
  473. /package/src/lock/redis/{providers → __tests__}/RedisLockProvider.spec.ts +0 -0
  474. /package/src/logger/{primitives → __tests__}/$logger.spec.ts +0 -0
  475. /package/src/logger/{services → __tests__}/Logger.spec.ts +0 -0
  476. /package/src/mcp/{primitives → __tests__}/$prompt.spec.ts +0 -0
  477. /package/src/mcp/{primitives → __tests__}/$resource.spec.ts +0 -0
  478. /package/src/mcp/{primitives → __tests__}/$tool.spec.ts +0 -0
  479. /package/src/mcp/{providers → __tests__}/McpServerProvider.spec.ts +0 -0
  480. /package/src/mcp/{helpers → __tests__}/jsonrpc.spec.ts +0 -0
  481. /package/src/orm/core/{helpers → __tests__}/parseQueryString.spec.ts +0 -0
  482. /package/src/queue/core/{primitives → __tests__}/$consumer.spec.ts +0 -0
  483. /package/src/queue/core/{providers → __tests__}/MemoryQueueProvider.spec.ts +0 -0
  484. /package/src/queue/core/{providers → __tests__}/WorkerProvider.spec.ts +0 -0
  485. /package/src/queue/redis/{providers → __tests__}/RedisQueueProvider.spec.ts +0 -0
  486. /package/src/react/form/{hooks → __tests__}/useForm.browser.spec.tsx +0 -0
  487. /package/src/react/head/{hooks → __tests__}/useHead.spec.tsx +0 -0
  488. /package/src/react/i18n/{components → __tests__}/Localize.spec.tsx +0 -0
  489. /package/src/react/router/{primitives → __tests__}/$page.browser.spec.tsx +0 -0
  490. /package/src/react/router/{primitives → __tests__}/$page.middleware.spec.tsx +0 -0
  491. /package/src/react/router/{primitives → __tests__}/$page.spec.tsx +0 -0
  492. /package/src/react/router/{providers → __tests__}/ReactPreloadProvider.spec.ts +0 -0
  493. /package/src/react/router/{providers → __tests__}/ReactServerProvider.spec.tsx +0 -0
  494. /package/src/react/router/{providers → __tests__}/ReactServerTemplateProvider.spec.ts +0 -0
  495. /package/src/retry/{primitives → __tests__}/$retry.spec.ts +0 -0
  496. /package/src/retry/{providers → __tests__}/RetryProvider.spec.ts +0 -0
  497. /package/src/router/{providers → __tests__}/RouterProvider.spec.ts +0 -0
  498. /package/src/security/{primitives → __tests__}/$issuer.spec.ts +0 -0
  499. /package/src/security/{primitives → __tests__}/$permission.spec.ts +0 -0
  500. /package/src/security/{primitives → __tests__}/$role.spec.ts +0 -0
  501. /package/src/security/{primitives → __tests__}/$serviceAccount.spec.ts +0 -0
  502. /package/src/security/{providers → __tests__}/SecurityProvider.spec.ts +0 -0
  503. /package/src/server/cookies/{providers → __tests__}/ServerCookiesProvider.spec.ts +0 -0
  504. /package/src/server/core/{primitives → __tests__}/$action.spec.ts +0 -0
  505. /package/src/server/core/{primitives → __tests__}/$middleware.spec.ts +0 -0
  506. /package/src/server/core/{primitives → __tests__}/$route.spec.ts +0 -0
  507. /package/src/server/core/{primitives → __tests__}/$sse.spec.ts +0 -0
  508. /package/src/server/core/{providers → __tests__}/BunHttpServerProvider.bun.spec.ts +0 -0
  509. /package/src/server/core/{services → __tests__}/HttpClient.spec.ts +0 -0
  510. /package/src/server/core/{providers → __tests__}/ServerLoggerProvider.spec.ts +0 -0
  511. /package/src/server/core/{services → __tests__}/UserAgentParser.spec.ts +0 -0
  512. /package/src/server/cors/{providers → __tests__}/ServerCorsProvider.spec.ts +0 -0
  513. /package/src/server/etag/{providers → __tests__}/ServerEtagProvider.spec.ts +0 -0
  514. /package/src/server/health/{providers → __tests__}/ServerHealthProvider.spec.ts +0 -0
  515. /package/src/server/links/{primitives → __tests__}/$remote.spec.ts +0 -0
  516. /package/src/server/links/{services → __tests__}/BatchEndpoint.spec.ts +0 -0
  517. /package/src/server/links/{providers → __tests__}/LinkProvider.spec.ts +0 -0
  518. /package/src/server/links/{providers → __tests__}/ServerLinksProvider.spec.ts +0 -0
  519. /package/src/server/metrics/{providers → __tests__}/ServerMetricsProvider.spec.ts +0 -0
  520. /package/src/server/proxy/{primitives → __tests__}/$proxy.spec.ts +0 -0
  521. /package/src/server/rate-limit/{providers → __tests__}/ServerRateLimitProvider.spec.ts +0 -0
  522. /package/src/server/static/{primitives → __tests__}/$serve.spec.ts +0 -0
  523. /package/src/server/swagger/{primitives → __tests__}/$swagger.spec.ts +0 -0
  524. /package/src/sms/{primitives → __tests__}/$sms.spec.ts +0 -0
  525. /package/src/sms/{providers → __tests__}/MemorySmsProvider.spec.ts +0 -0
  526. /package/src/system/{services → __tests__}/FileDetector.spec.ts +0 -0
  527. /package/src/system/{providers → __tests__}/NodeFileSystemProvider.spec.ts +0 -0
  528. /package/src/topic/core/{primitives → __tests__}/$subscriber.spec.ts +0 -0
  529. /package/src/topic/core/{providers → __tests__}/MemoryTopicProvider.spec.ts +0 -0
  530. /package/src/topic/redis/{providers → __tests__}/RedisTopicProvider.spec.ts +0 -0
  531. /package/src/websocket/{primitives → __tests__}/$channel.spec.ts +0 -0
@@ -1,4 +1,7 @@
1
- import { $inject, $use, Alepha, t } from "alepha";
1
+ import { spawn } from "node:child_process";
2
+ import { readdir, stat } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { $inject, $state, Alepha, t } from "alepha";
2
5
  import { $command } from "alepha/command";
3
6
  import { $logger } from "alepha/logger";
4
7
  import { FileSystemProvider } from "alepha/system";
@@ -18,48 +21,180 @@ export class DevCommand {
18
21
  protected readonly alepha = $inject(Alepha);
19
22
  protected readonly viteDevServer = $inject(ViteDevServerProvider);
20
23
  protected readonly boot = $inject(AppEntryProvider);
21
- protected readonly options = $use(devOptions);
24
+ protected readonly options = $state(devOptions);
22
25
 
23
26
  /**
24
27
  * Will run the project in watch mode.
28
+ *
29
+ * When run from a workspace root (with apps/ directory), spawns all apps in parallel.
30
+ * When run from an app directory, starts a single Vite dev server.
25
31
  */
26
32
  public readonly dev = $command({
27
33
  name: "dev",
28
34
  mode: true,
29
35
  description: "Run the project in development mode",
30
36
  flags: t.object({
31
- "no-devtools": t.optional(
32
- t.boolean({
33
- description: "Disable devtools",
34
- }),
35
- ),
36
- "no-vite-react-plugin": t.optional(
37
- t.boolean({
38
- description: "Disable Vite React plugin",
37
+ only: t.optional(
38
+ t.string({
39
+ description:
40
+ "Run only specific apps (comma-separated: --only api,companion)",
39
41
  }),
40
42
  ),
41
43
  }),
42
44
  handler: async ({ root, flags }) => {
43
- await this.scaffolder.ensureConfig(root, {
44
- tsconfigJson: true,
45
- });
46
-
47
- const entry = await this.boot.getAppEntry(root);
48
- this.log.debug("Entry file found", { entry });
49
-
50
- const options = this.options;
51
-
52
- // -> here, we assume we use Vite as runner (api or fullstack)
53
- // but it's planned to support Bun runner in the future as well
54
- await this.viteDevServer.init({
55
- root,
56
- entry,
57
- noDevtools: flags["no-devtools"] ?? options.noDevtools ?? false,
58
- noViteReactPlugin:
59
- flags["no-vite-react-plugin"] ?? options.noViteReactPlugin ?? false,
60
- });
61
-
62
- await this.viteDevServer.start();
45
+ const apps = await this.discoverApps(root);
46
+
47
+ if (apps.length > 0) {
48
+ await this.runMultiple(root, apps, flags);
49
+ } else {
50
+ await this.runSingle(root);
51
+ }
63
52
  },
64
53
  });
54
+
55
+ /**
56
+ * Discover apps in the workspace root.
57
+ *
58
+ * Looks for directories under apps/ that contain a package.json.
59
+ * Supports scoped directories (e.g., apps/@passeo/api).
60
+ * Returns empty array if not in a workspace root.
61
+ */
62
+ protected async discoverApps(
63
+ root: string,
64
+ ): Promise<Array<{ name: string; path: string }>> {
65
+ const appsDir = join(root, "apps");
66
+
67
+ if (!(await this.fs.exists(appsDir))) {
68
+ return [];
69
+ }
70
+
71
+ const entries = await readdir(appsDir);
72
+ const apps: Array<{ name: string; path: string }> = [];
73
+
74
+ for (const entry of entries) {
75
+ const appPath = join(appsDir, entry);
76
+ const pkgPath = join(appPath, "package.json");
77
+
78
+ if (await this.fs.exists(pkgPath)) {
79
+ apps.push({ name: entry, path: appPath });
80
+ continue;
81
+ }
82
+
83
+ // Check scoped directories (e.g., apps/@passeo/api)
84
+ const entryStat = await stat(appPath).catch(() => null);
85
+ if (entryStat?.isDirectory()) {
86
+ const scopedEntries = await readdir(appPath);
87
+ for (const scopedEntry of scopedEntries) {
88
+ const scopedPath = join(appPath, scopedEntry);
89
+ const scopedPkgPath = join(scopedPath, "package.json");
90
+
91
+ if (await this.fs.exists(scopedPkgPath)) {
92
+ apps.push({ name: scopedEntry, path: scopedPath });
93
+ }
94
+ }
95
+ }
96
+ }
97
+
98
+ return apps;
99
+ }
100
+
101
+ /**
102
+ * Run a single app (existing behavior).
103
+ */
104
+ protected async runSingle(root: string): Promise<void> {
105
+ await this.scaffolder.ensureConfig(root, {
106
+ tsconfigJson: true,
107
+ });
108
+
109
+ const entry = await this.boot.getAppEntry(root);
110
+ this.log.debug("Entry file found", { entry });
111
+
112
+ const options = this.options;
113
+
114
+ await this.viteDevServer.init({
115
+ root,
116
+ entry,
117
+ noViteReactPlugin: options.noViteReactPlugin ?? false,
118
+ });
119
+
120
+ await this.viteDevServer.start();
121
+ }
122
+
123
+ /**
124
+ * Run multiple apps in parallel with colored prefixed output.
125
+ */
126
+ protected async runMultiple(
127
+ _root: string,
128
+ apps: Array<{ name: string; path: string }>,
129
+ flags: Record<string, unknown>,
130
+ ): Promise<void> {
131
+ const only = flags.only as string | undefined;
132
+
133
+ if (only) {
134
+ const filter = only.split(",").map((s) => s.trim().toLowerCase());
135
+ apps = apps.filter((app) => filter.includes(app.name.toLowerCase()));
136
+ }
137
+
138
+ if (apps.length === 0) {
139
+ this.log.warn("No apps found to run");
140
+ return;
141
+ }
142
+
143
+ this.log.debug(
144
+ `Starting ${apps.length} apps: ${apps.map((a) => a.name).join(", ")}`,
145
+ );
146
+
147
+ const basePort = 5173;
148
+ const processes = apps.map((app, i) => this.spawnApp(app, basePort + i));
149
+
150
+ // Handle graceful shutdown
151
+ const cleanup = () => {
152
+ for (const proc of processes) {
153
+ proc.kill("SIGTERM");
154
+ }
155
+ };
156
+
157
+ process.once("SIGINT", cleanup);
158
+ process.once("SIGTERM", cleanup);
159
+
160
+ // Wait for all processes (they run until killed)
161
+ await Promise.allSettled(
162
+ processes.map(
163
+ (proc) =>
164
+ new Promise<void>((resolve) => {
165
+ proc.on("exit", () => resolve());
166
+ }),
167
+ ),
168
+ );
169
+ }
170
+
171
+ /**
172
+ * Spawn a single app process with inherited stdio.
173
+ *
174
+ * Each child process gets APP_NAME set, so the Alepha logger
175
+ * handles prefixing automatically.
176
+ */
177
+ protected spawnApp(
178
+ app: { name: string; path: string },
179
+ port: number,
180
+ ): ReturnType<typeof spawn> {
181
+ const proc = spawn("yarn", ["alepha", "dev"], {
182
+ cwd: app.path,
183
+ stdio: "inherit",
184
+ env: {
185
+ ...process.env,
186
+ APP_NAME: app.name.toUpperCase(),
187
+ SERVER_PORT: String(port),
188
+ FORCE_COLOR: "1",
189
+ },
190
+ });
191
+
192
+ proc.on("exit", (code) => {
193
+ if (code !== 0 && code !== null) {
194
+ this.log.error(`${app.name} exited with code ${code}`);
195
+ }
196
+ });
197
+
198
+ return proc;
199
+ }
65
200
  }
@@ -1,6 +1,6 @@
1
1
  import { exec } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
- import { $inject, $use, t } from "alepha";
3
+ import { $inject, $state, t } from "alepha";
4
4
  import { $command } from "alepha/command";
5
5
  import { $logger } from "alepha/logger";
6
6
  import { changelogOptions } from "../../atoms/changelogOptions.ts";
@@ -64,7 +64,7 @@ export class ChangelogCommand {
64
64
  protected readonly log = $logger();
65
65
  protected readonly git = $inject(GitProvider);
66
66
  protected readonly parser = $inject(GitMessageParser);
67
- protected readonly config = $use(changelogOptions);
67
+ protected readonly config = $state(changelogOptions);
68
68
 
69
69
  // ---------------------------------------------------------------------------
70
70
  // FORMATTING
@@ -43,15 +43,10 @@ export class InitCommand {
43
43
  "Include @alepha/ui (components, auth portal, admin portal)",
44
44
  }),
45
45
  ),
46
- auth: t.optional(
46
+ saas: t.optional(
47
47
  t.boolean({
48
48
  description:
49
- "Include authentication (AppSecurity, $uiAuth). Implies --api --ui --react",
50
- }),
51
- ),
52
- admin: t.optional(
53
- t.boolean({
54
- description: "Include admin portal ($uiAdmin). Implies --auth",
49
+ "Include authentication, admin portal, API, UI, and React. Everything you need for a SaaS app.",
55
50
  }),
56
51
  ),
57
52
  tailwind: t.optional(
@@ -25,7 +25,6 @@ export class VerifyCommand {
25
25
  description: "Verify the Alepha project",
26
26
  handler: async ({ root, run }) => {
27
27
  await run("alepha clean");
28
- await run("alepha format");
29
28
  await run("alepha lint");
30
29
 
31
30
  await run("alepha typecheck");
@@ -1,4 +1,4 @@
1
- import { $inject, $use, AlephaError } from "alepha";
1
+ import { $inject, $state, AlephaError } from "alepha";
2
2
  import { FileSystemProvider } from "alepha/system";
3
3
  import { appEntryOptions } from "../atoms/appEntryOptions.ts";
4
4
 
@@ -9,7 +9,7 @@ import { appEntryOptions } from "../atoms/appEntryOptions.ts";
9
9
  */
10
10
  export class AppEntryProvider {
11
11
  protected readonly fs = $inject(FileSystemProvider);
12
- protected readonly options = $use(appEntryOptions);
12
+ protected readonly options = $state(appEntryOptions);
13
13
 
14
14
  protected readonly serverEntries = [
15
15
  "main.server.ts",
@@ -1,6 +1,4 @@
1
- import { readFile } from "node:fs/promises";
2
- import { createRequire } from "node:module";
3
- import { dirname, join } from "node:path";
1
+ import { join } from "node:path";
4
2
  import { __alephaRef, $inject, type Alepha, AlephaError } from "alepha";
5
3
  import { $logger, ConsoleColorProvider } from "alepha/logger";
6
4
  import { FileSystemProvider } from "alepha/system";
@@ -19,17 +17,20 @@ export interface DevServerOptions {
19
17
  */
20
18
  entry: AppEntry;
21
19
 
22
- /**
23
- * Disable devtools.
24
- */
25
- noDevtools?: boolean;
26
-
27
20
  /**
28
21
  * Disable Vite React plugin.
29
22
  */
30
23
  noViteReactPlugin?: boolean;
31
24
  }
32
25
 
26
+ /**
27
+ * Hook called after Alepha is loaded during dev server init/reload.
28
+ */
29
+ export type OnAlephaLoadedHook = (
30
+ alepha: Alepha,
31
+ server: ViteDevServer,
32
+ ) => Promise<void>;
33
+
33
34
  /**
34
35
  * Vite development server with Alepha integration.
35
36
  *
@@ -60,7 +61,33 @@ export class ViteDevServerProvider {
60
61
  protected isReloading = false;
61
62
  protected needsBrowserReload = false;
62
63
  protected currentReloadPromise: Promise<void> | null = null;
63
- protected devtoolsAssetsPath: string | undefined;
64
+ protected extraVitePlugins: Plugin[] = [];
65
+ protected alephaLoadedHooks: OnAlephaLoadedHook[] = [];
66
+
67
+ /**
68
+ * Register an additional Vite plugin.
69
+ * Must be called before init().
70
+ */
71
+ public addVitePlugin(plugin: Plugin): void {
72
+ this.extraVitePlugins.push(plugin);
73
+ }
74
+
75
+ /**
76
+ * Register a hook called after Alepha is loaded/reloaded.
77
+ */
78
+ public onAlephaLoaded(hook: OnAlephaLoadedHook): void {
79
+ this.alephaLoadedHooks.push(hook);
80
+ }
81
+
82
+ /**
83
+ * Trigger a full Alepha reload programmatically.
84
+ */
85
+ public reload(): void {
86
+ this.hasError = true;
87
+ this.needsBrowserReload = true;
88
+ this.changedFiles.add("__manual_reload__");
89
+ this.scheduleReload();
90
+ }
64
91
 
65
92
  /**
66
93
  * Initialize the dev server and load Alepha.
@@ -88,10 +115,10 @@ export class ViteDevServerProvider {
88
115
  await this.alepha?.start();
89
116
  await this.listen();
90
117
 
91
- console.log("");
92
- this.server.printUrls();
93
- this.server.bindCLIShortcuts({ print: true });
94
- console.log("");
118
+ const port = this.server.config.server.port ?? 5173;
119
+ const url = `http://localhost:${port}/`;
120
+ const log = this.alepha?.log ?? this.log;
121
+ log.info(`Listening on ${this.colors.set("CYAN", url)}`);
95
122
  } catch (err) {
96
123
  this.hasError = true;
97
124
  this.currentError = err instanceof Error ? err : new Error(String(err));
@@ -126,6 +153,7 @@ export class ViteDevServerProvider {
126
153
  if (viteReact && !this.options.noViteReactPlugin) plugins.push(viteReact());
127
154
  plugins.push(this.viteUtils.createTsconfigPathsPlugin());
128
155
  plugins.push(this.viteUtils.createSsrPreloadPlugin());
156
+ plugins.push(...this.extraVitePlugins);
129
157
  plugins.push(this.createAlephaPlugin());
130
158
 
131
159
  // DEFAULT PORT
@@ -144,6 +172,14 @@ export class ViteDevServerProvider {
144
172
  root: this.options.root,
145
173
  plugins,
146
174
  appType: "custom",
175
+ resolve: {
176
+ dedupe: [
177
+ "react",
178
+ "react-dom",
179
+ "react/jsx-runtime",
180
+ "react/jsx-dev-runtime",
181
+ ],
182
+ },
147
183
  server: {
148
184
  port,
149
185
  },
@@ -205,51 +241,6 @@ export class ViteDevServerProvider {
205
241
  name: "alepha",
206
242
 
207
243
  configureServer: (server) => {
208
- // Resolve @alepha/devtools assets path (if installed)
209
- if (!this.options.noDevtools) {
210
- try {
211
- const require = createRequire(import.meta.url);
212
- const pkgPath = require.resolve("@alepha/devtools/package.json");
213
- this.devtoolsAssetsPath = join(dirname(pkgPath), "assets/ui");
214
- process.env.VITE_ALEPHA_DEVTOOLS = "true";
215
- } catch {
216
- this.log.debug("@alepha/devtools not installed, skipping devtools");
217
- }
218
- }
219
-
220
- // Devtools live reload via SSE
221
- if (this.devtoolsAssetsPath) {
222
- const assetsPath = this.devtoolsAssetsPath;
223
-
224
- server.middlewares.use(async (req, res, next) => {
225
- const url = req.url || "/";
226
-
227
- // Serve devtools HTML with reload script injected
228
- if (
229
- !url.startsWith("/__devtools") ||
230
- !req.headers.accept?.includes("text/html")
231
- ) {
232
- return next();
233
- }
234
-
235
- const indexPath = join(assetsPath, "index.html");
236
-
237
- try {
238
- let html = await readFile(indexPath, "utf-8");
239
- html = html.replace(
240
- "<head>",
241
- `<head><script type="module" src="/@vite/client"></script>`,
242
- );
243
-
244
- res.writeHead(200, { "content-type": "text/html" });
245
- res.end(html);
246
- } catch (err) {
247
- this.log.error("Failed to serve devtools UI", err);
248
- next();
249
- }
250
- });
251
- }
252
-
253
244
  // Re-send error overlay when a new browser connects (e.g. page refresh during error state)
254
245
  server.hot.on("connection", () => {
255
246
  if (this.currentError) {
@@ -257,6 +248,26 @@ export class ViteDevServerProvider {
257
248
  }
258
249
  });
259
250
 
251
+ // Readiness endpoint: responds only when Alepha is fully loaded
252
+ server.middlewares.use(async (req, res, next) => {
253
+ if (req.url !== "/__alepha/ready") {
254
+ next();
255
+ return;
256
+ }
257
+
258
+ if (this.currentReloadPromise) {
259
+ await this.currentReloadPromise;
260
+ }
261
+
262
+ if (this.alepha?.isReady()) {
263
+ res.writeHead(200, { "content-type": "text/plain" });
264
+ res.end("ok");
265
+ } else {
266
+ res.writeHead(503, { "content-type": "text/plain" });
267
+ res.end("not ready");
268
+ }
269
+ });
270
+
260
271
  // Return function to run AFTER Vite's built-in middleware
261
272
  return () => {
262
273
  server.middlewares.use(async (req, res, next) => {
@@ -267,6 +278,11 @@ export class ViteDevServerProvider {
267
278
  return;
268
279
  }
269
280
 
281
+ // Wait for in-progress reload to complete before serving
282
+ if (this.currentReloadPromise) {
283
+ await this.currentReloadPromise;
284
+ }
285
+
270
286
  // In error state, serve a minimal HTML shell so the browser
271
287
  // can connect to Vite's HMR and display the error overlay
272
288
  if (this.hasError && !this.alepha) {
@@ -341,11 +357,10 @@ export class ViteDevServerProvider {
341
357
 
342
358
  /**
343
359
  * Send full browser reload via Vite's HMR.
360
+ * Uses a custom event so the client can poll for readiness before reloading.
344
361
  */
345
362
  protected sendBrowserReload(): void {
346
- this.server.hot.send({
347
- type: "full-reload",
348
- });
363
+ this.server.hot.send("alepha:reload", {});
349
364
  }
350
365
 
351
366
  /**
@@ -482,13 +497,8 @@ export class ViteDevServerProvider {
482
497
  // Expose Vite server to Alepha for Logger SSR stack trace fixing
483
498
  alepha.store.set("alepha.vite.server" as any, this.server);
484
499
 
485
- if (this.devtoolsAssetsPath) {
486
- try {
487
- const mod = await this.server.ssrLoadModule("@alepha/devtools");
488
- alepha.with(mod.AlephaDevtools);
489
- } catch (err) {
490
- this.log.warn("Failed to load @alepha/devtools", err);
491
- }
500
+ for (const hook of this.alephaLoadedHooks) {
501
+ await hook(alepha, this.server);
492
502
  }
493
503
 
494
504
  this.alepha = alepha;
@@ -565,6 +575,24 @@ export class ViteDevServerProvider {
565
575
  if (preamble) {
566
576
  tags.push(preamble);
567
577
  }
578
+
579
+ // Reload handler: polls /__alepha/ready before reloading to avoid
580
+ // hitting the server while it's still restarting.
581
+ tags.push(`<script type="module">
582
+ if (import.meta.hot) {
583
+ import.meta.hot.on("alepha:reload", async () => {
584
+ for (let i = 0; i < 50; i++) {
585
+ try {
586
+ const res = await fetch("/__alepha/ready");
587
+ if (res.ok) { window.location.reload(); return; }
588
+ } catch {}
589
+ await new Promise(r => setTimeout(r, 200));
590
+ }
591
+ window.location.reload();
592
+ });
593
+ }
594
+ </script>`);
595
+
568
596
  if (style) {
569
597
  tags.push(`<link rel="stylesheet" href="/${style}">`);
570
598
  }
@@ -717,11 +745,13 @@ export class ViteDevServerProvider {
717
745
  /**
718
746
  * Log a formatted error with stack trace.
719
747
  */
720
- protected logError(title: string, _err: unknown): void {
748
+ protected logError(title: string, err: unknown): void {
721
749
  const c = this.colors;
722
750
 
723
751
  console.log();
724
752
  console.log(c.set("RED", ` ✗ ${title}`));
753
+ this.logErrorWithCause(err);
754
+ console.log();
725
755
  console.log(c.set("GREY_DARK", " Waiting for file changes to retry..."));
726
756
  console.log();
727
757
  }
@@ -399,9 +399,16 @@ export class PackageManagerUtils {
399
399
  };
400
400
 
401
401
  const devDependencies: Record<string, string> = {
402
- "drizzle-kit": alephaDeps["drizzle-kit"],
402
+ vite: alephaDeps.vite,
403
403
  };
404
404
 
405
+ // Only include drizzle-kit when the project uses a database.
406
+ // React-only projects (--react without --api/--saas) don't need it.
407
+ const isReactOnly = modes.react && !modes.ui;
408
+ if (!isReactOnly) {
409
+ devDependencies["drizzle-kit"] = alephaDeps["drizzle-kit"];
410
+ }
411
+
405
412
  // Add biome/vitest only if not a workspace package (workspace root has them)
406
413
  if (!modes.isPackage) {
407
414
  devDependencies["@biomejs/biome"] = alephaDeps["@biomejs/biome"];
@@ -5,7 +5,7 @@ import type { RunnerMethod } from "alepha/command";
5
5
  import { $logger, ConsoleColorProvider } from "alepha/logger";
6
6
  import { FileSystemProvider } from "alepha/system";
7
7
  import { cliAssets } from "../assets.ts";
8
- import { type AgentMdType, agentMd } from "../templates/agentMd.ts";
8
+ import { type AgentMdOptions, agentMd } from "../templates/agentMd.ts";
9
9
  import { alephaConfigTs } from "../templates/alephaConfigTs.ts";
10
10
  import { apiAppSecurityTs } from "../templates/apiAppSecurityTs.ts";
11
11
  import { apiHelloControllerTs } from "../templates/apiHelloControllerTs.ts";
@@ -20,6 +20,7 @@ import { mainCss } from "../templates/mainCss.ts";
20
20
  import { mainServerTs } from "../templates/mainServerTs.ts";
21
21
  import { tsconfigJson } from "../templates/tsconfigJson.ts";
22
22
  import { viteConfigTs } from "../templates/viteConfigTs.ts";
23
+ import { webAdminDashboardTsx } from "../templates/webAdminDashboardTsx.ts";
23
24
  import { webAppRouterTs } from "../templates/webAppRouterTs.ts";
24
25
  import { webHomeComponentTsx } from "../templates/webHomeComponentTsx.ts";
25
26
  import { webIndexTs } from "../templates/webIndexTs.ts";
@@ -74,7 +75,7 @@ export class ProjectScaffolder {
74
75
  tsconfigJson?: boolean;
75
76
  biomeJson?: boolean;
76
77
  editorconfig?: boolean;
77
- agentMd?: false | { type: AgentMdType };
78
+ agentMd?: false | AgentMdOptions;
78
79
  },
79
80
  ): Promise<void> {
80
81
  const tasks: Promise<void>[] = [];
@@ -186,10 +187,10 @@ export class ProjectScaffolder {
186
187
 
187
188
  public async ensureAgentMd(
188
189
  root: string,
189
- options: { type: AgentMdType; force?: boolean },
190
+ options: AgentMdOptions & { force?: boolean },
190
191
  ): Promise<void> {
191
192
  const filename = options.type === "claude" ? "CLAUDE.md" : "AGENTS.md";
192
- await this.ensureFile(root, filename, agentMd(options.type), options.force);
193
+ await this.ensureFile(root, filename, agentMd(options), options.force);
193
194
  }
194
195
 
195
196
  /**
@@ -356,6 +357,14 @@ export class ProjectScaffolder {
356
357
  webHomeComponentTsx({ api: opts.api }),
357
358
  opts.force,
358
359
  );
360
+ if (opts.admin) {
361
+ await this.ensureFile(
362
+ root,
363
+ "src/web/components/AdminDashboard.tsx",
364
+ webAdminDashboardTsx(),
365
+ opts.force,
366
+ );
367
+ }
359
368
  await this.ensureFile(
360
369
  root,
361
370
  "src/main.browser.ts",
@@ -407,8 +416,7 @@ export class ProjectScaffolder {
407
416
  api?: boolean;
408
417
  react?: boolean;
409
418
  ui?: boolean;
410
- auth?: boolean;
411
- admin?: boolean;
419
+ saas?: boolean;
412
420
  tailwind?: boolean;
413
421
  test?: boolean;
414
422
  force?: boolean;
@@ -420,11 +428,8 @@ export class ProjectScaffolder {
420
428
  await this.fs.mkdir(root, { force: true });
421
429
  }
422
430
 
423
- // Flag cascading: --admin → --auth --ui → --react, --api
424
- if (flags.admin) {
425
- flags.auth = true;
426
- }
427
- if (flags.auth) {
431
+ // Flag cascading: --saas → --api + --ui → --react
432
+ if (flags.saas) {
428
433
  flags.api = true;
429
434
  flags.ui = true;
430
435
  }
@@ -437,12 +442,7 @@ export class ProjectScaffolder {
437
442
 
438
443
  // When codegen flags are set, target directory must be empty (unless --force)
439
444
  const hasCodegenFlags =
440
- flags.admin ||
441
- flags.auth ||
442
- flags.api ||
443
- flags.ui ||
444
- flags.react ||
445
- flags.tailwind;
445
+ flags.saas || flags.api || flags.ui || flags.react || flags.tailwind;
446
446
  if (hasCodegenFlags && !flags.force) {
447
447
  const files = await this.fs.ls(root);
448
448
  // Allow a directory that only has package.json (common for monorepo packages)
@@ -466,8 +466,8 @@ export class ProjectScaffolder {
466
466
 
467
467
  const isExpo = await this.pm.hasExpo(root);
468
468
 
469
- // Get git email for admin auto-promotion (if auth enabled)
470
- const adminEmail = flags.auth ? await this.utils.getGitEmail() : undefined;
469
+ // Get git email for admin auto-promotion (if saas enabled)
470
+ const adminEmail = flags.saas ? await this.utils.getGitEmail() : undefined;
471
471
 
472
472
  const force = !!flags.force;
473
473
 
@@ -481,7 +481,7 @@ export class ProjectScaffolder {
481
481
  tsconfigJson: !workspace.config.tsconfigJson,
482
482
  biomeJson: true,
483
483
  editorconfig: !workspace.config.editorconfig,
484
- agentMd: agentType ? { type: agentType } : false,
484
+ agentMd: agentType ? { type: agentType, ui: !!flags.ui } : false,
485
485
  });
486
486
 
487
487
  // Create alepha.config.ts with documented options
@@ -495,7 +495,7 @@ export class ProjectScaffolder {
495
495
  });
496
496
  if (flags.api) {
497
497
  await this.ensureApiProject(root, {
498
- auth: !!flags.auth,
498
+ auth: !!flags.saas,
499
499
  adminEmail,
500
500
  force,
501
501
  });
@@ -504,8 +504,8 @@ export class ProjectScaffolder {
504
504
  await this.ensureWebProject(root, {
505
505
  api: !!flags.api,
506
506
  ui: !!flags.ui,
507
- auth: !!flags.auth,
508
- admin: !!flags.admin,
507
+ auth: !!flags.saas,
508
+ admin: !!flags.saas,
509
509
  tailwind: !!flags.tailwind,
510
510
  force,
511
511
  });