alepha 0.14.3 → 0.14.4

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 (114) hide show
  1. package/README.md +1 -1
  2. package/dist/api/audits/index.d.ts +338 -417
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/files/index.d.ts +1 -80
  5. package/dist/api/files/index.d.ts.map +1 -1
  6. package/dist/api/jobs/index.d.ts +156 -235
  7. package/dist/api/jobs/index.d.ts.map +1 -1
  8. package/dist/api/notifications/index.d.ts +170 -249
  9. package/dist/api/notifications/index.d.ts.map +1 -1
  10. package/dist/api/parameters/index.d.ts +266 -345
  11. package/dist/api/parameters/index.d.ts.map +1 -1
  12. package/dist/api/users/index.d.ts +755 -834
  13. package/dist/api/users/index.d.ts.map +1 -1
  14. package/dist/api/verifications/index.d.ts +125 -125
  15. package/dist/api/verifications/index.d.ts.map +1 -1
  16. package/dist/cli/index.d.ts +116 -20
  17. package/dist/cli/index.d.ts.map +1 -1
  18. package/dist/cli/index.js +212 -124
  19. package/dist/cli/index.js.map +1 -1
  20. package/dist/command/index.d.ts +6 -11
  21. package/dist/command/index.d.ts.map +1 -1
  22. package/dist/command/index.js +2 -2
  23. package/dist/command/index.js.map +1 -1
  24. package/dist/core/index.browser.js +26 -4
  25. package/dist/core/index.browser.js.map +1 -1
  26. package/dist/core/index.d.ts +16 -1
  27. package/dist/core/index.d.ts.map +1 -1
  28. package/dist/core/index.js +26 -4
  29. package/dist/core/index.js.map +1 -1
  30. package/dist/core/index.native.js +26 -4
  31. package/dist/core/index.native.js.map +1 -1
  32. package/dist/logger/index.d.ts +1 -1
  33. package/dist/logger/index.d.ts.map +1 -1
  34. package/dist/logger/index.js +12 -2
  35. package/dist/logger/index.js.map +1 -1
  36. package/dist/mcp/index.d.ts.map +1 -1
  37. package/dist/mcp/index.js +1 -1
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/orm/index.d.ts +37 -173
  40. package/dist/orm/index.d.ts.map +1 -1
  41. package/dist/orm/index.js +193 -422
  42. package/dist/orm/index.js.map +1 -1
  43. package/dist/server/auth/index.d.ts +167 -167
  44. package/dist/server/cache/index.d.ts +12 -0
  45. package/dist/server/cache/index.d.ts.map +1 -1
  46. package/dist/server/cache/index.js +55 -2
  47. package/dist/server/cache/index.js.map +1 -1
  48. package/dist/server/compress/index.d.ts +6 -0
  49. package/dist/server/compress/index.d.ts.map +1 -1
  50. package/dist/server/compress/index.js +36 -1
  51. package/dist/server/compress/index.js.map +1 -1
  52. package/dist/server/core/index.browser.js +2 -2
  53. package/dist/server/core/index.browser.js.map +1 -1
  54. package/dist/server/core/index.d.ts +10 -10
  55. package/dist/server/core/index.d.ts.map +1 -1
  56. package/dist/server/core/index.js +6 -3
  57. package/dist/server/core/index.js.map +1 -1
  58. package/dist/server/links/index.d.ts +39 -39
  59. package/dist/server/links/index.d.ts.map +1 -1
  60. package/dist/server/security/index.d.ts +9 -9
  61. package/dist/server/static/index.d.ts.map +1 -1
  62. package/dist/server/static/index.js +4 -0
  63. package/dist/server/static/index.js.map +1 -1
  64. package/dist/server/swagger/index.d.ts.map +1 -1
  65. package/dist/server/swagger/index.js +2 -3
  66. package/dist/server/swagger/index.js.map +1 -1
  67. package/dist/vite/index.d.ts +101 -106
  68. package/dist/vite/index.d.ts.map +1 -1
  69. package/dist/vite/index.js +571 -508
  70. package/dist/vite/index.js.map +1 -1
  71. package/package.json +1 -1
  72. package/src/cli/apps/AlephaCli.ts +0 -2
  73. package/src/cli/atoms/buildOptions.ts +88 -0
  74. package/src/cli/commands/build.ts +32 -69
  75. package/src/cli/commands/db.ts +0 -4
  76. package/src/cli/commands/dev.ts +16 -4
  77. package/src/cli/commands/gen/env.ts +53 -0
  78. package/src/cli/commands/gen/openapi.ts +1 -1
  79. package/src/cli/commands/gen/resource.ts +15 -0
  80. package/src/cli/commands/gen.ts +7 -1
  81. package/src/cli/commands/init.ts +0 -1
  82. package/src/cli/commands/test.ts +0 -1
  83. package/src/cli/commands/verify.ts +1 -1
  84. package/src/cli/defineConfig.ts +49 -7
  85. package/src/cli/index.ts +0 -1
  86. package/src/cli/services/AlephaCliUtils.ts +36 -25
  87. package/src/command/helpers/Runner.spec.ts +2 -2
  88. package/src/command/helpers/Runner.ts +1 -1
  89. package/src/command/primitives/$command.ts +0 -6
  90. package/src/command/providers/CliProvider.ts +1 -3
  91. package/src/core/Alepha.ts +42 -0
  92. package/src/logger/index.ts +15 -3
  93. package/src/mcp/transports/StdioMcpTransport.ts +1 -1
  94. package/src/orm/index.ts +2 -8
  95. package/src/queue/core/providers/WorkerProvider.spec.ts +48 -32
  96. package/src/server/cache/providers/ServerCacheProvider.spec.ts +183 -0
  97. package/src/server/cache/providers/ServerCacheProvider.ts +94 -9
  98. package/src/server/compress/providers/ServerCompressProvider.ts +61 -2
  99. package/src/server/core/helpers/ServerReply.ts +2 -2
  100. package/src/server/core/providers/ServerProvider.ts +11 -1
  101. package/src/server/static/providers/ServerStaticProvider.ts +10 -0
  102. package/src/server/swagger/providers/ServerSwaggerProvider.ts +5 -8
  103. package/src/vite/helpers/importViteReact.ts +13 -0
  104. package/src/vite/index.ts +1 -21
  105. package/src/vite/plugins/viteAlephaDev.ts +16 -1
  106. package/src/vite/plugins/viteAlephaSsrPreload.ts +222 -0
  107. package/src/vite/tasks/buildClient.ts +11 -0
  108. package/src/vite/tasks/buildServer.ts +47 -3
  109. package/src/vite/tasks/devServer.ts +69 -0
  110. package/src/vite/tasks/index.ts +2 -1
  111. package/src/cli/assets/viteConfigTs.ts +0 -14
  112. package/src/cli/commands/run.ts +0 -24
  113. package/src/vite/plugins/viteAlepha.ts +0 -37
  114. package/src/vite/plugins/viteAlephaBuild.ts +0 -281
package/dist/cli/index.js CHANGED
@@ -1,17 +1,108 @@
1
- import { createRequire } from "node:module";
2
- import { $atom, $hook, $inject, $module, $use, Alepha, AlephaError, OPTIONS, t } from "alepha";
1
+ import { $atom, $hook, $inject, $module, $use, Alepha, AlephaError, t } from "alepha";
3
2
  import { FileSystemProvider } from "alepha/file";
4
3
  import { access, mkdir, readFile, readdir, unlink, writeFile } from "node:fs/promises";
5
4
  import { join } from "node:path";
6
5
  import { $command, CliProvider, EnvUtils } from "alepha/command";
7
6
  import { $logger, ConsoleColorProvider } from "alepha/logger";
8
- import { boot, buildClient, buildServer, copyAssets, generateCloudflare, generateDocker, generateSitemap, generateVercel, prerenderPages } from "alepha/vite";
7
+ import { boot, buildClient, buildServer, copyAssets, devServer, generateCloudflare, generateDocker, generateSitemap, generateVercel, prerenderPages } from "alepha/vite";
9
8
  import { exec, spawn } from "node:child_process";
10
9
  import { readFileSync } from "node:fs";
11
10
  import { promisify } from "node:util";
12
11
  import { ServerSwaggerProvider } from "alepha/server/swagger";
13
12
  import * as os from "node:os";
14
13
 
14
+ //#region ../../src/core/constants/KIND.ts
15
+ /**
16
+ * Used for identifying primitives.
17
+ *
18
+ * @internal
19
+ */
20
+ const KIND = Symbol.for("Alepha.Kind");
21
+
22
+ //#endregion
23
+ //#region ../../src/core/primitives/$atom.ts
24
+ /**
25
+ * Define an atom for state management.
26
+ *
27
+ * Atom lets you define a piece of state with a name, schema, and default value.
28
+ *
29
+ * By default, Alepha state is just a simple key-value store.
30
+ * Using atoms allows you to have type safety, validation, and default values for your state.
31
+ *
32
+ * You control how state is structured and validated.
33
+ *
34
+ * Features:
35
+ * - Set a schema for validation
36
+ * - Set a default value for initial state
37
+ * - Rules, like read-only, custom validation, etc.
38
+ * - Automatic getter access in services with {@link $use}
39
+ * - SSR support (server state automatically serialized and hydrated on client)
40
+ * - React integration (useAtom hook for automatic component re-renders)
41
+ * - Middleware
42
+ * - Persistence adapters (localStorage, Redis, database, file system, cookie, etc.)
43
+ * - State migrations (version upgrades when schema changes)
44
+ * - Documentation generation & devtools integration
45
+ *
46
+ * Common use cases:
47
+ * - user preferences
48
+ * - feature flags
49
+ * - configuration options
50
+ * - session data
51
+ *
52
+ * Atom must contain only serializable data.
53
+ * Avoid storing complex objects like class instances, functions, or DOM elements.
54
+ * If you need to store complex data, consider using identifiers or references instead.
55
+ */
56
+ const $atom$1 = (options) => {
57
+ return new Atom(options);
58
+ };
59
+ var Atom = class {
60
+ options;
61
+ get schema() {
62
+ return this.options.schema;
63
+ }
64
+ get key() {
65
+ return this.options.name;
66
+ }
67
+ constructor(options) {
68
+ this.options = options;
69
+ }
70
+ };
71
+ $atom$1[KIND] = "atom";
72
+
73
+ //#endregion
74
+ //#region ../../src/cli/atoms/buildOptions.ts
75
+ /**
76
+ * Build options atom for CLI build command.
77
+ *
78
+ * Defines the available build configuration options with their defaults.
79
+ * Options can be overridden via vite.config.ts or CLI flags.
80
+ */
81
+ const buildOptions = $atom$1({
82
+ name: "alepha.build.options",
83
+ description: "Build configuration options",
84
+ schema: t.object({
85
+ stats: t.optional(t.boolean({ default: false })),
86
+ vercel: t.optional(t.object({
87
+ projectName: t.optional(t.string()),
88
+ orgId: t.optional(t.string()),
89
+ projectId: t.optional(t.string()),
90
+ config: t.optional(t.object({ crons: t.optional(t.array(t.object({
91
+ path: t.string(),
92
+ schedule: t.string()
93
+ }))) }))
94
+ })),
95
+ cloudflare: t.optional(t.object({ config: t.optional(t.json()) })),
96
+ docker: t.optional(t.object({
97
+ image: t.optional(t.string({ default: "node:24-alpine" })),
98
+ command: t.optional(t.string({ default: "node" }))
99
+ })),
100
+ sitemap: t.optional(t.object({ hostname: t.string() }))
101
+ }),
102
+ default: {}
103
+ });
104
+
105
+ //#endregion
15
106
  //#region ../../src/cli/assets/appRouterTs.ts
16
107
  const appRouterTs = () => `
17
108
  import { $page } from "@alepha/react/router";
@@ -138,21 +229,6 @@ const tsconfigJson = `
138
229
  }
139
230
  `.trim();
140
231
 
141
- //#endregion
142
- //#region ../../src/cli/assets/viteConfigTs.ts
143
- const viteConfigTs = (serverEntry) => `
144
- import { viteAlepha } from "alepha/vite";
145
-
146
- export default {
147
- plugins: [
148
- viteAlepha(${serverEntry ? `{ serverEntry: "${serverEntry}" }` : ""}),
149
- ],
150
- test: {
151
- globals: true,
152
- },
153
- };
154
- `.trim();
155
-
156
232
  //#endregion
157
233
  //#region ../../src/cli/version.ts
158
234
  const packageJson = JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf-8"));
@@ -236,6 +312,20 @@ var AlephaCliUtils = class {
236
312
  this.log.debug(`Config file written: ${path}`);
237
313
  return path;
238
314
  }
315
+ async editFile(root, name, editFn) {
316
+ const filePath = join(root, name);
317
+ try {
318
+ await writeFile(filePath, await editFn(await readFile(filePath, "utf8")));
319
+ } catch (error) {
320
+ this.log.debug("Could not edit file", error);
321
+ }
322
+ }
323
+ async editJsonFile(root, name, editFn) {
324
+ return await this.editFile(root, name, async (content) => {
325
+ const newObj = await editFn(JSON.parse(content));
326
+ return JSON.stringify(newObj, null, 2);
327
+ });
328
+ }
239
329
  async removeFiles(root, files) {
240
330
  await Promise.all(files.map((file) => this.fs.rm(join(root, file), {
241
331
  force: true,
@@ -246,17 +336,23 @@ var AlephaCliUtils = class {
246
336
  await this.removeFiles(root, [
247
337
  ".yarn",
248
338
  ".yarnrc.yml",
249
- ".yarn"
339
+ "yarn.lock"
250
340
  ]);
341
+ await this.editJsonFile(root, "package.json", (pkg) => {
342
+ delete pkg.packageManager;
343
+ });
251
344
  }
252
345
  async removePnpm(root) {
253
346
  await this.removeFiles(root, ["pnpm-lock.yaml", "pnpm-workspace.yaml"]);
347
+ await this.editJsonFile(root, "package.json", (pkg) => {
348
+ delete pkg.packageManager;
349
+ });
254
350
  }
255
351
  async removeNpm(root) {
256
352
  await this.removeFiles(root, ["package-lock.json"]);
257
353
  }
258
354
  async removeBun(root) {
259
- await this.removeFiles(root, ["bun.lockb"]);
355
+ await this.removeFiles(root, ["bun.lockb", "bun.lock"]);
260
356
  }
261
357
  async removeAllPmFilesExcept(root, except) {
262
358
  if (except !== "yarn") await this.removeYarn(root);
@@ -354,7 +450,6 @@ var AlephaCliUtils = class {
354
450
  const tasks = [];
355
451
  if (opts.packageJson) tasks.push(this.ensurePackageJson(root, typeof opts.packageJson === "boolean" ? {} : opts.packageJson));
356
452
  if (opts.tsconfigJson) tasks.push(this.ensureTsConfig(root));
357
- if (opts.viteConfigTs) tasks.push(this.ensureViteConfig(root));
358
453
  if (opts.indexHtml) tasks.push(this.ensureIndexHtml(root));
359
454
  if (opts.biomeJson) tasks.push(this.ensureBiomeConfig(root));
360
455
  if (opts.editorconfig) tasks.push(this.ensureEditorConfig(root));
@@ -370,14 +465,6 @@ var AlephaCliUtils = class {
370
465
  async ensureTsConfig(root) {
371
466
  await this.ensureFileExists(root, "tsconfig.json", tsconfigJson, true);
372
467
  }
373
- /**
374
- * Ensure vite.config.ts exists in the project.
375
- *
376
- * Creates a standard Alepha vite.config.ts if none exists.
377
- */
378
- async ensureViteConfig(root, serverEntry) {
379
- await this.ensureFileExists(root, "vite.config.ts", viteConfigTs(serverEntry), false);
380
- }
381
468
  async checkFileExists(root, name, checkParentDirectories = false) {
382
469
  const configPath = join(root, name);
383
470
  if (!checkParentDirectories) try {
@@ -548,7 +635,7 @@ ${models.map((it) => `export const ${it} = models["${it}"];`).join("\n")}
548
635
  if ((await this.fs.ls(testDir)).length === 0) await this.fs.writeFile(dummyPath, dummySpecTs());
549
636
  }
550
637
  async readPackageJson(root) {
551
- const packageJson$1 = await this.fs.createFile({ path: join(root, "package.json") }).text();
638
+ const packageJson$1 = await this.fs.createFile({ path: this.fs.join(root, "package.json") }).text();
552
639
  return JSON.parse(packageJson$1);
553
640
  }
554
641
  /**
@@ -618,8 +705,10 @@ ${models.map((it) => `export const ${it} = models["${it}"];`).join("\n")}
618
705
  var BuildCommand = class {
619
706
  log = $logger();
620
707
  utils = $inject(AlephaCliUtils);
708
+ options = $use(buildOptions);
621
709
  build = $command({
622
710
  name: "build",
711
+ mode: "production",
623
712
  description: "Build the project for production",
624
713
  args: t.optional(t.text({
625
714
  title: "path",
@@ -636,33 +725,28 @@ var BuildCommand = class {
636
725
  process.env.ALEPHA_BUILD_MODE = "cli";
637
726
  process.env.NODE_ENV = "production";
638
727
  if (await this.utils.hasExpo(root)) return;
639
- await this.utils.ensureConfig(root, {
640
- viteConfigTs: true,
641
- tsconfigJson: true
642
- });
728
+ await this.utils.ensureConfig(root, { tsconfigJson: true });
643
729
  const entry = await boot.getServerEntry(root, args);
644
730
  this.log.trace("Entry file found", { entry });
645
731
  const distDir = "dist";
646
732
  const clientDir = "public";
647
733
  await this.utils.ensureDependency(root, "vite", { run });
648
734
  await run.rm("dist", { alias: "clean dist" });
649
- const viteAlephaBuildOptions = (await createRequire(import.meta.url)("vite").resolveConfig({}, "build", "production")).plugins.find((it) => it.name === "alepha:build")?.[OPTIONS] || {};
735
+ const options = this.options;
650
736
  await this.utils.loadEnv(root, [".env", ".env.production"]);
651
- const stats = flags.stats ?? viteAlephaBuildOptions.stats ?? false;
652
- const hasServer = viteAlephaBuildOptions.serverEntry !== false;
737
+ const stats = flags.stats ?? options.stats ?? false;
653
738
  let hasClient = false;
654
739
  try {
655
740
  await access(join(root, "index.html"));
656
741
  hasClient = true;
657
742
  } catch {}
658
- const clientOptions = typeof viteAlephaBuildOptions.client === "object" ? viteAlephaBuildOptions.client : {};
659
743
  if (hasClient) await run({
660
744
  name: "vite build client",
661
745
  handler: () => buildClient({
662
746
  silent: true,
663
747
  dist: `${distDir}/${clientDir}`,
664
748
  stats,
665
- precompress: clientOptions.precompress
749
+ precompress: true
666
750
  })
667
751
  });
668
752
  await run({
@@ -680,7 +764,7 @@ var BuildCommand = class {
680
764
  clientDir: clientBuilt ? clientDir : void 0,
681
765
  stats
682
766
  });
683
- if (clientBuilt && hasServer) await unlink(`${distDir}/${clientDir}/index.html`);
767
+ if (clientBuilt) await unlink(`${distDir}/${clientDir}/index.html`);
684
768
  }
685
769
  });
686
770
  await copyAssets({
@@ -690,58 +774,49 @@ var BuildCommand = class {
690
774
  run
691
775
  });
692
776
  if (hasClient) {
693
- const sitemapBaseUrl = flags.sitemap ?? clientOptions.sitemap?.hostname;
694
- if (sitemapBaseUrl) await run({
777
+ const sitemapHostname = flags.sitemap ?? options.sitemap?.hostname;
778
+ if (sitemapHostname) await run({
695
779
  name: "add sitemap",
696
780
  handler: async () => {
697
781
  await writeFile(`${distDir}/${clientDir}/sitemap.xml`, await generateSitemap({
698
782
  entry: `${distDir}/index.js`,
699
- baseUrl: sitemapBaseUrl
783
+ baseUrl: sitemapHostname
700
784
  }));
701
785
  }
702
786
  });
703
- if (clientOptions.prerender) await run({
787
+ await run({
704
788
  name: "pre-render pages",
705
789
  handler: async () => {
706
790
  await prerenderPages({
707
791
  dist: `${distDir}/${clientDir}`,
708
792
  entry: `${distDir}/index.js`,
709
- compress: clientOptions.precompress
793
+ compress: true
710
794
  });
711
795
  }
712
796
  });
713
797
  }
714
- if (flags.vercel || viteAlephaBuildOptions.vercel) {
715
- const config = typeof viteAlephaBuildOptions.vercel === "object" ? viteAlephaBuildOptions.vercel : {};
716
- await run({
717
- name: "add Vercel config",
718
- handler: () => generateVercel({
719
- distDir,
720
- clientDir,
721
- config
722
- })
723
- });
724
- }
725
- if (flags.cloudflare || viteAlephaBuildOptions.cloudflare) {
726
- const config = typeof viteAlephaBuildOptions.cloudflare === "boolean" ? {} : viteAlephaBuildOptions.cloudflare;
727
- await run({
728
- name: "add Cloudflare config",
729
- handler: () => generateCloudflare({
730
- distDir,
731
- config
732
- })
733
- });
734
- }
735
- if (flags.docker || viteAlephaBuildOptions.docker) {
736
- const dockerConfig = typeof viteAlephaBuildOptions.docker === "object" ? viteAlephaBuildOptions.docker : {};
737
- await run({
738
- name: "add Docker config",
739
- handler: () => generateDocker({
740
- distDir,
741
- ...dockerConfig
742
- })
743
- });
744
- }
798
+ if (flags.vercel || options.vercel) await run({
799
+ name: "add Vercel config",
800
+ handler: () => generateVercel({
801
+ distDir,
802
+ clientDir,
803
+ config: options.vercel
804
+ })
805
+ });
806
+ if (flags.cloudflare || options.cloudflare) await run({
807
+ name: "add Cloudflare config",
808
+ handler: () => generateCloudflare({
809
+ distDir,
810
+ config: options.cloudflare?.config
811
+ })
812
+ });
813
+ if (flags.docker || options.docker) await run({
814
+ name: "add Docker config",
815
+ handler: () => generateDocker({
816
+ distDir,
817
+ ...options.docker
818
+ })
819
+ });
745
820
  }
746
821
  });
747
822
  };
@@ -837,7 +912,6 @@ var DbCommand = class {
837
912
  generate = $command({
838
913
  name: "generate",
839
914
  description: "Generate migration files based on current database schema",
840
- summary: false,
841
915
  args: t.optional(t.text({
842
916
  title: "path",
843
917
  description: "Path to the Alepha server entry file"
@@ -862,7 +936,6 @@ var DbCommand = class {
862
936
  push = $command({
863
937
  name: "push",
864
938
  description: "Push database schema changes directly to the database",
865
- summary: false,
866
939
  args: t.optional(t.text({
867
940
  title: "path",
868
941
  description: "Path to the Alepha server entry file"
@@ -885,7 +958,6 @@ var DbCommand = class {
885
958
  migrate = $command({
886
959
  name: "migrate",
887
960
  description: "Apply pending database migrations",
888
- summary: false,
889
961
  args: t.optional(t.text({
890
962
  title: "path",
891
963
  description: "Path to the Alepha server entry file"
@@ -908,7 +980,6 @@ var DbCommand = class {
908
980
  studio = $command({
909
981
  name: "studio",
910
982
  description: "Launch Drizzle Studio database browser",
911
- summary: false,
912
983
  args: t.optional(t.text({
913
984
  title: "path",
914
985
  description: "Path to the Alepha server entry file"
@@ -1122,10 +1193,7 @@ var DevCommand = class {
1122
1193
  })),
1123
1194
  handler: async ({ args, root }) => {
1124
1195
  const expo = await this.utils.hasExpo(root);
1125
- await this.utils.ensureConfig(root, {
1126
- viteConfigTs: !expo,
1127
- tsconfigJson: true
1128
- });
1196
+ await this.utils.ensureConfig(root, { tsconfigJson: true });
1129
1197
  if (expo) {
1130
1198
  await this.utils.exec("expo start");
1131
1199
  return;
@@ -1133,7 +1201,7 @@ var DevCommand = class {
1133
1201
  const entry = await boot.getServerEntry(root, args);
1134
1202
  this.log.trace("Entry file found", { entry });
1135
1203
  if (!await this.isFullstackProject(root)) {
1136
- const exe = this.alepha.isBun() ? "bun" : "tsx";
1204
+ const exe = await this.isBunProject(root) ? "bun" : "tsx";
1137
1205
  let cmd = `${exe} --watch`;
1138
1206
  if (await this.utils.exists(root, ".env")) cmd += " --env-file=./.env";
1139
1207
  cmd += ` ${entry}`;
@@ -1141,9 +1209,18 @@ var DevCommand = class {
1141
1209
  return;
1142
1210
  }
1143
1211
  await this.utils.ensureDependency(root, "vite");
1144
- await this.utils.exec("vite");
1212
+ await devServer();
1145
1213
  }
1146
1214
  });
1215
+ async isBunProject(root) {
1216
+ if (this.alepha.isBun()) return true;
1217
+ try {
1218
+ await access(join(root, "bun.lock"));
1219
+ return true;
1220
+ } catch {
1221
+ return false;
1222
+ }
1223
+ }
1147
1224
  async isFullstackProject(root) {
1148
1225
  try {
1149
1226
  await access(join(root, "index.html"));
@@ -1385,6 +1462,39 @@ var ChangelogCommand = class {
1385
1462
  });
1386
1463
  };
1387
1464
 
1465
+ //#endregion
1466
+ //#region ../../src/cli/commands/gen/env.ts
1467
+ var GenEnvCommand = class {
1468
+ log = $logger();
1469
+ utils = $inject(AlephaCliUtils);
1470
+ fs = $inject(FileSystemProvider);
1471
+ command = $command({
1472
+ name: "env",
1473
+ description: "Extract environment variables from server entry file",
1474
+ flags: t.object({ out: t.optional(t.text({
1475
+ aliases: ["o"],
1476
+ description: "Output file path (e.g., .env)"
1477
+ })) }),
1478
+ handler: async ({ root, flags }) => {
1479
+ const { alepha } = await this.utils.loadAlephaFromServerEntryFile(root);
1480
+ try {
1481
+ const { env } = alepha.dump();
1482
+ let dotEnvFile = "";
1483
+ for (const [key, value] of Object.entries(env)) {
1484
+ if (value.description) dotEnvFile += `# ${value.description.split("\n").join("\n# ")}\n`;
1485
+ if (value.required && !value.default) dotEnvFile += `# (required)\n`;
1486
+ if (value.enum) dotEnvFile += `# Possible values: ${value.enum.join(", ")}\n`;
1487
+ dotEnvFile += `${key}=${value.default || ""}\n\n`;
1488
+ }
1489
+ if (flags.out) await this.fs.writeFile(this.fs.join(root, flags.out), dotEnvFile);
1490
+ else this.log.info(dotEnvFile);
1491
+ } catch (err) {
1492
+ this.log.error("Failed to extract environment variables", err);
1493
+ }
1494
+ }
1495
+ });
1496
+ };
1497
+
1388
1498
  //#endregion
1389
1499
  //#region ../../src/cli/commands/gen/openapi.ts
1390
1500
  var OpenApiCommand = class {
@@ -1420,7 +1530,7 @@ var OpenApiCommand = class {
1420
1530
  this.log.error("Missing $swagger() primitive in your server configuration.");
1421
1531
  return;
1422
1532
  }
1423
- this.log.error(`OpenAPI generation failed - ${message}`, { err });
1533
+ this.log.error(`OpenAPI generation failed - ${message}`, err);
1424
1534
  }
1425
1535
  }
1426
1536
  });
@@ -1431,10 +1541,15 @@ var OpenApiCommand = class {
1431
1541
  var GenCommand = class {
1432
1542
  changelog = $inject(ChangelogCommand);
1433
1543
  openapi = $inject(OpenApiCommand);
1544
+ genEnv = $inject(GenEnvCommand);
1434
1545
  gen = $command({
1435
1546
  name: "gen",
1436
1547
  description: "Generate code, documentation, ...",
1437
- children: [this.changelog.command, this.openapi.command],
1548
+ children: [
1549
+ this.changelog.command,
1550
+ this.openapi.command,
1551
+ this.genEnv.command
1552
+ ],
1438
1553
  handler: async ({ help }) => {
1439
1554
  help();
1440
1555
  }
@@ -1471,7 +1586,6 @@ var InitCommand = class {
1471
1586
  tsconfigJson: true,
1472
1587
  packageJson: flags,
1473
1588
  biomeJson: true,
1474
- viteConfigTs: !isExpo,
1475
1589
  editorconfig: true,
1476
1590
  indexHtml: !!flags.react && !isExpo
1477
1591
  });
@@ -1539,30 +1653,6 @@ var RootCommand = class {
1539
1653
  });
1540
1654
  };
1541
1655
 
1542
- //#endregion
1543
- //#region ../../src/cli/commands/run.ts
1544
- var RunCommand = class {
1545
- utils = $inject(AlephaCliUtils);
1546
- run = $command({
1547
- name: "run",
1548
- hide: true,
1549
- description: "Run a TypeScript file directly",
1550
- flags: t.object({ watch: t.optional(t.boolean({
1551
- description: "Watch file for changes",
1552
- alias: "w"
1553
- })) }),
1554
- summary: false,
1555
- args: t.text({
1556
- title: "path",
1557
- description: "Filepath to run"
1558
- }),
1559
- handler: async ({ args, flags, root }) => {
1560
- await this.utils.ensureTsConfig(root);
1561
- await this.utils.exec(`tsx ${flags.watch ? "watch " : ""}${args}`);
1562
- }
1563
- });
1564
- };
1565
-
1566
1656
  //#endregion
1567
1657
  //#region ../../src/cli/commands/test.ts
1568
1658
  var TestCommand = class {
@@ -1579,10 +1669,7 @@ var TestCommand = class {
1579
1669
  description: "Additional arguments to pass to Vitest. E.g., --coverage"
1580
1670
  })) }),
1581
1671
  handler: async ({ root, flags, env }) => {
1582
- await this.utils.ensureConfig(root, {
1583
- tsconfigJson: true,
1584
- viteConfigTs: true
1585
- });
1672
+ await this.utils.ensureConfig(root, { tsconfigJson: true });
1586
1673
  await this.utils.ensureDependency(root, "vitest");
1587
1674
  const config = flags.config ? `--config=${flags.config}` : "";
1588
1675
  await this.utils.exec(`vitest run ${config} ${env.VITEST_ARGS}`);
@@ -1637,7 +1724,7 @@ var VerifyCommand = class {
1637
1724
  await run("alepha lint");
1638
1725
  await run("alepha typecheck");
1639
1726
  if ((await this.utils.readPackageJson(root)).devDependencies?.vitest) await run("alepha test");
1640
- if (await this.utils.exists(root, "migrations")) await run("alepha db:check-migrations");
1727
+ if (await this.utils.exists(root, "migrations")) await run("alepha db check-migrations");
1641
1728
  if (!await this.utils.hasExpo(root)) await run("alepha build");
1642
1729
  await run("alepha clean");
1643
1730
  }
@@ -1686,7 +1773,6 @@ const AlephaCli = $module({
1686
1773
  InitCommand,
1687
1774
  LintCommand,
1688
1775
  RootCommand,
1689
- RunCommand,
1690
1776
  TestCommand,
1691
1777
  TypecheckCommand,
1692
1778
  VerifyCommand,
@@ -1890,11 +1976,13 @@ async function analyzeModules(srcDir, packageName) {
1890
1976
 
1891
1977
  //#endregion
1892
1978
  //#region ../../src/cli/defineConfig.ts
1893
- const defineConfig = (config) => {
1979
+ const defineConfig = (runConfig) => {
1894
1980
  return (alepha) => {
1895
- const { commands, services = [] } = config(alepha);
1896
- for (const it of services) alepha.with(it);
1897
- return { ...commands };
1981
+ const config = typeof runConfig === "function" ? runConfig(alepha) : runConfig;
1982
+ if (config.services) for (const it of config.services) alepha.with(it);
1983
+ if (config.env) for (const [key, value] of Object.entries(config.env)) process.env[key] = String(value);
1984
+ if (config.build) alepha.set(buildOptions, config.build);
1985
+ return { ...config.commands };
1898
1986
  };
1899
1987
  };
1900
1988
  /**
@@ -1903,5 +1991,5 @@ const defineConfig = (config) => {
1903
1991
  const defineAlephaConfig = defineConfig;
1904
1992
 
1905
1993
  //#endregion
1906
- export { AlephaCli, AlephaCliUtils, AlephaPackageBuilderCli, BuildCommand, ChangelogCommand, CleanCommand, DEFAULT_IGNORE, DbCommand, DeployCommand, DevCommand, FormatCommand, GitMessageParser, GitProvider, InitCommand, LintCommand, OpenApiCommand, RootCommand, RunCommand, TestCommand, TypecheckCommand, VerifyCommand, analyzeModules, changelogOptions, defineAlephaConfig, defineConfig, version };
1994
+ export { AlephaCli, AlephaCliUtils, AlephaPackageBuilderCli, BuildCommand, ChangelogCommand, CleanCommand, DEFAULT_IGNORE, DbCommand, DeployCommand, DevCommand, FormatCommand, GitMessageParser, GitProvider, InitCommand, LintCommand, OpenApiCommand, RootCommand, TestCommand, TypecheckCommand, VerifyCommand, analyzeModules, changelogOptions, defineAlephaConfig, defineConfig, version };
1907
1995
  //# sourceMappingURL=index.js.map