alepha 0.14.4 → 0.15.1

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 (322) hide show
  1. package/README.md +44 -102
  2. package/dist/api/audits/index.d.ts +331 -443
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +2 -2
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +0 -113
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +2 -3
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +151 -262
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/notifications/index.browser.js +4 -4
  13. package/dist/api/notifications/index.browser.js.map +1 -1
  14. package/dist/api/notifications/index.d.ts +164 -276
  15. package/dist/api/notifications/index.d.ts.map +1 -1
  16. package/dist/api/notifications/index.js +4 -4
  17. package/dist/api/notifications/index.js.map +1 -1
  18. package/dist/api/parameters/index.d.ts +265 -377
  19. package/dist/api/parameters/index.d.ts.map +1 -1
  20. package/dist/api/users/index.browser.js +1 -2
  21. package/dist/api/users/index.browser.js.map +1 -1
  22. package/dist/api/users/index.d.ts +195 -301
  23. package/dist/api/users/index.d.ts.map +1 -1
  24. package/dist/api/users/index.js +203 -184
  25. package/dist/api/users/index.js.map +1 -1
  26. package/dist/api/verifications/index.d.ts.map +1 -1
  27. package/dist/batch/index.d.ts.map +1 -1
  28. package/dist/batch/index.js +1 -2
  29. package/dist/batch/index.js.map +1 -1
  30. package/dist/bucket/index.d.ts.map +1 -1
  31. package/dist/cache/core/index.d.ts.map +1 -1
  32. package/dist/cache/redis/index.d.ts.map +1 -1
  33. package/dist/cache/redis/index.js +2 -2
  34. package/dist/cache/redis/index.js.map +1 -1
  35. package/dist/cli/index.d.ts +5900 -165
  36. package/dist/cli/index.d.ts.map +1 -1
  37. package/dist/cli/index.js +1481 -639
  38. package/dist/cli/index.js.map +1 -1
  39. package/dist/command/index.d.ts +8 -4
  40. package/dist/command/index.d.ts.map +1 -1
  41. package/dist/command/index.js +29 -25
  42. package/dist/command/index.js.map +1 -1
  43. package/dist/core/index.browser.js +563 -54
  44. package/dist/core/index.browser.js.map +1 -1
  45. package/dist/core/index.d.ts +175 -8
  46. package/dist/core/index.d.ts.map +1 -1
  47. package/dist/core/index.js +564 -54
  48. package/dist/core/index.js.map +1 -1
  49. package/dist/core/index.native.js +563 -54
  50. package/dist/core/index.native.js.map +1 -1
  51. package/dist/datetime/index.d.ts.map +1 -1
  52. package/dist/datetime/index.js +4 -4
  53. package/dist/datetime/index.js.map +1 -1
  54. package/dist/email/index.d.ts +89 -42
  55. package/dist/email/index.d.ts.map +1 -1
  56. package/dist/email/index.js +129 -33
  57. package/dist/email/index.js.map +1 -1
  58. package/dist/fake/index.d.ts +7969 -2
  59. package/dist/fake/index.d.ts.map +1 -1
  60. package/dist/fake/index.js +22 -22
  61. package/dist/fake/index.js.map +1 -1
  62. package/dist/file/index.d.ts +134 -1
  63. package/dist/file/index.d.ts.map +1 -1
  64. package/dist/file/index.js +253 -1
  65. package/dist/file/index.js.map +1 -1
  66. package/dist/lock/core/index.d.ts.map +1 -1
  67. package/dist/lock/redis/index.d.ts.map +1 -1
  68. package/dist/logger/index.d.ts +1 -2
  69. package/dist/logger/index.d.ts.map +1 -1
  70. package/dist/logger/index.js +1 -5
  71. package/dist/logger/index.js.map +1 -1
  72. package/dist/mcp/index.d.ts +19 -1
  73. package/dist/mcp/index.d.ts.map +1 -1
  74. package/dist/mcp/index.js +28 -4
  75. package/dist/mcp/index.js.map +1 -1
  76. package/dist/orm/chunk-DH6iiROE.js +38 -0
  77. package/dist/orm/index.browser.js +9 -9
  78. package/dist/orm/index.browser.js.map +1 -1
  79. package/dist/orm/index.bun.js +2821 -0
  80. package/dist/orm/index.bun.js.map +1 -0
  81. package/dist/orm/index.d.ts +318 -169
  82. package/dist/orm/index.d.ts.map +1 -1
  83. package/dist/orm/index.js +2086 -1776
  84. package/dist/orm/index.js.map +1 -1
  85. package/dist/queue/core/index.d.ts +4 -4
  86. package/dist/queue/core/index.d.ts.map +1 -1
  87. package/dist/queue/redis/index.d.ts.map +1 -1
  88. package/dist/redis/index.bun.js +285 -0
  89. package/dist/redis/index.bun.js.map +1 -0
  90. package/dist/redis/index.d.ts +13 -31
  91. package/dist/redis/index.d.ts.map +1 -1
  92. package/dist/redis/index.js +18 -38
  93. package/dist/redis/index.js.map +1 -1
  94. package/dist/retry/index.d.ts.map +1 -1
  95. package/dist/router/index.d.ts.map +1 -1
  96. package/dist/scheduler/index.d.ts +83 -1
  97. package/dist/scheduler/index.d.ts.map +1 -1
  98. package/dist/scheduler/index.js +393 -1
  99. package/dist/scheduler/index.js.map +1 -1
  100. package/dist/security/index.browser.js +5 -1
  101. package/dist/security/index.browser.js.map +1 -1
  102. package/dist/security/index.d.ts +598 -112
  103. package/dist/security/index.d.ts.map +1 -1
  104. package/dist/security/index.js +1808 -97
  105. package/dist/security/index.js.map +1 -1
  106. package/dist/server/auth/index.d.ts +1200 -175
  107. package/dist/server/auth/index.d.ts.map +1 -1
  108. package/dist/server/auth/index.js +1268 -37
  109. package/dist/server/auth/index.js.map +1 -1
  110. package/dist/server/cache/index.d.ts +6 -3
  111. package/dist/server/cache/index.d.ts.map +1 -1
  112. package/dist/server/cache/index.js +1 -1
  113. package/dist/server/cache/index.js.map +1 -1
  114. package/dist/server/compress/index.d.ts.map +1 -1
  115. package/dist/server/cookies/index.d.ts.map +1 -1
  116. package/dist/server/cookies/index.js +3 -3
  117. package/dist/server/cookies/index.js.map +1 -1
  118. package/dist/server/core/index.d.ts +115 -13
  119. package/dist/server/core/index.d.ts.map +1 -1
  120. package/dist/server/core/index.js +321 -139
  121. package/dist/server/core/index.js.map +1 -1
  122. package/dist/server/cors/index.d.ts +0 -1
  123. package/dist/server/cors/index.d.ts.map +1 -1
  124. package/dist/server/health/index.d.ts +0 -1
  125. package/dist/server/health/index.d.ts.map +1 -1
  126. package/dist/server/helmet/index.d.ts.map +1 -1
  127. package/dist/server/links/index.browser.js +9 -1
  128. package/dist/server/links/index.browser.js.map +1 -1
  129. package/dist/server/links/index.d.ts +1 -2
  130. package/dist/server/links/index.d.ts.map +1 -1
  131. package/dist/server/links/index.js +14 -7
  132. package/dist/server/links/index.js.map +1 -1
  133. package/dist/server/metrics/index.d.ts +514 -1
  134. package/dist/server/metrics/index.d.ts.map +1 -1
  135. package/dist/server/metrics/index.js +4462 -4
  136. package/dist/server/metrics/index.js.map +1 -1
  137. package/dist/server/multipart/index.d.ts.map +1 -1
  138. package/dist/server/proxy/index.d.ts +0 -1
  139. package/dist/server/proxy/index.d.ts.map +1 -1
  140. package/dist/server/rate-limit/index.d.ts.map +1 -1
  141. package/dist/server/static/index.d.ts.map +1 -1
  142. package/dist/server/swagger/index.d.ts +1 -2
  143. package/dist/server/swagger/index.d.ts.map +1 -1
  144. package/dist/server/swagger/index.js +1 -2
  145. package/dist/server/swagger/index.js.map +1 -1
  146. package/dist/sms/index.d.ts +3 -1
  147. package/dist/sms/index.d.ts.map +1 -1
  148. package/dist/sms/index.js +10 -10
  149. package/dist/sms/index.js.map +1 -1
  150. package/dist/thread/index.d.ts +0 -1
  151. package/dist/thread/index.d.ts.map +1 -1
  152. package/dist/thread/index.js +2 -2
  153. package/dist/thread/index.js.map +1 -1
  154. package/dist/topic/core/index.d.ts.map +1 -1
  155. package/dist/topic/redis/index.d.ts.map +1 -1
  156. package/dist/vite/index.d.ts +6315 -149
  157. package/dist/vite/index.d.ts.map +1 -1
  158. package/dist/vite/index.js +140 -469
  159. package/dist/vite/index.js.map +1 -1
  160. package/dist/websocket/index.browser.js +9 -9
  161. package/dist/websocket/index.browser.js.map +1 -1
  162. package/dist/websocket/index.d.ts +28 -28
  163. package/dist/websocket/index.d.ts.map +1 -1
  164. package/dist/websocket/index.js +9 -9
  165. package/dist/websocket/index.js.map +1 -1
  166. package/package.json +13 -18
  167. package/src/api/files/controllers/AdminFileStatsController.ts +0 -1
  168. package/src/api/users/atoms/realmAuthSettingsAtom.ts +5 -0
  169. package/src/api/users/controllers/{UserRealmController.ts → RealmController.ts} +11 -11
  170. package/src/api/users/entities/users.ts +1 -1
  171. package/src/api/users/index.ts +8 -8
  172. package/src/api/users/primitives/{$userRealm.ts → $realm.ts} +17 -19
  173. package/src/api/users/providers/{UserRealmProvider.ts → RealmProvider.ts} +26 -30
  174. package/src/api/users/schemas/{userRealmConfigSchema.ts → realmConfigSchema.ts} +2 -2
  175. package/src/api/users/services/CredentialService.ts +7 -7
  176. package/src/api/users/services/IdentityService.ts +4 -4
  177. package/src/api/users/services/RegistrationService.spec.ts +25 -27
  178. package/src/api/users/services/RegistrationService.ts +38 -27
  179. package/src/api/users/services/SessionCrudService.ts +3 -3
  180. package/src/api/users/services/SessionService.spec.ts +3 -3
  181. package/src/api/users/services/SessionService.ts +27 -18
  182. package/src/api/users/services/UserService.ts +7 -7
  183. package/src/batch/providers/BatchProvider.ts +1 -2
  184. package/src/cli/apps/AlephaCli.ts +2 -2
  185. package/src/cli/apps/AlephaPackageBuilderCli.ts +47 -20
  186. package/src/cli/assets/apiHelloControllerTs.ts +19 -0
  187. package/src/cli/assets/apiIndexTs.ts +16 -0
  188. package/src/cli/assets/biomeJson.ts +2 -1
  189. package/src/cli/assets/claudeMd.ts +308 -0
  190. package/src/cli/assets/dummySpecTs.ts +2 -1
  191. package/src/cli/assets/editorconfig.ts +2 -1
  192. package/src/cli/assets/mainBrowserTs.ts +4 -3
  193. package/src/cli/assets/mainCss.ts +24 -0
  194. package/src/cli/assets/mainServerTs.ts +24 -0
  195. package/src/cli/assets/tsconfigJson.ts +2 -1
  196. package/src/cli/assets/webAppRouterTs.ts +16 -0
  197. package/src/cli/assets/webHelloComponentTsx.ts +20 -0
  198. package/src/cli/assets/webIndexTs.ts +16 -0
  199. package/src/cli/atoms/appEntryOptions.ts +13 -0
  200. package/src/cli/atoms/buildOptions.ts +1 -1
  201. package/src/cli/atoms/changelogOptions.ts +1 -1
  202. package/src/cli/commands/build.ts +97 -61
  203. package/src/cli/commands/db.ts +21 -18
  204. package/src/cli/commands/deploy.ts +17 -5
  205. package/src/cli/commands/dev.ts +26 -47
  206. package/src/cli/commands/gen/env.ts +1 -1
  207. package/src/cli/commands/init.ts +79 -25
  208. package/src/cli/commands/lint.ts +9 -3
  209. package/src/cli/commands/test.ts +8 -2
  210. package/src/cli/commands/typecheck.ts +5 -1
  211. package/src/cli/commands/verify.ts +4 -2
  212. package/src/cli/defineConfig.ts +9 -0
  213. package/src/cli/index.ts +2 -1
  214. package/src/cli/providers/AppEntryProvider.ts +131 -0
  215. package/src/cli/providers/ViteBuildProvider.ts +82 -0
  216. package/src/cli/providers/ViteDevServerProvider.ts +350 -0
  217. package/src/cli/providers/ViteTemplateProvider.ts +27 -0
  218. package/src/cli/services/AlephaCliUtils.ts +72 -602
  219. package/src/cli/services/PackageManagerUtils.ts +308 -0
  220. package/src/cli/services/ProjectScaffolder.ts +329 -0
  221. package/src/command/helpers/Runner.ts +15 -3
  222. package/src/core/Alepha.ts +2 -8
  223. package/src/core/__tests__/Alepha-graph.spec.ts +4 -0
  224. package/src/core/index.shared.ts +1 -0
  225. package/src/core/index.ts +2 -0
  226. package/src/core/primitives/$hook.ts +6 -2
  227. package/src/core/primitives/$module.spec.ts +4 -0
  228. package/src/core/primitives/$module.ts +12 -0
  229. package/src/core/providers/AlsProvider.ts +1 -1
  230. package/src/core/providers/CodecManager.spec.ts +12 -6
  231. package/src/core/providers/CodecManager.ts +26 -6
  232. package/src/core/providers/EventManager.ts +169 -13
  233. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +878 -0
  234. package/src/core/providers/KeylessJsonSchemaCodec.ts +789 -0
  235. package/src/core/providers/SchemaValidator.spec.ts +236 -0
  236. package/src/core/providers/StateManager.spec.ts +27 -16
  237. package/src/email/providers/LocalEmailProvider.spec.ts +111 -87
  238. package/src/email/providers/LocalEmailProvider.ts +52 -15
  239. package/src/email/providers/NodemailerEmailProvider.ts +167 -56
  240. package/src/file/errors/FileError.ts +7 -0
  241. package/src/file/index.ts +9 -1
  242. package/src/file/providers/MemoryFileSystemProvider.ts +393 -0
  243. package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
  244. package/src/mcp/errors/McpError.ts +30 -0
  245. package/src/mcp/index.ts +3 -0
  246. package/src/mcp/transports/SseMcpTransport.ts +16 -6
  247. package/src/orm/index.browser.ts +1 -19
  248. package/src/orm/index.bun.ts +77 -0
  249. package/src/orm/index.shared-server.ts +22 -0
  250. package/src/orm/index.shared.ts +15 -0
  251. package/src/orm/index.ts +19 -39
  252. package/src/orm/providers/DrizzleKitProvider.ts +3 -5
  253. package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -5
  254. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
  255. package/src/orm/providers/drivers/CloudflareD1Provider.ts +4 -0
  256. package/src/orm/providers/drivers/DatabaseProvider.ts +4 -0
  257. package/src/orm/providers/drivers/PglitePostgresProvider.ts +4 -0
  258. package/src/orm/services/Repository.ts +19 -0
  259. package/src/redis/index.bun.ts +35 -0
  260. package/src/redis/providers/BunRedisProvider.ts +12 -43
  261. package/src/redis/providers/BunRedisSubscriberProvider.ts +2 -3
  262. package/src/redis/providers/NodeRedisProvider.ts +16 -34
  263. package/src/{server/security → security}/__tests__/BasicAuth.spec.ts +11 -11
  264. package/src/{server/security → security}/__tests__/ServerSecurityProvider-realm.spec.ts +21 -16
  265. package/src/{server/security/providers → security/__tests__}/ServerSecurityProvider.spec.ts +5 -5
  266. package/src/security/index.browser.ts +5 -0
  267. package/src/security/index.ts +90 -7
  268. package/src/security/primitives/{$realm.spec.ts → $issuer.spec.ts} +11 -11
  269. package/src/security/primitives/{$realm.ts → $issuer.ts} +20 -17
  270. package/src/security/primitives/$role.ts +5 -5
  271. package/src/security/primitives/$serviceAccount.spec.ts +5 -5
  272. package/src/security/primitives/$serviceAccount.ts +3 -3
  273. package/src/{server/security → security}/providers/ServerSecurityProvider.ts +5 -7
  274. package/src/server/auth/primitives/$auth.ts +10 -10
  275. package/src/server/auth/primitives/$authCredentials.ts +3 -3
  276. package/src/server/auth/primitives/$authGithub.ts +3 -3
  277. package/src/server/auth/primitives/$authGoogle.ts +3 -3
  278. package/src/server/auth/providers/ServerAuthProvider.ts +13 -13
  279. package/src/server/cache/providers/ServerCacheProvider.ts +1 -1
  280. package/src/server/cookies/providers/ServerCookiesProvider.ts +3 -3
  281. package/src/server/core/index.ts +1 -1
  282. package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
  283. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
  284. package/src/server/core/providers/NodeHttpServerProvider.ts +92 -24
  285. package/src/server/core/providers/ServerBodyParserProvider.ts +19 -23
  286. package/src/server/core/providers/ServerLoggerProvider.ts +23 -19
  287. package/src/server/core/providers/ServerProvider.ts +144 -24
  288. package/src/server/core/providers/ServerRouterProvider.ts +259 -115
  289. package/src/server/core/providers/ServerTimingProvider.ts +2 -2
  290. package/src/server/links/atoms/apiLinksAtom.ts +7 -0
  291. package/src/server/links/index.browser.ts +2 -0
  292. package/src/server/links/index.ts +3 -1
  293. package/src/server/links/providers/LinkProvider.ts +1 -1
  294. package/src/server/swagger/index.ts +1 -1
  295. package/src/sms/providers/LocalSmsProvider.spec.ts +153 -111
  296. package/src/sms/providers/LocalSmsProvider.ts +8 -7
  297. package/src/vite/index.ts +3 -2
  298. package/src/vite/tasks/buildClient.ts +0 -1
  299. package/src/vite/tasks/buildServer.ts +80 -22
  300. package/src/vite/tasks/copyAssets.ts +5 -4
  301. package/src/vite/tasks/generateCloudflare.ts +7 -0
  302. package/src/vite/tasks/generateSitemap.ts +64 -23
  303. package/src/vite/tasks/index.ts +0 -2
  304. package/src/vite/tasks/prerenderPages.ts +49 -24
  305. package/dist/server/security/index.browser.js +0 -13
  306. package/dist/server/security/index.browser.js.map +0 -1
  307. package/dist/server/security/index.d.ts +0 -173
  308. package/dist/server/security/index.d.ts.map +0 -1
  309. package/dist/server/security/index.js +0 -311
  310. package/dist/server/security/index.js.map +0 -1
  311. package/src/cli/assets/appRouterTs.ts +0 -9
  312. package/src/cli/assets/indexHtml.ts +0 -15
  313. package/src/cli/assets/mainTs.ts +0 -13
  314. package/src/cli/commands/format.ts +0 -17
  315. package/src/server/security/index.browser.ts +0 -10
  316. package/src/server/security/index.ts +0 -94
  317. package/src/vite/helpers/boot.ts +0 -106
  318. package/src/vite/plugins/viteAlephaDev.ts +0 -177
  319. package/src/vite/tasks/devServer.ts +0 -69
  320. package/src/vite/tasks/runAlepha.ts +0 -270
  321. /package/src/{server/security → security}/primitives/$basicAuth.ts +0 -0
  322. /package/src/{server/security → security}/providers/ServerBasicAuthProvider.ts +0 -0
@@ -1,10 +1,8 @@
1
- import { access, readFile, unlink, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { $inject, $use, t } from "alepha";
1
+ import { $inject, $use, type Alepha, AlephaError, t } from "alepha";
4
2
  import { $command } from "alepha/command";
3
+ import { FileSystemProvider } from "alepha/file";
5
4
  import { $logger } from "alepha/logger";
6
5
  import {
7
- boot,
8
6
  buildClient,
9
7
  buildServer,
10
8
  copyAssets,
@@ -15,20 +13,26 @@ import {
15
13
  prerenderPages,
16
14
  } from "alepha/vite";
17
15
  import { buildOptions } from "../atoms/buildOptions.ts";
16
+ import { AppEntryProvider } from "../providers/AppEntryProvider.ts";
17
+ import { ViteBuildProvider } from "../providers/ViteBuildProvider.ts";
18
18
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
19
+ import { PackageManagerUtils } from "../services/PackageManagerUtils.ts";
20
+ import { ProjectScaffolder } from "../services/ProjectScaffolder.ts";
19
21
 
20
22
  export class BuildCommand {
21
23
  protected readonly log = $logger();
24
+ protected readonly fs = $inject(FileSystemProvider);
22
25
  protected readonly utils = $inject(AlephaCliUtils);
26
+ protected readonly pm = $inject(PackageManagerUtils);
27
+ protected readonly scaffolder = $inject(ProjectScaffolder);
28
+ protected readonly boot = $inject(AppEntryProvider);
29
+ protected readonly viteBuildProvider = $inject(ViteBuildProvider);
23
30
  protected readonly options = $use(buildOptions);
24
31
 
25
32
  public readonly build = $command({
26
33
  name: "build",
27
34
  mode: "production",
28
35
  description: "Build the project for production",
29
- args: t.optional(
30
- t.text({ title: "path", description: "Filepath to build" }),
31
- ),
32
36
  flags: t.object({
33
37
  stats: t.optional(
34
38
  t.boolean({
@@ -55,86 +59,128 @@ export class BuildCommand {
55
59
  description: "Generate sitemap.xml with base URL",
56
60
  }),
57
61
  ),
62
+ bun: t.optional(
63
+ t.boolean({
64
+ description: "Prioritize .bun.ts entry files for Bun runtime",
65
+ }),
66
+ ),
58
67
  }),
59
- handler: async ({ flags, args, run, root }) => {
60
- // Tell viteAlephaBuild plugin to skip - CLI handles all tasks
61
- process.env.ALEPHA_BUILD_MODE = "cli";
68
+ handler: async ({ flags, run, root }) => {
62
69
  process.env.NODE_ENV = "production";
63
70
 
64
- if (await this.utils.hasExpo(root)) {
71
+ if (await this.pm.hasExpo(root)) {
65
72
  // will come soon
66
73
  return;
67
74
  }
68
75
 
69
- await this.utils.ensureConfig(root, {
76
+ await this.scaffolder.ensureConfig(root, {
70
77
  tsconfigJson: true,
71
78
  });
72
79
 
73
- const entry = await boot.getServerEntry(root, args);
80
+ const entry = await this.boot.getAppEntry(root);
74
81
  this.log.trace("Entry file found", { entry });
75
82
 
76
83
  const distDir = "dist";
77
- const clientDir = "public";
84
+ const publicDir = "public";
78
85
 
79
- await this.utils.ensureDependency(root, "vite", { run });
86
+ await this.pm.ensureDependency(root, "vite", {
87
+ run,
88
+ exec: (cmd, opts) => this.utils.exec(cmd, opts),
89
+ });
80
90
  await run.rm("dist", { alias: "clean dist" });
81
91
 
82
92
  const options = this.options;
83
93
  await this.utils.loadEnv(root, [".env", ".env.production"]);
84
94
 
85
95
  const stats = flags.stats ?? options.stats ?? false;
86
-
96
+ let template = "";
87
97
  let hasClient = false;
88
- try {
89
- await access(join(root, "index.html"));
90
- hasClient = true;
91
- } catch {
92
- // No index.html
98
+ let alepha: Alepha | undefined;
99
+
100
+ await run({
101
+ name: "analyze app",
102
+ handler: async () => {
103
+ alepha = await this.viteBuildProvider.init({ entry });
104
+ hasClient = this.viteBuildProvider.hasClient();
105
+ if (hasClient) {
106
+ template = this.viteBuildProvider.generateIndexHtml();
107
+ }
108
+ },
109
+ });
110
+
111
+ if (!alepha) {
112
+ throw new AlephaError("Alepha instance not found");
93
113
  }
94
114
 
95
115
  // Build client (precompress always enabled)
96
116
  if (hasClient) {
97
- await run({
98
- name: "vite build client",
99
- handler: () =>
100
- buildClient({
101
- silent: true,
102
- dist: `${distDir}/${clientDir}`,
103
- stats,
104
- precompress: true,
105
- }),
106
- });
117
+ // TODO: find a way to avoid writing index.html to disk
118
+ const indexHtmlPath = this.fs.join(root, "index.html");
119
+ await this.fs.writeFile(indexHtmlPath, template);
120
+ try {
121
+ await run({
122
+ name: "vite build client",
123
+ handler: () =>
124
+ buildClient({
125
+ silent: true,
126
+ dist: `${distDir}/${publicDir}`,
127
+ stats,
128
+ precompress: true,
129
+ }),
130
+ });
131
+ } finally {
132
+ await this.fs.rm(indexHtmlPath);
133
+ }
107
134
  }
108
135
 
109
136
  // Build server
110
137
  await run({
111
138
  name: "vite build server",
112
139
  handler: async () => {
113
- let clientBuilt = false;
114
- try {
115
- await readFile(`${distDir}/${clientDir}/index.html`, "utf-8");
116
- clientBuilt = true;
117
- } catch {
118
- // No client build
140
+ if (!alepha) {
141
+ throw new AlephaError("Alepha instance not found");
142
+ }
143
+
144
+ const clientIndexPath = `${distDir}/${publicDir}/index.html`;
145
+ const clientBuilt = await this.fs.exists(clientIndexPath);
146
+
147
+ const conditions: string[] = [];
148
+
149
+ // bun:
150
+ // - alepha
151
+ // - react-dom
152
+
153
+ if (flags.bun) {
154
+ conditions.push("bun");
155
+ }
156
+
157
+ // workerd:
158
+ // - react-dom
159
+ // - postgres
160
+ if (options.cloudflare) {
161
+ conditions.push("workerd");
119
162
  }
120
163
 
121
164
  await buildServer({
122
165
  silent: true,
123
- entry,
166
+ entry: entry.server,
124
167
  distDir,
125
- clientDir: clientBuilt ? clientDir : undefined,
168
+ clientDir: clientBuilt ? publicDir : undefined,
126
169
  stats,
170
+ conditions,
171
+ alepha,
127
172
  });
128
173
 
129
174
  // Server will handle index.html if both client & server are built
130
175
  if (clientBuilt) {
131
- await unlink(`${distDir}/${clientDir}/index.html`);
176
+ await this.fs.rm(clientIndexPath);
132
177
  }
133
178
  },
134
179
  });
135
180
 
136
181
  // Copy assets
137
182
  await copyAssets({
183
+ alepha,
138
184
  root,
139
185
  entry: `${distDir}/index.js`,
140
186
  distDir,
@@ -145,30 +191,20 @@ export class BuildCommand {
145
191
  // Generate sitemap
146
192
  const sitemapHostname = flags.sitemap ?? options.sitemap?.hostname;
147
193
  if (sitemapHostname) {
148
- await run({
149
- name: "add sitemap",
150
- handler: async () => {
151
- await writeFile(
152
- `${distDir}/${clientDir}/sitemap.xml`,
153
- await generateSitemap({
154
- entry: `${distDir}/index.js`,
155
- baseUrl: sitemapHostname,
156
- }),
157
- );
158
- },
194
+ await generateSitemap({
195
+ alepha,
196
+ baseUrl: sitemapHostname,
197
+ output: `${distDir}/${publicDir}/sitemap.xml`,
198
+ run,
159
199
  });
160
200
  }
161
201
 
162
202
  // Pre-render static pages (always enabled)
163
- await run({
164
- name: "pre-render pages",
165
- handler: async () => {
166
- await prerenderPages({
167
- dist: `${distDir}/${clientDir}`,
168
- entry: `${distDir}/index.js`,
169
- compress: true,
170
- });
171
- },
203
+ await prerenderPages({
204
+ alepha,
205
+ dist: `${distDir}/${publicDir}`,
206
+ compress: true,
207
+ run,
172
208
  });
173
209
  }
174
210
 
@@ -179,7 +215,7 @@ export class BuildCommand {
179
215
  handler: () =>
180
216
  generateVercel({
181
217
  distDir,
182
- clientDir,
218
+ clientDir: publicDir,
183
219
  config: options.vercel,
184
220
  }),
185
221
  });
@@ -1,7 +1,6 @@
1
- import { readFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
1
  import { $inject, AlephaError, t } from "alepha";
4
2
  import { $command } from "alepha/command";
3
+ import { FileSystemProvider } from "alepha/file";
5
4
  import { $logger } from "alepha/logger";
6
5
  import type {
7
6
  DatabaseProvider,
@@ -27,6 +26,7 @@ const drizzleCommandFlags = t.object({
27
26
 
28
27
  export class DbCommand {
29
28
  protected readonly log = $logger();
29
+ protected readonly fs = $inject(FileSystemProvider);
30
30
  protected readonly utils = $inject(AlephaCliUtils);
31
31
 
32
32
  /**
@@ -66,26 +66,23 @@ export class DbCommand {
66
66
 
67
67
  accepted.add(providerName);
68
68
 
69
- const migrationDir = join(rootDir, "migrations", providerName);
69
+ const migrationDir = this.fs.join(rootDir, "migrations", providerName);
70
70
 
71
- const journalFile = await readFile(
72
- `${migrationDir}/meta/_journal.json`,
73
- "utf-8",
74
- ).catch(() => null);
71
+ const journalBuffer = await this.fs
72
+ .readFile(`${migrationDir}/meta/_journal.json`)
73
+ .catch(() => null);
75
74
 
76
- if (!journalFile) {
75
+ if (!journalBuffer) {
77
76
  this.log.info("No migration journal found.");
78
77
  return;
79
78
  }
80
79
 
81
- const journal = JSON.parse(journalFile);
80
+ const journal = JSON.parse(journalBuffer.toString("utf-8"));
82
81
  const lastMigration = journal.entries[journal.entries.length - 1];
83
- const lastSnapshot = JSON.parse(
84
- await readFile(
85
- `${migrationDir}/meta/${String(lastMigration.idx).padStart(4, "0")}_snapshot.json`,
86
- "utf-8",
87
- ),
82
+ const snapshotBuffer = await this.fs.readFile(
83
+ `${migrationDir}/meta/${String(lastMigration.idx).padStart(4, "0")}_snapshot.json`,
88
84
  );
85
+ const lastSnapshot = JSON.parse(snapshotBuffer.toString("utf-8"));
89
86
 
90
87
  const models = drizzleKitProvider.getModels(provider);
91
88
  const kit = drizzleKitProvider.importDrizzleKit();
@@ -295,6 +292,10 @@ export class DbCommand {
295
292
  const providerName = provider.name;
296
293
  const dialect = provider.dialect;
297
294
 
295
+ if (providerName === "") {
296
+ continue;
297
+ }
298
+
298
299
  if (accepted.has(providerName)) {
299
300
  continue;
300
301
  }
@@ -316,6 +317,7 @@ export class DbCommand {
316
317
  provider,
317
318
  providerName,
318
319
  providerUrl: provider.url,
320
+ providerDriver: provider.driver,
319
321
  dialect,
320
322
  entry,
321
323
  rootDir,
@@ -341,6 +343,7 @@ export class DbCommand {
341
343
  provider: DatabaseProvider;
342
344
  providerName: string;
343
345
  providerUrl: string;
346
+ providerDriver: string;
344
347
  dialect: string;
345
348
  entry: string;
346
349
  rootDir: string;
@@ -371,16 +374,16 @@ export class DbCommand {
371
374
  config.schemaFilter = options.provider.schema;
372
375
  }
373
376
 
374
- if (options.providerName === "d1") {
377
+ if (options.providerDriver === "d1") {
375
378
  config.driver = "d1-http";
376
379
  }
377
380
 
378
- if (options.providerName === "pglite") {
381
+ if (options.providerDriver === "pglite") {
379
382
  config.driver = "pglite";
380
383
  }
381
384
 
382
385
  if (options.dialect === "sqlite") {
383
- if (options.providerName === "d1") {
386
+ if (options.providerDriver === "d1") {
384
387
  const token = process.env.CLOUDFLARE_API_TOKEN;
385
388
  if (!token) {
386
389
  throw new AlephaError(
@@ -421,7 +424,7 @@ export class DbCommand {
421
424
  } else {
422
425
  let url = options.providerUrl;
423
426
  url = url.replace("sqlite://", "").replace("file://", "");
424
- url = join(options.rootDir, url);
427
+ url = this.fs.join(options.rootDir, url);
425
428
 
426
429
  config.dbCredentials = {
427
430
  url,
@@ -1,12 +1,15 @@
1
- import { join } from "node:path";
2
1
  import { $inject, AlephaError, t } from "alepha";
3
2
  import { $command } from "alepha/command";
3
+ import { FileSystemProvider } from "alepha/file";
4
4
  import { $logger } from "alepha/logger";
5
5
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
6
+ import { PackageManagerUtils } from "../services/PackageManagerUtils.ts";
6
7
 
7
8
  export class DeployCommand {
8
9
  protected readonly log = $logger();
10
+ protected readonly fs = $inject(FileSystemProvider);
9
11
  protected readonly utils = $inject(AlephaCliUtils);
12
+ protected readonly pm = $inject(PackageManagerUtils);
10
13
 
11
14
  /**
12
15
  * Deploy the project to a hosting platform (e.g., Vercel, Cloudflare, Surge)
@@ -79,7 +82,10 @@ export class DeployCommand {
79
82
  this.log.debug("Running database migrations before deployment...");
80
83
  await this.utils.exec(`alepha db migrate --mode=${mode}`);
81
84
  }
82
- await this.utils.ensureDependency(root, "vercel", { dev: true });
85
+ await this.pm.ensureDependency(root, "vercel", {
86
+ dev: true,
87
+ exec: (cmd, opts) => this.utils.exec(cmd, opts),
88
+ });
83
89
  const command =
84
90
  `vercel . --cwd=dist ${mode === "production" ? "--prod" : ""}`.trim();
85
91
  this.log.debug(`Deploying to Vercel with command: ${command}`);
@@ -93,7 +99,10 @@ export class DeployCommand {
93
99
  this.log.debug("Running database migrations before deployment...");
94
100
  await this.utils.exec(`alepha db migrate --mode=${mode}`);
95
101
  }
96
- await this.utils.ensureDependency(root, "wrangler", { dev: true });
102
+ await this.pm.ensureDependency(root, "wrangler", {
103
+ dev: true,
104
+ exec: (cmd, opts) => this.utils.exec(cmd, opts),
105
+ });
97
106
  const command =
98
107
  `wrangler deploy ${mode === "production" ? "" : "--env preview"} --config=dist/wrangler.jsonc`.trim();
99
108
  this.log.info(`Deploying to Cloudflare with command: ${command}`);
@@ -103,8 +112,11 @@ export class DeployCommand {
103
112
 
104
113
  // Surge deployment
105
114
  if (await this.utils.exists(root, "dist/public/404.html")) {
106
- await this.utils.ensureDependency(root, "surge", { dev: true });
107
- const distPath = join(root, "dist/public");
115
+ await this.pm.ensureDependency(root, "surge", {
116
+ dev: true,
117
+ exec: (cmd, opts) => this.utils.exec(cmd, opts),
118
+ });
119
+ const distPath = this.fs.join(root, "dist/public");
108
120
  this.log.debug(`Deploying to Surge from directory: ${distPath}`);
109
121
  await this.utils.exec(`surge ${distPath}`);
110
122
  return;
@@ -1,15 +1,22 @@
1
- import { access } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { $inject, Alepha, t } from "alepha";
1
+ import { $inject, Alepha } from "alepha";
4
2
  import { $command } from "alepha/command";
3
+ import { FileSystemProvider } from "alepha/file";
5
4
  import { $logger } from "alepha/logger";
6
- import { boot, devServer } from "alepha/vite";
5
+ import { AppEntryProvider } from "../providers/AppEntryProvider.ts";
6
+ import { ViteDevServerProvider } from "../providers/ViteDevServerProvider.ts";
7
7
  import { AlephaCliUtils } from "../services/AlephaCliUtils.ts";
8
+ import { PackageManagerUtils } from "../services/PackageManagerUtils.ts";
9
+ import { ProjectScaffolder } from "../services/ProjectScaffolder.ts";
8
10
 
9
11
  export class DevCommand {
10
12
  protected readonly log = $logger();
13
+ protected readonly fs = $inject(FileSystemProvider);
11
14
  protected readonly utils = $inject(AlephaCliUtils);
15
+ protected readonly pm = $inject(PackageManagerUtils);
16
+ protected readonly scaffolder = $inject(ProjectScaffolder);
12
17
  protected readonly alepha = $inject(Alepha);
18
+ protected readonly viteDevServer = $inject(ViteDevServerProvider);
19
+ protected readonly boot = $inject(AppEntryProvider);
13
20
 
14
21
  /**
15
22
  * Will run the project in watch mode.
@@ -20,11 +27,13 @@ export class DevCommand {
20
27
  public readonly dev = $command({
21
28
  name: "dev",
22
29
  description: "Run the project in development mode",
23
- args: t.optional(t.text({ title: "path", description: "Filepath to run" })),
24
- handler: async ({ args, root }) => {
25
- const expo = await this.utils.hasExpo(root);
30
+ handler: async ({ root }) => {
31
+ const [expo, react] = await Promise.all([
32
+ this.pm.hasExpo(root),
33
+ this.pm.hasReact(root),
34
+ ]);
26
35
 
27
- await this.utils.ensureConfig(root, {
36
+ await this.scaffolder.ensureConfig(root, {
28
37
  tsconfigJson: true,
29
38
  });
30
39
 
@@ -33,49 +42,19 @@ export class DevCommand {
33
42
  return;
34
43
  }
35
44
 
36
- const entry = await boot.getServerEntry(root, args);
37
- this.log.trace("Entry file found", { entry });
45
+ const entry = await this.boot.getAppEntry(root);
46
+ this.log.debug("Entry file found", { entry });
38
47
 
39
- const isFullstack = await this.isFullstackProject(root);
40
-
41
- if (!isFullstack) {
42
- const exe = (await this.isBunProject(root)) ? "bun" : "tsx";
43
- let cmd = `${exe} --watch`;
44
- if (await this.utils.exists(root, ".env")) {
45
- cmd += " --env-file=./.env";
46
- }
47
- cmd += ` ${entry}`;
48
- await this.utils.exec(cmd, {
49
- global: exe === "bun",
50
- });
51
- return;
52
- }
48
+ // -> here, we assume we use Vite as runner (api or fullstack)
49
+ // but it's planned to support Bun runner in the future as well
53
50
 
54
51
  // Ensure vite is installed before running
55
- await this.utils.ensureDependency(root, "vite");
52
+ await this.pm.ensureDependency(root, "vite", {
53
+ exec: (cmd, opts) => this.utils.exec(cmd, opts),
54
+ });
56
55
 
57
- await devServer();
56
+ await this.viteDevServer.init({ root, entry });
57
+ await this.viteDevServer.start();
58
58
  },
59
59
  });
60
-
61
- protected async isBunProject(root: string): Promise<boolean> {
62
- if (this.alepha.isBun()) {
63
- return true;
64
- }
65
- try {
66
- await access(join(root, "bun.lock"));
67
- return true;
68
- } catch {
69
- return false;
70
- }
71
- }
72
-
73
- protected async isFullstackProject(root: string): Promise<boolean> {
74
- try {
75
- await access(join(root, "index.html"));
76
- return true;
77
- } catch {
78
- return false;
79
- }
80
- }
81
60
  }
@@ -37,7 +37,7 @@ export class GenEnvCommand {
37
37
  if (value.enum) {
38
38
  dotEnvFile += `# Possible values: ${value.enum.join(", ")}\n`;
39
39
  }
40
- dotEnvFile += `${key}=${value.default || ""}\n\n`;
40
+ dotEnvFile += `#${key}=${value.default || ""}\n\n`;
41
41
  }
42
42
 
43
43
  if (flags.out) {